Module Name: src
Committed By: rillig
Date: Thu Mar 18 14:58:44 UTC 2021
Modified Files:
src/usr.bin/xlint/lint1: init.c lint1.h
Log Message:
lint: document the initialization of an object in more detail
This will help fixing the bugs that are currently demonstrated in
msg_168.c and d_struct_init_nested.c.
To generate a diff of this commit:
cvs rdiff -u -r1.91 -r1.92 src/usr.bin/xlint/lint1/init.c
cvs rdiff -u -r1.73 -r1.74 src/usr.bin/xlint/lint1/lint1.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/usr.bin/xlint/lint1/init.c
diff -u src/usr.bin/xlint/lint1/init.c:1.91 src/usr.bin/xlint/lint1/init.c:1.92
--- src/usr.bin/xlint/lint1/init.c:1.91 Wed Mar 17 15:45:30 2021
+++ src/usr.bin/xlint/lint1/init.c Thu Mar 18 14:58:44 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: init.c,v 1.91 2021/03/17 15:45:30 rillig Exp $ */
+/* $NetBSD: init.c,v 1.92 2021/03/18 14:58:44 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.91 2021/03/17 15:45:30 rillig Exp $");
+__RCSID("$NetBSD: init.c,v 1.92 2021/03/18 14:58:44 rillig Exp $");
#endif
#include <stdlib.h>
@@ -64,9 +64,23 @@ __RCSID("$NetBSD: init.c,v 1.91 2021/03/
*/
typedef struct initstack_element {
- /* XXX: Why is i_type often null? */
- type_t *i_type; /* type of initialization */
- type_t *i_subt; /* type of next level */
+ /*
+ * The type to be initialized at this level.
+ */
+ type_t *i_type;
+ /*
+ * The type that is initialized inside a further level of
+ * braces. It is completely independent from i_type->t_subt.
+ *
+ * For example, in 'int var = { init }', initially there is an
+ * initstack_element with i_subt == int. When the '{' is processed,
+ * an element with i_type == int is pushed to the stack. When the
+ * corresponding '}' is processed, the inner element is popped again.
+ *
+ * During initialization, only the top 2 elements of the stack are
+ * looked at.
+ */
+ type_t *i_subt;
/*
* This level of the initializer requires a '}' to be completed.
@@ -607,6 +621,7 @@ again:
initstk = inxt;
goto again;
}
+ /* XXX: Why is this set to 1 unconditionally? */
istk->i_remaining = 1;
break;
}
@@ -639,6 +654,11 @@ check_too_many_initializers(void)
initerr = true;
}
+/*
+ * Process a '{' in an initializer by starting the initialization of the
+ * nested data structure, with i_type being the i_subt of the outer
+ * initialization level.
+ */
static void
initstack_next_brace(void)
{
@@ -657,8 +677,9 @@ initstack_next_brace(void)
initstack_push();
if (!initerr) {
initstk->i_brace = true;
- debug_step("%p %s", namedmem, type_name(
- initstk->i_type != NULL ? initstk->i_type
+ debug_named_member();
+ debug_step("expecting type '%s'",
+ type_name(initstk->i_type != NULL ? initstk->i_type
: initstk->i_subt));
}
@@ -675,6 +696,7 @@ initstack_next_nobrace(void)
if (initstk->i_type == NULL && !is_scalar(initstk->i_subt->t_tspec)) {
/* {}-enclosed initializer required */
error(181);
+ /* XXX: maybe set initerr here */
}
if (!initerr)
@@ -683,7 +705,7 @@ initstack_next_nobrace(void)
/*
* 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
+ * 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.
@@ -727,6 +749,10 @@ init_lbrace(void)
debug_leave();
}
+/*
+ * Process a '}' in an initializer by finishing the current level of the
+ * initialization stack.
+ */
void
init_rbrace(void)
{
@@ -734,11 +760,7 @@ init_rbrace(void)
return;
debug_enter();
- debug_initstack();
-
initstack_pop_brace();
-
- debug_initstack();
debug_leave();
}
@@ -784,9 +806,9 @@ init_using_expr(tnode_t *tn)
scl_t sclass;
debug_enter();
+ debug_initstack();
debug_named_member();
debug_node(tn, debug_ind);
- debug_initstack();
if (initerr || tn == NULL) {
debug_leave();
@@ -852,7 +874,7 @@ init_using_expr(tnode_t *tn)
lt = ln->tn_type->t_tspec;
rt = tn->tn_type->t_tspec;
- lint_assert(is_scalar(lt));
+ lint_assert(is_scalar(lt)); /* at least before C99 */
if (!typeok(INIT, 0, ln, tn)) {
debug_initstack();
Index: src/usr.bin/xlint/lint1/lint1.h
diff -u src/usr.bin/xlint/lint1/lint1.h:1.73 src/usr.bin/xlint/lint1/lint1.h:1.74
--- src/usr.bin/xlint/lint1/lint1.h:1.73 Wed Mar 17 02:24:06 2021
+++ src/usr.bin/xlint/lint1/lint1.h Thu Mar 18 14:58:44 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: lint1.h,v 1.73 2021/03/17 02:24:06 rillig Exp $ */
+/* $NetBSD: lint1.h,v 1.74 2021/03/18 14:58:44 rillig Exp $ */
/*
* Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved.
@@ -160,7 +160,7 @@ struct type {
bool t_is_enum : 1; /* type is (or was) enum (t_enum valid) */
bool t_packed : 1;
union {
- int _t_dim; /* dimension */
+ int _t_dim; /* dimension (if ARRAY) */
struct_or_union *_t_str;
enumeration *_t_enum;
struct sym *_t_args; /* arguments (if t_proto) */