summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
authorHans Wennborg <hans@hanshq.net>2014-08-27 21:27:40 +0000
committerHans Wennborg <hans@hanshq.net>2014-08-27 21:27:40 +0000
commitdd96db2c034ce7700f4a4943bf148834adca42e7 (patch)
treeecfb5452ff7b8e9fffbd17d98272639defc55876 /clang/lib/Sema/SemaDecl.cpp
parentcdb871d734232e38a5b17e12bdf4d713d6850998 (diff)
downloadbcm5719-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.cpp29
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
OpenPOWER on IntegriCloud