diff options
author | Hans Wennborg <hans@hanshq.net> | 2014-08-27 21:27:40 +0000 |
---|---|---|
committer | Hans Wennborg <hans@hanshq.net> | 2014-08-27 21:27:40 +0000 |
commit | dd96db2c034ce7700f4a4943bf148834adca42e7 (patch) | |
tree | ecfb5452ff7b8e9fffbd17d98272639defc55876 /clang/lib/Sema/SemaDecl.cpp | |
parent | cdb871d734232e38a5b17e12bdf4d713d6850998 (diff) | |
download | bcm5719-llvm-dd96db2c034ce7700f4a4943bf148834adca42e7.tar.gz bcm5719-llvm-dd96db2c034ce7700f4a4943bf148834adca42e7.zip |
Allow adding dll attributes on certain redecls with a warning if the decl hasn't been used yet (PR20746)
This shouldn't really be allowed, but it comes up in real code (see PR). As
long as the decl hasn't been used there's no technical difficulty in supporting
it, so downgrade the error to a warning.
Differential Revision: http://reviews.llvm.org/D5087
llvm-svn: 216619
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 29 |
1 files changed, 23 insertions, 6 deletions
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 |