glcpp: error on multiple #else/#elif directives
authorErik Faye-Lund <kusmabite@gmail.com>
Tue, 17 Dec 2013 15:37:33 +0000 (16:37 +0100)
committerCarl Worth <cworth@cworth.org>
Thu, 2 Jan 2014 22:22:58 +0000 (14:22 -0800)
The preprocessor currently accepts multiple else/elif-groups
per if-section. The GLSL-preprocessor is defined by the C++
specification, which defines the following parse-rule:

if-section:
if-group elif-groups(opt) else-group(opt) endif-line

This clearly only allows a single else-group, that has to come
after any elif-groups.

So let's modify the code to follow the specification. Add test
to prevent regressions.

Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Carl Worth <cworth@cworth.org>
Cc: 10.0 <mesa-stable@lists.freedesktop.org>
src/glsl/glcpp/glcpp-parse.y
src/glsl/glcpp/glcpp.h
src/glsl/glcpp/tests/118-multiple-else.c [new file with mode: 0644]
src/glsl/glcpp/tests/118-multiple-else.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/119-elif-after-else.c [new file with mode: 0644]
src/glsl/glcpp/tests/119-elif-after-else.c.expected [new file with mode: 0644]

index 5474577ebe4a2d2b2627339aa8d95290ce5d9e0b..ef084b6392a7a1e6abdad02fe1b75fc71f983466 100644 (file)
@@ -310,6 +310,11 @@ control_line:
                        _glcpp_parser_expand_and_lex_from (parser,
                                                           ELIF_EXPANDED, $2);
                }
+               else if (parser->skip_stack &&
+                   parser->skip_stack->has_else)
+               {
+                       glcpp_error(& @1, parser, "#elif after #else");
+               }
                else
                {
                        _glcpp_parser_skip_stack_change_if (parser, & @1,
@@ -324,6 +329,11 @@ control_line:
                {
                        glcpp_error(& @1, parser, "#elif with no expression");
                }
+               else if (parser->skip_stack &&
+                   parser->skip_stack->has_else)
+               {
+                       glcpp_error(& @1, parser, "#elif after #else");
+               }
                else
                {
                        _glcpp_parser_skip_stack_change_if (parser, & @1,
@@ -332,7 +342,17 @@ control_line:
                }
        }
 |      HASH_ELSE {
-               _glcpp_parser_skip_stack_change_if (parser, & @1, "else", 1);
+               if (parser->skip_stack &&
+                   parser->skip_stack->has_else)
+               {
+                       glcpp_error(& @1, parser, "multiple #else");
+               }
+               else
+               {
+                       _glcpp_parser_skip_stack_change_if (parser, & @1, "else", 1);
+                       if (parser->skip_stack)
+                               parser->skip_stack->has_else = true;
+               }
        } NEWLINE
 |      HASH_ENDIF {
                _glcpp_parser_skip_stack_pop (parser, & @1);
@@ -2025,6 +2045,7 @@ _glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, YYLTYPE *loc,
                node->type = SKIP_TO_ENDIF;
        }
 
+       node->has_else = false;
        node->next = parser->skip_stack;
        parser->skip_stack = node;
 }
index e95ab8497d8185019944b67b19f2f0902c8f4d5d..85f3fdcd2cd8bdeaa8c014cbd85ee063d0340a5d 100644 (file)
@@ -153,6 +153,7 @@ typedef enum skip_type {
 
 typedef struct skip_node {
        skip_type_t type;
+       bool has_else;
        YYLTYPE loc; /* location of the initial #if/#elif/... */
        struct skip_node *next;
 } skip_node_t;
diff --git a/src/glsl/glcpp/tests/118-multiple-else.c b/src/glsl/glcpp/tests/118-multiple-else.c
new file mode 100644 (file)
index 0000000..62ad49c
--- /dev/null
@@ -0,0 +1,6 @@
+#if 0
+#else
+int foo;
+#else
+int bar;
+#endif
diff --git a/src/glsl/glcpp/tests/118-multiple-else.c.expected b/src/glsl/glcpp/tests/118-multiple-else.c.expected
new file mode 100644 (file)
index 0000000..eaec481
--- /dev/null
@@ -0,0 +1,8 @@
+0:4(1): preprocessor error: multiple #else
+
+
+int foo;
+
+int bar;
+
+
diff --git a/src/glsl/glcpp/tests/119-elif-after-else.c b/src/glsl/glcpp/tests/119-elif-after-else.c
new file mode 100644 (file)
index 0000000..9b9e923
--- /dev/null
@@ -0,0 +1,6 @@
+#if 0
+#else
+int foo;
+#elif 0
+int bar;
+#endif
diff --git a/src/glsl/glcpp/tests/119-elif-after-else.c.expected b/src/glsl/glcpp/tests/119-elif-after-else.c.expected
new file mode 100644 (file)
index 0000000..33f0513
--- /dev/null
@@ -0,0 +1,8 @@
+0:4(1): preprocessor error: #elif after #else
+
+
+int foo;
+
+int bar;
+
+