[coroutines] Skip over passthrough operator co_await
authorGor Nishanov <GorNishanov@gmail.com>
Tue, 23 May 2017 05:25:31 +0000 (05:25 +0000)
committerGor Nishanov <GorNishanov@gmail.com>
Tue, 23 May 2017 05:25:31 +0000 (05:25 +0000)
https://reviews.llvm.org/D31627

llvm-svn: 303605

clang/lib/CodeGen/CGCoroutine.cpp
clang/test/CodeGenCoroutines/coro-await.cpp

index bb98c24..b16ab72 100644 (file)
@@ -151,6 +151,20 @@ static RValue emitSuspendExpression(CodeGenFunction &CGF, CGCoroData &Coro,
                                     AwaitKind Kind, AggValueSlot aggSlot,
                                     bool ignoreResult) {
   auto *E = S.getCommonExpr();
+
+  // FIXME: rsmith 5/22/2017. Does it still make sense for us to have a 
+  // UO_Coawait at all? As I recall, the only purpose it ever had was to
+  // represent a dependent co_await expression that couldn't yet be resolved to
+  // a CoawaitExpr. But now we have (and need!) a separate DependentCoawaitExpr
+  // node to store unqualified lookup results, it seems that the UnaryOperator
+  // portion of the representation serves no purpose (and as seen in this patch,
+  // it's getting in the way). Can we remove it?
+
+  // Skip passthrough operator co_await (present when awaiting on an LValue).
+  if (auto *UO = dyn_cast<UnaryOperator>(E))
+    if (UO->getOpcode() == UO_Coawait)
+      E = UO->getSubExpr();
+
   auto Binder =
       CodeGenFunction::OpaqueValueMappingData::bind(CGF, S.getOpaqueValue(), E);
   auto UnbindOnExit = llvm::make_scope_exit([&] { Binder.unbind(CGF); });
index dfeeba0..1e2deaa 100644 (file)
@@ -271,3 +271,10 @@ extern "C" void EndlessLoop() {
   // CHECK-NOT: call void @_ZNSt12experimental16coroutine_traitsIJvEE12promise_type13final_suspendEv(
   // CHECK-NOT: call zeroext i1 @_ZN10final_susp11await_readyEv(%struct.final_susp*
 }
+
+// Verifies that we don't crash when awaiting on an lvalue.
+// CHECK-LABEL: @_Z11AwaitLValuev(
+void AwaitLValue() {
+  suspend_always lval;
+  co_await lval;
+}