bool AddsAttr = !(OldImportAttr || OldExportAttr) && HasNewAttr;
if (AddsAttr && !IsSpecialization && !OldDecl->isImplicit()) {
- // If the declaration hasn't been used yet, allow with a warning for
- // free functions and global variables.
+ // Allow with a warning for free functions and global variables.
bool JustWarn = false;
- if (!OldDecl->isUsed() && !OldDecl->isCXXClassMember()) {
+ if (!OldDecl->isCXXClassMember()) {
auto *VD = dyn_cast<VarDecl>(OldDecl);
if (VD && !VD->getDescribedVarTemplate())
JustWarn = true;
JustWarn = true;
}
+ // We cannot change a declaration that's been used because IR has already
+ // been emitted. Dllimported functions will still work though (modulo
+ // address equality) as they can use the thunk.
+ if (OldDecl->isUsed())
+ if (!isa<FunctionDecl>(OldDecl) || !NewImportAttr)
+ JustWarn = false;
+
unsigned DiagID = JustWarn ? diag::warn_attribute_dll_redeclaration
: diag::err_attribute_dll_redeclaration;
S.Diag(NewDecl->getLocation(), DiagID)
void redecl4(); // expected-note{{previous declaration is here}}
void useRedecl4() { redecl4(); }
-__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}}
// Allow with a warning if the decl hasn't been used yet.
void redecl5(); // expected-note{{previous declaration is here}}