shithub: scc

Download patch

ref: 0dc51a53f9e0728586d36fe4f39402f91defe4e7
parent: 3bb913a9bf49c3144c5e7b7864d0a77ab6c67f63
author: Roberto E. Vargas Caballero <[email protected]>
date: Tue Apr 8 17:10:50 EDT 2014

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.

--- a/cc.h
+++ b/cc.h
@@ -204,6 +204,9 @@
 typedef struct node {
 	void (*code)(struct node *);
 	Type *type;
+	struct {
+		bool lvalue : 1;
+	} b;
 	union unode {
 		Symbol *sym;
 		Type *type;
--- a/expr.c
+++ b/expr.c
@@ -18,6 +18,7 @@
 		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 @@
 {
 	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 @@
 		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 @@
 	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 @@
 		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;