+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
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);
}
}
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)))
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.
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
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));
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
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);
}
}
- 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);
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);
--- /dev/null
+// { 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>*>();
+}
--- /dev/null
+// { 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);
--- /dev/null
+// { dg-options -std=c++1z }
+
+template <class T> struct A;
+
+template <class T> struct A {
+ A(T&&);
+};
+
+int i;
+A a = i; // { dg-error "" }