def warn_attribute_invalid_on_definition : Warning<
"'%0' attribute cannot be specified on a definition">,
InGroup<IgnoredAttributes>;
+def err_attribute_dll_redeclaration : Error<
+ "redeclaration of %q0 cannot add %q1 attribute">;
def err_attribute_dllimport_data_definition : Error<
"definition of dllimport data">;
def err_attribute_weakref_not_static : Error<
}
}
+static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl,
+ NamedDecl *NewDecl,
+ bool IsSpecialization) {
+ if (TemplateDecl *OldTD = dyn_cast<TemplateDecl>(OldDecl))
+ OldDecl = OldTD->getTemplatedDecl();
+ if (TemplateDecl *NewTD = dyn_cast<TemplateDecl>(NewDecl))
+ NewDecl = NewTD->getTemplatedDecl();
+
+ if (!OldDecl || !NewDecl)
+ return;
+
+ const DLLImportAttr *OldImportAttr = OldDecl->getAttr<DLLImportAttr>();
+ const DLLExportAttr *OldExportAttr = OldDecl->getAttr<DLLExportAttr>();
+ const DLLImportAttr *NewImportAttr = NewDecl->getAttr<DLLImportAttr>();
+ const DLLExportAttr *NewExportAttr = NewDecl->getAttr<DLLExportAttr>();
+
+ // dllimport and dllexport are inheritable attributes so we have to exclude
+ // inherited attribute instances.
+ bool HasNewAttr = (NewImportAttr && !NewImportAttr->isInherited()) ||
+ (NewExportAttr && !NewExportAttr->isInherited());
+
+ // A redeclaration is not allowed to add a dllimport or dllexport attribute,
+ // the only exception being explicit specializations.
+ // 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);
+ S.Diag(OldDecl->getLocation(), diag::note_previous_declaration);
+ NewDecl->setInvalidDecl();
+ return;
+ }
+
+ // A redeclaration is not allowed to drop a dllimport attribute, the only
+ // exception being inline function definitions.
+ // FIXME: Handle inline functions.
+ // NB: MSVC converts such a declaration to dllexport.
+ if (OldImportAttr && !HasNewAttr) {
+ S.Diag(NewDecl->getLocation(),
+ diag::warn_redeclaration_without_attribute_prev_attribute_ignored)
+ << NewDecl << OldImportAttr;
+ S.Diag(OldDecl->getLocation(), diag::note_previous_declaration);
+ S.Diag(OldImportAttr->getLocation(), diag::note_previous_attribute);
+ OldDecl->dropAttr<DLLImportAttr>();
+ NewDecl->dropAttr<DLLImportAttr>();
+ }
+}
+
/// Given that we are within the definition of the given function,
/// will that definition behave like C99's 'inline', where the
/// definition is discarded except for optimization purposes?
}
}
+ if (D.isRedeclaration() && !Previous.empty()) {
+ checkDLLAttributeRedeclaration(
+ *this, dyn_cast<NamedDecl>(Previous.getRepresentativeDecl()), NewVD,
+ IsExplicitSpecialization);
+ }
+
if (NewTemplate) {
if (NewVD->isInvalidDecl())
NewTemplate->setInvalidDecl();
// Set this FunctionDecl's range up to the right paren.
NewFD->setRangeEnd(D.getSourceRange().getEnd());
+ if (D.isRedeclaration() && !Previous.empty()) {
+ checkDLLAttributeRedeclaration(
+ *this, dyn_cast<NamedDecl>(Previous.getRepresentativeDecl()), NewFD,
+ isExplicitSpecialization || isFunctionTemplateSpecialization);
+ }
+
if (getLangOpts().CPlusPlus) {
if (FunctionTemplate) {
if (NewFD->isInvalidDecl())
FD->setInvalidDecl();
return D;
}
-
- // Visual C++ appears to not think this is an issue, so only issue
- // a warning when Microsoft extensions are disabled.
- if (!LangOpts.MicrosoftExt) {
- // If a symbol previously declared dllimport is later defined, the
- // attribute is ignored in subsequent references, and a warning is
- // emitted.
- Diag(FD->getLocation(),
- diag::warn_redeclaration_without_attribute_prev_attribute_ignored)
- << FD << DA;
- }
}
// We want to attach documentation to original Decl (which might be
// a function template).
__declspec(dllexport) extern int GlobalDeclInit;
int GlobalDeclInit = 1;
+// Redeclarations
+__declspec(dllexport) extern int GlobalRedecl1;
+__declspec(dllexport) int GlobalRedecl1;
+
+__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}}
+
// Export in local scope.
void functionScope() {
__declspec(dllexport) extern int ExternLocalVarDecl;
__declspec(dllexport) void redecl3();
void redecl3() {}
+ void redecl4(); // expected-note{{previous declaration is here}}
+__declspec(dllexport) void redecl4(); // expected-error{{redeclaration of 'redecl4' cannot add 'dllexport' attribute}}
+
//===----------------------------------------------------------------------===//
int __declspec(dllimport) GlobalInit2 = 1; // expected-error{{definition of dllimport data}}
// Declare, then reject definition.
-__declspec(dllimport) extern int ExternGlobalDeclInit;
-int ExternGlobalDeclInit = 1; // expected-error{{definition of dllimport data}}
+__declspec(dllimport) extern int ExternGlobalDeclInit; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
+int ExternGlobalDeclInit = 1; // expected-warning{{'ExternGlobalDeclInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
-__declspec(dllimport) int GlobalDeclInit;
-int GlobalDeclInit = 1; // expected-error{{definition of dllimport data}}
+__declspec(dllimport) int GlobalDeclInit; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
+int GlobalDeclInit = 1; // expected-warning{{'GlobalDeclInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
-int *__attribute__((dllimport)) GlobalDeclChunkAttrInit;
-int *GlobalDeclChunkAttrInit = 0; // expected-error{{definition of dllimport data}}
+int *__attribute__((dllimport)) GlobalDeclChunkAttrInit; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
+int *GlobalDeclChunkAttrInit = 0; // expected-warning{{'GlobalDeclChunkAttrInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
-int GlobalDeclAttrInit __attribute__((dllimport));
-int GlobalDeclAttrInit = 1; // expected-error{{definition of dllimport data}}
+int GlobalDeclAttrInit __attribute__((dllimport)); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
+int GlobalDeclAttrInit = 1; // expected-warning{{'GlobalDeclAttrInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
// Redeclarations
__declspec(dllimport) extern int GlobalRedecl1;
int GlobalRedecl2c __attribute__((dllimport));
int GlobalRedecl2c __attribute__((dllimport));
+// NB: MSVC issues a warning and makes GlobalRedecl3 dllexport. We follow GCC
+// and drop the dllimport with a warning.
+__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}}
+
+ extern int GlobalRedecl4; // expected-note{{previous declaration is here}}
+__declspec(dllimport) extern int GlobalRedecl4; // expected-error{{redeclaration of 'GlobalRedecl4' cannot add 'dllimport' attribute}}
+
// Import in local scope.
__declspec(dllimport) float LocalRedecl1; // expected-note{{previous definition is here}}
__declspec(dllimport) float LocalRedecl2; // expected-note{{previous definition is here}}
__declspec(dllimport) void redecl1();
__declspec(dllimport) void redecl1();
-__declspec(dllimport) void redecl3();
+// NB: MSVC issues a warning and makes redecl2/redecl3 dllexport. We follow GCC
+// and drop the dllimport with a warning.
+__declspec(dllimport) void redecl2(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
+ void redecl2(); // expected-warning{{'redecl2' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+
+__declspec(dllimport) void redecl3(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
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}}
class AAA {
__declspec(dllimport) void f(void) { }
-void f2(void);
+void f2(void); // expected-note{{previous declaration is here}}
};
-__declspec(dllimport) void AAA::f2(void) { // expected-error {{'dllimport' attribute can be applied only to symbol}}
+__declspec(dllimport) void AAA::f2(void) { // expected-error{{'dllimport' attribute can be applied only to symbol}}
+ // expected-error@-1{{redeclaration of 'AAA::f2' cannot add 'dllimport' attribute}}
}
__declspec(dllexport) extern int GlobalDeclInit;
int GlobalDeclInit = 1;
+// Redeclarations
+__declspec(dllexport) extern int GlobalRedecl1;
+__declspec(dllexport) int GlobalRedecl1;
+
+__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}}
+
// Export in local scope.
void functionScope() {
__declspec(dllexport) extern int ExternLocalVarDecl;
__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}}
+
+// Friend functions
+struct FuncFriend {
+ friend __declspec(dllexport) void friend1();
+ friend __declspec(dllexport) void friend2();
+ friend void friend3(); // expected-note{{previous declaration is here}}
+};
+__declspec(dllexport) void friend1() {}
+ void friend2() {}
+__declspec(dllexport) void friend3() {} // expected-error{{redeclaration of 'friend3' cannot add 'dllexport' attribute}}
+
+// Implicit declarations can be redeclared with dllexport.
+__declspec(dllexport) void* operator new(__SIZE_TYPE__ n);
+
//===----------------------------------------------------------------------===//
template<typename T> __declspec(dllexport) void funcTmplRedecl2();
template<typename T> void funcTmplRedecl2() {}
-template<typename T> __declspec(dllexport) void funcTmplRedecl3();
-template<typename T> void funcTmplRedecl3() {}
+template<typename T> void funcTmplRedecl3(); // expected-note{{previous declaration is here}}
+template<typename T> __declspec(dllexport) void funcTmplRedecl3(); // expected-error{{redeclaration of 'funcTmplRedecl3' cannot add 'dllexport' attribute}}
+
+// Function template friends
+struct FuncTmplFriend {
+ template<typename T> friend __declspec(dllexport) void funcTmplFriend1();
+ template<typename T> friend __declspec(dllexport) void funcTmplFriend2();
+ template<typename T> friend void funcTmplFriend3(); // expected-note{{previous declaration is here}}
+};
+template<typename T> __declspec(dllexport) void funcTmplFriend1() {}
+template<typename T> void funcTmplFriend2() {}
+template<typename T> __declspec(dllexport) void funcTmplFriend3() {} // expected-error{{redeclaration of 'funcTmplFriend3' cannot add 'dllexport' attribute}}
template<typename T> void funcTmpl() {}
int __declspec(dllimport) GlobalInit2 = 1; // expected-error{{definition of dllimport data}}
// Declare, then reject definition.
-__declspec(dllimport) extern int ExternGlobalDeclInit;
-int ExternGlobalDeclInit = 1; // expected-error{{definition of dllimport data}}
+__declspec(dllimport) extern int ExternGlobalDeclInit; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
+int ExternGlobalDeclInit = 1; // expected-warning{{'ExternGlobalDeclInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
-__declspec(dllimport) int GlobalDeclInit;
-int GlobalDeclInit = 1; // expected-error{{definition of dllimport data}}
+__declspec(dllimport) int GlobalDeclInit; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
+int GlobalDeclInit = 1; // expected-warning{{'GlobalDeclInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
-int *__attribute__((dllimport)) GlobalDeclChunkAttrInit;
-int *GlobalDeclChunkAttrInit = 0; // expected-error{{definition of dllimport data}}
+int *__attribute__((dllimport)) GlobalDeclChunkAttrInit; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
+int *GlobalDeclChunkAttrInit = 0; // expected-warning{{'GlobalDeclChunkAttrInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
-int GlobalDeclAttrInit __attribute__((dllimport));
-int GlobalDeclAttrInit = 1; // expected-error{{definition of dllimport data}}
+int GlobalDeclAttrInit __attribute__((dllimport)); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
+int GlobalDeclAttrInit = 1; // expected-warning{{'GlobalDeclAttrInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
// Redeclarations
__declspec(dllimport) extern int GlobalRedecl1;
int GlobalRedecl2c __attribute__((dllimport));
int GlobalRedecl2c __attribute__((dllimport));
+// NB: MSVC issues a warning and makes GlobalRedecl3 dllexport. We follow GCC
+// and drop the dllimport with a warning.
+__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}}
+
+ extern int GlobalRedecl4; // expected-note{{previous declaration is here}}
+__declspec(dllimport) extern int GlobalRedecl4; // expected-error{{redeclaration of 'GlobalRedecl4' cannot add 'dllimport' attribute}}
+
// Import in local scope.
__declspec(dllimport) float LocalRedecl1; // expected-note{{previous definition is here}}
__declspec(dllimport) float LocalRedecl2; // expected-note{{previous definition is here}}
__declspec(dllimport) void redecl1();
__declspec(dllimport) void redecl1();
-__declspec(dllimport) void redecl3();
+// NB: MSVC issues a warning and makes redecl2/redecl3 dllexport. We follow GCC
+// and drop the dllimport with a warning.
+__declspec(dllimport) void redecl2(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
+ void redecl2(); // expected-warning{{'redecl2' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+
+__declspec(dllimport) void redecl3(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
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}}
+
+// Friend functions
+struct FuncFriend {
+ friend __declspec(dllimport) void friend1();
+ friend __declspec(dllimport) void friend2(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
+ friend __declspec(dllimport) void friend3(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
+ friend void friend4(); // expected-note{{previous declaration is here}}
+};
+__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}}
+
+// Implicit declarations can be redeclared with dllimport.
+__declspec(dllimport) void* operator new(__SIZE_TYPE__ n);
+
//===----------------------------------------------------------------------===//
template<typename T> __declspec(dllimport) void funcTmplRedecl1();
template<typename T> __declspec(dllimport) void funcTmplRedecl1();
-template<typename T> __declspec(dllimport) void funcTmplRedecl2();
-template<typename T> void funcTmplRedecl2();
+template<typename T> __declspec(dllimport) void funcTmplRedecl2(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
+template<typename T> void funcTmplRedecl2(); // expected-warning{{'funcTmplRedecl2' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
-template<typename T> __declspec(dllimport) void funcTmplRedecl3();
+template<typename T> __declspec(dllimport) void funcTmplRedecl3(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
template<typename T> void funcTmplRedecl3() {} // expected-warning{{'funcTmplRedecl3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+template<typename T> void funcTmplRedecl4(); // expected-note{{previous declaration is here}}
+template<typename T> __declspec(dllimport) void funcTmplRedecl4(); // expected-error{{redeclaration of 'funcTmplRedecl4' cannot add 'dllimport' attribute}}
+
+// Function template friends
+struct FuncTmplFriend {
+ template<typename T> friend __declspec(dllimport) void funcTmplFriend1();
+ template<typename T> friend __declspec(dllimport) void funcTmplFriend2(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
+ template<typename T> friend __declspec(dllimport) void funcTmplFriend3(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
+ template<typename T> friend void funcTmplFriend4(); // expected-note{{previous declaration is here}}
+};
+template<typename T> __declspec(dllimport) void funcTmplFriend1();
+template<typename T> void funcTmplFriend2(); // expected-warning{{'funcTmplFriend2' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+template<typename T> void funcTmplFriend3() {} // expected-warning{{'funcTmplFriend3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+template<typename T> __declspec(dllimport) void funcTmplFriend4(); // expected-error{{redeclaration of 'funcTmplFriend4' cannot add 'dllimport' attribute}}
+
template<typename T> void funcTmpl() {}
template<typename T> __declspec(dllimport) void importedFuncTmpl();