]> git.ipfire.org Git - thirdparty/gcc.git/commit
c++/coroutines: only defer expanding co_{await,return,yield} if dependent [PR112341]
authorArsen Arsenović <arsen@aarsen.me>
Tue, 30 Jul 2024 21:36:24 +0000 (23:36 +0200)
committerArsen Arsenović <arsen@gcc.gnu.org>
Thu, 1 Aug 2024 14:11:15 +0000 (16:11 +0200)
commit32e678b2ed752154b2f96719e33f11a7c6417f20
treed86a8fb13c9da8b70f0e1119cad63caa60d0cf94
parent64ca25aec4939aea79bd812b089fbb666ca6f2fd
c++/coroutines: only defer expanding co_{await,return,yield} if dependent [PR112341]

By doing so, we can get diagnostics in template decls when we know we
can.  For instance, in the following:

  awaitable g();
  template<typename>
  task f()
  {
    co_await g();
    co_yield 1;
    co_return "foo";
  }

... the coroutine promise type in each statement is always
std::coroutine_handle<task>::promise_type, and all of the operands are
not type-dependent, so we can always compute the resulting types (and
expected types) of these expressions and statements.

Also, when we do not know the type of the CO_AWAIT_EXPR or
CO_YIELD_EXPR, we now return NULL_TREE as the type rather than
unknown_type_node.  This is more correct, since the type is not unknown,
it just isn't determined yet.  This also means we can remove the
CO_AWAIT_EXPR and CO_YIELD_EXPR special-cases from
type_dependent_expression_p.

PR c++/112341 - error: insufficient contextual information to determine type on co_await result in function template

gcc/cp/ChangeLog:

PR c++/112341
* coroutines.cc (struct coroutine_info): Also cache the
traits type.
(ensure_coro_initialized): New function.  Makes sure we have
initialized the coroutine state successfully, or informs the
caller should it fail to do so.  Extracted from
coro_promise_type_found_p.
(coro_get_traits_class): New function.  Gets the (cached)
coroutine traits type for a given coroutine.  Extracted from
coro_promise_type_found_p and refactored to cache the result.
(coro_promise_type_found_p): Use the two functions above.
(build_template_co_await_expr): New function.  Builds a
CO_AWAIT_EXPR representing a CO_AWAIT_EXPR in a template
declaration.
(build_co_await): Use the above if processing_template_decl, and
give it a proper type.
(coro_dependent_p): New function.  Returns true iff its
argument is a type-dependent expression OR the current functions
traits class is type dependent.
(finish_co_await_expr): Defer expansion only in the case
coro_dependent_p returns true.
(finish_co_yield_expr): Ditto.
(finish_co_return_stmt): Ditto.
* pt.cc (type_dependent_expression_p): Do not treat
CO_AWAIT/CO_YIELD specially.

gcc/testsuite/ChangeLog:

PR c++/112341
* g++.dg/coroutines/pr112341-2.C: New test.
* g++.dg/coroutines/pr112341-3.C: New test.
* g++.dg/coroutines/torture/co-yield-03-tmpl-nondependent.C: New
test.
* g++.dg/coroutines/pr112341.C: New test.
gcc/cp/coroutines.cc
gcc/cp/pt.cc
gcc/testsuite/g++.dg/coroutines/pr112341-2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/coroutines/pr112341-3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/coroutines/pr112341.C [new file with mode: 0644]
gcc/testsuite/g++.dg/coroutines/torture/co-yield-03-tmpl-nondependent.C [new file with mode: 0644]