diff mbox series

[coroutines] expanding inside a template

Message ID 719e4bac-e225-8a59-5b3e-e4dd14d205c1@acm.org
State New
Headers show
Series [coroutines] expanding inside a template | expand

Commit Message

Nathan Sidwell Feb. 28, 2022, 5:56 p.m. UTC
Iain,
this is the second bug, also found in Folly and also not extracted to a 
testcase.  We were ICEing because we ended up tsubst_copying something 
that had already been tsubst, leading to an assert failure (mostly such 
repeated tsubsting is harmless).

We had a non-dependent co_await in a non-dependent-type template fn, so 
we processed it at definition time, and then reprocessed at 
instantiation time.

This is not quite the right fix, as it'll make all co_awaits in a 
template function have dependent type.  However, in practice it appears 
less ICEy!

Exprs only have dependent type if at least one operand is dependent -- 
which was what you were trying to do.  Coroutines have the additional 
wrinkle, that the current fn's type is an implicit operand.

So, if the coroutine function's type is not dependent, and the operand 
is not dependent, we should determine the type of the co_await 
expression using the DEPENDENT_EXPR wrapper machinery.  That allows us 
to determine the subexpression type, but leave its operand unchanged and 
then instantiate it later.

I'm not sure if the std explicitly calls out this dependent-subexpr-type 
wrinkle.

nathan
diff mbox series

Patch


Summary:
The coroutine machinery attempts to process non-dependent
   coroutine expressions at template definition time.  That's just wrong.


diff --git a/9.x/src/gcc-10.x/gcc/cp/coroutines.cc b/9.x/src/gcc-10.x/gcc/cp/coroutines.cc
index 91c017f0b7..d0f292f2a6 100644
--- a/9.x/src/gcc-10.x/gcc/cp/coroutines.cc
+++ b/9.x/src/gcc-10.x/gcc/cp/coroutines.cc
@@ -1153,7 +1153,7 @@  finish_co_await_expr (location_t kw, tree expr)
   /* If we don't know the promise type, we can't proceed, build the
      co_await with the expression unchanged.  */
   tree functype = TREE_TYPE (current_function_decl);
-  if (dependent_type_p (functype) || type_dependent_expression_p (expr))
+  if (processing_template_decl)
     return build5_loc (kw, CO_AWAIT_EXPR, unknown_type_node, expr,
 		       NULL_TREE, NULL_TREE, NULL_TREE, integer_zero_node);
 
@@ -1230,7 +1230,7 @@  finish_co_yield_expr (location_t kw, tree expr)
   /* If we don't know the promise type, we can't proceed, build the
      co_await with the expression unchanged.  */
   tree functype = TREE_TYPE (current_function_decl);
-  if (dependent_type_p (functype) || type_dependent_expression_p (expr))
+  if (processing_template_decl)
     return build2_loc (kw, CO_YIELD_EXPR, unknown_type_node, expr, NULL_TREE);
 
   if (!coro_promise_type_found_p (current_function_decl, kw))
@@ -1316,7 +1316,7 @@  finish_co_return_stmt (location_t kw, tree expr)
   /* If we don't know the promise type, we can't proceed, build the
      co_return with the expression unchanged.  */
   tree functype = TREE_TYPE (current_function_decl);
-  if (dependent_type_p (functype) || type_dependent_expression_p (expr))
+  if (processing_template_decl)
     {
       /* co_return expressions are always void type, regardless of the
 	 expression type.  */
-- 
2.30.2