From: Rafael Espindola Date: Fri, 18 May 2012 01:47:00 +0000 (+0000) Subject: Centralize the handling of the "attribute declaration must precede definition" X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3f664061e58aabd01996f01b96eb9f5c9e45c3e2;p=clang 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 --- 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(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/test/Sema/attr-decl-after-definition.c b/test/Sema/attr-decl-after-definition.c index 4d32e0028b..ba6df59068 100644 --- a/test/Sema/attr-decl-after-definition.c +++ b/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}}