aboutsummaryrefslogtreecommitdiffhomepage
path: root/eval.c
diff options
context:
space:
mode:
Diffstat (limited to 'eval.c')
-rw-r--r--eval.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/eval.c b/eval.c
index 2a2de6d..cfd8d2b 100644
--- a/eval.c
+++ b/eval.c
@@ -135,6 +135,8 @@ isglobsym(const struct expr *ex)
static bool
isaddrconst(struct expr *ex)
{
+ if (ex->t == ECAST)
+ return isaddrconst(ex->sub) || (eval(ex->sub, EVSTATICINI) && ex->sub->t == ENUMLIT);
if (ex->t == EADDROF && isglobsym(ex->sub))
return 1;
if (isglobsym(ex) && in_range(ex->ty.t, TYARRAY, TYFUNC))
@@ -253,8 +255,16 @@ eval(struct expr *ex, enum evalmode mode)
if (mode <= EVINTCONST) return isint(ex->ty);
return 1;
}
- if (mode == EVSTATICINI && isaddrconst(ex))
+ if (ex->t == ESTRLIT) return 1;
+ if (mode == EVSTATICINI && isaddrconst(ex)) {
+ struct expr *e = ex;
+ while (e->t == ECAST) e = e->sub;
+ if (e != ex) {
+ e->ty = ex->ty;
+ *ex = *e;
+ }
return 1;
+ }
if (isunop(ex->t)) return unop(ex, mode) && eval(ex, mode);
if (isbinop(ex->t)) return binop(ex, mode) && eval(ex, mode);
if (ex->t == ESEQ) {
@@ -263,12 +273,18 @@ eval(struct expr *ex, enum evalmode mode)
return eval(ex, mode);
}
if (ex->t == ECOND) {
- if (!eval(&ex->sub[0], mode)) return 0;
+ if (!eval(&ex->sub[0], mode) || ex->sub[0].t != ENUMLIT) return 0;
if (!eval(&ex->sub[1], mode)) return 0;
if (!eval(&ex->sub[2], mode)) return 0;
*ex = ex->sub[!ex->sub[0].u + 1];
return eval(ex, mode);
}
+ if (ex->t == EINIT) {
+ for (struct initval *v = ex->init->vals; v; v = v->next) {
+ if (!eval(&v->ex, mode)) return 0;
+ }
+ return 1;
+ }
return 0;
}