]> granicus.if.org Git - clang/commitdiff
[Modules TS] Avoid computing the linkage of the enclosing DeclContext for a declarati...
authorRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 10 Oct 2017 00:49:38 +0000 (00:49 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 10 Oct 2017 00:49:38 +0000 (00:49 +0000)
This works around a language issue where adding a typedef name for linkage
purposes changes the linkage of an already-defined class after it becomes
complete.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@315256 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/DeclBase.h
include/clang/Sema/Sema.h
lib/AST/Decl.cpp
test/Modules/anon-linkage.cpp [new file with mode: 0644]

index aa278c301ed172605fe0ecadd63c562e61e4a5d3..47515a848a46f8273018e8237e16111eeff126db 100644 (file)
@@ -740,7 +740,10 @@ public:
 
   /// Get the module that owns this declaration for linkage purposes.
   /// There only ever is such a module under the C++ Modules TS.
-  Module *getOwningModuleForLinkage() const;
+  ///
+  /// \param IgnoreLinkage Ignore the linkage of the entity; assume that
+  /// all declarations in a global module fragment are unowned.
+  Module *getOwningModuleForLinkage(bool IgnoreLinkage = false) const;
 
   /// \brief Determine whether this declaration might be hidden from name
   /// lookup. Note that the declaration might be visible even if this returns
index f32fafa447bf11ad8c2a6303a6d9f73628a9c33b..277c62f543937abf72c4cce1cbe06df1dfb24c2c 100644 (file)
@@ -3051,8 +3051,11 @@ public:
 
   RedeclarationKind forRedeclarationInCurContext() {
     // A declaration with an owning module for linkage can never link against
-    // anything that is not visible.
-    if (cast<Decl>(CurContext)->getOwningModuleForLinkage())
+    // anything that is not visible. We don't need to check linkage here; if
+    // the context has internal linkage, redeclaration lookup won't find things
+    // from other TUs, and we can't safely compute linkage yet in general.
+    if (cast<Decl>(CurContext)
+            ->getOwningModuleForLinkage(/*IgnoreLinkage*/true))
       return ForVisibleRedeclaration;
     return ForExternalRedeclaration;
   }
index cdd89d20e6bc1325f7ed38830351a6787546b31d..4a9b9bea8306bbdf02b428c744def28d1f7b1096 100644 (file)
@@ -1395,7 +1395,7 @@ LinkageInfo LinkageComputer::getDeclLinkageAndVisibility(const NamedDecl *D) {
                                             : NamedDecl::VisibilityForValue));
 }
 
-Module *Decl::getOwningModuleForLinkage() const {
+Module *Decl::getOwningModuleForLinkage(bool IgnoreLinkage) const {
   Module *M = getOwningModule();
   if (!M)
     return nullptr;
@@ -1413,6 +1413,8 @@ Module *Decl::getOwningModuleForLinkage() const {
     // for linkage purposes. But internal linkage declarations in the global
     // module fragment of a particular module are owned by that module for
     // linkage purposes.
+    if (IgnoreLinkage)
+      return nullptr;
     bool InternalLinkage;
     if (auto *ND = dyn_cast<NamedDecl>(this))
       InternalLinkage = !ND->hasExternalFormalLinkage();
diff --git a/test/Modules/anon-linkage.cpp b/test/Modules/anon-linkage.cpp
new file mode 100644 (file)
index 0000000..5906382
--- /dev/null
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -std=c++17 -fmodules-ts %s
+
+typedef struct {
+  int c;
+  union {
+    int n;
+    char c[4];
+  } v;
+} mbstate;
+
+export module M;
+export using ::mbstate;