Skip to content

Commit

Permalink
c++: designated init and aggregate members [PR103337]
Browse files Browse the repository at this point in the history
Our C++20 designated initializer handling was broken with members of class
type; we would find the relevant member and then try to find a member of
the member with the same name.  Or we would sometimes ignore the designator
entirely.  The former problem is fixed by the change to reshape_init_class,
the latter by the change to reshape_init_r.

	PR c++/103337
	PR c++/102740
	PR c++/103299
	PR c++/102538

gcc/cp/ChangeLog:

	* decl.c (reshape_init_class): Avoid looking for designator
	after we found it.
	(reshape_init_r): Keep looking for designator.

gcc/testsuite/ChangeLog:

	* g++.dg/ext/flexary3.C: Remove one error.
	* g++.dg/parse/pr43765.C: Likewise.
	* g++.dg/cpp2a/desig22.C: New test.
	* g++.dg/cpp2a/desig23.C: New test.
	* g++.dg/cpp2a/desig24.C: New test.
	* g++.dg/cpp2a/desig25.C: New test.
  • Loading branch information
jicama authored and antmak committed Apr 12, 2022
1 parent 7dd7099 commit 011e89d
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 9 deletions.
47 changes: 42 additions & 5 deletions gcc/cp/decl.c
Original file line number Diff line number Diff line change
Expand Up @@ -6377,8 +6377,9 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p,
{
tree field_init;
constructor_elt *old_cur = d->cur;
bool direct_desig = false;

/* Handle designated initializers, as an extension. */
/* Handle C++20 designated initializers. */
if (d->cur->index)
{
if (d->cur->index == error_mark_node)
Expand All @@ -6396,7 +6397,10 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p,
}
}
else if (TREE_CODE (d->cur->index) == IDENTIFIER_NODE)
field = get_class_binding (type, d->cur->index);
{
field = get_class_binding (type, d->cur->index);
direct_desig = true;
}
else
{
if (complain & tf_error)
Expand Down Expand Up @@ -6442,6 +6446,7 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p,
break;
gcc_assert (aafield);
field = aafield;
direct_desig = false;
}
}

Expand All @@ -6456,9 +6461,32 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p,
assumed to correspond to no elements of the initializer list. */
goto continue_;

field_init = reshape_init_r (TREE_TYPE (field), d,
/*first_initializer_p=*/NULL_TREE,
complain);
if (direct_desig)
{
/* The designated field F is initialized from this one element:
Temporarily clear the designator so a recursive reshape_init_class
doesn't try to find it again in F, and adjust d->end so we don't
try to use the next initializer to initialize another member of F.

Note that we don't want these changes if we found the designator
inside an anon aggr above; we leave them alone to implement:

"If the element is an anonymous union member and the initializer
list is a brace-enclosed designated- initializer-list, the element
is initialized by the designated-initializer-list { D }, where D
is the designated- initializer-clause naming a member of the
anonymous union member." */
auto end_ = make_temp_override (d->end, d->cur + 1);
auto idx_ = make_temp_override (d->cur->index, NULL_TREE);
field_init = reshape_init_r (TREE_TYPE (field), d,
/*first_initializer_p=*/NULL_TREE,
complain);
}
else
field_init = reshape_init_r (TREE_TYPE (field), d,
/*first_initializer_p=*/NULL_TREE,
complain);

if (field_init == error_mark_node)
return error_mark_node;

Expand Down Expand Up @@ -6708,6 +6736,15 @@ reshape_init_r (tree type, reshape_iter *d, tree first_initializer_p,
to handle initialization of arrays and similar. */
else if (COMPOUND_LITERAL_P (stripped_init))
gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (stripped_init));
/* If we have an unresolved designator, we need to find the member it
designates within TYPE, so proceed to the routines below. For
FIELD_DECL or INTEGER_CST designators, we're already initializing
the designated element. */
else if (d->cur->index
&& TREE_CODE (d->cur->index) == IDENTIFIER_NODE)
/* Brace elision with designators is only permitted for anonymous
aggregates. */
gcc_checking_assert (ANON_AGGR_TYPE_P (type));
/* A CONSTRUCTOR of the target's type is a previously
digested initializer. */
else if (same_type_ignoring_top_level_qualifiers_p (type, init_type))
Expand Down
11 changes: 11 additions & 0 deletions gcc/testsuite/g++.dg/cpp2a/desig22.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// PR c++/103337
// { dg-do compile { target c++20 } }

struct op_t {
struct put_t {
int x;
} put;
};

op_t x{0}; // OK
op_t y{.put=0}; // bogus error: 'op_t::put_t' has no non-static data member named 'put'
20 changes: 20 additions & 0 deletions gcc/testsuite/g++.dg/cpp2a/desig23.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// PR c++/102740
// { dg-do compile { target c++20 } }
// { dg-additional-options -Wmissing-braces }

typedef struct {
union {
struct {
const void* content;
} put;
};
} op_t;

op_t f(const char* alias) {
return op_t{
.put =
{
.content = alias,
},
}; // { dg-warning "missing braces" }
}
11 changes: 11 additions & 0 deletions gcc/testsuite/g++.dg/cpp2a/desig24.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// PR c++/103299
// { dg-do compile { target c++20 } }

struct foo {
union {
int fp1{};
char fp2;
};
};

static_assert(foo{.fp2={}}.fp2 == 0);
13 changes: 13 additions & 0 deletions gcc/testsuite/g++.dg/cpp2a/desig25.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// PR c++/102538
// { dg-do run { target c++20 } }

struct X { union { char r8[8]; int r32[2]; }; };
struct Y { X v[1]; };
Y x = { { { .r32 = { 5, 6 } } } };

int
main ()
{
if (x.v[0].r32[0] != 5 || x.v[0].r32[1] != 6)
__builtin_abort ();
}
2 changes: 1 addition & 1 deletion gcc/testsuite/g++.dg/ext/flexary3.C
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ struct s {

int main()
{
struct s s = { .c = 0 }; // { dg-error "initializer" }
struct s s = { .c = 0 };
// { dg-error "non-static initialization of a flexible array member" "" { target *-*-* } .-1 }
return 0;
}
6 changes: 3 additions & 3 deletions gcc/testsuite/g++.dg/parse/pr43765.C
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ SomeType vals[] =
{
{ 0, values : temp, }, // { dg-error "either all initializer clauses should be designated or none of them should be" "" { target c++2a } }
0
}; // { dg-error "GNU-style designated initializer for an array|cannot convert" }
// (note the error above is on the wrong line)
// { dg-error "initialization of flexible array member in a nested context" "" { target *-*-* } .-2 }
};
// (note the error below is on the wrong line)
// { dg-error "initialization of flexible array member in a nested context" "" { target *-*-* } .-2 }

0 comments on commit 011e89d

Please sign in to comment.