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>tags/mesa-10.1-rc1
@@ -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; | |||
} |
@@ -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; |
@@ -0,0 +1,6 @@ | |||
#if 0 | |||
#else | |||
int foo; | |||
#else | |||
int bar; | |||
#endif |
@@ -0,0 +1,8 @@ | |||
0:4(1): preprocessor error: multiple #else | |||
int foo; | |||
int bar; | |||
@@ -0,0 +1,6 @@ | |||
#if 0 | |||
#else | |||
int foo; | |||
#elif 0 | |||
int bar; | |||
#endif |
@@ -0,0 +1,8 @@ | |||
0:4(1): preprocessor error: #elif after #else | |||
int foo; | |||
int bar; | |||