diff options
| author | Rafael Espindola <rafael.espindola@gmail.com> | 2012-05-18 01:47:00 +0000 |
|---|---|---|
| committer | Rafael Espindola <rafael.espindola@gmail.com> | 2012-05-18 01:47:00 +0000 |
| commit | 3619104239aad500853ea3d23214d3bc22c16692 (patch) | |
| tree | a9205d4f95709d5435c02e888bea529ed279c77a /clang/lib | |
| parent | 22d405f57b62d0eee7a994f074859e399583f7f1 (diff) | |
| download | bcm5719-llvm-3619104239aad500853ea3d23214d3bc22c16692.tar.gz bcm5719-llvm-3619104239aad500853ea3d23214d3bc22c16692.zip | |
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.
llvm-svn: 157039
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 44 |
1 files changed, 21 insertions, 23 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index cc42720a7b9..6de5627f3de 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/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>() && |

