Skip to content

Commit

Permalink
Fix structural inequivalency of forward EnumDecl
Browse files Browse the repository at this point in the history
Summary:
Currently we consider one forward declared RecordDecl and another with a
definition equal. We have to do the same in case of enums.

Reviewers: a_sidorin, r.stahl, xazax.hun

Subscribers: rnkovacs, dkrupp, cfe-commits

Differential Revision: https://reviews.llvm.org/D50444

llvm-svn: 339336
  • Loading branch information
martong committed Aug 9, 2018
1 parent 01ae462 commit 6b01e1c
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 0 deletions.
8 changes: 8 additions & 0 deletions clang/lib/AST/ASTStructuralEquivalence.cpp
Expand Up @@ -1178,6 +1178,14 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
/// Determine structural equivalence of two enums.
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
EnumDecl *D1, EnumDecl *D2) {

// Compare the definitions of these two enums. If either or both are
// incomplete (i.e. forward declared), we assume that they are equivalent.
D1 = D1->getDefinition();
D2 = D2->getDefinition();
if (!D1 || !D2)
return true;

EnumDecl::enumerator_iterator EC2 = D2->enumerator_begin(),
EC2End = D2->enumerator_end();
for (EnumDecl::enumerator_iterator EC1 = D1->enumerator_begin(),
Expand Down
54 changes: 54 additions & 0 deletions clang/unittests/AST/StructuralEquivalenceTest.cpp
Expand Up @@ -642,6 +642,32 @@ TEST_F(StructuralEquivalenceRecordTest, TemplateVsNonTemplate) {
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(
"struct A{ }; struct B{ }; void foo(A a, A b);",
Expand All @@ -650,5 +676,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

0 comments on commit 6b01e1c

Please sign in to comment.