mirror of
https://github.com/cc65/cc65.git
synced 2025-04-12 00:37:12 +00:00
Fixed constant expression checks with no-code requirement.
Used return-by-value initialization for ExprDesc.
This commit is contained in:
parent
1abb9da2b2
commit
725511131a
@ -129,16 +129,13 @@ static SymEntry* AsmGetSym (unsigned Arg, unsigned Type)
|
||||
static void ParseByteArg (StrBuf* T, unsigned Arg)
|
||||
/* Parse the %b format specifier */
|
||||
{
|
||||
ExprDesc Expr;
|
||||
char Buf [16];
|
||||
|
||||
ED_Init (&Expr);
|
||||
|
||||
/* We expect an argument separated by a comma */
|
||||
ConsumeComma ();
|
||||
|
||||
/* Evaluate the expression */
|
||||
ConstAbsIntExpr (hie1, &Expr);
|
||||
ExprDesc Expr = StaticConstAbsIntExpr (hie1);
|
||||
|
||||
/* Check the range but allow negative values if the type is signed */
|
||||
if (IsSignUnsigned (Expr.Type)) {
|
||||
@ -165,16 +162,13 @@ static void ParseByteArg (StrBuf* T, unsigned Arg)
|
||||
static void ParseWordArg (StrBuf* T, unsigned Arg)
|
||||
/* Parse the %w format specifier */
|
||||
{
|
||||
ExprDesc Expr;
|
||||
char Buf [16];
|
||||
|
||||
ED_Init (&Expr);
|
||||
|
||||
/* We expect an argument separated by a comma */
|
||||
ConsumeComma ();
|
||||
|
||||
/* Evaluate the expression */
|
||||
ConstAbsIntExpr (hie1, &Expr);
|
||||
ExprDesc Expr = StaticConstAbsIntExpr (hie1);
|
||||
|
||||
/* Check the range but allow negative values if the type is signed */
|
||||
if (IsSignUnsigned (Expr.Type)) {
|
||||
@ -201,16 +195,13 @@ static void ParseWordArg (StrBuf* T, unsigned Arg)
|
||||
static void ParseLongArg (StrBuf* T, unsigned Arg attribute ((unused)))
|
||||
/* Parse the %l format specifier */
|
||||
{
|
||||
ExprDesc Expr;
|
||||
char Buf [16];
|
||||
|
||||
ED_Init (&Expr);
|
||||
|
||||
/* We expect an argument separated by a comma */
|
||||
ConsumeComma ();
|
||||
|
||||
/* Evaluate the expression */
|
||||
ConstAbsIntExpr (hie1, &Expr);
|
||||
ExprDesc Expr = StaticConstAbsIntExpr (hie1);
|
||||
|
||||
/* Convert into a hex number */
|
||||
xsprintf (Buf, sizeof (Buf), "$%08lX", Expr.IVal & 0xFFFFFFFF);
|
||||
@ -315,8 +306,6 @@ static void ParseStrArg (StrBuf* T, unsigned Arg attribute ((unused)))
|
||||
ExprDesc Expr;
|
||||
char Buf [64];
|
||||
|
||||
ED_Init (&Expr);
|
||||
|
||||
/* We expect an argument separated by a comma */
|
||||
ConsumeComma ();
|
||||
|
||||
@ -336,7 +325,7 @@ static void ParseStrArg (StrBuf* T, unsigned Arg attribute ((unused)))
|
||||
break;
|
||||
|
||||
default:
|
||||
ConstAbsIntExpr (hie1, &Expr);
|
||||
Expr = StaticConstAbsIntExpr (hie1);
|
||||
xsprintf (Buf, sizeof (Buf), "%ld", Expr.IVal);
|
||||
SB_AppendStr (T, Buf);
|
||||
break;
|
||||
|
@ -590,10 +590,8 @@ static SymEntry* ParseEnumDecl (const char* Name)
|
||||
/* Check for an assigned value */
|
||||
if (CurTok.Tok == TOK_ASSIGN) {
|
||||
|
||||
ExprDesc Expr;
|
||||
ED_Init (&Expr);
|
||||
NextToken ();
|
||||
ConstAbsIntExpr (hie1, &Expr);
|
||||
ExprDesc Expr = StaticConstAbsIntExpr (hie1);
|
||||
EnumVal = Expr.IVal;
|
||||
MemberType = Expr.Type;
|
||||
IsSigned = IsSignSigned (MemberType);
|
||||
@ -720,9 +718,6 @@ static int ParseFieldWidth (Declaration* Decl)
|
||||
** otherwise the width of the field.
|
||||
*/
|
||||
{
|
||||
ExprDesc Expr;
|
||||
ED_Init (&Expr);
|
||||
|
||||
if (CurTok.Tok != TOK_COLON) {
|
||||
/* No bit-field declaration */
|
||||
return -1;
|
||||
@ -746,7 +741,7 @@ static int ParseFieldWidth (Declaration* Decl)
|
||||
|
||||
/* Read the width */
|
||||
NextToken ();
|
||||
ConstAbsIntExpr (hie1, &Expr);
|
||||
ExprDesc Expr = StaticConstAbsIntExpr (hie1);
|
||||
|
||||
if (Expr.IVal < 0) {
|
||||
Error ("Negative width in bit-field");
|
||||
@ -1819,9 +1814,7 @@ static void Declarator (const DeclSpec* Spec, Declaration* D, declmode_t Mode)
|
||||
|
||||
/* Read the size if it is given */
|
||||
if (CurTok.Tok != TOK_RBRACK) {
|
||||
ExprDesc Expr;
|
||||
ED_Init (&Expr);
|
||||
ConstAbsIntExpr (hie1, &Expr);
|
||||
ExprDesc Expr = StaticConstAbsIntExpr (hie1);
|
||||
if (Expr.IVal <= 0) {
|
||||
if (D->Ident[0] != '\0') {
|
||||
Error ("Size of array '%s' is invalid", D->Ident);
|
||||
@ -2158,7 +2151,7 @@ static void OutputBitFieldData (StructInitData* SI)
|
||||
|
||||
|
||||
|
||||
static void ParseScalarInitInternal (Type* T, ExprDesc* ED)
|
||||
static ExprDesc ParseScalarInitInternal (Type* T)
|
||||
/* Parse initializaton for scalar data types. This function will not output the
|
||||
** data but return it in ED.
|
||||
*/
|
||||
@ -2174,11 +2167,13 @@ static void ParseScalarInitInternal (Type* T, ExprDesc* ED)
|
||||
}
|
||||
|
||||
/* Get the expression and convert it to the target type */
|
||||
ConstExpr (hie1, ED);
|
||||
TypeConversion (ED, T);
|
||||
ExprDesc ED = StaticConstExpr (hie1);
|
||||
TypeConversion (&ED, T);
|
||||
|
||||
/* Close eventually opening braces */
|
||||
ClosingCurlyBraces (BraceCount);
|
||||
|
||||
return ED;
|
||||
}
|
||||
|
||||
|
||||
@ -2186,11 +2181,8 @@ static void ParseScalarInitInternal (Type* T, ExprDesc* ED)
|
||||
static unsigned ParseScalarInit (Type* T)
|
||||
/* Parse initializaton for scalar data types. Return the number of data bytes. */
|
||||
{
|
||||
ExprDesc ED;
|
||||
ED_Init (&ED);
|
||||
|
||||
/* Parse initialization */
|
||||
ParseScalarInitInternal (T, &ED);
|
||||
ExprDesc ED = ParseScalarInitInternal (T);
|
||||
|
||||
/* Output the data */
|
||||
DefineData (&ED);
|
||||
@ -2208,10 +2200,7 @@ static unsigned ParsePointerInit (Type* T)
|
||||
unsigned BraceCount = OpeningCurlyBraces (0);
|
||||
|
||||
/* Expression */
|
||||
ExprDesc ED;
|
||||
ED_Init (&ED);
|
||||
|
||||
ConstExpr (hie1, &ED);
|
||||
ExprDesc ED = StaticConstExpr (hie1);
|
||||
TypeConversion (&ED, T);
|
||||
|
||||
/* Output the data */
|
||||
@ -2438,7 +2427,7 @@ static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers)
|
||||
SI.Offs * CHAR_BITS + SI.ValBits);
|
||||
|
||||
/* Read the data, check for a constant integer, do a range check */
|
||||
ParseScalarInitInternal (Entry->Type, &ED);
|
||||
ED = ParseScalarInitInternal (Entry->Type);
|
||||
if (!ED_IsConstAbsInt (&ED)) {
|
||||
Error ("Constant initializer expected");
|
||||
ED_MakeConstAbsInt (&ED, 1);
|
||||
@ -2556,10 +2545,7 @@ static unsigned ParseVoidInit (Type* T)
|
||||
/* Allow an arbitrary list of values */
|
||||
Size = 0;
|
||||
do {
|
||||
ExprDesc Expr;
|
||||
ED_Init (&Expr);
|
||||
|
||||
ConstExpr (hie1, &Expr);
|
||||
ExprDesc Expr = StaticConstExpr (hie1);
|
||||
switch (GetUnderlyingTypeCode (&Expr.Type[0])) {
|
||||
|
||||
case T_SCHAR:
|
||||
|
@ -3147,17 +3147,14 @@ static void hieAndPP (ExprDesc* Expr)
|
||||
** called recursively from the preprocessor.
|
||||
*/
|
||||
{
|
||||
ConstAbsIntExpr (hie2, Expr);
|
||||
*Expr = StaticConstAbsIntExpr (hie2);
|
||||
while (CurTok.Tok == TOK_BOOL_AND) {
|
||||
|
||||
ExprDesc Expr2;
|
||||
ED_Init (&Expr2);
|
||||
|
||||
/* Skip the && */
|
||||
NextToken ();
|
||||
|
||||
/* Get rhs */
|
||||
ConstAbsIntExpr (hie2, &Expr2);
|
||||
ExprDesc Expr2 = StaticConstAbsIntExpr (hie2);
|
||||
|
||||
/* Combine the two */
|
||||
Expr->IVal = (Expr->IVal && Expr2.IVal);
|
||||
@ -3171,17 +3168,14 @@ static void hieOrPP (ExprDesc *Expr)
|
||||
** called recursively from the preprocessor.
|
||||
*/
|
||||
{
|
||||
ConstAbsIntExpr (hieAndPP, Expr);
|
||||
*Expr = StaticConstAbsIntExpr (hieAndPP);
|
||||
while (CurTok.Tok == TOK_BOOL_OR) {
|
||||
|
||||
ExprDesc Expr2;
|
||||
ED_Init (&Expr2);
|
||||
|
||||
/* Skip the && */
|
||||
NextToken ();
|
||||
|
||||
/* Get rhs */
|
||||
ConstAbsIntExpr (hieAndPP, &Expr2);
|
||||
ExprDesc Expr2 = StaticConstAbsIntExpr (hieAndPP);
|
||||
|
||||
/* Combine the two */
|
||||
Expr->IVal = (Expr->IVal || Expr2.IVal);
|
||||
@ -3900,24 +3894,6 @@ void Expression0 (ExprDesc* Expr)
|
||||
|
||||
|
||||
|
||||
void ConstExpr (void (*Func) (ExprDesc*), ExprDesc* Expr)
|
||||
/* Will evaluate an expression via the given function. If the result is not
|
||||
** a constant of some sort, a diagnostic will be printed, and the value is
|
||||
** replaced by a constant one to make sure there are no internal errors that
|
||||
** result from this input error.
|
||||
*/
|
||||
{
|
||||
Expr->Flags |= E_EVAL_CONST;
|
||||
ExprWithCheck (Func, Expr);
|
||||
if (!ED_IsConst (Expr)) {
|
||||
Error ("Constant expression expected");
|
||||
/* To avoid any compiler errors, make the expression a valid const */
|
||||
ED_MakeConstAbsInt (Expr, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void BoolExpr (void (*Func) (ExprDesc*), ExprDesc* Expr)
|
||||
/* Will evaluate an expression via the given function. If the result is not
|
||||
** something that may be evaluated in a boolean context, a diagnostic will be
|
||||
@ -3927,26 +3903,56 @@ void BoolExpr (void (*Func) (ExprDesc*), ExprDesc* Expr)
|
||||
{
|
||||
ExprWithCheck (Func, Expr);
|
||||
if (!ED_IsBool (Expr)) {
|
||||
Error ("Boolean expression expected");
|
||||
Error ("Scalar expression expected");
|
||||
/* To avoid any compiler errors, make the expression a valid int */
|
||||
ED_MakeConstAbsInt (Expr, 1);
|
||||
ED_MakeConstBool (Expr, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ConstAbsIntExpr (void (*Func) (ExprDesc*), ExprDesc* Expr)
|
||||
/* Will evaluate an expression via the given function. If the result is not
|
||||
** a constant numeric integer value, a diagnostic will be printed, and the
|
||||
ExprDesc StaticConstExpr (void (*Func) (ExprDesc*))
|
||||
/* Will evaluate an expression via the given function. If the result is not a
|
||||
** static constant expression, a diagnostic will be printed, and the value is
|
||||
** replaced by a constant one to make sure there are no internal errors that
|
||||
** result from this input error.
|
||||
*/
|
||||
{
|
||||
ExprDesc Expr;
|
||||
ED_Init (&Expr);
|
||||
|
||||
Expr.Flags |= E_EVAL_C_CONST;
|
||||
MarkedExprWithCheck (Func, &Expr);
|
||||
if (!ED_IsConst (&Expr) || !ED_CodeRangeIsEmpty (&Expr)) {
|
||||
Error ("Constant expression expected");
|
||||
/* To avoid any compiler errors, make the expression a valid const */
|
||||
ED_MakeConstAbsInt (&Expr, 1);
|
||||
}
|
||||
|
||||
/* Return by value */
|
||||
return Expr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ExprDesc StaticConstAbsIntExpr (void (*Func) (ExprDesc*))
|
||||
/* Will evaluate an expression via the given function. If the result is not a
|
||||
** static constant numeric integer value, a diagnostic will be printed, and the
|
||||
** value is replaced by a constant one to make sure there are no internal
|
||||
** errors that result from this input error.
|
||||
*/
|
||||
{
|
||||
Expr->Flags |= E_EVAL_CONST;
|
||||
ExprWithCheck (Func, Expr);
|
||||
if (!ED_IsConstAbsInt (Expr)) {
|
||||
ExprDesc Expr;
|
||||
ED_Init (&Expr);
|
||||
|
||||
Expr.Flags |= E_EVAL_C_CONST;
|
||||
MarkedExprWithCheck (Func, &Expr);
|
||||
if (!ED_IsConstAbsInt (&Expr) || !ED_CodeRangeIsEmpty (&Expr)) {
|
||||
Error ("Constant integer expression expected");
|
||||
/* To avoid any compiler errors, make the expression a valid const */
|
||||
ED_MakeConstAbsInt (Expr, 1);
|
||||
ED_MakeConstAbsInt (&Expr, 1);
|
||||
}
|
||||
|
||||
/* Return by value */
|
||||
return Expr;
|
||||
}
|
||||
|
@ -54,13 +54,6 @@ int evalexpr (unsigned flags, void (*Func) (ExprDesc*), ExprDesc* Expr);
|
||||
void Expression0 (ExprDesc* Expr);
|
||||
/* Evaluate an expression via hie0 and put the result into the primary register */
|
||||
|
||||
void ConstExpr (void (*Func) (ExprDesc*), ExprDesc* Expr);
|
||||
/* Will evaluate an expression via the given function. If the result is not
|
||||
** a constant of some sort, a diagnostic will be printed, and the value is
|
||||
** replaced by a constant one to make sure there are no internal errors that
|
||||
** result from this input error.
|
||||
*/
|
||||
|
||||
void BoolExpr (void (*Func) (ExprDesc*), ExprDesc* Expr);
|
||||
/* Will evaluate an expression via the given function. If the result is not
|
||||
** something that may be evaluated in a boolean context, a diagnostic will be
|
||||
@ -68,9 +61,16 @@ void BoolExpr (void (*Func) (ExprDesc*), ExprDesc* Expr);
|
||||
** are no internal errors that result from this input error.
|
||||
*/
|
||||
|
||||
void ConstAbsIntExpr (void (*Func) (ExprDesc*), ExprDesc* Expr);
|
||||
/* Will evaluate an expression via the given function. If the result is not
|
||||
** a constant numeric integer value, a diagnostic will be printed, and the
|
||||
ExprDesc StaticConstExpr (void (*Func) (ExprDesc*));
|
||||
/* Get an expression evaluated via the given function. If the result is not a
|
||||
** static constant expression, a diagnostic will be printed, and the value is
|
||||
** replaced by a constant one to make sure there are no internal errors that
|
||||
** result from this input error.
|
||||
*/
|
||||
|
||||
ExprDesc StaticConstAbsIntExpr (void (*Func) (ExprDesc*));
|
||||
/* Get an expression evaluate via the given function. If the result is not a
|
||||
** static constant numeric integer value, a diagnostic will be printed, and the
|
||||
** value is replaced by a constant one to make sure there are no internal
|
||||
** errors that result from this input error.
|
||||
*/
|
||||
|
@ -1042,9 +1042,6 @@ static void DoError (void)
|
||||
static int DoIf (int Skip)
|
||||
/* Process #if directive */
|
||||
{
|
||||
ExprDesc Expr;
|
||||
ED_Init (&Expr);
|
||||
|
||||
/* We're about to abuse the compiler expression parser to evaluate the
|
||||
** #if expression. Save the current tokens to come back here later.
|
||||
** NOTE: Yes, this is a hack, but it saves a complete separate expression
|
||||
@ -1079,7 +1076,7 @@ static int DoIf (int Skip)
|
||||
NextToken ();
|
||||
|
||||
/* Call the expression parser */
|
||||
ConstExpr (hie1, &Expr);
|
||||
ExprDesc Expr = StaticConstExpr (hie1);
|
||||
|
||||
/* End preprocessing mode */
|
||||
Preprocessing = 0;
|
||||
|
@ -44,7 +44,7 @@
|
||||
|
||||
|
||||
|
||||
/* Set when the preprocessor calls ConstExpr() recursively */
|
||||
/* Set when the preprocessor calls StaticConstExpr() recursively */
|
||||
extern unsigned char Preprocessing;
|
||||
|
||||
|
||||
|
@ -55,8 +55,6 @@ void ParseStaticAssert ()
|
||||
ExprDesc Expr;
|
||||
int failed;
|
||||
|
||||
ED_Init (&Expr);
|
||||
|
||||
/* Skip the _Static_assert token itself */
|
||||
CHECK (CurTok.Tok == TOK_STATIC_ASSERT);
|
||||
NextToken ();
|
||||
@ -67,7 +65,7 @@ void ParseStaticAssert ()
|
||||
}
|
||||
|
||||
/* Parse assertion condition */
|
||||
ConstAbsIntExpr (hie1, &Expr);
|
||||
Expr = StaticConstAbsIntExpr (hie1);
|
||||
failed = !Expr.IVal;
|
||||
|
||||
/* If there is a comma, we also have an error message. The message is optional because we
|
||||
|
@ -216,8 +216,7 @@ void CaseLabel (void)
|
||||
NextToken ();
|
||||
|
||||
/* Read the selector expression */
|
||||
ED_Init (&CaseExpr);
|
||||
ConstAbsIntExpr (hie1, &CaseExpr);
|
||||
CaseExpr = StaticConstAbsIntExpr (hie1);
|
||||
Val = CaseExpr.IVal;
|
||||
|
||||
/* Now check if we're inside a switch statement */
|
||||
|
Loading…
x
Reference in New Issue
Block a user