Fix #if-skipping to *really* skip the skipped group.
authorCarl Worth <cworth@cworth.org>
Tue, 1 Jun 2010 18:20:18 +0000 (11:20 -0700)
committerCarl Worth <cworth@cworth.org>
Tue, 1 Jun 2010 18:23:08 +0000 (11:23 -0700)
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.

glcpp-lex.l
glcpp-parse.y
glcpp.h
tests/062-if-0-skips-garbage.c [new file with mode: 0644]

index 52269c6b306f9e3620111bb2515cf08731420ff9..a51d9e185fc6f7d834ae6f5d4bb5d610829efb98 100644 (file)
@@ -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;
 }
 
index f4c834e038fd5da2c6ed1f46b110975d3619032c..dd8e133f5506ff9ec38a3105c5d11b26dcbdee36 100644 (file)
@@ -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;
diff --git a/glcpp.h b/glcpp.h
index 5c8c304a9ca737073fa9f87caad45ae564448b5b..41fc2043d139fc7b0c303bdef3932c2f5e3db90b 100644 (file)
--- a/glcpp.h
+++ b/glcpp.h
@@ -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 (file)
index 0000000..d9e439b
--- /dev/null
@@ -0,0 +1,5 @@
+#define foo(a,b)
+#if 0
+foo(bar)
+foo(
+#endif