diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2017-10-10 00:49:38 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2017-10-10 00:49:38 +0000 |
commit | a0b68be6cf16ee2742efdb53492f8112a5edbe70 (patch) | |
tree | c084d03d7b89122d61ce1392ebae5800b7b46abd | |
parent | e6a0242ebc5f256d4589af4d0b87bee27962f5fe (diff) | |
download | bcm5719-llvm-a0b68be6cf16ee2742efdb53492f8112a5edbe70.tar.gz bcm5719-llvm-a0b68be6cf16ee2742efdb53492f8112a5edbe70.zip |
[Modules TS] Avoid computing the linkage of the enclosing DeclContext for a declaration in the global module.
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.
llvm-svn: 315256
-rw-r--r-- | clang/include/clang/AST/DeclBase.h | 5 | ||||
-rw-r--r-- | clang/include/clang/Sema/Sema.h | 7 | ||||
-rw-r--r-- | clang/lib/AST/Decl.cpp | 4 | ||||
-rw-r--r-- | clang/test/Modules/anon-linkage.cpp | 12 |
4 files changed, 24 insertions, 4 deletions
diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index aa278c301ed..47515a848a4 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -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 diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index f32fafa447b..277c62f5439 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -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; } diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index cdd89d20e6b..4a9b9bea830 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -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/clang/test/Modules/anon-linkage.cpp b/clang/test/Modules/anon-linkage.cpp new file mode 100644 index 00000000000..590638292b5 --- /dev/null +++ b/clang/test/Modules/anon-linkage.cpp @@ -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; |