[PATCH] D82029: [Coroutines] Ensure co_await promise.final_suspend() does not throw

Lewis Baker via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Thu Jun 18 14:17:03 PDT 2020


lewissbaker added inline comments.


================
Comment at: clang/include/clang/Basic/DiagnosticSemaKinds.td:10521
+def err_coroutine_promise_final_suspend_requires_nothrow : Error<
+  "all code generated by co_await __promise.final_suspend() must not throw"
+>;
----------------
I'd perhaps word this to be more direct in what the compiler is requiring.
It's possible to have a function that does not throw that is not declared noexcept, but what the compiler requires here is that the expression is noexcept - or in standardese "not potentially throwing".

So maybe something like:
> the expression 'co_await __promise.final_suspend()' is required to be non-throwing



================
Comment at: clang/lib/Sema/SemaCoroutine.cpp:662-664
+  for (const auto *D : ThrowingDecls) {
+    S.Diag(D->getEndLoc(), diag::note_coroutine_function_declare_noexcept);
+  }
----------------
Should we be sorting the ThrowingDecls by something other than the pointer so that the error output has a deterministic order here?


================
Comment at: clang/lib/Sema/SemaExceptionSpec.cpp:1049
 
-  FT = S.ResolveExceptionSpec(Loc.isInvalid() ? E->getBeginLoc() : Loc, FT);
+  if (Loc.isValid() || (Loc.isInvalid() && E)) {
+    FT = S.ResolveExceptionSpec(Loc.isInvalid() ? E->getBeginLoc() : Loc, FT);
----------------
The function documentation says at least one of E and Loc must be true.
Should this be an assertion, then, rather than a conditional check?


================
Comment at: clang/test/AST/Inputs/std-coroutine.h:13
 struct coroutine_handle {
-  static coroutine_handle from_address(void *);
+  static coroutine_handle from_address(void *) noexcept;
 };
----------------
Note that the actual `std::coroutine_handle::from_address()` method is not specified to have a noexcept declaration, even though it is defined as such in both libstdc++/libc++ implementation.

See http://eel.is/c++draft/coroutine.handle#export.import-itemdecl:2

Note, however, that the specification doesn't define a co_await expression in terms of coroutine_handle::from_address() or coroutine_handle::from_promise(), but is rather just defined in terms of some handle 'h' that refers to the current coroutine.

See http://eel.is/c++draft/expr.await#3.5

So while technically we shouldn't be requiring the from_address() method to be noexcept, I think that it's probably ok since the compiler, at least in theory, has control over how it constructs a handle and can choose to call the from_address() method assuming that it is defined noexcept, even though it is not required to be.



================
Comment at: clang/test/SemaCXX/coroutine-final-suspend-noexcept.cpp:14
+struct coroutine_handle {
+  static coroutine_handle from_address(void *); // expected-note {{must be declared with 'noexcept'}}
+};
----------------
I'm not sure that we should be _requiring_ the compiler to emit an error for this line.

The language specification does not require implementations to declare the from_address() method as noexcept, even though Clang now requires standard library implementations to declare this method as noexcept - this is an additional implementation requirement that Clang is placing on standard library implementations for them to be compatible with Clang's coroutines implementation.

I guess this is probably ok to raise as an error, though, as most users will just be using the compiler-provided implementation and both libc++/libstdc++ are (currently) compatible.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D82029/new/

https://reviews.llvm.org/D82029





More information about the cfe-commits mailing list