From 8299fc5b58d96ecff9c9c5ef3ef206552c192559 Mon Sep 17 00:00:00 2001 From: Gabor Marton Date: Wed, 28 Nov 2018 16:01:34 +0100 Subject: [PATCH] Use DeclarationName in structural eq --- lib/AST/ASTStructuralEquivalence.cpp | 72 +++++++++++++++---- unittests/AST/StructuralEquivalenceTest.cpp | 80 ++++++++++++++++++--- 2 files changed, 129 insertions(+), 23 deletions(-) diff --git a/lib/AST/ASTStructuralEquivalence.cpp b/lib/AST/ASTStructuralEquivalence.cpp index 41d4fc229629..e8644524d8ce 100644 --- a/lib/AST/ASTStructuralEquivalence.cpp +++ b/lib/AST/ASTStructuralEquivalence.cpp @@ -121,6 +121,54 @@ static bool IsStructurallyEquivalent(const IdentifierInfo *Name1, return Name1->getName() == Name2->getName(); } +static bool IsStructurallyEquivalent(const DeclarationName Name1, + const DeclarationName Name2) { + if (Name1.getNameKind() != Name2.getNameKind()) + return false; + + switch (Name1.getNameKind()) { + + case DeclarationName::Identifier: { + const IdentifierInfo *II1 = Name1.getAsIdentifierInfo(); + const IdentifierInfo *II2 = Name2.getAsIdentifierInfo(); + if (!II1 || !II2) + return II1 == II2; + return Name1.getAsIdentifierInfo()->getName() == + Name2.getAsIdentifierInfo()->getName(); + } + + // We assume that the parent CXXRecordDecl is being checked before this + // function is called. + case DeclarationName::CXXConstructorName: + case DeclarationName::CXXDestructorName: + case DeclarationName::CXXConversionFunctionName: + return true; + + case DeclarationName::CXXDeductionGuideName: + return IsStructurallyEquivalent( + Name1.getCXXDeductionGuideTemplate()->getDeclName(), + Name2.getCXXDeductionGuideTemplate()->getDeclName()); + + case DeclarationName::CXXOperatorName: + return Name1.getCXXOverloadedOperator() == Name2.getCXXOverloadedOperator(); + + case DeclarationName::CXXLiteralOperatorName: + return Name1.getCXXLiteralIdentifier()->getName() == + Name2.getCXXLiteralIdentifier()->getName(); + + case DeclarationName::CXXUsingDirective: + return false; // FIXME When do we consider two using directives equal? + + case DeclarationName::ObjCZeroArgSelector: + case DeclarationName::ObjCOneArgSelector: + case DeclarationName::ObjCMultiArgSelector: + return true; // FIXME + + } + + return true; +} + /// Determine whether two nested-name-specifiers are equivalent. static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, NestedNameSpecifier *NNS1, @@ -988,13 +1036,6 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return false; } - const IdentifierInfo *Name1 = Method1->getIdentifier(); - const IdentifierInfo *Name2 = Method2->getIdentifier(); - if (!::IsStructurallyEquivalent(Name1, Name2)) { - return false; - // TODO: Names do not match, add warning like at check for FieldDecl. - } - // Check the prototypes. if (!::IsStructurallyEquivalent(Context, Method1->getType(), Method2->getType())) @@ -1684,6 +1725,14 @@ bool StructuralEquivalenceContext::CheckKindSpecificEquivalence( } } else if (auto *MD1 = dyn_cast(D1)) { if (auto *MD2 = dyn_cast(D2)) { + CXXRecordDecl *Parent1 = MD1->getParent(); + CXXRecordDecl *Parent2 = MD2->getParent(); + if (!IsStructurallyEquivalent(Parent1->getDeclName(), + Parent2->getDeclName()) || + !IsStructurallyEquivalent(*this, Parent1, Parent2)) + return false; + if (!IsStructurallyEquivalent(MD1->getDeclName(), MD2->getDeclName())) + return false; if (!::IsStructurallyEquivalent(*this, MD1, MD2)) return false; } else { @@ -1692,15 +1741,8 @@ bool StructuralEquivalenceContext::CheckKindSpecificEquivalence( } } else if (FunctionDecl *FD1 = dyn_cast(D1)) { if (FunctionDecl *FD2 = dyn_cast(D2)) { - if (FD1->isOverloadedOperator()) { - if (!FD2->isOverloadedOperator()) + if (!IsStructurallyEquivalent(FD1->getDeclName(), FD2->getDeclName())) return false; - if (FD1->getOverloadedOperator() != FD2->getOverloadedOperator()) - return false; - } - if (!::IsStructurallyEquivalent(FD1->getIdentifier(), - FD2->getIdentifier())) - return false; if (!::IsStructurallyEquivalent(*this, FD1, FD2)) return false; } else { diff --git a/unittests/AST/StructuralEquivalenceTest.cpp b/unittests/AST/StructuralEquivalenceTest.cpp index 0131efcc14ad..af63519dde1a 100644 --- a/unittests/AST/StructuralEquivalenceTest.cpp +++ b/unittests/AST/StructuralEquivalenceTest.cpp @@ -248,12 +248,21 @@ TEST_F(StructuralEquivalenceFunctionTest, SameOperators) { EXPECT_TRUE(testStructuralMatch(t)); } -TEST_F(StructuralEquivalenceFunctionTest, CtorVsDtor) { +TEST_F(StructuralEquivalenceFunctionTest, EqualLiteralOperators) { auto t = makeDecls( - "struct X{ X(); };", - "struct X{ ~X(); };", Lang_CXX, - cxxConstructorDecl(), - cxxDestructorDecl()); + "int operator \"\"_a(const char*);", + "int operator \"\"_a(const char*);", + Lang_CXX11, + functionDecl()); + EXPECT_TRUE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceFunctionTest, NotEqualLiteralOperators) { + auto t = makeDecls( + "int operator \"\"_a(const char*);", + "int operator \"\"_b(const char*);", + Lang_CXX11, + functionDecl()); EXPECT_FALSE(testStructuralMatch(t)); } @@ -300,8 +309,7 @@ TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexceptTrue) { EXPECT_FALSE(testStructuralMatch(t)); } -TEST_F(StructuralEquivalenceFunctionTest, DISABLED_NoexceptNonMatch) { - // The expression is not checked yet. +TEST_F(StructuralEquivalenceFunctionTest, NoexceptNonMatch) { auto t = makeNamedDecls("void foo() noexcept(false);", "void foo() noexcept(true);", Lang_CXX11); EXPECT_FALSE(testStructuralMatch(t)); @@ -436,6 +444,12 @@ TEST_F(StructuralEquivalenceCXXMethodTest, Const) { EXPECT_FALSE(testStructuralMatch(t)); } +TEST_F(StructuralEquivalenceCXXMethodTest, DifferentClasses) { + auto t = makeNamedDecls("struct X { void foo(); };", + "struct Y { void foo(); };", Lang_CXX); + EXPECT_FALSE(testStructuralMatch(t)); +} + TEST_F(StructuralEquivalenceCXXMethodTest, Static) { auto t = makeNamedDecls("struct X { void foo(); };", "struct X { static void foo(); };", Lang_CXX); @@ -475,6 +489,47 @@ TEST_F(StructuralEquivalenceCXXMethodTest, Constructor) { EXPECT_FALSE(testStructuralMatch(t)); } +TEST_F(StructuralEquivalenceCXXMethodTest, EqualConstructors) { + auto t = makeDecls( + "struct X{ X(); };", + "struct X{ X(); };", Lang_CXX, + cxxConstructorDecl()); + EXPECT_TRUE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceCXXMethodTest, NotEqualConstructors) { + auto t = makeDecls( + "struct X{ X(); };", + "struct Y{ Y(); };", Lang_CXX, + cxxConstructorDecl()); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceCXXMethodTest, CtorVsDtor) { + auto t = makeDecls( + "struct X{ X(); };", + "struct X{ ~X(); };", Lang_CXX, + cxxConstructorDecl(), + cxxDestructorDecl()); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceCXXMethodTest, EqualDestructors) { + auto t = makeDecls( + "struct X{ ~X(); };", + "struct X{ ~X(); };", Lang_CXX, + cxxDestructorDecl()); + EXPECT_TRUE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceCXXMethodTest, NotEqualDestructors) { + auto t = makeDecls( + "struct X{ ~X(); };", + "struct Y{ ~Y(); };", Lang_CXX, + cxxDestructorDecl()); + EXPECT_FALSE(testStructuralMatch(t)); +} + TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorParam) { auto t = makeDecls("struct X { X(); };", "struct X { X(int); };", Lang_CXX, @@ -498,7 +553,16 @@ TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorDefault) { EXPECT_FALSE(testStructuralMatch(t)); } -TEST_F(StructuralEquivalenceCXXMethodTest, Conversion) { +TEST_F(StructuralEquivalenceCXXMethodTest, EqualConversionFunctions) { + auto t = makeDecls( + "struct X { operator bool(); };", + "struct X { operator bool(); };", + Lang_CXX11, + cxxConversionDecl()); + EXPECT_TRUE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceCXXMethodTest, NotEqualConversionFunctions) { auto t = makeDecls("struct X { operator bool(); };", "struct X { operator char(); };", Lang_CXX11,