aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/pt.cc
diff options
context:
space:
mode:
authorPatrick Palka <ppalka@redhat.com>2022-12-23 09:18:37 -0500
committerPatrick Palka <ppalka@redhat.com>2022-12-23 09:18:37 -0500
commitbd1fc4a219d8c0fad0ec41002e895b49e384c1c2 (patch)
treecd99579216aa7a67a62163ba94967f78c0870e84 /gcc/cp/pt.cc
parentb358521b608f36409281a51263ace3155d28f54d (diff)
downloadgcc-bd1fc4a219d8c0fad0ec41002e895b49e384c1c2.zip
gcc-bd1fc4a219d8c0fad0ec41002e895b49e384c1c2.tar.gz
gcc-bd1fc4a219d8c0fad0ec41002e895b49e384c1c2.tar.bz2
c++: template friend with variadic constraints [PR107853]
When instantiating a constrained hidden template friend, we substitute into its template-head requirements in tsubst_friend_function. For this substitution we use the template's full argument vector whose outer levels correspond to the instantiated class's arguments and innermost level corresponds to the template's own level-lowered generic arguments. But for A<int>::f here, for which the relevant argument vector is {{int}, {Us...}}, the substitution into (C<Ts, Us> && ...) triggers the assert in use_pack_expansion_extra_args_p since one argument is a pack expansion and the other isn't. And for A<int, int>::f, for which the relevant argument vector is {{int, int}, {Us...}}, the use_pack_expansion_extra_args_p assert would also trigger but we first get a bogus "mismatched argument pack lengths" error from tsubst_pack_expansion. Sidestepping the question of whether tsubst_pack_expansion should be able to handle such substitutions, it seems we can work around this by using only the instantiated class's arguments and not also the template friend's own generic arguments, which is consistent with how we normally substitute into the signature of a member template. PR c++/107853 gcc/cp/ChangeLog: * constraint.cc (maybe_substitute_reqs_for): Substitute into the template-head requirements of a template friend using only its outer arguments via outer_template_args. * cp-tree.h (outer_template_args): Declare. * pt.cc (outer_template_args): Define, factored out and generalized from ... (ctor_deduction_guides_for): ... here. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/concepts-friend12.C: New test. * g++.dg/cpp2a/concepts-friend13.C: New test.
Diffstat (limited to 'gcc/cp/pt.cc')
-rw-r--r--gcc/cp/pt.cc34
1 files changed, 24 insertions, 10 deletions
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index e68c749..cbe5898 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -4958,6 +4958,28 @@ generic_targs_for (tree tmpl)
return template_parms_to_args (DECL_TEMPLATE_PARMS (tmpl));
}
+/* Return the template arguments corresponding to the template parameters of
+ TMPL's enclosing scope. When TMPL is a member of a partial specialization,
+ this returns the arguments for the partial specialization as opposed to those
+ for the primary template, which is the main difference between this function
+ and simply using e.g. the TYPE_TI_ARGS of TMPL's DECL_CONTEXT. */
+
+tree
+outer_template_args (tree tmpl)
+{
+ tree ti = get_template_info (DECL_TEMPLATE_RESULT (tmpl));
+ if (!ti)
+ return NULL_TREE;
+ tree args = TI_ARGS (ti);
+ if (!PRIMARY_TEMPLATE_P (tmpl))
+ return args;
+ if (TMPL_ARGS_DEPTH (args) == 1)
+ return NULL_TREE;
+ args = copy_node (args);
+ --TREE_VEC_LENGTH (args);
+ return args;
+}
+
/* Update the declared TYPE by doing any lookups which were thought to be
dependent, but are not now that we know the SCOPE of the declarator. */
@@ -30081,16 +30103,8 @@ alias_ctad_tweaks (tree tmpl, tree uguides)
static tree
ctor_deduction_guides_for (tree tmpl, tsubst_flags_t complain)
{
- tree type = TREE_TYPE (tmpl);
- tree outer_args = NULL_TREE;
- if (DECL_CLASS_SCOPE_P (tmpl)
- && CLASSTYPE_TEMPLATE_INSTANTIATION (DECL_CONTEXT (tmpl)))
- {
- outer_args = copy_node (CLASSTYPE_TI_ARGS (type));
- gcc_assert (TMPL_ARGS_DEPTH (outer_args) > 1);
- --TREE_VEC_LENGTH (outer_args);
- type = TREE_TYPE (most_general_template (tmpl));
- }
+ tree outer_args = outer_template_args (tmpl);
+ tree type = TREE_TYPE (most_general_template (tmpl));
tree cands = NULL_TREE;