glcpp: Additional fixes for not evaluating skipped #if/#elif expressions.
authorCarl Worth <cworth@cworth.org>
Wed, 11 Aug 2010 19:43:44 +0000 (12:43 -0700)
committerCarl Worth <cworth@cworth.org>
Wed, 11 Aug 2010 19:43:44 +0000 (12:43 -0700)
This adds a couple of test cases to expand our coverage of invalid #if and
being skipped, (either by being nested inside an #if/#elif that evaluates to
zero or by being after an #if/#elif that evaluates to non-zero).

src/glsl/glcpp/glcpp-parse.y
src/glsl/glcpp/tests/075-elif-elif-undef.c [new file with mode: 0644]
src/glsl/glcpp/tests/075-elif-elif-undef.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/076-elif-undef-nested.c [new file with mode: 0644]
src/glsl/glcpp/tests/076-elif-undef-nested.c.expected [new file with mode: 0644]

index a4383574506a8bf88ce294854b1918765265292e..643c449d0e17e808de9d388a75445d5b8ca96e5d 100644 (file)
@@ -223,14 +223,22 @@ control_line:
                talloc_free ($2);
        }
 |      HASH_IF conditional_tokens NEWLINE {
-               /* If we're skipping to the next #elif/#else case or to #endif,
-                * don't bother expanding or parsing the expression.
-                */
-               if (parser->skip_stack != NULL && parser->skip_stack->type != SKIP_NO_SKIP) {
+               /* Be careful to only evaluate the 'if' expression if
+                * we are not skipping. When we are skipping, we
+                * simply push a new 0-valued 'if' onto the skip
+                * stack.
+                *
+                * This avoids generating diagnostics for invalid
+                * expressions that are being skipped. */
+               if (parser->skip_stack == NULL ||
+                   parser->skip_stack->type == SKIP_NO_SKIP)
+               {
+                       _glcpp_parser_expand_if (parser, IF_EXPANDED, $2);
+               }       
+               else
+               {
                        _glcpp_parser_skip_stack_push_if (parser, & @1, 0);
                        parser->skip_stack->type = SKIP_TO_ENDIF;
-               } else {
-                       _glcpp_parser_expand_if (parser, IF_EXPANDED, $2);
                }
        }
 |      HASH_IFDEF IDENTIFIER junk NEWLINE {
@@ -244,24 +252,38 @@ control_line:
                _glcpp_parser_skip_stack_push_if (parser, & @1, macro == NULL);
        }
 |      HASH_ELIF conditional_tokens NEWLINE {
-               /* If we just finished a non-skipped #if/#ifdef/#ifndef block,
-                * don't bother expanding or parsing the expression.
-                */
-               if (parser->skip_stack != NULL && parser->skip_stack->type == SKIP_NO_SKIP)
-                       parser->skip_stack->type = SKIP_TO_ENDIF;
-               else
+               /* Be careful to only evaluate the 'elif' expression
+                * if we are not skipping. When we are skipping, we
+                * simply change to a 0-valued 'elif' on the skip
+                * stack.
+                *
+                * This avoids generating diagnostics for invalid
+                * expressions that are being skipped. */
+               if (parser->skip_stack &&
+                   parser->skip_stack->type == SKIP_TO_ELSE)
+               {
                        _glcpp_parser_expand_if (parser, ELIF_EXPANDED, $2);
+               }
+               else
+               {
+                       _glcpp_parser_skip_stack_change_if (parser, & @1,
+                                                           "elif", 0);
+               }
        }
 |      HASH_ELIF NEWLINE {
-               /* #elif without an expression results in a warning if the
-                * condition doesn't matter (we just handled #if 1 or such)
-                * but an error otherwise. */
-               if (parser->skip_stack != NULL && parser->skip_stack->type == SKIP_NO_SKIP) {
-                       parser->skip_stack->type = SKIP_TO_ENDIF;
-                       glcpp_warning(& @1, parser, "ignoring illegal #elif without expression");
-               } else {
+               /* #elif without an expression is an error unless we
+                * are skipping. */
+               if (parser->skip_stack &&
+                   parser->skip_stack->type == SKIP_TO_ELSE)
+               {
                        glcpp_error(& @1, parser, "#elif needs an expression");
                }
+               else
+               {
+                       _glcpp_parser_skip_stack_change_if (parser, & @1,
+                                                           "elif", 0);
+                       glcpp_warning(& @1, parser, "ignoring illegal #elif without expression");
+               }
        }
 |      HASH_ELSE NEWLINE {
                _glcpp_parser_skip_stack_change_if (parser, & @1, "else", 1);
diff --git a/src/glsl/glcpp/tests/075-elif-elif-undef.c b/src/glsl/glcpp/tests/075-elif-elif-undef.c
new file mode 100644 (file)
index 0000000..264bc4f
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef UNDEF
+#elif UNDEF < 0
+#elif UNDEF == 3
+#endif
diff --git a/src/glsl/glcpp/tests/075-elif-elif-undef.c.expected b/src/glsl/glcpp/tests/075-elif-elif-undef.c.expected
new file mode 100644 (file)
index 0000000..3f2ff2d
--- /dev/null
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/src/glsl/glcpp/tests/076-elif-undef-nested.c b/src/glsl/glcpp/tests/076-elif-undef-nested.c
new file mode 100644 (file)
index 0000000..ebd550e
--- /dev/null
@@ -0,0 +1,5 @@
+#ifdef UNDEF
+#if UNDEF == 4
+#elif UNDEF == 5
+#endif
+#endif
diff --git a/src/glsl/glcpp/tests/076-elif-undef-nested.c.expected b/src/glsl/glcpp/tests/076-elif-undef-nested.c.expected
new file mode 100644 (file)
index 0000000..6fb66a5
--- /dev/null
@@ -0,0 +1,6 @@
+
+
+
+
+
+