scc

Simple C99 Compiler
Log | Files | Refs | README | LICENSE

commit 9e7c2e2a2707f5db37322bf67f7eccf778d42136
parent 104f6821fce36276746996377f2b78b631f2d368
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Mon, 14 Apr 2014 09:01:43 +0200

Fix comparisions

arithmetic operations can change the order of evaluations of its arguments,
but it is not the same for comparisions, because is not the same a > b than
b < a.
1

Diffstat:
expr.c | 70++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
1 file changed, 52 insertions(+), 18 deletions(-)

diff --git a/expr.c b/expr.c @@ -112,18 +112,6 @@ arithmetic(char op, Node *np1, Node *np2) case PTR: case ARY: pointer: switch (op) { - case OLT: case OGT: case OGE: - case OLE: case OEQ: case ONE: - if (t1 == ARY) - tp1 = mktype(tp1->type, PTR, NULL, 0); - else if (t1 != PTR) - goto incorrect; - if (t2 == ARY) - tp2 = mktype(tp2->type, PTR, NULL, 0); - else if (t2 != PTR) - goto incorrect; - /* FIX: result of comparisions is integer type */ - break; case OADD: case OSUB: tp3 = tp1->type; /* TODO: I think tp3 is not needed */ if (!tp1->defined) @@ -156,6 +144,56 @@ error: } static Node * +compare(char op, Node *np1, Node *np2) +{ + Type *tp1, *tp2; + uint8_t t1, t2; + + tp1 = UNQUAL(np1->type), tp2 = UNQUAL(np2->type); + t1 = tp1->op, t2 = tp2->op; + + switch (t1) { + case INT: + switch (t2) { + case INT: + if (tp1 != tp2) + intconv(&np1, &np2); + break; + case FLOAT: + np1 = castcode(np1, tp2); + break; + default: + goto incompatibles; + } + case FLOAT: + switch (t2) { + case INT: + np2 = castcode(np2, tp1); + break; + case FLOAT: + if (tp1 != tp2) + floatconv(&np1, &np2); + break; + defualt: + goto incompatibles; + } + case ARY: + case FTN: + /* TODO: cover this cases */ + case PTR: + if (tp1 != tp2) + goto incompatibles; + default: + goto incompatibles; + } + + return bincode(op, inttype, np1, np2); + +incompatibles: + error("incompatibles type in comparision"); +} + +static Node * array(Node *np1, Node *np2) { Type *tp; @@ -385,11 +423,7 @@ relational(void) default: return np; } next(); - /* - * FIX: This is incorrect because in relation - * we cannot change the order of the operands - */ - np = arithmetic(op, np, shift()); + np = compare(op, np, shift()); } } @@ -407,7 +441,7 @@ eq(void) default: return np; } next(); - np = arithmetic(op, np, relational()); + np = compare(op, np, relational()); } }