shithub: scc

Download patch

ref: 3394d4da4e02f25e0ffbafca52f7a41c49fd6ef0
parent: 6e021a04133c17cc9510a71ffd0cff2be70d7b35
author: Roberto E. Vargas Caballero <[email protected]>
date: Fri Apr 11 14:09:55 EDT 2014

Check types in assigment

Not all the types are compatible in assigment, so a check is needed
before the assigment.

--- a/expr.c
+++ b/expr.c
@@ -37,7 +37,37 @@
 	return bincode(op, np1->type, np1, np2);
 }
 
+/*
+ * Convert the second Node to the type of the first
+ */
 static Node *
+convert(Node *np1, Node *np2)
+{
+	Type *tp1, *tp2;
+	register uint8_t t1, t2;
+
+	tp1 = UNQUAL(np1->type), tp2 = UNQUAL(np2->type);
+	if (tp1 == tp2)
+		return np2;
+	t1 = tp1->op, t2 = tp2->op;
+
+	switch (t1) {
+	case ENUM: case INT: case FLOAT:
+		switch (t2) {
+		case INT: case FLOAT: case ENUM:
+			return castcode(np2, tp1);
+		}
+		break;
+	case PTR:
+		switch (t2) {
+		case ARY: case FTN:
+			/* TODO: take address of np2 */;
+		}
+	}
+	return NULL;
+}
+
+static Node *
 arithmetic(char op, Node *np1, Node *np2)
 {
 	char *err;
@@ -423,7 +453,8 @@
 static Node *
 assign(void)
 {
-	register Node *np = bit_or();
+	register Node *np1 = bit_or(), *np2;
+	char *err;
 
 	for (;;) {
 		register char op;
@@ -443,11 +474,23 @@
 		default:  goto return_np;
 		}
 		next();
-		/* TODO: cast types */
-		np = bincode(op, np->type, np, assign());
+		np2 = assign();
+		if (!np1->b.lvalue)
+			goto nolvalue;
+		if ((np2 = convert(np1, np2)) == NULL)
+			goto incompatibles;
+		np1 = bincode(op, np1->type, np1, np2);
 	}
 return_np:
-	return np;
+	return np1;
+
+nolvalue:
+	err = "lvalue required as left operand of assignment";
+	goto error;
+incompatibles:
+	err = "incompatible types when assigning";
+error:
+	error(err);
 }
 
 Node *