On 21/11/2019 13:11, Luc Van Oostenryck wrote: > It's common to declare a function with the attribute > 'pure' or 'noreturn' and to omit the attribute in the > function definition. It mak somehow sense since the > information conveyed by these attributes are destined > to the function users not the function itself. > > So, when checking declaration/definition, let the > current symbol inherit any function attributes present > in previous declarations. > > Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx> > --- > > The patch is also available for review & testing at: > git://github.com/lucvoo/sparse-dev.git fun-attr-inherit > > Changes since v1: > * the old name was 'allow omitted function attribute in definition' > * change the approach: instead of filtering out these attributes at > check-time, let's inherit them at declaration-time. Yep, I noticed that you didn't push the last patch #5. I had also thought that this would be a better approach, or rather that the test should be that the 'attributes list' given on the function definition should be a subset of the list given on the declaration. (so that the 'extra' attributes would be inherited by the function). This would imply, of course, that sparse should issue a warning/error when the attribute list on the definition contained some attributes that were not present in the declaration. Well, it seems reasonable anyway! ;-) It seems gcc has other ideas: $ cat -n junk.c 1 2 extern void exit (int __status) __attribute__ ((__noreturn__)); 3 4 void func0(int a) __attribute__ ((pure)); 5 6 __attribute__ ((pure)) __attribute__ ((__noreturn__)) 7 void func0(int a) 8 { 9 exit(0); 10 } $ So, sparse (with this patch applied) gets it: $ ./sparse junk.c junk.c:7:6: error: symbol 'func0' redeclared with different type (originally declared at junk.c:4) - different modifiers $ But gcc, not so much: $ gcc -c junk.c $ gcc -Wall -c junk.c $ gcc -Wall -Wextra -c junk.c junk.c: In function ‘func0’: junk.c:7:16: warning: unused parameter ‘a’ [-Wunused-parameter] void func0(int a) ^ $ So, I don't know ... ATB, Ramsay Jones > > > symbol.c | 9 +++++++++ > ...ion-attribute-omitted.c => function-redecl-funattr.c} | 3 +-- > validation/function-redecl2.c | 3 --- > 3 files changed, 10 insertions(+), 5 deletions(-) > rename validation/{function-attribute-omitted.c => function-redecl-funattr.c} (75%) > > diff --git a/symbol.c b/symbol.c > index 90149e5ae..bafa7c432 100644 > --- a/symbol.c > +++ b/symbol.c > @@ -588,6 +588,14 @@ struct symbol *befoul(struct symbol *type) > return NULL; > } > > +static void inherit_declaration(struct symbol *sym, struct symbol *prev) > +{ > + unsigned long mods = prev->ctype.modifiers; > + > + // inherit function attributes > + sym->ctype.modifiers |= mods & MOD_FUN_ATTR; > +} > + > void check_declaration(struct symbol *sym) > { > int warned = 0; > @@ -598,6 +606,7 @@ void check_declaration(struct symbol *sym) > continue; > if (sym->scope == next->scope) { > sym->same_symbol = next; > + inherit_declaration(sym, next); > return; > } > /* Extern in block level matches a TOPLEVEL non-static symbol */ > diff --git a/validation/function-attribute-omitted.c b/validation/function-redecl-funattr.c > similarity index 75% > rename from validation/function-attribute-omitted.c > rename to validation/function-redecl-funattr.c > index 43b301d8f..b1e2fb195 100644 > --- a/validation/function-attribute-omitted.c > +++ b/validation/function-redecl-funattr.c > @@ -9,6 +9,5 @@ void __noreturn n(void); > void n(void) { while (1) ; } > > /* > - * check-name: function-attribute-omitted > - * check-known-to-fail > + * check-name: function-redecl-funattr > */ > diff --git a/validation/function-redecl2.c b/validation/function-redecl2.c > index 3435aa00c..ef396137a 100644 > --- a/validation/function-redecl2.c > +++ b/validation/function-redecl2.c > @@ -25,7 +25,4 @@ void func2(int a) > > /* > * check-name: function-redecl2 > - * > - * check-known-to-fail > - * > */ >