aboutsummaryrefslogtreecommitdiffhomepage
path: root/c/eval.c
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2026-03-09 10:24:39 +0100
committerlemon <lsof@mailbox.org>2026-03-09 10:24:39 +0100
commit1529b5221389c75371d0f3f181957a77a158a53c (patch)
tree89f2c9893c38fc74a4ed08c11c7d20c894bcf7b5 /c/eval.c
parent9f1e1fa5d89b0cd1ae5bef585eadd97870994344 (diff)
c: relax constexpr constraints, fix alignof
- Allow short-circuiting of constant logical expressions where the unevaluated operand is not a constant expression (`1 || 0/0`) - Allow constant integer expressions that evaluate to zero to be used as null pointer constants (GNU extension). + According to the standard, `int *x = 5*0;` should be rejected. But compilers evaluate `5*0 -> 0` and allow it as if a null pointer literal.
Diffstat (limited to 'c/eval.c')
-rw-r--r--c/eval.c35
1 files changed, 23 insertions, 12 deletions
diff --git a/c/eval.c b/c/eval.c
index e2d67d7..839ff7a 100644
--- a/c/eval.c
+++ b/c/eval.c
@@ -215,15 +215,16 @@ binop(struct expr *ex, enum evalmode mode)
if (ex->ty.t == TYPTR) mode = EVFOLD;
if (!eval(lhs, mode)) return 0;
- if (!eval(rhs, mode)) return 0;
if (in_range(ex->t, EADD, ESHR))
oty = ex->ty;
else
oty = cvtarith(lhs->ty, rhs->ty);
- if (!numcast(oty, lhs, lhs)) return 0;
- if (!numcast(oty, rhs, rhs)) return 0;
flt = isflt(oty);
sgn = issigned(oty);
+ if (ex->t != ELOGAND && ex->t != ELOGIOR) {
+ if (!numcast(oty, lhs, lhs)) return 0;
+ if (!eval(rhs, mode) || !numcast(oty, rhs, rhs)) return 0;
+ }
switch (ex->t) {
#define ef else if
case EADD: if (flt) lhs->f += rhs->f;
@@ -264,14 +265,6 @@ binop(struct expr *ex, enum evalmode mode)
ef (sgn) lhs->i >>= rhs->i;
else lhs->u >>= rhs->u;
break;
- case ELOGAND: if (flt) t = lhs->f && rhs->f;
- else t = lhs->u && rhs->u;
- lhs->u = t;
- break;
- case ELOGIOR: if (flt) t = lhs->f || rhs->f;
- else t = lhs->u || rhs->u;
- lhs->u = t;
- break;
case EEQU: if (flt) t = lhs->f == rhs->f;
else t = lhs->u == rhs->u;
lhs->u = t;
@@ -300,12 +293,30 @@ binop(struct expr *ex, enum evalmode mode)
else t = lhs->u >= rhs->u;
lhs->u = t;
break;
+ case ELOGAND: if (flt) t = lhs->f; else t = lhs->u;
+ if (t) {
+ if (!eval(rhs, mode) || !numcast(oty, rhs, rhs)) return 0;
+ if (flt) t = t && lhs->f;
+ else t = t && lhs->u;
+ }
+ lhs->u = t;
+ break;
+ case ELOGIOR: if (flt) t = lhs->f; else t = lhs->u;
+ if (!t) {
+ if (!eval(rhs, mode) || !numcast(oty, rhs, rhs)) return 0;
+ if (flt) t = t || lhs->f;
+ else t = t || lhs->u;
+ }
+ lhs->u = t;
+ break;
default: return 0;
#undef ef
}
- if (!in_range(ex->t, EADD, ESHR))
+ if (!in_range(ex->t, EADD, ESHR)) {
+ lhs->t = ENUMLIT;
lhs->ty = mktype(TYINT);
+ }
return numcast(ex->ty, ex, lhs);
}