Module Name: src Committed By: rillig Date: Thu Mar 25 01:42:53 UTC 2021
Modified Files: src/tests/usr.bin/xlint/lint1: d_struct_init_nested.c d_struct_init_nested.exp src/usr.bin/xlint/lint1: init.c Log Message: lint: fix C99 initialization with expression of type 'struct' This has been a long-standing limitation of lint. Now it is almost ready for C99, see the list of "major changes" in the foreword of C99. One known remaining bug in the area of initialization is designators with several levels, such as '.member[2].member.member'. Oh, and designators for arrays are only supported in the parser but not in the type checker. There's still some work to do. To generate a diff of this commit: cvs rdiff -u -r1.5 -r1.6 src/tests/usr.bin/xlint/lint1/d_struct_init_nested.c cvs rdiff -u -r1.7 -r1.8 \ src/tests/usr.bin/xlint/lint1/d_struct_init_nested.exp cvs rdiff -u -r1.117 -r1.118 src/usr.bin/xlint/lint1/init.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/tests/usr.bin/xlint/lint1/d_struct_init_nested.c diff -u src/tests/usr.bin/xlint/lint1/d_struct_init_nested.c:1.5 src/tests/usr.bin/xlint/lint1/d_struct_init_nested.c:1.6 --- src/tests/usr.bin/xlint/lint1/d_struct_init_nested.c:1.5 Thu Mar 18 20:58:02 2021 +++ src/tests/usr.bin/xlint/lint1/d_struct_init_nested.c Thu Mar 25 01:42:53 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: d_struct_init_nested.c,v 1.5 2021/03/18 20:58:02 rillig Exp $ */ +/* $NetBSD: d_struct_init_nested.c,v 1.6 2021/03/25 01:42:53 rillig Exp $ */ # 3 "d_struct_init_nested.c" /* @@ -32,9 +32,9 @@ funcOuter3Inner1(void) }; struct Outer3Inner1 o3i1 = { O1C, - inner, /*FIXME*//* expect: 185 */ + inner, O3C - }; /*FIXME*//* expect: 172 */ + }; return o3i1.o1; } @@ -59,8 +59,22 @@ funcOuter3Inner2(void) }; struct Outer3Inner2 o3i2 = { O1C, - inner, /*FIXME*//* expect: 185 */ + inner, O3C - }; /*FIXME*//* expect: 210 */ + }; return o3i2.o1; } + +/* + * For static storage duration, each initializer expression must be a constant + * expression. + */ +struct Inner2 inner = { + I1C, + I2C +}; +struct Outer3Inner2 o3i2 = { + O1C, + inner, /* expect: non-constant initializer */ + O3C +}; Index: src/tests/usr.bin/xlint/lint1/d_struct_init_nested.exp diff -u src/tests/usr.bin/xlint/lint1/d_struct_init_nested.exp:1.7 src/tests/usr.bin/xlint/lint1/d_struct_init_nested.exp:1.8 --- src/tests/usr.bin/xlint/lint1/d_struct_init_nested.exp:1.7 Sun Mar 21 20:44:59 2021 +++ src/tests/usr.bin/xlint/lint1/d_struct_init_nested.exp Thu Mar 25 01:42:53 2021 @@ -1,4 +1 @@ -d_struct_init_nested.c(35): error: cannot initialize 'enum I1' from 'struct Inner1' [185] -d_struct_init_nested.c(37): error: too many struct/union initializers [172] -d_struct_init_nested.c(62): error: cannot initialize 'enum I1' from 'struct Inner2' [185] -d_struct_init_nested.c(64): warning: enum type mismatch between 'enum I2' and 'enum O3' in initialization [210] +d_struct_init_nested.c(78): error: non-constant initializer [177] Index: src/usr.bin/xlint/lint1/init.c diff -u src/usr.bin/xlint/lint1/init.c:1.117 src/usr.bin/xlint/lint1/init.c:1.118 --- src/usr.bin/xlint/lint1/init.c:1.117 Thu Mar 25 00:48:58 2021 +++ src/usr.bin/xlint/lint1/init.c Thu Mar 25 01:42:53 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: init.c,v 1.117 2021/03/25 00:48:58 rillig Exp $ */ +/* $NetBSD: init.c,v 1.118 2021/03/25 01:42:53 rillig Exp $ */ /* * Copyright (c) 1994, 1995 Jochen Pohl @@ -37,7 +37,7 @@ #include <sys/cdefs.h> #if defined(__RCSID) && !defined(lint) -__RCSID("$NetBSD: init.c,v 1.117 2021/03/25 00:48:58 rillig Exp $"); +__RCSID("$NetBSD: init.c,v 1.118 2021/03/25 01:42:53 rillig Exp $"); #endif #include <stdlib.h> @@ -382,7 +382,7 @@ begin_initialization(sym_t *sym) { struct initialization *curr_init; - debug_step("begin initialization"); + debug_step("begin initialization of '%s'", type_name(sym->s_type)); curr_init = xcalloc(1, sizeof *curr_init); curr_init->next = init; init = curr_init; @@ -858,7 +858,7 @@ initstack_next_brace(void) } static void -initstack_next_nobrace(void) +initstack_next_nobrace(tnode_t *tn) { debug_enter(); @@ -871,17 +871,19 @@ initstack_next_nobrace(void) if (!initerr) check_too_many_initializers(); - /* - * Make sure an entry with a scalar type is at the top of the stack. - * - * FIXME: Since C99, an initializer for an object with automatic - * storage need not be a constant expression anymore. It is - * perfectly fine to initialize a struct with a struct expression, - * see d_struct_init_nested.c for a demonstration. - */ while (!initerr) { - if ((initstk->i_type != NULL && - is_scalar(initstk->i_type->t_tspec))) + initstack_element *istk = initstk; + + if (tn->tn_type->t_tspec == STRUCT && + istk->i_type == tn->tn_type && + istk->i_enclosing != NULL && + istk->i_enclosing->i_enclosing != NULL) { + istk->i_brace = false; + istk->i_remaining = 1; /* the struct itself */ + break; + } + + if ((istk->i_type != NULL && is_scalar(istk->i_type->t_tspec))) break; initstack_push(); } @@ -1010,8 +1012,6 @@ check_init_expr(tnode_t *tn, scl_t sclas lt = ln->tn_type->t_tspec; rt = tn->tn_type->t_tspec; - lint_assert(is_scalar(lt)); /* at least before C99 */ - debug_step("typeok '%s', '%s'", type_name(ln->tn_type), type_name(tn->tn_type)); if (!typeok(INIT, 0, ln, tn)) @@ -1062,7 +1062,7 @@ init_using_expr(tnode_t *tn) goto done_initstack; } - initstack_next_nobrace(); + initstack_next_nobrace(tn); if (initerr || tn == NULL) goto done_initstack;