https://gcc.gnu.org/g:5348e3cb9bc99d2ee4d7438b8eca5c92fff5b931

commit r15-3038-g5348e3cb9bc99d2ee4d7438b8eca5c92fff5b931
Author: Patrick Palka <ppa...@redhat.com>
Date:   Tue Aug 20 08:34:36 2024 -0400

    c++: default targ eligibility refinement [PR101463]
    
    On Tue, 9 Jan 2024, Jason Merrill wrote:
    > On 1/5/24 15:01, Patrick Palka wrote[1]:
    > > Here during default template argument substitution we wrongly consider
    > > the (substituted) default arguments v and vt<int> as value-dependent[1]
    > > which ultimately leads to deduction failure for the calls.
    > >
    > > The bogus value_dependent_expression_p result aside, I noticed
    > > type_unification_real during default targ substitution keeps track of
    > > whether all previous targs are known and non-dependent, as is the case
    > > for these calls.  And in such cases it should be safe to avoid checking
    > > dependence of the substituted default targ and just assume it's not.
    > > This patch implements this optimization, which lets us accept both
    > > testcases by sidestepping the value_dependent_expression_p issue
    > > altogether.
    >
    > Hmm, maybe instead of substituting and asking if it's dependent, we should
    > specifically look for undeduced parameters.
    
    This patch implements this refinement, which incidentally fixes PR101463
    just as well.
    
    [1]: https://gcc.gnu.org/pipermail/gcc-patches/2024-January/641957.html
    
            PR c++/101463
    
    gcc/cp/ChangeLog:
    
            * pt.cc (type_unification_real): Directly look for undeduced
            parameters in the default argument instead of doing a trial
            substitution.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/cpp1z/nontype6.C: New test.
            * g++.dg/cpp1z/nontype6a.C: New test.
    
    Reviewed-by: Jason Merrill <ja...@redhat.com>

Diff:
---
 gcc/cp/pt.cc                           | 41 ++++++++++++++++++----------------
 gcc/testsuite/g++.dg/cpp1z/nontype6.C  | 24 ++++++++++++++++++++
 gcc/testsuite/g++.dg/cpp1z/nontype6a.C | 25 +++++++++++++++++++++
 3 files changed, 71 insertions(+), 19 deletions(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index ea660a5a5c6..bc3ad5edcc5 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -23619,28 +23619,31 @@ type_unification_real (tree tparms,
                 is important if the default argument contains something that
                 might be instantiation-dependent like access (87480).  */
              processing_template_decl_sentinel s (!any_dependent_targs);
-             tree substed = NULL_TREE;
-             if (saw_undeduced == 1 && !any_dependent_targs)
+
+             tree used_tparms = NULL_TREE;
+             if (saw_undeduced == 1)
                {
-                 /* First instatiate in template context, in case we still
-                    depend on undeduced template parameters.  */
-                 ++processing_template_decl;
-                 substed = tsubst_template_arg (arg, full_targs, complain,
-                                                NULL_TREE);
-                 --processing_template_decl;
-                 if (substed != error_mark_node
-                     && !uses_template_parms (substed))
-                   /* We replaced all the tparms, substitute again out of
-                      template context.  */
-                   substed = NULL_TREE;
+                 tree tparms_list = build_tree_list (size_int (1), tparms);
+                 used_tparms = find_template_parameters (arg, tparms_list);
+                 for (; used_tparms; used_tparms = TREE_CHAIN (used_tparms))
+                   {
+                     int level, index;
+                     template_parm_level_and_index (TREE_VALUE (used_tparms),
+                                                    &level, &index);
+                     if (TREE_VEC_ELT (targs, index) == NULL_TREE)
+                       break;
+                   }
                }
-             if (!substed)
-               substed = tsubst_template_arg (arg, full_targs, complain,
-                                              NULL_TREE);
 
-             if (!uses_template_parms (substed))
-               arg = convert_template_argument (parm, substed, full_targs,
-                                                complain, i, NULL_TREE);
+             if (!used_tparms)
+               {
+                 /* All template parameters within this default argument are
+                    deduced, so we can use it.  */
+                 arg = tsubst_template_arg (arg, full_targs, complain,
+                                            NULL_TREE);
+                 arg = convert_template_argument (parm, arg, full_targs,
+                                                  complain, i, NULL_TREE);
+               }
              else if (saw_undeduced == 1)
                arg = NULL_TREE;
              else if (!any_dependent_targs)
diff --git a/gcc/testsuite/g++.dg/cpp1z/nontype6.C 
b/gcc/testsuite/g++.dg/cpp1z/nontype6.C
new file mode 100644
index 00000000000..06cd234cc61
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/nontype6.C
@@ -0,0 +1,24 @@
+// PR c++/101463
+// { dg-do compile { target c++17 } }
+
+int a;
+
+int& v = a;
+
+template<const int& = v>
+void f(int) { }
+
+template<class T, int& = v>
+void g(T) { }
+
+template<class T>
+int& vt = a;
+
+template<class T, int& = vt<T>>
+void h(T) { }
+
+int main() {
+  f(0);
+  g(0);
+  h(0);
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/nontype6a.C 
b/gcc/testsuite/g++.dg/cpp1z/nontype6a.C
new file mode 100644
index 00000000000..8bc40a0505c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/nontype6a.C
@@ -0,0 +1,25 @@
+// PR c++/101463
+// A version of nontype6.C where v and vt are constexpr.
+// { dg-do compile { target c++17 } }
+
+int a;
+
+constexpr int& v = a;
+
+template<const int& = v>
+void f(int) { }
+
+template<class T, const int& = v>
+void g(T) { }
+
+template<class T>
+constexpr int& vt = a;
+
+template<class T, const int& = vt<T>>
+void h(T) { }
+
+int main() {
+  f(0);
+  g(0);
+  h(0);
+}

Reply via email to