summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Worth <cworth@cworth.org>2010-06-01 11:20:18 -0700
committerCarl Worth <cworth@cworth.org>2010-06-01 11:23:08 -0700
commita771a40e2257657cbdae0eb97a7bb8733db76b91 (patch)
tree363998c5e734aea3fc40d4fff94bcf5d2646479b
parent96d3994881832201db7edd8a0a6f4b34655649d3 (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.l48
-rw-r--r--glcpp-parse.y15
-rw-r--r--glcpp.h1
-rw-r--r--tests/062-if-0-skips-garbage.c5
4 files changed, 44 insertions, 25 deletions
diff --git a/glcpp-lex.l b/glcpp-lex.l
index 52269c6..a51d9e1 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 f4c834e..dd8e133 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;
diff --git a/glcpp.h b/glcpp.h
index 5c8c304..41fc204 100644
--- 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
index 0000000..d9e439b
--- /dev/null
+++ b/tests/062-if-0-skips-garbage.c
@@ -0,0 +1,5 @@
+#define foo(a,b)
+#if 0
+foo(bar)
+foo(
+#endif