On Wed, Jun 6, 2018, 4:43 PM Marek Polacek <pola...@redhat.com> wrote:
> 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. Right, you want to test conversion to the element type, not the array or init list type. 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}); > +} >