// RUN: %clang_cc1 -std=c++20 -ast-dump -ast-dump-filter=foo %s | FileCheck %s --strict-whitespace // RUN: %clang_cc1 -std=c++20 -triple i386-windows-pc -ast-dump -ast-dump-filter=foo %s | FileCheck %s --strict-whitespace namespace std { template struct coroutine_traits; template struct coroutine_handle { template coroutine_handle(coroutine_handle &&) noexcept; static coroutine_handle from_address(void *__addr) noexcept; }; } // namespace std struct executor {}; struct awaitable {}; struct awaitable_frame { awaitable get_return_object(); void return_void(); void unhandled_exception(); struct result_t { ~result_t(); bool await_ready() const noexcept; void await_suspend(std::coroutine_handle) noexcept; void await_resume() const noexcept; }; result_t initial_suspend() noexcept; result_t final_suspend() noexcept; result_t await_transform(executor) noexcept; }; namespace std { template <> struct coroutine_traits { typedef awaitable_frame promise_type; }; } // namespace std awaitable foo() { co_await executor(); } // Check that CoawaitExpr contains the correct subexpressions, including // the operand expression as written in the source. // CHECK-LABEL: Dumping foo: // CHECK: FunctionDecl {{.*}} foo 'awaitable ()' // CHECK: `-CoroutineBodyStmt {{.*}} // CHECK: |-CompoundStmt {{.*}} // CHECK: | `-ExprWithCleanups {{.*}} 'void' // CHECK: | `-CoawaitExpr {{.*}} 'void' // CHECK: | |-CXXTemporaryObjectExpr {{.*}} 'executor' 'void (){{.*}} noexcept' zeroing // CHECK: | |-MaterializeTemporaryExpr {{.*}} 'result_t':'awaitable_frame::result_t' lvalue // CHECK: | | `-CXXBindTemporaryExpr {{.*}} 'result_t':'awaitable_frame::result_t' (CXXTemporary {{.*}}) // CHECK: | | `-CXXMemberCallExpr {{.*}} 'result_t':'awaitable_frame::result_t' // CHECK: | | |-MemberExpr {{.*}} '' .await_transform {{.*}} // CHECK: | | | `-DeclRefExpr {{.*}} 'std::coroutine_traits::promise_type':'awaitable_frame' lvalue Var {{.*}} '__promise' 'std::coroutine_traits::promise_type':'awaitable_frame' // CHECK: | | `-CXXTemporaryObjectExpr {{.*}} 'executor' 'void (){{.*}} noexcept' zeroing // CHECK: | |-ExprWithCleanups {{.*}} 'bool' // CHECK: | | `-CXXMemberCallExpr {{.*}} 'bool' // CHECK: | | `-MemberExpr {{.*}} '' .await_ready {{.*}} // CHECK: | | `-ImplicitCastExpr {{.*}} 'const awaitable_frame::result_t' lvalue // CHECK: | | `-OpaqueValueExpr {{.*}} 'result_t':'awaitable_frame::result_t' lvalue // CHECK: | | `-MaterializeTemporaryExpr {{.*}} 'result_t':'awaitable_frame::result_t' lvalue // CHECK: | | `-CXXBindTemporaryExpr {{.*}} 'result_t':'awaitable_frame::result_t' (CXXTemporary {{.*}}) // CHECK: | | `-CXXMemberCallExpr {{.*}} 'result_t':'awaitable_frame::result_t' // CHECK: | | |-MemberExpr {{.*}} '' .await_transform {{.*}} // CHECK: | | | `-DeclRefExpr {{.*}} 'std::coroutine_traits::promise_type':'awaitable_frame' lvalue Var {{.*}} '__promise' 'std::coroutine_traits::promise_type':'awaitable_frame' // CHECK: | | `-CXXTemporaryObjectExpr {{.*}} 'executor' 'void (){{.*}} noexcept' zeroing // CHECK: | |-ExprWithCleanups {{.*}} 'void' // CHECK: | | `-CXXMemberCallExpr {{.*}} 'void' // CHECK: | | |-MemberExpr {{.*}} '' .await_suspend {{.*}} // CHECK: | | | `-OpaqueValueExpr {{.*}} 'result_t':'awaitable_frame::result_t' lvalue // CHECK: | | | `-MaterializeTemporaryExpr {{.*}} 'result_t':'awaitable_frame::result_t' lvalue // CHECK: | | | `-CXXBindTemporaryExpr {{.*}} 'result_t':'awaitable_frame::result_t' (CXXTemporary {{.*}}) // CHECK: | | | `-CXXMemberCallExpr {{.*}} 'result_t':'awaitable_frame::result_t' // CHECK: | | | |-MemberExpr {{.*}} '' .await_transform {{.*}} // CHECK: | | | | `-DeclRefExpr {{.*}} 'std::coroutine_traits::promise_type':'awaitable_frame' lvalue Var {{.*}} '__promise' 'std::coroutine_traits::promise_type':'awaitable_frame' // CHECK: | | | `-CXXTemporaryObjectExpr {{.*}} 'executor' 'void (){{.*}} noexcept' zeroing // CHECK: | | `-ImplicitCastExpr {{.*}} 'std::coroutine_handle' // CHECK: | | `-CXXConstructExpr {{.*}} 'std::coroutine_handle' 'void (coroutine_handle &&){{.*}} noexcept' // CHECK: | | `-MaterializeTemporaryExpr {{.*}} 'coroutine_handle':'std::coroutine_handle' xvalue // CHECK: | | `-CallExpr {{.*}} 'coroutine_handle':'std::coroutine_handle' // CHECK: | | |-ImplicitCastExpr {{.*}} 'coroutine_handle (*)(void *) noexcept' // CHECK: | | | `-DeclRefExpr {{.*}} 'coroutine_handle (void *) noexcept' lvalue CXXMethod {{.*}} 'from_address' 'coroutine_handle (void *) noexcept' // CHECK: | | `-CallExpr {{.*}} 'void *' // CHECK: | | `-ImplicitCastExpr {{.*}} 'void *(*)() noexcept' // CHECK: | | `-DeclRefExpr {{.*}} 'void *() noexcept' lvalue Function {{.*}} '__builtin_coro_frame' 'void *() noexcept' // CHECK: | `-CXXMemberCallExpr {{.*}} 'void' // CHECK: | `-MemberExpr {{.*}} '' .await_resume {{.*}} // CHECK: | `-ImplicitCastExpr {{.*}} 'const awaitable_frame::result_t' lvalue // CHECK: | `-OpaqueValueExpr {{.*}} 'result_t':'awaitable_frame::result_t' lvalue // CHECK: | `-MaterializeTemporaryExpr {{.*}} 'result_t':'awaitable_frame::result_t' lvalue // CHECK: | `-CXXBindTemporaryExpr {{.*}} 'result_t':'awaitable_frame::result_t' (CXXTemporary {{.*}}) // CHECK: | `-CXXMemberCallExpr {{.*}} 'result_t':'awaitable_frame::result_t' // CHECK: | |-MemberExpr {{.*}} '' .await_transform {{.*}} // CHECK: | | `-DeclRefExpr {{.*}} 'std::coroutine_traits::promise_type':'awaitable_frame' lvalue Var {{.*}} '__promise' 'std::coroutine_traits::promise_type':'awaitable_frame' // CHECK: | `-CXXTemporaryObjectExpr {{.*}} 'executor' 'void (){{.*}} noexcept' zeroing // Rest of the generated coroutine statements omitted.