Fixed a problem with the test expression in a for loop: It was not evaluated
correctly if it did not contain an explicit comparison operator. Removed an old hack from the test subroutine that did no longer work. git-svn-id: svn://svn.cc65.org/cc65/trunk@1619 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
@@ -475,6 +475,23 @@ void ConstSubExpr (int (*F) (ExprDesc*), ExprDesc* Expr)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void CheckBoolExpr (ExprDesc* lval)
|
||||||
|
/* Check if the given expression is a boolean expression, output a diagnostic
|
||||||
|
* if not.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
/* If it's an integer, it's ok. If it's not an integer, but a pointer,
|
||||||
|
* the pointer used in a boolean context is also ok
|
||||||
|
*/
|
||||||
|
if (!IsClassInt (lval->Type) && !IsClassPtr (lval->Type)) {
|
||||||
|
Error ("Boolean expression expected");
|
||||||
|
/* To avoid any compiler errors, make the expression a valid int */
|
||||||
|
MakeConstIntExpr (lval, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* code */
|
/* code */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
@@ -3108,50 +3125,34 @@ void intexpr (ExprDesc* lval)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void boolexpr (ExprDesc* lval)
|
void Test (unsigned Label, int Invert)
|
||||||
/* Get a boolean expression */
|
/* Evaluate a boolean test expression and jump depending on the result of
|
||||||
{
|
* the test and on Invert.
|
||||||
/* Read an expression */
|
|
||||||
expression (lval);
|
|
||||||
|
|
||||||
/* If it's an integer, it's ok. If it's not an integer, but a pointer,
|
|
||||||
* the pointer used in a boolean context is also ok
|
|
||||||
*/
|
*/
|
||||||
if (!IsClassInt (lval->Type) && !IsClassPtr (lval->Type)) {
|
|
||||||
Error ("Boolean expression expected");
|
|
||||||
/* To avoid any compiler errors, make the expression a valid int */
|
|
||||||
MakeConstIntExpr (lval, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void test (unsigned label, int cond)
|
|
||||||
/* Generate code to perform test and jump if false. */
|
|
||||||
{
|
{
|
||||||
int k;
|
int k;
|
||||||
ExprDesc lval;
|
ExprDesc lval;
|
||||||
|
|
||||||
/* Eat the parenthesis */
|
/* Evaluate the expression */
|
||||||
ConsumeLParen ();
|
|
||||||
|
|
||||||
/* Prepare the expression, setup labels */
|
|
||||||
memset (&lval, 0, sizeof (lval));
|
memset (&lval, 0, sizeof (lval));
|
||||||
|
|
||||||
/* Generate code to eval the expr */
|
|
||||||
k = expr (hie0, &lval);
|
k = expr (hie0, &lval);
|
||||||
|
|
||||||
|
/* Check for a boolean expression */
|
||||||
|
CheckBoolExpr (&lval);
|
||||||
|
|
||||||
|
/* Check for a constant expression */
|
||||||
if (k == 0 && lval.Flags == E_MCONST) {
|
if (k == 0 && lval.Flags == E_MCONST) {
|
||||||
|
|
||||||
/* Constant rvalue */
|
/* Constant rvalue */
|
||||||
if (cond == 0 && lval.ConstVal == 0) {
|
if (!Invert && lval.ConstVal == 0) {
|
||||||
g_jump (label);
|
g_jump (Label);
|
||||||
Warning ("Unreachable code");
|
Warning ("Unreachable code");
|
||||||
} else if (cond && lval.ConstVal) {
|
} else if (Invert && lval.ConstVal != 0) {
|
||||||
g_jump (label);
|
g_jump (Label);
|
||||||
}
|
|
||||||
ConsumeRParen ();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
/* If the expr hasn't set condition codes, set the force-test flag */
|
/* If the expr hasn't set condition codes, set the force-test flag */
|
||||||
if ((lval.Test & E_CC) == 0) {
|
if ((lval.Test & E_CC) == 0) {
|
||||||
lval.Test |= E_FORCETEST;
|
lval.Test |= E_FORCETEST;
|
||||||
@@ -3161,17 +3162,26 @@ void test (unsigned label, int cond)
|
|||||||
exprhs (CF_FORCECHAR, k, &lval);
|
exprhs (CF_FORCECHAR, k, &lval);
|
||||||
|
|
||||||
/* Generate the jump */
|
/* Generate the jump */
|
||||||
if (cond) {
|
if (Invert) {
|
||||||
g_truejump (CF_NONE, label);
|
g_truejump (CF_NONE, Label);
|
||||||
} else {
|
} else {
|
||||||
/* Special case (putting this here is a small hack - but hey, the
|
g_falsejump (CF_NONE, Label);
|
||||||
* compiler itself is one big hack...): If a semicolon follows, we
|
}
|
||||||
* don't have a statement and may omit the jump.
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void TestInParens (unsigned Label, int Invert)
|
||||||
|
/* Evaluate a boolean test expression in parenthesis and jump depending on
|
||||||
|
* the result of the test * and on Invert.
|
||||||
*/
|
*/
|
||||||
if (CurTok.Tok != TOK_SEMI) {
|
{
|
||||||
g_falsejump (CF_NONE, label);
|
/* Eat the parenthesis */
|
||||||
}
|
ConsumeLParen ();
|
||||||
}
|
|
||||||
|
/* Do the test */
|
||||||
|
Test (Label, Invert);
|
||||||
|
|
||||||
/* Check for the closing brace */
|
/* Check for the closing brace */
|
||||||
ConsumeRParen ();
|
ConsumeRParen ();
|
||||||
@@ -3179,4 +3189,3 @@ void test (unsigned label, int cond)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,11 @@ void ConstSubExpr (int (*F) (ExprDesc*), ExprDesc* Expr);
|
|||||||
* from this input error.
|
* from this input error.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
void CheckBoolExpr (ExprDesc* lval);
|
||||||
|
/* Check if the given expression is a boolean expression, output a diagnostic
|
||||||
|
* if not.
|
||||||
|
*/
|
||||||
|
|
||||||
unsigned assignadjust (type* lhst, ExprDesc* rhs);
|
unsigned assignadjust (type* lhst, ExprDesc* rhs);
|
||||||
/* Adjust the type of the right hand expression so that it can be assigned to
|
/* Adjust the type of the right hand expression so that it can be assigned to
|
||||||
* the type on the left hand side. This function is used for assignment and
|
* the type on the left hand side. This function is used for assignment and
|
||||||
@@ -77,12 +82,6 @@ void ConstIntExpr (ExprDesc* Val);
|
|||||||
void intexpr (ExprDesc* lval);
|
void intexpr (ExprDesc* lval);
|
||||||
/* Get an integer expression */
|
/* Get an integer expression */
|
||||||
|
|
||||||
void boolexpr (ExprDesc* lval);
|
|
||||||
/* Get a boolean expression */
|
|
||||||
|
|
||||||
void test (unsigned label, int cond);
|
|
||||||
/* Generate code to perform test and jump if false. */
|
|
||||||
|
|
||||||
int hie10 (ExprDesc* lval);
|
int hie10 (ExprDesc* lval);
|
||||||
/* Handle ++, --, !, unary - etc. */
|
/* Handle ++, --, !, unary - etc. */
|
||||||
|
|
||||||
@@ -95,6 +94,16 @@ int hie0 (ExprDesc* lval);
|
|||||||
void DefineData (ExprDesc* lval);
|
void DefineData (ExprDesc* lval);
|
||||||
/* Output a data definition for the given expression */
|
/* Output a data definition for the given expression */
|
||||||
|
|
||||||
|
void Test (unsigned Label, int Invert);
|
||||||
|
/* Evaluate a boolean test expression and jump depending on the result of
|
||||||
|
* the test and on Invert.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void TestInParens (unsigned Label, int Invert);
|
||||||
|
/* Evaluate a boolean test expression in parenthesis and jump depending on
|
||||||
|
* the result of the test * and on Invert.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* End of expr.h */
|
/* End of expr.h */
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ static int IfStatement (void)
|
|||||||
|
|
||||||
/* Generate a jump label and parse the condition */
|
/* Generate a jump label and parse the condition */
|
||||||
Label1 = GetLocalLabel ();
|
Label1 = GetLocalLabel ();
|
||||||
test (Label1, 0);
|
TestInParens (Label1, 0);
|
||||||
|
|
||||||
/* Parse the if body */
|
/* Parse the if body */
|
||||||
GotBreak = Statement (0);
|
GotBreak = Statement (0);
|
||||||
@@ -182,7 +182,7 @@ static void DoStatement (void)
|
|||||||
|
|
||||||
/* Parse the end condition */
|
/* Parse the end condition */
|
||||||
Consume (TOK_WHILE, "`while' expected");
|
Consume (TOK_WHILE, "`while' expected");
|
||||||
test (loop, 1);
|
TestInParens (loop, 1);
|
||||||
ConsumeSemi ();
|
ConsumeSemi ();
|
||||||
|
|
||||||
/* Define the break label */
|
/* Define the break label */
|
||||||
@@ -213,7 +213,7 @@ static void WhileStatement (void)
|
|||||||
g_defcodelabel (loop);
|
g_defcodelabel (loop);
|
||||||
|
|
||||||
/* Test the loop condition */
|
/* Test the loop condition */
|
||||||
test (lab, 0);
|
TestInParens (lab, 0);
|
||||||
|
|
||||||
/* Loop body */
|
/* Loop body */
|
||||||
Statement (&PendingToken);
|
Statement (&PendingToken);
|
||||||
@@ -339,7 +339,6 @@ static void ForStatement (void)
|
|||||||
/* Handle a 'for' statement */
|
/* Handle a 'for' statement */
|
||||||
{
|
{
|
||||||
ExprDesc lval1;
|
ExprDesc lval1;
|
||||||
ExprDesc lval2;
|
|
||||||
ExprDesc lval3;
|
ExprDesc lval3;
|
||||||
int HaveIncExpr;
|
int HaveIncExpr;
|
||||||
CodeMark IncExprStart;
|
CodeMark IncExprStart;
|
||||||
@@ -372,8 +371,7 @@ static void ForStatement (void)
|
|||||||
|
|
||||||
/* Parse the test expression */
|
/* Parse the test expression */
|
||||||
if (CurTok.Tok != TOK_SEMI) {
|
if (CurTok.Tok != TOK_SEMI) {
|
||||||
boolexpr (&lval2);
|
Test (lstat, 1);
|
||||||
g_truejump (CF_NONE, lstat);
|
|
||||||
g_jump (lab);
|
g_jump (lab);
|
||||||
} else {
|
} else {
|
||||||
g_jump (lstat);
|
g_jump (lstat);
|
||||||
|
|||||||
Reference in New Issue
Block a user