From fdded33097f3a584221abfc63fb4d370baca08d2 Mon Sep 17 00:00:00 2001 From: acqn Date: Sat, 15 Aug 2020 06:27:11 +0800 Subject: [PATCH 1/6] Made it easier to support 0-size structs in the future. --- src/cc65/compile.c | 10 ++++++---- src/cc65/datatype.c | 12 ++++++++++-- src/cc65/locals.c | 12 ++++++------ 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/cc65/compile.c b/src/cc65/compile.c index 85c9bd5a4..d1f78098d 100644 --- a/src/cc65/compile.c +++ b/src/cc65/compile.c @@ -218,14 +218,16 @@ static void Parse (void) ** void types in ISO modes. */ if (Size == 0) { - if (!IsTypeVoid (Decl.Type)) { + if (!IsEmptiableObjectType (Decl.Type)) { if (!IsTypeArray (Decl.Type)) { /* Size is unknown and not an array */ - Error ("Variable '%s' has unknown size", Decl.Ident); + Error ("Cannot initialize variable '%s' of unknown size", Decl.Ident); } } else if (IS_Get (&Standard) != STD_CC65) { /* We cannot declare variables of type void */ - Error ("Illegal type for variable '%s'", Decl.Ident); + Error ("Illegal type '%s' for variable '%s'", + GetFullTypeName (Decl.Type), + Decl.Ident); } } @@ -253,7 +255,7 @@ static void Parse (void) /* We cannot declare variables of type void */ Error ("Illegal type for variable '%s'", Decl.Ident); Entry->Flags &= ~(SC_STORAGE | SC_DEF); - } else if (Size == 0 && SymIsDef (Entry)) { + } else if (Size == 0 && SymIsDef (Entry) && !IsEmptiableObjectType (Decl.Type)) { /* Size is unknown. Is it an array? */ if (!IsTypeArray (Decl.Type)) { Error ("Variable '%s' has unknown size", Decl.Ident); diff --git a/src/cc65/datatype.c b/src/cc65/datatype.c index e43af238e..b69a44dd0 100644 --- a/src/cc65/datatype.c +++ b/src/cc65/datatype.c @@ -805,7 +805,11 @@ unsigned CheckedSizeOf (const Type* T) { unsigned Size = SizeOf (T); if (Size == 0) { - Error ("Size of type '%s' is unknown", GetFullTypeName (T)); + if (HasUnknownSize (T + 1)) { + Error ("Size of type '%s' is unknown", GetFullTypeName (T)); + } else { + Error ("Size of type '%s' is 0", GetFullTypeName (T)); + } Size = SIZEOF_CHAR; /* Don't return zero */ } return Size; @@ -821,7 +825,11 @@ unsigned CheckedPSizeOf (const Type* T) { unsigned Size = PSizeOf (T); if (Size == 0) { - Error ("Size of type '%s' is unknown", GetFullTypeName (T + 1)); + if (HasUnknownSize (T + 1)) { + Error ("Pointer to type '%s' of unknown size", GetFullTypeName (T + 1)); + } else { + Error ("Pointer to type '%s' of 0 size", GetFullTypeName (T + 1)); + } Size = SIZEOF_CHAR; /* Don't return zero */ } return Size; diff --git a/src/cc65/locals.c b/src/cc65/locals.c index 297994455..ad36bded0 100644 --- a/src/cc65/locals.c +++ b/src/cc65/locals.c @@ -174,8 +174,8 @@ static void ParseRegisterDecl (Declaration* Decl, int Reg) Sym->Flags |= SC_REF; } - /* Cannot allocate a variable of zero size */ - if (Size == 0) { + /* Cannot allocate a variable of unknown size */ + if (HasUnknownSize (Sym->Type)) { if (IsTypeArray (Decl->Type)) { Error ("Array '%s' has unknown size", Decl->Ident); } else { @@ -370,8 +370,8 @@ static void ParseAutoDecl (Declaration* Decl) } } - /* Cannot allocate a variable of zero size */ - if (Size == 0) { + /* Cannot allocate an incomplete variable */ + if (HasUnknownSize (Sym->Type)) { if (IsTypeArray (Decl->Type)) { Error ("Array '%s' has unknown size", Decl->Ident); } else { @@ -428,8 +428,8 @@ static void ParseStaticDecl (Declaration* Decl) } - /* Cannot allocate a variable of zero size */ - if (Size == 0) { + /* Cannot allocate an incomplete variable */ + if (HasUnknownSize (Sym->Type)) { if (IsTypeArray (Decl->Type)) { Error ("Array '%s' has unknown size", Decl->Ident); } else { From e9545d68ee5208b7ece65bf08e260603bd9a9894 Mon Sep 17 00:00:00 2001 From: acqn Date: Sat, 17 Apr 2021 11:43:03 +0800 Subject: [PATCH 2/6] Minor clean-ups and typo fixes. --- src/cc65/assignment.c | 15 --------------- src/cc65/expr.c | 9 +-------- src/cc65/expr.h | 9 ++++++++- src/cc65/swstmt.c | 2 +- 4 files changed, 10 insertions(+), 25 deletions(-) diff --git a/src/cc65/assignment.c b/src/cc65/assignment.c index e6d1e4526..d565551ea 100644 --- a/src/cc65/assignment.c +++ b/src/cc65/assignment.c @@ -49,21 +49,6 @@ -/*****************************************************************************/ -/* Data */ -/*****************************************************************************/ - - - -/* Map a generator function and its attributes to a token */ -typedef struct GenDesc { - token_t Tok; /* Token to map to */ - unsigned Flags; /* Flags for generator function */ - void (*Func) (unsigned, unsigned long); /* Generator func */ -} GenDesc; - - - /*****************************************************************************/ /* Code */ /*****************************************************************************/ diff --git a/src/cc65/expr.c b/src/cc65/expr.c index 0275e61a3..dc45b108d 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -48,13 +48,6 @@ -/* Map a generator function and its attributes to a token */ -typedef struct GenDesc { - token_t Tok; /* Token to map to */ - unsigned Flags; /* Flags for generator function */ - void (*Func) (unsigned, unsigned long); /* Generator func */ -} GenDesc; - /* Descriptors for the operations */ static GenDesc GenPASGN = { TOK_PLUS_ASSIGN, GEN_NOPUSH, g_add }; static GenDesc GenSASGN = { TOK_MINUS_ASSIGN, GEN_NOPUSH, g_sub }; @@ -243,7 +236,7 @@ static const GenDesc* FindGen (token_t Tok, const GenDesc* Table) /* Find a token in a generator table */ { while (Table->Tok != TOK_INVALID) { - if (Table->Tok == Tok) { + if ((token_t)Table->Tok == Tok) { return Table; } ++Table; diff --git a/src/cc65/expr.h b/src/cc65/expr.h index 841edcb62..abdf8ab0d 100644 --- a/src/cc65/expr.h +++ b/src/cc65/expr.h @@ -26,13 +26,20 @@ #define SQP_KEEP_NONE 0x00 #define SQP_KEEP_TEST 0x01U #define SQP_KEEP_EAX 0x02U -#define SQP_KEEP_EXPR 0x03U /* SQP_KEEP_TEST | SQP_KEEP_EAX */ +#define SQP_KEEP_EXPR 0x03U /* SQP_KEEP_TEST | SQP_KEEP_EAX */ /* Generator attributes */ #define GEN_NOPUSH 0x01 /* Don't push lhs */ #define GEN_COMM 0x02 /* Operator is commutative */ #define GEN_NOFUNC 0x04 /* Not allowed for function pointers */ +/* Map a generator function and its attributes to a token */ +typedef struct GenDesc { + long Tok; /* Token to map to */ + unsigned Flags; /* Flags for generator function */ + void (*Func) (unsigned, unsigned long); /* Generator func */ +} GenDesc; + /*****************************************************************************/ diff --git a/src/cc65/swstmt.c b/src/cc65/swstmt.c index ee0bd1a85..00555ffc3 100644 --- a/src/cc65/swstmt.c +++ b/src/cc65/swstmt.c @@ -206,7 +206,7 @@ void SwitchStatement (void) void CaseLabel (void) -/* Handle a case sabel */ +/* Handle a case label */ { ExprDesc CaseExpr; /* Case label expression */ long Val; /* Case label value */ From 924fcf5d0690f8d0eb761d98d88f372107c9d924 Mon Sep 17 00:00:00 2001 From: acqn Date: Tue, 8 Jun 2021 09:32:58 +0800 Subject: [PATCH 3/6] Replaced several occurance of PtrConversion() with StdConversion(). Variadic arguments of functions should be default-promoted. --- src/cc65/datatype.c | 19 +++++++++++++++++++ src/cc65/datatype.h | 6 ++++++ src/cc65/expr.c | 9 +++++---- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/cc65/datatype.c b/src/cc65/datatype.c index b69a44dd0..6d9afa403 100644 --- a/src/cc65/datatype.c +++ b/src/cc65/datatype.c @@ -1007,6 +1007,25 @@ const Type* PtrConversion (const Type* T) +const Type* StdConversion (const Type* T) +/* If the type is a function, convert it to pointer to function. If the +** expression is an array, convert it to pointer to first element. If the +** type is an integer, do integeral promotion. Otherwise return T. +*/ +{ + if (IsTypeFunc (T)) { + return AddressOf (T); + } else if (IsTypeArray (T)) { + return AddressOf (GetElementType (T)); + } else if (IsClassInt (T)) { + return IntPromotion (T); + } else { + return T; + } +} + + + const Type* IntPromotion (const Type* T) /* Apply the integer promotions to T and return the result. The returned type ** string may be T if there is no need to change it. diff --git a/src/cc65/datatype.h b/src/cc65/datatype.h index c60023944..e8ba7b6c0 100644 --- a/src/cc65/datatype.h +++ b/src/cc65/datatype.h @@ -368,6 +368,12 @@ const Type* PtrConversion (const Type* T); ** return T. */ +const Type* StdConversion (const Type* T); +/* If the type is a function, convert it to pointer to function. If the +** expression is an array, convert it to pointer to first element. If the +** type is an integer, do integeral promotion. Otherwise return T. +*/ + const Type* IntPromotion (const Type* T); /* Apply the integer promotions to T and return the result. The returned type ** string may be T if there is no need to change it. diff --git a/src/cc65/expr.c b/src/cc65/expr.c index dc45b108d..dc2374190 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -765,9 +765,10 @@ static unsigned FunctionArgList (FuncDesc* Func, int IsFastcall, ExprDesc* ED) } else { /* No prototype available. Convert array to "pointer to first - ** element", and function to "pointer to function". + ** element", function to "pointer to function" and do integral + ** promotion if necessary. */ - Expr.Type = PtrConversion (Expr.Type); + TypeConversion (&Expr, StdConversion (Expr.Type)); } @@ -3062,7 +3063,7 @@ static void parseadd (ExprDesc* Expr, int DoArrayRef) Error ("Invalid operands for binary operator '+'"); } else { /* Array and function types must be converted to pointer types */ - Expr->Type = PtrConversion (Expr->Type); + Expr->Type = StdConversion (Expr->Type); } } @@ -3341,7 +3342,7 @@ static void parsesub (ExprDesc* Expr) } /* Result type is either a pointer or an integer */ - Expr->Type = PtrConversion (Expr->Type); + Expr->Type = StdConversion (Expr->Type); /* Condition code not set */ ED_MarkAsUntested (Expr); From 2d014383cd13a96bdad1af8350da8b197c96dec5 Mon Sep 17 00:00:00 2001 From: acqn Date: Tue, 8 Jun 2021 00:43:26 +0800 Subject: [PATCH 4/6] Replaced certain usage of "(New-)PointerTo()" with "AddressOf()". --- src/cc65/expr.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/cc65/expr.c b/src/cc65/expr.c index dc2374190..9c12741ec 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -1127,7 +1127,7 @@ static void Primary (ExprDesc* E) /* output its label */ E->Flags = E_RTYPE_RVAL | E_LOC_CODE | E_ADDRESS_OF; E->Name = Entry->V.L.Label; - E->Type = NewPointerTo (type_void); + E->Type = type_void_p; NextToken (); } else { Error ("Computed gotos are a C extension, not supported with this --standard"); @@ -1946,7 +1946,7 @@ void hie10 (ExprDesc* Expr) /* The & operator yields an rvalue address */ ED_AddrExpr (Expr); } - Expr->Type = NewPointerTo (Expr->Type); + Expr->Type = AddressOf (Expr->Type); break; case TOK_SIZEOF: @@ -2265,9 +2265,9 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */ Tok = CurTok.Tok; NextToken (); - /* If lhs is a function, convert it to pointer to function */ + /* If lhs is a function, convert it to the address of the function */ if (IsTypeFunc (Expr->Type)) { - Expr->Type = NewPointerTo (Expr->Type); + Expr->Type = AddressOf (Expr->Type); } /* Get the lhs on stack */ @@ -2287,9 +2287,9 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */ /* Get the right hand side */ MarkedExprWithCheck (hienext, &Expr2); - /* If rhs is a function, convert it to pointer to function */ + /* If rhs is a function, convert it to the address of the function */ if (IsTypeFunc (Expr2.Type)) { - Expr2.Type = NewPointerTo (Expr2.Type); + Expr2.Type = AddressOf (Expr2.Type); } /* Check for a numeric constant expression */ From aac03eae6f3746dd21c5d26c551b93b5729578b3 Mon Sep 17 00:00:00 2001 From: acqn Date: Sun, 16 May 2021 19:08:42 +0800 Subject: [PATCH 5/6] Better future-proof bit-masking. --- src/cc65/typeconv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cc65/typeconv.c b/src/cc65/typeconv.c index a7528a2f8..c72b2c5eb 100644 --- a/src/cc65/typeconv.c +++ b/src/cc65/typeconv.c @@ -143,10 +143,10 @@ static void DoConversion (ExprDesc* Expr, const Type* NewType) /* Do the integer constant <-> absolute address conversion if necessary */ if (IsClassPtr (NewType)) { - Expr->Flags &= ~E_LOC_NONE; + Expr->Flags &= ~E_MASK_LOC; Expr->Flags |= E_LOC_ABS | E_ADDRESS_OF; } else if (IsClassInt (NewType)) { - Expr->Flags &= ~(E_LOC_ABS | E_ADDRESS_OF); + Expr->Flags &= ~(E_MASK_LOC | E_ADDRESS_OF); Expr->Flags |= E_LOC_NONE; } From 6a3b9a9880599acc38fd721a24c5864ec3194a3e Mon Sep 17 00:00:00 2001 From: acqn Date: Sun, 16 May 2021 19:08:42 +0800 Subject: [PATCH 6/6] E_ADDRESS_OF logic fix. --- src/cc65/exprdesc.c | 5 ++--- src/cc65/exprdesc.h | 3 +-- src/cc65/loadexpr.c | 1 + 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/cc65/exprdesc.c b/src/cc65/exprdesc.c index 3d7b7c384..7d0ace004 100644 --- a/src/cc65/exprdesc.c +++ b/src/cc65/exprdesc.c @@ -93,8 +93,7 @@ int ED_IsLocPrimaryOrExpr (const ExprDesc* Expr) int ED_IsIndExpr (const ExprDesc* Expr) /* Check if the expression is a reference to its value */ { - return (Expr->Flags & E_ADDRESS_OF) == 0 && - !ED_IsLocNone (Expr) && !ED_IsLocPrimary (Expr); + return (Expr->Flags & E_ADDRESS_OF) == 0 && !ED_IsLocNone (Expr); } #endif @@ -282,7 +281,7 @@ ExprDesc* ED_AddrExpr (ExprDesc* Expr) case E_LOC_EXPR: Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE); - Expr->Flags |= E_LOC_PRIMARY | E_RTYPE_RVAL; + Expr->Flags |= E_ADDRESS_OF | E_LOC_PRIMARY | E_RTYPE_RVAL; break; default: diff --git a/src/cc65/exprdesc.h b/src/cc65/exprdesc.h index 13eb36e5e..f2b66ee56 100644 --- a/src/cc65/exprdesc.h +++ b/src/cc65/exprdesc.h @@ -493,8 +493,7 @@ INLINE int ED_IsAddrExpr (const ExprDesc* Expr) INLINE int ED_IsIndExpr (const ExprDesc* Expr) /* Check if the expression is a reference to its value */ { - return (Expr->Flags & E_ADDRESS_OF) == 0 && - !ED_IsLocNone (Expr) && !ED_IsLocPrimary (Expr); + return (Expr->Flags & E_ADDRESS_OF) == 0 && !ED_IsLocNone (Expr); } #else int ED_IsIndExpr (const ExprDesc* Expr); diff --git a/src/cc65/loadexpr.c b/src/cc65/loadexpr.c index 4b7f8e279..c5badc1b3 100644 --- a/src/cc65/loadexpr.c +++ b/src/cc65/loadexpr.c @@ -92,6 +92,7 @@ static void LoadAddress (unsigned Flags, ExprDesc* Expr) g_leasp (Expr->IVal); break; + case E_LOC_PRIMARY: case E_LOC_EXPR: if (Expr->IVal != 0) { /* We have an expression in the primary plus a constant