From 3619104239aad500853ea3d23214d3bc22c16692 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Fri, 18 May 2012 01:47:00 +0000 Subject: [PATCH] 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 --- clang/lib/Sema/SemaDecl.cpp | 44 +++++++++++++--------------- clang/test/Sema/attr-decl-after-definition.c | 3 ++ 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index cc42720..6de5627 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(D)) + return TD->getDefinition(); + if (VarDecl *VD = dyn_cast(D)) + return VD->getDefinition(); + if (FunctionDecl *FD = dyn_cast(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(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(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() && diff --git a/clang/test/Sema/attr-decl-after-definition.c b/clang/test/Sema/attr-decl-after-definition.c index 4d32e00..ba6df59 100644 --- a/clang/test/Sema/attr-decl-after-definition.c +++ b/clang/test/Sema/attr-decl-after-definition.c @@ -17,3 +17,6 @@ int bar = 0; // expected-note {{previous definition is here}} int bar __attribute__((weak)); // expected-warning {{must precede definition}} int bar; +struct zed { // expected-note {{previous definition is here}} +}; +struct __attribute__((visibility("hidden"))) zed; // expected-warning {{must precede definition}} -- 2.7.4