On Thu, Dec 12, 2024 at 4:08 PM Patrick Palka <[email protected]> wrote:
>
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look
> OK for trunk only? The original testcase from the PR seems to compile
> successfully on the release branches so I'm avoiding doing anything on
> the release branches for now.
Ping.
>
> -- >8 --
>
> Ever since r15-3530-gdfb63765e994be the extra-args mechanism now expects
> to see tf_partial whenever doing a partial substitution containing
> dependent arguments. The below testcase shows that instantiate_template
> for AT with args={T}/{T*}A is neglecting to set it in that case, and we
> end up ICEing from add_extra_args during the subsequent full substitution.
> This patch just fixes this by setting tf_partial appropriately.
>
> PR c++/117887
>
> gcc/cp/ChangeLog:
>
> * pt.cc (instantiate_template): Set tf_partial if arguments are
> dependent.
>
> gcc/testsuite/ChangeLog:
>
> * g++.dg/cpp2a/concepts-requires39.C: New test.
> * g++.dg/cpp2a/lambda-targ10.C: New test.
> ---
> gcc/cp/pt.cc | 15 ++++++++++++---
> .../g++.dg/cpp2a/concepts-requires39.C | 17 +++++++++++++++++
> gcc/testsuite/g++.dg/cpp2a/lambda-targ10.C | 17 +++++++++++++++++
> 3 files changed, 46 insertions(+), 3 deletions(-)
> create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-requires39.C
> create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-targ10.C
>
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index 2f2ec39b083..781590ab2e0 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -22272,7 +22272,11 @@ instantiate_template (tree tmpl, tree orig_args,
> tsubst_flags_t complain)
> substitution of a template variable, but the type of the variable
> template may be auto, in which case we will call do_auto_deduction
> in mark_used (which clears tf_partial) and the auto must be properly
> - reduced at that time for the deduction to work. */
> + reduced at that time for the deduction to work.
> +
> + Note that later below we set tf_partial iff there are dependent
> + arguments, but the above is concerned specifically about the
> + non-dependent case. */
> complain &= tf_warning_or_error;
>
> gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL);
> @@ -22351,9 +22355,14 @@ instantiate_template (tree tmpl, tree orig_args,
> tsubst_flags_t complain)
> template, not the context of the overload resolution we're doing. */
> push_to_top_level ();
> /* If there are dependent arguments, e.g. because we're doing partial
> - ordering, make sure processing_template_decl stays set. */
> + ordering, make sure processing_template_decl stays set. And set
> + tf_partial mainly for benefit of instantiation of alias templates
> + that contain extra-args trees. */
> if (uses_template_parms (targ_ptr))
> - ++processing_template_decl;
> + {
> + ++processing_template_decl;
> + complain |= tf_partial;
> + }
> if (DECL_CLASS_SCOPE_P (gen_tmpl))
> {
> tree ctx;
> diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-requires39.C
> b/gcc/testsuite/g++.dg/cpp2a/concepts-requires39.C
> new file mode 100644
> index 00000000000..b13682033da
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-requires39.C
> @@ -0,0 +1,17 @@
> +// PR c++/117887
> +// { dg-do compile { target c++20 } }
> +
> +template<bool V> struct A { static constexpr bool value = V; };
> +
> +template<class T>
> +using AT = A<requires { requires sizeof(T) != sizeof(T*); }>;
> +
> +template<class T> struct B { using type = T; };
> +
> +template<class T>
> +void f() {
> + static_assert( B<AT<T>>::type::value);
> + static_assert(!B<AT<T*>>::type::value);
> +}
> +
> +template void f<char>();
> diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-targ10.C
> b/gcc/testsuite/g++.dg/cpp2a/lambda-targ10.C
> new file mode 100644
> index 00000000000..7f175c93062
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp2a/lambda-targ10.C
> @@ -0,0 +1,17 @@
> +// PR c++/117887
> +// { dg-do compile { target c++20 } }
> +
> +template<bool V, class T> struct A { static constexpr bool value = V; };
> +
> +template<class T>
> +using AT = A<[]{return sizeof(T) != sizeof(T*); }(), T>;
> +
> +template<class T> struct B { using type = T; };
> +
> +template<class T>
> +void f() {
> + static_assert( B<AT<T>>::type::value);
> + static_assert(!B<AT<T*>>::type::value);
> +}
> +
> +template void f<char>();
> --
> 2.47.1.440.gcaacdb5dfd
>