Browse Source

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 <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
Erik Faye-Lund 11 years ago
parent
commit
eb212c5a30

+ 22
- 1
src/glsl/glcpp/glcpp-parse.y View 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;
}

+ 1
- 0
src/glsl/glcpp/glcpp.h View 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;

+ 6
- 0
src/glsl/glcpp/tests/118-multiple-else.c View File

@@ -0,0 +1,6 @@
#if 0
#else
int foo;
#else
int bar;
#endif

+ 8
- 0
src/glsl/glcpp/tests/118-multiple-else.c.expected View File

@@ -0,0 +1,8 @@
0:4(1): preprocessor error: multiple #else


int foo;

int bar;



+ 6
- 0
src/glsl/glcpp/tests/119-elif-after-else.c View File

@@ -0,0 +1,6 @@
#if 0
#else
int foo;
#elif 0
int bar;
#endif

+ 8
- 0
src/glsl/glcpp/tests/119-elif-after-else.c.expected View File

@@ -0,0 +1,8 @@
0:4(1): preprocessor error: #elif after #else


int foo;

int bar;



Loading…
Cancel
Save