diff options
Diffstat (limited to 'unittests/AST/StructuralEquivalenceTest.cpp')
-rw-r--r-- | unittests/AST/StructuralEquivalenceTest.cpp | 158 |
1 files changed, 153 insertions, 5 deletions
diff --git a/unittests/AST/StructuralEquivalenceTest.cpp b/unittests/AST/StructuralEquivalenceTest.cpp index d5b529c6b6743..cd1f01d4bfc69 100644 --- a/unittests/AST/StructuralEquivalenceTest.cpp +++ b/unittests/AST/StructuralEquivalenceTest.cpp @@ -78,11 +78,18 @@ struct StructuralEquivalenceTest : ::testing::Test { } bool testStructuralMatch(Decl *D0, Decl *D1) { - llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls; - StructuralEquivalenceContext Ctx( - D0->getASTContext(), D1->getASTContext(), NonEquivalentDecls, - StructuralEquivalenceKind::Default, false, false); - return Ctx.IsEquivalent(D0, D1); + llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls01; + llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls10; + StructuralEquivalenceContext Ctx01( + D0->getASTContext(), D1->getASTContext(), + NonEquivalentDecls01, StructuralEquivalenceKind::Default, false, false); + StructuralEquivalenceContext Ctx10( + D1->getASTContext(), D0->getASTContext(), + NonEquivalentDecls10, StructuralEquivalenceKind::Default, false, false); + bool Eq01 = Ctx01.IsEquivalent(D0, D1); + bool Eq10 = Ctx10.IsEquivalent(D1, D0); + EXPECT_EQ(Eq01, Eq10); + return Eq01; } bool testStructuralMatch(std::tuple<Decl *, Decl *> t) { @@ -215,6 +222,14 @@ TEST_F(StructuralEquivalenceTest, WrongOrderOfFieldsInClass) { 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); @@ -582,6 +597,77 @@ TEST_F(StructuralEquivalenceRecordTest, UnnamedRecordsShouldBeInequivalent) { EXPECT_FALSE(testStructuralMatch(R0, R1)); } +TEST_F(StructuralEquivalenceRecordTest, AnonymousRecordsShouldBeInequivalent) { + auto t = makeTuDecls( + R"( + struct X { + struct { + int a; + }; + struct { + int b; + }; + }; + )", + "", Lang_C); + auto *TU = get<0>(t); + auto *A = FirstDeclMatcher<IndirectFieldDecl>().match( + TU, indirectFieldDecl(hasName("a"))); + auto *FA = cast<FieldDecl>(A->chain().front()); + RecordDecl *RA = cast<RecordType>(FA->getType().getTypePtr())->getDecl(); + auto *B = FirstDeclMatcher<IndirectFieldDecl>().match( + TU, indirectFieldDecl(hasName("b"))); + auto *FB = cast<FieldDecl>(B->chain().front()); + RecordDecl *RB = cast<RecordType>(FB->getType().getTypePtr())->getDecl(); + + ASSERT_NE(RA, RB); + EXPECT_TRUE(testStructuralMatch(RA, RA)); + EXPECT_TRUE(testStructuralMatch(RB, RB)); + EXPECT_FALSE(testStructuralMatch(RA, RB)); +} + +TEST_F(StructuralEquivalenceRecordTest, + RecordsAreInequivalentIfOrderOfAnonRecordsIsDifferent) { + auto t = makeTuDecls( + R"( + struct X { + struct { int a; }; + struct { int b; }; + }; + )", + R"( + struct X { // The order is reversed. + struct { int b; }; + struct { int a; }; + }; + )", + Lang_C); + + auto *TU = get<0>(t); + auto *A = FirstDeclMatcher<IndirectFieldDecl>().match( + TU, indirectFieldDecl(hasName("a"))); + auto *FA = cast<FieldDecl>(A->chain().front()); + RecordDecl *RA = cast<RecordType>(FA->getType().getTypePtr())->getDecl(); + + auto *TU1 = get<1>(t); + auto *A1 = FirstDeclMatcher<IndirectFieldDecl>().match( + TU1, indirectFieldDecl(hasName("a"))); + auto *FA1 = cast<FieldDecl>(A1->chain().front()); + RecordDecl *RA1 = cast<RecordType>(FA1->getType().getTypePtr())->getDecl(); + + RecordDecl *X = + FirstDeclMatcher<RecordDecl>().match(TU, recordDecl(hasName("X"))); + RecordDecl *X1 = + FirstDeclMatcher<RecordDecl>().match(TU1, recordDecl(hasName("X"))); + ASSERT_NE(X, X1); + EXPECT_FALSE(testStructuralMatch(X, X1)); + + ASSERT_NE(RA, RA1); + EXPECT_TRUE(testStructuralMatch(RA, RA)); + EXPECT_TRUE(testStructuralMatch(RA1, RA1)); + EXPECT_FALSE(testStructuralMatch(RA1, RA)); +} + TEST_F(StructuralEquivalenceRecordTest, UnnamedRecordsShouldBeInequivalentEvenIfTheSecondIsBeingDefined) { auto Code = @@ -618,6 +704,40 @@ TEST_F(StructuralEquivalenceRecordTest, EXPECT_FALSE(testStructuralMatch(R0, R1)); } +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(StructuralEquivalenceRecordTest, + FwdDeclRecordShouldBeEqualWithFwdDeclRecord) { + auto t = makeNamedDecls("class foo;", "class foo;", Lang_CXX11); + EXPECT_TRUE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceRecordTest, + FwdDeclRecordShouldBeEqualWithRecordWhichHasDefinition) { + auto t = + makeNamedDecls("class foo;", "class foo { int A; };", Lang_CXX11); + EXPECT_TRUE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceRecordTest, + RecordShouldBeEqualWithRecordWhichHasDefinition) { + auto t = makeNamedDecls("class foo { int A; };", "class foo { int A; };", + Lang_CXX11); + EXPECT_TRUE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceRecordTest, RecordsWithDifferentBody) { + auto t = makeNamedDecls("class foo { int B; };", "class foo { int A; };", + Lang_CXX11); + EXPECT_FALSE(testStructuralMatch(t)); +} TEST_F(StructuralEquivalenceTest, CompareSameDeclWithMultiple) { auto t = makeNamedDecls( @@ -627,5 +747,33 @@ TEST_F(StructuralEquivalenceTest, CompareSameDeclWithMultiple) { EXPECT_FALSE(testStructuralMatch(t)); } +struct StructuralEquivalenceEnumTest : StructuralEquivalenceTest {}; + +TEST_F(StructuralEquivalenceEnumTest, FwdDeclEnumShouldBeEqualWithFwdDeclEnum) { + auto t = makeNamedDecls("enum class foo;", "enum class foo;", Lang_CXX11); + EXPECT_TRUE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceEnumTest, + FwdDeclEnumShouldBeEqualWithEnumWhichHasDefinition) { + auto t = + makeNamedDecls("enum class foo;", "enum class foo { A };", Lang_CXX11); + EXPECT_TRUE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceEnumTest, + EnumShouldBeEqualWithEnumWhichHasDefinition) { + auto t = makeNamedDecls("enum class foo { A };", "enum class foo { A };", + Lang_CXX11); + EXPECT_TRUE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceEnumTest, EnumsWithDifferentBody) { + auto t = makeNamedDecls("enum class foo { B };", "enum class foo { A };", + Lang_CXX11); + EXPECT_FALSE(testStructuralMatch(t)); +} + + } // end namespace ast_matchers } // end namespace clang |