summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
authorNico Rieck <nico.rieck@gmail.com>2014-03-31 14:56:15 +0000
committerNico Rieck <nico.rieck@gmail.com>2014-03-31 14:56:15 +0000
commit82f0b06749e57467a730a7be9afe9a5ad539ebdc (patch)
tree60f5c77bcee188defa2566a97ea23d9c0b297237 /clang/lib/Sema/SemaDecl.cpp
parentc991305cc975aec8e76e5f1031dab470c5dcc35f (diff)
downloadbcm5719-llvm-82f0b06749e57467a730a7be9afe9a5ad539ebdc.tar.gz
bcm5719-llvm-82f0b06749e57467a730a7be9afe9a5ad539ebdc.zip
Sema: Check dll attributes on redeclarations
A redeclaration may not add dllimport or dllexport attributes. dllexport is sticky and can be omitted on redeclarations while dllimport cannot. llvm-svn: 205197
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r--clang/lib/Sema/SemaDecl.cpp73
1 files changed, 62 insertions, 11 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 82579d89cd2..26f8b2587fd 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -4845,6 +4845,56 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) {
}
}
+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?
@@ -5497,6 +5547,12 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
}
+ if (D.isRedeclaration() && !Previous.empty()) {
+ checkDLLAttributeRedeclaration(
+ *this, dyn_cast<NamedDecl>(Previous.getRepresentativeDecl()), NewVD,
+ IsExplicitSpecialization);
+ }
+
if (NewTemplate) {
if (NewVD->isInvalidDecl())
NewTemplate->setInvalidDecl();
@@ -7318,6 +7374,12 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// 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())
@@ -9679,17 +9741,6 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
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).
OpenPOWER on IntegriCloud