From 54f63a0cdc9c2b52e03ceb9939313365ee83914b Mon Sep 17 00:00:00 2001 From: Kugel Fuhr <98353208+kugelfuhr@users.noreply.github.com> Date: Thu, 19 Jun 2025 09:11:30 +0200 Subject: [PATCH 1/2] Fix the behavior of variable symbols in regard to cheap locals. Previously every assignment to a variable symbol opened the same scope for cheap locals. So when redefining a variable symbol, an old cheap local scope was reopened which was unexpected and confusing. The change fixes this so that only the first definition of a variable symbol opens a new scope for cheap locals, but redefinitions of the same symbol do not. --- src/ca65/symentry.c | 9 +++++++-- test/asm/err/bug505.s | 28 ++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 test/asm/err/bug505.s diff --git a/src/ca65/symentry.c b/src/ca65/symentry.c index 1048bfbc2..c57fcff2a 100644 --- a/src/ca65/symentry.c +++ b/src/ca65/symentry.c @@ -211,6 +211,8 @@ static void SymReplaceExprRefs (SymEntry* S) void SymDef (SymEntry* S, ExprNode* Expr, unsigned char AddrSize, unsigned Flags) /* Define a new symbol */ { + int Redef = 0; /* Flag for symbol redefinition */ + if (S->Flags & SF_IMPORT) { /* Defined symbol is marked as imported external symbol */ Error ("Symbol '%m%p' is already an import", GetSymName (S)); @@ -238,6 +240,7 @@ void SymDef (SymEntry* S, ExprNode* Expr, unsigned char AddrSize, unsigned Flags */ FreeExpr (S->Expr); S->Expr = 0; + Redef = 1; } } @@ -291,8 +294,10 @@ void SymDef (SymEntry* S, ExprNode* Expr, unsigned char AddrSize, unsigned Flags } } - /* If this is not a local symbol, remember it as the last global one */ - if ((S->Flags & SF_LOCAL) == 0) { + /* If this is not a local symbol and not a redefinition for a variable + ** symbol, remember it as the last global one. + */ + if ((S->Flags & SF_LOCAL) == 0 && !Redef) { SymLast = S; } } diff --git a/test/asm/err/bug505.s b/test/asm/err/bug505.s new file mode 100644 index 000000000..3125f3966 --- /dev/null +++ b/test/asm/err/bug505.s @@ -0,0 +1,28 @@ +; Test for #525 taken from the issue +; Redefining a variable symbol "reopens" the old name space for cheap locals +; Behavior should be: First definition of a variable symbol opens a new +; scope for cheap locals, redefinitions of the same symbols do not. + +;this starts a new scope for cheap local lables +SomeSymbol .set 4 + + jmp @CheapLocal1 + +@CheapLocal0: + + .byte $8b + +CheapLocalScopeBreaker0: + +CheapLocalScopeBreaker1: + +CheapLocalScopeBreaker2: + +CheapLocalScopeBreaker3: + +;this continues the same cheap scope as before, regardless of the many global labels in between +SomeSymbol .set 5 + +@CheapLocal1: + + lda @CheapLocal0 From 758bdaa4aded54aa27af5ba40af239e0a60d7c58 Mon Sep 17 00:00:00 2001 From: Kugel Fuhr <98353208+kugelfuhr@users.noreply.github.com> Date: Thu, 19 Jun 2025 17:59:30 +0200 Subject: [PATCH 2/2] Fixed a typo in the test source. --- test/asm/err/bug505.s | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/asm/err/bug505.s b/test/asm/err/bug505.s index 3125f3966..8cb0e2f18 100644 --- a/test/asm/err/bug505.s +++ b/test/asm/err/bug505.s @@ -1,6 +1,6 @@ -; Test for #525 taken from the issue +; Test for #505 taken from the issue ; Redefining a variable symbol "reopens" the old name space for cheap locals -; Behavior should be: First definition of a variable symbol opens a new +; Behavior should be: First definition of a variable symbol opens a new ; scope for cheap locals, redefinitions of the same symbols do not. ;this starts a new scope for cheap local lables