diff options
author | Jason Merrill <jason@redhat.com> | 2022-12-14 17:42:52 -0500 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2022-12-15 00:26:13 -0500 |
commit | 4ef521bbc63f8a3883d507a8b6c1f95f442df3fe (patch) | |
tree | 83306869a166ea795ca55b4d6944dce955803c04 /gcc/cp/call.cc | |
parent | 26f4aefaebc056acacc2a842f5b092ed9e671ef0 (diff) | |
download | gcc-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.cc | 35 |
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; |