aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--decl.c25
-rw-r--r--doc/c23.md6
-rw-r--r--init.c10
-rw-r--r--test/initializer-empty-struct.c5
-rw-r--r--test/initializer-empty-struct.qbe8
-rw-r--r--test/initializer-empty.c4
-rw-r--r--test/initializer-empty.qbe8
7 files changed, 51 insertions, 15 deletions
diff --git a/decl.c b/decl.c
index d10e3b6..72a2dd8 100644
--- a/decl.c
+++ b/decl.c
@@ -947,26 +947,25 @@ decl(struct scope *s, struct func *f)
error(&tok.loc, "specified alignment of object '%s' is less strict than is required by type", name);
if (d->align < align)
d->align = align;
+ init = NULL;
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);
- } else {
- init = NULL;
- }
- if (init || d->linkage == LINKNONE) {
- if (d->linkage != LINKNONE || sc & SCSTATIC)
- emitdata(d, init);
- else
- funcinit(f, d, init);
- d->defined = true;
- if (d->tentative.next)
- listremove(&d->tentative);
- } else if (!(sc & SCEXTERN) && !d->defined && !d->tentative.next) {
- listinsert(tentativedefns.prev, &d->tentative);
+ } else if (d->linkage != LINKNONE) {
+ if (!(sc & SCEXTERN) && !d->defined && !d->tentative.next)
+ listinsert(tentativedefns.prev, &d->tentative);
+ break;
}
+ if (d->linkage != LINKNONE || sc & SCSTATIC)
+ emitdata(d, init);
+ else
+ funcinit(f, d, init);
+ d->defined = true;
+ if (d->tentative.next)
+ listremove(&d->tentative);
break;
case DECLFUNC:
if (align)
diff --git a/doc/c23.md b/doc/c23.md
index bc1acb0..f612677 100644
--- a/doc/c23.md
+++ b/doc/c23.md
@@ -35,8 +35,14 @@ a function definition that does not use that parameter.
C23 allows binary integer constants in addition to octal, decimal,
and hexadecimal, using syntax like `0b01101011`.
+## [N2900]: Consistent, warningless, and intuitive initialization with {}
+
+C23 allows empty initializers to initialize an object as if it had
+static storage duration.
+
[N2265]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2265.pdf
[N2418]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2418.pdf
[N2508]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2508.pdf
[N2510]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2510.pdf
[N2549]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2549.pdf
+[N2900]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2900.htm
diff --git a/init.c b/init.c
index 58bd89a..374ebff 100644
--- a/init.c
+++ b/init.c
@@ -216,7 +216,7 @@ parseinit(struct scope *s, struct type *t)
p.sub->iscur = false;
p.init = NULL;
p.last = &p.init;
- if (t->incomplete && !(t->kind == TYPEARRAY && t->u.array.length == 0))
+ if (t->incomplete && t->kind != TYPEARRAY)
error(&tok.loc, "initializer specified for incomplete type");
for (;;) {
if (p.cur) {
@@ -228,6 +228,11 @@ parseinit(struct scope *s, struct type *t)
focus(&p);
}
if (consume(TLBRACE)) {
+ if (consume(TRBRACE)){
+ if (p.sub->type->incomplete)
+ error(&tok.loc, "array of unknown size has empty initializer");
+ goto next;
+ }
if (p.cur == p.sub) {
if (p.cur->type->prop & PROPSCALAR)
error(&tok.loc, "nested braces around scalar initializer");
@@ -271,8 +276,9 @@ parseinit(struct scope *s, struct type *t)
bits = (struct bitfield){0};
initadd(&p, mkinit(p.sub->offset, p.sub->offset + p.sub->type->size, bits, expr));
for (;;) {
- if (p.sub->type->kind == TYPEARRAY && p.sub->type->incomplete)
+ if (p.sub->type->incomplete)
p.sub->type->incomplete = false;
+ next:
if (!p.cur)
return p.init;
if (tok.kind == TCOMMA) {
diff --git a/test/initializer-empty-struct.c b/test/initializer-empty-struct.c
new file mode 100644
index 0000000..01538f5
--- /dev/null
+++ b/test/initializer-empty-struct.c
@@ -0,0 +1,5 @@
+struct s {float x; long y;};
+struct s s = {};
+void f(void) {
+ struct s t = {};
+}
diff --git a/test/initializer-empty-struct.qbe b/test/initializer-empty-struct.qbe
new file mode 100644
index 0000000..9bbfb34
--- /dev/null
+++ b/test/initializer-empty-struct.qbe
@@ -0,0 +1,8 @@
+export data $s = align 8 { z 16 }
+export
+function $f() {
+@start.1
+ %.1 =l alloc8 16
+@body.2
+ ret
+}
diff --git a/test/initializer-empty.c b/test/initializer-empty.c
new file mode 100644
index 0000000..e3e444c
--- /dev/null
+++ b/test/initializer-empty.c
@@ -0,0 +1,4 @@
+int x = {};
+void f(void) {
+ int y = {};
+}
diff --git a/test/initializer-empty.qbe b/test/initializer-empty.qbe
new file mode 100644
index 0000000..2ed8249
--- /dev/null
+++ b/test/initializer-empty.qbe
@@ -0,0 +1,8 @@
+export data $x = align 4 { z 4 }
+export
+function $f() {
+@start.1
+ %.1 =l alloc4 4
+@body.2
+ ret
+}