diff options
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 29 | ||||
-rw-r--r-- | clang/test/Sema/dllexport.c | 12 | ||||
-rw-r--r-- | clang/test/Sema/dllimport.c | 21 | ||||
-rw-r--r-- | clang/test/SemaCXX/dllexport.cpp | 10 | ||||
-rw-r--r-- | clang/test/SemaCXX/dllimport.cpp | 10 |
6 files changed, 65 insertions, 20 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 077345f1ae8..6f96e3a35b3 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2133,6 +2133,9 @@ def warn_attribute_invalid_on_definition : Warning< InGroup<IgnoredAttributes>; def err_attribute_dll_redeclaration : Error< "redeclaration of %q0 cannot add %q1 attribute">; +def warn_attribute_dll_redeclaration : Warning< + "redeclaration of %q0 should not add %q1 attribute">, + InGroup<DiagGroup<"dll-attribute-on-redeclaration">>; def err_attribute_dllimport_function_definition : Error< "dllimport cannot be applied to non-inline function definition">; def err_attribute_dll_deleted : Error< diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index e5cf31a9b37..2d2f97316de 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -5075,7 +5075,7 @@ static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl, NewDecl = NewTD->getTemplatedDecl(); if (!OldDecl || !NewDecl) - return; + return; const DLLImportAttr *OldImportAttr = OldDecl->getAttr<DLLImportAttr>(); const DLLExportAttr *OldExportAttr = OldDecl->getAttr<DLLExportAttr>(); @@ -5092,13 +5092,30 @@ static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl, // Implicitly generated declarations are also excluded for now because there // is no other way to switch these to use dllimport or dllexport. bool AddsAttr = !(OldImportAttr || OldExportAttr) && HasNewAttr; + if (AddsAttr && !IsSpecialization && !OldDecl->isImplicit()) { - S.Diag(NewDecl->getLocation(), diag::err_attribute_dll_redeclaration) - << NewDecl - << (NewImportAttr ? (const Attr *)NewImportAttr : NewExportAttr); + // If the declaration hasn't been used yet, allow with a warning for + // free functions and global variables. + bool JustWarn = false; + if (!OldDecl->isUsed() && OldDecl->getDeclContext()->isFileContext()) { + auto *VD = dyn_cast<VarDecl>(OldDecl); + if (VD && !VD->getDescribedVarTemplate()) + JustWarn = true; + auto *FD = dyn_cast<FunctionDecl>(OldDecl); + if (FD && FD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) + JustWarn = true; + } + + unsigned DiagID = JustWarn ? diag::warn_attribute_dll_redeclaration + : diag::err_attribute_dll_redeclaration; + S.Diag(NewDecl->getLocation(), DiagID) + << NewDecl + << (NewImportAttr ? (const Attr *)NewImportAttr : NewExportAttr); S.Diag(OldDecl->getLocation(), diag::note_previous_declaration); - NewDecl->setInvalidDecl(); - return; + if (!JustWarn) { + NewDecl->setInvalidDecl(); + return; + } } // A redeclaration is not allowed to drop a dllimport attribute, the only diff --git a/clang/test/Sema/dllexport.c b/clang/test/Sema/dllexport.c index c6d04dc6342..6c71ad82987 100644 --- a/clang/test/Sema/dllexport.c +++ b/clang/test/Sema/dllexport.c @@ -39,8 +39,13 @@ __declspec(dllexport) extern int GlobalRedecl2; int GlobalRedecl2; extern int GlobalRedecl3; // expected-note{{previous declaration is here}} +int useGlobalRedecl3() { return GlobalRedecl3; } __declspec(dllexport) extern int GlobalRedecl3; // expected-error{{redeclaration of 'GlobalRedecl3' cannot add 'dllexport' attribute}} + extern int GlobalRedecl4; // expected-note{{previous declaration is here}} +__declspec(dllexport) extern int GlobalRedecl4; // expected-warning{{redeclaration of 'GlobalRedecl4' should not add 'dllexport' attribute}} + + // External linkage is required. __declspec(dllexport) static int StaticGlobal; // expected-error{{'StaticGlobal' must have external linkage when declared 'dllexport'}} @@ -86,11 +91,18 @@ __declspec(dllexport) void redecl3(); void redecl3() {} void redecl4(); // expected-note{{previous declaration is here}} +void useRedecl4() { redecl4(); } __declspec(dllexport) void redecl4(); // expected-error{{redeclaration of 'redecl4' cannot add 'dllexport' attribute}} void redecl5(); // expected-note{{previous declaration is here}} +void useRedecl5() { redecl5(); } __declspec(dllexport) inline void redecl5() {} // expected-error{{redeclaration of 'redecl5' cannot add 'dllexport' attribute}} +// Allow with a warning if the decl hasn't been used yet. + void redecl6(); // expected-note{{previous declaration is here}} +__declspec(dllexport) void redecl6(); // expected-warning{{redeclaration of 'redecl6' should not 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 30ea4f3089c..d64c85953d0 100644 --- a/clang/test/Sema/dllimport.c +++ b/clang/test/Sema/dllimport.c @@ -64,9 +64,16 @@ int GlobalRedecl2c __attribute__((dllimport)); __declspec(dllimport) extern int GlobalRedecl3; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} extern int GlobalRedecl3; // expected-warning{{'GlobalRedecl3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} +// Adding an attribute on redeclaration. extern int GlobalRedecl4; // expected-note{{previous declaration is here}} +int useGlobalRedecl4() { return GlobalRedecl4; } __declspec(dllimport) extern int GlobalRedecl4; // expected-error{{redeclaration of 'GlobalRedecl4' cannot add 'dllimport' attribute}} +// Allow with a warning if the decl hasn't been used yet. + extern int GlobalRedecl5; // expected-note{{previous declaration is here}} +__declspec(dllimport) extern int GlobalRedecl5; // expected-warning{{redeclaration of 'GlobalRedecl5' should not add 'dllimport' attribute}} + + // External linkage is required. __declspec(dllimport) static int StaticGlobal; // expected-error{{'StaticGlobal' must have external linkage when declared 'dllimport'}} @@ -128,14 +135,20 @@ __declspec(dllimport) void redecl3(); // expected-note{{previous declaration is void redecl3() {} // expected-warning{{'redecl3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} void redecl4(); // expected-note{{previous declaration is here}} +void useRedecl4() { redecl4(); } __declspec(dllimport) void redecl4(); // expected-error{{redeclaration of 'redecl4' cannot add 'dllimport' attribute}} +// Allow with a warning if the decl hasn't been used yet. + void redecl5(); // expected-note{{previous declaration is here}} +__declspec(dllimport) void redecl5(); // expected-warning{{redeclaration of 'redecl5' should not add 'dllimport' attribute}} + + // Inline redeclarations are fine. -__declspec(dllimport) void redecl5(); - inline void redecl5() {} +__declspec(dllimport) void redecl6(); + inline void redecl6() {} - void redecl6(); // expected-note{{previous declaration is here}} -__declspec(dllimport) inline void redecl6() {} // expected-error{{redeclaration of 'redecl6' cannot add 'dllimport' attribute}} + void redecl7(); // expected-note{{previous declaration is here}} +__declspec(dllimport) inline void redecl7() {} // expected-warning{{redeclaration of 'redecl7' should not 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 8219c47cd11..df87c737865 100644 --- a/clang/test/SemaCXX/dllexport.cpp +++ b/clang/test/SemaCXX/dllexport.cpp @@ -53,7 +53,7 @@ __declspec(dllexport) extern int GlobalRedecl2; 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}} +__declspec(dllexport) extern int GlobalRedecl3; // expected-warning{{redeclaration of 'GlobalRedecl3' should not add 'dllexport' attribute}} // External linkage is required. __declspec(dllexport) static int StaticGlobal; // expected-error{{'StaticGlobal' must have external linkage when declared 'dllexport'}} @@ -186,10 +186,10 @@ __declspec(dllexport) void redecl2(); void redecl2() {} void redecl3(); // expected-note{{previous declaration is here}} -__declspec(dllexport) void redecl3(); // expected-error{{redeclaration of 'redecl3' cannot add 'dllexport' attribute}} +__declspec(dllexport) void redecl3(); // expected-warning{{redeclaration of 'redecl3' should not add 'dllexport' attribute}} void redecl4(); // expected-note{{previous declaration is here}} -__declspec(dllexport) inline void redecl4() {} // expected-error{{redeclaration of 'redecl4' cannot add 'dllexport' attribute}} +__declspec(dllexport) inline void redecl4() {} // expected-warning{{redeclaration of 'redecl4' should not add 'dllexport' attribute}} // Friend functions struct FuncFriend { @@ -200,8 +200,8 @@ struct FuncFriend { }; __declspec(dllexport) void friend1() {} void friend2() {} -__declspec(dllexport) void friend3() {} // expected-error{{redeclaration of 'friend3' cannot add 'dllexport' attribute}} -__declspec(dllexport) inline void friend4() {} // expected-error{{redeclaration of 'friend4' cannot add 'dllexport' attribute}} +__declspec(dllexport) void friend3() {} // expected-warning{{redeclaration of 'friend3' should not add 'dllexport' attribute}} +__declspec(dllexport) inline void friend4() {} // expected-warning{{redeclaration of 'friend4' should not add 'dllexport' attribute}} // Implicit declarations can be redeclared with dllexport. __declspec(dllexport) void* operator new(__SIZE_TYPE__ n); diff --git a/clang/test/SemaCXX/dllimport.cpp b/clang/test/SemaCXX/dllimport.cpp index 875cf1e5ea8..d0e88368fc3 100644 --- a/clang/test/SemaCXX/dllimport.cpp +++ b/clang/test/SemaCXX/dllimport.cpp @@ -75,7 +75,7 @@ __declspec(dllimport) extern int GlobalRedecl3; // expected-note{{previous decla extern int GlobalRedecl3; // expected-warning{{'GlobalRedecl3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} extern int GlobalRedecl4; // expected-note{{previous declaration is here}} -__declspec(dllimport) extern int GlobalRedecl4; // expected-error{{redeclaration of 'GlobalRedecl4' cannot add 'dllimport' attribute}} +__declspec(dllimport) extern int GlobalRedecl4; // expected-warning{{redeclaration of 'GlobalRedecl4' should not add 'dllimport' attribute}} // External linkage is required. __declspec(dllimport) static int StaticGlobal; // expected-error{{'StaticGlobal' must have external linkage when declared 'dllimport'}} @@ -224,10 +224,10 @@ __declspec(dllimport) void redecl3(); // expected-note{{previous declaration is void redecl3() {} // expected-warning{{'redecl3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} void redecl4(); // expected-note{{previous declaration is here}} -__declspec(dllimport) void redecl4(); // expected-error{{redeclaration of 'redecl4' cannot add 'dllimport' attribute}} +__declspec(dllimport) void redecl4(); // expected-warning{{redeclaration of 'redecl4' should not add 'dllimport' attribute}} void redecl5(); // expected-note{{previous declaration is here}} -__declspec(dllimport) inline void redecl5() {} // expected-error{{redeclaration of 'redecl5' cannot add 'dllimport' attribute}} +__declspec(dllimport) inline void redecl5() {} // expected-warning{{redeclaration of 'redecl5' should not add 'dllimport' attribute}} // Friend functions struct FuncFriend { @@ -240,8 +240,8 @@ struct FuncFriend { __declspec(dllimport) void friend1(); void friend2(); // expected-warning{{'friend2' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} void friend3() {} // expected-warning{{'friend3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} -__declspec(dllimport) void friend4(); // expected-error{{redeclaration of 'friend4' cannot add 'dllimport' attribute}} -__declspec(dllimport) inline void friend5() {} // expected-error{{redeclaration of 'friend5' cannot add 'dllimport' attribute}} +__declspec(dllimport) void friend4(); // expected-warning{{redeclaration of 'friend4' should not add 'dllimport' attribute}} +__declspec(dllimport) inline void friend5() {} // expected-warning{{redeclaration of 'friend5' should not add 'dllimport' attribute}} void __declspec(dllimport) friend6(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} void __declspec(dllimport) friend7(); |