1
0
mirror of https://github.com/cc65/cc65.git synced 2025-08-08 06:25:17 +00:00

More reliable test for true/false with addresses for AND, OR and ternary operators.

Minor comment typo fix.
This commit is contained in:
acqn
2021-03-13 14:27:11 +08:00
committed by Oliver Schmidt
parent f8835d2867
commit 3c2e7ce41c
3 changed files with 47 additions and 8 deletions

View File

@@ -3658,7 +3658,7 @@ static int hieAnd (ExprDesc* Expr, unsigned* TrueLab, int* TrueLabAllocated)
*/ */
DoDeferred (SQP_KEEP_NONE, Expr); DoDeferred (SQP_KEEP_NONE, Expr);
if (Expr->IVal == 0 && !ED_IsAddrExpr (Expr)) { if (ED_IsConstFalse (Expr)) {
/* Skip remaining */ /* Skip remaining */
Flags |= E_EVAL_UNEVAL; Flags |= E_EVAL_UNEVAL;
} }
@@ -3713,7 +3713,7 @@ static int hieAnd (ExprDesc* Expr, unsigned* TrueLab, int* TrueLabAllocated)
*/ */
DoDeferred (SQP_KEEP_NONE, &Expr2); DoDeferred (SQP_KEEP_NONE, &Expr2);
if (Expr2.IVal == 0 && !ED_IsAddrExpr (&Expr2)) { if (ED_IsConstFalse (&Expr2)) {
/* Skip remaining */ /* Skip remaining */
Flags |= E_EVAL_UNEVAL; Flags |= E_EVAL_UNEVAL;
/* The value of the expression will be false */ /* The value of the expression will be false */
@@ -3826,7 +3826,7 @@ static void hieOr (ExprDesc *Expr)
*/ */
DoDeferred (SQP_KEEP_NONE, Expr); DoDeferred (SQP_KEEP_NONE, Expr);
if (Expr->IVal != 0 || ED_IsAddrExpr (Expr)) { if (ED_IsConstTrue (Expr)) {
/* Skip remaining */ /* Skip remaining */
Flags |= E_EVAL_UNEVAL; Flags |= E_EVAL_UNEVAL;
} }
@@ -3878,7 +3878,7 @@ static void hieOr (ExprDesc *Expr)
*/ */
DoDeferred (SQP_KEEP_NONE, &Expr2); DoDeferred (SQP_KEEP_NONE, &Expr2);
if (Expr2.IVal != 0 || ED_IsAddrExpr (&Expr2)) { if (ED_IsConstTrue (&Expr2)) {
/* Skip remaining */ /* Skip remaining */
Flags |= E_EVAL_UNEVAL; Flags |= E_EVAL_UNEVAL;
/* The result is always true */ /* The result is always true */
@@ -3945,6 +3945,7 @@ static void hieQuest (ExprDesc* Expr)
/* Check if it's a ternary expression */ /* Check if it's a ternary expression */
if (CurTok.Tok == TOK_QUEST) { if (CurTok.Tok == TOK_QUEST) {
/* The constant condition must be compile-time known as well */
int ConstantCond = ED_IsConstBool (Expr); int ConstantCond = ED_IsConstBool (Expr);
unsigned Flags = Expr->Flags & E_MASK_KEEP_RESULT; unsigned Flags = Expr->Flags & E_MASK_KEEP_RESULT;
@@ -3955,9 +3956,13 @@ static void hieQuest (ExprDesc* Expr)
NextToken (); NextToken ();
/* Convert non-integer constant boolean */ /* Convert non-integer constant to boolean constant, so that we may just
if (ED_IsAddrExpr (Expr)) { ** check it in the same way.
*/
if (ED_IsConstTrue (Expr)) {
ED_MakeConstBool (Expr, 1); ED_MakeConstBool (Expr, 1);
} else if (ED_IsConstFalse (Expr)) {
ED_MakeConstBool (Expr, 0);
} }
if (!ConstantCond) { if (!ConstantCond) {

View File

@@ -397,6 +397,30 @@ int ED_IsConstBool (const ExprDesc* Expr)
int ED_IsConstTrue (const ExprDesc* Expr)
/* Return true if the constant expression can be evaluated as boolean true at
** compile time.
*/
{
/* Non-zero arithmetics and objects addresses are boolean true */
return (ED_IsConstAbsInt (Expr) && Expr->IVal != 0) ||
(ED_IsAddrExpr (Expr));
}
int ED_IsConstFalse (const ExprDesc* Expr)
/* Return true if the constant expression can be evaluated as boolean false at
** compile time.
*/
{
/* Zero arithmetics and null pointers are boolean false */
return (ED_IsConstAbsInt (Expr) && Expr->IVal == 0) ||
ED_IsNullPtr (Expr);
}
int ED_IsConst (const ExprDesc* Expr) int ED_IsConst (const ExprDesc* Expr)
/* Return true if the expression denotes a constant of some sort. This can be a /* Return true if the expression denotes a constant of some sort. This can be a
** numeric constant, the address of a global variable (maybe with offset) or ** numeric constant, the address of a global variable (maybe with offset) or
@@ -449,7 +473,7 @@ int ED_IsNullPtr (const ExprDesc* Expr)
int ED_IsBool (const ExprDesc* Expr) int ED_IsBool (const ExprDesc* Expr)
/* Return true of the expression can be treated as a boolean, that is, it can /* Return true if the expression can be treated as a boolean, that is, it can
** be an operand to a compare operation. ** be an operand to a compare operation.
*/ */
{ {

View File

@@ -643,6 +643,16 @@ int ED_IsConstAbsInt (const ExprDesc* Expr);
int ED_IsConstBool (const ExprDesc* Expr); int ED_IsConstBool (const ExprDesc* Expr);
/* Return true if the expression can be constantly evaluated as a boolean. */ /* Return true if the expression can be constantly evaluated as a boolean. */
int ED_IsConstTrue (const ExprDesc* Expr);
/* Return true if the constant expression can be evaluated as boolean true at
** compile time.
*/
int ED_IsConstFalse (const ExprDesc* Expr);
/* Return true if the constant expression can be evaluated as boolean false at
** compile time.
*/
int ED_IsConst (const ExprDesc* Expr); int ED_IsConst (const ExprDesc* Expr);
/* Return true if the expression denotes a constant of some sort. This can be a /* Return true if the expression denotes a constant of some sort. This can be a
** numeric constant, the address of a global variable (maybe with offset) or ** numeric constant, the address of a global variable (maybe with offset) or
@@ -668,7 +678,7 @@ int ED_IsNullPtr (const ExprDesc* Expr);
/* Return true if the given expression is a NULL pointer constant */ /* Return true if the given expression is a NULL pointer constant */
int ED_IsBool (const ExprDesc* Expr); int ED_IsBool (const ExprDesc* Expr);
/* Return true of the expression can be treated as a boolean, that is, it can /* Return true if the expression can be treated as a boolean, that is, it can
** be an operand to a compare operation with 0/NULL. ** be an operand to a compare operation with 0/NULL.
*/ */