]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: reference variable as default targ [PR101463]
authorPatrick Palka <ppalka@redhat.com>
Tue, 5 Nov 2024 20:18:26 +0000 (15:18 -0500)
committerPatrick Palka <ppalka@redhat.com>
Tue, 5 Nov 2024 20:18:26 +0000 (15:18 -0500)
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 <jason@redhat.com>
gcc/cp/pt.cc
gcc/testsuite/g++.dg/cpp1z/nontype6.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/nontype6a.C [new file with mode: 0644]

index 818d5b65edcecbb6576bf52205590e55620ba2fb..4f83426fb56c59bd806375710ea2b8b60d2bfef2 100644 (file)
@@ -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 (file)
index 0000000..06cd234
--- /dev/null
@@ -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 (file)
index 0000000..8bc40a0
--- /dev/null
@@ -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);
+}