aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/c/ChangeLog12
-rw-r--r--gcc/c/c-parser.c18
-rw-r--r--gcc/c/c-tree.h1
-rw-r--r--gcc/c/c-typeck.c53
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/pr69522.c9
6 files changed, 65 insertions, 33 deletions
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index b595b81..dda2216 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,15 @@
+2016-02-12 Bernd Schmidt <bschmidt@redhat.com>
+
+ PR c/69522
+ * c-parser.c (c_parser_braced_init): New arg outer_obstack. All
+ callers changed. If nested_p is true, use it to call
+ finish_implicit_inits.
+ * c-tree.h (finish_implicit_inits): Declare.
+ * c-typeck.c (finish_implicit_inits): New function. Move code
+ from ...
+ (push_init_level): ... here.
+ (set_designator, process_init_element): Call finish_implicit_inits.
+
2016-02-11 Jakub Jelinek <jakub@redhat.com>
PR c/69768
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index eede3a7..7a27244 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -1293,7 +1293,8 @@ static tree c_parser_simple_asm_expr (c_parser *);
static tree c_parser_attributes (c_parser *);
static struct c_type_name *c_parser_type_name (c_parser *);
static struct c_expr c_parser_initializer (c_parser *);
-static struct c_expr c_parser_braced_init (c_parser *, tree, bool);
+static struct c_expr c_parser_braced_init (c_parser *, tree, bool,
+ struct obstack *);
static void c_parser_initelt (c_parser *, struct obstack *);
static void c_parser_initval (c_parser *, struct c_expr *,
struct obstack *);
@@ -4307,7 +4308,7 @@ static struct c_expr
c_parser_initializer (c_parser *parser)
{
if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
- return c_parser_braced_init (parser, NULL_TREE, false);
+ return c_parser_braced_init (parser, NULL_TREE, false, NULL);
else
{
struct c_expr ret;
@@ -4327,7 +4328,8 @@ c_parser_initializer (c_parser *parser)
top-level initializer in a declaration. */
static struct c_expr
-c_parser_braced_init (c_parser *parser, tree type, bool nested_p)
+c_parser_braced_init (c_parser *parser, tree type, bool nested_p,
+ struct obstack *outer_obstack)
{
struct c_expr ret;
struct obstack braced_init_obstack;
@@ -4336,7 +4338,10 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p)
gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE));
c_parser_consume_token (parser);
if (nested_p)
- push_init_level (brace_loc, 0, &braced_init_obstack);
+ {
+ finish_implicit_inits (brace_loc, outer_obstack);
+ push_init_level (brace_loc, 0, &braced_init_obstack);
+ }
else
really_start_incremental_init (type);
if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
@@ -4594,7 +4599,8 @@ c_parser_initval (c_parser *parser, struct c_expr *after,
location_t loc = c_parser_peek_token (parser)->location;
if (c_parser_next_token_is (parser, CPP_OPEN_BRACE) && !after)
- init = c_parser_braced_init (parser, NULL_TREE, true);
+ init = c_parser_braced_init (parser, NULL_TREE, true,
+ braced_init_obstack);
else
{
init = c_parser_expr_no_commas (parser, after);
@@ -8083,7 +8089,7 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser,
error_at (type_loc, "compound literal has variable size");
type = error_mark_node;
}
- init = c_parser_braced_init (parser, type, false);
+ init = c_parser_braced_init (parser, type, false, NULL);
finish_init ();
maybe_warn_string_init (type_loc, type, init);
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index cf79ba7..96ab049 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -625,6 +625,7 @@ extern void maybe_warn_string_init (location_t, tree, struct c_expr);
extern void start_init (tree, tree, int);
extern void finish_init (void);
extern void really_start_incremental_init (tree);
+extern void finish_implicit_inits (location_t, struct obstack *);
extern void push_init_level (location_t, int, struct obstack *);
extern struct c_expr pop_init_level (location_t, int, struct obstack *);
extern void set_init_index (location_t, tree, tree, struct obstack *);
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 82efacf..1122a88 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -7548,6 +7548,30 @@ really_start_incremental_init (tree type)
}
}
+/* Called when we see an open brace for a nested initializer. Finish
+ off any pending levels with implicit braces. */
+void
+finish_implicit_inits (location_t loc, struct obstack *braced_init_obstack)
+{
+ while (constructor_stack->implicit)
+ {
+ if (RECORD_OR_UNION_TYPE_P (constructor_type)
+ && constructor_fields == 0)
+ process_init_element (input_location,
+ pop_init_level (loc, 1, braced_init_obstack),
+ true, braced_init_obstack);
+ else if (TREE_CODE (constructor_type) == ARRAY_TYPE
+ && constructor_max_index
+ && tree_int_cst_lt (constructor_max_index,
+ constructor_index))
+ process_init_element (input_location,
+ pop_init_level (loc, 1, braced_init_obstack),
+ true, braced_init_obstack);
+ else
+ break;
+ }
+}
+
/* Push down into a subobject, for initialization.
If this is for an explicit set of braces, IMPLICIT is 0.
If it is because the next element belongs at a lower level,
@@ -7560,33 +7584,6 @@ push_init_level (location_t loc, int implicit,
struct constructor_stack *p;
tree value = NULL_TREE;
- /* If we've exhausted any levels that didn't have braces,
- pop them now. If implicit == 1, this will have been done in
- process_init_element; do not repeat it here because in the case
- of excess initializers for an empty aggregate this leads to an
- infinite cycle of popping a level and immediately recreating
- it. */
- if (implicit != 1)
- {
- while (constructor_stack->implicit)
- {
- if (RECORD_OR_UNION_TYPE_P (constructor_type)
- && constructor_fields == 0)
- process_init_element (input_location,
- pop_init_level (loc, 1, braced_init_obstack),
- true, braced_init_obstack);
- else if (TREE_CODE (constructor_type) == ARRAY_TYPE
- && constructor_max_index
- && tree_int_cst_lt (constructor_max_index,
- constructor_index))
- process_init_element (input_location,
- pop_init_level (loc, 1, braced_init_obstack),
- true, braced_init_obstack);
- else
- break;
- }
- }
-
/* Unless this is an explicit brace, we need to preserve previous
content if any. */
if (implicit)
@@ -8013,6 +8010,7 @@ set_designator (location_t loc, int array,
}
constructor_designated = 1;
+ finish_implicit_inits (loc, braced_init_obstack);
push_init_level (loc, 2, braced_init_obstack);
return 0;
}
@@ -9396,6 +9394,7 @@ process_init_element (location_t loc, struct c_expr value, bool implicit,
p = p->next;
if (!p)
break;
+ finish_implicit_inits (loc, braced_init_obstack);
push_init_level (loc, 2, braced_init_obstack);
p->stack = constructor_stack;
if (p->range_end && tree_int_cst_equal (p->index, p->range_end))
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 5fcd863..cd3161f 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2016-02-12 Bernd Schmidt <bschmidt@redhat.com>
+
+ PR c/69522
+ gcc.dg/pr69522.c: New test.
+
2016-02-12 Patrick Palka <ppalka@gcc.gnu.org>
PR c++/69098
diff --git a/gcc/testsuite/gcc.dg/pr69522.c b/gcc/testsuite/gcc.dg/pr69522.c
new file mode 100644
index 0000000..452a1ae
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr69522.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+struct str {};
+struct {
+ struct str b;
+ float c[1];
+ int d[1];
+ float e[2];
+ int f[1];
+} a = {{}, 0, {0.5}, 0, 0, {0}};