1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-17 16:29:32 +00:00

Move the expression test code into separate modules.

The Test() and TestInParens() functions do now return information about the
expression that was tested.
An if... statement where the expression is always true will now print a
warning "Unreachable code" if it has an else clause.


git-svn-id: svn://svn.cc65.org/cc65/trunk@2889 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2004-03-02 18:00:08 +00:00
parent 9d46a42600
commit e47ed98aa7
7 changed files with 233 additions and 83 deletions

View File

@ -90,7 +90,7 @@ static GenDesc GenOASGN = { TOK_OR_ASSIGN, GEN_NOPUSH, g_or };
int hie0 (ExprDesc *lval);
/* Parse comma operator. */
static int expr (int (*func) (ExprDesc*), ExprDesc *lval);
int expr (int (*func) (ExprDesc*), ExprDesc *lval);
/* Expression parser; func is either hie0 or hie1. */
@ -2987,7 +2987,7 @@ int evalexpr (unsigned flags, int (*f) (ExprDesc*), ExprDesc* lval)
static int expr (int (*func) (ExprDesc*), ExprDesc *lval)
int expr (int (*func) (ExprDesc*), ExprDesc *lval)
/* Expression parser; func is either hie0 or hie1. */
{
int k;
@ -3071,66 +3071,3 @@ void intexpr (ExprDesc* lval)
void Test (unsigned Label, int Invert)
/* Evaluate a boolean test expression and jump depending on the result of
* the test and on Invert.
*/
{
int k;
ExprDesc lval;
/* Evaluate the expression */
k = expr (hie0, InitExprDesc (&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 */
ExprLoad (CF_FORCECHAR, k, &lval);
/* Generate the jump */
if (Invert) {
g_truejump (CF_NONE, Label);
} else {
g_falsejump (CF_NONE, Label);
}
}
}
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.
*/
{
/* Eat the parenthesis */
ConsumeLParen ();
/* Do the test */
Test (Label, Invert);
/* Check for the closing brace */
ConsumeRParen ();
}

View File

@ -61,6 +61,9 @@ int evalexpr (unsigned flags, int (*f) (ExprDesc*), ExprDesc* lval);
* primary register and 1 is returned.
*/
int expr (int (*func) (ExprDesc*), ExprDesc *lval);
/* Expression parser; func is either hie0 or hie1. */
void expression1 (ExprDesc* lval);
/* Evaluate an expression on level 1 (no comma operator) and put it into
* the primary register
@ -87,16 +90,6 @@ int hie1 (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

@ -84,6 +84,7 @@ OBJS = anonname.o \
swstmt.o \
symentry.o \
symtab.o \
testexpr.o \
textseg.o \
typecmp.o \
typeconv.o \

View File

@ -118,6 +118,7 @@ OBJS = anonname.obj \
swstmt.obj \
symentry.obj \
symtab.obj \
testexpr.obj \
textseg.obj \
typecmp.obj \
typeconv.obj \

View File

@ -58,6 +58,7 @@
#include "swstmt.h"
#include "symtab.h"
#include "stmt.h"
#include "testexpr.h"
#include "typeconv.h"
@ -133,6 +134,7 @@ static int IfStatement (void)
/* Handle an 'if' statement */
{
unsigned Label1;
unsigned TestResult;
int GotBreak;
/* Skip the if */
@ -140,7 +142,7 @@ static int IfStatement (void)
/* Generate a jump label and parse the condition */
Label1 = GetLocalLabel ();
TestInParens (Label1, 0);
TestResult = TestInParens (Label1, 0);
/* Parse the if body */
GotBreak = Statement (0);
@ -157,21 +159,28 @@ static int IfStatement (void)
} else {
/* Generate a jump around the else branch */
/* Generate a jump around the else branch */
unsigned Label2 = GetLocalLabel ();
g_jump (Label2);
g_jump (Label2);
/* Skip the else */
/* Skip the else */
NextToken ();
/* Define the target for the first test */
g_defcodelabel (Label1);
/* If the if expression was always true, the code in the else branch
* is never executed. Output a warning if this is the case.
*/
if (TestResult == TESTEXPR_TRUE) {
Warning ("Unreachable code");
}
/* Total break only if both branches had a break. */
/* Define the target for the first test */
g_defcodelabel (Label1);
/* Total break only if both branches had a break. */
GotBreak &= Statement (0);
/* Generate the label for the else clause */
g_defcodelabel (Label2);
g_defcodelabel (Label2);
/* Done */
return GotBreak;

130
src/cc65/testexpr.c Normal file
View File

@ -0,0 +1,130 @@
/*****************************************************************************/
/* */
/* testexpr.c */
/* */
/* Test an expression and jump */
/* */
/* */
/* */
/* (C) 2004 Ullrich von Bassewitz */
/* Römerstraße 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include "codegen.h"
#include "error.h"
#include "expr.h"
#include "scanner.h"
#include "testexpr.h"
/*****************************************************************************/
/* Code */
/*****************************************************************************/
unsigned Test (unsigned Label, int Invert)
/* Evaluate a boolean test expression and jump depending on the result of
* the test and on Invert. The function returns one of the TESTEXPR_xx codes
* defined above. If the jump is always true, a warning is output.
*/
{
ExprDesc lval;
unsigned Result;
/* Evaluate the expression */
int k = expr (hie0, InitExprDesc (&lval));
/* Check for a boolean expression */
CheckBoolExpr (&lval);
/* Check for a constant expression */
if (k == 0 && lval.Flags == E_MCONST) {
/* Result is constant, so we know the outcome */
Result = (lval.ConstVal != 0);
/* Constant rvalue */
if (!Invert && lval.ConstVal == 0) {
g_jump (Label);
Warning ("Unreachable code");
} else if (Invert && lval.ConstVal != 0) {
g_jump (Label);
}
} else {
/* Result is unknown */
Result = TESTEXPR_UNKNOWN;
/* 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 */
ExprLoad (CF_FORCECHAR, k, &lval);
/* Generate the jump */
if (Invert) {
g_truejump (CF_NONE, Label);
} else {
g_falsejump (CF_NONE, Label);
}
}
/* Return the result */
return Result;
}
unsigned TestInParens (unsigned Label, int Invert)
/* Evaluate a boolean test expression in parenthesis and jump depending on
* the result of the test * and on Invert. The function returns one of the
* TESTEXPR_xx codes defined above. If the jump is always true, a warning is
* output.
*/
{
unsigned Result;
/* Eat the parenthesis */
ConsumeLParen ();
/* Do the test */
Result = Test (Label, Invert);
/* Check for the closing brace */
ConsumeRParen ();
/* Return the result of the expression */
return Result;
}

79
src/cc65/testexpr.h Normal file
View File

@ -0,0 +1,79 @@
/*****************************************************************************/
/* */
/* test.h */
/* */
/* Test an expression and jump */
/* */
/* */
/* */
/* (C) 2004 Ullrich von Bassewitz */
/* Römerstraße 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef TESTEXPR_H
#define TESTEXPR_H
/*****************************************************************************/
/* Data */
/*****************************************************************************/
#define TESTEXPR_UNKNOWN 0 /* Result of expression unknown */
#define TESTEXPR_TRUE 1 /* Expression yields true */
#define TESTEXPR_FALSE 2 /* Expression yields false */
/*****************************************************************************/
/* Code */
/*****************************************************************************/
unsigned Test (unsigned Label, int Invert);
/* Evaluate a boolean test expression and jump depending on the result of
* the test and on Invert. The function returns one of the TESTEXPR_xx codes
* defined above. If the jump is always true, a warning is output.
*/
unsigned TestInParens (unsigned Label, int Invert);
/* Evaluate a boolean test expression in parenthesis and jump depending on
* the result of the test * and on Invert. The function returns one of the
* TESTEXPR_xx codes defined above. If the jump is always true, a warning is
* output.
*/
/* End of testexpr.h */
#endif