Author: aaronballman Date: Tue Mar 19 07:53:52 2019 New Revision: 356458 URL: http://llvm.org/viewvc/llvm-project?rev=356458&view=rev Log: 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. Added: cfe/trunk/test/CodeGen/dllexport-1.c cfe/trunk/test/Sema/dllexport-1.cpp cfe/trunk/test/Sema/dllexport-2.cpp Modified: cfe/trunk/lib/Sema/SemaDecl.cpp cfe/trunk/test/SemaCXX/dllexport.cpp cfe/trunk/test/SemaCXX/dllimport.cpp Modified: cfe/trunk/lib/Sema/SemaDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=356458&r1=356457&r2=356458&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Mar 19 07:53:52 2019 @@ -5964,10 +5964,24 @@ static void checkAttributesAfterMerging( } 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 *Re !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); Added: cfe/trunk/test/CodeGen/dllexport-1.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/dllexport-1.c?rev=356458&view=auto ============================================================================== --- cfe/trunk/test/CodeGen/dllexport-1.c (added) +++ cfe/trunk/test/CodeGen/dllexport-1.c Tue Mar 19 07:53:52 2019 @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -fms-extensions -Wno-ignored-attributes -Wno-extern-initializer -o - %s | FileCheck %s -check-prefix CHECK-LNX +// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -emit-llvm -fms-extensions -o - -DMSVC %s | FileCheck %s -check-prefix CHECK-MSVC + +// Export const variable. + +// CHECK-MSVC: @x = dso_local dllexport constant i32 3, align 4 +// CHECK-LNX: @x = constant i32 3, align 4 + +// CHECK-MSVC: @z = dso_local constant i32 4, align 4 +// CHECK-LNX: @z = constant i32 4, align 4 + +// CHECK-MSVC: @y = common dso_local dllexport global i32 0, align 4 +// CHECK-LNX: @y = common global i32 0, align 4 + +__declspec(dllexport) int const x = 3; +__declspec(dllexport) const int y; + +// expected-warning@+1 {{'extern' variable has an initializer}} +extern int const z = 4; + +int main() { + int a = x + y + z; + return a; +} Added: cfe/trunk/test/Sema/dllexport-1.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/dllexport-1.cpp?rev=356458&view=auto ============================================================================== --- cfe/trunk/test/Sema/dllexport-1.cpp (added) +++ cfe/trunk/test/Sema/dllexport-1.cpp Tue Mar 19 07:53:52 2019 @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -fms-extensions -verify %s +// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -fsyntax-only -fms-extensions -verify %s -DMSVC + +// Export const variable initialization. + +#ifdef MSVC +// expected-no-diagnostics +#endif + +#ifndef MSVC +// expected-warning@+2 {{__declspec attribute 'dllexport' is not supported}} +#endif +__declspec(dllexport) int const x = 3; + +namespace { +namespace named { +#ifndef MSVC +// expected-warning@+2 {{__declspec attribute 'dllexport' is not supported}} +#endif +__declspec(dllexport) int const x = 3; +} +} // namespace + +namespace named1 { +namespace { +namespace named { +#ifndef MSVC +// expected-warning@+2 {{__declspec attribute 'dllexport' is not supported}} +#endif +__declspec(dllexport) int const x = 3; +} +} // namespace +} // namespace named1 Added: cfe/trunk/test/Sema/dllexport-2.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/dllexport-2.cpp?rev=356458&view=auto ============================================================================== --- cfe/trunk/test/Sema/dllexport-2.cpp (added) +++ cfe/trunk/test/Sema/dllexport-2.cpp Tue Mar 19 07:53:52 2019 @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -fms-extensions -verify %s +// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -fsyntax-only -fms-extensions -verify %s -DMSVC + +// Export const variable. + +#ifdef MSVC +// expected-error@+4 {{'j' must have external linkage when declared 'dllexport'}} +#else +// expected-warning@+2 {{__declspec attribute 'dllexport' is not supported}} +#endif +__declspec(dllexport) int const j; // expected-error {{default initialization of an object of const type 'const int'}} + +// With typedef +typedef const int CInt; + +#ifdef MSVC +// expected-error@+4 {{'j2' must have external linkage when declared 'dllexport'}} +#else +// expected-warning@+2 {{__declspec attribute 'dllexport' is not supported}} +#endif +__declspec(dllexport) CInt j2; //expected-error {{default initialization of an object of const type 'CInt'}} + +#ifndef MSVC +// expected-warning@+2 {{__declspec attribute 'dllexport' is not supported}} +#endif +__declspec(dllexport) CInt j3 = 3; Modified: cfe/trunk/test/SemaCXX/dllexport.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/dllexport.cpp?rev=356458&r1=356457&r2=356458&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/dllexport.cpp (original) +++ cfe/trunk/test/SemaCXX/dllexport.cpp Tue Mar 19 07:53:52 2019 @@ -69,7 +69,9 @@ __declspec(dllexport) extern int GlobalR // External linkage is required. __declspec(dllexport) static int StaticGlobal; // expected-error{{'StaticGlobal' must have external linkage when declared 'dllexport'}} __declspec(dllexport) Internal InternalTypeGlobal; // expected-error{{'InternalTypeGlobal' must have external linkage when declared 'dllexport'}} +#ifndef MS namespace { __declspec(dllexport) int InternalGlobal; } // expected-error{{'(anonymous namespace)::InternalGlobal' must have external linkage when declared 'dllexport'}} +#endif namespace ns { __declspec(dllexport) int ExternalGlobal; } __declspec(dllexport) auto InternalAutoTypeGlobal = Internal(); // expected-error{{'InternalAutoTypeGlobal' must have external linkage when declared 'dllexport'}} @@ -124,7 +126,9 @@ template<typename T> __declspec(dllexpor // External linkage is required. template<typename T> __declspec(dllexport) static int StaticVarTmpl; // expected-error{{'StaticVarTmpl' must have external linkage when declared 'dllexport'}} template<typename T> __declspec(dllexport) Internal InternalTypeVarTmpl; // expected-error{{'InternalTypeVarTmpl' must have external linkage when declared 'dllexport'}} +#ifndef MS namespace { template<typename T> __declspec(dllexport) int InternalVarTmpl; } // expected-error{{'(anonymous namespace)::InternalVarTmpl' must have external linkage when declared 'dllexport'}} +#endif namespace ns { template<typename T> __declspec(dllexport) int ExternalVarTmpl = 1; } template<typename T> __declspec(dllexport) auto InternalAutoTypeVarTmpl = Internal(); // expected-error{{'InternalAutoTypeVarTmpl' must have external linkage when declared 'dllexport'}} Modified: cfe/trunk/test/SemaCXX/dllimport.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/dllimport.cpp?rev=356458&r1=356457&r2=356458&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/dllimport.cpp (original) +++ cfe/trunk/test/SemaCXX/dllimport.cpp Tue Mar 19 07:53:52 2019 @@ -121,7 +121,9 @@ __declspec(dllimport) extern int GlobalR // External linkage is required. __declspec(dllimport) static int StaticGlobal; // expected-error{{'StaticGlobal' must have external linkage when declared 'dllimport'}} __declspec(dllimport) Internal InternalTypeGlobal; // expected-error{{'InternalTypeGlobal' must have external linkage when declared 'dllimport'}} +#ifndef MS namespace { __declspec(dllimport) int InternalGlobal; } // expected-error{{'(anonymous namespace)::InternalGlobal' must have external linkage when declared 'dllimport'}} +#endif namespace ns { __declspec(dllimport) int ExternalGlobal; } __declspec(dllimport) auto InternalAutoTypeGlobal = Internal(); // expected-error{{'InternalAutoTypeGlobal' must have external linkage when declared 'dllimport'}} @@ -213,7 +215,9 @@ template<typename T> __declspec(dllimpor // External linkage is required. template<typename T> __declspec(dllimport) static int StaticVarTmpl; // expected-error{{'StaticVarTmpl' must have external linkage when declared 'dllimport'}} template<typename T> __declspec(dllimport) Internal InternalTypeVarTmpl; // expected-error{{'InternalTypeVarTmpl' must have external linkage when declared 'dllimport'}} +#ifndef MS namespace { template<typename T> __declspec(dllimport) int InternalVarTmpl; } // expected-error{{'(anonymous namespace)::InternalVarTmpl' must have external linkage when declared 'dllimport'}} +#endif namespace ns { template<typename T> __declspec(dllimport) int ExternalVarTmpl; } template<typename T> __declspec(dllimport) auto InternalAutoTypeVarTmpl = Internal(); // expected-error{{definition of dllimport data}} // expected-error{{'InternalAutoTypeVarTmpl' must have external linkage when declared 'dllimport'}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits