What is the currently handled exception after co_await?

Viewed 285

GCC permits one to resume C++20 coroutines from catch sections and in the coroutine to call co_await again from its catch sections.

What is considered then the current handled exception in such cases?

Please consider an example:

#include <coroutine>
#include <iostream>

struct ReturnObject {
  struct promise_type {
    ReturnObject get_return_object() { return { std::coroutine_handle<promise_type>::from_promise(*this) }; }
    std::suspend_always initial_suspend() { return {}; }
    std::suspend_always final_suspend() noexcept { return {}; }
    void unhandled_exception() {}
    void return_void() {}
  };
  std::coroutine_handle<promise_type> h_;
};

ReturnObject coroutine()
{
  try {
      std::cout << "Exception 1 being thrown\n";
      throw 1;
  }
  catch( int a ) {
      std::cout << "Exception caught in coroutine " << a << std::endl; 
      co_await std::suspend_always{};
      try {
        std::cout << "Current exception being rethrown\n";
        throw;
      }
      catch( int b ) {
        std::cout << "Exception caught in coroutine " << b << std::endl; 
      }
  }
}

int main()
{
  auto h = coroutine().h_;

  try {
      std::cout << "Exception 0 being thrown" << std::endl;
      throw 0;
  }
  catch( int a ) { 
      std::cout << "Exception " << a << " caught in main" << std::endl; 
      h();
  }

  h();
  h.destroy();
}

It prints ( https://gcc.godbolt.org/z/4deoG7Pnh ):

Exception 0 being thrown
Exception 0 caught in main
Exception 1 being thrown
Exception caught in coroutine 1
Current exception being rethrown
Exception caught in coroutine 0

Here I am mostly interesting in the last line, since it shows that throw; re-throws 0 and not 1, which was actually the one being processed. Is it correct?

1 Answers

co_await can only appear outside of a catch block, as specified by the standard:

An await-expression shall appear only in a potentially-evaluated expression within the compound-statement of a function-body outside of a handler.

co_yield is defined as a variation of co_await, so it has the same limitations:

A yield-expression shall appear only within a suspension context of a function ([expr.await]).

So the compiler should have deemed the code il-formed and issued an error.

Related