summaryrefslogtreecommitdiffstats
path: root/test/CodeGenCoroutines
diff options
context:
space:
mode:
authorEric Fiselier <eric@efcs.ca>2017-06-15 19:43:36 +0000
committerEric Fiselier <eric@efcs.ca>2017-06-15 19:43:36 +0000
commite512155cf60dfc7500625795ce5c1be29044a514 (patch)
treefea911a0b2ca3132faf884a631f929afb311b721 /test/CodeGenCoroutines
parentd5b5a8fae59b609c5e26c63c9e39b8441aa1085d (diff)
[coroutines] Allow co_await and co_yield expressions that return an lvalue to compile
Summary: The title says it all. Reviewers: GorNishanov, rsmith Reviewed By: GorNishanov Subscribers: rjmccall, cfe-commits Differential Revision: https://reviews.llvm.org/D34194 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@305496 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/CodeGenCoroutines')
-rw-r--r--test/CodeGenCoroutines/coro-await.cpp50
1 files changed, 49 insertions, 1 deletions
diff --git a/test/CodeGenCoroutines/coro-await.cpp b/test/CodeGenCoroutines/coro-await.cpp
index 1e2deaa8f5..fc6559f1e0 100644
--- a/test/CodeGenCoroutines/coro-await.cpp
+++ b/test/CodeGenCoroutines/coro-await.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fcoroutines-ts -std=c++14 -emit-llvm %s -o - -disable-llvm-passes | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fcoroutines-ts -std=c++14 \
+// RUN: -emit-llvm %s -o - -disable-llvm-passes -Wno-coroutine -Wno-unused | FileCheck %s
namespace std {
namespace experimental {
@@ -278,3 +279,50 @@ void AwaitLValue() {
suspend_always lval;
co_await lval;
}
+
+struct RefTag { };
+
+struct AwaitResumeReturnsLValue {
+ bool await_ready();
+ void await_suspend(std::experimental::coroutine_handle<>);
+ RefTag& await_resume();
+};
+
+
+template<>
+struct std::experimental::coroutine_traits<void,double> {
+ struct promise_type {
+ void get_return_object();
+ init_susp initial_suspend();
+ final_susp final_suspend();
+ void return_void();
+ AwaitResumeReturnsLValue yield_value(int);
+ };
+};
+
+// Verifies that we don't crash when returning an lvalue from an await_resume()
+// expression.
+// CHECK-LABEL: define void @_Z18AwaitReturnsLValued(double)
+void AwaitReturnsLValue(double) {
+ AwaitResumeReturnsLValue a;
+ // CHECK: %[[AVAR:.+]] = alloca %struct.AwaitResumeReturnsLValue,
+ // CHECK: %[[XVAR:.+]] = alloca %struct.RefTag*,
+
+ // CHECK: %[[YVAR:.+]] = alloca %struct.RefTag*,
+ // CHECK-NEXT: %[[TMP1:.+]] = alloca %struct.AwaitResumeReturnsLValue,
+
+ // CHECK: %[[ZVAR:.+]] = alloca %struct.RefTag*,
+ // CHECK-NEXT: %[[TMP2:.+]] = alloca %struct.AwaitResumeReturnsLValue,
+
+ // CHECK: %[[RES1:.+]] = call dereferenceable({{.*}}) %struct.RefTag* @_ZN24AwaitResumeReturnsLValue12await_resumeEv(%struct.AwaitResumeReturnsLValue* %[[AVAR]])
+ // CHECK-NEXT: store %struct.RefTag* %[[RES1]], %struct.RefTag** %[[XVAR]],
+ RefTag& x = co_await a;
+
+ // CHECK: %[[RES2:.+]] = call dereferenceable({{.*}}) %struct.RefTag* @_ZN24AwaitResumeReturnsLValue12await_resumeEv(%struct.AwaitResumeReturnsLValue* %[[TMP1]])
+ // CHECK-NEXT: store %struct.RefTag* %[[RES2]], %struct.RefTag** %[[YVAR]],
+
+ RefTag& y = co_await AwaitResumeReturnsLValue{};
+ // CHECK: %[[RES3:.+]] = call dereferenceable({{.*}}) %struct.RefTag* @_ZN24AwaitResumeReturnsLValue12await_resumeEv(%struct.AwaitResumeReturnsLValue* %[[TMP2]])
+ // CHECK-NEXT: store %struct.RefTag* %[[RES3]], %struct.RefTag** %[[ZVAR]],
+ RefTag& z = co_yield 42;
+}