]> granicus.if.org Git - clang/commitdiff
Don't allow dllexport/import on static local variables
authorHans Wennborg <hans@hanshq.net>
Fri, 4 Sep 2015 19:59:39 +0000 (19:59 +0000)
committerHans Wennborg <hans@hanshq.net>
Fri, 4 Sep 2015 19:59:39 +0000 (19:59 +0000)
They might technically have external linkage, but it still doesn't make sense
for the user to try and export such variables. This matches MSVC's and MinGW's
behaviour.

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

lib/Sema/SemaDecl.cpp
test/Sema/dllexport.c
test/Sema/dllimport.c
test/SemaCXX/dllexport.cpp
test/SemaCXX/dllimport.cpp

index 141f35a6a0ef500b5932ec94c3dbd0daf504dc95..acff354f70e8c7047aea023293f29dd2ce0acbed 100644 (file)
@@ -5355,9 +5355,11 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) {
     }
   }
 
-  // dll attributes require external linkage.
   if (const InheritableAttr *Attr = getDLLAttr(&ND)) {
-    if (!ND.isExternallyVisible()) {
+    // 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())) {
       S.Diag(ND.getLocation(), diag::err_attribute_dll_not_extern)
         << &ND << Attr;
       ND.setInvalidDecl();
index 69aad2eb54c0843159ad0dd88c98dcad8b74ca3e..56c9e74225f296800dc6753427bfde8306782856 100644 (file)
@@ -109,6 +109,11 @@ __declspec(dllexport) void redecl6(); // expected-warning{{redeclaration of 'red
 // External linkage is required.
 __declspec(dllexport) static int staticFunc(); // expected-error{{'staticFunc' must have external linkage when declared 'dllexport'}}
 
+// Static locals don't count as having external linkage.
+void staticLocalFunc() {
+  __declspec(dllexport) static int staticLocal; // expected-error{{'staticLocal' must have external linkage when declared 'dllexport'}}
+}
+
 
 
 //===----------------------------------------------------------------------===//
index d81aecd604c7f6a22f0242ffb678e875285a524d..f863499cf8402c8b4b51f2c88b37765a12e32f20 100644 (file)
@@ -168,3 +168,8 @@ __declspec(dllimport) inline void redecl7() {}
 
 // External linkage is required.
 __declspec(dllimport) static int staticFunc(); // expected-error{{'staticFunc' must have external linkage when declared 'dllimport'}}
+
+// Static locals don't count as having external linkage.
+void staticLocalFunc() {
+  __declspec(dllimport) static int staticLocal; // expected-error{{'staticLocal' must have external linkage when declared 'dllimport'}}
+}
index c3f26aa315553b76ef47d36de29c62ba698eb3ba..f7076fb8e8656f092a4a07fd0e49fafb9df42c5b 100644 (file)
@@ -71,14 +71,9 @@ __declspec(dllexport) auto ExternalAutoTypeGlobal = External();
 
 // Thread local variables are invalid.
 __declspec(dllexport) __thread int ThreadLocalGlobal; // expected-error{{'ThreadLocalGlobal' cannot be thread local when declared 'dllexport'}}
-inline void InlineWithThreadLocal() {
-  static __declspec(dllexport) __thread int ThreadLocalGlobal; // expected-error{{'ThreadLocalGlobal' cannot be thread local when declared 'dllexport'}}
-}
-
-// But if they're in a dllexport function, it's ok, because they will never get imported.
+// But a static local TLS var in an export function is OK.
 inline void __declspec(dllexport) ExportedInlineWithThreadLocal() {
-  static __declspec(dllexport) __thread int OK1; // no-error
-  static __thread int OK2; // no-error
+  static __thread int OK; // no-error
 }
 
 // Export in local scope.
index f17c2e22414c00636cda03c87374115ae0628d7d..91ed6b42606c96c4d07c6fb6b2ee254082cd4056 100644 (file)
@@ -93,16 +93,10 @@ __declspec(dllimport) auto InternalAutoTypeGlobal = Internal(); // expected-erro
 
 // Thread local variables are invalid.
 __declspec(dllimport) __thread int ThreadLocalGlobal; // expected-error{{'ThreadLocalGlobal' cannot be thread local when declared 'dllimport'}}
-inline void InlineWithThreadLocal() {
-  static __declspec(dllimport) __thread int ThreadLocalGlobal; // expected-error{{'ThreadLocalGlobal' cannot be thread local when declared 'dllimport'}}
-}
-
-// But if they're in a dllimported function, it's OK because we will not inline the function.
 // This doesn't work on MinGW, because there, dllimport on the inline function is ignored.
 #ifndef GNU
 inline void __declspec(dllimport) ImportedInlineWithThreadLocal() {
-  static __declspec(dllimport) __thread int OK1; // no-error
-  static __thread int OK2; // no-error
+  static __thread int OK; // no-error
 }
 #endif