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
This commit is contained in:
parent
2b83483746
commit
9a642ccae4
8 changed files with 89 additions and 10 deletions
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)))
|
||||
|
|
28
gcc/cp/pt.c
28
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<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);
|
||||
|
|
|
@ -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);
|
||||
|
|
13
gcc/testsuite/g++.dg/cpp1z/class-deduction33.C
Normal file
13
gcc/testsuite/g++.dg/cpp1z/class-deduction33.C
Normal file
|
@ -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>*>();
|
||||
}
|
13
gcc/testsuite/g++.dg/cpp1z/class-deduction34.C
Normal file
13
gcc/testsuite/g++.dg/cpp1z/class-deduction34.C
Normal file
|
@ -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);
|
10
gcc/testsuite/g++.dg/cpp1z/class-deduction35.C
Normal file
10
gcc/testsuite/g++.dg/cpp1z/class-deduction35.C
Normal file
|
@ -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 "" }
|
Loading…
Add table
Reference in a new issue