diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index bd461f4597a1..37f277da52a3 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2074,6 +2074,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; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 26f8b2587fdd..9d7f13cdd789 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -4843,6 +4843,22 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) { ND.dropAttr(); } } + + // dll attributes require external linkage. + if (const DLLImportAttr *Attr = ND.getAttr()) { + if (!ND.isExternallyVisible()) { + S.Diag(ND.getLocation(), diag::err_attribute_dll_not_extern) + << &ND << Attr; + ND.setInvalidDecl(); + } + } + if (const DLLExportAttr *Attr = ND.getAttr()) { + 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/clang/test/Sema/dllexport.c b/clang/test/Sema/dllexport.c index 675bd492f856..8a71e5d7251e 100644 --- a/clang/test/Sema/dllexport.c +++ b/clang/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{{redeclaration of 'GlobalRedecl3' cannot add 'dllexport' attribute}} +// 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{{redeclaration of 'redecl4' cannot add 'dllexport' attribute}} +// External linkage is required. +__declspec(dllexport) static int staticFunc(); // expected-error{{'staticFunc' must have external linkage when declared 'dllexport'}} + //===----------------------------------------------------------------------===// diff --git a/clang/test/Sema/dllimport.c b/clang/test/Sema/dllimport.c index 46031173cd2d..a4982940c65a 100644 --- a/clang/test/Sema/dllimport.c +++ b/clang/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{{redeclaration of 'GlobalRedecl4' cannot add 'dllimport' attribute}} +// 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{{redeclaration of 'redecl4' cannot add 'dllimport' attribute}} + +// External linkage is required. +__declspec(dllimport) static int staticFunc(); // expected-error{{'staticFunc' must have external linkage when declared 'dllimport'}} diff --git a/clang/test/SemaCXX/dllexport.cpp b/clang/test/SemaCXX/dllexport.cpp index acbd4ce78f4c..0f4cb5c246d9 100644 --- a/clang/test/SemaCXX/dllexport.cpp +++ b/clang/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,21 @@ __declspec(dllexport) extern int GlobalRedecl2; extern int GlobalRedecl3; // expected-note{{previous declaration is here}} __declspec(dllexport) extern int GlobalRedecl3; // expected-error{{redeclaration of 'GlobalRedecl3' cannot add 'dllexport' attribute}} +// 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{{'::InternalGlobal' must have external linkage when declared 'dllexport'}} +namespace ns { __declspec(dllexport) int ExternalGlobal; } + +__declspec(dllexport) auto InternalAutoTypeGlobal = Internal(); // expected-error{{'InternalAutoTypeGlobal' must have external linkage when declared 'dllexport'}} +__declspec(dllexport) auto ExternalAutoTypeGlobal = External(); + // 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 +124,12 @@ __declspec(dllexport) void friend3() {} // expected-error{{redeclaration of 'fri // 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{{'::internalFunc' must have external linkage when declared 'dllexport'}} +namespace ns { __declspec(dllexport) void externalFunc() {} } + //===----------------------------------------------------------------------===// @@ -143,6 +163,12 @@ template __declspec(dllexport) void funcTmplFriend1() {} template void funcTmplFriend2() {} template __declspec(dllexport) void funcTmplFriend3() {} // expected-error{{redeclaration of 'funcTmplFriend3' cannot add 'dllexport' attribute}} +// External linkage is required. +template __declspec(dllexport) static int staticFuncTmpl(); // expected-error{{'staticFuncTmpl' must have external linkage when declared 'dllexport'}} +template __declspec(dllexport) Internal internalRetFuncTmpl(); // expected-error{{'internalRetFuncTmpl' must have external linkage when declared 'dllexport'}} +namespace { template __declspec(dllexport) void internalFuncTmpl(); } // expected-error{{'::internalFuncTmpl' must have external linkage when declared 'dllexport'}} +namespace ns { template __declspec(dllexport) void externalFuncTmpl(); } + template void funcTmpl() {} template __declspec(dllexport) void exportedFuncTmplDecl(); diff --git a/clang/test/SemaCXX/dllimport.cpp b/clang/test/SemaCXX/dllimport.cpp index f63943924c69..a96f18b23970 100644 --- a/clang/test/SemaCXX/dllimport.cpp +++ b/clang/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,15 @@ __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{{redeclaration of 'GlobalRedecl4' cannot add 'dllimport' attribute}} +// 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{{'::InternalGlobal' must have external linkage when declared 'dllimport'}} +namespace ns { __declspec(dllimport) int ExternalGlobal; } + +__declspec(dllimport) auto InternalAutoTypeGlobal = Internal(); // expected-error{{'InternalAutoTypeGlobal' must have external linkage when declared 'dllimport'}} + // expected-error@-1{{definition of dllimport data}} + // 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 +99,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 +155,12 @@ __declspec(dllimport) void friend4(); // expected-error{{redeclaration of 'frien // 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{{'::internalFunc' must have external linkage when declared 'dllimport'}} +namespace ns { __declspec(dllimport) void externalFunc(); } + //===----------------------------------------------------------------------===// @@ -179,6 +196,12 @@ template void funcTmplFriend2(); // expected-w template void funcTmplFriend3() {} // expected-warning{{'funcTmplFriend3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} template __declspec(dllimport) void funcTmplFriend4(); // expected-error{{redeclaration of 'funcTmplFriend4' cannot add 'dllimport' attribute}} +// External linkage is required. +template __declspec(dllimport) static int staticFuncTmpl(); // expected-error{{'staticFuncTmpl' must have external linkage when declared 'dllimport'}} +template __declspec(dllimport) Internal internalRetFuncTmpl(); // expected-error{{'internalRetFuncTmpl' must have external linkage when declared 'dllimport'}} +namespace { template __declspec(dllimport) void internalFuncTmpl(); } // expected-error{{'::internalFuncTmpl' must have external linkage when declared 'dllimport'}} +namespace ns { template __declspec(dllimport) void externalFuncTmpl(); } + template void funcTmpl() {} template __declspec(dllimport) void importedFuncTmpl();