TEST_F(StructuralEquivalenceRecordTest, UnnamedRecordsShouldBeInequivalentEvenIfTheSecondIsBeingDefined) { auto Code = R"( struct A { struct { struct A *next; } entry0; struct { struct A *next; } entry1; }; )"; auto t = makeTuDecls(Code, Code, Lang_C); auto *FromTU = get<0>(t); auto *Entry1 = FirstDeclMatcher<FieldDecl>().match(FromTU, fieldDecl(hasName("entry1"))); auto *ToTU = get<1>(t); auto *Entry0 = FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry0"))); auto *A = FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A"))); A->startDefinition(); // Set isBeingDefined, getDefinition() will return a // nullptr. This may be the case during ASTImport. auto *R0 = getRecordDecl(Entry0); auto *R1 = getRecordDecl(Entry1); ASSERT_NE(R0, R1); EXPECT_TRUE(testStructuralMatch(R0, R0)); EXPECT_TRUE(testStructuralMatch(R1, R1)); EXPECT_FALSE(testStructuralMatch(R0, R1)); }
TEST_F(StructuralEquivalenceRecordTest, Match) { auto Code = R"( struct A{ }; struct B{ }; struct foo: A, virtual B { void x(); int a; }; )"; auto t = makeNamedDecls(Code, Code, Lang_CXX); EXPECT_TRUE(testStructuralMatch(t)); } TEST_F(StructuralEquivalenceRecordTest, UnnamedRecordsShouldBeInequivalent) { auto t = makeTuDecls( R"( struct A { struct { struct A *next; } entry0; struct { struct A *next; } entry1; }; )", "", Lang_C); auto *TU = get<0>(t); auto *Entry0 = FirstDeclMatcher<FieldDecl>().match(TU, fieldDecl(hasName("entry0"))); auto *Entry1 = FirstDeclMatcher<FieldDecl>().match(TU, fieldDecl(hasName("entry1"))); auto *R0 = getRecordDecl(Entry0); auto *R1 = getRecordDecl(Entry1); ASSERT_NE(R0, R1); EXPECT_TRUE(testStructuralMatch(R0, R0)); EXPECT_TRUE(testStructuralMatch(R1, R1)); EXPECT_FALSE(testStructuralMatch(R0, R1)); }
bool CppClass::isAbstract() const { const CXXRecordDecl * cxxRecordDecl = getRecordDecl(this->getDecl()); return cxxRecordDecl->isAbstract(); }
bool CppClass::isAnonymous() const { const CXXRecordDecl * cxxRecordDecl = getRecordDecl(this->getDecl()); return cxxRecordDecl->isAnonymousStructOrUnion(); }