diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2012-05-10 02:50:16 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2012-05-10 02:50:16 +0000 |
commit | 98ae834a3e289f84f0765d0d0ca7ff22ccaba458 (patch) | |
tree | 03ecf7dfefbdfd70031efc768701c98b753b91d2 /lib/Sema/SemaDecl.cpp | |
parent | 88feba05142651618aba0a0e57b0b98e026de336 (diff) |
Fix an old (2009) FIXME:
// FIXME: This needs to happen before we merge declarations. Then,
// let attribute merging cope with attribute conflicts.
This was already being done for variables, but for functions we were merging
then first and then applying the attributes. To avoid duplicating merging
logic, some of the helpers in SemaDeclAttr.cpp become methods that can
handle merging two attributes in one decl or inheriting attributes from one
decl to another.
With this change we are now able to produce errors for variables with
incompatible visibility attributes or warn about unused dllimports in
variables.
This changes the attribute list iteration back to being in reverse source
code order, as that matches what decl merging does and avoids differentiating
the two cases is the merge*Attr methods.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@156531 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 47 |
1 files changed, 34 insertions, 13 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index dfe73884d4..691c27cc25 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1658,6 +1658,32 @@ DeclHasAttr(const Decl *D, const Attr *A) { return false; } +bool Sema::mergeDeclAttribute(Decl *D, InheritableAttr *Attr) { + if (AvailabilityAttr *AA = dyn_cast<AvailabilityAttr>(Attr)) + return mergeAvailabilityAttr(D, AA->getRange(), true, AA->getPlatform(), + AA->getIntroduced(), AA->getDeprecated(), + AA->getObsoleted(), AA->getUnavailable(), + AA->getMessage()); + + if (VisibilityAttr *VA = dyn_cast<VisibilityAttr>(Attr)) + return mergeVisibilityAttr(D, VA->getRange(), true, VA->getVisibility()); + + if (DLLImportAttr *ImportA = dyn_cast<DLLImportAttr>(Attr)) + return mergeDLLImportAttr(D, ImportA->getRange(), true); + + if (DLLExportAttr *ExportA = dyn_cast<DLLExportAttr>(Attr)) + return mergeDLLExportAttr(D, ExportA->getRange(), true); + + if (!DeclHasAttr(D, Attr)) { + InheritableAttr *NewAttr = cast<InheritableAttr>(Attr->clone(Context)); + NewAttr->setInherited(true); + D->addAttr(NewAttr); + return true; + } + + return false; +} + /// mergeDeclAttributes - Copy attributes from the Old decl to the New one. void Sema::mergeDeclAttributes(Decl *New, Decl *Old, bool MergeDeprecation) { @@ -1681,12 +1707,8 @@ void Sema::mergeDeclAttributes(Decl *New, Decl *Old, isa<AvailabilityAttr>(*i))) continue; - if (!DeclHasAttr(New, *i)) { - InheritableAttr *newAttr = cast<InheritableAttr>((*i)->clone(Context)); - newAttr->setInherited(true); - New->addAttr(newAttr); + if (mergeDeclAttribute(New, *i)) foundAny = true; - } } if (!foundAny) New->dropAttrs(); @@ -5376,6 +5398,10 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, NewFD->setInvalidDecl(); } + // Handle attributes. + ProcessDeclAttributes(S, NewFD, D, + /*NonInheritable=*/false, /*Inheritable=*/true); + if (!getLangOpts().CPlusPlus) { // Perform semantic checking on the function declaration. bool isExplicitSpecialization=false; @@ -5623,14 +5649,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, << D.getCXXScopeSpec().getRange(); } } - - - // Handle attributes. We need to have merged decls when handling attributes - // (for example to check for conflicts, etc). - // FIXME: This needs to happen before we merge declarations. Then, - // let attribute merging cope with attribute conflicts. - ProcessDeclAttributes(S, NewFD, D, - /*NonInheritable=*/false, /*Inheritable=*/true); // attributes declared post-definition are currently ignored // FIXME: This should happen during attribute merging @@ -8715,6 +8733,9 @@ CreateNewDecl: InFunctionDeclarator && Name) DeclsInPrototypeScope.push_back(New); + if (PrevDecl) + mergeDeclAttributes(New, PrevDecl); + OwnedDecl = true; return New; } |