aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2019-09-30 16:27:17 +0200
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2020-06-18 21:26:31 +0200
commite6b31b72c25f767b6ac661ef36963ac2c2787ac4 (patch)
tree53e490c0c3d4b6021a9f3c677d5079027beeb8fe
parent5d390e127ede8a2fa84f78f6f53fcb551bec5908 (diff)
downloadsparse-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.c34
-rw-r--r--symbol.h2
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;
diff --git a/symbol.h b/symbol.h
index 6b483101..e256322e 100644
--- a/symbol.h
+++ b/symbol.h
@@ -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 *);