diff options
author | Marek Polacek <polacek@redhat.com> | 2024-08-28 15:45:49 -0400 |
---|---|---|
committer | Marek Polacek <polacek@redhat.com> | 2024-08-28 18:45:54 -0400 |
commit | 9f79c7ddff5f1b004803931406ad17eaba095fff (patch) | |
tree | d0b1fed04d4679645a4f39e719b609cdd764c410 /gcc | |
parent | b8ef805e4d850971b9926fd81b4f0612ddffaf82 (diff) | |
download | gcc-9f79c7ddff5f1b004803931406ad17eaba095fff.zip gcc-9f79c7ddff5f1b004803931406ad17eaba095fff.tar.gz gcc-9f79c7ddff5f1b004803931406ad17eaba095fff.tar.bz2 |
c++: wrong error due to std::initializer_list opt [PR116476]
Here maybe_init_list_as_array gets elttype=field, init={NON_LVALUE_EXPR <2>}
and it tries to convert the init's element type (int) to field
using implicit_conversion, which works, so overall maybe_init_list_as_array
is successful.
But it constifies init_elttype so we end up with "const int". Later,
when we actually perform the conversion and invoke field::field(T&&),
we end up with this error:
error: binding reference of type 'int&&' to 'const int' discards qualifiers
So I think maybe_init_list_as_array should try to perform the conversion,
like it does below with fc.
PR c++/116476
gcc/cp/ChangeLog:
* call.cc (maybe_init_list_as_array): Try convert_like and see if it
worked.
gcc/testsuite/ChangeLog:
* g++.dg/cpp0x/initlist-opt2.C: New test.
Reviewed-by: Jason Merrill <jason@redhat.com>
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/call.cc | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/initlist-opt2.C | 21 |
2 files changed, 26 insertions, 1 deletions
diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index 623e4c6..fa7f05d 100644 --- a/gcc/cp/call.cc +++ b/gcc/cp/call.cc @@ -4319,6 +4319,7 @@ maybe_init_list_as_array (tree elttype, tree init) /* 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; + init_elttype = cp_build_qualified_type (init_elttype, TYPE_QUAL_CONST); tree arg = build_stub_object (init_elttype); conversion *c = implicit_conversion (elttype, init_elttype, arg, false, LOOKUP_NORMAL, tf_none); @@ -4326,6 +4327,10 @@ maybe_init_list_as_array (tree elttype, tree init) c = next_conversion (c); if (!c || c->kind != ck_user) return NULL_TREE; + /* Check that we actually can perform the conversion. */ + if (convert_like (c, arg, tf_none) == error_mark_node) + /* Let the normal code give the error. */ + return NULL_TREE; tree first = CONSTRUCTOR_ELT (init, 0)->value; conversion *fc = implicit_conversion (elttype, init_elttype, first, false, @@ -4358,7 +4363,6 @@ maybe_init_list_as_array (tree elttype, tree init) if (!is_xible (INIT_EXPR, elttype, copy_argtypes)) return NULL_TREE; - init_elttype = cp_build_qualified_type (init_elttype, TYPE_QUAL_CONST); tree arr = build_array_of_n_type (init_elttype, CONSTRUCTOR_NELTS (init)); arr = finish_compound_literal (arr, init, tf_none); DECL_MERGEABLE (TARGET_EXPR_SLOT (arr)) = true; diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-opt2.C b/gcc/testsuite/g++.dg/cpp0x/initlist-opt2.C new file mode 100644 index 0000000..6c71857 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/initlist-opt2.C @@ -0,0 +1,21 @@ +// PR c++/116476 +// { dg-do compile { target c++11 } } + +namespace std { +template <typename T> +class initializer_list { + T *_M_len; + __SIZE_TYPE__ size; +}; +} // namespace std + + +template <class T> +struct field { + field(T &&) {} +}; +struct vector { + vector(std::initializer_list<field<int>>) { } +}; + +vector fields_normal{2}; |