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: document how initialization works,...



details:   https://anonhg.NetBSD.org/src/rev/b0e2585622c9
branches:  trunk
changeset: 953723:b0e2585622c9
user:      rillig <rillig%NetBSD.org@localhost>
date:      Thu Mar 18 20:22:50 2021 +0000

description:
lint: document how initialization works, improve debug logging

No functional change outside debug mode.

diffstat:

 usr.bin/xlint/lint1/init.c |  66 ++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 58 insertions(+), 8 deletions(-)

diffs (142 lines):

diff -r d2b38d9d021b -r b0e2585622c9 usr.bin/xlint/lint1/init.c
--- a/usr.bin/xlint/lint1/init.c        Thu Mar 18 20:20:55 2021 +0000
+++ b/usr.bin/xlint/lint1/init.c        Thu Mar 18 20:22:50 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: init.c,v 1.92 2021/03/18 14:58:44 rillig Exp $ */
+/*     $NetBSD: init.c,v 1.93 2021/03/18 20:22:50 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.92 2021/03/18 14:58:44 rillig Exp $");
+__RCSID("$NetBSD: init.c,v 1.93 2021/03/18 20:22:50 rillig Exp $");
 #endif
 
 #include <stdlib.h>
@@ -47,6 +47,46 @@
 
 
 /*
+ * Initialization
+ *
+ * Handles initializations of global or local objects, like in:
+ *
+ *     int number = 12345;
+ *     int number_with_braces = { 12345 };
+ *
+ *     int array_of_unknown_size[] = { 111, 222, 333 };
+ *     int array_flat[2][2] = { 11, 12, 21, 22 };
+ *     int array_nested[2][2] = { { 11, 12 }, { 21, 22 } };
+ *
+ *     struct { int x, y; } point = { 3, 4 };
+ *     struct { int x, y; } point = { .y = 3, .x = 4 };
+ *
+ * An initializer may be surrounded by an extra pair of braces, like in the
+ * example 'number_with_braces'.  For multi-dimensional arrays, the inner
+ * braces may be omitted like in array_flat or spelled out like in
+ * array_nested.
+ *
+ * For the initializer, the grammar parser calls these functions:
+ *
+ *     init_lbrace     for a '{'
+ *     init_using_expr for a value
+ *     init_rbrace     for a '}'
+ *
+ * The state of the current initialization is stored in initstk, a stack of
+ * initstack_element, one element per level of braces.
+ * (TODO: It might be more complicated for multi-dimensional arrays.)
+ *
+ * In initstk, when initializing an array, there is an additional level where
+ * the number of remaining elements toggles between 1 and 0.
+ * (TODO: Why is this extra level actually needed?  It seems redundant.)
+ *
+ * See also:
+ *     C99 6.7.8 "Initialization"
+ *     d_c99_init.c for more examples
+ */
+
+
+/*
  * Type of stack which is used for initialization of aggregate types.
  *
  * XXX: Since C99, a stack is an inappropriate data structure for modelling
@@ -94,6 +134,7 @@
         */
        bool i_brace: 1;
 
+       /* Whether i_type is an array of unknown size. */
        bool i_array_of_unknown_size: 1;
        bool i_seen_named_member: 1;
 
@@ -106,6 +147,8 @@
        /*
         * The number of remaining elements.
         *
+        * For an array of unknown size, this is always 0 and thus irrelevant.
+        *
         * XXX: for scalars?
         * XXX: for structs?
         * XXX: for unions?
@@ -499,11 +542,13 @@
                 */
                lint_assert(istk->i_enclosing->i_enclosing == NULL);
                lint_assert(istk->i_type->t_tspec == ARRAY);
+
                debug_step("extending array of unknown size '%s'",
                    type_name(istk->i_type));
                istk->i_remaining = 1;
                istk->i_type->t_dim++;
                setcomplete(istk->i_type, true);
+
                debug_step("extended type is '%s'", type_name(istk->i_type));
        }
 
@@ -544,9 +589,9 @@
                istk->i_subt = istk->i_type->t_subt;
                istk->i_array_of_unknown_size = is_incomplete(istk->i_type);
                istk->i_remaining = istk->i_type->t_dim;
-               debug_step("elements array %s[%d] %s",
-                   type_name(istk->i_subt), istk->i_remaining,
-                   namedmem != NULL ? namedmem->n_name : "*none*");
+               debug_named_member();
+               debug_step("type '%s' remaining %d",
+                   type_name(istk->i_type), istk->i_remaining);
                break;
        case UNION:
                if (tflag)
@@ -563,10 +608,10 @@
                        return;
                }
                cnt = 0;
-               debug_step("lookup type=%s, name=%s named=%d",
+               debug_named_member();
+               debug_step("lookup for '%s'%s",
                    type_name(istk->i_type),
-                   namedmem != NULL ? namedmem->n_name : "*none*",
-                   istk->i_seen_named_member);
+                   istk->i_seen_named_member ? ", seen named member" : "");
                for (m = istk->i_type->t_str->sou_first_member;
                     m != NULL; m = m->s_next) {
                        if (m->s_bitfield && m->s_name == unnamed)
@@ -876,6 +921,8 @@
 
        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)) {
                debug_initstack();
                debug_leave();
@@ -892,6 +939,9 @@
 
        check_bit_field_init(ln, lt, rt);
 
+       /*
+        * XXX: Is it correct to do this conversion _after_ the typeok above?
+        */
        if (lt != rt || (initstk->i_type->t_bitfield && tn->tn_op == CON))
                tn = convert(INIT, 0, initstk->i_type, tn);
 



Home | Main Index | Thread Index | Old Index