One way of detecting gotos inside an statement expression is to use a new kind of scope for the gotos & labels. So create this new scope and open/close them when entering/leaving statement expressions. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx> --- expression.c | 2 ++ scope.c | 14 ++++++++++++++ scope.h | 4 ++++ 3 files changed, 20 insertions(+) diff --git a/expression.c b/expression.c index 78e577cf10a1..08650724a988 100644 --- a/expression.c +++ b/expression.c @@ -71,7 +71,9 @@ struct token *parens_expression(struct token *token, struct expression **expr, c struct statement *stmt = alloc_statement(token->pos, STMT_COMPOUND); *expr = e; e->statement = stmt; + start_label_scope(); token = compound_statement(token->next, stmt); + end_label_scope(); token = expect(token, '}', "at end of statement expression"); } else token = parse_expression(token, expr); diff --git a/scope.c b/scope.c index be042a45357d..24c8a7a484f7 100644 --- a/scope.c +++ b/scope.c @@ -36,6 +36,7 @@ static struct scope builtin_scope = { .next = &builtin_scope }; struct scope *block_scope = &builtin_scope, // regular automatic variables etc + *label_scope = &builtin_scope, // expr-stmt labels *function_scope = &builtin_scope, // labels, arguments etc *file_scope = &builtin_scope, // static *global_scope = &builtin_scope; // externally visible @@ -81,6 +82,7 @@ void start_file_scope(void) /* top-level stuff defaults to file scope, "extern" etc will choose global scope */ function_scope = scope; + label_scope = scope; block_scope = scope; } @@ -93,6 +95,7 @@ void start_function_scope(void) { start_scope(&block_scope); function_scope = block_scope; + label_scope = function_scope; } static void remove_symbol_scope(struct symbol *sym) @@ -138,6 +141,17 @@ void end_function_scope(void) { end_scope(&block_scope); function_scope = block_scope; + label_scope = function_scope; +} + +void start_label_scope(void) +{ + start_scope(&label_scope); +} + +void end_label_scope(void) +{ + end_scope(&label_scope); } int is_outer_scope(struct scope *scope) diff --git a/scope.h b/scope.h index 83741459eb6a..ddcb90bd146b 100644 --- a/scope.h +++ b/scope.h @@ -34,6 +34,7 @@ struct scope { extern struct scope *block_scope, + *label_scope, *function_scope, *file_scope, *global_scope; @@ -53,6 +54,9 @@ extern void end_block_scope(void); extern void start_function_scope(void); extern void end_function_scope(void); +extern void start_label_scope(void); +extern void end_label_scope(void); + extern void set_current_scope(struct symbol *); extern void bind_scope(struct symbol *, struct scope *); extern void rebind_scope(struct symbol *, struct scope *); -- 2.26.0