From 38511843e5172e93204480dbc3f5ebe1c7a6c774 Mon Sep 17 00:00:00 2001 From: acqn Date: Mon, 3 Jan 2022 23:50:48 +0800 Subject: [PATCH 1/3] Fixed crash with labels in non-function/block scopes. --- src/cc65/declare.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cc65/declare.c b/src/cc65/declare.c index c1346e872..8af67524f 100644 --- a/src/cc65/declare.c +++ b/src/cc65/declare.c @@ -1485,7 +1485,7 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers, ** long as it has no qualifiers. */ D->Flags |= DS_DEF_TYPE; - D->Type[0].C = T_QUAL_NONE; + D->Type[0].C = T_INT; D->Type[1].C = T_END; break; } From 6beb090193ee932ee67bed553f54d721c48c276d Mon Sep 17 00:00:00 2001 From: acqn Date: Mon, 3 Jan 2022 23:54:14 +0800 Subject: [PATCH 2/3] Fixed anonymous bit-fields declared with typedef'ed type names. --- src/cc65/declare.c | 2 +- src/cc65/symtab.c | 95 +++++++++++++++++++++++++++++++++++++--------- src/cc65/symtab.h | 23 ++++++++++- 3 files changed, 100 insertions(+), 20 deletions(-) diff --git a/src/cc65/declare.c b/src/cc65/declare.c index 8af67524f..fa4c52818 100644 --- a/src/cc65/declare.c +++ b/src/cc65/declare.c @@ -1462,7 +1462,7 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers, case TOK_IDENT: /* This could be a label */ - if (NextTok.Tok != TOK_COLON) { + if (NextTok.Tok != TOK_COLON || GetLexicalLevel () == LEX_LEVEL_STRUCT) { Entry = FindSym (CurTok.Ident); if (Entry && SymIsTypeDef (Entry)) { /* It's a typedef */ diff --git a/src/cc65/symtab.c b/src/cc65/symtab.c index 3de0bb460..c1c5c4696 100644 --- a/src/cc65/symtab.c +++ b/src/cc65/symtab.c @@ -88,7 +88,8 @@ SymTable EmptySymTab = { #define SYMTAB_SIZE_LABEL 7U /* The current and root symbol tables */ -static unsigned LexicalLevel = 0; /* For safety checks */ +static unsigned LexLevelDepth = 0; /* For safety checks */ +static LexicalLevel* CurrentLex = 0; static SymTable* SymTab0 = 0; static SymTable* SymTab = 0; static SymTable* TagTab0 = 0; @@ -213,10 +214,46 @@ static void CheckSymTable (SymTable* Tab) +unsigned GetLexicalLevelDepth (void) +/* Return the current lexical level depth */ +{ + return LexLevelDepth; +} + + + unsigned GetLexicalLevel (void) /* Return the current lexical level */ { - return LexicalLevel; + if (CurrentLex != 0) { + return CurrentLex->CurrentLevel; + } + return LEX_LEVEL_NONE; +} + + + +void PushLexicalLevel (unsigned NewLevel) +/* Enter the specified lexical level */ +{ + LexicalLevel* L = xmalloc (sizeof (LexicalLevel)); + L->PrevLex = CurrentLex; + CurrentLex = L; + CurrentLex->CurrentLevel = NewLevel; + ++LexLevelDepth; +} + + + +void PopLexicalLevel (void) +/* Exit the current lexical level */ +{ + LexicalLevel* L; + PRECONDITION (CurrentLex != 0 && LexLevelDepth > 0); + L = CurrentLex; + CurrentLex = L->PrevLex; + xfree (L); + --LexLevelDepth; } @@ -225,7 +262,10 @@ void EnterGlobalLevel (void) /* Enter the program global lexical level */ { /* Safety */ - PRECONDITION (++LexicalLevel == LEX_LEVEL_GLOBAL); + PRECONDITION (GetLexicalLevel () == LEX_LEVEL_NONE); + + /* Enter global lexical level */ + PushLexicalLevel (LEX_LEVEL_GLOBAL); /* Create and assign the symbol table */ SymTab0 = SymTab = NewSymTable (SYMTAB_SIZE_GLOBAL); @@ -246,7 +286,7 @@ void LeaveGlobalLevel (void) /* Leave the program global lexical level */ { /* Safety */ - PRECONDITION (LexicalLevel-- == LEX_LEVEL_GLOBAL); + PRECONDITION (GetLexicalLevel () == LEX_LEVEL_GLOBAL); /* Check the tables */ CheckSymTable (SymTab0); @@ -260,6 +300,9 @@ void LeaveGlobalLevel (void) /* Don't delete the symbol and struct tables! */ SymTab = 0; TagTab = 0; + + /* Exit global lexical level */ + PopLexicalLevel (); } @@ -269,8 +312,8 @@ void EnterFunctionLevel (void) { SymTable* S; - /* New lexical level */ - ++LexicalLevel; + /* Enter function lexical level */ + PushLexicalLevel (LEX_LEVEL_FUNCTION); /* Get a new symbol table and make it current */ S = NewSymTable (SYMTAB_SIZE_FUNCTION); @@ -293,8 +336,11 @@ void EnterFunctionLevel (void) void RememberFunctionLevel (struct FuncDesc* F) /* Remember the symbol tables for the level and leave the level without checks */ { - /* Leave the lexical level */ - --LexicalLevel; + /* Safety */ + PRECONDITION (GetLexicalLevel () == LEX_LEVEL_FUNCTION); + + /* Leave function lexical level */ + PopLexicalLevel (); /* Remember the tables */ F->SymTab = SymTab; @@ -311,8 +357,8 @@ void RememberFunctionLevel (struct FuncDesc* F) void ReenterFunctionLevel (struct FuncDesc* F) /* Reenter the function lexical level using the existing tables from F */ { - /* New lexical level */ - ++LexicalLevel; + /* Enter function lexical level */ + PushLexicalLevel (LEX_LEVEL_FUNCTION); /* Make the tables current again */ F->SymTab->PrevTab = SymTab; @@ -330,8 +376,11 @@ void ReenterFunctionLevel (struct FuncDesc* F) void LeaveFunctionLevel (void) /* Leave function lexical level */ { - /* Leave the lexical level */ - --LexicalLevel; + /* Safety */ + PRECONDITION (GetLexicalLevel () == LEX_LEVEL_FUNCTION); + + /* Leave function lexical level */ + PopLexicalLevel (); /* Check the tables */ CheckSymTable (SymTab); @@ -355,8 +404,8 @@ void EnterBlockLevel (void) { SymTable* S; - /* New lexical level */ - ++LexicalLevel; + /* Enter block lexical level */ + PushLexicalLevel (LEX_LEVEL_BLOCK); /* Get a new symbol table and make it current */ S = NewSymTable (SYMTAB_SIZE_BLOCK); @@ -374,8 +423,11 @@ void EnterBlockLevel (void) void LeaveBlockLevel (void) /* Leave a nested block in a function */ { - /* Leave the lexical level */ - --LexicalLevel; + /* Safety */ + PRECONDITION (GetLexicalLevel () == LEX_LEVEL_BLOCK); + + /* Leave block lexical level */ + PopLexicalLevel (); /* Check the tables */ CheckSymTable (SymTab); @@ -392,6 +444,9 @@ void EnterStructLevel (void) { SymTable* S; + /* Enter struct lexical level */ + PushLexicalLevel (LEX_LEVEL_STRUCT); + /* Get a new symbol table and make it current. Note: Structs and enums ** nested in struct scope are NOT local to the struct but visible in the ** outside scope. So we will NOT create a new struct or enum table. @@ -406,6 +461,12 @@ void EnterStructLevel (void) void LeaveStructLevel (void) /* Leave a nested block for a struct definition */ { + /* Safety */ + PRECONDITION (GetLexicalLevel () == LEX_LEVEL_STRUCT); + + /* Leave struct lexical level */ + PopLexicalLevel (); + /* Don't delete the table */ FieldTab = FieldTab->PrevTab; } @@ -1398,7 +1459,7 @@ void EmitDebugInfo (void) /* For cosmetic reasons in the output file, we will insert two tabs ** on global level and just one on local level. */ - if (LexicalLevel == LEX_LEVEL_GLOBAL) { + if (GetLexicalLevel () == LEX_LEVEL_GLOBAL) { Head = "\t.dbg\t\tsym"; } else { Head = "\t.dbg\tsym"; diff --git a/src/cc65/symtab.h b/src/cc65/symtab.h index 469a4ba77..1df61a822 100644 --- a/src/cc65/symtab.h +++ b/src/cc65/symtab.h @@ -65,12 +65,22 @@ struct SymTable { /* An empty symbol table */ extern SymTable EmptySymTab; -/* Forwards */ -struct FuncDesc; +/* Lexical level linked list node type */ +typedef struct LexicalLevel LexicalLevel; +struct LexicalLevel { + LexicalLevel* PrevLex; + unsigned CurrentLevel; +}; /* Predefined lexical levels */ +#define LEX_LEVEL_NONE 0U #define LEX_LEVEL_GLOBAL 1U #define LEX_LEVEL_FUNCTION 2U +#define LEX_LEVEL_BLOCK 3U +#define LEX_LEVEL_STRUCT 4U + +/* Forwards */ +struct FuncDesc; @@ -80,9 +90,18 @@ struct FuncDesc; +unsigned GetLexicalLevelDepth (void); +/* Return the current lexical level depth */ + unsigned GetLexicalLevel (void); /* Return the current lexical level */ +void PushLexicalLevel (unsigned NewLevel); +/* Enter the specified lexical level */ + +void PopLexicalLevel (void); +/* Exit the current lexical level */ + void EnterGlobalLevel (void); /* Enter the program global lexical level */ From 6dbafda53f2bfcce1d4f27cfb64538d15875b9bf Mon Sep 17 00:00:00 2001 From: acqn Date: Mon, 14 Feb 2022 22:28:22 +0800 Subject: [PATCH 3/3] Testcase for #1662. --- test/val/bitfield.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/test/val/bitfield.c b/test/val/bitfield.c index 939d90dff..1de19777a 100644 --- a/test/val/bitfield.c +++ b/test/val/bitfield.c @@ -26,8 +26,10 @@ static unsigned char failures = 0; +typedef unsigned int field_type; + static struct four_bits { - unsigned int x : 4; + field_type x : 4; } fb = {1}; static void test_four_bits(void) @@ -57,8 +59,8 @@ static void test_four_bits(void) */ static struct four_bits_with_int { - unsigned int x : 4; - unsigned int y; + field_type x : 4; + field_type y; } fbi = {1, 2}; static void test_four_bits_with_int(void) @@ -95,8 +97,8 @@ static void test_four_bits_with_int(void) } static struct overlap { - unsigned int x : 10; - unsigned int y : 10; + field_type x : 10; + field_type y : 10; } o = {11, 22}; /* Tests that bit-fields can share allocation units. */ @@ -133,9 +135,9 @@ static void test_overlap(void) } static struct overlap_with_int { - unsigned int x : 10; - unsigned int y : 10; - unsigned int z; + field_type x : 10; + field_type y : 10; + field_type z; } oi = {111, 222, 333}; static void test_overlap_with_int(void) @@ -183,8 +185,8 @@ static void test_overlap_with_int(void) } static struct full_width { - unsigned int x : 8; - unsigned int y : 16; + field_type x : 8; + field_type y : 16; } fw = {255, 17}; static void test_full_width(void) @@ -220,13 +222,13 @@ static void test_full_width(void) } static struct aligned_end { - unsigned int : 2; - unsigned int x : 6; - unsigned int : 3; - unsigned int y : 13; + field_type : 2; + field_type x : 6; + field_type : 3; + field_type y : 13; /* z crosses a byte boundary, but fits in a byte when shifted. */ - unsigned int : 6; - unsigned int z : 7; + field_type : 6; + field_type z : 7; } ae = {63, 17, 100}; static void test_aligned_end(void)