]> granicus.if.org Git - clang/commitdiff
[coroutines] Materialize the awaitable before generating the await_* calls.
authorRichard Smith <richard-llvm@metafoo.co.uk>
Sun, 22 Nov 2015 03:13:02 +0000 (03:13 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Sun, 22 Nov 2015 03:13:02 +0000 (03:13 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@253812 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaCoroutine.cpp

index a0d24b8cecd46f9f7b44ae0596b62c0571464efc..20c9c551d464120d29a5535c6161c906587d8ff3 100644 (file)
@@ -195,7 +195,7 @@ static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, SourceLocation Loc,
   const StringRef Funcs[] = {"await_ready", "await_suspend", "await_resume"};
   for (size_t I = 0, N = llvm::array_lengthof(Funcs); I != N; ++I) {
     Expr *Operand = new (S.Context) OpaqueValueExpr(
-        Loc, E->getType(), E->getValueKind(), E->getObjectKind(), E);
+        Loc, E->getType(), VK_LValue, E->getObjectKind(), E);
 
     // FIXME: Pass coroutine handle to await_suspend.
     ExprResult Result = buildMemberCall(S, Operand, Loc, Funcs[I], None);
@@ -237,8 +237,10 @@ ExprResult Sema::BuildCoawaitExpr(SourceLocation Loc, Expr *E) {
     return Res;
   }
 
-  // FIXME: If E is a prvalue, create a temporary.
-  // FIXME: If E is an xvalue, convert to lvalue.
+  // If the expression is a temporary, materialize it as an lvalue so that we
+  // can use it multiple times.
+  if (E->getValueKind() == VK_RValue)
+    E = new (Context) MaterializeTemporaryExpr(E->getType(), E, true);
 
   // Build the await_ready, await_suspend, await_resume calls.
   ReadySuspendResumeResult RSS = buildCoawaitCalls(*this, Loc, E);
@@ -306,8 +308,10 @@ ExprResult Sema::BuildCoyieldExpr(SourceLocation Loc, Expr *E) {
     return Res;
   }
 
-  // FIXME: If E is a prvalue, create a temporary.
-  // FIXME: If E is an xvalue, convert to lvalue.
+  // If the expression is a temporary, materialize it as an lvalue so that we
+  // can use it multiple times.
+  if (E->getValueKind() == VK_RValue)
+    E = new (Context) MaterializeTemporaryExpr(E->getType(), E, true);
 
   // Build the await_ready, await_suspend, await_resume calls.
   ReadySuspendResumeResult RSS = buildCoawaitCalls(*this, Loc, E);