From 9f79c7ddff5f1b004803931406ad17eaba095fff Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Wed, 28 Aug 2024 15:45:49 -0400 Subject: [PATCH] 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 --- gcc/cp/call.cc | 6 +++++- gcc/testsuite/g++.dg/cpp0x/initlist-opt2.C | 21 +++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/initlist-opt2.C diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index 623e4c66c11..fa7f05d76f6 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 00000000000..6c71857daab --- /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 +class initializer_list { + T *_M_len; + __SIZE_TYPE__ size; +}; +} // namespace std + + +template +struct field { + field(T &&) {} +}; +struct vector { + vector(std::initializer_list>) { } +}; + +vector fields_normal{2};