aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2020-04-01 15:45:33 +0200
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2020-05-21 17:27:45 +0200
commitdb0a795b145501e456cac5180be03ef697810845 (patch)
tree9b6d3d16c6322970b4dbea9260cde61ec97478f6
parentdbaf79f0e3abc46002fbf918240e1c09c6e4697a (diff)
downloadsparse-db0a795b145501e456cac5180be03ef697810845.tar.gz
scope: let labels have their own scope
It's invalid to jump inside a statement expression. So, concerning labels & gotos, a statement expression is like a kind of scope. So, in preparation for the detection of such jumps, create these new scopes and open/close them when entering/leaving statement expressions. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
-rw-r--r--expression.c2
-rw-r--r--scope.c17
-rw-r--r--scope.h4
3 files changed, 21 insertions, 2 deletions
diff --git a/expression.c b/expression.c
index ffb3c2dc..f8a8f03e 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 cc54f1e1..75ee19cf 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 = NULL, // expr-stmt labels
*function_scope = &builtin_scope, // labels, arguments etc
*file_scope = &builtin_scope, // static
*global_scope = &builtin_scope; // externally visible
@@ -91,8 +92,9 @@ void start_block_scope(void)
void start_function_scope(void)
{
- start_scope(&function_scope);
start_scope(&block_scope);
+ start_scope(&label_scope);
+ function_scope = label_scope;
}
static void remove_symbol_scope(struct symbol *sym)
@@ -137,7 +139,18 @@ void end_block_scope(void)
void end_function_scope(void)
{
end_scope(&block_scope);
- end_scope(&function_scope);
+ end_label_scope();
+ function_scope = label_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 83741459..ddcb90bd 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 *);