From 7c25529f0a525ec4b4dcf40d847e2734c2349d5d Mon Sep 17 00:00:00 2001 From: lemon Date: Sat, 18 Apr 2026 16:10:11 +0200 Subject: c: fix some more static initializer edge cases --- src/c.c | 20 +++++++++++++------- test/22-decl.c | 6 ++++++ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/c.c b/src/c.c index 4517ab3..0aff669 100644 --- a/src/c.c +++ b/src/c.c @@ -265,7 +265,7 @@ redeclarationok(const Decl *old, Decl *new) { bool takeoldscls = 0; if (old->scls != new->scls) { - if (old->scls == SCSTATIC && (new->scls &~ SCEXTERN) == SCNONE && old->ty.t == TYFUNC && new->ty.t == TYFUNC) + if (old->scls == SCSTATIC && (new->scls &~ SCEXTERN) == SCNONE) takeoldscls = 1; else return 0; @@ -1449,16 +1449,19 @@ rodatarelocok(void) return !(ccopt.pie | ccopt.pic); } +static bool iniwriterec(CComp *cm, InitParser *ip, uint off, Expr *ex); + static void iniwrite(CComp *cm, InitParser *ip, uint off, uint bitsiz, uint bitoff, Type ty, Expr *ex) { - if (ex->ty.t == TYSTRUCT && ip->ev == EVSTATICINI) { + if (isagg(ex->ty) && ip->ev == EVSTATICINI) { assert(ty.bits == ex->ty.bits); + assert(ex->t != EINIT); for (uint i = 0, n = nmemb(ex->ty); i < n; ++i) { - uint suboff; - Type sub = membertype(&suboff, &bitsiz, &bitoff, ex->ty, i); - iniwrite(cm, ip, off + suboff, bitsiz, bitoff, sub, exprdup(cm, &mkexpr(EGETF, ex->span, sub, .sub = ex))); - } + uint suboff; + Type sub = membertype(&suboff, &bitsiz, &bitoff, ex->ty, i); + iniwrite(cm, ip, off + suboff, bitsiz, bitoff, sub, exprdup(cm, &mkexpr(EGETF, ex->span, sub, .sub = ex))); + } } else if (ip->ev == EVSTATICINI) { uchar *p; uint siz = typesize(ty); @@ -1812,8 +1815,11 @@ initializer(CComp *cm, Type *ty, enum evalmode ev, bool globl, iniwrite(cm, ip, 0, 0, 0, *ty, &ex); } else if (!initcheck(*ty, &ex)) { error(&ex.span, "cannot initialize '%ty' with expression of type '%ty'", *ty, ex.ty); + } else if (ex.t == EINIT) { + if (!iniwriterec(cm, ip, 0, &ex)) + goto CannotEval; } else { - if (ev && !eval(&ex, ev) && ev != EVFOLD) + if (ev && !eval(&ex, ev) && ev != EVFOLD) CannotEval: error(&ex.span, "cannot evaluate expression statically"); else if (ev == EVSTATICINI || !isscalar(*ty)) iniwrite(cm, ip, 0, 0, 0, *ty, &ex); diff --git a/test/22-decl.c b/test/22-decl.c index ddb1a57..a14b776 100644 --- a/test/22-decl.c +++ b/test/22-decl.c @@ -8,6 +8,12 @@ int a[]; int a[100]; int a[]; +static unsigned local; +extern unsigned local; + +typedef struct foo { char r; } foo_t; +static const foo_t T = ((foo_t) { 3 }); + int main() { } -- cgit v1.2.3