Index: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td @@ -2133,6 +2133,9 @@ InGroup; 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>; def err_attribute_dllimport_function_definition : Error< "dllimport cannot be applied to non-inline function definition">; def err_attribute_dll_deleted : Error< Index: cfe/trunk/lib/Sema/SemaDecl.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaDecl.cpp +++ cfe/trunk/lib/Sema/SemaDecl.cpp @@ -5075,7 +5075,7 @@ NewDecl = NewTD->getTemplatedDecl(); if (!OldDecl || !NewDecl) - return; + return; const DLLImportAttr *OldImportAttr = OldDecl->getAttr(); const DLLExportAttr *OldExportAttr = OldDecl->getAttr(); @@ -5092,13 +5092,30 @@ // 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(OldDecl); + if (VD && !VD->getDescribedVarTemplate()) + JustWarn = true; + auto *FD = dyn_cast(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 Index: cfe/trunk/test/Sema/dllexport.c =================================================================== --- cfe/trunk/test/Sema/dllexport.c +++ cfe/trunk/test/Sema/dllexport.c @@ -39,8 +39,13 @@ 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 @@ 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'}} Index: cfe/trunk/test/Sema/dllimport.c =================================================================== --- cfe/trunk/test/Sema/dllimport.c +++ cfe/trunk/test/Sema/dllimport.c @@ -64,9 +64,16 @@ __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 @@ 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'}} Index: cfe/trunk/test/SemaCXX/dllexport.cpp =================================================================== --- cfe/trunk/test/SemaCXX/dllexport.cpp +++ cfe/trunk/test/SemaCXX/dllexport.cpp @@ -53,7 +53,7 @@ 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 @@ 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 @@ }; __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); Index: cfe/trunk/test/SemaCXX/dllimport.cpp =================================================================== --- cfe/trunk/test/SemaCXX/dllimport.cpp +++ cfe/trunk/test/SemaCXX/dllimport.cpp @@ -75,7 +75,7 @@ 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 @@ 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 @@ __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();