Skip to content

Commit 0a6233a

Browse files
authored
[clang][ASTImporter] Fix import of anonymous enums if multiple are present (#99281)
After changes in PR #87144 and #93923 regressions appeared in some cases. The problem was that if multiple anonymous enums are present in a class and are imported as new the import of the second enum can fail because it is detected as different from the first and causes ODR error. Now in case of enums without name an existing similar enum is searched, if not found the enum is imported. ODR error is not detected. This may be incorrect if non-matching structures are imported, but this is the less important case (import of matching classes is more important to work).
1 parent 5663639 commit 0a6233a

File tree

2 files changed

+89
-15
lines changed

2 files changed

+89
-15
lines changed

clang/lib/AST/ASTImporter.cpp

+7-2
Original file line numberDiff line numberDiff line change
@@ -2949,7 +2949,7 @@ ExpectedDecl ASTNodeImporter::VisitEnumDecl(EnumDecl *D) {
29492949
if (auto *FoundEnum = dyn_cast<EnumDecl>(FoundDecl)) {
29502950
if (!hasSameVisibilityContextAndLinkage(FoundEnum, D))
29512951
continue;
2952-
if (IsStructuralMatch(D, FoundEnum)) {
2952+
if (IsStructuralMatch(D, FoundEnum, !SearchName.isEmpty())) {
29532953
EnumDecl *FoundDef = FoundEnum->getDefinition();
29542954
if (D->isThisDeclarationADefinition() && FoundDef)
29552955
return Importer.MapImported(D, FoundDef);
@@ -2960,7 +2960,12 @@ ExpectedDecl ASTNodeImporter::VisitEnumDecl(EnumDecl *D) {
29602960
}
29612961
}
29622962

2963-
if (!ConflictingDecls.empty()) {
2963+
// In case of unnamed enums, we try to find an existing similar one, if none
2964+
// was found, perform the import always.
2965+
// Structural in-equivalence is not detected in this way here, but it may
2966+
// be found when the parent decl is imported (if the enum is part of a
2967+
// class). To make this totally exact a more difficult solution is needed.
2968+
if (SearchName && !ConflictingDecls.empty()) {
29642969
ExpectedName NameOrErr = Importer.HandleNameConflict(
29652970
SearchName, DC, IDNS, ConflictingDecls.data(),
29662971
ConflictingDecls.size());

clang/unittests/AST/ASTImporterTest.cpp

+82-13
Original file line numberDiff line numberDiff line change
@@ -9681,37 +9681,106 @@ AST_MATCHER_P(EnumDecl, hasEnumConstName, StringRef, ConstName) {
96819681
return false;
96829682
}
96839683

9684-
TEST_P(ASTImporterOptionSpecificTestBase, ImportAnonymousEnum) {
9684+
TEST_P(ASTImporterOptionSpecificTestBase, ImportAnonymousEnums) {
9685+
const char *Code =
9686+
R"(
9687+
struct A {
9688+
enum { E1, E2 } x;
9689+
enum { E3, E4 } y;
9690+
};
9691+
)";
9692+
Decl *FromTU = getTuDecl(Code, Lang_CXX11);
9693+
auto *FromEnumE1 = FirstDeclMatcher<EnumDecl>().match(
9694+
FromTU, enumDecl(hasEnumConstName("E1")));
9695+
auto *ImportedEnumE1 = Import(FromEnumE1, Lang_CXX11);
9696+
EXPECT_TRUE(ImportedEnumE1);
9697+
auto *FromEnumE3 = FirstDeclMatcher<EnumDecl>().match(
9698+
FromTU, enumDecl(hasEnumConstName("E3")));
9699+
auto *ImportedEnumE3 = Import(FromEnumE3, Lang_CXX11);
9700+
EXPECT_TRUE(ImportedEnumE3);
9701+
EXPECT_NE(ImportedEnumE1, ImportedEnumE3);
9702+
}
9703+
9704+
TEST_P(ASTImporterOptionSpecificTestBase, ImportFreeStandingAnonymousEnums) {
9705+
const char *Code =
9706+
R"(
9707+
struct A {
9708+
enum { E1, E2 };
9709+
enum { E3, E4 };
9710+
};
9711+
)";
9712+
Decl *FromTU = getTuDecl(Code, Lang_CXX11);
9713+
auto *FromEnumE1 = FirstDeclMatcher<EnumDecl>().match(
9714+
FromTU, enumDecl(hasEnumConstName("E1")));
9715+
auto *ImportedEnumE1 = Import(FromEnumE1, Lang_CXX11);
9716+
EXPECT_TRUE(ImportedEnumE1);
9717+
auto *FromEnumE3 = FirstDeclMatcher<EnumDecl>().match(
9718+
FromTU, enumDecl(hasEnumConstName("E3")));
9719+
auto *ImportedEnumE3 = Import(FromEnumE3, Lang_CXX11);
9720+
EXPECT_TRUE(ImportedEnumE3);
9721+
EXPECT_NE(ImportedEnumE1, ImportedEnumE3);
9722+
}
9723+
9724+
TEST_P(ASTImporterOptionSpecificTestBase, ImportExistingAnonymousEnums) {
96859725
const char *ToCode =
96869726
R"(
96879727
struct A {
9688-
enum { E1, E2} x;
9689-
enum { E3, E4} y;
9728+
enum { E1, E2 } x;
9729+
enum { E3, E4 } y;
96909730
};
96919731
)";
96929732
Decl *ToTU = getToTuDecl(ToCode, Lang_CXX11);
9693-
auto *ToE1 = FirstDeclMatcher<EnumDecl>().match(
9733+
auto *ToEnumE1 = FirstDeclMatcher<EnumDecl>().match(
96949734
ToTU, enumDecl(hasEnumConstName("E1")));
9695-
auto *ToE3 = FirstDeclMatcher<EnumDecl>().match(
9735+
auto *ToEnumE3 = FirstDeclMatcher<EnumDecl>().match(
96969736
ToTU, enumDecl(hasEnumConstName("E3")));
96979737
const char *Code =
96989738
R"(
96999739
struct A {
9700-
enum { E1, E2} x;
9701-
enum { E3, E4} y;
9740+
enum { E1, E2 } x;
9741+
enum { E3, E4 } y;
97029742
};
97039743
)";
97049744
Decl *FromTU = getTuDecl(Code, Lang_CXX11);
9705-
auto *FromE1 = FirstDeclMatcher<EnumDecl>().match(
9745+
auto *FromEnumE1 = FirstDeclMatcher<EnumDecl>().match(
97069746
FromTU, enumDecl(hasEnumConstName("E1")));
9747+
auto *ImportedEnumE1 = Import(FromEnumE1, Lang_CXX11);
9748+
ASSERT_TRUE(ImportedEnumE1);
9749+
EXPECT_EQ(ImportedEnumE1, ToEnumE1);
9750+
auto *FromEnumE3 = FirstDeclMatcher<EnumDecl>().match(
9751+
FromTU, enumDecl(hasEnumConstName("E3")));
9752+
auto *ImportedEnumE3 = Import(FromEnumE3, Lang_CXX11);
9753+
ASSERT_TRUE(ImportedEnumE3);
9754+
EXPECT_EQ(ImportedEnumE3, ToEnumE3);
9755+
}
9756+
9757+
TEST_P(ASTImporterOptionSpecificTestBase, ImportExistingEmptyAnonymousEnums) {
9758+
const char *ToCode =
9759+
R"(
9760+
struct A {
9761+
enum {};
9762+
};
9763+
)";
9764+
Decl *ToTU = getToTuDecl(ToCode, Lang_CXX11);
9765+
auto *ToE1 = FirstDeclMatcher<EnumDecl>().match(ToTU, enumDecl());
9766+
const char *Code =
9767+
R"(
9768+
struct A {
9769+
enum {};
9770+
enum {};
9771+
};
9772+
)";
9773+
Decl *FromTU = getTuDecl(Code, Lang_CXX11);
9774+
auto *FromE1 = FirstDeclMatcher<EnumDecl>().match(FromTU, enumDecl());
97079775
auto *ImportedE1 = Import(FromE1, Lang_CXX11);
97089776
ASSERT_TRUE(ImportedE1);
97099777
EXPECT_EQ(ImportedE1, ToE1);
9710-
auto *FromE3 = FirstDeclMatcher<EnumDecl>().match(
9711-
FromTU, enumDecl(hasEnumConstName("E3")));
9712-
auto *ImportedE3 = Import(FromE3, Lang_CXX11);
9713-
ASSERT_TRUE(ImportedE3);
9714-
EXPECT_EQ(ImportedE3, ToE3);
9778+
auto *FromE2 = LastDeclMatcher<EnumDecl>().match(FromTU, enumDecl());
9779+
ASSERT_NE(FromE1, FromE2);
9780+
auto *ImportedE2 = Import(FromE2, Lang_CXX11);
9781+
ASSERT_TRUE(ImportedE2);
9782+
// FIXME: These should not be equal, or the import should fail.
9783+
EXPECT_EQ(ImportedE2, ToE1);
97159784
}
97169785

97179786
INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ASTImporterLookupTableTest,

0 commit comments

Comments
 (0)