From 9a642ccae4ba5ca86c58f7770fd833158530bf88 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Wed, 1 Mar 2017 20:58:30 -0500 Subject: [PATCH] Class template argument deduction in new-expression 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 | 12 ++++++++ gcc/cp/init.c | 10 +++++-- gcc/cp/parser.c | 3 +- gcc/cp/pt.c | 28 ++++++++++++++++--- gcc/cp/typeck2.c | 10 +++++-- .../g++.dg/cpp1z/class-deduction33.C | 13 +++++++++ .../g++.dg/cpp1z/class-deduction34.C | 13 +++++++++ .../g++.dg/cpp1z/class-deduction35.C | 10 +++++++ 8 files changed, 89 insertions(+), 10 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction33.C create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction34.C create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction35.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1c3f1e845e3..405e3d52b7e 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,15 @@ +2017-03-01 Jason Merrill + + 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 PR c++/79746 diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 7ded37e753a..191fe13e310 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -3478,15 +3478,19 @@ build_new (vec **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); } } diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 50528e24335..e6848701150 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -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))) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index ec9d53a83ee..8144ca66a01 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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'. */ 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 + becomes context::template memtmpl. */ + 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); diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 1e0354d8a73..58a01c98f2a 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -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 %"); + { + 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 index 00000000000..d135031c277 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction33.C @@ -0,0 +1,13 @@ +// { dg-options -std=c++1z } + +template struct same; +template struct same {}; + +template struct A { }; +template struct B { B(T,T); }; + +int main() +{ + same*>(); + same*>(); +} diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction34.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction34.C new file mode 100644 index 00000000000..b03587969cf --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction34.C @@ -0,0 +1,13 @@ +// { dg-options -std=c++1z } + +template +struct A +{ + template + static constexpr bool B = U(); + + template > + 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 index 00000000000..b0e53d1c75e --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction35.C @@ -0,0 +1,10 @@ +// { dg-options -std=c++1z } + +template struct A; + +template struct A { + A(T&&); +}; + +int i; +A a = i; // { dg-error "" } -- 2.30.2