aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPatrick Palka <ppalka@redhat.com>2024-08-20 08:34:36 -0400
committerPatrick Palka <ppalka@redhat.com>2024-08-20 08:34:36 -0400
commit5348e3cb9bc99d2ee4d7438b8eca5c92fff5b931 (patch)
treefb41f19ae76754c19116845f1f770419ee283fdb /gcc
parent20a5b4824993ae1c99f3b965c5e07bbd2c64b2ce (diff)
downloadgcc-5348e3cb9bc99d2ee4d7438b8eca5c92fff5b931.zip
gcc-5348e3cb9bc99d2ee4d7438b8eca5c92fff5b931.tar.gz
gcc-5348e3cb9bc99d2ee4d7438b8eca5c92fff5b931.tar.bz2
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 <jason@redhat.com>
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/pt.cc41
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/nontype6.C24
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/nontype6a.C25
3 files changed, 71 insertions, 19 deletions
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index ea660a5..bc3ad5e 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 0000000..06cd234
--- /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 0000000..8bc40a0
--- /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);
+}