tree grooaf = NULL_TREE;
tree dummy_promise = build_dummy_object (get_coroutine_promise_type (orig));
- /* We don't require this, so lookup_promise_method can return NULL... */
+ /* We don't require this, so lookup_promise_method can return NULL,
+ but, if the lookup succeeds, then the function must be usable. */
if (grooaf_meth && BASELINK_P (grooaf_meth))
- {
- /* ... but, if the lookup succeeds, then the function must be
- usable.
- build_new_method_call () wants a valid pointer to (an empty) args
- list in this case. */
- vec<tree, va_gc> *args = make_tree_vector ();
- grooaf = build_new_method_call (dummy_promise, grooaf_meth, &args,
- NULL_TREE, LOOKUP_NORMAL, NULL,
- tf_warning_or_error);
- release_tree_vector (args);
- }
+ grooaf = build_new_method_call (dummy_promise, grooaf_meth, NULL,
+ NULL_TREE, LOOKUP_NORMAL, NULL,
+ tf_warning_or_error);
/* Allocate the frame, this has several possibilities:
[dcl.fct.def.coroutine] / 9 (part 1)
The allocation function’s name is looked up in the scope of the promise
type. It's not a failure for it to be absent see part 4, below. */
+
tree nwname = ovl_op_identifier (false, NEW_EXPR);
- tree fns = lookup_promise_method (orig, nwname, fn_start,
- /*musthave=*/false);
tree new_fn = NULL_TREE;
- if (fns && BASELINK_P (fns))
+
+ if (TYPE_HAS_NEW_OPERATOR (promise_type))
{
+ tree fns = lookup_promise_method (orig, nwname, fn_start,
+ /*musthave=*/true);
/* [dcl.fct.def.coroutine] / 9 (part 2)
If the lookup finds an allocation function in the scope of the promise
type, overload resolution is performed on a function call created by
vec_safe_push (args, arg);
}
- /* We might need to check that the provided function is nothrow. */
+ /* Note the function selected; we test to see if it's NOTHROW. */
tree func;
- /* Failure is OK for the first attempt. */
+ /* Failure is not an error for this attempt. */
new_fn = build_new_method_call (dummy_promise, fns, &args, NULL,
LOOKUP_NORMAL, &func, tf_none);
release_tree_vector (args);
- if (!new_fn || new_fn == error_mark_node)
+ if (new_fn == error_mark_node)
{
/* [dcl.fct.def.coroutine] / 9 (part 3)
If no viable function is found, overload resolution is performed
again on a function call created by passing just the amount of
space required as an argument of type std::size_t. */
- args = make_tree_vector ();
- vec_safe_push (args, resizeable); /* Space needed. */
+ args = make_tree_vector_single (resizeable); /* Space needed. */
new_fn = build_new_method_call (dummy_promise, fns, &args,
NULL_TREE, LOOKUP_NORMAL, &func,
tf_none);
release_tree_vector (args);
}
- /* However, if the initial lookup succeeded, then one of these two
- options must be available. */
- if (!new_fn || new_fn == error_mark_node)
+ /* However, if the promise provides an operator new, then one of these
+ two options must be available. */
+ if (new_fn == error_mark_node)
{
error_at (fn_start, "%qE is provided by %qT but is not usable with"
" the function signature %qD", nwname, promise_type, orig);
error_at (fn_start, "%qE is provided by %qT but %qE is not marked"
" %<throw()%> or %<noexcept%>", grooaf, promise_type, nwname);
}
- else
+ else /* No operator new in the promise. */
{
/* [dcl.fct.def.coroutine] / 9 (part 4)
If this lookup fails, the allocation function’s name is looked up in
/* build_operator_new_call () will insert size needed as element 0 of
this, and we might need to append the std::nothrow constant. */
vec_alloc (args, 2);
-
if (grooaf)
{
/* [dcl.fct.def.coroutine] / 10 (part 2)
tree std_nt = lookup_qualified_name (std_node,
get_identifier ("nothrow"),
0, /*complain=*/true, false);
+ if (!std_nt || std_nt == error_mark_node)
+ error_at (fn_start, "%qE is provided by %qT but %<std::nothrow%> "
+ "cannot be found", grooaf, promise_type);
vec_safe_push (args, std_nt);
}
tf_warning_or_error);
resizeable = build_call_expr_internal_loc
(fn_start, IFN_CO_FRAME, size_type_node, 2, frame_size, coro_fp);
- CALL_EXPR_ARG (new_fn, 0) = resizeable;
+ /* If the operator call fails for some reason, then don't try to
+ amend it. */
+ if (new_fn != error_mark_node)
+ CALL_EXPR_ARG (new_fn, 0) = resizeable;
release_tree_vector (args);
}