diff options
author | Carl Worth <cworth@cworth.org> | 2010-06-01 11:20:18 -0700 |
---|---|---|
committer | Carl Worth <cworth@cworth.org> | 2010-06-01 11:23:08 -0700 |
commit | a771a40e2257657cbdae0eb97a7bb8733db76b91 (patch) | |
tree | 363998c5e734aea3fc40d4fff94bcf5d2646479b | |
parent | 96d3994881832201db7edd8a0a6f4b34655649d3 (diff) |
Fix #if-skipping to *really* skip the skipped group.
Previously we were avoiding printing within a skipped group, but we
were still evluating directives such as #define and #undef and still
emitting diagnostics for things such as macro calls with the wrong
number of arguments.
Add a test for this and fix it with a high-priority rule in the lexer
that consumes the skipped content.
-rw-r--r-- | glcpp-lex.l | 48 | ||||
-rw-r--r-- | glcpp-parse.y | 15 | ||||
-rw-r--r-- | glcpp.h | 1 | ||||
-rw-r--r-- | tests/062-if-0-skips-garbage.c | 5 |
4 files changed, 44 insertions, 25 deletions
diff --git a/glcpp-lex.l b/glcpp-lex.l index 52269c6b30..a51d9e185f 100644 --- a/glcpp-lex.l +++ b/glcpp-lex.l @@ -47,39 +47,58 @@ HEXADECIMAL_INTEGER 0[xX][0-9a-fA-F]+[uU]? %% -{HASH}define{HSPACE}+/{IDENTIFIER}"(" { +{HASH}if/.*\n { + yyextra->lexing_if = 1; yyextra->space_tokens = 0; - return HASH_DEFINE_FUNC; + return HASH_IF; } -{HASH}define { +{HASH}elif/.*\n { + yyextra->lexing_if = 1; yyextra->space_tokens = 0; - return HASH_DEFINE_OBJ; + return HASH_ELIF; } -{HASH}undef { +{HASH}else/.*\n { yyextra->space_tokens = 0; - return HASH_UNDEF; + return HASH_ELSE; } -{HASH}if { +{HASH}endif/.*\n { yyextra->space_tokens = 0; - return HASH_IF; + return HASH_ENDIF; } -{HASH}elif { + /* When skipping (due to an #if 0 or similar) consume anything + * up to a newline. We do this less priroty than any + * #if-related directive (#if, #elif, #else, #endif), but with + * more priority than any other directive or token to avoid + * any side-effects from skipped content. + * + * We use the lexing_if flag to avoid skipping any part of an + * if conditional expression. */ +[^\n]+/\n { + if (yyextra->lexing_if || + yyextra->skip_stack == NULL || + yyextra->skip_stack->type == SKIP_NO_SKIP) + { + REJECT; + } +} + +{HASH}define{HSPACE}+/{IDENTIFIER}"(" { yyextra->space_tokens = 0; - return HASH_ELIF; + return HASH_DEFINE_FUNC; } -{HASH}else { +{HASH}define { yyextra->space_tokens = 0; - return HASH_ELSE; + return HASH_DEFINE_OBJ; } -{HASH}endif { +{HASH}undef { yyextra->space_tokens = 0; - return HASH_ENDIF; + return HASH_UNDEF; } {HASH} { @@ -163,6 +182,7 @@ HEXADECIMAL_INTEGER 0[xX][0-9a-fA-F]+[uU]? } \n { + yyextra->lexing_if = 0; return NEWLINE; } diff --git a/glcpp-parse.y b/glcpp-parse.y index f4c834e038..dd8e133f55 100644 --- a/glcpp-parse.y +++ b/glcpp-parse.y @@ -159,19 +159,11 @@ input: line: control_line { - if (parser->skip_stack == NULL || - parser->skip_stack->type == SKIP_NO_SKIP) - { - printf ("\n"); - } + printf ("\n"); } | text_line { - if (parser->skip_stack == NULL || - parser->skip_stack->type == SKIP_NO_SKIP) - { - _glcpp_parser_print_expanded_token_list (parser, $1); - printf ("\n"); - } + _glcpp_parser_print_expanded_token_list (parser, $1); + printf ("\n"); talloc_free ($1); } | expanded_line @@ -889,6 +881,7 @@ glcpp_parser_create (void) parser->defines = hash_table_ctor (32, hash_table_string_hash, hash_table_string_compare); parser->active = _string_list_create (parser); + parser->lexing_if = 0; parser->space_tokens = 1; parser->newline_as_space = 0; parser->in_control_line = 0; @@ -127,6 +127,7 @@ struct glcpp_parser { yyscan_t scanner; struct hash_table *defines; string_list_t *active; + int lexing_if; int space_tokens; int newline_as_space; int in_control_line; diff --git a/tests/062-if-0-skips-garbage.c b/tests/062-if-0-skips-garbage.c new file mode 100644 index 0000000000..d9e439bb89 --- /dev/null +++ b/tests/062-if-0-skips-garbage.c @@ -0,0 +1,5 @@ +#define foo(a,b) +#if 0 +foo(bar) +foo( +#endif |