balazske created this revision. Herald added a subscriber: cfe-commits. When checking a class or function the described class or function template is checked too. Improved test with symmetric check, added new tests.
Repository: rC Clang https://reviews.llvm.org/D49223 Files: lib/AST/ASTStructuralEquivalence.cpp unittests/AST/StructuralEquivalenceTest.cpp Index: unittests/AST/StructuralEquivalenceTest.cpp =================================================================== --- unittests/AST/StructuralEquivalenceTest.cpp +++ unittests/AST/StructuralEquivalenceTest.cpp @@ -63,10 +63,18 @@ } bool testStructuralMatch(NamedDecl *D0, NamedDecl *D1) { - llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls; - StructuralEquivalenceContext Ctx(D0->getASTContext(), D1->getASTContext(), - NonEquivalentDecls, false, false); - return Ctx.IsStructurallyEquivalent(D0, D1); + llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls01; + llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls10; + StructuralEquivalenceContext Ctx01( + D0->getASTContext(), D1->getASTContext(), + NonEquivalentDecls01, false, false); + StructuralEquivalenceContext Ctx10( + D1->getASTContext(), D0->getASTContext(), + NonEquivalentDecls10, false, false); + bool Eq01 = Ctx01.IsStructurallyEquivalent(D0, D1); + bool Eq10 = Ctx10.IsStructurallyEquivalent(D1, D0); + EXPECT_EQ(Eq01, Eq10); + return Eq01; } bool testStructuralMatch(std::tuple<NamedDecl *, NamedDecl *> t) { @@ -199,6 +207,14 @@ struct StructuralEquivalenceFunctionTest : StructuralEquivalenceTest { }; +TEST_F(StructuralEquivalenceFunctionTest, TemplateVsNonTemplate) { + auto t = makeNamedDecls( + "void foo();", + "template<class T> void foo();", + Lang_CXX); + EXPECT_FALSE(testStructuralMatch(t)); +} + TEST_F(StructuralEquivalenceFunctionTest, ParamConstWithRef) { auto t = makeNamedDecls("void foo(int&);", "void foo(const int&);", Lang_CXX); @@ -534,6 +550,15 @@ EXPECT_TRUE(testStructuralMatch(t)); } +TEST_F(StructuralEquivalenceRecordTest, TemplateVsNonTemplate) { + auto t = makeDecls<CXXRecordDecl>( + "struct A { };", + "template<class T> struct A { };", + Lang_CXX, + cxxRecordDecl(hasName("A"))); + EXPECT_FALSE(testStructuralMatch(t)); +} + TEST_F(StructuralEquivalenceTest, CompareSameDeclWithMultiple) { auto t = makeNamedDecls( "struct A{ }; struct B{ }; void foo(A a, A b);", Index: lib/AST/ASTStructuralEquivalence.cpp =================================================================== --- lib/AST/ASTStructuralEquivalence.cpp +++ lib/AST/ASTStructuralEquivalence.cpp @@ -955,13 +955,21 @@ if (!D1 || !D2) return true; + if (D1->isTemplated() != D2->isTemplated()) + return false; + if (auto *D1CXX = dyn_cast<CXXRecordDecl>(D1)) { if (auto *D2CXX = dyn_cast<CXXRecordDecl>(D2)) { if (D1CXX->hasExternalLexicalStorage() && !D1CXX->isCompleteDefinition()) { D1CXX->getASTContext().getExternalSource()->CompleteType(D1CXX); } + if (auto *T1 = D1CXX->getDescribedClassTemplate()) + if (auto *T2 = D2CXX->getDescribedClassTemplate()) + if (!IsStructurallyEquivalent(Context, T1, T2)) + return false; + if (D1CXX->getNumBases() != D2CXX->getNumBases()) { if (Context.Complain) { Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) @@ -1309,6 +1317,14 @@ if (!IsStructurallyEquivalent(Context, D1->getType(), D2->getType())) return false; + if (D1->isTemplated() != D2->isTemplated()) + return false; + + if (auto T1 = D1->getDescribedFunctionTemplate()) + if (auto T2 = D2->getDescribedFunctionTemplate()) + if (!IsStructurallyEquivalent(Context, T1, T2)) + return false; + return true; }
Index: unittests/AST/StructuralEquivalenceTest.cpp =================================================================== --- unittests/AST/StructuralEquivalenceTest.cpp +++ unittests/AST/StructuralEquivalenceTest.cpp @@ -63,10 +63,18 @@ } bool testStructuralMatch(NamedDecl *D0, NamedDecl *D1) { - llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls; - StructuralEquivalenceContext Ctx(D0->getASTContext(), D1->getASTContext(), - NonEquivalentDecls, false, false); - return Ctx.IsStructurallyEquivalent(D0, D1); + llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls01; + llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls10; + StructuralEquivalenceContext Ctx01( + D0->getASTContext(), D1->getASTContext(), + NonEquivalentDecls01, false, false); + StructuralEquivalenceContext Ctx10( + D1->getASTContext(), D0->getASTContext(), + NonEquivalentDecls10, false, false); + bool Eq01 = Ctx01.IsStructurallyEquivalent(D0, D1); + bool Eq10 = Ctx10.IsStructurallyEquivalent(D1, D0); + EXPECT_EQ(Eq01, Eq10); + return Eq01; } bool testStructuralMatch(std::tuple<NamedDecl *, NamedDecl *> t) { @@ -199,6 +207,14 @@ struct StructuralEquivalenceFunctionTest : StructuralEquivalenceTest { }; +TEST_F(StructuralEquivalenceFunctionTest, TemplateVsNonTemplate) { + auto t = makeNamedDecls( + "void foo();", + "template<class T> void foo();", + Lang_CXX); + EXPECT_FALSE(testStructuralMatch(t)); +} + TEST_F(StructuralEquivalenceFunctionTest, ParamConstWithRef) { auto t = makeNamedDecls("void foo(int&);", "void foo(const int&);", Lang_CXX); @@ -534,6 +550,15 @@ EXPECT_TRUE(testStructuralMatch(t)); } +TEST_F(StructuralEquivalenceRecordTest, TemplateVsNonTemplate) { + auto t = makeDecls<CXXRecordDecl>( + "struct A { };", + "template<class T> struct A { };", + Lang_CXX, + cxxRecordDecl(hasName("A"))); + EXPECT_FALSE(testStructuralMatch(t)); +} + TEST_F(StructuralEquivalenceTest, CompareSameDeclWithMultiple) { auto t = makeNamedDecls( "struct A{ }; struct B{ }; void foo(A a, A b);", Index: lib/AST/ASTStructuralEquivalence.cpp =================================================================== --- lib/AST/ASTStructuralEquivalence.cpp +++ lib/AST/ASTStructuralEquivalence.cpp @@ -955,13 +955,21 @@ if (!D1 || !D2) return true; + if (D1->isTemplated() != D2->isTemplated()) + return false; + if (auto *D1CXX = dyn_cast<CXXRecordDecl>(D1)) { if (auto *D2CXX = dyn_cast<CXXRecordDecl>(D2)) { if (D1CXX->hasExternalLexicalStorage() && !D1CXX->isCompleteDefinition()) { D1CXX->getASTContext().getExternalSource()->CompleteType(D1CXX); } + if (auto *T1 = D1CXX->getDescribedClassTemplate()) + if (auto *T2 = D2CXX->getDescribedClassTemplate()) + if (!IsStructurallyEquivalent(Context, T1, T2)) + return false; + if (D1CXX->getNumBases() != D2CXX->getNumBases()) { if (Context.Complain) { Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) @@ -1309,6 +1317,14 @@ if (!IsStructurallyEquivalent(Context, D1->getType(), D2->getType())) return false; + if (D1->isTemplated() != D2->isTemplated()) + return false; + + if (auto T1 = D1->getDescribedFunctionTemplate()) + if (auto T2 = D2->getDescribedFunctionTemplate()) + if (!IsStructurallyEquivalent(Context, T1, T2)) + return false; + return true; }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits