balazske created this revision.
Herald added subscribers: cfe-commits, teemperor, gamesh411, Szelethus, dkrupp.
Herald added a reviewer: martong.
Herald added a reviewer: a.sidorin.
Herald added a reviewer: shafik.
Herald added a project: clang.
ASTImporter makes now difference between C++11 scoped enums with same
name in different translation units if these are not visible outside.
Enum declarations are linked into decl chain correctly.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D74554

Files:
  clang/lib/AST/ASTImporter.cpp
  clang/unittests/AST/ASTImporterTest.cpp
  clang/unittests/AST/ASTImporterVisibilityTest.cpp

Index: clang/unittests/AST/ASTImporterVisibilityTest.cpp
===================================================================
--- clang/unittests/AST/ASTImporterVisibilityTest.cpp
+++ 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<GetFunPattern>;
 using ImportVariablesVisibilityChain = ImportVisibilityChain<GetVarPattern>;
 using ImportClassesVisibilityChain = ImportVisibilityChain<GetClassPattern>;
+using ImportScopedEnumsVisibilityChain = ImportVisibilityChain<GetEnumPattern>;
 using ImportFunctionTemplatesVisibilityChain =
     ImportVisibilityChain<GetFunTemplPattern>;
 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<GetVarPattern>;
 using ImportClassesVisibility = ImportVisibility<GetClassPattern>;
 using ImportEnumsVisibility = ImportVisibility<GetEnumPattern>;
+using ImportScopedEnumsVisibility = ImportVisibility<GetEnumPattern>;
 using ImportTypedefNameVisibility = ImportVisibility<GetTypedefNamePattern>;
 using ImportFunctionTemplatesVisibility = ImportVisibility<GetFunTemplPattern>;
 using ImportClassTemplatesVisibility = ImportVisibility<GetClassTemplPattern>;
@@ -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(
Index: clang/unittests/AST/ASTImporterTest.cpp
===================================================================
--- clang/unittests/AST/ASTImporterTest.cpp
+++ 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<EnumDecl>().match(
+      ToTU, enumDecl(hasName("E"), unless(isImplicit())));
+  auto *FromDefE = FirstDeclMatcher<EnumDecl>().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) {
Index: clang/lib/AST/ASTImporter.cpp
===================================================================
--- clang/lib/AST/ASTImporter.cpp
+++ 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<NamedDecl *, 4> ConflictingDecls;
     auto FoundDecls =
@@ -2594,8 +2595,13 @@
       if (auto *FoundEnum = dyn_cast<EnumDecl>(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;
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to