Commit 23f1f679 by Patrick Palka

c++: Fix usage of CONSTRUCTOR_PLACEHOLDER_BOUNDARY inside array initializers [PR90996]

This PR reports that ever since the introduction of the
CONSTRUCTOR_PLACEHOLDER_BOUNDARY flag, we are sometimes failing to resolve
PLACEHOLDER_EXPRs inside array initializers that refer to some inner
constructor.  In the testcase in the PR, we have as the initializer for "S c[];"
the following

  {{.a=(int &) &_ZGR1c_, .b={*(&<PLACEHOLDER_EXPR struct S>)->a}}}

where CONSTRUCTOR_PLACEHOLDER_BOUNDARY is set on the middle constructor.  When
calling replace_placeholders from store_init_value, we pass the entire
initializer to it, and as a result we fail to resolve the PLACEHOLDER_EXPR
within due to the CONSTRUCTOR_PLACEHOLDER_BOUNDARY flag on the middle
constructor blocking replace_placeholders_r from reaching it.

To fix this, we could perhaps either call replace_placeholders in more places,
or we could change where we set CONSTRUCTOR_PLACEHOLDER_BOUNDARY.  This patch
takes this latter approach -- when building up an array initializer, we now
bubble any CONSTRUCTOR_PLACEHOLDER_BOUNDARY flag from the element initializers
up to the array initializer so that the boundary doesn't later impede us when we
call replace_placeholders from store_init_value.

Besides fixing the kind of code like in the testcase, this shouldn't cause any
other differences in PLACEHOLDER_EXPR resolution because we don't create or use
PLACEHOLDER_EXPRs of array type in the frontend, as far as I can tell.

gcc/cp/ChangeLog:

	PR c++/90996
	* tree.c (replace_placeholders): Look through all handled components,
	not just COMPONENT_REFs.
	* typeck2.c (process_init_constructor_array): Propagate
	CONSTRUCTOR_PLACEHOLDER_BOUNDARY up from each element initializer to
	the array initializer.

gcc/testsuite/ChangeLog:

	PR c++/90996
	* g++.dg/cpp1y/pr90996.C: New test.
parent d51af82b
2020-04-07 Patrick Palka <ppalka@redhat.com>
PR c++/90996
* tree.c (replace_placeholders): Look through all handled components,
not just COMPONENT_REFs.
* typeck2.c (process_init_constructor_array): Propagate
CONSTRUCTOR_PLACEHOLDER_BOUNDARY up from each element initializer to
the array initializer.
2020-04-07 Jakub Jelinek <jakub@redhat.com>
PR c++/94512
......
......@@ -3247,7 +3247,7 @@ replace_placeholders (tree exp, tree obj, bool *seen_p /*= NULL*/)
/* If the object isn't a (member of a) class, do nothing. */
tree op0 = obj;
while (TREE_CODE (op0) == COMPONENT_REF)
while (handled_component_p (op0))
op0 = TREE_OPERAND (op0, 0);
if (!CLASS_TYPE_P (strip_array_types (TREE_TYPE (op0))))
return exp;
......
......@@ -1488,6 +1488,17 @@ process_init_constructor_array (tree type, tree init, int nested, int flags,
= massage_init_elt (TREE_TYPE (type), ce->value, nested, flags,
complain);
if (TREE_CODE (ce->value) == CONSTRUCTOR
&& CONSTRUCTOR_PLACEHOLDER_BOUNDARY (ce->value))
{
/* Shift CONSTRUCTOR_PLACEHOLDER_BOUNDARY from the element initializer
up to the array initializer, so that the call to
replace_placeholders from store_init_value can resolve any
PLACEHOLDER_EXPRs inside this element initializer. */
CONSTRUCTOR_PLACEHOLDER_BOUNDARY (ce->value) = 0;
CONSTRUCTOR_PLACEHOLDER_BOUNDARY (init) = 1;
}
gcc_checking_assert
(ce->value == error_mark_node
|| (same_type_ignoring_top_level_qualifiers_p
......@@ -1516,6 +1527,13 @@ process_init_constructor_array (tree type, tree init, int nested, int flags,
/* The default zero-initialization is fine for us; don't
add anything to the CONSTRUCTOR. */
next = NULL_TREE;
else if (TREE_CODE (next) == CONSTRUCTOR
&& CONSTRUCTOR_PLACEHOLDER_BOUNDARY (next))
{
/* As above. */
CONSTRUCTOR_PLACEHOLDER_BOUNDARY (next) = 0;
CONSTRUCTOR_PLACEHOLDER_BOUNDARY (init) = 1;
}
}
else if (!zero_init_p (TREE_TYPE (type)))
next = build_zero_init (TREE_TYPE (type),
......
2020-04-07 Patrick Palka <ppalka@redhat.com>
PR c++/90996
* g++.dg/cpp1y/pr90996.C: New test.
2020-04-07 Jakub Jelinek <jakub@redhat.com>
PR target/94509
......
// PR c++/90996
// { dg-do compile { target c++14 } }
struct S
{
int &&a = 2;
int b[1] {a};
};
S c[2][2] {{{5}}};
struct T
{
S c[2][2] {{{7}}};
};
T d {};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment