On 01/09/18 00:16, Luc Van Oostenryck wrote: > Sparse has support for a subset of GCC's large collection of > attributes. It's not easy to know wich versions support this s/wich/which/ > or this attributes but since GCC5, there is a good solution s/this attributes but since GCC5,/that attribute. However, since GCC5/ > to this problem: the magic macro __has_attribute(<name>) > which evaluates to 1 if <name> is an attribute known to the > compiler and 0 otherwise. > > Add support for this __has_attribute() macro by extending the > already existing support for __has_builtin(). ATB, Ramsay Jones > > Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx> > --- > ident-list.h | 1 + > lib.c | 1 + > pre-process.c | 33 ++++++++++++++++++------- > validation/preprocessor/has-attribute.c | 1 - > 4 files changed, 26 insertions(+), 10 deletions(-) > > diff --git a/ident-list.h b/ident-list.h > index a37a4a1b5..75740b9d9 100644 > --- a/ident-list.h > +++ b/ident-list.h > @@ -59,6 +59,7 @@ IDENT_RESERVED(__label__); > * sparse. */ > IDENT(defined); > IDENT(once); > +IDENT(__has_attribute); > IDENT(__has_builtin); > __IDENT(pragma_ident, "__pragma__", 0); > __IDENT(__VA_ARGS___ident, "__VA_ARGS__", 0); > diff --git a/lib.c b/lib.c > index db456a63e..48c6dc983 100644 > --- a/lib.c > +++ b/lib.c > @@ -1287,6 +1287,7 @@ static void create_builtin_stream(void) > add_pre_buffer("#add_system \"%s/include-fixed\"\n", gcc_base_dir); > > add_pre_buffer("#define __has_builtin(x) 0\n"); > + add_pre_buffer("#define __has_attribute(x) 0\n"); > add_pre_buffer("#define __builtin_stdarg_start(a,b) ((a) = (__builtin_va_list)(&(b)))\n"); > add_pre_buffer("#define __builtin_va_start(a,b) ((a) = (__builtin_va_list)(&(b)))\n"); > add_pre_buffer("#define __builtin_ms_va_start(a,b) ((a) = (__builtin_ms_va_list)(&(b)))\n"); > diff --git a/pre-process.c b/pre-process.c > index da4b7acdb..bf4b8e766 100644 > --- a/pre-process.c > +++ b/pre-process.c > @@ -165,6 +165,12 @@ static void replace_with_has_builtin(struct token *token) > replace_with_bool(token, sym && sym->builtin); > } > > +static void replace_with_has_attribute(struct token *token) > +{ > + struct symbol *sym = lookup_symbol(token->ident, NS_KEYWORD); > + replace_with_bool(token, sym && sym->op && sym->op->attribute); > +} > + > static void expand_line(struct token *token) > { > replace_with_integer(token, token->pos.line); > @@ -1592,6 +1598,10 @@ static int expression_value(struct token **where) > state = 4; > beginning = list; > break; > + } else if (p->ident == &__has_attribute_ident) { > + state = 6; > + beginning = list; > + break; > } > if (!expand_one_symbol(list)) > continue; > @@ -1623,29 +1633,34 @@ static int expression_value(struct token **where) > *list = p->next; > continue; > > - // __has_builtin(xyz) > - case 4: > + // __has_builtin(x) or __has_attribute(x) > + case 4: case 6: > if (match_op(p, '(')) { > - state = 5; > + state++; > } else { > - sparse_error(p->pos, "missing '(' after \"__has_builtin\""); > + sparse_error(p->pos, "missing '(' after \"__has_%s\"", > + state == 4 ? "builtin" : "attribute"); > state = 0; > } > *beginning = p; > break; > - case 5: > + case 5: case 7: > if (token_type(p) != TOKEN_IDENT) { > sparse_error(p->pos, "identifier expected"); > state = 0; > break; > } > if (!match_op(p->next, ')')) > - sparse_error(p->pos, "missing ')' after \"__has_builtin\""); > - state = 6; > - replace_with_has_builtin(p); > + sparse_error(p->pos, "missing ')' after \"__has_%s\"", > + state == 5 ? "builtin" : "attribute"); > + if (state == 5) > + replace_with_has_builtin(p); > + else > + replace_with_has_attribute(p); > + state = 8; > *beginning = p; > break; > - case 6: > + case 8: > state = 0; > *list = p->next; > continue; > diff --git a/validation/preprocessor/has-attribute.c b/validation/preprocessor/has-attribute.c > index ec8dbb06e..3149cbfa6 100644 > --- a/validation/preprocessor/has-attribute.c > +++ b/validation/preprocessor/has-attribute.c > @@ -44,7 +44,6 @@ __has_attribute()??? Quesako? > /* > * check-name: has-attribute > * check-command: sparse -E $file > - * check-known-to-fail > * > * check-output-start > >