coroutines: Handle component_ref in captures_temporary
gcc/cp * coroutines.cc (captures_temporary): Strip component_ref to its base object. gcc/testsuite * g++.dg/coroutines/torture/co-await-15-capture-comp-ref.C: New test.
This commit is contained in:
parent
c46da87b9d
commit
7f327e8765
@ -7,6 +7,11 @@
|
||||
|
||||
2020-03-03 Jun Ma <JunMa@linux.alibaba.com>
|
||||
|
||||
* coroutines.cc (captures_temporary): Strip component_ref
|
||||
to its base object.
|
||||
|
||||
2020-03-03 Jun Ma <JunMa@linux.alibaba.com>
|
||||
|
||||
* coroutines.cc (finish_co_await_expr): Build co_await_expr
|
||||
with unknown_type_node.
|
||||
(finish_co_yield_expr): Ditto.
|
||||
|
@ -2613,12 +2613,22 @@ captures_temporary (tree *stmt, int *do_subtree, void *d)
|
||||
continue;
|
||||
|
||||
parm = TREE_OPERAND (parm, 0);
|
||||
if (TREE_CODE (parm) == VAR_DECL && !DECL_ARTIFICIAL (parm))
|
||||
/* This isn't a temporary... */
|
||||
continue;
|
||||
|
||||
if (TREE_CODE (parm) == PARM_DECL)
|
||||
/* .. nor is this... */
|
||||
/* In case of component_ref, we need to capture the object of base
|
||||
class as if it is temporary object. There are two possibilities:
|
||||
(*base).field and base->field. */
|
||||
while (TREE_CODE (parm) == COMPONENT_REF)
|
||||
{
|
||||
parm = TREE_OPERAND (parm, 0);
|
||||
if (TREE_CODE (parm) == INDIRECT_REF)
|
||||
parm = TREE_OPERAND (parm, 0);
|
||||
parm = STRIP_NOPS (parm);
|
||||
}
|
||||
|
||||
/* This isn't a temporary. */
|
||||
if ((TREE_CODE (parm) == VAR_DECL && !DECL_ARTIFICIAL (parm))
|
||||
|| TREE_CODE (parm) == PARM_DECL
|
||||
|| TREE_CODE (parm) == NON_LVALUE_EXPR)
|
||||
continue;
|
||||
|
||||
if (TREE_CODE (parm) == TARGET_EXPR)
|
||||
|
@ -29,6 +29,10 @@
|
||||
* gcc.c-torture/compile/pr93927-1.c: New test.
|
||||
* gcc.c-torture/compile/pr93927-2.c: New test.
|
||||
|
||||
2020-03-03 Jun Ma <JunMa@linux.alibaba.com>
|
||||
|
||||
* g++.dg/coroutines/torture/co-await-15-capture-comp-ref.C: New test.
|
||||
|
||||
2020-03-03 Jun Ma <JunMa@linux.alibaba.com>
|
||||
|
||||
* g++.dg/coroutines/torture/co-await-14-template-traits.C: New test.
|
||||
|
@ -0,0 +1,99 @@
|
||||
// { dg-do run }
|
||||
|
||||
#include "../coro.h"
|
||||
|
||||
class resumable {
|
||||
public:
|
||||
struct promise_type;
|
||||
using coro_handle = std::coroutine_handle<promise_type>;
|
||||
resumable(coro_handle handle) : handle_(handle) { }
|
||||
resumable(resumable&) = delete;
|
||||
resumable(resumable&&) = delete;
|
||||
~resumable() { handle_.destroy(); }
|
||||
coro_handle handle_;
|
||||
};
|
||||
|
||||
struct resumable::promise_type {
|
||||
using coro_handle = std::coroutine_handle<promise_type>;
|
||||
int used;
|
||||
auto get_return_object() {
|
||||
return coro_handle::from_promise(*this);
|
||||
}
|
||||
auto initial_suspend() { return std::suspend_never(); }
|
||||
auto final_suspend() { return std::suspend_always(); }
|
||||
void return_value(int x) {used = x;}
|
||||
void unhandled_exception() {}
|
||||
|
||||
struct TestAwaiter {
|
||||
int recent_test;
|
||||
TestAwaiter(int test) : recent_test{test} {}
|
||||
bool await_ready() { return false; }
|
||||
void await_suspend(std::coroutine_handle<promise_type>) {}
|
||||
int await_resume() {
|
||||
return recent_test;
|
||||
}
|
||||
auto operator co_await() {
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
struct TestAwaiterCH :TestAwaiter {
|
||||
TestAwaiterCH(int test) : TestAwaiter(test) {};
|
||||
};
|
||||
|
||||
struct TestAwaiterCHCH :TestAwaiterCH {
|
||||
TestAwaiterCHCH(int test) : TestAwaiterCH(test) {};
|
||||
|
||||
resumable foo(){
|
||||
int x = co_await *this;
|
||||
co_return x;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
struct TestP {
|
||||
resumable::promise_type::TestAwaiterCHCH tp = resumable::promise_type::TestAwaiterCHCH(6);
|
||||
};
|
||||
|
||||
resumable foo1(int t){
|
||||
int x = co_await resumable::promise_type::TestAwaiterCH(t);
|
||||
co_return x;
|
||||
}
|
||||
|
||||
resumable foo2(){
|
||||
struct TestP TP;
|
||||
int x = co_await TP.tp;
|
||||
co_return x;
|
||||
}
|
||||
|
||||
resumable foo3(){
|
||||
int x = co_await TestP{}.tp;
|
||||
co_return x;
|
||||
}
|
||||
|
||||
int main(){
|
||||
auto t = resumable::promise_type::TestAwaiterCHCH(4);
|
||||
resumable res = t.foo();
|
||||
while (!res.handle_.done())
|
||||
res.handle_.resume();
|
||||
if (res.handle_.promise().used != 4)
|
||||
abort();
|
||||
|
||||
resumable res1 = foo1(5);
|
||||
while (!res1.handle_.done())
|
||||
res1.handle_.resume();
|
||||
if (res1.handle_.promise().used != 5)
|
||||
abort();
|
||||
|
||||
resumable res2 = foo2();
|
||||
while (!res2.handle_.done())
|
||||
res2.handle_.resume();
|
||||
if (res2.handle_.promise().used != 6)
|
||||
abort();
|
||||
|
||||
resumable res3 = foo2();
|
||||
while (!res3.handle_.done())
|
||||
res3.handle_.resume();
|
||||
if (res3.handle_.promise().used != 6)
|
||||
abort();
|
||||
}
|
Loading…
Reference in New Issue
Block a user