GCC consider these macros as being defined, sparse doesn't. Also sparse uses a sequence of comparisons, one for each of __DATE__, __FILE__, ..., which is not ideal. Fix this by defining and using a table to associate to the corresponding symbol a method doing the expansion. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx> --- ident-list.h | 5 -- pre-process.c | 78 ++++++++++++++++++++++--------- symbol.h | 1 + validation/preprocessor/dynamic.c | 1 - 4 files changed, 58 insertions(+), 27 deletions(-) diff --git a/ident-list.h b/ident-list.h index 2f1fecb48..5394f5877 100644 --- a/ident-list.h +++ b/ident-list.h @@ -61,14 +61,9 @@ IDENT(defined); IDENT(once); __IDENT(pragma_ident, "__pragma__", 0); __IDENT(__VA_ARGS___ident, "__VA_ARGS__", 0); -__IDENT(__LINE___ident, "__LINE__", 0); -__IDENT(__FILE___ident, "__FILE__", 0); -__IDENT(__DATE___ident, "__DATE__", 0); -__IDENT(__TIME___ident, "__TIME__", 0); __IDENT(__func___ident, "__func__", 0); __IDENT(__FUNCTION___ident, "__FUNCTION__", 0); __IDENT(__PRETTY_FUNCTION___ident, "__PRETTY_FUNCTION__", 0); -__IDENT(__COUNTER___ident, "__COUNTER__", 0); /* Sparse commands */ IDENT_RESERVED(__context__); diff --git a/pre-process.c b/pre-process.c index 7d335ab0c..1e4725439 100644 --- a/pre-process.c +++ b/pre-process.c @@ -154,39 +154,60 @@ static void replace_with_defined(struct token *token) token->number = string[defined]; } +static void expand_line(struct token *token) +{ + replace_with_integer(token, token->pos.line); +} + +static void expand_file(struct token *token) +{ + replace_with_string(token, stream_name(token->pos.stream)); +} + +static time_t t = 0; +static void expand_date(struct token *token) +{ + static char buffer[12]; /* __DATE__: 3 + ' ' + 2 + ' ' + 4 + '\0' */ + + if (!t) + time(&t); + strftime(buffer, 12, "%b %e %Y", localtime(&t)); + replace_with_string(token, buffer); +} + +static void expand_time(struct token *token) +{ + static char buffer[9]; /* __TIME__: 2 + ':' + 2 + ':' + 2 + '\0' */ + + if (!t) + time(&t); + strftime(buffer, 9, "%T", localtime(&t)); + replace_with_string(token, buffer); +} + +static void expand_counter(struct token *token) +{ + replace_with_integer(token, counter_macro++); +} + static int expand_one_symbol(struct token **list) { struct token *token = *list; struct symbol *sym; - static char buffer[12]; /* __DATE__: 3 + ' ' + 2 + ' ' + 4 + '\0' */ - static time_t t = 0; if (token->pos.noexpand) return 1; sym = lookup_macro(token->ident); - if (sym) { + if (!sym) + return 1; + if (sym->expander) { + sym->expander(token); + return 1; + } else { sym->used_in = file_scope; return expand(list, sym); } - if (token->ident == &__LINE___ident) { - replace_with_integer(token, token->pos.line); - } else if (token->ident == &__FILE___ident) { - replace_with_string(token, stream_name(token->pos.stream)); - } else if (token->ident == &__DATE___ident) { - if (!t) - time(&t); - strftime(buffer, 12, "%b %e %Y", localtime(&t)); - replace_with_string(token, buffer); - } else if (token->ident == &__TIME___ident) { - if (!t) - time(&t); - strftime(buffer, 9, "%T", localtime(&t)); - replace_with_string(token, buffer); - } else if (token->ident == &__COUNTER___ident) { - replace_with_integer(token, counter_macro++); - } - return 1; } static inline struct token *scan_next(struct token **where) @@ -1891,6 +1912,16 @@ static void init_preprocessor(void) { "if", handle_if }, { "elif", handle_elif }, }; + static struct { + const char *name; + void (*expander)(struct token *); + } dynamic[] = { + { "__LINE__", expand_line }, + { "__FILE__", expand_file }, + { "__DATE__", expand_date }, + { "__TIME__", expand_time }, + { "__COUNTER__", expand_counter }, + }; for (i = 0; i < ARRAY_SIZE(normal); i++) { struct symbol *sym; @@ -1904,6 +1935,11 @@ static void init_preprocessor(void) sym->handler = special[i].handler; sym->normal = 0; } + for (i = 0; i < ARRAY_SIZE(dynamic); i++) { + struct symbol *sym; + sym = create_symbol(stream, dynamic[i].name, SYM_NODE, NS_MACRO); + sym->expander = dynamic[i].expander; + } counter_macro = 0; } diff --git a/symbol.h b/symbol.h index 4edb44041..c1ae4d2b0 100644 --- a/symbol.h +++ b/symbol.h @@ -155,6 +155,7 @@ struct symbol { struct token *expansion; struct token *arglist; struct scope *used_in; + void (*expander)(struct token *); }; struct /* NS_PREPROCESSOR */ { int (*handler)(struct stream *, struct token **, struct token *); diff --git a/validation/preprocessor/dynamic.c b/validation/preprocessor/dynamic.c index 3622be8d1..a829542f8 100644 --- a/validation/preprocessor/dynamic.c +++ b/validation/preprocessor/dynamic.c @@ -17,7 +17,6 @@ counter /* * check-name: dynamic-macros * check-command: sparse -E $file - * check-known-to-fail * * check-output-start -- 2.17.1 -- To unsubscribe from this list: send the line "unsubscribe linux-sparse" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html