Re: [PATCH 15/17] scope: give a scope for labels & gotos

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Apr 14, 2020 at 12:49 AM Luc Van Oostenryck
<luc.vanoostenryck@xxxxxxxxx> wrote:
>
> The problem is that now normal labels use the new label_scope
> but the ones declared with __label__ use block_scope and these
> 2 scopes are kinda in a different namespace of scope.

Oh, I forgot about the special __label__ thing that actually declares labels.

That one has an interesting behavior, in that the _lifetime_ of the
symbol is the block scope, but the *use* of the symbol must remain in
label scope.

The most obvious fix is probably something like the appended: make the
'sym->scope' remain the lifetime scope, but then attach a "must be
used in this scope' thing to any NS_LABEL case.

That fairly clearly separates the two issues.

Again, not actually tested outside of the obvious trivial case.

              Linus
 parse.c  | 16 +++++++++++-----
 scope.c  |  1 +
 symbol.h |  3 +++
 3 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/parse.c b/parse.c
index 8e238f59..b6109516 100644
--- a/parse.c
+++ b/parse.c
@@ -728,6 +728,7 @@ struct symbol *label_symbol(struct token *token)
 	if (!sym) {
 		sym = alloc_symbol(token->pos, SYM_LABEL);
 		bind_symbol(sym, token->ident, NS_LABEL);
+		sym->declared_scope = label_scope;
 		fn_local_symbol(sym);
 	}
 	return sym;
@@ -2541,13 +2542,14 @@ static struct token *statement(struct token *token, struct statement **tree)
 			}
 			/*
 			 * If the scope of the label symbol is different
-			 * from the current label scope, that means that
-			 * it must have been used at an outer scope.
+			 * from the declared label scope, that means that
+			 * it must have been used or declared at an outer
+			 * scope.
 			 *
 			 * That's not ok.
 			 */
-			if (s->scope != label_scope) {
-				sparse_error(stmt->pos, "label '%s' used outside label expression", show_ident(s->ident));
+			if (s->scope != s->declared_scope) {
+				sparse_error(stmt->pos, "label '%s' used outside statement expression", show_ident(s->ident));
 				sparse_error(s->pos, "invalid use here");
 			}
 			stmt->type = STMT_LABEL;
@@ -2575,9 +2577,13 @@ static struct token *label_statement(struct token *token)
 {
 	while (token_type(token) == TOKEN_IDENT) {
 		struct symbol *sym = alloc_symbol(token->pos, SYM_LABEL);
-		/* it's block-scope, but we want label namespace */
+
+		/* it's lifetile is block-scope, but we want label namespace */
 		bind_symbol(sym, token->ident, NS_SYMBOL);
 		sym->namespace = NS_LABEL;
+
+		/* But we must define it in this label scope */
+		sym->declared_scope = label_scope;
 		fn_local_symbol(sym);
 		token = token->next;
 		if (!match_op(token, ','))
diff --git a/scope.c b/scope.c
index 4b0f7947..11792ec4 100644
--- a/scope.c
+++ b/scope.c
@@ -171,6 +171,7 @@ void end_label_scope(void)
 
 		/* Re-bind the symbol to the parent scope, we'll try again */
 		bind_scope(sym, label_scope);
+		sym->declared_scope = label_scope;
 	} END_FOR_EACH_PTR(sym);
 
 	end_scope(&block_scope);
diff --git a/symbol.h b/symbol.h
index 18476582..08e35438 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 *declared_scope;
+		};
 		struct /* NS_SYMBOL */ {
 			unsigned long	offset;
 			int		bit_size;

[Index of Archives]     [Newbies FAQ]     [LKML]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Trinity Fuzzer Tool]

  Powered by Linux