diff options
author | Michael Forney <mforney@mforney.org> | 2024-03-16 00:43:43 -0700 |
---|---|---|
committer | Michael Forney <mforney@mforney.org> | 2024-03-16 00:45:04 -0700 |
commit | ad769cfc78bea044ac4b2f19fe5a0ed79fc423a5 (patch) | |
tree | f1fc035ab64346d17eb6aa5973e59bef1303a255 | |
parent | e96df56b734d0a2619e7690c60a5472449d086c1 (diff) |
Fix C23 empty initializers
These should should act as zero initializers, but since init==NULL
was used to mean both "no initializer" and "empty initializer",
empty initializers weren't zero-initializing the variable.
-rw-r--r-- | cc.h | 2 | ||||
-rw-r--r-- | decl.c | 5 | ||||
-rw-r--r-- | qbe.c | 8 | ||||
-rw-r--r-- | test/initializer-empty-struct.qbe | 3 | ||||
-rw-r--r-- | test/initializer-empty.qbe | 1 |
5 files changed, 13 insertions, 6 deletions
@@ -542,7 +542,7 @@ void funcjnz(struct func *, struct value *, struct type *, struct block *, struc void funcret(struct func *, struct value *); struct gotolabel *funcgoto(struct func *, char *); void funcswitch(struct func *, struct value *, struct switchcases *, struct block *); -void funcinit(struct func *, struct decl *, struct init *); +void funcinit(struct func *, struct decl *, struct init *, _Bool); void emitfunc(struct func *, _Bool); void emitdata(struct decl *, struct init *); @@ -890,6 +890,7 @@ decl(struct scope *s, struct func *f) enum storageclass sc; enum funcspec fs; struct init *init; + bool hasinit; struct param *p; char *name, *asmname; int allowfunc = !f; @@ -952,12 +953,14 @@ decl(struct scope *s, struct func *f) if (d->u.obj.align < align) d->u.obj.align = align; init = NULL; + hasinit = false; if (consume(TASSIGN)) { if (f && d->linkage != LINKNONE) error(&tok.loc, "object '%s' with block scope and %s linkage cannot have initializer", name, d->linkage == LINKEXTERN ? "external" : "internal"); if (d->defined) error(&tok.loc, "object '%s' redefined", name); init = parseinit(s, d->type); + hasinit = true; } else if (d->linkage != LINKNONE) { if (!(sc & SCEXTERN) && !d->defined && !d->u.obj.tentative.next) listinsert(tentativedefns.prev, &d->u.obj.tentative); @@ -966,7 +969,7 @@ decl(struct scope *s, struct func *f) if (d->linkage != LINKNONE || sc & SCSTATIC) emitdata(d, init); else - funcinit(f, d, init); + funcinit(f, d, init, hasinit); d->defined = true; if (d->u.obj.tentative.next) listremove(&d->u.obj.tentative); @@ -498,7 +498,7 @@ mkfunc(struct decl *decl, char *name, struct type *t, struct scope *s) d->value = p->value; } else { v = typecompatible(p->type, pt) ? p->value : convert(f, pt, p->type, p->value); - funcinit(f, d, NULL); + funcalloc(f, d); funcstore(f, p->type, QUALNONE, (struct lvalue){d->value}, v); } scopeputdecl(s, p->name, d); @@ -640,7 +640,7 @@ funclval(struct func *f, struct expr *e) break; case EXPRCOMPOUND: d = mkdecl(DECLOBJECT, e->type, e->qual, LINKNONE); - funcinit(f, d, e->u.compound.init); + funcinit(f, d, e->u.compound.init, true); lval.addr = d->value; break; case EXPRUNARY: @@ -931,7 +931,7 @@ zero(struct func *func, struct value *addr, int align, unsigned long long offset } void -funcinit(struct func *func, struct decl *d, struct init *init) +funcinit(struct func *func, struct decl *d, struct init *init, bool hasinit) { struct lvalue dst; struct value *src, *v; @@ -939,7 +939,7 @@ funcinit(struct func *func, struct decl *d, struct init *init) size_t i, w; funcalloc(func, d); - if (!init) + if (!hasinit) return; for (; init; init = init->next) { zero(func, d->value, d->type->align, offset, init->start); diff --git a/test/initializer-empty-struct.qbe b/test/initializer-empty-struct.qbe index 9bbfb34..400f504 100644 --- a/test/initializer-empty-struct.qbe +++ b/test/initializer-empty-struct.qbe @@ -4,5 +4,8 @@ function $f() { @start.1 %.1 =l alloc8 16 @body.2 + storel 0, %.1 + %.2 =l add %.1, 8 + storel 0, %.2 ret } diff --git a/test/initializer-empty.qbe b/test/initializer-empty.qbe index 2ed8249..f3358bd 100644 --- a/test/initializer-empty.qbe +++ b/test/initializer-empty.qbe @@ -4,5 +4,6 @@ function $f() { @start.1 %.1 =l alloc4 4 @body.2 + storew 0, %.1 ret } |