aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Forney <mforney@mforney.org>2024-03-16 00:43:43 -0700
committerMichael Forney <mforney@mforney.org>2024-03-16 00:45:04 -0700
commitad769cfc78bea044ac4b2f19fe5a0ed79fc423a5 (patch)
treef1fc035ab64346d17eb6aa5973e59bef1303a255
parente96df56b734d0a2619e7690c60a5472449d086c1 (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.h2
-rw-r--r--decl.c5
-rw-r--r--qbe.c8
-rw-r--r--test/initializer-empty-struct.qbe3
-rw-r--r--test/initializer-empty.qbe1
5 files changed, 13 insertions, 6 deletions
diff --git a/cc.h b/cc.h
index 860ca94..956e2e9 100644
--- a/cc.h
+++ b/cc.h
@@ -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 *);
diff --git a/decl.c b/decl.c
index 8ffc058..111c0e3 100644
--- a/decl.c
+++ b/decl.c
@@ -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);
diff --git a/qbe.c b/qbe.c
index cce245e..08d10b5 100644
--- a/qbe.c
+++ b/qbe.c
@@ -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
}