https://gcc.gnu.org/g:9f79c7ddff5f1b004803931406ad17eaba095fff

commit r15-3274-g9f79c7ddff5f1b004803931406ad17eaba095fff
Author: Marek Polacek <pola...@redhat.com>
Date:   Wed Aug 28 15:45:49 2024 -0400

    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 <ja...@redhat.com>

Diff:
---
 gcc/cp/call.cc                             |  6 +++++-
 gcc/testsuite/g++.dg/cpp0x/initlist-opt2.C | 21 +++++++++++++++++++++
 2 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 623e4c66c117..fa7f05d76f68 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 000000000000..6c71857daabc
--- /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};

Reply via email to