Both attributes require external linkage. This is not fully compatible
with MSVC because MSVC allows exporting/importing from anonymous
namespaces. But until we can mangle this properly this should not be
allowed.

-Nico
>From cee23a9951259b8e323d1d2c6ef9368cc50a6624 Mon Sep 17 00:00:00 2001
From: Nico Rieck <[email protected]>
Date: Tue, 25 Mar 2014 23:02:59 +0100
Subject: [PATCH] Require external linkage for dllimport/dllexport attributes
---
 include/clang/Basic/DiagnosticSemaKinds.td |  2 ++
 lib/Sema/SemaDecl.cpp                      | 16 ++++++++++++++++
 test/Sema/dllexport.c                      |  9 +++++++++
 test/Sema/dllimport.c                      |  7 +++++++
 test/SemaCXX/dllexport.cpp                 | 28 ++++++++++++++++++++++++++++
 test/SemaCXX/dllimport.cpp                 | 25 +++++++++++++++++++++++++
 6 files changed, 87 insertions(+)

diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 4786708..74852af 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2071,6 +2071,8 @@ def err_attribute_weak_static : Error<
   "weak declaration cannot have internal linkage">;
 def err_attribute_selectany_non_extern_data : Error<
   "'selectany' can only be applied to data items with external linkage">;
+def err_attribute_dll_not_extern : Error<
+  "%q0 must have external linkage when declared %q1">;
 def warn_attribute_invalid_on_definition : Warning<
   "'%0' attribute cannot be specified on a definition">,
   InGroup<IgnoredAttributes>;
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 27ad642..2ff7557 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -4843,6 +4843,22 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) {
       ND.dropAttr<SelectAnyAttr>();
     }
   }
+
+  // dll attributes require external linkage.
+  if (const DLLImportAttr *Attr = ND.getAttr<DLLImportAttr>()) {
+    if (!ND.isExternallyVisible()) {
+      S.Diag(ND.getLocation(), diag::err_attribute_dll_not_extern)
+        << &ND << Attr;
+      ND.setInvalidDecl();
+    }
+  }
+  if (const DLLExportAttr *Attr = ND.getAttr<DLLExportAttr>()) {
+    if (!ND.isExternallyVisible()) {
+      S.Diag(ND.getLocation(), diag::err_attribute_dll_not_extern)
+        << &ND << Attr;
+      ND.setInvalidDecl();
+    }
+  }
 }
 
 static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl,
diff --git a/test/Sema/dllexport.c b/test/Sema/dllexport.c
index 5cfe147..f77d296 100644
--- a/test/Sema/dllexport.c
+++ b/test/Sema/dllexport.c
@@ -41,9 +41,15 @@ __declspec(dllexport) extern int GlobalRedecl2;
                       extern int GlobalRedecl3; // expected-note{{previous declaration is here}}
 __declspec(dllexport) extern int GlobalRedecl3; // expected-error{{'GlobalRedecl3' redeclared with different dll attributes}}
 
+// External linkage is required.
+__declspec(dllexport) static int StaticGlobal; // expected-error{{'StaticGlobal' must have external linkage when declared 'dllexport'}}
+
 // Export in local scope.
 void functionScope() {
+  __declspec(dllexport)        int LocalVarDecl; // expected-error{{'LocalVarDecl' must have external linkage when declared 'dllexport'}}
+  __declspec(dllexport)        int LocalVarDef = 1; // expected-error{{'LocalVarDef' must have external linkage when declared 'dllexport'}}
   __declspec(dllexport) extern int ExternLocalVarDecl;
+  __declspec(dllexport) static int StaticLocalVar; // expected-error{{'StaticLocalVar' must have external linkage when declared 'dllexport'}}
 }
 
 
@@ -82,6 +88,9 @@ __declspec(dllexport) void redecl3();
                       void redecl4(); // expected-note{{previous declaration is here}}
 __declspec(dllexport) void redecl4(); // expected-error{{'redecl4' redeclared with different dll attributes}}
 
+// External linkage is required.
+__declspec(dllexport) static int staticFunc(); // expected-error{{'staticFunc' must have external linkage when declared 'dllexport'}}
+
 
 
 //===----------------------------------------------------------------------===//
diff --git a/test/Sema/dllimport.c b/test/Sema/dllimport.c
index 4aea694..07b1b97 100644
--- a/test/Sema/dllimport.c
+++ b/test/Sema/dllimport.c
@@ -64,6 +64,9 @@ __declspec(dllimport) extern int GlobalRedecl3; // expected-note{{previous decla
                       extern int GlobalRedecl4; // expected-note{{previous declaration is here}}
 __declspec(dllimport) extern int GlobalRedecl4; // expected-error{{'GlobalRedecl4' redeclared with different dll attributes}}
 
+// External linkage is required.
+__declspec(dllimport) static int StaticGlobal; // expected-error{{'StaticGlobal' must have external linkage when declared 'dllimport'}}
+
 // Import in local scope.
 __declspec(dllimport) float LocalRedecl1; // expected-note{{previous definition is here}}
 __declspec(dllimport) float LocalRedecl2; // expected-note{{previous definition is here}}
@@ -77,6 +80,7 @@ void functionScope() {
   __declspec(dllimport)        int LocalVarDef = 1; // expected-error{{definition of dllimport data}}
   __declspec(dllimport) extern int ExternLocalVarDecl;
   __declspec(dllimport) extern int ExternLocalVarDef = 1; // expected-error{{definition of dllimport data}}
+  __declspec(dllimport) static int StaticLocalVar; // expected-error{{'StaticLocalVar' must have external linkage when declared 'dllimport'}}
 }
 
 
@@ -113,3 +117,6 @@ __declspec(dllimport) void redecl3(); // expected-note{{previous declaration is
 
                       void redecl4(); // expected-note{{previous declaration is here}}
 __declspec(dllimport) void redecl4(); // expected-error{{'redecl4' redeclared with different dll attributes}}
+
+// External linkage is required.
+__declspec(dllimport) static int staticFunc(); // expected-error{{'staticFunc' must have external linkage when declared 'dllimport'}}
diff --git a/test/SemaCXX/dllexport.cpp b/test/SemaCXX/dllexport.cpp
index 378e231..2a4e936 100644
--- a/test/SemaCXX/dllexport.cpp
+++ b/test/SemaCXX/dllexport.cpp
@@ -11,6 +11,8 @@ struct ExplicitSpec_Exported {};
 struct ExplicitSpec_Def_Exported {};
 struct ExplicitSpec_InlineDef_Exported {};
 struct ExplicitSpec_NotExported {};
+namespace { struct Internal {}; }
+struct External { int v; };
 
 
 // Invalid usage.
@@ -53,9 +55,23 @@ __declspec(dllexport) extern int GlobalRedecl2;
                       extern int GlobalRedecl3; // expected-note{{previous declaration is here}}
 __declspec(dllexport) extern int GlobalRedecl3; // expected-error{{'GlobalRedecl3' redeclared with different dll attributes}}
 
+// 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'}}
+namespace    { __declspec(dllexport) int InternalGlobal; } // expected-error{{'<anonymous namespace>::InternalGlobal' must have external linkage when declared 'dllexport'}}
+namespace ns { __declspec(dllexport) int ExternalGlobal; }
+
+#if __has_feature(cxx_auto_type)
+__declspec(dllexport) auto InternalAutoTypeGlobal = Internal(); // expected-error{{'InternalAutoTypeGlobal' must have external linkage when declared 'dllexport'}}
+__declspec(dllexport) auto ExternalAutoTypeGlobal = External();
+#endif
+
 // Export in local scope.
 void functionScope() {
+  __declspec(dllexport)        int LocalVarDecl; // expected-error{{'LocalVarDecl' must have external linkage when declared 'dllexport'}}
+  __declspec(dllexport)        int LocalVarDef = 1; // expected-error{{'LocalVarDef' must have external linkage when declared 'dllexport'}}
   __declspec(dllexport) extern int ExternLocalVarDecl;
+  __declspec(dllexport) static int StaticLocalVar; // expected-error{{'StaticLocalVar' must have external linkage when declared 'dllexport'}}
 }
 
 
@@ -110,6 +126,12 @@ __declspec(dllexport) void friend3() {} // expected-error{{'friend3' redeclared
 // Implicit declarations can be redeclared with dllexport.
 __declspec(dllexport) void* operator new(__SIZE_TYPE__ n);
 
+// External linkage is required.
+__declspec(dllexport) static int staticFunc(); // expected-error{{'staticFunc' must have external linkage when declared 'dllexport'}}
+__declspec(dllexport) Internal internalRetFunc(); // expected-error{{'internalRetFunc' must have external linkage when declared 'dllexport'}}
+namespace    { __declspec(dllexport) void internalFunc() {} } // expected-error{{'<anonymous namespace>::internalFunc' must have external linkage when declared 'dllexport'}}
+namespace ns { __declspec(dllexport) void externalFunc() {} }
+
 
 
 //===----------------------------------------------------------------------===//
@@ -143,6 +165,12 @@ template<typename T> __declspec(dllexport) void funcTmplFriend1() {}
 template<typename T>                       void funcTmplFriend2() {}
 template<typename T> __declspec(dllexport) void funcTmplFriend3() {} // expected-error{{'funcTmplFriend3' redeclared with different dll attributes}}
 
+// External linkage is required.
+template<typename T> __declspec(dllexport) static int staticFuncTmpl(); // expected-error{{'staticFuncTmpl' must have external linkage when declared 'dllexport'}}
+template<typename T> __declspec(dllexport) Internal internalRetFuncTmpl(); // expected-error{{'internalRetFuncTmpl' must have external linkage when declared 'dllexport'}}
+namespace    { template<typename T> __declspec(dllexport) void internalFuncTmpl(); } // expected-error{{'<anonymous namespace>::internalFuncTmpl' must have external linkage when declared 'dllexport'}}
+namespace ns { template<typename T> __declspec(dllexport) void externalFuncTmpl(); }
+
 
 template<typename T> void funcTmpl() {}
 template<typename T> __declspec(dllexport) void exportedFuncTmplDecl();
diff --git a/test/SemaCXX/dllimport.cpp b/test/SemaCXX/dllimport.cpp
index 95bc6a2..9f2209f 100644
--- a/test/SemaCXX/dllimport.cpp
+++ b/test/SemaCXX/dllimport.cpp
@@ -11,6 +11,7 @@ struct ExplicitSpec_Imported {};
 struct ExplicitSpec_Def_Imported {};
 struct ExplicitSpec_InlineDef_Imported {};
 struct ExplicitSpec_NotImported {};
+namespace { struct Internal {}; }
 
 
 // Invalid usage.
@@ -76,6 +77,17 @@ __declspec(dllimport) extern int GlobalRedecl3; // expected-note{{previous decla
                       extern int GlobalRedecl4; // expected-note{{previous declaration is here}}
 __declspec(dllimport) extern int GlobalRedecl4; // expected-error{{'GlobalRedecl4' redeclared with different dll attributes}}
 
+// 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'}}
+namespace    { __declspec(dllimport) int InternalGlobal; } // expected-error{{'<anonymous namespace>::InternalGlobal' must have external linkage when declared 'dllimport'}}
+namespace ns { __declspec(dllimport) int ExternalGlobal; }
+
+#if __has_feature(cxx_auto_type)
+__declspec(dllimport) auto InternalAutoTypeGlobal = Internal(); // expected-error{{'InternalAutoTypeGlobal' must have external linkage when declared 'dllimport'}}
+                                                                // expected-error@-1{{definition of dllimport data}}
+#endif
+
 // Import in local scope.
 __declspec(dllimport) float LocalRedecl1; // expected-note{{previous definition is here}}
 __declspec(dllimport) float LocalRedecl2; // expected-note{{previous definition is here}}
@@ -89,6 +101,7 @@ void functionScope() {
   __declspec(dllimport)        int LocalVarDef = 1; // expected-error{{definition of dllimport data}}
   __declspec(dllimport) extern int ExternLocalVarDecl;
   __declspec(dllimport) extern int ExternLocalVarDef = 1; // expected-error{{definition of dllimport data}}
+  __declspec(dllimport) static int StaticLocalVar; // expected-error{{'StaticLocalVar' must have external linkage when declared 'dllimport'}}
 }
 
 
@@ -144,6 +157,12 @@ __declspec(dllimport) void friend4(); // expected-error{{'friend4' redeclared wi
 // Implicit declarations can be redeclared with dllimport.
 __declspec(dllimport) void* operator new(__SIZE_TYPE__ n);
 
+// External linkage is required.
+__declspec(dllimport) static int staticFunc(); // expected-error{{'staticFunc' must have external linkage when declared 'dllimport'}}
+__declspec(dllimport) Internal internalRetFunc(); // expected-error{{'internalRetFunc' must have external linkage when declared 'dllimport'}}
+namespace    { __declspec(dllimport) void internalFunc(); } // expected-error{{'<anonymous namespace>::internalFunc' must have external linkage when declared 'dllimport'}}
+namespace ns { __declspec(dllimport) void externalFunc(); }
+
 
 
 //===----------------------------------------------------------------------===//
@@ -179,6 +198,12 @@ template<typename T>                       void funcTmplFriend2(); // expected-w
 template<typename T>                       void funcTmplFriend3() {} // expected-warning{{'funcTmplFriend3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
 template<typename T> __declspec(dllimport) void funcTmplFriend4(); // expected-error{{'funcTmplFriend4' redeclared with different dll attributes}}
 
+// External linkage is required.
+template<typename T> __declspec(dllimport) static int staticFuncTmpl(); // expected-error{{'staticFuncTmpl' must have external linkage when declared 'dllimport'}}
+template<typename T> __declspec(dllimport) Internal internalRetFuncTmpl(); // expected-error{{'internalRetFuncTmpl' must have external linkage when declared 'dllimport'}}
+namespace    { template<typename T> __declspec(dllimport) void internalFuncTmpl(); } // expected-error{{'<anonymous namespace>::internalFuncTmpl' must have external linkage when declared 'dllimport'}}
+namespace ns { template<typename T> __declspec(dllimport) void externalFuncTmpl(); }
+
 
 template<typename T> void funcTmpl() {}
 template<typename T> __declspec(dllimport) void importedFuncTmpl();
-- 
1.9.0.msysgit.0

_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to