This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: C++ PATCH for c++/85977, array reference size deduction failure
- From: Jason Merrill <jason at redhat dot com>
- To: Marek Polacek <polacek at redhat dot com>
- Cc: gcc-patches List <gcc-patches at gcc dot gnu dot org>
- Date: Wed, 6 Jun 2018 18:22:16 +0200
- Subject: Re: C++ PATCH for c++/85977, array reference size deduction failure
- References: <20180530212344.GJ3559@redhat.com> <CADzB+2=EUWAZSNUPMTWJDX76AGxsYDJeRWgf9H7J4qAibbXXLw@mail.gmail.com> <20180601155252.GB23949@redhat.com> <CADzB+2nZn5qhfi3NOtcCxxn_gsPE=mzcp4m9JU_nKJA1Su_acQ@mail.gmail.com> <20180606144302.GA28085@redhat.com>
On Wed, Jun 6, 2018, 4:43 PM Marek Polacek <polacek@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 <polacek@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});
> +}
>