diff --git a/src/cc65/expr.c b/src/cc65/expr.c index 43df6bfa4..845b46696 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -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 (); -} - - - diff --git a/src/cc65/expr.h b/src/cc65/expr.h index 99a0af32d..f60fc6d55 100644 --- a/src/cc65/expr.h +++ b/src/cc65/expr.h @@ -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 */ diff --git a/src/cc65/make/gcc.mak b/src/cc65/make/gcc.mak index 179b875c5..d33a06fa1 100644 --- a/src/cc65/make/gcc.mak +++ b/src/cc65/make/gcc.mak @@ -84,6 +84,7 @@ OBJS = anonname.o \ swstmt.o \ symentry.o \ symtab.o \ + testexpr.o \ textseg.o \ typecmp.o \ typeconv.o \ diff --git a/src/cc65/make/watcom.mak b/src/cc65/make/watcom.mak index 101bf5c07..884175a83 100644 --- a/src/cc65/make/watcom.mak +++ b/src/cc65/make/watcom.mak @@ -118,6 +118,7 @@ OBJS = anonname.obj \ swstmt.obj \ symentry.obj \ symtab.obj \ + testexpr.obj \ textseg.obj \ typecmp.obj \ typeconv.obj \ diff --git a/src/cc65/stmt.c b/src/cc65/stmt.c index 9d7b1e74c..64ab61b79 100644 --- a/src/cc65/stmt.c +++ b/src/cc65/stmt.c @@ -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; diff --git a/src/cc65/testexpr.c b/src/cc65/testexpr.c new file mode 100644 index 000000000..5defef988 --- /dev/null +++ b/src/cc65/testexpr.c @@ -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; +} + + + + diff --git a/src/cc65/testexpr.h b/src/cc65/testexpr.h new file mode 100644 index 000000000..20585417a --- /dev/null +++ b/src/cc65/testexpr.h @@ -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 + + + +