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/ASTImporterGenericRedeclTest.cpp b/clang/unittests/AST/ASTImporterGenericRedeclTest.cpp --- a/clang/unittests/AST/ASTImporterGenericRedeclTest.cpp +++ b/clang/unittests/AST/ASTImporterGenericRedeclTest.cpp @@ -35,6 +35,15 @@ } }; +struct EnumClass { + using DeclTy = EnumDecl; + static constexpr auto *Prototype = "enum class X;"; + static constexpr auto *Definition = "enum class X {};"; + BindableMatcher getPattern() { + return enumDecl(hasName("X"), unless(isImplicit())); + } +}; + struct Variable { using DeclTy = VarDecl; static constexpr auto *Prototype = "extern int X;"; @@ -407,6 +416,9 @@ RedeclChain, Class, , PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( + RedeclChain, EnumClass, , + PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition) +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( RedeclChain, Variable, , PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( @@ -426,6 +438,8 @@ DefinitionShouldBeImportedAsADefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, , DefinitionShouldBeImportedAsADefinition) +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, EnumClass, , + DefinitionShouldBeImportedAsADefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, , DefinitionShouldBeImportedAsADefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, , @@ -441,6 +455,8 @@ ImportPrototypeAfterImportedPrototype) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, , ImportPrototypeAfterImportedPrototype) +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, EnumClass, , + ImportPrototypeAfterImportedPrototype) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, , ImportPrototypeAfterImportedPrototype) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, , @@ -456,6 +472,8 @@ ImportDefinitionAfterImportedPrototype) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, , ImportDefinitionAfterImportedPrototype) +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, EnumClass, , + ImportDefinitionAfterImportedPrototype) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, , ImportDefinitionAfterImportedPrototype) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, , @@ -471,6 +489,8 @@ ImportPrototypeAfterImportedDefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, , ImportPrototypeAfterImportedDefinition) +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, EnumClass, , + ImportPrototypeAfterImportedDefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, , ImportPrototypeAfterImportedDefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, , @@ -485,6 +505,8 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, , ImportPrototypes) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, , ImportPrototypes) +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, EnumClass, , + ImportPrototypes) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, , ImportPrototypes) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, , @@ -499,6 +521,8 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, , ImportDefinitions) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, , ImportDefinitions) +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, EnumClass, , + ImportDefinitions) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, , ImportDefinitions) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, , @@ -514,6 +538,8 @@ ImportDefinitionThenPrototype) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, , ImportDefinitionThenPrototype) +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, EnumClass, , + ImportDefinitionThenPrototype) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, , ImportDefinitionThenPrototype) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, , @@ -529,6 +555,8 @@ ImportPrototypeThenDefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, , ImportPrototypeThenDefinition) +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, EnumClass, , + ImportPrototypeThenDefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, , ImportPrototypeThenDefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, , @@ -562,6 +590,8 @@ DefaultTestValuesForRunOptions, ); INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainClass, DefaultTestValuesForRunOptions, ); +INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainEnumClass, + DefaultTestValuesForRunOptions, ); INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainVariable, DefaultTestValuesForRunOptions, ); INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainFunctionTemplate, diff --git a/clang/unittests/AST/ASTImporterODRStrategiesTest.cpp b/clang/unittests/AST/ASTImporterODRStrategiesTest.cpp --- a/clang/unittests/AST/ASTImporterODRStrategiesTest.cpp +++ b/clang/unittests/AST/ASTImporterODRStrategiesTest.cpp @@ -64,6 +64,14 @@ Language getLang() { return Lang_CXX; } }; +struct EnumClass { + using DeclTy = EnumDecl; + static constexpr auto *Definition = "enum class X { a, b };"; + static constexpr auto *ConflictingDefinition = "enum class X { a, b, c };"; + BindableMatcher getPattern() { return enumDecl(hasName("X")); } + Language getLang() { return Lang_CXX11; } +}; + struct EnumConstant { using DeclTy = EnumConstantDecl; static constexpr auto *Definition = "enum E { X = 0 };"; @@ -397,6 +405,9 @@ Enum, Liberal, , ImportConflictingDefAfterDef) ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE( + EnumClass, Liberal, , + ImportConflictingDefAfterDef) +ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE( EnumConstant, Liberal, , ImportConflictingDefAfterDef) ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE( @@ -435,6 +446,9 @@ Enum, Conservative, , DontImportConflictingDefAfterDef) ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE( + EnumClass, Conservative, , + DontImportConflictingDefAfterDef) +ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE( EnumConstant, Conservative, , DontImportConflictingDefAfterDef) ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE( @@ -596,6 +610,9 @@ ODRViolationTests, EnumConservative, DefaultTestValuesForRunOptions, ); INSTANTIATE_TEST_CASE_P( + ODRViolationTests, EnumClassConservative, + DefaultTestValuesForRunOptions, ); +INSTANTIATE_TEST_CASE_P( ODRViolationTests, EnumConstantConservative, DefaultTestValuesForRunOptions, ); INSTANTIATE_TEST_CASE_P( @@ -641,6 +658,9 @@ ODRViolationTests, EnumLiberal, DefaultTestValuesForRunOptions, ); INSTANTIATE_TEST_CASE_P( + ODRViolationTests, EnumClassLiberal, + DefaultTestValuesForRunOptions, ); +INSTANTIATE_TEST_CASE_P( ODRViolationTests, EnumConstantLiberal, DefaultTestValuesForRunOptions, ); INSTANTIATE_TEST_CASE_P( 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(); @@ -393,6 +412,15 @@ 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( DefaultTestValuesForRunOptions,