c++: alias CTAD and member alias templates [PR104470]
authorJason Merrill <jason@redhat.com>
Wed, 27 Apr 2022 15:13:24 +0000 (11:13 -0400)
committerJason Merrill <jason@redhat.com>
Sun, 15 May 2022 09:47:40 +0000 (05:47 -0400)
In this testcase, we were trying to substitute into
variant<Foo<T>>::__accepted_type, but failed to look it up because
variant<Foo<T>> doesn't exist.  In other cases we already rewrite such
things into a dependent reference; we need to do that for alias templates as
well.

This caused some testsuite regressions on alias uses outside of deduction
guides, so I've made all of this rewriting conditional on a new tf_dguide
tsubst flag.

PR c++/104470

gcc/cp/ChangeLog:

* cp-tree.h (enum tsubst_flags): Add tf_dguide.
* pt.cc (tsubst_aggr_type): Check it.
(tsubst_baselink, tsubst_copy): Check it.
(maybe_dependent_member_ref): Check it.
(instantiate_alias_template): Handle it.
(build_deduction_guide): Set it.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/explicit11.C: Second example also ill-formed.
* g++.dg/cpp2a/class-deduction-alias12.C: New test.

gcc/cp/cp-tree.h
gcc/cp/pt.cc
gcc/testsuite/g++.dg/cpp2a/class-deduction-alias12.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/explicit11.C

index e9a3d09..7217799 100644 (file)
@@ -5565,6 +5565,7 @@ enum tsubst_flags {
                                    constraint normalization.  */
   tf_tst_ok = 1 << 12,          /* Allow a typename-specifier to name
                                    a template (C++17 or later).  */
+  tf_dguide = 1 << 13,         /* Building a deduction guide from a ctor.  */
   /* Convenient substitution flags combinations.  */
   tf_warning_or_error = tf_warning | tf_error
 };
index 254586c..7758758 100644 (file)
@@ -13730,8 +13730,8 @@ tsubst_aggr_type (tree t,
                                         complain, in_decl);
          if (argvec == error_mark_node)
            r = error_mark_node;
-         else if (!entering_scope
-                  && cxx_dialect >= cxx17 && dependent_scope_p (context))
+         else if (!entering_scope && (complain & tf_dguide)
+                  && dependent_scope_p (context))
            {
              /* See maybe_dependent_member_ref.  */
              tree name = TYPE_IDENTIFIER (t);
@@ -16497,7 +16497,7 @@ tsubst_baselink (tree baselink, tree object_type,
        name = make_conv_op_name (optype);
 
       /* See maybe_dependent_member_ref.  */
-      if (dependent_scope_p (qualifying_scope))
+      if ((complain & tf_dguide) && dependent_scope_p (qualifying_scope))
        {
          if (template_id_p)
            name = build2 (TEMPLATE_ID_EXPR, unknown_type_node, name,
@@ -16817,7 +16817,7 @@ static tree
 maybe_dependent_member_ref (tree t, tree args, tsubst_flags_t complain,
                            tree in_decl)
 {
-  if (cxx_dialect < cxx17)
+  if (!(complain & tf_dguide))
     return NULL_TREE;
 
   tree ctx = context_for_name_lookup (t);
@@ -17075,7 +17075,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
             have to substitute this with one having context `D<int>'.  */
 
          tree context = tsubst (DECL_CONTEXT (t), args, complain, in_decl);
-         if (dependent_scope_p (context))
+         if ((complain & tf_dguide) && dependent_scope_p (context))
            {
              /* When rewriting a constructor into a deduction guide, a
                 non-dependent name can become dependent, so memtmpl<args>
@@ -21715,6 +21715,21 @@ instantiate_alias_template (tree tmpl, tree args, tsubst_flags_t complain)
   if (tmpl == error_mark_node || args == error_mark_node)
     return error_mark_node;
 
+  /* See maybe_dependent_member_ref.  */
+  if (complain & tf_dguide)
+    {
+      tree ctx = tsubst_aggr_type (DECL_CONTEXT (tmpl), args, complain,
+                                  tmpl, true);
+      if (dependent_scope_p (ctx))
+       {
+         tree name = DECL_NAME (tmpl);
+         tree fullname = build_nt (TEMPLATE_ID_EXPR, name,
+                                   INNERMOST_TEMPLATE_ARGS (args));
+         tree tname = build_typename_type (ctx, name, fullname, typename_type);
+         return TYPE_NAME (tname);
+       }
+    }
+
   args =
     coerce_innermost_template_parms (DECL_TEMPLATE_PARMS (tmpl),
                                     args, tmpl, complain,
@@ -29279,6 +29294,8 @@ build_deduction_guide (tree type, tree ctor, tree outer_args, tsubst_flags_t com
       ++processing_template_decl;
       bool ok = true;
 
+      complain |= tf_dguide;
+
       fn_tmpl
        = (TREE_CODE (ctor) == TEMPLATE_DECL ? ctor
           : DECL_TI_TEMPLATE (ctor));
diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias12.C b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias12.C
new file mode 100644 (file)
index 0000000..725e758
--- /dev/null
@@ -0,0 +1,23 @@
+// PR c++/104470
+// { dg-do compile { target c++20 } }
+
+template<typename _Types>
+class variant
+{
+  template<typename _Tp>
+    static constexpr int __accepted_index = 0;
+  template<int _Np>
+    using __to_type = int;
+  template<typename _Tp>
+    using __accepted_type = __to_type<__accepted_index<_Tp>>;
+  template<typename _Tp, typename _Tj = __accepted_type<_Tp>>
+    variant(_Tp __t)  { }
+};
+template <typename T>
+struct Foo
+{
+  T value;
+};
+template <typename T>
+using V = variant<Foo<T>>;
+V e = Foo{1};                  // { dg-error "" }
index 2df42cd..b6adfd0 100644 (file)
@@ -26,4 +26,4 @@ struct B {
   template<typename U> B(U, TA<U>);
 };
 
-B b{(int *)0, (char *)0};
+B b{(int *)0, (char *)0};      // { dg-error "deduction|no match" }