aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Forney <mforney@mforney.org>2024-03-23 14:15:00 -0700
committerMichael Forney <mforney@mforney.org>2024-03-23 14:15:00 -0700
commit2e3ecc7000138622a528eef7681bfdd8ca0bc3c5 (patch)
tree86331119dbf3a15df98ea54701cedd6a8be63026
parent52d9d1e21c38d33a0dcab8021751743ac180766b (diff)
expr: Keep track of storage duration of compound literals
-rw-r--r--cc.h14
-rw-r--r--decl.c2
-rw-r--r--eval.c16
-rw-r--r--expr.c15
-rw-r--r--qbe.c2
5 files changed, 25 insertions, 24 deletions
diff --git a/cc.h b/cc.h
index bd05deb..b75d511 100644
--- a/cc.h
+++ b/cc.h
@@ -247,6 +247,12 @@ enum linkage {
LINKEXTERN,
};
+enum storageduration {
+ SDSTATIC,
+ SDTHREAD,
+ SDAUTO,
+};
+
enum builtinkind {
BUILTINALLOCA,
BUILTINCONSTANTP,
@@ -360,6 +366,7 @@ struct expr {
struct bitfield bits;
} bitfield;
struct {
+ enum storageduration storage;
struct init *init;
} compound;
struct {
@@ -502,12 +509,7 @@ struct expr *exprpromote(struct expr *);
/* eval */
-enum evalkind {
- EVALARITH, /* arithmetic constant expression */
- EVALINIT, /* initializer constant expression */
-};
-
-struct expr *eval(struct expr *, enum evalkind);
+struct expr *eval(struct expr *);
/* init */
diff --git a/decl.c b/decl.c
index fc48dc9..34e61f4 100644
--- a/decl.c
+++ b/decl.c
@@ -625,7 +625,7 @@ declaratortypes(struct scope *s, struct list *result, char **name, bool allowabs
error(&tok.loc, "VLAs are not yet supported");
t = mkarraytype(NULL, tq, 0);
if (tok.kind != TRBRACK) {
- e = eval(assignexpr(s), EVALARITH);
+ e = eval(assignexpr(s));
if (e->kind != EXPRCONST || !(e->type->prop & PROPINT))
error(&tok.loc, "VLAs are not yet supported");
i = e->u.constant.u;
diff --git a/eval.c b/eval.c
index 9b6b33c..e1be25e 100644
--- a/eval.c
+++ b/eval.c
@@ -101,7 +101,7 @@ binary(struct expr *expr, enum tokenkind op, struct expr *l, struct expr *r)
#undef S
struct expr *
-eval(struct expr *expr, enum evalkind kind)
+eval(struct expr *expr)
{
struct expr *l, *r, *c;
struct decl *d;
@@ -116,7 +116,7 @@ eval(struct expr *expr, enum evalkind kind)
expr->u.constant.u = intconstvalue(expr->u.ident.decl->value);
break;
case EXPRCOMPOUND:
- if (kind != EVALINIT)
+ if (expr->u.compound.storage != SDSTATIC)
break;
d = mkdecl(DECLOBJECT, t, expr->qual, LINKNONE);
d->value = mkglobal(NULL, true);
@@ -125,17 +125,15 @@ eval(struct expr *expr, enum evalkind kind)
expr->u.ident.decl = d;
break;
case EXPRUNARY:
- l = eval(expr->base, kind);
+ l = eval(expr->base);
switch (expr->op) {
case TBAND:
switch (l->kind) {
case EXPRUNARY:
if (l->op == TMUL)
- expr = eval(l->base, kind);
+ expr = eval(l->base);
break;
case EXPRSTRING:
- if (kind != EVALINIT)
- break;
l->u.ident.decl = stringdecl(l);
l->kind = EXPRIDENT;
expr->base = l;
@@ -152,7 +150,7 @@ eval(struct expr *expr, enum evalkind kind)
}
break;
case EXPRCAST:
- l = eval(expr->base, kind);
+ l = eval(expr->base);
if (l->kind == EXPRCONST) {
expr->kind = EXPRCONST;
if (l->type->prop & PROPINT && t->prop & PROPFLOAT) {
@@ -186,8 +184,8 @@ eval(struct expr *expr, enum evalkind kind)
}
break;
case EXPRBINARY:
- l = eval(expr->u.binary.l, kind);
- r = eval(expr->u.binary.r, kind);
+ l = eval(expr->u.binary.l);
+ r = eval(expr->u.binary.r);
expr->u.binary.l = l;
expr->u.binary.r = r;
switch (expr->op) {
diff --git a/expr.c b/expr.c
index 9a168de..d9fb9b6 100644
--- a/expr.c
+++ b/expr.c
@@ -271,11 +271,11 @@ mkbinaryexpr(struct location *loc, enum tokenkind op, struct expr *l, struct exp
e = l, l = r, r = e;
if (l->type->kind != TYPEPOINTER)
error(loc, "invalid operands to '%s' operator", tokstr[op]);
- if (nullpointer(eval(r, EVALARITH))) {
+ if (nullpointer(eval(r))) {
r = exprconvert(r, l->type);
break;
}
- if (nullpointer(eval(l, EVALARITH))) {
+ if (nullpointer(eval(l))) {
l = exprconvert(l, r->type);
break;
}
@@ -781,7 +781,7 @@ builtinfunc(struct scope *s, enum builtinkind kind)
e->u.builtin.kind = BUILTINALLOCA;
break;
case BUILTINCONSTANTP:
- e = mkconstexpr(&typeint, eval(condexpr(s), EVALARITH)->kind == EXPRCONST);
+ e = mkconstexpr(&typeint, eval(condexpr(s))->kind == EXPRCONST);
break;
case BUILTINEXPECT:
/* just a no-op for now */
@@ -1126,6 +1126,7 @@ castexpr(struct scope *s)
e->qual = tq;
e->lvalue = true;
e->u.compound.init = parseinit(s, t);
+ e->u.compound.storage = s == &filescope ? SDSTATIC : SDAUTO;
e = postfixexpr(s, decay(e));
goto done;
}
@@ -1216,8 +1217,8 @@ condexpr(struct scope *s)
} else if (lt == &typevoid && rt == &typevoid) {
t = &typevoid;
} else {
- l = eval(l, EVALARITH);
- r = eval(r, EVALARITH);
+ l = eval(l);
+ r = eval(r);
if (nullpointer(l) && rt->kind == TYPEPOINTER) {
t = rt;
} else if (nullpointer(r) && lt->kind == TYPEPOINTER) {
@@ -1239,7 +1240,7 @@ condexpr(struct scope *s)
error(&tok.loc, "invalid operands to conditional operator");
}
}
- e = eval(e, EVALARITH);
+ e = eval(e);
if (e->kind == EXPRCONST && e->type->prop & PROPINT)
return exprconvert(e->u.constant.u ? l : r, t);
e = mkexpr(EXPRCOND, t, e);
@@ -1251,7 +1252,7 @@ condexpr(struct scope *s)
struct expr *
evalexpr(struct scope *s)
{
- return eval(condexpr(s), EVALARITH);
+ return eval(condexpr(s));
}
unsigned long long
diff --git a/qbe.c b/qbe.c
index 08d10b5..60e911f 100644
--- a/qbe.c
+++ b/qbe.c
@@ -1323,7 +1323,7 @@ emitdata(struct decl *d, struct init *init)
align = d->u.obj.align;
for (cur = init; cur; cur = cur->next)
- cur->expr = eval(cur->expr, EVALINIT);
+ cur->expr = eval(cur->expr);
if (d->linkage == LINKEXTERN)
fputs("export ", stdout);
fputs("data ", stdout);