On 12/12/24 4:08 PM, Patrick Palka 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.

OK.

-- >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>();

Reply via email to