Class template argument deduction in new-expression
authorJason Merrill <jason@redhat.com>
Thu, 2 Mar 2017 01:58:30 +0000 (20:58 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 2 Mar 2017 01:58:30 +0000 (20:58 -0500)
Class template argument deduction in new-expression
* init.c (build_new): Handle deduction from no initializer.
* parser.c (cp_parser_new_expression): Don't require a single
expression for class template deduction.
* typeck2.c (cxx_incomplete_type_diagnostic): Fix diagnostic for
class template placeholder.
* pt.c (tsubst_copy) [TEMPLATE_DECL]: Handle dependent context.
(tsubst_copy_and_build) [TEMPLATE_ID_EXPR]: Handle SCOPE_REF.
(redeclare_class_template): Set TEMPLATE_TYPE_PARM_FOR_CLASS.

From-SVN: r245826

gcc/cp/ChangeLog
gcc/cp/init.c
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/typeck2.c
gcc/testsuite/g++.dg/cpp1z/class-deduction33.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/class-deduction34.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/class-deduction35.C [new file with mode: 0644]

index 1c3f1e845e3c15782e94063177333f22fedfb74f..405e3d52b7e3642a36012ef7ef24f13d1cc34638 100644 (file)
@@ -1,3 +1,15 @@
+2017-03-01  Jason Merrill  <jason@redhat.com>
+
+       Class template argument deduction in new-expression
+       * init.c (build_new): Handle deduction from no initializer.
+       * parser.c (cp_parser_new_expression): Don't require a single
+       expression for class template deduction.
+       * typeck2.c (cxx_incomplete_type_diagnostic): Fix diagnostic for
+       class template placeholder.
+       * pt.c (tsubst_copy) [TEMPLATE_DECL]: Handle dependent context.
+       (tsubst_copy_and_build) [TEMPLATE_ID_EXPR]: Handle SCOPE_REF.
+       (redeclare_class_template): Set TEMPLATE_TYPE_PARM_FOR_CLASS.
+
 2017-03-01  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/79746
index 7ded37e753a850136a6f7948d643954ec18ff076..191fe13e31039947d1d5d660eef0b9c0d8d9ba94 100644 (file)
@@ -3478,15 +3478,19 @@ build_new (vec<tree, va_gc> **placement, tree type, tree nelts,
   if (type == error_mark_node)
     return error_mark_node;
 
-  if (nelts == NULL_TREE && vec_safe_length (*init) == 1
+  if (nelts == NULL_TREE
       /* Don't do auto deduction where it might affect mangling.  */
       && (!processing_template_decl || at_function_scope_p ()))
     {
       tree auto_node = type_uses_auto (type);
       if (auto_node)
        {
-         tree d_init = (**init)[0];
-         d_init = resolve_nondeduced_context (d_init, complain);
+         tree d_init = NULL_TREE;
+         if (vec_safe_length (*init) == 1)
+           {
+             d_init = (**init)[0];
+             d_init = resolve_nondeduced_context (d_init, complain);
+           }
          type = do_auto_deduction (type, d_init, auto_node);
        }
     }
index 50528e24335fde2c7fe7cc715bdbc37fab5a3e8c..e6848701150020f02cd683b271a8d32ba01540ea 100644 (file)
@@ -8228,7 +8228,8 @@ cp_parser_new_expression (cp_parser* parser)
      contain a new-initializer of the form ( assignment-expression )".
      Additionally, consistently with the spirit of DR 1467, we want to accept
      'new auto { 2 }' too.  */
-  else if (type_uses_auto (type)
+  else if ((ret = type_uses_auto (type))
+          && !CLASS_PLACEHOLDER_TEMPLATE (ret)
           && (vec_safe_length (initializer) != 1
               || (BRACE_ENCLOSED_INITIALIZER_P ((*initializer)[0])
                   && CONSTRUCTOR_NELTS ((*initializer)[0]) != 1)))
index ec9d53a83ee2fadba023a01dac3e82f79a18a60b..8144ca66a0152b80ab191a478d7197dfd0ceb3ce 100644 (file)
@@ -5732,6 +5732,9 @@ redeclare_class_template (tree type, tree parms, tree cons)
          gcc_assert (DECL_CONTEXT (parm) == NULL_TREE);
          DECL_CONTEXT (parm) = tmpl;
        }
+
+      if (TREE_CODE (parm) == TYPE_DECL)
+       TEMPLATE_TYPE_PARM_FOR_CLASS (TREE_TYPE (parm)) = true;
     }
 
   // Cannot redeclare a class template with a different set of constraints.
@@ -14638,6 +14641,15 @@ 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))
+           {
+             /* When rewriting a constructor into a deduction guide, a
+                non-dependent name can become dependent, so memtmpl<args>
+                becomes context::template memtmpl<args>.  */
+             tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+             return build_qualified_name (type, context, DECL_NAME (t),
+                                          /*template*/true);
+           }
          return lookup_field (context, DECL_NAME(t), 0, false);
        }
       else
@@ -16621,6 +16633,14 @@ tsubst_copy_and_build (tree t,
        if (targs == error_mark_node)
          return error_mark_node;
 
+       if (TREE_CODE (templ) == SCOPE_REF)
+         {
+           tree name = TREE_OPERAND (templ, 1);
+           tree tid = lookup_template_function (name, targs);
+           TREE_OPERAND (templ, 1) = tid;
+           return templ;
+         }
+
        if (variable_template_p (templ))
          RETURN (lookup_and_finish_template_variable (templ, targs, complain));
 
@@ -25144,7 +25164,7 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags,
       type = TREE_TYPE (most_general_template (tmpl));
     }
 
-  bool saw_default = false;
+  bool saw_ctor = false;
   bool saw_copy = false;
   if (CLASSTYPE_METHOD_VEC (type))
     // FIXME cache artificial deduction guides
@@ -25154,9 +25174,9 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags,
        tree guide = build_deduction_guide (fn, outer_args, complain);
        cands = ovl_cons (guide, cands);
 
+       saw_ctor = true;
+
        tree parms = FUNCTION_FIRST_USER_PARMTYPE (fn);
-       if (sufficient_parms_p (parms))
-         saw_default = true;
        if (parms && sufficient_parms_p (TREE_CHAIN (parms)))
          {
            tree pt = TREE_VALUE (parms);
@@ -25167,7 +25187,7 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags,
          }
       }
 
-  if (!saw_default && args->length() == 0)
+  if (!saw_ctor && args->length() == 0)
     {
       tree guide = build_deduction_guide (type, outer_args, complain);
       cands = ovl_cons (guide, cands);
index 1e0354d8a73ea50267c0495ca92a43e33c7da821..58a01c98f2a5f9fb8797f8086007b92ca7a63ec6 100644 (file)
@@ -523,8 +523,14 @@ cxx_incomplete_type_diagnostic (location_t loc, const_tree value,
 
     case TEMPLATE_TYPE_PARM:
       if (is_auto (type))
-       emit_diagnostic (diag_kind, loc, 0,
-                        "invalid use of %<auto%>");
+       {
+         if (CLASS_PLACEHOLDER_TEMPLATE (type))
+           emit_diagnostic (diag_kind, loc, 0,
+                            "invalid use of placeholder %qT", type);
+         else
+           emit_diagnostic (diag_kind, loc, 0,
+                            "invalid use of %qT", type);
+       }
       else
        emit_diagnostic (diag_kind, loc, 0,
                         "invalid use of template type parameter %qT", type);
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction33.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction33.C
new file mode 100644 (file)
index 0000000..d135031
--- /dev/null
@@ -0,0 +1,13 @@
+// { dg-options -std=c++1z }
+
+template <class,class> struct same;
+template <class T> struct same<T,T> {};
+
+template <class T = void> struct A { };
+template <class T> struct B { B(T,T); };
+
+int main()
+{
+  same<decltype(new A),A<void>*>();
+  same<decltype(new B{1,2}),B<int>*>();
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction34.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction34.C
new file mode 100644 (file)
index 0000000..b035879
--- /dev/null
@@ -0,0 +1,13 @@
+// { dg-options -std=c++1z }
+
+template <class T>
+struct A
+{
+  template <class U>
+  static constexpr bool B = U();
+
+  template <class U, bool V = B<U>>
+  A(T, U);
+};
+
+A a (1,2);
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction35.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction35.C
new file mode 100644 (file)
index 0000000..b0e53d1
--- /dev/null
@@ -0,0 +1,10 @@
+// { dg-options -std=c++1z }
+
+template <class T> struct A;
+
+template <class T> struct A {
+  A(T&&);
+};
+
+int i;
+A a = i;                       // { dg-error "" }