Merge pull request #1662 from acqn/StructFix

[cc65] Fixed ICE on unnamed bit-fields declared with typedef'ed types
This commit is contained in:
Bob Andrews 2022-02-14 17:31:45 +01:00 committed by GitHub
commit 24c8de87c2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 119 additions and 37 deletions

View File

@ -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 */
@ -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;
}

View File

@ -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";

View File

@ -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 */

View File

@ -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)