aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPatrick Palka <ppalka@redhat.com>2024-02-08 09:10:44 -0500
committerPatrick Palka <ppalka@redhat.com>2024-02-08 09:10:44 -0500
commit465b9c51f5c79ce3fbb36f1abc7194b39ad9cae7 (patch)
tree2ff49aa60b96d4aa138280aa2812e952b2b9f633 /gcc
parentd2d5ef6e22082d945c4d255b44194155680a93bd (diff)
downloadgcc-465b9c51f5c79ce3fbb36f1abc7194b39ad9cae7.zip
gcc-465b9c51f5c79ce3fbb36f1abc7194b39ad9cae7.tar.gz
gcc-465b9c51f5c79ce3fbb36f1abc7194b39ad9cae7.tar.bz2
c++: NTTP type CTAD w/ tmpl from current inst [PR113649]
Since template argument coercion happens relative to the most general template (for a class template at least), during NTTP type CTAD we might need to consider outer arguments particularly if the CTAD template is from the current instantiation (and so depends on outer template parameters). This patch makes do_class_deduction substitute as many levels of outer template arguments into a CTAD template (from the current instantiation) as it can take. PR c++/113649 gcc/cp/ChangeLog: * pt.cc (do_class_deduction): Add outer_targs parameter. Substitute outer arguments into the CTAD template. (do_auto_deduction): Pass outer_targs to do_class_deduction. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/nontype-class65.C: New test. Reviewed-by: Jason Merrill <jason@redhat.com>
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/pt.cc21
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/nontype-class65.C16
2 files changed, 35 insertions, 2 deletions
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 55c23b6..f9abb21 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -30682,7 +30682,7 @@ ctad_template_p (tree tmpl)
type. */
static tree
-do_class_deduction (tree ptype, tree tmpl, tree init,
+do_class_deduction (tree ptype, tree tmpl, tree init, tree outer_targs,
int flags, tsubst_flags_t complain)
{
/* We should have handled this in the caller. */
@@ -30744,6 +30744,23 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
if (type_dependent_expression_p (init))
return ptype;
+ if (outer_targs)
+ {
+ int args_depth = TMPL_ARGS_DEPTH (outer_targs);
+ int parms_depth = TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl));
+ if (parms_depth > 1)
+ {
+ /* Substitute outer arguments into this CTAD template from the
+ current instantiation. */
+ int want = std::min (args_depth, parms_depth - 1);
+ outer_targs = strip_innermost_template_args (outer_targs,
+ args_depth - want);
+ tmpl = tsubst (tmpl, outer_targs, complain, NULL_TREE);
+ if (tmpl == error_mark_node)
+ return error_mark_node;
+ }
+ }
+
/* Don't bother with the alias rules for an equivalent template. */
tmpl = get_underlying_template (tmpl);
@@ -30999,7 +31016,7 @@ do_auto_deduction (tree type, tree init, tree auto_node,
if (tree ctmpl = CLASS_PLACEHOLDER_TEMPLATE (auto_node))
/* C++17 class template argument deduction. */
- return do_class_deduction (type, ctmpl, init, flags, complain);
+ return do_class_deduction (type, ctmpl, init, outer_targs, flags, complain);
if (init == NULL_TREE || TREE_TYPE (init) == NULL_TREE)
/* Nothing we can do with this, even in deduction context. */
diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class65.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class65.C
new file mode 100644
index 0000000..8397ea5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class65.C
@@ -0,0 +1,16 @@
+// PR c++/113649
+// { dg-do compile { target c++20 } }
+
+template<class... Args>
+struct A {
+ template<class Ret>
+ struct Fun { constexpr Fun(Ret(*)(Args...)) { } };
+
+ template<Fun f>
+ struct B { using type = decltype(f); };
+};
+
+bool f(char, long);
+
+using type = A<char, long>::B<&f>::type;
+using type = A<char, long>::Fun<bool>;