https://gcc.gnu.org/g:124f2f62e01c6f110279608ad09e0f1d378e4899

commit r14-10890-g124f2f62e01c6f110279608ad09e0f1d378e4899
Author: Patrick Palka <ppa...@redhat.com>
Date:   Tue Nov 5 15:18:26 2024 -0500

    c++: reference variable as default targ [PR101463]
    
    Here during default template argument substitution we wrongly consider
    the (substituted) default arguments v and vt<int> as value-dependent
    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 for GCC 14, which lets us accept
    both testcases by sidestepping the value_dependent_expression_p issue
    altogether.  (Note that for GCC 15 we fixed this differently, see
    r15-3038-g5348e3cb9bc99d.)
    
            PR c++/101463
    
    gcc/cp/ChangeLog:
    
            * pt.cc (type_unification_real): Avoid checking dependence of
            a substituted default template argument if we can assume it's
            non-dependent.
    
    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                           |  4 +++-
 gcc/testsuite/g++.dg/cpp1z/nontype6.C  | 24 ++++++++++++++++++++++++
 gcc/testsuite/g++.dg/cpp1z/nontype6a.C | 25 +++++++++++++++++++++++++
 3 files changed, 52 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 818d5b65edce..4f83426fb56c 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -23651,12 +23651,14 @@ type_unification_real (tree tparms,
                    /* We replaced all the tparms, substitute again out of
                       template context.  */
                    substed = NULL_TREE;
+                 else
+                   processing_template_decl = 1;
                }
              if (!substed)
                substed = tsubst_template_arg (arg, full_targs, complain,
                                               NULL_TREE);
 
-             if (!uses_template_parms (substed))
+             if (!processing_template_decl || !uses_template_parms (substed))
                arg = convert_template_argument (parm, substed, full_targs,
                                                 complain, i, NULL_TREE);
              else if (saw_undeduced == 1)
diff --git a/gcc/testsuite/g++.dg/cpp1z/nontype6.C 
b/gcc/testsuite/g++.dg/cpp1z/nontype6.C
new file mode 100644
index 000000000000..06cd234cc61a
--- /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 000000000000..8bc40a0505c2
--- /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