diff options
author | Ori Bernstein <ori@eigenstate.org> | 2019-09-07 18:25:04 -0700 |
---|---|---|
committer | Ori Bernstein <ori@eigenstate.org> | 2019-09-07 18:25:04 -0700 |
commit | 71939a82ccc505b0baa990d7fe17e7085d0ab8fc (patch) | |
tree | 67b8995b14a4c78c5c2b9f87bdd2e9bfe1cf7e1d /sys/src/cmd/cc | |
parent | 2917cb1d17b30e599f3934fcf2878f3174d63871 (diff) |
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
Diffstat (limited to 'sys/src/cmd/cc')
-rw-r--r-- | sys/src/cmd/cc/dcl.c | 40 |
1 files changed, 20 insertions, 20 deletions
diff --git a/sys/src/cmd/cc/dcl.c b/sys/src/cmd/cc/dcl.c index 4e6fd7775..03410bcb9 100644 --- a/sys/src/cmd/cc/dcl.c +++ b/sys/src/cmd/cc/dcl.c @@ -373,35 +373,35 @@ init1(Sym *s, Type *t, long o, int exflag) 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); |