diff options
author | Patrick Palka <ppalka@redhat.com> | 2020-04-06 14:05:44 -0400 |
---|---|---|
committer | Patrick Palka <ppalka@redhat.com> | 2020-04-07 09:04:30 -0400 |
commit | 23f1f679141bbb4720ca195cb758605dc017b7fd (patch) | |
tree | 99de79d9c5b3ab3c5c00dfd98a2a480e6b2c94a2 /gcc | |
parent | d51af82b4cf4c95c4a7451df2180cc6ebb44856b (diff) | |
download | gcc-23f1f679141bbb4720ca195cb758605dc017b7fd.zip gcc-23f1f679141bbb4720ca195cb758605dc017b7fd.tar.gz gcc-23f1f679141bbb4720ca195cb758605dc017b7fd.tar.bz2 |
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.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/cp/tree.c | 2 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 18 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1y/pr90996.C | 17 |
5 files changed, 50 insertions, 1 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 4452796..67bee23 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +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 diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 5eb0dcd..d1192b7 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -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; diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index cf1cb5a..56fd9ba 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -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), diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index af475d4..982f0b1 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +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 diff --git a/gcc/testsuite/g++.dg/cpp1y/pr90996.C b/gcc/testsuite/g++.dg/cpp1y/pr90996.C new file mode 100644 index 0000000..780cbb4 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/pr90996.C @@ -0,0 +1,17 @@ +// 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 {}; |