From e47ed98aa76260babf1ff71023bf698a0475bc27 Mon Sep 17 00:00:00 2001 From: cuz Date: Tue, 2 Mar 2004 18:00:08 +0000 Subject: [PATCH] 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 --- src/cc65/expr.c | 67 +------------------- src/cc65/expr.h | 13 +--- src/cc65/make/gcc.mak | 1 + src/cc65/make/watcom.mak | 1 + src/cc65/stmt.c | 25 +++++--- src/cc65/testexpr.c | 130 +++++++++++++++++++++++++++++++++++++++ src/cc65/testexpr.h | 79 ++++++++++++++++++++++++ 7 files changed, 233 insertions(+), 83 deletions(-) create mode 100644 src/cc65/testexpr.c create mode 100644 src/cc65/testexpr.h 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"); + } + + /* Define the target for the first test */ + g_defcodelabel (Label1); - /* Total break only if both branches had a break. */ + /* 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 + + + + -- 2.39.5