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: rewrite handling of initialization...



details:   https://anonhg.NetBSD.org/src/rev/f91a6e49e116
branches:  trunk
changeset: 954157:f91a6e49e116
user:      rillig <rillig%NetBSD.org@localhost>
date:      Tue Mar 30 14:25:28 2021 +0000

description:
lint: rewrite handling of initializations, fixing several bugs

The previous implementation had a wrong model of how initialization
happens in C99, its assertions failed in all kind of edge cases and it
was not possible to fix the remaining bugs one at a time without running
into even more obscure assertion failures.

The debug logging was detailed but did not help to clarify the
situation.  After about 20 failed attempts at fixing the small details I
decided to start all over and rewrite the initialization code from
scratch.  I left the low-level parts of handling designators, the code
that is independent of brace_level and the high-level parts of how the
parser calls into this module.  Everything else is completely new.

The concept of a brace level stays since that is how C99 describes
initialization.  The previous code could not handle multi-level
designations (see d_init_pop_member.c).  There are no more assertion
failures in the initialization code.

Some TODO comments have been left in the tests to keep the line numbers
the same in this commit.  These will be cleaned up in a follow-up
commit.

The new implementation does not handle initialization with "missing"
braces.  This is an edge case that both GCC and Clang warn about, so it
is not widely used.  If necessary, it may be added later.

The new implementation does not use any global variables in the vast
majority of the functions, to make all dependencies and possible
modifications obvious.

diffstat:

 tests/usr.bin/xlint/lint1/d_c99_bool.c                  |     4 +-
 tests/usr.bin/xlint/lint1/d_c99_init.c                  |    54 +-
 tests/usr.bin/xlint/lint1/d_c99_init.exp                |    13 +-
 tests/usr.bin/xlint/lint1/d_init_array_using_string.c   |     8 +-
 tests/usr.bin/xlint/lint1/d_init_array_using_string.exp |     6 +-
 tests/usr.bin/xlint/lint1/d_init_pop_member.c           |     8 +-
 tests/usr.bin/xlint/lint1/d_init_pop_member.exp         |     3 +-
 usr.bin/xlint/lint1/cgram.y                             |     6 +-
 usr.bin/xlint/lint1/decl.c                              |    12 +-
 usr.bin/xlint/lint1/externs1.h                          |     6 +-
 usr.bin/xlint/lint1/init.c                              |  1352 +++++---------
 11 files changed, 547 insertions(+), 925 deletions(-)

diffs (truncated from 2126 to 300 lines):

diff -r 2a3ae6bcaf06 -r f91a6e49e116 tests/usr.bin/xlint/lint1/d_c99_bool.c
--- a/tests/usr.bin/xlint/lint1/d_c99_bool.c    Tue Mar 30 13:41:46 2021 +0000
+++ b/tests/usr.bin/xlint/lint1/d_c99_bool.c    Tue Mar 30 14:25:28 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: d_c99_bool.c,v 1.6 2021/02/21 09:07:58 rillig Exp $    */
+/*     $NetBSD: d_c99_bool.c,v 1.7 2021/03/30 14:25:28 rillig Exp $    */
 # 3 "d_c99_bool.c"
 
 /*
@@ -9,7 +9,7 @@
  * invoke undefined behavior.
  */
 
-/* Below, each wrong assertion produces "negative array dimension" [20]. */
+/* Below, each false statement produces "negative array dimension" [20]. */
 
 int int_0_converts_to_false[(_Bool)0 ? -1 : 1];
 int int_0_converts_to_true_[(_Bool)0 ? 1 : -1];                        /* expect: 20 */
diff -r 2a3ae6bcaf06 -r f91a6e49e116 tests/usr.bin/xlint/lint1/d_c99_init.c
--- a/tests/usr.bin/xlint/lint1/d_c99_init.c    Tue Mar 30 13:41:46 2021 +0000
+++ b/tests/usr.bin/xlint/lint1/d_c99_init.c    Tue Mar 30 14:25:28 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: d_c99_init.c,v 1.23 2021/03/29 22:42:10 rillig Exp $   */
+/*     $NetBSD: d_c99_init.c,v 1.24 2021/03/30 14:25:28 rillig Exp $   */
 # 3 "d_c99_init.c"
 
 /*
@@ -23,7 +23,7 @@
 int scalar_with_too_many_initializers = { 3, 5 };      /* expect: 174 */
 
 
-// See init_using_expr, 'handing over to ASSIGN'.
+// See init_expr, 'handing over to ASSIGN'.
 void
 struct_initialization_via_assignment(any arg)
 {
@@ -32,13 +32,13 @@
 }
 
 
-// See init_using_expr, initstack_string.
+// See init_expr, initialization_init_array_using_string.
 char static_duration[] = "static duration";
 signed char static_duration_signed[] = "static duration";
 unsigned char static_duration_unsigned[] = "static duration";
 int static_duration_wchar[] = L"static duration";
 
-// See init_using_expr.
+// See init_expr.
 void
 initialization_by_braced_string(void)
 {
@@ -80,7 +80,7 @@
        444,                    /* expect: too many array initializers */
 };
 
-// See initstack_push, 'extending array of unknown size'.
+// See initialization_set_set_of_unknown_array.
 int array_of_unknown_size[] = {
        111,
        222,
@@ -135,8 +135,8 @@
 struct point point_with_mixed_designators = {
        .x = 3,
        4,
-       // FIXME: assertion failure '== ARRAY'
-       // 5,
+       /* TODO: remove me */
+       5,                      /* expect: too many struct/union initializers */
        .x = 3,
 };
 
@@ -211,8 +211,8 @@
  * structs.
  */
 struct geometry geometry = {
-       // FIXME: assertion "istk->i_type != NULL" failed in initstack_push
-       //.pentagons[0].points[4].x = 1,
+       /* TODO: remove me */
+       .pentagons[0].points[4].x = 1,
        .points[0][0][0] = { 0, 0 },
        .points[2][4][1] = {301, 302 },
        /* TODO: expect+1: array index 3 must be between 0 and 2 */
@@ -239,8 +239,8 @@
 };
 
 char message_with_suffix[] = {
-       "message",
-       /* expect+1: too many array initializers */
+       "message",              /* expect: illegal combination */
+       /* */
        '\n',
 };
 
@@ -279,7 +279,7 @@
        int a[3], b;
 } c99_6_7_8_p28_example5[] = {
        { 1 },
-       2,
+       2,                      /* XXX *//* expect: cannot initialize */
 };
 
 short c99_6_7_8_p29_example6a[4][3][2] = {
@@ -330,8 +330,8 @@
 }
 
 struct point unknown_member_name_beginning = {
-       // FIXME: assertion "bl->bl_type != NULL" failed in initialization_push
-       // .r = 5,
+       /* TODO: remove me */
+       .r = 5,                 /* expect: undefined struct/union member: r */
        .x = 4,
        .y = 3,
 };
@@ -354,13 +354,31 @@
 };
 
 union value unknown_union_member_name_first = {
-       // FIXME: assertion "bl->bl_type != NULL" failed in initialization_push
-       // .unknown_value = 4,
+       /* TODO: remove me */
+       .unknown_value = 4,     /* expect: undefined struct/union member */
        .int_value = 3,
 };
 
 union value unknown_union_member_name_second = {
        .int_value = 3,
-       // FIXME: assertion "bl->bl_type->t_tspec == ARRAY" failed in brace_level_extend_if_array_of_unknown_size
-       // .unknown_value = 4,
+       /* TODO: remove me */
+       .unknown_value = 4,     /* expect: undefined struct/union member */
+};
+
+struct point designators_with_subscript = {
+       [0] = 3,                /* expect: only for arrays */
+       .member[0][0].member = 4, /* expect: undefined struct/union member */
+       .x.y.z = 5,     /* intentionally not caught, see designator_look_up */
 };
+
+struct {
+       int : 16;
+} struct_with_only_unnamed_members = { /* expect: has no named members */
+       123,            /* expect: too many struct/union initializers */
+};
+
+union {
+       int : 16;
+} union_with_only_unnamed_members = {  /* expect: has no named members */
+       123,            /* expect: too many struct/union initializers */
+};
diff -r 2a3ae6bcaf06 -r f91a6e49e116 tests/usr.bin/xlint/lint1/d_c99_init.exp
--- a/tests/usr.bin/xlint/lint1/d_c99_init.exp  Tue Mar 30 13:41:46 2021 +0000
+++ b/tests/usr.bin/xlint/lint1/d_c99_init.exp  Tue Mar 30 14:25:28 2021 +0000
@@ -1,10 +1,21 @@
 d_c99_init.c(23): error: too many initializers [174]
 d_c99_init.c(63): error: cannot initialize 'pointer to const void' from 'struct any' [185]
 d_c99_init.c(80): error: too many array initializers, expected 3 [173]
+d_c99_init.c(139): error: too many struct/union initializers [172]
 d_c99_init.c(145): error: syntax error 'named member must only be used with struct/union' [249]
 d_c99_init.c(232): error: too many struct/union initializers [172]
 d_c99_init.c(238): warning: illegal combination of integer (char) and pointer (pointer to char) [183]
-d_c99_init.c(244): error: too many array initializers, expected 8 [173]
+d_c99_init.c(242): warning: illegal combination of integer (char) and pointer (pointer to char) [183]
+d_c99_init.c(282): error: cannot initialize 'struct <unnamed>' from 'int' [185]
 d_c99_init.c(324): error: duplicate case in switch: 0 [199]
+d_c99_init.c(334): error: undefined struct/union member: r [101]
 d_c99_init.c(341): error: undefined struct/union member: r [101]
 d_c99_init.c(348): error: undefined struct/union member: r [101]
+d_c99_init.c(358): error: undefined struct/union member: unknown_value [101]
+d_c99_init.c(365): error: undefined struct/union member: unknown_value [101]
+d_c99_init.c(369): error: syntax error 'designator '[...]' is only for arrays' [249]
+d_c99_init.c(370): error: undefined struct/union member: member [101]
+d_c99_init.c(376): warning: structure has no named members [65]
+d_c99_init.c(377): error: too many struct/union initializers [172]
+d_c99_init.c(382): warning: union has no named members [65]
+d_c99_init.c(383): error: too many struct/union initializers [172]
diff -r 2a3ae6bcaf06 -r f91a6e49e116 tests/usr.bin/xlint/lint1/d_init_array_using_string.c
--- a/tests/usr.bin/xlint/lint1/d_init_array_using_string.c     Tue Mar 30 13:41:46 2021 +0000
+++ b/tests/usr.bin/xlint/lint1/d_init_array_using_string.c     Tue Mar 30 14:25:28 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: d_init_array_using_string.c,v 1.2 2021/03/23 22:58:08 rillig Exp $     */
+/*     $NetBSD: d_init_array_using_string.c,v 1.3 2021/03/30 14:25:28 rillig Exp $     */
 # 3 "d_init_array_using_string.c"
 
 /*
@@ -56,8 +56,8 @@
        };
 
        struct cs_ws type_mismatch = {
-               L"",            /* expect: illegal combination */
-               "",             /* expect: illegal combination */
+               L"",            /* expect: cannot initialize */
+               "",             /* expect: cannot initialize */
        };
 
        struct cs_ws no_terminating_null = {
@@ -74,4 +74,6 @@
                { "" },
                { L"" },
        };
+       /* expect-3: illegal combination of integer (char) and pointer (pointer to char) */
+       /* expect-3: illegal combination of integer (int) and pointer (pointer to int) */
 }
diff -r 2a3ae6bcaf06 -r f91a6e49e116 tests/usr.bin/xlint/lint1/d_init_array_using_string.exp
--- a/tests/usr.bin/xlint/lint1/d_init_array_using_string.exp   Tue Mar 30 13:41:46 2021 +0000
+++ b/tests/usr.bin/xlint/lint1/d_init_array_using_string.exp   Tue Mar 30 14:25:28 2021 +0000
@@ -2,7 +2,9 @@
 d_init_array_using_string.c(17): warning: illegal pointer combination (pointer to const int) and (pointer to char), op = [124]
 d_init_array_using_string.c(34): warning: illegal pointer combination [184]
 d_init_array_using_string.c(35): warning: illegal pointer combination [184]
-d_init_array_using_string.c(59): warning: illegal combination of integer (char) and pointer (pointer to int) [183]
-d_init_array_using_string.c(60): warning: illegal combination of integer (char) and pointer (pointer to char) [183]
+d_init_array_using_string.c(59): error: cannot initialize 'array[10] of const char' from 'pointer to int' [185]
+d_init_array_using_string.c(60): error: cannot initialize 'array[10] of const int' from 'pointer to char' [185]
 d_init_array_using_string.c(69): warning: non-null byte ignored in string initializer [187]
 d_init_array_using_string.c(70): warning: non-null byte ignored in string initializer [187]
+d_init_array_using_string.c(74): warning: illegal combination of integer (char) and pointer (pointer to char) [183]
+d_init_array_using_string.c(75): warning: illegal combination of integer (int) and pointer (pointer to int) [183]
diff -r 2a3ae6bcaf06 -r f91a6e49e116 tests/usr.bin/xlint/lint1/d_init_pop_member.c
--- a/tests/usr.bin/xlint/lint1/d_init_pop_member.c     Tue Mar 30 13:41:46 2021 +0000
+++ b/tests/usr.bin/xlint/lint1/d_init_pop_member.c     Tue Mar 30 14:25:28 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: d_init_pop_member.c,v 1.6 2021/03/19 17:40:37 rillig Exp $     */
+/*     $NetBSD: d_init_pop_member.c,v 1.7 2021/03/30 14:25:28 rillig Exp $     */
 # 3 "d_init_pop_member.c"
 
 /*
@@ -35,7 +35,7 @@
 
 void func(void)
 {
-       struct state st = {
+       struct state st = {     /* expect: set but not used */
            .capital.mayor.hobbies.dancing = 1,
            /*
             * Since 2015-07-28:
@@ -45,7 +45,7 @@
             * Before init.c 1.52 from 2020-01-01:
             * wrong "warning: bit-field initializer does not fit [180]"
             */
-           .capital.mayor.favorite_color.green = 0xFF, /*FIXME*//* expect: 101 */
+           .capital.mayor.favorite_color.green = 0xFF,
            /*
             * Since 2015-07-28:
             * wrong "undefined struct/union member: capital [101]"
@@ -54,6 +54,6 @@
             * Before init.c 1.52 from 2020-01-01:
             * wrong "warning: bit-field initializer does not fit [180]"
             */
-           .capital.mayor.favorite_color.red = 0xFF, /*FIXME*//* expect: 101 */
+           .capital.mayor.favorite_color.red = 0xFF,
        };
 }
diff -r 2a3ae6bcaf06 -r f91a6e49e116 tests/usr.bin/xlint/lint1/d_init_pop_member.exp
--- a/tests/usr.bin/xlint/lint1/d_init_pop_member.exp   Tue Mar 30 13:41:46 2021 +0000
+++ b/tests/usr.bin/xlint/lint1/d_init_pop_member.exp   Tue Mar 30 14:25:28 2021 +0000
@@ -1,2 +1,1 @@
-d_init_pop_member.c(48): error: undefined struct/union member: capital [101]
-d_init_pop_member.c(57): error: undefined struct/union member: capital [101]
+d_init_pop_member.c(38): warning: st set but not used in function func [191]
diff -r 2a3ae6bcaf06 -r f91a6e49e116 usr.bin/xlint/lint1/cgram.y
--- a/usr.bin/xlint/lint1/cgram.y       Tue Mar 30 13:41:46 2021 +0000
+++ b/usr.bin/xlint/lint1/cgram.y       Tue Mar 30 14:25:28 2021 +0000
@@ -1,5 +1,5 @@
 %{
-/* $NetBSD: cgram.y,v 1.206 2021/03/29 20:39:18 rillig Exp $ */
+/* $NetBSD: cgram.y,v 1.207 2021/03/30 14:25:28 rillig Exp $ */
 
 /*
  * Copyright (c) 1996 Christopher G. Demetriou.  All Rights Reserved.
@@ -35,7 +35,7 @@
 
 #include <sys/cdefs.h>
 #if defined(__RCSID) && !defined(lint)
-__RCSID("$NetBSD: cgram.y,v 1.206 2021/03/29 20:39:18 rillig Exp $");
+__RCSID("$NetBSD: cgram.y,v 1.207 2021/03/30 14:25:28 rillig Exp $");
 #endif
 
 #include <limits.h>
@@ -1345,7 +1345,7 @@
 
 initializer:                   /* C99 6.7.8 "Initialization" */
          expr                          %prec T_COMMA {
-               init_using_expr($1);
+               init_expr($1);
          }
        | init_lbrace init_rbrace {
                /* XXX: Empty braces are not covered by C99 6.7.8. */
diff -r 2a3ae6bcaf06 -r f91a6e49e116 usr.bin/xlint/lint1/decl.c
--- a/usr.bin/xlint/lint1/decl.c        Tue Mar 30 13:41:46 2021 +0000
+++ b/usr.bin/xlint/lint1/decl.c        Tue Mar 30 14:25:28 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: decl.c,v 1.166 2021/03/27 22:13:55 rillig Exp $ */
+/* $NetBSD: decl.c,v 1.167 2021/03/30 14:25:28 rillig Exp $ */
 
 /*
  * Copyright (c) 1996 Christopher G. Demetriou.  All Rights Reserved.
@@ -38,7 +38,7 @@
 
 #include <sys/cdefs.h>



Home | Main Index | Thread Index | Old Index