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<
NewDecl = NewTD->getTemplatedDecl();
if (!OldDecl || !NewDecl)
- return;
+ return;
const DLLImportAttr *OldImportAttr = OldDecl->getAttr<DLLImportAttr>();
const DLLExportAttr *OldExportAttr = OldDecl->getAttr<DLLExportAttr>();
// 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
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'}}
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'}}
__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'}}
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'}}
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'}}
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 {
};
__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);
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'}}
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 {
__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();