In the first testcase below, during parsing of the alias template
ConstSpanType, transparency of alias template specializations means we
replace SpanType<T> with SpanType's substituted definition.  But this
substitution lowers the level of the CTAD placeholder for span(T()) from
2 to 1, and so the later instantiantion of ConstSpanType<int>
erroneously substitutes this CTAD placeholder with the template argument
at level 1 index 0, i.e. with int, before we get a chance to perform the
CTAD.

In light of this, it seems we should avoid level lowering when
substituting through through the type-id of a dependent alias template
specialization.  To that end this patch makes lookup_template_class_1
pass tf_partial to tsubst in this situation.

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?

        PR c++/91911

gcc/cp/ChangeLog:

        * pt.c (lookup_template_class_1): When looking up a dependent
        alias template specialization, pass tf_partial to tsubst.

gcc/testsuite/ChangeLog:

        * g++.dg/cpp1z/class-deduction92.C: New test.
---
 gcc/cp/pt.c                                   |  7 +++++-
 .../g++.dg/cpp1z/class-deduction92.C          | 17 +++++++++++++
 .../g++.dg/cpp1z/class-deduction93.C          | 25 +++++++++++++++++++
 3 files changed, 48 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction92.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction93.C

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index f73c7471a33..23c5f515716 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -9954,7 +9954,12 @@ lookup_template_class_1 (tree d1, tree arglist, tree 
in_decl, tree context,
                template-arguments for the template-parameters in the
                type-id of the alias template.  */
 
-         t = tsubst (TREE_TYPE (gen_tmpl), arglist, complain, in_decl);
+         /* When substituting a dependent alias template specialization,
+            we pass tf_partial to avoid lowering the level of any 'auto'
+            in its type-id which might correspond to CTAD placeholders.  */
+         t = tsubst (TREE_TYPE (gen_tmpl), arglist,
+                     complain | (is_dependent_type * tf_partial),
+                     in_decl);
          /* Note that the call above (by indirectly calling
             register_specialization in tsubst_decl) registers the
             TYPE_DECL representing the specialization of the alias
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction92.C 
b/gcc/testsuite/g++.dg/cpp1z/class-deduction92.C
new file mode 100644
index 00000000000..ae3c55508b2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction92.C
@@ -0,0 +1,17 @@
+// PR c++/91911
+// { dg-do compile { target c++17 } }
+
+template<class T>
+struct span {
+  using value_type = T;
+  span(T);
+};
+
+template<class T>
+using SpanType = decltype(span(T()));
+
+template<class T>
+using ConstSpanType = span<const typename SpanType<T>::value_type>;
+
+using type = ConstSpanType<int>;
+using type = span<const int>;
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction93.C 
b/gcc/testsuite/g++.dg/cpp1z/class-deduction93.C
new file mode 100644
index 00000000000..eebc986832e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction93.C
@@ -0,0 +1,25 @@
+// PR c++/98077
+// { dg-do compile { target c++17 } }
+
+template<class R>
+struct function {
+  template<class T> function(T) { }
+  using type = R;
+};
+
+template<class T> function(T) -> function<decltype(T()())>;
+
+template<class T>
+struct CallableTrait;
+
+template<class R>
+struct CallableTrait<function<R>> { using ReturnType = R; };
+
+template<class F>
+using CallableTraitT = decltype(function{F()});
+
+template<class F>
+using ReturnType = typename CallableTraitT<F>::type;
+
+using type = ReturnType<int(*)()>;
+using type = int;
-- 
2.32.0.93.g670b81a890

Reply via email to