diff options
-rw-r--r-- | decl.c | 25 | ||||
-rw-r--r-- | doc/c23.md | 6 | ||||
-rw-r--r-- | init.c | 10 | ||||
-rw-r--r-- | test/initializer-empty-struct.c | 5 | ||||
-rw-r--r-- | test/initializer-empty-struct.qbe | 8 | ||||
-rw-r--r-- | test/initializer-empty.c | 4 | ||||
-rw-r--r-- | test/initializer-empty.qbe | 8 |
7 files changed, 51 insertions, 15 deletions
@@ -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) @@ -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 @@ -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 +} |