Files
clang-p2996/clang/test/AST/coroutine-locals-cleanup.cpp
Chuanqi Xu 2fbd254aa4 [Coroutines] [Clang] Look up coroutine component in std namespace first
Summary: Now in libcxx and clang, all the coroutine components are
defined in std::experimental namespace.
And now the coroutine TS is merged into C++20. So in the working draft
like N4892, we could find the coroutine components is defined in std
namespace instead of std::experimental namespace.
And the coroutine support in clang seems to be relatively stable. So I
think it may be suitable to move the coroutine component into the
experiment namespace now.

But move the coroutine component into the std namespace may be an break
change. So I planned to split this change into two patch. One in clang
and other in libcxx.

This patch would make clang lookup coroutine_traits in std namespace
first. For the compatibility consideration, clang would lookup in
std::experimental namespace if it can't find definitions in std
namespace and emit a warning in this case. So the existing codes
wouldn't be break after update compiler.

Test Plan: check-clang, check-libcxx

Reviewed By: lxfind

Differential Revision: https://reviews.llvm.org/D108696
2021-09-03 10:22:55 +08:00

108 lines
3.1 KiB
C++

// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fcoroutines-ts -std=c++14 -fsyntax-only -ast-dump %s | FileCheck %s
#include "Inputs/std-coroutine.h"
using namespace std;
struct Task {
struct promise_type {
Task get_return_object() noexcept {
return Task{coroutine_handle<promise_type>::from_promise(*this)};
}
void return_void() noexcept {}
struct final_awaiter {
bool await_ready() noexcept { return false; }
coroutine_handle<> await_suspend(coroutine_handle<promise_type> h) noexcept {
h.destroy();
return {};
}
void await_resume() noexcept {}
};
void unhandled_exception() noexcept {}
final_awaiter final_suspend() noexcept { return {}; }
suspend_always initial_suspend() noexcept { return {}; }
template <typename Awaitable>
auto await_transform(Awaitable &&awaitable) {
return awaitable.co_viaIfAsync();
}
};
using handle_t = coroutine_handle<promise_type>;
class Awaiter {
public:
explicit Awaiter(handle_t coro) noexcept;
Awaiter(Awaiter &&other) noexcept;
Awaiter(const Awaiter &) = delete;
~Awaiter();
bool await_ready() noexcept { return false; }
handle_t await_suspend(coroutine_handle<> continuation) noexcept;
void await_resume();
private:
handle_t coro_;
};
Task(handle_t coro) noexcept : coro_(coro) {}
handle_t coro_;
Task(const Task &t) = delete;
Task(Task &&t) noexcept;
~Task();
Task &operator=(Task t) noexcept;
Awaiter co_viaIfAsync();
};
static Task foo() {
co_return;
}
Task bar() {
auto mode = 2;
switch (mode) {
case 1:
co_await foo();
break;
case 2:
co_await foo();
break;
default:
break;
}
}
// CHECK-LABEL: FunctionDecl {{.*}} bar 'Task ()'
// CHECK: SwitchStmt
// CHECK: CaseStmt
// CHECK: ExprWithCleanups {{.*}} 'void'
// CHECK-NEXT: CoawaitExpr
// CHECK-NEXT: MaterializeTemporaryExpr {{.*}} 'Task::Awaiter':'Task::Awaiter'
// CHECK: ExprWithCleanups {{.*}} 'bool'
// CHECK-NEXT: CXXMemberCallExpr {{.*}} 'bool'
// CHECK-NEXT: MemberExpr {{.*}} .await_ready
// CHECK: CallExpr {{.*}} 'void'
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(void *)'
// CHECK-NEXT: DeclRefExpr {{.*}} '__builtin_coro_resume' 'void (void *)'
// CHECK-NEXT: ExprWithCleanups {{.*}} 'void *'
// CHECK: CaseStmt
// CHECK: ExprWithCleanups {{.*}} 'void'
// CHECK-NEXT: CoawaitExpr
// CHECK-NEXT: MaterializeTemporaryExpr {{.*}} 'Task::Awaiter':'Task::Awaiter'
// CHECK: ExprWithCleanups {{.*}} 'bool'
// CHECK-NEXT: CXXMemberCallExpr {{.*}} 'bool'
// CHECK-NEXT: MemberExpr {{.*}} .await_ready
// CHECK: CallExpr {{.*}} 'void'
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(void *)'
// CHECK-NEXT: DeclRefExpr {{.*}} '__builtin_coro_resume' 'void (void *)'
// CHECK-NEXT: ExprWithCleanups {{.*}} 'void *'