diff options
author | Aaron Ballman <aaron@aaronballman.com> | 2019-03-19 14:53:52 +0000 |
---|---|---|
committer | Aaron Ballman <aaron@aaronballman.com> | 2019-03-19 14:53:52 +0000 |
commit | 165435ffa088d477ac9e802b06b636d2452996e9 (patch) | |
tree | 91c2d2ae6e6782575ab24c2185796bb3da91a09b /clang/lib/Sema/SemaDecl.cpp | |
parent | 7045c6f0b5a79a8866824b2579a22151eb4dde69 (diff) | |
download | bcm5719-llvm-165435ffa088d477ac9e802b06b636d2452996e9.tar.gz bcm5719-llvm-165435ffa088d477ac9e802b06b636d2452996e9.zip |
Ensure that const variables declared at namespace scope correctly have external linkage when marked as dllexport and targeting the MSVC ABI.
Patch thanks to Zahira Ammarguellat.
llvm-svn: 356458
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 26 |
1 files changed, 24 insertions, 2 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 2078caa0bb9..9fa7f48d8d2 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -5964,10 +5964,24 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) { } if (const InheritableAttr *Attr = getDLLAttr(&ND)) { + auto *VD = dyn_cast<VarDecl>(&ND); + bool IsAnonymousNS = false; + bool IsMicrosoft = S.Context.getTargetInfo().getCXXABI().isMicrosoft(); + if (VD) { + const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(VD->getDeclContext()); + while (NS && !IsAnonymousNS) { + IsAnonymousNS = NS->isAnonymousNamespace(); + NS = dyn_cast<NamespaceDecl>(NS->getParent()); + } + } // dll attributes require external linkage. Static locals may have external // linkage but still cannot be explicitly imported or exported. - auto *VD = dyn_cast<VarDecl>(&ND); - if (!ND.isExternallyVisible() || (VD && VD->isStaticLocal())) { + // In Microsoft mode, a variable defined in anonymous namespace must have + // external linkage in order to be exported. + bool AnonNSInMicrosoftMode = IsAnonymousNS && IsMicrosoft; + if ((ND.isExternallyVisible() && AnonNSInMicrosoftMode) || + (!AnonNSInMicrosoftMode && + (!ND.isExternallyVisible() || (VD && VD->isStaticLocal())))) { S.Diag(ND.getLocation(), diag::err_attribute_dll_not_extern) << &ND << Attr; ND.setInvalidDecl(); @@ -11376,6 +11390,14 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { !isTemplateInstantiation(VDecl->getTemplateSpecializationKind())) Diag(VDecl->getLocation(), diag::warn_extern_init); + // In Microsoft C++ mode, a const variable defined in namespace scope has + // external linkage by default if the variable is declared with + // __declspec(dllexport). + if (Context.getTargetInfo().getCXXABI().isMicrosoft() && + getLangOpts().CPlusPlus && VDecl->getType().isConstQualified() && + VDecl->hasAttr<DLLExportAttr>() && VDecl->getDefinition()) + VDecl->setStorageClass(SC_Extern); + // C99 6.7.8p4. All file scoped initializers need to be constant. if (!getLangOpts().CPlusPlus && !VDecl->isInvalidDecl()) CheckForConstantInitializer(Init, DclT); |