aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/call.cc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2022-12-14 17:42:52 -0500
committerJason Merrill <jason@redhat.com>2022-12-15 00:26:13 -0500
commit4ef521bbc63f8a3883d507a8b6c1f95f442df3fe (patch)
tree83306869a166ea795ca55b4d6944dce955803c04 /gcc/cp/call.cc
parent26f4aefaebc056acacc2a842f5b092ed9e671ef0 (diff)
downloadgcc-4ef521bbc63f8a3883d507a8b6c1f95f442df3fe.zip
gcc-4ef521bbc63f8a3883d507a8b6c1f95f442df3fe.tar.gz
gcc-4ef521bbc63f8a3883d507a8b6c1f95f442df3fe.tar.bz2
c++: fix initializer_list transformation [PR108071]
In these testcases, we weren't adequately verifying that constructing the element type from an array element would have the same effect as constructing it from one of the initializers. PR c++/108071 PR c++/105838 gcc/cp/ChangeLog: * call.cc (struct conversion_obstack_sentinel): New. (maybe_init_list_as_array): Compare conversion of dummy argument. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/initlist131.C: New test. * g++.dg/cpp0x/initlist132.C: New test. * g++.dg/cpp0x/initlist133.C: New test.
Diffstat (limited to 'gcc/cp/call.cc')
-rw-r--r--gcc/cp/call.cc35
1 files changed, 29 insertions, 6 deletions
diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 33b5e7f8..c25df17 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -622,6 +622,15 @@ conversion_obstack_alloc (size_t n)
return p;
}
+/* RAII class to discard anything added to conversion_obstack. */
+
+struct conversion_obstack_sentinel
+{
+ void *p;
+ conversion_obstack_sentinel (): p (conversion_obstack_alloc (0)) {}
+ ~conversion_obstack_sentinel () { obstack_free (&conversion_obstack, p); }
+};
+
/* Allocate rejection reasons. */
static struct rejection_reason *
@@ -4219,18 +4228,32 @@ static tree
maybe_init_list_as_array (tree elttype, tree init)
{
/* Only do this if the array can go in rodata but not once converted. */
- if (!CLASS_TYPE_P (elttype))
+ if (!TYPE_NON_AGGREGATE_CLASS (elttype))
return NULL_TREE;
tree init_elttype = braced_init_element_type (init);
if (!init_elttype || !SCALAR_TYPE_P (init_elttype) || !TREE_CONSTANT (init))
return NULL_TREE;
+ /* Check with a stub expression to weed out special cases, and check whether
+ we call the same function for direct-init as copy-list-init. */
+ conversion_obstack_sentinel cos;
+ tree arg = build_stub_object (init_elttype);
+ conversion *c = implicit_conversion (elttype, init_elttype, arg, false,
+ LOOKUP_NORMAL, tf_none);
+ if (c && c->kind == ck_rvalue)
+ c = next_conversion (c);
+ if (!c || c->kind != ck_user)
+ return NULL_TREE;
+
tree first = CONSTRUCTOR_ELT (init, 0)->value;
- if (TREE_CODE (init_elttype) == INTEGER_TYPE && null_ptr_cst_p (first))
- /* Avoid confusion from treating 0 as a null pointer constant. */
- first = build1 (UNARY_PLUS_EXPR, init_elttype, first);
- first = (perform_implicit_conversion_flags
- (elttype, first, tf_none, LOOKUP_IMPLICIT|LOOKUP_NO_NARROWING));
+ conversion *fc = implicit_conversion (elttype, init_elttype, first, false,
+ LOOKUP_IMPLICIT|LOOKUP_NO_NARROWING,
+ tf_none);
+ if (fc && fc->kind == ck_rvalue)
+ fc = next_conversion (fc);
+ if (!fc || fc->kind != ck_user || fc->cand->fn != c->cand->fn)
+ return NULL_TREE;
+ first = convert_like (fc, first, tf_none);
if (first == error_mark_node)
/* Let the normal code give the error. */
return NULL_TREE;