forked from OSchip/llvm-project
[coroutines] Pass implicit object parameter to promise ctor (fix BUG37604)
Summary: Complete the implementation of p0914r1. Implicit object parameter should be passed to a promise constructor. Fixes: https://bugs.llvm.org/show_bug.cgi?id=37604 Reviewers: modocache, rsmith, lewissbaker Reviewed By: modocache Subscribers: cfe-commits, EricWF Differential Revision: https://reviews.llvm.org/D47454 llvm-svn: 333379
This commit is contained in:
parent
afa95ee03d
commit
07ac63f89e
|
@ -510,6 +510,20 @@ VarDecl *Sema::buildCoroutinePromise(SourceLocation Loc) {
|
|||
// Build a list of arguments, based on the coroutine functions arguments,
|
||||
// that will be passed to the promise type's constructor.
|
||||
llvm::SmallVector<Expr *, 4> CtorArgExprs;
|
||||
|
||||
// Add implicit object parameter.
|
||||
if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
|
||||
if (MD->isInstance() && !isLambdaCallOperator(MD)) {
|
||||
ExprResult ThisExpr = ActOnCXXThis(Loc);
|
||||
if (ThisExpr.isInvalid())
|
||||
return nullptr;
|
||||
ThisExpr = CreateBuiltinUnaryOp(Loc, UO_Deref, ThisExpr.get());
|
||||
if (ThisExpr.isInvalid())
|
||||
return nullptr;
|
||||
CtorArgExprs.push_back(ThisExpr.get());
|
||||
}
|
||||
}
|
||||
|
||||
auto &Moves = ScopeInfo->CoroutineParameterMoves;
|
||||
for (auto *PD : FD->parameters()) {
|
||||
if (PD->getType()->isDependentType())
|
||||
|
|
|
@ -156,3 +156,28 @@ void coroutine_matching_promise_constructor(promise_matching_constructor, int, f
|
|||
// CHECK: invoke void @_ZNSt12experimental16coroutine_traitsIJv28promise_matching_constructorifdEE12promise_typeC1ES1_ifd(%"struct.std::experimental::coroutine_traits<void, promise_matching_constructor, int, float, double>::promise_type"* %__promise, i32 %[[INT]], float %[[FLOAT]], double %[[DOUBLE]])
|
||||
co_return;
|
||||
}
|
||||
|
||||
struct some_class;
|
||||
|
||||
struct method {};
|
||||
|
||||
template <typename... Args> struct std::experimental::coroutine_traits<method, Args...> {
|
||||
struct promise_type {
|
||||
promise_type(some_class&, float);
|
||||
method get_return_object();
|
||||
suspend_always initial_suspend();
|
||||
suspend_always final_suspend();
|
||||
void return_void();
|
||||
void unhandled_exception();
|
||||
};
|
||||
};
|
||||
|
||||
struct some_class {
|
||||
method good_coroutine_calls_custom_constructor(float);
|
||||
};
|
||||
|
||||
// CHECK-LABEL: define void @_ZN10some_class39good_coroutine_calls_custom_constructorEf(%struct.some_class*
|
||||
method some_class::good_coroutine_calls_custom_constructor(float) {
|
||||
// CHECK: invoke void @_ZNSt12experimental16coroutine_traitsIJ6methodR10some_classfEE12promise_typeC1ES3_f(%"struct.std::experimental::coroutine_traits<method, some_class &, float>::promise_type"* %__promise, %struct.some_class* dereferenceable(1) %{{.+}}, float
|
||||
co_return;
|
||||
}
|
||||
|
|
|
@ -831,7 +831,7 @@ struct std::experimental::coroutine_traits<int, mismatch_gro_type_tag1> {
|
|||
};
|
||||
};
|
||||
|
||||
extern "C" int f(mismatch_gro_type_tag1) {
|
||||
extern "C" int f(mismatch_gro_type_tag1) {
|
||||
// expected-error@-1 {{cannot initialize return object of type 'int' with an rvalue of type 'void'}}
|
||||
co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
|
||||
}
|
||||
|
@ -848,7 +848,7 @@ struct std::experimental::coroutine_traits<int, mismatch_gro_type_tag2> {
|
|||
};
|
||||
};
|
||||
|
||||
extern "C" int f(mismatch_gro_type_tag2) {
|
||||
extern "C" int f(mismatch_gro_type_tag2) {
|
||||
// expected-error@-1 {{cannot initialize return object of type 'int' with an lvalue of type 'void *'}}
|
||||
co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
|
||||
}
|
||||
|
@ -866,7 +866,7 @@ struct std::experimental::coroutine_traits<int, mismatch_gro_type_tag3> {
|
|||
};
|
||||
};
|
||||
|
||||
extern "C" int f(mismatch_gro_type_tag3) {
|
||||
extern "C" int f(mismatch_gro_type_tag3) {
|
||||
// expected-error@-1 {{cannot initialize return object of type 'int' with an rvalue of type 'void'}}
|
||||
co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
|
||||
}
|
||||
|
@ -885,7 +885,7 @@ struct std::experimental::coroutine_traits<int, mismatch_gro_type_tag4> {
|
|||
};
|
||||
};
|
||||
|
||||
extern "C" int f(mismatch_gro_type_tag4) {
|
||||
extern "C" int f(mismatch_gro_type_tag4) {
|
||||
// expected-error@-1 {{cannot initialize return object of type 'int' with an rvalue of type 'char *'}}
|
||||
co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
|
||||
}
|
||||
|
@ -1246,7 +1246,10 @@ good_coroutine_calls_default_constructor() {
|
|||
co_return;
|
||||
}
|
||||
|
||||
struct some_class;
|
||||
|
||||
struct good_promise_custom_constructor {
|
||||
good_promise_custom_constructor(some_class&, float, int);
|
||||
good_promise_custom_constructor(double, float, int);
|
||||
good_promise_custom_constructor() = delete;
|
||||
coro<good_promise_custom_constructor> get_return_object();
|
||||
|
@ -1261,9 +1264,20 @@ good_coroutine_calls_custom_constructor(double, float, int) {
|
|||
co_return;
|
||||
}
|
||||
|
||||
struct some_class {
|
||||
coro<good_promise_custom_constructor>
|
||||
good_coroutine_calls_custom_constructor(float, int) {
|
||||
co_return;
|
||||
}
|
||||
coro<good_promise_custom_constructor>
|
||||
static good_coroutine_calls_custom_constructor(double, float, int) {
|
||||
co_return;
|
||||
}
|
||||
};
|
||||
|
||||
struct bad_promise_no_matching_constructor {
|
||||
bad_promise_no_matching_constructor(int, int, int);
|
||||
// expected-note@+1 {{'bad_promise_no_matching_constructor' has been explicitly marked deleted here}}
|
||||
// expected-note@+1 2 {{'bad_promise_no_matching_constructor' has been explicitly marked deleted here}}
|
||||
bad_promise_no_matching_constructor() = delete;
|
||||
coro<bad_promise_no_matching_constructor> get_return_object();
|
||||
suspend_always initial_suspend();
|
||||
|
@ -1278,6 +1292,14 @@ bad_coroutine_calls_with_no_matching_constructor(int, int) {
|
|||
co_return;
|
||||
}
|
||||
|
||||
struct some_class2 {
|
||||
coro<bad_promise_no_matching_constructor>
|
||||
bad_coroutine_calls_with_no_matching_constructor(int, int, int) {
|
||||
// expected-error@-1 {{call to deleted constructor}}
|
||||
co_return;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace CoroHandleMemberFunctionTest
|
||||
|
||||
class awaitable_no_unused_warn {
|
||||
|
|
Loading…
Reference in New Issue