On Fri, Jun 01, 2018 at 12:39:08PM -0400, Jason Merrill wrote:
> Yes, we still need to do deduction on the array bound, so we can't
> return immediately.  We just want to avoid the
> 
>       FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (arg), i, elt)
> 
> loop.

Got it.  But then there's this part:

> And then we want to check convertibility of the elements in
> type_unification_real, when we check convertibility of other function
> parameters that don't involve template parameters:
> 
>       /* DR 1391: All parameters have args, now check non-dependent
>       parms for convertibility.  */

which I hoped would be achieved by this:

@@ -20370,6 +20370,16 @@ type_unification_real (tree tparms,
        if (check_non_deducible_conversion (parm, arg, strict, flags,
                        explain_p))
          return 1;
+
+       if (BRACE_ENCLOSED_INITIALIZER_P (arg))
+         {
+       tree elt;
+       unsigned int i;
+       FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (arg), i, elt)
+         if (check_non_deducible_conversion (parm, elt, strict, flags,
+                             explain_p))
+           return 1;
+         }
      }
 
       /* Now substitute into the default template arguments.  */


but that breaks e.g. initlist34.C, because ARG is {0} and PARM is
struct initializer_list, and checking whether we can convert 0 to
struct initializer_list doesn't work, so we return 1.  I've probably
misunderstood what you wanted me to do here.  For the attached testcases
we'll never reach that code anyway, because PARM depends on a template
parameter.

2018-06-05  Marek Polacek  <pola...@redhat.com>

        PR c++/85977
        * pt.c (unify): If ELTTYPE has no deducible template parms, skip
        deduction from the list elements.

        * g++.dg/cpp0x/initlist102.C: New test.
        * g++.dg/cpp0x/initlist103.C: New test.
        * g++.dg/cpp0x/initlist104.C: New test.

diff --git gcc/cp/pt.c gcc/cp/pt.c
index aad68a32643..19c542b76d5 100644
--- gcc/cp/pt.c
+++ gcc/cp/pt.c
@@ -21404,24 +21415,30 @@ unify (tree tparms, tree targs, tree parm, tree arg, 
int strict,
            return unify_success (explain_p);
        }
 
-      FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (arg), i, elt)
-       {
-         int elt_strict = strict;
+      if (strict != DEDUCE_EXACT
+         && TYPE_P (elttype)
+         && !uses_deducible_template_parms (elttype))
+       /* If ELTTYPE has no deducible template parms, skip deduction from
+          the list elements.  */;
+      else
+       FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (arg), i, elt)
+         {
+           int elt_strict = strict;
 
-         if (elt == error_mark_node)
-           return unify_invalid (explain_p);
+           if (elt == error_mark_node)
+             return unify_invalid (explain_p);
 
-         if (!BRACE_ENCLOSED_INITIALIZER_P (elt))
-           {
-             tree type = TREE_TYPE (elt);
-             if (type == error_mark_node)
-               return unify_invalid (explain_p);
-             /* It should only be possible to get here for a call.  */
-             gcc_assert (elt_strict & UNIFY_ALLOW_OUTER_LEVEL);
-             elt_strict |= maybe_adjust_types_for_deduction
-               (DEDUCE_CALL, &elttype, &type, elt);
-             elt = type;
-           }
+           if (!BRACE_ENCLOSED_INITIALIZER_P (elt))
+             {
+               tree type = TREE_TYPE (elt);
+               if (type == error_mark_node)
+                 return unify_invalid (explain_p);
+               /* It should only be possible to get here for a call.  */
+               gcc_assert (elt_strict & UNIFY_ALLOW_OUTER_LEVEL);
+               elt_strict |= maybe_adjust_types_for_deduction
+                 (DEDUCE_CALL, &elttype, &type, elt);
+               elt = type;
+             }
 
          RECUR_AND_CHECK_FAILURE (tparms, targs, elttype, elt, elt_strict,
                                   explain_p);
diff --git gcc/testsuite/g++.dg/cpp0x/initlist102.C 
gcc/testsuite/g++.dg/cpp0x/initlist102.C
index e69de29bb2d..e114866292f 100644
--- gcc/testsuite/g++.dg/cpp0x/initlist102.C
+++ gcc/testsuite/g++.dg/cpp0x/initlist102.C
@@ -0,0 +1,39 @@
+// PR c++/85977, Incorrect handling of array reference size deduction
+// { dg-do compile { target c++11 } }
+
+template <int N>
+void fn1 (const char (&)[N]) { static_assert (N == 3, "fn1");}
+
+template <int N>
+void fn2 (const short (&)[N]) { static_assert (N == 3, "fn2");}
+
+template <int N>
+void fn3 (const int (&)[N]) { static_assert (N == 3, "fn2");}
+
+template <int N>
+void fn4 (const long (&)[N]) { static_assert (N == 3, "fn4");}
+
+template <int N>
+void fn5 (const unsigned char (&)[N]) { static_assert (N == 3, "fn5");}
+
+template <int N>
+void fn6 (const unsigned short (&)[N]) { static_assert (N == 3, "fn6");}
+
+template <int N>
+void fn7 (const unsigned int (&)[N]) { static_assert (N == 3, "fn7");}
+
+template <int N>
+void fn8 (const unsigned int (&)[N]) { static_assert (N == 3, "fn8");}
+
+void
+bar ()
+{
+  fn1 ({1, 2, 3});
+  fn2 ({1, 2, 3});
+  fn3 ({1, 2, 3});
+  fn4 ({1, 2, 3});
+  fn5 ({1, 2, 3});
+  fn6 ({1, 2, 3});
+  fn7 ({1, 2, 3});
+  fn8 ({1, 2, 3});
+}
diff --git gcc/testsuite/g++.dg/cpp0x/initlist103.C 
gcc/testsuite/g++.dg/cpp0x/initlist103.C
index e69de29bb2d..0c1923c6ab0 100644
--- gcc/testsuite/g++.dg/cpp0x/initlist103.C
+++ gcc/testsuite/g++.dg/cpp0x/initlist103.C
@@ -0,0 +1,11 @@
+// PR c++/85977, Incorrect handling of array reference size deduction
+// { dg-do compile { target c++11 } }
+
+template <int N>
+void fn (const char (&)[N]) { }
+
+void
+bar ()
+{
+  fn ({1.2}); // { dg-error "narrowing" }
+}
diff --git gcc/testsuite/g++.dg/cpp0x/initlist104.C 
gcc/testsuite/g++.dg/cpp0x/initlist104.C
index e69de29bb2d..99487a70607 100644
--- gcc/testsuite/g++.dg/cpp0x/initlist104.C
+++ gcc/testsuite/g++.dg/cpp0x/initlist104.C
@@ -0,0 +1,11 @@
+// PR c++/85977, Incorrect handling of array reference size deduction
+// { dg-do compile { target c++11 } }
+
+template <typename T, int N>
+void fn (const T (&)[N]) { static_assert (N == 3, "fn"); }
+
+void
+bar ()
+{
+  fn ({1, 2, 3});
+}

Reply via email to