llvm-project/clang/test/CodeGenCoroutines/coro-newpm-pipeline.cpp
Xun Li 516803dc86 [Coroutines] Ensure co_await promise.final_suspend() does not throw
Summary:
This patch addresses https://bugs.llvm.org/show_bug.cgi?id=46256
The spec of coroutine requires that the expression co_­await promise.final_­suspend() shall not be potentially-throwing.
To check this, we recursively look at every call (including Call, MemberCall, OperatorCall and Constructor) in all code
generated by the final suspend, and ensure that the callees are declared with noexcept. We also look at any returned data
type that requires explicit destruction, and check their destructors for noexcept.

This patch does not check declarations with dependent types yet, which will be done in future patches.

Updated all tests to add noexcept to the required functions, and added a dedicated test for this patch.

This patch might start to cause existing codebase fail to compile because most people may not have been strict in tagging
all the related functions noexcept.

Reviewers: lewissbaker, modocache, junparser

Reviewed By: modocache

Subscribers: arphaman, junparser, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D82029
2020-06-22 15:01:42 -07:00

58 lines
2.0 KiB
C++

// Tests that coroutine passes are added to and run by the new pass manager
// pipeline, at -O0 and above.
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm-bc -o /dev/null \
// RUN: -fexperimental-new-pass-manager -fdebug-pass-manager -fcoroutines-ts \
// RUN: -O0 %s 2>&1 | FileCheck %s
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm-bc -o /dev/null \
// RUN: -fexperimental-new-pass-manager -fdebug-pass-manager -fcoroutines-ts \
// RUN: -O1 %s 2>&1 | FileCheck %s
//
// CHECK: Starting llvm::Module pass manager run.
// CHECK: Running pass:{{.*}}CoroEarlyPass
//
// The first coro-split pass enqueues a second run of the entire CGSCC pipeline.
// CHECK: Starting CGSCC pass manager run.
// CHECK: Running pass: CoroSplitPass on (_Z3foov)
// CHECK: Running pass:{{.*}}CoroElidePass{{.*}} on {{.*}}_Z3foov{{.*}}
// CHECK: Finished CGSCC pass manager run.
//
// The second coro-split pass splits coroutine 'foo' into funclets
// 'foo.resume', 'foo.destroy', and 'foo.cleanup'.
// CHECK: Starting CGSCC pass manager run.
// CHECK: Running pass: CoroSplitPass on (_Z3foov)
// CHECK: Running pass:{{.*}}CoroElidePass{{.*}} on {{.*}}_Z3foov{{.*}}
// CHECK: Finished CGSCC pass manager run.
//
// CHECK: Running pass:{{.*}}CoroCleanupPass
// CHECK: Finished llvm::Module pass manager run.
namespace std {
namespace experimental {
struct handle {};
struct awaitable {
bool await_ready() noexcept { return true; }
void await_suspend(handle) noexcept {}
bool await_resume() noexcept { return true; }
};
template <typename T> struct coroutine_handle {
static handle from_address(void *address) noexcept { return {}; }
};
template <typename T = void> struct coroutine_traits {
struct promise_type {
awaitable initial_suspend() { return {}; }
awaitable final_suspend() noexcept { return {}; }
void return_void() {}
T get_return_object() { return T(); }
void unhandled_exception() {}
};
};
} // namespace experimental
} // namespace std
void foo() { co_return; }