aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2020-04-09 09:14:01 +0200
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2020-05-21 17:27:45 +0200
commit177f5fe2255e2fd16040c802a7298ec21a29bd80 (patch)
treee4689872972c4217c2caad41c557bdc2a2474f29
parenteff5e6c1a4e6c36614dcfaa0213e2ccf57e844a3 (diff)
downloadsparse-177f5fe2255e2fd16040c802a7298ec21a29bd80.tar.gz
scope: give a scope for labels & gotos
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@gmail.com>
-rw-r--r--parse.c8
-rw-r--r--parse.h1
-rw-r--r--symbol.h4
3 files changed, 12 insertions, 1 deletions
diff --git a/parse.c b/parse.c
index ecc33765..bf45e3b0 100644
--- a/parse.c
+++ b/parse.c
@@ -2488,7 +2488,12 @@ static struct token *parse_goto_statement(struct token *token, struct statement
token = parse_expression(token->next, &stmt->goto_expression);
add_statement(&function_computed_goto_list, stmt);
} else if (token_type(token) == TOKEN_IDENT) {
- stmt->goto_label = label_symbol(token);
+ struct symbol *label = label_symbol(token);
+ stmt->goto_label = label;
+ if (!label->stmt && !label->label_scope) {
+ label->label_scope = label_scope;
+ label->label_pos = stmt->pos;
+ }
token = token->next;
} else {
sparse_error(token->pos, "Expected identifier or goto expression");
@@ -2549,6 +2554,7 @@ static struct token *statement(struct token *token, struct statement **tree)
}
stmt->type = STMT_LABEL;
stmt->label_identifier = s;
+ stmt->label_scope = label_scope;
s->stmt = stmt;
return statement(token, &stmt->label_statement);
}
diff --git a/parse.h b/parse.h
index 0742a2a8..daef2439 100644
--- a/parse.h
+++ b/parse.h
@@ -72,6 +72,7 @@ struct statement {
};
struct /* labeled_struct */ {
struct symbol *label_identifier;
+ struct scope *label_scope;
struct statement *label_statement;
};
struct /* case_struct */ {
diff --git a/symbol.h b/symbol.h
index c297c778..2293d06d 100644
--- a/symbol.h
+++ b/symbol.h
@@ -167,6 +167,10 @@ struct symbol {
int (*handler)(struct stream *, struct token **, struct token *);
int normal;
};
+ struct /* NS_LABEL */ {
+ struct scope *label_scope;
+ struct position label_pos;
+ };
struct /* NS_SYMBOL */ {
unsigned long offset;
int bit_size;