diff options
author | Nico Rieck <nico.rieck@gmail.com> | 2014-03-31 14:56:15 +0000 |
---|---|---|
committer | Nico Rieck <nico.rieck@gmail.com> | 2014-03-31 14:56:15 +0000 |
commit | 82f0b06749e57467a730a7be9afe9a5ad539ebdc (patch) | |
tree | 60f5c77bcee188defa2566a97ea23d9c0b297237 /clang/lib/Sema/SemaDecl.cpp | |
parent | c991305cc975aec8e76e5f1031dab470c5dcc35f (diff) | |
download | bcm5719-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.cpp | 73 |
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). |