aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorIain Sandoe <iain@sandoe.co.uk>2021-10-02 12:44:01 +0100
committerIain Sandoe <iain@sandoe.co.uk>2021-10-03 20:41:59 +0100
commit0ee1ab15c237ffb50be1a5ce9c5e542b16df4d12 (patch)
treedc2bda9d2a7656bff68d73c083446387ea3befaa /gcc
parent8fbe1b18ed090a026d08f0b0e5f8cd56d652125d (diff)
downloadgcc-0ee1ab15c237ffb50be1a5ce9c5e542b16df4d12.zip
gcc-0ee1ab15c237ffb50be1a5ce9c5e542b16df4d12.tar.gz
gcc-0ee1ab15c237ffb50be1a5ce9c5e542b16df4d12.tar.bz2
coroutines: Look through NOPs for awaiter variables [PR 99575].
There was a missing STRIP_NOPS which meant that, in some cases, an awaiter variable could be hidden by a view-convert-expr. Signed-off-by: Iain Sandoe <iain@sandoe.co.uk> PR c++/99575 gcc/cp/ChangeLog: * coroutines.cc (build_co_await): Strip NOPs from candidate awaiter expressions before testing to see if they need a temporary. gcc/testsuite/ChangeLog: * g++.dg/coroutines/pr99575.C: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/coroutines.cc1
-rw-r--r--gcc/testsuite/g++.dg/coroutines/pr99575.C35
2 files changed, 36 insertions, 0 deletions
diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index 2f45575..876a146 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -1008,6 +1008,7 @@ build_co_await (location_t loc, tree a, suspend_point_kind suspend_kind)
}
/* Only build a temporary if we need it. */
+ STRIP_NOPS (e_proxy);
if (TREE_CODE (e_proxy) == PARM_DECL
|| (VAR_P (e_proxy) && !is_local_temp (e_proxy)))
{
diff --git a/gcc/testsuite/g++.dg/coroutines/pr99575.C b/gcc/testsuite/g++.dg/coroutines/pr99575.C
new file mode 100644
index 0000000..d5f86c1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/pr99575.C
@@ -0,0 +1,35 @@
+
+#include <coroutine>
+
+class Task {
+ public:
+ struct promise_type {
+ Task get_return_object() { return Task{}; }
+ std::suspend_always initial_suspend() { return {}; }
+ std::suspend_always final_suspend() noexcept { return {}; }
+ void unhandled_exception() {}
+ void return_void() {}
+ };
+
+ bool await_ready() const { return false; }
+ void await_suspend(std::coroutine_handle<void> continuation) {}
+ void await_resume() {}
+};
+
+class NonMoveableTask {
+ public:
+ NonMoveableTask() = default;
+ NonMoveableTask(const NonMoveableTask&) = delete;
+ NonMoveableTask(NonMoveableTask&&) = delete;
+
+ NonMoveableTask& operator=(const NonMoveableTask&) = delete;
+ NonMoveableTask& operator=(NonMoveableTask&& other) = delete;
+
+ bool await_ready() const { return false; }
+ void await_suspend(std::coroutine_handle<void>) {}
+ void await_resume() {}
+};
+
+Task Foo(NonMoveableTask* task) { co_await* task; }
+
+int main() {}