From e4f15a2bf03c3f068113466aa1ed00fbcc572d83 Mon Sep 17 00:00:00 2001 From: Gor Nishanov Date: Tue, 23 May 2017 05:25:31 +0000 Subject: [PATCH] [coroutines] Skip over passthrough operator co_await https://reviews.llvm.org/D31627 llvm-svn: 303605 --- clang/lib/CodeGen/CGCoroutine.cpp | 14 ++++++++++++++ clang/test/CodeGenCoroutines/coro-await.cpp | 7 +++++++ 2 files changed, 21 insertions(+) diff --git a/clang/lib/CodeGen/CGCoroutine.cpp b/clang/lib/CodeGen/CGCoroutine.cpp index bb98c24..b16ab72 100644 --- a/clang/lib/CodeGen/CGCoroutine.cpp +++ b/clang/lib/CodeGen/CGCoroutine.cpp @@ -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(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); }); diff --git a/clang/test/CodeGenCoroutines/coro-await.cpp b/clang/test/CodeGenCoroutines/coro-await.cpp index dfeeba0..1e2deaa 100644 --- a/clang/test/CodeGenCoroutines/coro-await.cpp +++ b/clang/test/CodeGenCoroutines/coro-await.cpp @@ -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; +} -- 2.7.4