diff options
| author | Rafael Espindola <rafael.espindola@gmail.com> | 2012-07-15 01:33:40 +0000 |
|---|---|---|
| committer | Rafael Espindola <rafael.espindola@gmail.com> | 2012-07-15 01:33:40 +0000 |
| commit | faf556b7456b1b8044b24cb9c60198ccae70ba65 (patch) | |
| tree | 7c862cf4a40ecebd0c49017cb04915cc98531d9f /clang/lib/Sema | |
| parent | a5bba70c9c7174837ed4f1fb828e7c1d8f078572 (diff) | |
| download | bcm5719-llvm-faf556b7456b1b8044b24cb9c60198ccae70ba65.tar.gz bcm5719-llvm-faf556b7456b1b8044b24cb9c60198ccae70ba65.zip | |
Without this patch clang warns on
struct __attribute__((visibility("hidden"))) zed {
};
struct __attribute__((visibility("hidden"))) zed;
Which is a bit silly and got a lot noisier now that we correctly handle
visibility pragmas. This patch fixes that and also has some extra quality
improvements:
* We now produce an error instead of a warning for
struct __attribute__((visibility("hidden"))) zed {
};
struct __attribute__((visibility("default"))) zed;
* The "after definition" warning now points to the new attribute that is
ignored instead of pointing to the declaration.
llvm-svn: 160227
Diffstat (limited to 'clang/lib/Sema')
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 42 |
1 files changed, 36 insertions, 6 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index ea032ac28e9..17b120bc866 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -1767,16 +1767,46 @@ static const Decl *getDefinition(const Decl *D) { return NULL; } +static bool hasAttribute(const Decl *D, attr::Kind Kind) { + for (Decl::attr_iterator I = D->attr_begin(), E = D->attr_end(); + I != E; ++I) { + Attr *Attribute = *I; + if (Attribute->getKind() == Kind) + return true; + } + return false; +} + +/// checkNewAttributesAfterDef - If we already have a definition, check that +/// there are no new attributes in this declaration. +static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) { + if (!New->hasAttrs()) + return; + + const Decl *Def = getDefinition(Old); + if (!Def || Def == New) + return; + + AttrVec &NewAttributes = New->getAttrs(); + for (unsigned I = 0, E = NewAttributes.size(); I != E;) { + const Attr *NewAttribute = NewAttributes[I]; + if (hasAttribute(Def, NewAttribute->getKind())) { + ++I; + continue; // regular attr merging will take care of validating this. + } + S.Diag(NewAttribute->getLocation(), + diag::warn_attribute_precede_definition); + S.Diag(Def->getLocation(), diag::note_previous_definition); + NewAttributes.erase(NewAttributes.begin() + I); + --E; + } +} + /// mergeDeclAttributes - Copy attributes from the Old decl to the New one. void Sema::mergeDeclAttributes(Decl *New, Decl *Old, bool MergeDeprecation) { // attributes declared post-definition are currently ignored - const Decl *Def = getDefinition(Old); - if (Def && Def != New && New->hasAttrs()) { - Diag(New->getLocation(), diag::warn_attribute_precede_definition); - Diag(Def->getLocation(), diag::note_previous_definition); - New->dropAttrs(); - } + checkNewAttributesAfterDef(*this, New, Old); if (!Old->hasAttrs()) return; |

