One way of detecting gotos inside an statement expression is to use a new kind of scope for the gotos & labels. Since gotos don't need to have their label predeclared, nothing can be checked at parsing time but later it can be checked that a goto doesn't jump inside one of the label scope created by statement expressions. So, add additional scope information to gotos and labels to allow such check to be done. Note: the label's symbols are still created in the function scope since they belong to a single namespace. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx> --- parse.c | 2 ++ parse.h | 1 + symbol.h | 3 +++ 3 files changed, 6 insertions(+) diff --git a/parse.c b/parse.c index 1a2c7af22ff4..244991c1c4f5 100644 --- a/parse.c +++ b/parse.c @@ -2481,6 +2481,7 @@ static struct token *parse_goto_statement(struct token *token, struct statement add_statement(&function_computed_goto_list, stmt); } else if (token_type(token) == TOKEN_IDENT) { stmt->goto_label = label_symbol(token); + stmt->goto_scope = label_scope; token = token->next; } else { sparse_error(token->pos, "Expected identifier or goto expression"); @@ -2533,6 +2534,7 @@ static struct token *statement(struct token *token, struct statement **tree) if (match_op(token->next, ':')) { struct symbol *s = label_symbol(token); + s->label_scope = label_scope; token = skip_attributes(token->next->next); if (s->stmt) { sparse_error(stmt->pos, "label '%s' redefined", show_ident(s->ident)); diff --git a/parse.h b/parse.h index 0742a2a87e9d..5995eb56849f 100644 --- a/parse.h +++ b/parse.h @@ -99,6 +99,7 @@ struct statement { }; struct /* goto_struct */ { struct symbol *goto_label; + struct scope *goto_scope; /* computed gotos have these: */ struct expression *goto_expression; diff --git a/symbol.h b/symbol.h index de13d60b8b75..f9d7bcaa997f 100644 --- a/symbol.h +++ b/symbol.h @@ -167,6 +167,9 @@ struct symbol { int (*handler)(struct stream *, struct token **, struct token *); int normal; }; + struct /* NS_LABEL */ { + struct scope *label_scope; + }; struct /* NS_SYMBOL */ { unsigned long offset; int bit_size; -- 2.26.0