commit 0dc51a53f9e0728586d36fe4f39402f91defe4e7
parent 3bb913a9bf49c3144c5e7b7864d0a77ab6c67f63
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Tue, 8 Apr 2014 21:10:50 +0200
Add lvalue to Node
Some operations (assignment, increment, decrement, take address,
or content) can be only applied to lvalues, so it is important keep track
when a node is a lvalue or not.
Diffstat:
2 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/cc.h b/cc.h
@@ -204,6 +204,9 @@ extern void expect(uint8_t tok);
typedef struct node {
void (*code)(struct node *);
Type *type;
+ struct {
+ bool lvalue : 1;
+ } b;
union unode {
Symbol *sym;
Type *type;
diff --git a/expr.c b/expr.c
@@ -18,6 +18,7 @@ primary(void)
if ((sym = yylval.sym) == NULL)
error("'%s' undeclared", yytext);
np = node(emitsym, sym->type, SYM(sym), 0);
+ np->b.lvalue = 1;
next();
break;
case CONSTANT:
@@ -50,7 +51,7 @@ arithmetic(char op, Node *np1, Node *np2)
{
Node *naux;
Type *tp1, *tp2, *tp3;
- uint8_t t1, t2, taux;
+ uint8_t t1, t2, taux, lvalue = 0;
tp1 = UNQUAL(np1->type), tp2 = UNQUAL(np2->type);
t1 = tp1->op, t2 = tp2->op;
@@ -101,12 +102,15 @@ pointer:
np2 = bincode(OMUL, tp1,
castcode(np2, tp1),
sizeofcode(tp3));
+ lvalue = 1;
break;
default:
goto incorrect;
}
- return bincode(op, tp1, np1, np2);
+ np1 = bincode(op, tp1, np1, np2);
+ np1->b.lvalue = lvalue;
+ return np1;
nocomplete:
error("invalid use of indefined type");
@@ -145,7 +149,8 @@ incdec(Node *np, char op)
Type *tp;
char *err;
- /* TODO: Check against l-value */
+ if (!np->b.lvalue)
+ goto nolvalue;
tp = UNQUAL(np->type);
if (isconst(np->type->op))
goto const_mod;
@@ -155,11 +160,16 @@ incdec(Node *np, char op)
if (!tp->type->defined)
goto nocomplete;
case INT: case FLOAT:
- return unarycode(op, np->type, np);
+ np = unarycode(op, np->type, np);
+ np->b.lvalue = 0;
+ return np;
default:
goto bad_type;
}
+nolvalue:
+ err = "lvalue required in operation";
+ goto error;
nocomplete:
err = "invalid use of indefined type";
goto error;