aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2012-05-18 01:47:00 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2012-05-18 01:47:00 +0000
commit3f664061e58aabd01996f01b96eb9f5c9e45c3e2 (patch)
tree0e367323517f4a19992a8c57893212fdf5484266 /lib/Sema/SemaDecl.cpp
parent1434518f17272968765602a54391c794c975350a (diff)
Centralize the handling of the "attribute declaration must precede definition"
warning. This also makes us warn on tags, which, ironically, is the only case gcc warns on. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@157039 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r--lib/Sema/SemaDecl.cpp44
1 files changed, 21 insertions, 23 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index cc42720a7b..6de5627f3d 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -1698,9 +1698,30 @@ bool Sema::mergeDeclAttribute(Decl *D, InheritableAttr *Attr) {
return false;
}
+static const Decl *getDefinition(Decl *D) {
+ if (TagDecl *TD = dyn_cast<TagDecl>(D))
+ return TD->getDefinition();
+ if (VarDecl *VD = dyn_cast<VarDecl>(D))
+ return VD->getDefinition();
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ const FunctionDecl* Def;
+ if (FD->hasBody(Def))
+ return Def;
+ }
+ return NULL;
+}
+
/// 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();
+ }
+
if (!Old->hasAttrs())
return;
@@ -4251,18 +4272,6 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
CheckMemberSpecialization(NewVD, Previous))
NewVD->setInvalidDecl();
}
-
- // attributes declared post-definition are currently ignored
- // FIXME: This should be handled in attribute merging, not
- // here.
- if (Previous.isSingleResult()) {
- VarDecl *Def = dyn_cast<VarDecl>(Previous.getFoundDecl());
- if (Def && (Def = Def->getDefinition()) &&
- Def != NewVD && D.hasAttributes()) {
- Diag(NewVD->getLocation(), diag::warn_attribute_precede_definition);
- Diag(Def->getLocation(), diag::note_previous_definition);
- }
- }
// If this is a locally-scoped extern C variable, update the map of
// such variables.
@@ -5665,17 +5674,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
}
- // attributes declared post-definition are currently ignored
- // FIXME: This should happen during attribute merging
- if (D.isRedeclaration() && Previous.isSingleResult()) {
- const FunctionDecl *Def;
- FunctionDecl *PrevFD = dyn_cast<FunctionDecl>(Previous.getFoundDecl());
- if (PrevFD && PrevFD->isDefined(Def) && D.hasAttributes()) {
- Diag(NewFD->getLocation(), diag::warn_attribute_precede_definition);
- Diag(Def->getLocation(), diag::note_previous_definition);
- }
- }
-
AddKnownFunctionAttributes(NewFD);
if (NewFD->hasAttr<OverloadableAttr>() &&