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
