diff options
author | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2019-09-30 16:27:17 +0200 |
---|---|---|
committer | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2020-06-18 21:26:31 +0200 |
commit | e6b31b72c25f767b6ac661ef36963ac2c2787ac4 (patch) | |
tree | 53e490c0c3d4b6021a9f3c677d5079027beeb8fe | |
parent | 5d390e127ede8a2fa84f78f6f53fcb551bec5908 (diff) | |
download | sparse-e6b31b72c25f767b6ac661ef36963ac2c2787ac4.tar.gz |
pre-process: add support for builtin macros
Sparse support the expansion of one-symbol-builtin macros like __FILE__.
It also support builtin macros with an argument, like 'defined()'
or '__has_attribute()'.
However, these last one are only expanded inside a pre-processor
conditional expression. This is correct for 'defined()' but macros
like '__has_attribute()' should be expanded in all contexts,
like user defined macros.
So, add support for the general expansion of such macros.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
-rw-r--r-- | pre-process.c | 34 | ||||
-rw-r--r-- | symbol.h | 2 |
2 files changed, 36 insertions, 0 deletions
diff --git a/pre-process.c b/pre-process.c index 059a7c1d..d2e13400 100644 --- a/pre-process.c +++ b/pre-process.c @@ -777,6 +777,9 @@ static int expand(struct token **list, struct symbol *sym) expand_arguments(nargs, args); } + if (sym->expand) + return sym->expand(token, args) ? 0 : 1; + expanding->tainted = 1; last = token->next; @@ -2000,6 +2003,34 @@ static int handle_nondirective(struct stream *stream, struct token **line, struc return 1; } +static void create_arglist(struct symbol *sym, int count) +{ + struct token *token; + struct token **next; + + if (!count) + return; + + token = __alloc_token(0); + token_type(token) = TOKEN_ARG_COUNT; + token->count.normal = count; + sym->arglist = token; + next = &token->next; + + while (count--) { + struct token *id, *uses; + id = __alloc_token(0); + token_type(id) = TOKEN_IDENT; + uses = __alloc_token(0); + token_type(uses) = TOKEN_ARG_COUNT; + uses->count.normal = 1; + + *next = id; + id->next = uses; + next = &uses->next; + } + *next = &eof_token_entry; +} static void init_preprocessor(void) { @@ -2041,6 +2072,7 @@ static void init_preprocessor(void) static struct { const char *name; void (*expand_simple)(struct token *); + bool (*expand)(struct token *, struct arg *args); } dynamic[] = { { "__LINE__", expand_line }, { "__FILE__", expand_file }, @@ -2067,6 +2099,8 @@ static void init_preprocessor(void) struct symbol *sym; sym = create_symbol(stream, dynamic[i].name, SYM_NODE, NS_MACRO); sym->expand_simple = dynamic[i].expand_simple; + if ((sym->expand = dynamic[i].expand) != NULL) + create_arglist(sym, 1); } counter_macro = 0; @@ -114,6 +114,7 @@ struct decl_state { struct pseudo; struct entrypoint; +struct arg; struct symbol_op { enum keyword type; @@ -161,6 +162,7 @@ struct symbol { struct token *arglist; struct scope *used_in; void (*expand_simple)(struct token *); + bool (*expand)(struct token *, struct arg *args); }; struct /* NS_PREPROCESSOR */ { int (*handler)(struct stream *, struct token **, struct token *); |