Fixed constant expression checks with no-code requirement.

Used return-by-value initialization for ExprDesc.
This commit is contained in:
acqn
2020-08-20 07:52:11 +08:00
parent 1abb9da2b2
commit 725511131a
8 changed files with 73 additions and 98 deletions

View File

@@ -129,16 +129,13 @@ static SymEntry* AsmGetSym (unsigned Arg, unsigned Type)
static void ParseByteArg (StrBuf* T, unsigned Arg) static void ParseByteArg (StrBuf* T, unsigned Arg)
/* Parse the %b format specifier */ /* Parse the %b format specifier */
{ {
ExprDesc Expr;
char Buf [16]; char Buf [16];
ED_Init (&Expr);
/* We expect an argument separated by a comma */ /* We expect an argument separated by a comma */
ConsumeComma (); ConsumeComma ();
/* Evaluate the expression */ /* Evaluate the expression */
ConstAbsIntExpr (hie1, &Expr); ExprDesc Expr = StaticConstAbsIntExpr (hie1);
/* Check the range but allow negative values if the type is signed */ /* Check the range but allow negative values if the type is signed */
if (IsSignUnsigned (Expr.Type)) { if (IsSignUnsigned (Expr.Type)) {
@@ -165,16 +162,13 @@ static void ParseByteArg (StrBuf* T, unsigned Arg)
static void ParseWordArg (StrBuf* T, unsigned Arg) static void ParseWordArg (StrBuf* T, unsigned Arg)
/* Parse the %w format specifier */ /* Parse the %w format specifier */
{ {
ExprDesc Expr;
char Buf [16]; char Buf [16];
ED_Init (&Expr);
/* We expect an argument separated by a comma */ /* We expect an argument separated by a comma */
ConsumeComma (); ConsumeComma ();
/* Evaluate the expression */ /* Evaluate the expression */
ConstAbsIntExpr (hie1, &Expr); ExprDesc Expr = StaticConstAbsIntExpr (hie1);
/* Check the range but allow negative values if the type is signed */ /* Check the range but allow negative values if the type is signed */
if (IsSignUnsigned (Expr.Type)) { if (IsSignUnsigned (Expr.Type)) {
@@ -201,16 +195,13 @@ static void ParseWordArg (StrBuf* T, unsigned Arg)
static void ParseLongArg (StrBuf* T, unsigned Arg attribute ((unused))) static void ParseLongArg (StrBuf* T, unsigned Arg attribute ((unused)))
/* Parse the %l format specifier */ /* Parse the %l format specifier */
{ {
ExprDesc Expr;
char Buf [16]; char Buf [16];
ED_Init (&Expr);
/* We expect an argument separated by a comma */ /* We expect an argument separated by a comma */
ConsumeComma (); ConsumeComma ();
/* Evaluate the expression */ /* Evaluate the expression */
ConstAbsIntExpr (hie1, &Expr); ExprDesc Expr = StaticConstAbsIntExpr (hie1);
/* Convert into a hex number */ /* Convert into a hex number */
xsprintf (Buf, sizeof (Buf), "$%08lX", Expr.IVal & 0xFFFFFFFF); xsprintf (Buf, sizeof (Buf), "$%08lX", Expr.IVal & 0xFFFFFFFF);
@@ -315,8 +306,6 @@ static void ParseStrArg (StrBuf* T, unsigned Arg attribute ((unused)))
ExprDesc Expr; ExprDesc Expr;
char Buf [64]; char Buf [64];
ED_Init (&Expr);
/* We expect an argument separated by a comma */ /* We expect an argument separated by a comma */
ConsumeComma (); ConsumeComma ();
@@ -336,7 +325,7 @@ static void ParseStrArg (StrBuf* T, unsigned Arg attribute ((unused)))
break; break;
default: default:
ConstAbsIntExpr (hie1, &Expr); Expr = StaticConstAbsIntExpr (hie1);
xsprintf (Buf, sizeof (Buf), "%ld", Expr.IVal); xsprintf (Buf, sizeof (Buf), "%ld", Expr.IVal);
SB_AppendStr (T, Buf); SB_AppendStr (T, Buf);
break; break;

View File

@@ -590,10 +590,8 @@ static SymEntry* ParseEnumDecl (const char* Name)
/* Check for an assigned value */ /* Check for an assigned value */
if (CurTok.Tok == TOK_ASSIGN) { if (CurTok.Tok == TOK_ASSIGN) {
ExprDesc Expr;
ED_Init (&Expr);
NextToken (); NextToken ();
ConstAbsIntExpr (hie1, &Expr); ExprDesc Expr = StaticConstAbsIntExpr (hie1);
EnumVal = Expr.IVal; EnumVal = Expr.IVal;
MemberType = Expr.Type; MemberType = Expr.Type;
IsSigned = IsSignSigned (MemberType); IsSigned = IsSignSigned (MemberType);
@@ -720,9 +718,6 @@ static int ParseFieldWidth (Declaration* Decl)
** otherwise the width of the field. ** otherwise the width of the field.
*/ */
{ {
ExprDesc Expr;
ED_Init (&Expr);
if (CurTok.Tok != TOK_COLON) { if (CurTok.Tok != TOK_COLON) {
/* No bit-field declaration */ /* No bit-field declaration */
return -1; return -1;
@@ -746,7 +741,7 @@ static int ParseFieldWidth (Declaration* Decl)
/* Read the width */ /* Read the width */
NextToken (); NextToken ();
ConstAbsIntExpr (hie1, &Expr); ExprDesc Expr = StaticConstAbsIntExpr (hie1);
if (Expr.IVal < 0) { if (Expr.IVal < 0) {
Error ("Negative width in bit-field"); 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 */ /* Read the size if it is given */
if (CurTok.Tok != TOK_RBRACK) { if (CurTok.Tok != TOK_RBRACK) {
ExprDesc Expr; ExprDesc Expr = StaticConstAbsIntExpr (hie1);
ED_Init (&Expr);
ConstAbsIntExpr (hie1, &Expr);
if (Expr.IVal <= 0) { if (Expr.IVal <= 0) {
if (D->Ident[0] != '\0') { if (D->Ident[0] != '\0') {
Error ("Size of array '%s' is invalid", D->Ident); 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 /* Parse initializaton for scalar data types. This function will not output the
** data but return it in ED. ** 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 */ /* Get the expression and convert it to the target type */
ConstExpr (hie1, ED); ExprDesc ED = StaticConstExpr (hie1);
TypeConversion (ED, T); TypeConversion (&ED, T);
/* Close eventually opening braces */ /* Close eventually opening braces */
ClosingCurlyBraces (BraceCount); ClosingCurlyBraces (BraceCount);
return ED;
} }
@@ -2186,11 +2181,8 @@ static void ParseScalarInitInternal (Type* T, ExprDesc* ED)
static unsigned ParseScalarInit (Type* T) static unsigned ParseScalarInit (Type* T)
/* Parse initializaton for scalar data types. Return the number of data bytes. */ /* Parse initializaton for scalar data types. Return the number of data bytes. */
{ {
ExprDesc ED;
ED_Init (&ED);
/* Parse initialization */ /* Parse initialization */
ParseScalarInitInternal (T, &ED); ExprDesc ED = ParseScalarInitInternal (T);
/* Output the data */ /* Output the data */
DefineData (&ED); DefineData (&ED);
@@ -2208,10 +2200,7 @@ static unsigned ParsePointerInit (Type* T)
unsigned BraceCount = OpeningCurlyBraces (0); unsigned BraceCount = OpeningCurlyBraces (0);
/* Expression */ /* Expression */
ExprDesc ED; ExprDesc ED = StaticConstExpr (hie1);
ED_Init (&ED);
ConstExpr (hie1, &ED);
TypeConversion (&ED, T); TypeConversion (&ED, T);
/* Output the data */ /* Output the data */
@@ -2438,7 +2427,7 @@ static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers)
SI.Offs * CHAR_BITS + SI.ValBits); SI.Offs * CHAR_BITS + SI.ValBits);
/* Read the data, check for a constant integer, do a range check */ /* Read the data, check for a constant integer, do a range check */
ParseScalarInitInternal (Entry->Type, &ED); ED = ParseScalarInitInternal (Entry->Type);
if (!ED_IsConstAbsInt (&ED)) { if (!ED_IsConstAbsInt (&ED)) {
Error ("Constant initializer expected"); Error ("Constant initializer expected");
ED_MakeConstAbsInt (&ED, 1); ED_MakeConstAbsInt (&ED, 1);
@@ -2556,10 +2545,7 @@ static unsigned ParseVoidInit (Type* T)
/* Allow an arbitrary list of values */ /* Allow an arbitrary list of values */
Size = 0; Size = 0;
do { do {
ExprDesc Expr; ExprDesc Expr = StaticConstExpr (hie1);
ED_Init (&Expr);
ConstExpr (hie1, &Expr);
switch (GetUnderlyingTypeCode (&Expr.Type[0])) { switch (GetUnderlyingTypeCode (&Expr.Type[0])) {
case T_SCHAR: case T_SCHAR:

View File

@@ -3147,17 +3147,14 @@ static void hieAndPP (ExprDesc* Expr)
** called recursively from the preprocessor. ** called recursively from the preprocessor.
*/ */
{ {
ConstAbsIntExpr (hie2, Expr); *Expr = StaticConstAbsIntExpr (hie2);
while (CurTok.Tok == TOK_BOOL_AND) { while (CurTok.Tok == TOK_BOOL_AND) {
ExprDesc Expr2;
ED_Init (&Expr2);
/* Skip the && */ /* Skip the && */
NextToken (); NextToken ();
/* Get rhs */ /* Get rhs */
ConstAbsIntExpr (hie2, &Expr2); ExprDesc Expr2 = StaticConstAbsIntExpr (hie2);
/* Combine the two */ /* Combine the two */
Expr->IVal = (Expr->IVal && Expr2.IVal); Expr->IVal = (Expr->IVal && Expr2.IVal);
@@ -3171,17 +3168,14 @@ static void hieOrPP (ExprDesc *Expr)
** called recursively from the preprocessor. ** called recursively from the preprocessor.
*/ */
{ {
ConstAbsIntExpr (hieAndPP, Expr); *Expr = StaticConstAbsIntExpr (hieAndPP);
while (CurTok.Tok == TOK_BOOL_OR) { while (CurTok.Tok == TOK_BOOL_OR) {
ExprDesc Expr2;
ED_Init (&Expr2);
/* Skip the && */ /* Skip the && */
NextToken (); NextToken ();
/* Get rhs */ /* Get rhs */
ConstAbsIntExpr (hieAndPP, &Expr2); ExprDesc Expr2 = StaticConstAbsIntExpr (hieAndPP);
/* Combine the two */ /* Combine the two */
Expr->IVal = (Expr->IVal || Expr2.IVal); 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) void BoolExpr (void (*Func) (ExprDesc*), ExprDesc* Expr)
/* Will evaluate an expression via the given function. If the result is not /* 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 ** 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); ExprWithCheck (Func, Expr);
if (!ED_IsBool (Expr)) { if (!ED_IsBool (Expr)) {
Error ("Boolean expression expected"); Error ("Scalar expression expected");
/* To avoid any compiler errors, make the expression a valid int */ /* 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) ExprDesc StaticConstExpr (void (*Func) (ExprDesc*))
/* Will evaluate an expression via the given function. If the result is not /* Will evaluate an expression via the given function. If the result is not a
** a constant numeric integer value, a diagnostic will be printed, and the ** 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 ** value is replaced by a constant one to make sure there are no internal
** errors that result from this input error. ** errors that result from this input error.
*/ */
{ {
Expr->Flags |= E_EVAL_CONST; ExprDesc Expr;
ExprWithCheck (Func, Expr); ED_Init (&Expr);
if (!ED_IsConstAbsInt (Expr)) {
Expr.Flags |= E_EVAL_C_CONST;
MarkedExprWithCheck (Func, &Expr);
if (!ED_IsConstAbsInt (&Expr) || !ED_CodeRangeIsEmpty (&Expr)) {
Error ("Constant integer expression expected"); Error ("Constant integer expression expected");
/* To avoid any compiler errors, make the expression a valid const */ /* To avoid any compiler errors, make the expression a valid const */
ED_MakeConstAbsInt (Expr, 1); ED_MakeConstAbsInt (&Expr, 1);
} }
/* Return by value */
return Expr;
} }

View File

@@ -54,13 +54,6 @@ int evalexpr (unsigned flags, void (*Func) (ExprDesc*), ExprDesc* Expr);
void Expression0 (ExprDesc* Expr); void Expression0 (ExprDesc* Expr);
/* Evaluate an expression via hie0 and put the result into the primary register */ /* 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); void BoolExpr (void (*Func) (ExprDesc*), ExprDesc* Expr);
/* Will evaluate an expression via the given function. If the result is not /* 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 ** 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. ** are no internal errors that result from this input error.
*/ */
void ConstAbsIntExpr (void (*Func) (ExprDesc*), ExprDesc* Expr); ExprDesc StaticConstExpr (void (*Func) (ExprDesc*));
/* Will evaluate an expression via the given function. If the result is not /* Get an expression evaluated via the given function. If the result is not a
** a constant numeric integer value, a diagnostic will be printed, and the ** 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 ** value is replaced by a constant one to make sure there are no internal
** errors that result from this input error. ** errors that result from this input error.
*/ */

View File

@@ -1042,9 +1042,6 @@ static void DoError (void)
static int DoIf (int Skip) static int DoIf (int Skip)
/* Process #if directive */ /* Process #if directive */
{ {
ExprDesc Expr;
ED_Init (&Expr);
/* We're about to abuse the compiler expression parser to evaluate the /* We're about to abuse the compiler expression parser to evaluate the
** #if expression. Save the current tokens to come back here later. ** #if expression. Save the current tokens to come back here later.
** NOTE: Yes, this is a hack, but it saves a complete separate expression ** NOTE: Yes, this is a hack, but it saves a complete separate expression
@@ -1079,7 +1076,7 @@ static int DoIf (int Skip)
NextToken (); NextToken ();
/* Call the expression parser */ /* Call the expression parser */
ConstExpr (hie1, &Expr); ExprDesc Expr = StaticConstExpr (hie1);
/* End preprocessing mode */ /* End preprocessing mode */
Preprocessing = 0; Preprocessing = 0;

View File

@@ -44,7 +44,7 @@
/* Set when the preprocessor calls ConstExpr() recursively */ /* Set when the preprocessor calls StaticConstExpr() recursively */
extern unsigned char Preprocessing; extern unsigned char Preprocessing;

View File

@@ -55,8 +55,6 @@ void ParseStaticAssert ()
ExprDesc Expr; ExprDesc Expr;
int failed; int failed;
ED_Init (&Expr);
/* Skip the _Static_assert token itself */ /* Skip the _Static_assert token itself */
CHECK (CurTok.Tok == TOK_STATIC_ASSERT); CHECK (CurTok.Tok == TOK_STATIC_ASSERT);
NextToken (); NextToken ();
@@ -67,7 +65,7 @@ void ParseStaticAssert ()
} }
/* Parse assertion condition */ /* Parse assertion condition */
ConstAbsIntExpr (hie1, &Expr); Expr = StaticConstAbsIntExpr (hie1);
failed = !Expr.IVal; failed = !Expr.IVal;
/* If there is a comma, we also have an error message. The message is optional because we /* If there is a comma, we also have an error message. The message is optional because we

View File

@@ -216,8 +216,7 @@ void CaseLabel (void)
NextToken (); NextToken ();
/* Read the selector expression */ /* Read the selector expression */
ED_Init (&CaseExpr); CaseExpr = StaticConstAbsIntExpr (hie1);
ConstAbsIntExpr (hie1, &CaseExpr);
Val = CaseExpr.IVal; Val = CaseExpr.IVal;
/* Now check if we're inside a switch statement */ /* Now check if we're inside a switch statement */