aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2012-07-15 01:33:40 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2012-07-15 01:33:40 +0000
commitd320ffc0f58df23eb0e698c79105a68de9c0e37a (patch)
treee443ddada3b7b632945e96771d8a4f8a61fc07e6 /lib
parent4b044c6bc71d1fdce8998af09cf08b026fdd2189 (diff)
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@160227 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/Sema/SemaDecl.cpp42
1 files changed, 36 insertions, 6 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index ea032ac28e..17b120bc86 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/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;