diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -2578,6 +2578,7 @@ IDNS |= Decl::IDNS_Ordinary; // We may already have an enum of the same name; try to find and match it. + EnumDecl *PrevDecl = nullptr; if (!DC->isFunctionOrMethod() && SearchName) { SmallVector ConflictingDecls; auto FoundDecls = @@ -2594,8 +2595,13 @@ if (auto *FoundEnum = dyn_cast(FoundDecl)) { if (!hasSameVisibilityContext(FoundEnum, D)) continue; - if (IsStructuralMatch(D, FoundEnum)) - return Importer.MapImported(D, FoundEnum); + if (IsStructuralMatch(D, FoundEnum)) { + EnumDecl *FoundDef = FoundEnum->getDefinition(); + if (D->isThisDeclarationADefinition() && FoundDef) + return Importer.MapImported(D, FoundDef); + PrevDecl = FoundEnum->getMostRecentDecl(); + break; + } ConflictingDecls.push_back(FoundDecl); } } @@ -2623,7 +2629,7 @@ EnumDecl *D2; if (GetImportedOrCreateDecl( D2, D, Importer.getToContext(), DC, ToBeginLoc, - Loc, Name.getAsIdentifierInfo(), nullptr, D->isScoped(), + Loc, Name.getAsIdentifierInfo(), PrevDecl, D->isScoped(), D->isScopedUsingClassTag(), D->isFixed())) return D2; diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -4864,6 +4864,33 @@ EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings()); } +TEST_P(ASTImporterOptionSpecificTestBase, + ImportOfEnumDefinitionAfterFwdDeclaration) { + Decl *ToTU = getToTuDecl( + R"( + enum class E; + )", + Lang_CXX11); + Decl *FromTU = getTuDecl( + R"( + enum class E {}; + )", + Lang_CXX11); + auto *ToFwdE = FirstDeclMatcher().match( + ToTU, enumDecl(hasName("E"), unless(isImplicit()))); + auto *FromDefE = FirstDeclMatcher().match( + FromTU, + enumDecl(hasName("E"), isDefinition(), unless(isImplicit()))); + ASSERT_FALSE(ToFwdE->isThisDeclarationADefinition()); + ASSERT_TRUE(FromDefE->isThisDeclarationADefinition()); + + auto *ToDefE = Import(FromDefE, Lang_CXX11); + + EXPECT_TRUE(ToDefE); + EXPECT_TRUE(ToDefE->isThisDeclarationADefinition()); + EXPECT_EQ(ToFwdE->getCanonicalDecl(), ToDefE->getCanonicalDecl()); +} + struct ImportFriendFunctionTemplates : ASTImporterOptionSpecificTestBase {}; TEST_P(ImportFriendFunctionTemplates, LookupShouldFindPreviousFriend) { diff --git a/clang/unittests/AST/ASTImporterVisibilityTest.cpp b/clang/unittests/AST/ASTImporterVisibilityTest.cpp --- a/clang/unittests/AST/ASTImporterVisibilityTest.cpp +++ b/clang/unittests/AST/ASTImporterVisibilityTest.cpp @@ -69,6 +69,8 @@ // EnumDecl: const auto *ExternE = "enum E {};"; const auto *AnonE = "namespace { enum E {}; }"; +const auto *ExternEC = "enum class E;"; +const auto *AnonEC = "namespace { enum class E; }"; // TypedefNameDecl: const auto *ExternTypedef = "typedef int T;"; const auto *AnonTypedef = "namespace { typedef int T; }"; @@ -125,6 +127,7 @@ using ImportFunctionsVisibilityChain = ImportVisibilityChain; using ImportVariablesVisibilityChain = ImportVisibilityChain; using ImportClassesVisibilityChain = ImportVisibilityChain; +using ImportScopedEnumsVisibilityChain = ImportVisibilityChain; using ImportFunctionTemplatesVisibilityChain = ImportVisibilityChain; using ImportClassTemplatesVisibilityChain = @@ -142,6 +145,10 @@ TEST_P(ImportClassesVisibilityChain, ImportChain) { TypedTest_ImportChain(); } +// Value-parameterized test for scoped enums. +TEST_P(ImportScopedEnumsVisibilityChain, ImportChain) { + TypedTest_ImportChain(); +} // Value-parameterized test for function templates. TEST_P(ImportFunctionTemplatesVisibilityChain, ImportChain) { TypedTest_ImportChain(); @@ -173,6 +180,11 @@ ::testing::Combine( DefaultTestValuesForRunOptions, ::testing::Values(ExternC, AnonC)), ); +INSTANTIATE_TEST_CASE_P( + ParameterizedTests, ImportScopedEnumsVisibilityChain, + ::testing::Combine( + DefaultTestValuesForRunOptions, + ::testing::Values(ExternEC, AnonEC)), ); INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctionTemplatesVisibilityChain, ::testing::Combine(DefaultTestValuesForRunOptions, @@ -291,6 +303,7 @@ using ImportVariablesVisibility = ImportVisibility; using ImportClassesVisibility = ImportVisibility; using ImportEnumsVisibility = ImportVisibility; +using ImportScopedEnumsVisibility = ImportVisibility; using ImportTypedefNameVisibility = ImportVisibility; using ImportFunctionTemplatesVisibility = ImportVisibility; using ImportClassTemplatesVisibility = ImportVisibility; @@ -323,6 +336,12 @@ TEST_P(ImportEnumsVisibility, ImportAfterImport) { TypedTest_ImportAfterImportWithMerge(); } +TEST_P(ImportScopedEnumsVisibility, ImportAfter) { + TypedTest_ImportAfter(); +} +TEST_P(ImportScopedEnumsVisibility, ImportAfterImport) { + TypedTest_ImportAfterImport(); +} // TypedefNameDecl. TEST_P(ImportTypedefNameVisibility, ImportAfter) { TypedTest_ImportAfterWithMerge(); @@ -392,6 +411,15 @@ std::make_tuple(ExternE, AnonE, ExpectUnlinkedDeclChain), std::make_tuple(AnonE, ExternE, ExpectUnlinkedDeclChain), std::make_tuple(AnonE, AnonE, ExpectUnlinkedDeclChain))), ); +INSTANTIATE_TEST_CASE_P( + ParameterizedTests, ImportScopedEnumsVisibility, + ::testing::Combine( + DefaultTestValuesForRunOptions, + ::testing::Values( + std::make_tuple(ExternEC, ExternEC, ExpectLinkedDeclChain), + std::make_tuple(ExternEC, AnonEC, ExpectUnlinkedDeclChain), + std::make_tuple(AnonEC, ExternEC, ExpectUnlinkedDeclChain), + std::make_tuple(AnonEC, AnonEC, ExpectUnlinkedDeclChain))), ); INSTANTIATE_TEST_CASE_P( ParameterizedTests, ImportTypedefNameVisibility, ::testing::Combine(