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:
parent
4a9210e3e1
commit
89f00263af
117
src/cc65/expr.c
117
src/cc65/expr.c
@ -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)
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user