bool hasSameVisibilityContextAndLinkage(T *Found, T *From);
bool IsStructuralMatch(Decl *From, Decl *To, bool Complain = true);
- bool IsStructuralMatch(EnumConstantDecl *FromEC, EnumConstantDecl *ToEC);
ExpectedDecl VisitDecl(Decl *D);
ExpectedDecl VisitImportDecl(ImportDecl *D);
ExpectedDecl VisitEmptyDecl(EmptyDecl *D);
return Ctx.IsEquivalent(From, To);
}
-bool ASTNodeImporter::IsStructuralMatch(EnumConstantDecl *FromEC,
- EnumConstantDecl *ToEC) {
- const llvm::APSInt &FromVal = FromEC->getInitVal();
- const llvm::APSInt &ToVal = ToEC->getInitVal();
-
- return FromVal.isSigned() == ToVal.isSigned() &&
- FromVal.getBitWidth() == ToVal.getBitWidth() &&
- FromVal == ToVal;
-}
-
ExpectedDecl ASTNodeImporter::VisitDecl(Decl *D) {
Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node)
<< D->getDeclKindName();
return true;
}
+static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
+ EnumConstantDecl *D1,
+ EnumConstantDecl *D2) {
+ const llvm::APSInt &FromVal = D1->getInitVal();
+ const llvm::APSInt &ToVal = D2->getInitVal();
+ if (FromVal.isSigned() != ToVal.isSigned())
+ return false;
+ if (FromVal.getBitWidth() != ToVal.getBitWidth())
+ return false;
+ if (FromVal != ToVal)
+ return false;
+
+ if (!IsStructurallyEquivalent(D1->getIdentifier(), D2->getIdentifier()))
+ return false;
+
+ // Init expressions are the most expensive check, so do them last.
+ return IsStructurallyEquivalent(Context, D1->getInitExpr(),
+ D2->getInitExpr());
+}
+
/// Determine structural equivalence of two enums.
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
EnumDecl *D1, EnumDecl *D2) {
EXPECT_FALSE(testStructuralMatch(t));
}
+struct StructuralEquivalenceEnumConstantTest : StructuralEquivalenceTest {};
+
+TEST_F(StructuralEquivalenceEnumConstantTest, EnumConstantsWithSameValues) {
+ auto t = makeNamedDecls("enum foo { foo = 1 };", "enum foo { foo = 1 };",
+ Lang_C89);
+ EXPECT_TRUE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceEnumConstantTest,
+ EnumConstantsWithDifferentValues) {
+ auto t =
+ makeNamedDecls("enum e { foo = 1 };", "enum e { foo = 2 };", Lang_C89);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceEnumConstantTest,
+ EnumConstantsWithDifferentExprsButSameValues) {
+ auto t = makeNamedDecls("enum e { foo = 1 + 1 };", "enum e { foo = 2 };",
+ Lang_CXX11);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceEnumConstantTest,
+ EnumConstantsWithDifferentSignedness) {
+ auto t = makeNamedDecls("enum e : unsigned { foo = 1 };",
+ "enum e : int { foo = 1 };", Lang_CXX11);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceEnumConstantTest, EnumConstantsWithDifferentWidth) {
+ auto t = makeNamedDecls("enum e : short { foo = 1 };",
+ "enum e : int { foo = 1 };", Lang_CXX11);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceEnumConstantTest, EnumConstantsWithDifferentName) {
+ auto t =
+ makeDecls<EnumConstantDecl>("enum e { foo = 1 };", "enum e { bar = 1 };",
+ Lang_CXX11, enumConstantDecl());
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
struct StructuralEquivalenceTemplateTest : StructuralEquivalenceTest {};
TEST_F(StructuralEquivalenceTemplateTest, ExactlySameTemplates) {