@@ -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 */
};
@@ -1,7 +1,8 @@
-/* $NetBSD: init.c,v 1.178 2021/03/29 21:34:17 rillig Exp $ */
+/* $NetBSD: init.c,v 1.179 2021/03/30 14:25:28 rillig Exp $ */
/*
* Copyright (c) 1994, 1995 Jochen Pohl
+ * Copyright (c) 2021 Roland Illig
* All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -37,7 +38,7 @@
#include <sys/cdefs.h>
#if defined(__RCSID) && !defined(lint)
-__RCSID("$NetBSD: init.c,v 1.178 2021/03/29 21:34:17 rillig Exp $");
+__RCSID("$NetBSD: init.c,v 1.179 2021/03/30 14:25:28 rillig Exp $");
#endif
#include <stdlib.h>
@@ -47,10 +48,8 @@
/*
- * Initialization
+ * Initialization of global or local objects, like in:
*
- * Handles initializations of global or local objects, like in:
- *
* int number = 12345;
* int number_with_braces = { 12345 };
*
@@ -66,158 +65,37 @@
* 6.7.8p11).
*
* For multi-dimensional arrays, the inner braces may be omitted like in
- * array_flat or spelled out like in array_nested.
+ * array_flat or spelled out like in array_nested. This is unusual in
+ * practice and therefore only supported very basically.
*
- * For the initializer, the grammar parser calls these functions:
+ * During initialization, the grammar parser calls these functions:
*
* begin_initialization
* init_lbrace for each '{'
* add_designator_member for each '.member' before '='
* add_designator_subscript for each '[123]' before '='
- * init_using_expr for each expression
+ * init_expr for each expression
* init_rbrace for each '}'
* end_initialization
*
* Each '{' begins a new brace level, each '}' ends the current brace level.
* Each brace level has an associated "current object".
*
- * Most of the time, the topmost level of brace_level contains a scalar type,
- * and its remaining count toggles between 1 and 0.
- *
* See also:
* C99 6.7.8 "Initialization"
* d_c99_init.c for more examples
*/
-
/*
- * Describes a single brace level of an ongoing initialization.
- *
- * XXX: Since C99, the initializers can be listed in arbitrary order by using
- * designators to specify the sub-object to be initialized. The member names
- * of non-leaf structs may thus appear repeatedly, as demonstrated in
- * d_init_pop_member.c.
- *
- * See C99 6.7.8, which spans 6 pages full of tricky details and carefully
- * selected examples.
- */
-struct brace_level {
-
- /*
- * The type of the current object that is initialized at this brace
- * level.
- *
- * On the outermost element, this is always NULL since the outermost
- * initializer-expression may be enclosed in an optional pair of
- * braces, as of the current implementation.
- *
- * FIXME: This approach is wrong. It's not that the outermost
- * initializer may be enclosed in additional braces, it's every scalar
- * that may be enclosed in additional braces, as of C99 6.7.8p11.
- *
- * Everywhere else it is nonnull.
- */
- type_t *bl_type;
-
- /*
- * The type that will be initialized at the next initialization level,
- * usually enclosed by another pair of braces.
- *
- * For an array, it is the element type, but without 'const'.
- *
- * For a struct or union type, it is one of the member types, but
- * without 'const'.
- *
- * The outermost stack element has no bl_type but nevertheless has
- * bl_subtype. For example, in 'int var = { 12345 }', initially there
- * is a brace_level with bl_subtype 'int'. When the '{' is processed,
- * an element with bl_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.
- *
- * XXX: Having bl_subtype here is the wrong approach, it should not be
- * necessary at all; see bl_type.
- */
- type_t *bl_subtype;
-
- /*
- * Whether this level of the initializer requires a '}' to be
- * completed.
- *
- * Multidimensional arrays do not need a closing brace to complete
- * an inner array; for example, { 1, 2, 3, 4 } is a valid initializer
- * for 'int arr[2][2]'.
- *
- * XXX: Double-check whether this is the correct approach at all; see
- * bl_type.
- */
- bool bl_brace: 1;
-
- /* Whether bl_type is an array of unknown size. */
- bool bl_array_of_unknown_size: 1;
-
- /*
- * XXX: This feels wrong. Whether or not there has been a named
- * initializer (called 'designation' since C99) should not matter at
- * all. Even after an initializer with designation, counting of the
- * remaining elements continues, see C99 6.7.8p17.
- */
- bool bl_seen_named_member: 1;
-
- /*
- * For structs, the next member to be initialized by a designator-less
- * initializer.
- */
- sym_t *bl_next_member;
-
- /* TODO: Add bl_next_subscript for arrays. */
-
- /* TODO: Understand C99 6.7.8p17 and footnote 128 for unions. */
-
- /*
- * The number of remaining elements to be used by expressions without
- * designator.
- *
- * This says nothing about which members have been initialized or not
- * since starting with C99, members may be initialized in arbitrary
- * order by using designators.
- *
- * For an array of unknown size, this is always 0 and thus irrelevant.
- *
- * XXX: for scalars?
- * XXX: for structs?
- * XXX: for unions?
- * XXX: for arrays?
- *
- * XXX: Having the count of remaining objects should not be necessary.
- * It is probably clearer to use bl_next_member and bl_next_subscript
- * for this purpose.
- */
- int bl_remaining;
-
- /*
- * The initialization state of the enclosing data structure
- * (struct, union, array).
- *
- * XXX: Or for a scalar, for the top-level element, or for expressions
- * in redundant braces such as '{{{{ 0 }}}}' (not yet implemented as
- * of 2021-03-25).
- */
- struct brace_level *bl_enclosing;
-};
-
-/*
* A single component on the path to the sub-object that is initialized by an
* initializer expression. Either a struct or union member, or an array
* subscript.
*
- * See also: C99 6.7.8 "Initialization"
+ * C99 6.7.8p6, 6.7.8p7
*/
struct designator {
- const char *dr_name; /* for struct and union */
- /* TODO: add 'dr_subscript' for arrays */
+ const char *dr_name; /* for struct and union */
+ size_t dr_subscript; /* for array */
struct designator *dr_next;
};
@@ -226,16 +104,36 @@
* initialize. Examples for designations are '.member' or
* '.member[123].member.member[1][1]'.
*
- * See also: C99 6.7.8 "Initialization"
+ * C99 6.7.8p6, 6.7.8p7
*/
struct designation {
struct designator *dn_head;
struct designator *dn_tail;
};
+/*
+ * Describes a single brace level of an ongoing initialization.
+ *
+ * See C99 6.7.8p17.
+ */
+struct brace_level {
+ /*
+ * The type of the current object that is initialized at this brace
+ * level.
+ */
+ const type_t *bl_type;
+ const sym_t *bl_next_member; /* for structs and unions */
+ size_t bl_array_next_subscript;
+ bool bl_array_of_unknown_size: 1;
+ bool bl_scalar_done: 1; /* for scalars */
+ bool bl_omitted_braces: 1; /* skip further checks */
+ struct designation bl_designation; /* .member[123].member */
+ struct brace_level *bl_enclosing;
+};
+
struct initialization {
/*
- * is set as soon as a fatal error occurred in the initialization.
+ * Is set as soon as a fatal error occurred in the initialization.
* The effect is that the rest of the initialization is ignored
* (parsed by yacc, expression trees built, but no initialization
* takes place).
@@ -248,21 +146,12 @@
/* The innermost brace level. */
struct brace_level *in_brace_level;
- /*
- * The C99 designator, if any, for the current initialization
- * expression.
- */
- struct designation in_designation;
-
- struct initialization *in_next;
+ struct initialization *in_enclosing;
};
-static struct initialization *init;
-
-
#ifdef DEBUG
-static int debug_ind = 0;
+static int debug_indentation = 0;
#endif
@@ -282,14 +171,14 @@
debug_indent(void)
{
- debug_printf("%*s", 2 * debug_ind, "");
+ debug_printf("%*s", 2 * debug_indentation, "");
}
static void
debug_enter(const char *func)
{
- printf("%*s+ %s\n", 2 * debug_ind++, "", func);
+ printf("%*s+ %s\n", 2 * debug_indentation++, "", func);
}
static void __printflike(1, 2)
@@ -308,7 +197,7 @@
debug_leave(const char *func)
{
- printf("%*s- %s\n", 2 * --debug_ind, "", func);
+ printf("%*s- %s\n", 2 * --debug_indentation, "", func);
}
#define debug_enter() (debug_enter)(__func__)
@@ -316,6 +205,7 @@
#else
+/* TODO: This is C99 */
#define debug_printf(fmt, ...) do { } while (false)
#define debug_indent() do { } while (false)
#define debug_enter() do { } while (false)
@@ -334,6 +224,7 @@
return r;
}
+/* C99 6.7.8p7 */
static bool
is_struct_or_union(tspec_t t)
{
@@ -365,23 +256,76 @@
/* C99 6.7.8p9 */
static bool
-is_unnamed_member(const sym_t *m)
+is_unnamed(const sym_t *m)
{
return m->s_bitfield && m->s_name == unnamed;
}
+/* C99 6.7.8p9 */
static const sym_t *
-look_up_member(const sym_t *m, const char *name)
+skip_unnamed(const sym_t *m)
{
- for (; m != NULL; m = m->s_next)
- if (!is_unnamed_member(m) && strcmp(m->s_name, name) == 0)
+ while (m != NULL && is_unnamed(m))
+ m = m->s_next;
+ return m;
+}
+
+static const sym_t *
+first_named_member(const type_t *tp)
+{
+
+ lint_assert(is_struct_or_union(tp->t_tspec));
+ return skip_unnamed(tp->t_str->sou_first_member);
+}
+
+static const sym_t *
+look_up_member(const type_t *tp, const char *name)
+{
+ const sym_t *m;
+
+ lint_assert(is_struct_or_union(tp->t_tspec));
+ for (m = tp->t_str->sou_first_member; m != NULL; m = m->s_next)
+ if (!is_unnamed(m) && strcmp(m->s_name, name) == 0)
return m;
return NULL;
}
+static const type_t *
+sym_type(const sym_t *sym)
+{
+ return sym != NULL ? sym->s_type : NULL;
+}
+
+static const type_t *
+look_up_member_type(const type_t *tp, const char *name)
+{
+ const sym_t *member;
+
+ member = look_up_member(tp, name);
+ if (member == NULL) {
+ /* TODO: add type information */
+ /* undefined struct/union member: %s */
+ error(101, name);
+ }
+
+ return sym_type(member);
+}
+
+static void
+update_type_of_array_of_unknown_size(sym_t *sym, size_t size)
+{
+ type_t *tp;
+
+ tp = duptyp(sym->s_type);
+ tp->t_dim = (int)size;
+ tp->t_incomplete_array = false;
+ sym->s_type = tp;
+}
+
+
/* In traditional C, bit-fields can be initialized only by integer constants. */
static void
check_bit_field_init(const tnode_t *ln, tspec_t lt, tspec_t rt)
@@ -418,6 +362,18 @@
}
static void
+check_no_auto_aggregate(const sym_t *sym)
+{
+
+ if (tflag &&
+ has_automatic_storage_duration(sym) &&
+ !is_scalar(sym->s_type->t_tspec)) {
+ /* no automatic aggregate initialization in trad. C */
+ warning(188);
+ }
+}
+
+static void
check_init_expr(const type_t *tp, sym_t *sym, tnode_t *tn)
{
tnode_t *ln;
@@ -463,12 +419,13 @@
static struct designator *
-designator_new(const char *name)
+designator_new(const char *name, size_t subscript)
{
struct designator *dr;
dr = xcalloc(1, sizeof *dr);
dr->dr_name = name;
+ dr->dr_subscript = subscript;
return dr;
}
@@ -480,6 +437,35 @@
}
+static const type_t *
+designator_look_up(const struct designator *dr, const type_t *tp)
+{
+ switch (tp->t_tspec) {
+ case STRUCT:
+ case UNION:
+ if (dr->dr_name == NULL) {
+ /* syntax error '%s' */
+ error(249, "designator '[...]' is only for arrays");
+ return sym_type(first_named_member(tp));
+ }
+
+ return look_up_member_type(tp, dr->dr_name);
+ case ARRAY:
+ if (dr->dr_name != NULL) {
+ /* TODO: reword; kept for compatibility */
+ /* syntax error '%s' */
+ error(249,
+ "named member must only be used with struct/union");
+ }
+ return tp->t_subt;
+ default:
+ /* syntax error '%s' */
+ error(249, "scalar type cannot use designator");
+ return tp;
+ }
+}
+
+
#ifdef DEBUG
static void
designation_debug(const struct designation *dn)
@@ -491,8 +477,13 @@
debug_indent();
debug_printf("designation: ");
- for (dr = dn->dn_head; dr != NULL; dr = dr->dr_next)
- debug_printf(".%s", dr->dr_name);
+ for (dr = dn->dn_head; dr != NULL; dr = dr->dr_next) {
+ if (dr->dr_name != NULL) {
+ debug_printf(".%s", dr->dr_name);
+ lint_assert(dr->dr_subscript == 0);
+ } else
+ debug_printf("[%zu]", dr->dr_subscript);
+ }
debug_printf("\n");
}
#else
@@ -500,9 +491,12 @@
#endif
static void
-designation_add(struct designation *dn, struct designator *dr)
+designation_add(struct designation *dn, const char *name, size_t subscript)
{
+ struct designator *dr;
+ dr = designator_new(name, subscript);
+
if (dn->dn_head != NULL) {
dn->dn_tail->dr_next = dr;
dn->dn_tail = dr;
@@ -510,44 +504,46 @@
dn->dn_head = dr;
dn->dn_tail = dr;
}
-
- designation_debug(dn);
}
-/* TODO: add support for array subscripts, not only named members */
/*
- * TODO: This function should not be necessary at all. There is no need to
- * remove the head of the list.
+ * Starting at the type of the current object, resolve the type of the
+ * sub-object by following each designator in the list.
*/
+static const type_t *
+designation_look_up(const struct designation *dn, const type_t *tp)
+{
+ const struct designator *dr;
+
+ for (dr = dn->dn_head; dr != NULL && tp != NULL; dr = dr->dr_next)
+ tp = designator_look_up(dr, tp);
+ return tp;
+}
+
+
+
static void
-designation_shift_level(struct designation *dn)
+designation_reset(struct designation *dn)
{
- lint_assert(dn->dn_head != NULL);
+ struct designator *dr, *next;
- if (dn->dn_head == dn->dn_tail) {
- designator_free(dn->dn_head);
- dn->dn_head = NULL;
- dn->dn_tail = NULL;
- } else {
- struct designator *head = dn->dn_head;
- dn->dn_head = dn->dn_head->dr_next;
- designator_free(head);
+ for (dr = dn->dn_head; dr != NULL; dr = next) {
+ next = dr->dr_next;
+ designator_free(dr);
}
-
- designation_debug(dn);
}
static struct brace_level *
-brace_level_new(type_t *type, type_t *subtype, int remaining,
- struct brace_level *enclosing)
+brace_level_new(const type_t *tp, struct brace_level *enclosing)
{
- struct brace_level *bl = xcalloc(1, sizeof(*bl));
+ struct brace_level *bl;
- bl->bl_type = type;
- bl->bl_subtype = subtype;
- bl->bl_remaining = remaining;
+ bl = xcalloc(1, sizeof(*bl));
+ bl->bl_type = tp;
bl->bl_enclosing = enclosing;
+ if (is_struct_or_union(tp->t_tspec))
+ bl->bl_next_member = first_named_member(tp);
return bl;
}
@@ -555,246 +551,173 @@
static void
brace_level_free(struct brace_level *bl)
{
+
+ designation_reset(&bl->bl_designation);
free(bl);
}
#ifdef DEBUG
-/*
- * TODO: only log the top of the stack after each modifying operation
- *
- * TODO: wrap all write accesses to brace_level in setter functions
- */
static void
brace_level_debug(const struct brace_level *bl)
{
- if (bl->bl_type != NULL)
- debug_printf("type '%s'", type_name(bl->bl_type));
- if (bl->bl_type != NULL && bl->bl_subtype != NULL)
- debug_printf(", ");
- if (bl->bl_subtype != NULL)
- debug_printf("subtype '%s'", type_name(bl->bl_subtype));
- if (bl->bl_brace)
- debug_printf(", needs closing brace");
+ lint_assert(bl->bl_type != NULL);
+ lint_assert(bl->bl_next_member == NULL ||
+ !is_unnamed(bl->bl_next_member));
+
+ debug_printf("type '%s'", type_name(bl->bl_type));
+
if (bl->bl_array_of_unknown_size)
debug_printf(", array of unknown size");
- if (bl->bl_seen_named_member)
- debug_printf(", seen named member");
- const type_t *eff_type = bl->bl_type != NULL
- ? bl->bl_type : bl->bl_subtype;
- if (eff_type->t_tspec == STRUCT && bl->bl_next_member != NULL)
+ if (is_struct_or_union(bl->bl_type->t_tspec) &&
+ bl->bl_next_member != NULL)
debug_printf(", next member '%s'",
bl->bl_next_member->s_name);
+ if (bl->bl_type->t_tspec == ARRAY)
+ debug_printf(", next array subscript %zu",
+ bl->bl_array_next_subscript);
- debug_printf(", remaining %d\n", bl->bl_remaining);
+ debug_printf("\n");
}
#else
-#define brace_level_debug(bl) do { } while (false)
+#define brace_level_debug(level) do { } while (false)
#endif
static void
-brace_level_assert_struct_or_union(const struct brace_level *bl)
+brace_level_remove_designation(struct brace_level *bl)
{
- lint_assert(is_struct_or_union(bl->bl_type->t_tspec));
-}
+ struct designator *dr, *next;
-static void
-brace_level_assert_array(const struct brace_level *bl)
-{
- lint_assert(bl->bl_type->t_tspec == ARRAY);
-}
+ for (dr = bl->bl_designation.dn_head; dr != NULL; dr = next) {
+ next = dr->dr_next;
+ designator_free(dr);
+ }
-static type_t *
-brace_level_subtype(struct brace_level *bl)
-{
-
- if (bl->bl_subtype != NULL)
- return bl->bl_subtype;
-
- return bl->bl_type;
+ bl->bl_designation.dn_head = NULL;
+ bl->bl_designation.dn_tail = NULL;
}
-static void
-brace_level_set_array_dimension(struct brace_level *bl, int dim)
-{
- brace_level_assert_array(bl);
- debug_step("setting the array size to %d", dim);
- bl->bl_type->t_dim = dim;
- debug_indent();
- brace_level_debug(bl);
-}
-
-static void
-brace_level_next_member(struct brace_level *bl)
+static const type_t *
+brace_level_sub_type_struct_or_union(const struct brace_level *bl)
{
- const sym_t *m;
- brace_level_assert_struct_or_union(bl);
- do {
- m = bl->bl_next_member = bl->bl_next_member->s_next;
- /* XXX: can this assertion be made to fail? */
- lint_assert(m != NULL);
- } while (m->s_bitfield && m->s_name == unnamed);
+ if (bl->bl_next_member == NULL) {
+ /* too many struct/union initializers */
+ error(172);
+ return NULL;
+ }
- debug_indent();
- brace_level_debug(bl);
+ lint_assert(!is_unnamed(bl->bl_next_member));
+ return sym_type(bl->bl_next_member);
}
-static const sym_t *
-brace_level_look_up_member(const struct brace_level *bl, const char *name)
+static const type_t *
+brace_level_sub_type_array(const struct brace_level *bl)
{
- brace_level_assert_struct_or_union(bl);
- return look_up_member(bl->bl_type->t_str->sou_first_member, name);
+ if (!bl->bl_type->t_incomplete_array &&
+ !bl->bl_omitted_braces &&
+ bl->bl_array_next_subscript >= (size_t)bl->bl_type->t_dim) {
+ /* too many array initializers, expected %d */
+ error(173, bl->bl_type->t_dim);
+ }
+
+ return bl->bl_type->t_subt;
}
-static sym_t *
-brace_level_look_up_first_member_named(struct brace_level *bl,
- const char *name, int *count)
+static const type_t *
+brace_level_sub_type_scalar(const struct brace_level *bl)
{
- sym_t *m;
- for (m = bl->bl_type->t_str->sou_first_member;
- m != NULL; m = m->s_next) {
- if (is_unnamed_member(m))
- continue;
- if (strcmp(m->s_name, name) != 0)
- continue;
- (*count)++;
- break;
+ if (bl->bl_scalar_done) {
+ /* too many initializers */
+ error(174);
}
- return m;
+ return bl->bl_type;
}
-static sym_t *
-brace_level_look_up_first_member_unnamed(struct brace_level *bl, int *count)
+/* Return the type of the sub-object that is currently being initialized. */
+static const type_t *
+brace_level_sub_type(const struct brace_level *bl)
{
- sym_t *m;
- brace_level_assert_struct_or_union(bl);
+ if (bl->bl_designation.dn_head != NULL)
+ return designation_look_up(&bl->bl_designation, bl->bl_type);
- for (m = bl->bl_type->t_str->sou_first_member;
- m != NULL; m = m->s_next) {
- if (is_unnamed_member(m))
- continue;
- /* XXX: What is this code for? */
- if (++(*count) == 1) {
- bl->bl_next_member = m;
- bl->bl_subtype = m->s_type;
- }
+ switch (bl->bl_type->t_tspec) {
+ case STRUCT:
+ case UNION:
+ return brace_level_sub_type_struct_or_union(bl);
+ case ARRAY:
+ return brace_level_sub_type_array(bl);
+ default:
+ return brace_level_sub_type_scalar(bl);
}
-
- return m;
}
-/* TODO: document me */
-/* TODO: think of a better name than 'push' */
-static bool
-brace_level_push_array(struct brace_level *bl)
+static void
+brace_level_apply_designation(struct brace_level *bl)
{
- brace_level_assert_array(bl);
+ const struct designator *dr = bl->bl_designation.dn_head;
- if (bl->bl_enclosing->bl_seen_named_member) {
- bl->bl_brace = true;
- debug_step("ARRAY, seen named member, needs closing brace");
- }
+ if (dr == NULL)
+ return;
- if (is_incomplete(bl->bl_type) &&
- bl->bl_enclosing->bl_enclosing != NULL) {
- /* initialization of an incomplete type */
- error(175);
- return false;
- }
+ designation_debug(&bl->bl_designation);
- bl->bl_subtype = bl->bl_type->t_subt;
- bl->bl_array_of_unknown_size = is_incomplete(bl->bl_type);
- bl->bl_remaining = bl->bl_type->t_dim;
- debug_step("type '%s' remaining %d",
- type_name(bl->bl_type), bl->bl_remaining);
- return true;
+ switch (bl->bl_type->t_tspec) {
+ case STRUCT:
+ case UNION:
+ if (dr->dr_name == NULL)
+ return; /* error, silently ignored */
+ bl->bl_next_member = look_up_member(bl->bl_type, dr->dr_name);
+ break;
+ case ARRAY:
+ if (dr->dr_name != NULL)
+ return; /* error, silently ignored */
+ bl->bl_array_next_subscript = dr->dr_subscript;
+ break;
+ default:
+ break; /* error, silently ignored */
+ }
}
/*
- * If the removed element was a structure member, we must go
- * to the next structure member.
+ * After initializing a sub-object, advance to the next sub-object.
*
- * XXX: Nothing should ever be "removed" at this point.
- *
- * TODO: think of a better name than 'pop'
+ * C99 6.7.8p17
*/
static void
-brace_level_pop_item_unnamed(struct brace_level *bl)
+brace_level_advance(struct brace_level *bl)
{
- if (bl->bl_remaining > 0 && bl->bl_type->t_tspec == STRUCT &&
- !bl->bl_seen_named_member) {
- brace_level_next_member(bl);
- bl->bl_subtype = bl->bl_next_member->s_type;
- }
-}
-static bool
-brace_level_check_too_many_initializers(struct brace_level *bl)
-{
- if (bl->bl_remaining > 0)
- return true;
- /*
- * FIXME: even with named members, there can be too many initializers
- */
- if (bl->bl_array_of_unknown_size || bl->bl_seen_named_member)
- return true;
-
- tspec_t t = bl->bl_type->t_tspec;
- if (t == ARRAY) {
- /* too many array initializers, expected %d */
- error(173, bl->bl_type->t_dim);
- } else if (is_struct_or_union(t)) {
- /* too many struct/union initializers */
- error(172);
- } else {
- /* too many initializers */
- error(174);
+ switch (bl->bl_type->t_tspec) {
+ case STRUCT:
+ lint_assert(bl->bl_next_member != NULL);
+ bl->bl_next_member = skip_unnamed(bl->bl_next_member->s_next);
+ break;
+ case UNION:
+ bl->bl_next_member = NULL;
+ break;
+ case ARRAY:
+ bl->bl_array_next_subscript++;
+ break;
+ default:
+ bl->bl_scalar_done = true;
+ break;
}
- return false;
}
-/* Extend an array of unknown size by one element */
-static void
-brace_level_extend_if_array_of_unknown_size(struct brace_level *bl)
-{
- if (bl->bl_remaining != 0)
- return;
- /*
- * XXX: According to the function name, there should be a 'return' if
- * bl_array_of_unknown_size is false. There's probably a test missing
- * for that case.
- */
-
- /*
- * The only place where an incomplete array may appear is at the
- * outermost aggregate bl of the object to be initialized.
- */
- lint_assert(bl->bl_enclosing->bl_enclosing == NULL);
- lint_assert(bl->bl_type->t_tspec == ARRAY);
-
- debug_step("extending array of unknown size '%s'",
- type_name(bl->bl_type));
- bl->bl_remaining = 1;
- bl->bl_type->t_dim++;
- setcomplete(bl->bl_type, true);
-
- debug_step("extended type is '%s'", type_name(bl->bl_type));
-}
-
-
static struct initialization *
initialization_new(sym_t *sym)
{
- struct initialization *in = xcalloc(1, sizeof(*in));
+ struct initialization *in;
+ in = xcalloc(1, sizeof(*in));
in->in_sym = sym;
return in;
@@ -814,20 +737,19 @@
}
#ifdef DEBUG
-/*
- * TODO: only call debug_initstack after each push/pop.
- */
static void
initialization_debug(const struct initialization *in)
{
+ size_t i;
+ const struct brace_level *bl;
+
if (in->in_brace_level == NULL) {
- debug_step("no brace level in the current initialization");
+ debug_step("no brace level");
return;
}
- size_t i = 0;
- for (const struct brace_level *bl = in->in_brace_level;
- bl != NULL; bl = bl->bl_enclosing) {
+ i = 0;
+ for (bl = in->in_brace_level; bl != NULL; bl = bl->bl_enclosing) {
debug_indent();
debug_printf("brace level %zu: ", i);
brace_level_debug(bl);
@@ -839,476 +761,136 @@
#endif
/*
- * Initialize the initialization stack by putting an entry for the object
- * which is to be initialized on it.
- *
- * TODO: merge into initialization_new if possible
+ * Return the type of the object or sub-object that is currently being
+ * initialized.
*/
-static void
-initialization_init(struct initialization *in)
+static const type_t *
+initialization_sub_type(struct initialization *in)
{
- if (in->in_err)
- return;
+ const type_t *tp;
- debug_enter();
-
- /*
- * If the type which is to be initialized is an incomplete array,
- * it must be duplicated.
- */
- if (in->in_sym->s_type->t_tspec == ARRAY && is_incomplete(in->in_sym->s_type))
- in->in_sym->s_type = duptyp(in->in_sym->s_type);
- /* TODO: does 'duptyp' create a memory leak? */
-
- in->in_brace_level = brace_level_new(NULL, in->in_sym->s_type, 1, NULL);
-
- initialization_debug(in);
- debug_leave();
+ tp = in->in_brace_level != NULL
+ ? brace_level_sub_type(in->in_brace_level)
+ : in->in_sym->s_type;
+ if (tp == NULL)
+ in->in_err = true;
+ return tp;
}
static void
-initialization_set_error(struct initialization *in)
+initialization_begin_brace_level(struct initialization *in)
{
- in->in_err = true;
-}
+ const type_t *tp;
-/* TODO: document me */
-/* TODO: think of a better name than 'push' */
-static bool
-initialization_push_struct_or_union(struct initialization *in)
-{
- struct brace_level *bl = in->in_brace_level;
- int cnt;
- sym_t *m;
+ if (in->in_err)
+ return;
- if (is_incomplete(bl->bl_type)) {
- /* initialization of an incomplete type */
- error(175);
- initialization_set_error(in);
- return false;
- }
-
- cnt = 0;
- designation_debug(&in->in_designation);
- debug_step("lookup for '%s'%s",
- type_name(bl->bl_type),
- bl->bl_seen_named_member ? ", seen named member" : "");
-
- if (in->in_designation.dn_head != NULL)
- m = brace_level_look_up_first_member_named(bl,
- in->in_designation.dn_head->dr_name, &cnt);
- else
- m = brace_level_look_up_first_member_unnamed(bl, &cnt);
-
- if (in->in_designation.dn_head != NULL) {
- if (m == NULL) {
- debug_step("pop struct");
- return true;
- }
- bl->bl_next_member = m;
- bl->bl_subtype = m->s_type;
- bl->bl_seen_named_member = true;
- debug_step("named member '%s'",
- in->in_designation.dn_head->dr_name);
- designation_shift_level(&in->in_designation);
- cnt = bl->bl_type->t_tspec == STRUCT ? 2 : 1;
- }
- bl->bl_brace = true;
- debug_step("unnamed element with type '%s'%s",
- type_name(
- bl->bl_type != NULL ? bl->bl_type : bl->bl_subtype),
- bl->bl_brace ? ", needs closing brace" : "");
- if (cnt == 0) {
- /* cannot init. struct/union with no named member */
- error(179);
- initialization_set_error(in);
- return false;
- }
- bl->bl_remaining = bl->bl_type->t_tspec == STRUCT ? cnt : 1;
- return false;
-}
-
-static void
-initialization_end_brace_level(struct initialization *in)
-{
- struct brace_level *bl = in->in_brace_level;
- in->in_brace_level = bl->bl_enclosing;
- brace_level_free(bl);
-}
-
-/* TODO: document me */
-/* TODO: think of a better name than 'push' */
-static void
-initialization_push(struct initialization *in)
-{
- struct brace_level *bl;
-
debug_enter();
- brace_level_extend_if_array_of_unknown_size(in->in_brace_level);
-
- bl = in->in_brace_level;
- lint_assert(bl->bl_remaining > 0);
-
- in->in_brace_level = brace_level_new(brace_level_subtype(bl), NULL, 0,
- bl);
- lint_assert(in->in_brace_level->bl_type != NULL);
- lint_assert(in->in_brace_level->bl_type->t_tspec != FUNC);
-
-again:
- bl = in->in_brace_level;
-
- debug_step("expecting type '%s'", type_name(bl->bl_type));
- lint_assert(bl->bl_type != NULL);
- switch (bl->bl_type->t_tspec) {
- case ARRAY:
- if (in->in_designation.dn_head != NULL) {
- debug_step("pop array, named member '%s'%s",
- in->in_designation.dn_head->dr_name,
- bl->bl_brace ? ", needs closing brace" : "");
- goto pop;
- }
-
- if (!brace_level_push_array(bl))
- initialization_set_error(in);
- break;
-
- case UNION:
- if (tflag)
- /* initialization of union is illegal in trad. C */
- warning(238);
- /* FALLTHROUGH */
- case STRUCT:
- if (initialization_push_struct_or_union(in))
- goto pop;
- break;
- default:
- if (in->in_designation.dn_head != NULL) {
- debug_step("pop scalar");
- pop:
- initialization_end_brace_level(in);
- goto again;
- }
- /* The initialization stack now expects a single scalar. */
- bl->bl_remaining = 1;
- break;
+ tp = initialization_sub_type(in);
+ if (tp == NULL) {
+ in->in_err = true;
+ goto done;
}
- initialization_debug(in);
- debug_leave();
-}
+ if (tflag && in->in_brace_level == NULL)
+ check_no_auto_aggregate(in->in_sym);
-/* TODO: document me */
-static void
-initialization_pop_item_named(struct initialization *in, const char *name)
-{
- struct brace_level *bl = in->in_brace_level;
- const sym_t *m;
-
- /*
- * TODO: fix wording of the debug message; this doesn't seem to be
- * related to initializing the named member.
- */
- debug_step("initializing named member '%s'", name);
-
- if (!is_struct_or_union(bl->bl_type->t_tspec)) {
- /* syntax error '%s' */
- error(249, "named member must only be used with struct/union");
- initialization_set_error(in);
- return;
+ if (tflag && tp->t_tspec == UNION) {
+ /* initialization of union is illegal in traditional C */
+ warning(238);
}
- m = brace_level_look_up_member(bl, name);
- if (m == NULL) {
- /* TODO: add type information to the message */
- /* undefined struct/union member: %s */
- error(101, name);
-
- designation_shift_level(&in->in_designation);
- bl->bl_seen_named_member = true;
- return;
+ if (tp->t_tspec == STRUCT && tp->t_str->sou_incomplete) {
+ /* TODO: add type information */
+ /* initialization of an incomplete type */
+ error(175);
+ in->in_err = true;
+ goto done;
}
- debug_step("found matching member");
- bl->bl_subtype = m->s_type;
- /* XXX: why ++? */
- bl->bl_remaining++;
- /* XXX: why is bl_seen_named_member not set? */
- designation_shift_level(&in->in_designation);
-}
+ if (in->in_brace_level != NULL)
+ brace_level_apply_designation(in->in_brace_level);
-/* TODO: think of a better name than 'pop' */
-static void
-initialization_pop_item(struct initialization *in)
-{
- struct brace_level *bl;
+ in->in_brace_level = brace_level_new(tp, in->in_brace_level);
- debug_enter();
-
- bl = in->in_brace_level;
- debug_indent();
- debug_printf("popping: ");
- brace_level_debug(bl);
-
- in->in_brace_level = bl->bl_enclosing;
- brace_level_free(bl);
- bl = in->in_brace_level;
- lint_assert(bl != NULL);
-
- bl->bl_remaining--;
- lint_assert(bl->bl_remaining >= 0);
- debug_step("%d elements remaining", bl->bl_remaining);
-
- if (in->in_designation.dn_head != NULL && in->in_designation.dn_head->dr_name != NULL)
- initialization_pop_item_named(in, in->in_designation.dn_head->dr_name);
- else
- brace_level_pop_item_unnamed(bl);
-
+done:
initialization_debug(in);
debug_leave();
}
-/*
- * Take all entries which cannot be used for further initializers from the
- * stack, but do this only if they do not require a closing brace.
- */
-/* TODO: think of a better name than 'pop' */
+/* C99 6.7.8p22 */
static void
-initialization_pop_nobrace(struct initialization *in)
+initialization_set_size_of_unknown_array(struct initialization *in)
{
- debug_enter();
- while (!in->in_brace_level->bl_brace &&
- in->in_brace_level->bl_remaining == 0 &&
- !in->in_brace_level->bl_array_of_unknown_size)
- initialization_pop_item(in);
- debug_leave();
+ if (in->in_sym->s_type->t_incomplete_array &&
+ in->in_brace_level->bl_enclosing == NULL)
+ update_type_of_array_of_unknown_size(in->in_sym,
+ in->in_brace_level->bl_array_next_subscript);
}
-/*
- * Process a '{' in an initializer by starting the initialization of the
- * nested data structure, with bl_type being the bl_subtype of the outer
- * initialization level.
- */
static void
-initialization_next_brace(struct initialization *in)
+initialization_end_brace_level(struct initialization *in)
{
+ struct brace_level *bl;
- debug_enter();
- initialization_debug(in);
-
- if (!in->in_err &&
- !brace_level_check_too_many_initializers(in->in_brace_level))
- initialization_set_error(in);
-
- if (!in->in_err)
- initialization_push(in);
-
- if (!in->in_err) {
- in->in_brace_level->bl_brace = true;
- designation_debug(&in->in_designation);
- if (in->in_brace_level->bl_type != NULL)
- debug_step("expecting type '%s'",
- type_name(in->in_brace_level->bl_type));
- }
-
- initialization_debug(in);
- debug_leave();
-}
-
-static void
-check_no_auto_aggregate(scl_t sclass, const struct brace_level *bl)
-{
- if (!tflag)
- return;
- if (!(sclass == AUTO || sclass == REG))
- return;
- if (!(bl->bl_enclosing == NULL))
- return;
- if (is_scalar(bl->bl_subtype->t_tspec))
- return;
-
- /* no automatic aggregate initialization in trad. C */
- warning(188);
-}
-
-static void
-initialization_lbrace(struct initialization *in)
-{
if (in->in_err)
return;
debug_enter();
- initialization_debug(in);
- check_no_auto_aggregate(in->in_sym->s_scl, in->in_brace_level);
+ initialization_set_size_of_unknown_array(in);
- /*
- * Remove all entries which cannot be used for further initializers
- * and do not expect a closing brace.
- */
- initialization_pop_nobrace(in);
+ bl = in->in_brace_level;
+ in->in_brace_level = bl->bl_enclosing;
+ brace_level_free(bl);
- initialization_next_brace(in);
+ if (in->in_brace_level != NULL) {
+ brace_level_advance(in->in_brace_level);
+ brace_level_remove_designation(in->in_brace_level);
+ }
initialization_debug(in);
debug_leave();
}
-/*
- * Process a '}' in an initializer by finishing the current level of the
- * initialization stack.
- *
- * Take all entries, including the first which requires a closing brace,
- * from the stack.
- */
static void
-initialization_rbrace(struct initialization *in)
+initialization_add_designator(struct initialization *in,
+ const char *name, size_t subscript)
{
- bool brace;
if (in->in_err)
return;
- debug_enter();
- do {
- brace = in->in_brace_level->bl_brace;
- /* TODO: improve wording of the debug message */
- debug_step("loop brace=%d", brace);
- initialization_pop_item(in);
- } while (!brace);
- initialization_debug(in);
- debug_leave();
+ lint_assert(in->in_brace_level != NULL);
+ designation_add(&in->in_brace_level->bl_designation, name, subscript);
}
-/*
- * A sub-object of an array is initialized using a designator. This does not
- * have to be an array element directly, it can also be used to initialize
- * only a sub-object of the array element.
- *
- * C99 example: struct { int member[4]; } var = { [2] = 12345 };
- *
- * GNU example: struct { int member[4]; } var = { [1 ... 3] = 12345 };
- *
- * TODO: test the following initialization with an outer and an inner type:
- *
- * .deeply[0].nested = {
- * .deeply[1].nested = {
- * 12345,
- * },
- * }
- */
static void
-initialization_add_designator_subscript(struct initialization *in,
- range_t range)
+initialization_remove_designation(struct initialization *in)
{
- struct brace_level *bl;
- debug_enter();
- if (range.lo == range.hi)
- debug_step("subscript is %zu", range.hi);
- else
- debug_step("subscript range is %zu ... %zu",
- range.lo, range.hi);
-
- /* XXX: This call is wrong here, it must be somewhere else. */
- initialization_pop_nobrace(in);
-
- bl = in->in_brace_level;
- if (bl->bl_array_of_unknown_size) {
- /* No +1 here, extend_if_array_of_unknown_size will add it. */
- int auto_dim = (int)range.hi;
- if (auto_dim > bl->bl_type->t_dim)
- brace_level_set_array_dimension(bl, auto_dim);
- }
-
- debug_leave();
+ if (in->in_brace_level != NULL)
+ brace_level_remove_designation(in->in_brace_level);
}
-/* Initialize a character array or wchar_t array with a string literal. */
-static bool
-initialization_init_array_using_string(struct initialization *in, tnode_t *tn)
-{
- struct brace_level *bl;
- strg_t *strg;
-
- if (tn->tn_op != STRING)
- return false;
-
- debug_enter();
-
- bl = in->in_brace_level;
- strg = tn->tn_string;
-
- /*
- * Check if we have an array type which can be initialized by
- * the string.
- */
- if (is_string_array(bl->bl_subtype, strg->st_tspec)) {
- debug_step("subtype is an array");
-
- /* Put the array at top of stack */
- initialization_push(in);
- bl = in->in_brace_level;
-
- } else if (is_string_array(bl->bl_type, strg->st_tspec)) {
- debug_step("type is an array");
-
- /*
- * If the array is already partly initialized, we are
- * wrong here.
- */
- if (bl->bl_remaining != bl->bl_type->t_dim)
- goto nope;
- } else
- goto nope;
-
- if (bl->bl_array_of_unknown_size) {
- bl->bl_array_of_unknown_size = false;
- bl->bl_type->t_dim = (int)(strg->st_len + 1);
- setcomplete(bl->bl_type, true);
- } else {
- /*
- * TODO: check for buffer overflow in the object to be
- * initialized
- */
- /* XXX: double-check for off-by-one error */
- if (bl->bl_type->t_dim < (int)strg->st_len) {
- /* non-null byte ignored in string initializer */
- warning(187);
- }
-
- /*
- * TODO: C99 6.7.8p14 allows a string literal to be enclosed
- * in optional redundant braces, just like scalars. Add tests
- * for this.
- */
- }
-
- /* In every case the array is initialized completely. */
- bl->bl_remaining = 0;
-
- initialization_debug(in);
- debug_leave();
- return true;
-nope:
- debug_leave();
- return false;
-}
-
/*
- * Initialize a non-array object with automatic storage duration and only a
- * single initializer expression without braces by delegating to ASSIGN.
+ * An object with automatic storage duration that has a single initializer
+ * expression without braces and is not an array is initialized by delegating
+ * to the ASSIGN operator.
*/
static bool
-initialization_init_using_assign(struct initialization *in, tnode_t *rn)
+initialization_expr_using_assign(struct initialization *in, tnode_t *rn)
{
tnode_t *ln, *tn;
- if (in->in_sym->s_type->t_tspec == ARRAY)
+ if (!has_automatic_storage_duration(in->in_sym))
return false;
- if (in->in_brace_level->bl_enclosing != NULL)
+ if (in->in_brace_level != NULL)
return false;
+ if (in->in_sym->s_type->t_tspec == ARRAY)
+ return false;
debug_step("handing over to ASSIGN");
@@ -1319,93 +901,114 @@
tn = build(ASSIGN, ln, rn);
expr(tn, false, false, false, false);
- /* XXX: why not clean up the initstack here already? */
return true;
}
-/* TODO: document me, or think of a better name */
-static void
-initialization_next_nobrace(struct initialization *in, tnode_t *tn)
+/* Initialize a character array or wchar_t array with a string literal. */
+static bool
+initialization_init_array_using_string(struct initialization *in, tnode_t *tn)
{
- debug_enter();
+ struct brace_level *bl;
+ const type_t *tp;
+ strg_t *strg;
- if (in->in_brace_level->bl_type == NULL &&
- !is_scalar(in->in_brace_level->bl_subtype->t_tspec)) {
- /* {}-enclosed initializer required */
- error(181);
- /* XXX: maybe set initerr here */
- }
+ if (tn->tn_op != STRING)
+ return false;
- if (!in->in_err &&
- !brace_level_check_too_many_initializers(in->in_brace_level))
- initialization_set_error(in);
+ bl = in->in_brace_level;
+ tp = initialization_sub_type(in);
+ strg = tn->tn_string;
- while (!in->in_err) {
- struct brace_level *bl = in->in_brace_level;
+ if (!is_string_array(tp, strg->st_tspec))
+ return false;
+ if (bl != NULL && tp->t_tspec != ARRAY &&
+ bl->bl_array_next_subscript != 0)
+ return false;
- if (tn->tn_type->t_tspec == STRUCT &&
- bl->bl_type == tn->tn_type &&
- bl->bl_enclosing != NULL &&
- bl->bl_enclosing->bl_enclosing != NULL) {
- bl->bl_brace = false;
- bl->bl_remaining = 1; /* the struct itself */
- break;
- }
+ if (bl != NULL && tp->t_dim < (int)strg->st_len) {
+ /* non-null byte ignored in string initializer */
+ warning(187);
+ }
- if (bl->bl_type != NULL &&
- is_scalar(bl->bl_type->t_tspec))
- break;
- initialization_push(in);
+ if (tp == in->in_sym->s_type && tp->t_incomplete_array) {
+ if (bl != NULL) {
+ bl->bl_array_next_subscript = strg->st_len + 1;
+ /* see initialization_set_size_of_unknown_array */
+ } else
+ update_type_of_array_of_unknown_size(in->in_sym,
+ strg->st_len + 1);
}
- initialization_debug(in);
- debug_leave();
+ return true;
}
+/*
+ * Initialize a single sub-object as part of the currently ongoing
+ * initialization.
+ */
static void
initialization_expr(struct initialization *in, tnode_t *tn)
{
+ const type_t *tp;
+ if (in->in_err)
+ return;
+
+ if (in->in_brace_level != NULL &&
+ in->in_brace_level->bl_omitted_braces)
+ return;
+
debug_enter();
- initialization_debug(in);
- designation_debug(&in->in_designation);
- debug_step("expr:");
- debug_node(tn, debug_ind + 1);
- if (in->in_err || tn == NULL)
+ if (tn == NULL)
+ goto advance;
+ if (initialization_expr_using_assign(in, tn))
goto done;
+ if (initialization_init_array_using_string(in, tn))
+ goto advance;
- if (has_automatic_storage_duration(in->in_sym) &&
- initialization_init_using_assign(in, tn))
+ if (in->in_brace_level != NULL)
+ brace_level_apply_designation(in->in_brace_level);
+ tp = initialization_sub_type(in);
+ if (tp == NULL)
goto done;
- initialization_pop_nobrace(in);
+ if (in->in_brace_level == NULL && !is_scalar(tp->t_tspec)) {
+ /* {}-enclosed initializer required */
+ error(181);
+ goto done;
+ }
- if (initialization_init_array_using_string(in, tn)) {
- debug_step("after initializing the string:");
- goto done_debug;
+ /*
+ * Hack to accept initializations with omitted braces, see
+ * c99_6_7_8_p28_example5 in test d_c99_init.c. Since both GCC and
+ * Clang already warn about this at level -Wall, there is no point
+ * in letting lint check this again.
+ */
+ if (is_scalar(tn->tn_type->t_tspec) &&
+ tp->t_tspec == ARRAY &&
+ in->in_brace_level != NULL) {
+ in->in_brace_level->bl_omitted_braces = true;
+ goto done;
}
- initialization_next_nobrace(in, tn);
- if (in->in_err || tn == NULL)
- goto done_debug;
+ debug_step("expecting '%s', expression has '%s'",
+ type_name(tp), type_name(tn->tn_type));
+ check_init_expr(tp, in->in_sym, tn);
- /* Using initsym here is better than nothing. */
- check_init_expr(in->in_brace_level->bl_type, in->in_sym, tn);
-
- in->in_brace_level->bl_remaining--;
- debug_step("%d elements remaining", in->in_brace_level->bl_remaining);
-
-done_debug:
- initialization_debug(in);
-
+advance:
+ if (in->in_brace_level != NULL)
+ brace_level_advance(in->in_brace_level);
done:
- while (in->in_designation.dn_head != NULL)
- designation_shift_level(&in->in_designation);
-
+ initialization_remove_designation(in);
+ initialization_debug(in);
debug_leave();
}
+
+static struct initialization *init;
+
+
static struct initialization *
current_init(void)
{
@@ -1414,13 +1017,6 @@
return init;
}
-bool *
-current_initerr(void)
-{
-
- return ¤t_init()->in_err;
-}
-
sym_t **
current_initsym(void)
{
@@ -1434,8 +1030,12 @@
struct initialization *in;
debug_step("begin initialization of '%s'", type_name(sym->s_type));
+#ifdef DEBUG
+ debug_indentation++;
+#endif
+
in = initialization_new(sym);
- in->in_next = init;
+ in->in_enclosing = init;
init = in;
}
@@ -1445,8 +1045,12 @@
struct initialization *in;
in = init;
- init = init->in_next;
+ init = in->in_enclosing;
initialization_free(in);
+
+#ifdef DEBUG
+ debug_indentation--;
+#endif
debug_step("end initialization");
}
@@ -1454,33 +1058,25 @@
add_designator_member(sbuf_t *sb)
{
- designation_add(¤t_init()->in_designation,
- designator_new(sb->sb_name));
+ initialization_add_designator(current_init(), sb->sb_name, 0);
}
void
add_designator_subscript(range_t range)
{
- initialization_add_designator_subscript(current_init(), range);
+ initialization_add_designator(current_init(), NULL, range.hi);
}
void
-initstack_init(void)
-{
-
- initialization_init(current_init());
-}
-
-void
init_lbrace(void)
{
- initialization_lbrace(current_init());
+ initialization_begin_brace_level(current_init());
}
void
-init_using_expr(tnode_t *tn)
+init_expr(tnode_t *tn)
{
initialization_expr(current_init(), tn);
@@ -1490,5 +1086,5 @@
init_rbrace(void)
{
- initialization_rbrace(current_init());
+ initialization_end_brace_level(current_init());
}