code: plan9front

Download patch

ref: 71939a82ccc505b0baa990d7fe17e7085d0ab8fc
parent: 2917cb1d17b30e599f3934fcf2878f3174d63871
author: Ori Bernstein <ori@eigenstate.org>
date: Sat Sep 7 21:25:04 EDT 2019

Allow address expressions in ?c after int casts.

This fixes ocaml on non-x86 architectures, where we have code
that looks like:

	#define Fl_head ((uintptr_t)(&sentinel.first_field))

Without this change, we get an error about a non-constant
initializer. This change takes the checks for pointers and
makes them apply to all expressions. It also makes the checks
stricter, preventing the following from compiling to junk:

	int x;
	int y = 42;
	int *p = &x + y

--- a/sys/src/cmd/cc/dcl.c
+++ b/sys/src/cmd/cc/dcl.c
@@ -373,35 +373,35 @@
 			goto gext;
 		}
 		if(t->etype == TIND) {
-			while(a->op == OCAST) {
+			if(a->op == OCAST)
 				warn(a, "CAST in initialization ignored");
-				a = a->left;
-			}
-			if(!sametype(t, a->type)) {
+			if(!sametype(t, a->type))
 				diag(a, "initialization of incompatible pointers: %s\n%T and %T",
 					s->name, t, a->type);
-			}
-			switch(a->op) {
-			case OADDR:
-				a = a->left;
-				break;
-			case ONAME:
-			case OIND:
-				diag(a, "initializer is not a constant: %s", s->name);
-				return Z;
-			}
-			goto gext;
 		}
 
 		while(a->op == OCAST)
 			a = a->left;
-		if(a->op == OADDR) {
-			warn(a, "initialize pointer to an integer: %s", s->name);
+
+		switch(a->op) {
+		case OADDR:
+			if(t->etype != TIND)
+				warn(a, "initialize pointer to an integer: %s", s->name);
 			a = a->left;
-			goto gext;
+			break;
+		case OADD:
+			/*
+			 * Constants will be folded before this point, which just leaves offsets
+			 * from names.
+			 */
+			l = a->left;
+			r = a->right;
+			if(l->op == OADDR && r->op == OCONST || r->op == OADDR && l->op == OCONST)
+				break;
+		default:
+			diag(a, "initializer is not a constant: %s", s->name);
+			return Z;
 		}
-		diag(a, "initializer is not a constant: %s", s->name);
-		return Z;
 
 	gext:
 		gextern(s, a, o, t->width);