99 lines · cpp
1// RUN: %clang_cc1 -std=c++20 -ast-dump -ast-dump-filter=foo %s | FileCheck %s --strict-whitespace2// RUN: %clang_cc1 -std=c++20 -triple i386-windows-pc -ast-dump -ast-dump-filter=foo %s | FileCheck %s --strict-whitespace3 4namespace std {5template <typename, typename...> struct coroutine_traits;6template <typename> struct coroutine_handle {7 template <typename U>8 coroutine_handle(coroutine_handle<U> &&) noexcept;9 static coroutine_handle from_address(void *__addr) noexcept;10};11} // namespace std12 13struct executor {};14struct awaitable {};15struct awaitable_frame {16 awaitable get_return_object();17 void return_void();18 void unhandled_exception();19 struct result_t {20 ~result_t();21 bool await_ready() const noexcept;22 void await_suspend(std::coroutine_handle<void>) noexcept;23 void await_resume() const noexcept;24 };25 result_t initial_suspend() noexcept;26 result_t final_suspend() noexcept;27 result_t await_transform(executor) noexcept;28};29 30namespace std {31template <>32struct coroutine_traits<awaitable> {33 typedef awaitable_frame promise_type;34};35} // namespace std36 37awaitable foo() {38 co_await executor();39}40 41// Check that CoawaitExpr contains the correct subexpressions, including42// the operand expression as written in the source.43 44// CHECK-LABEL: Dumping foo:45// CHECK: FunctionDecl {{.*}} foo 'awaitable ()'46// CHECK: `-CoroutineBodyStmt {{.*}}47// CHECK: |-CompoundStmt {{.*}}48// CHECK: | `-ExprWithCleanups {{.*}} 'void'49// CHECK: | `-CoawaitExpr {{.*}} 'void'50// CHECK: | |-CXXTemporaryObjectExpr {{.*}} 'executor' 'void (){{.*}} noexcept' zeroing51// CHECK: | |-MaterializeTemporaryExpr {{.*}} 'result_t' lvalue52// CHECK: | | `-CXXBindTemporaryExpr {{.*}} 'result_t' (CXXTemporary {{.*}})53// CHECK: | | `-CXXMemberCallExpr {{.*}} 'result_t'54// CHECK: | | |-MemberExpr {{.*}} '<bound member function type>' .await_transform {{.*}}55// CHECK: | | | `-DeclRefExpr {{.*}} 'std::coroutine_traits<awaitable>::promise_type':'awaitable_frame' lvalue Var {{.*}} '__promise' 'std::coroutine_traits<awaitable>::promise_type':'awaitable_frame'56// CHECK: | | `-CXXTemporaryObjectExpr {{.*}} 'executor' 'void (){{.*}} noexcept' zeroing57// CHECK: | |-ExprWithCleanups {{.*}} 'bool'58// CHECK: | | `-CXXMemberCallExpr {{.*}} 'bool'59// CHECK: | | `-MemberExpr {{.*}} '<bound member function type>' .await_ready {{.*}}60// CHECK: | | `-ImplicitCastExpr {{.*}} 'const awaitable_frame::result_t' lvalue <NoOp>61// CHECK: | | `-OpaqueValueExpr {{.*}} 'result_t' lvalue62// CHECK: | | `-MaterializeTemporaryExpr {{.*}} 'result_t' lvalue63// CHECK: | | `-CXXBindTemporaryExpr {{.*}} 'result_t' (CXXTemporary {{.*}})64// CHECK: | | `-CXXMemberCallExpr {{.*}} 'result_t'65// CHECK: | | |-MemberExpr {{.*}} '<bound member function type>' .await_transform {{.*}}66// CHECK: | | | `-DeclRefExpr {{.*}} 'std::coroutine_traits<awaitable>::promise_type':'awaitable_frame' lvalue Var {{.*}} '__promise' 'std::coroutine_traits<awaitable>::promise_type':'awaitable_frame'67// CHECK: | | `-CXXTemporaryObjectExpr {{.*}} 'executor' 'void (){{.*}} noexcept' zeroing68// CHECK: | |-ExprWithCleanups {{.*}} 'void'69// CHECK: | | `-CXXMemberCallExpr {{.*}} 'void'70// CHECK: | | |-MemberExpr {{.*}} '<bound member function type>' .await_suspend {{.*}}71// CHECK: | | | `-OpaqueValueExpr {{.*}} 'result_t' lvalue72// CHECK: | | | `-MaterializeTemporaryExpr {{.*}} 'result_t' lvalue73// CHECK: | | | `-CXXBindTemporaryExpr {{.*}} 'result_t' (CXXTemporary {{.*}})74// CHECK: | | | `-CXXMemberCallExpr {{.*}} 'result_t'75// CHECK: | | | |-MemberExpr {{.*}} '<bound member function type>' .await_transform {{.*}}76// CHECK: | | | | `-DeclRefExpr {{.*}} 'std::coroutine_traits<awaitable>::promise_type':'awaitable_frame' lvalue Var {{.*}} '__promise' 'std::coroutine_traits<awaitable>::promise_type':'awaitable_frame'77// CHECK: | | | `-CXXTemporaryObjectExpr {{.*}} 'executor' 'void (){{.*}} noexcept' zeroing78// CHECK: | | `-ImplicitCastExpr {{.*}} 'std::coroutine_handle<void>' <ConstructorConversion>79// CHECK: | | `-CXXConstructExpr {{.*}} 'std::coroutine_handle<void>' 'void (coroutine_handle<awaitable_frame> &&){{.*}} noexcept'80// CHECK: | | `-MaterializeTemporaryExpr {{.*}} 'coroutine_handle<awaitable_frame>' xvalue81// CHECK: | | `-CallExpr {{.*}} 'coroutine_handle<awaitable_frame>'82// CHECK: | | |-ImplicitCastExpr {{.*}} 'coroutine_handle<awaitable_frame> (*)(void *) noexcept' <FunctionToPointerDecay>83// CHECK: | | | `-DeclRefExpr {{.*}} 'coroutine_handle<awaitable_frame> (void *) noexcept' lvalue CXXMethod {{.*}} 'from_address' 'coroutine_handle<awaitable_frame> (void *) noexcept'84// CHECK: | | `-CallExpr {{.*}} 'void *'85// CHECK: | | `-ImplicitCastExpr {{.*}} 'void *(*)() noexcept' <FunctionToPointerDecay>86// CHECK: | | `-DeclRefExpr {{.*}} 'void *() noexcept' lvalue Function {{.*}} '__builtin_coro_frame' 'void *() noexcept'87// CHECK: | `-CXXMemberCallExpr {{.*}} 'void'88// CHECK: | `-MemberExpr {{.*}} '<bound member function type>' .await_resume {{.*}}89// CHECK: | `-ImplicitCastExpr {{.*}} 'const awaitable_frame::result_t' lvalue <NoOp>90// CHECK: | `-OpaqueValueExpr {{.*}} 'result_t' lvalue91// CHECK: | `-MaterializeTemporaryExpr {{.*}} 'result_t' lvalue92// CHECK: | `-CXXBindTemporaryExpr {{.*}} 'result_t' (CXXTemporary {{.*}})93// CHECK: | `-CXXMemberCallExpr {{.*}} 'result_t'94// CHECK: | |-MemberExpr {{.*}} '<bound member function type>' .await_transform {{.*}}95// CHECK: | | `-DeclRefExpr {{.*}} 'std::coroutine_traits<awaitable>::promise_type':'awaitable_frame' lvalue Var {{.*}} '__promise' 'std::coroutine_traits<awaitable>::promise_type':'awaitable_frame'96// CHECK: | `-CXXTemporaryObjectExpr {{.*}} <col:12, col:21> 'executor' 'void (){{.*}} noexcept' zeroing97 98// Rest of the generated coroutine statements omitted.99