ref: 71939a82ccc505b0baa990d7fe17e7085d0ab8fc
parent: 2917cb1d17b30e599f3934fcf2878f3174d63871
author: Ori Bernstein <[email protected]>
date: Sat Sep 7 14: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);