Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.bin/xlint/lint1 lint: fix C99 initialization with expres...



details:   https://anonhg.NetBSD.org/src/rev/864df064c096
branches:  trunk
changeset: 1019914:864df064c096
user:      rillig <rillig%NetBSD.org@localhost>
date:      Thu Mar 25 01:42:53 2021 +0000

description:
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.

diffstat:

 tests/usr.bin/xlint/lint1/d_struct_init_nested.c   |  24 ++++++++++++---
 tests/usr.bin/xlint/lint1/d_struct_init_nested.exp |   5 +--
 usr.bin/xlint/lint1/init.c                         |  34 +++++++++++-----------
 3 files changed, 37 insertions(+), 26 deletions(-)

diffs (139 lines):

diff -r dc95e2b5528e -r 864df064c096 tests/usr.bin/xlint/lint1/d_struct_init_nested.c
--- a/tests/usr.bin/xlint/lint1/d_struct_init_nested.c  Thu Mar 25 00:48:58 2021 +0000
+++ b/tests/usr.bin/xlint/lint1/d_struct_init_nested.c  Thu Mar 25 01:42:53 2021 +0000
@@ -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 @@
        };
        struct Outer3Inner1 o3i1 = {
            O1C,
-           inner,              /*FIXME*//* expect: 185 */
+           inner,
            O3C
-       };                      /*FIXME*//* expect: 172 */
+       };
 
        return o3i1.o1;
 }
@@ -59,8 +59,22 @@
        };
        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
+};
diff -r dc95e2b5528e -r 864df064c096 tests/usr.bin/xlint/lint1/d_struct_init_nested.exp
--- a/tests/usr.bin/xlint/lint1/d_struct_init_nested.exp        Thu Mar 25 00:48:58 2021 +0000
+++ b/tests/usr.bin/xlint/lint1/d_struct_init_nested.exp        Thu Mar 25 01:42:53 2021 +0000
@@ -1,4 +1,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]
diff -r dc95e2b5528e -r 864df064c096 usr.bin/xlint/lint1/init.c
--- a/usr.bin/xlint/lint1/init.c        Thu Mar 25 00:48:58 2021 +0000
+++ b/usr.bin/xlint/lint1/init.c        Thu Mar 25 01:42:53 2021 +0000
@@ -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 @@
 {
        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 @@
 }
 
 static void
-initstack_next_nobrace(void)
+initstack_next_nobrace(tnode_t *tn)
 {
        debug_enter();
 
@@ -871,17 +871,19 @@
        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 @@
        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 @@
                goto done_initstack;
        }
 
-       initstack_next_nobrace();
+       initstack_next_nobrace(tn);
        if (initerr || tn == NULL)
                goto done_initstack;
 



Home | Main Index | Thread Index | Old Index