From: Erik Faye-Lund Date: Tue, 17 Dec 2013 15:37:33 +0000 (+0100) Subject: glcpp: error on multiple #else/#elif directives X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=eb212c5a302f0122a13b36dfdf07e91f951ae2e7;p=mesa.git glcpp: error on multiple #else/#elif directives 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 Reviewed-by: Kenneth Graunke Reviewed-by: Carl Worth Cc: 10.0 --- diff --git a/src/glsl/glcpp/glcpp-parse.y b/src/glsl/glcpp/glcpp-parse.y index 5474577ebe4..ef084b6392a 100644 --- a/src/glsl/glcpp/glcpp-parse.y +++ b/src/glsl/glcpp/glcpp-parse.y @@ -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; } diff --git a/src/glsl/glcpp/glcpp.h b/src/glsl/glcpp/glcpp.h index e95ab8497d8..85f3fdcd2cd 100644 --- a/src/glsl/glcpp/glcpp.h +++ b/src/glsl/glcpp/glcpp.h @@ -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 index 00000000000..62ad49cf7bb --- /dev/null +++ b/src/glsl/glcpp/tests/118-multiple-else.c @@ -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 index 00000000000..eaec4815076 --- /dev/null +++ b/src/glsl/glcpp/tests/118-multiple-else.c.expected @@ -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 index 00000000000..9b9e9233bcb --- /dev/null +++ b/src/glsl/glcpp/tests/119-elif-after-else.c @@ -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 index 00000000000..33f05136158 --- /dev/null +++ b/src/glsl/glcpp/tests/119-elif-after-else.c.expected @@ -0,0 +1,8 @@ +0:4(1): preprocessor error: #elif after #else + + +int foo; + +int bar; + +