1
0
mirror of https://github.com/cc65/cc65.git synced 2025-04-09 10:39:40 +00:00

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:
cuz 2002-11-24 18:18:16 +00:00
parent 4a9210e3e1
commit 89f00263af
3 changed files with 82 additions and 66 deletions

View File

@ -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 */
/*****************************************************************************/
@ -3108,70 +3125,63 @@ void intexpr (ExprDesc* lval)
void boolexpr (ExprDesc* lval)
/* Get a boolean expression */
void Test (unsigned Label, int Invert)
/* Evaluate a boolean test expression and jump depending on the result of
* the test and on Invert.
*/
{
/* Read an expression */
expression (lval);
int k;
ExprDesc 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);
/* Evaluate the expression */
memset (&lval, 0, sizeof (lval));
k = expr (hie0, &lval);
/* Check for a boolean expression */
CheckBoolExpr (&lval);
/* Check for a constant expression */
if (k == 0 && lval.Flags == E_MCONST) {
/* Constant rvalue */
if (!Invert && lval.ConstVal == 0) {
g_jump (Label);
Warning ("Unreachable code");
} else if (Invert && lval.ConstVal != 0) {
g_jump (Label);
}
} else {
/* If the expr hasn't set condition codes, set the force-test flag */
if ((lval.Test & E_CC) == 0) {
lval.Test |= E_FORCETEST;
}
/* Load the value into the primary register */
exprhs (CF_FORCECHAR, k, &lval);
/* Generate the jump */
if (Invert) {
g_truejump (CF_NONE, Label);
} else {
g_falsejump (CF_NONE, Label);
}
}
}
void test (unsigned label, int cond)
/* Generate code to perform test and jump if false. */
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.
*/
{
int k;
ExprDesc lval;
/* Eat the parenthesis */
ConsumeLParen ();
/* Prepare the expression, setup labels */
memset (&lval, 0, sizeof (lval));
/* Generate code to eval the expr */
k = expr (hie0, &lval);
if (k == 0 && lval.Flags == E_MCONST) {
/* Constant rvalue */
if (cond == 0 && lval.ConstVal == 0) {
g_jump (label);
Warning ("Unreachable code");
} else if (cond && lval.ConstVal) {
g_jump (label);
}
ConsumeRParen ();
return;
}
/* If the expr hasn't set condition codes, set the force-test flag */
if ((lval.Test & E_CC) == 0) {
lval.Test |= E_FORCETEST;
}
/* Load the value into the primary register */
exprhs (CF_FORCECHAR, k, &lval);
/* Generate the jump */
if (cond) {
g_truejump (CF_NONE, label);
} else {
/* Special case (putting this here is a small hack - but hey, the
* compiler itself is one big hack...): If a semicolon follows, we
* don't have a statement and may omit the jump.
*/
if (CurTok.Tok != TOK_SEMI) {
g_falsejump (CF_NONE, label);
}
}
/* Do the test */
Test (Label, Invert);
/* Check for the closing brace */
ConsumeRParen ();
@ -3179,4 +3189,3 @@ void test (unsigned label, int cond)

View File

@ -37,6 +37,11 @@ void ConstSubExpr (int (*F) (ExprDesc*), ExprDesc* Expr);
* 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);
/* 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
@ -77,12 +82,6 @@ void ConstIntExpr (ExprDesc* Val);
void intexpr (ExprDesc* lval);
/* 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);
/* Handle ++, --, !, unary - etc. */
@ -95,6 +94,16 @@ int hie0 (ExprDesc* lval);
void DefineData (ExprDesc* lval);
/* 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 */

View File

@ -121,7 +121,7 @@ static int IfStatement (void)
/* Generate a jump label and parse the condition */
Label1 = GetLocalLabel ();
test (Label1, 0);
TestInParens (Label1, 0);
/* Parse the if body */
GotBreak = Statement (0);
@ -182,7 +182,7 @@ static void DoStatement (void)
/* Parse the end condition */
Consume (TOK_WHILE, "`while' expected");
test (loop, 1);
TestInParens (loop, 1);
ConsumeSemi ();
/* Define the break label */
@ -213,7 +213,7 @@ static void WhileStatement (void)
g_defcodelabel (loop);
/* Test the loop condition */
test (lab, 0);
TestInParens (lab, 0);
/* Loop body */
Statement (&PendingToken);
@ -339,7 +339,6 @@ static void ForStatement (void)
/* Handle a 'for' statement */
{
ExprDesc lval1;
ExprDesc lval2;
ExprDesc lval3;
int HaveIncExpr;
CodeMark IncExprStart;
@ -372,8 +371,7 @@ static void ForStatement (void)
/* Parse the test expression */
if (CurTok.Tok != TOK_SEMI) {
boolexpr (&lval2);
g_truejump (CF_NONE, lstat);
Test (lstat, 1);
g_jump (lab);
} else {
g_jump (lstat);