aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Palka <ppalka@redhat.com>2023-09-18 14:54:45 -0400
committerPatrick Palka <ppalka@redhat.com>2023-09-18 14:54:45 -0400
commit80968d5f4683ffb50dbe8051d10f754d5fd00dfb (patch)
tree288034bb500183048407366ba738ec63e84d04b1
parent6e92a6a2a72d3b7a5e1b29042d8a6a43fe1085aa (diff)
downloadgcc-80968d5f4683ffb50dbe8051d10f754d5fd00dfb.zip
gcc-80968d5f4683ffb50dbe8051d10f754d5fd00dfb.tar.gz
gcc-80968d5f4683ffb50dbe8051d10f754d5fd00dfb.tar.bz2
c++: optimize unifying nested templated classes [PR89231]
Since the LHS of a qualified-id is a non-deduced context, it effectively means we can't deduce from outer template arguments of a class template specialization. And checking for equality between the TI_TEMPLATE of a class specialization parm/arg already implies that the outer template arguments are the same. Hence recursing into outer template arguments during unification of class specializations is redundant, so this patch makes unify recurse only into innermost arguments. This incidentally fixes the testcase from PR89231 because there more_specialized_partial_inst wrongly considers the two partial specializations to be unordered ultimately because unify for identical parm=arg=A<Ps...>::Collect<N...> gets confused when it recurses into parm=arg={Ps...} since Ps is outside the (innermost) level of tparms that we're actually deducing. PR c++/89231 gcc/cp/ChangeLog: * pt.cc (try_class_unification): Strengthen TI_TEMPLATE equality test by not calling most_general_template. Only unify the innermost levels of template arguments. (unify) <case CLASS_TYPE>: Only unify the innermost levels of template arguments, and only if the template is primary. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/variadic-partial3.C: New test.
-rw-r--r--gcc/cp/pt.cc18
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-partial3.C19
2 files changed, 31 insertions, 6 deletions
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 31ff80e..777ff59 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -23990,8 +23990,7 @@ try_class_unification (tree tparms, tree targs, tree parm, tree arg,
return NULL_TREE;
else if (TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM)
/* Matches anything. */;
- else if (most_general_template (CLASSTYPE_TI_TEMPLATE (arg))
- != most_general_template (CLASSTYPE_TI_TEMPLATE (parm)))
+ else if (CLASSTYPE_TI_TEMPLATE (arg) != CLASSTYPE_TI_TEMPLATE (parm))
return NULL_TREE;
/* We need to make a new template argument vector for the call to
@@ -24032,8 +24031,10 @@ try_class_unification (tree tparms, tree targs, tree parm, tree arg,
if (TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM)
err = unify_bound_ttp_args (tparms, targs, parm, arg, explain_p);
else
- err = unify (tparms, targs, CLASSTYPE_TI_ARGS (parm),
- CLASSTYPE_TI_ARGS (arg), UNIFY_ALLOW_NONE, explain_p);
+ err = unify (tparms, targs,
+ INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (parm)),
+ INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (arg)),
+ UNIFY_ALLOW_NONE, explain_p);
return err ? NULL_TREE : arg;
}
@@ -25159,8 +25160,13 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
/* There's no chance of unification succeeding. */
return unify_type_mismatch (explain_p, parm, arg);
- return unify (tparms, targs, CLASSTYPE_TI_ARGS (parm),
- CLASSTYPE_TI_ARGS (t), UNIFY_ALLOW_NONE, explain_p);
+ if (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t)))
+ return unify (tparms, targs,
+ INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (parm)),
+ INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (t)),
+ UNIFY_ALLOW_NONE, explain_p);
+ else
+ return unify_success (explain_p);
}
else if (!same_type_ignoring_top_level_qualifiers_p (parm, arg))
return unify_type_mismatch (explain_p, parm, arg);
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-partial3.C b/gcc/testsuite/g++.dg/cpp0x/variadic-partial3.C
new file mode 100644
index 0000000..5af6071
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-partial3.C
@@ -0,0 +1,19 @@
+// PR c++/89231
+// { dg-do compile { target c++11 } }
+
+template<class... Ps>
+struct A {
+ template<int... Ns>
+ struct Collect { };
+
+ template<int C, int I = 0, class S = Collect<>>
+ struct Seq;
+
+ template<int C, int I, int... N>
+ struct Seq<C, I, Collect<N...>> : Seq<C - 1, I + 1, Collect<N..., I>> { };
+
+ template<int I, int... N>
+ struct Seq<0, I, Collect<N...>> : Collect<N...> { };
+};
+
+A<int>::Seq<4> test;