diff options
| author | 2026-03-09 10:24:39 +0100 | |
|---|---|---|
| committer | 2026-03-09 10:24:39 +0100 | |
| commit | 1529b5221389c75371d0f3f181957a77a158a53c (patch) | |
| tree | 89f2c9893c38fc74a4ed08c11c7d20c894bcf7b5 /c/eval.c | |
| parent | 9f1e1fa5d89b0cd1ae5bef585eadd97870994344 (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.c | 35 |
1 files changed, 23 insertions, 12 deletions
@@ -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); } |