diff options
author | Gor Nishanov <GorNishanov@gmail.com> | 2017-05-24 20:09:14 +0000 |
---|---|---|
committer | Gor Nishanov <GorNishanov@gmail.com> | 2017-05-24 20:09:14 +0000 |
commit | 33d5fd24a0840075411d3943e6310d11027e6e93 (patch) | |
tree | 259e62fcb1ceaa742e73673fee17df702c175266 /clang/lib/Sema/SemaCoroutine.cpp | |
parent | 7a8717d2165ec94ce882b4cc872582d109c41fbd (diff) | |
download | bcm5719-llvm-33d5fd24a0840075411d3943e6310d11027e6e93.tar.gz bcm5719-llvm-33d5fd24a0840075411d3943e6310d11027e6e93.zip |
[coroutines] Add support for coroutines with non-scalar parameters
Summary:
Simple types like int are handled by LLVM Coroutines just fine.
But for non-scalar parameters we need to create copies of those parameters in the coroutine frame and make all uses of those parameters to refer to parameter copies.
Reviewers: rsmith, EricWF, GorNishanov
Subscribers: cfe-commits
Differential Revision: https://reviews.llvm.org/D33507
llvm-svn: 303803
Diffstat (limited to 'clang/lib/Sema/SemaCoroutine.cpp')
-rw-r--r-- | clang/lib/Sema/SemaCoroutine.cpp | 62 |
1 files changed, 61 insertions, 1 deletions
diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp index b02196500d9..8f7011c985e 100644 --- a/clang/lib/Sema/SemaCoroutine.cpp +++ b/clang/lib/Sema/SemaCoroutine.cpp @@ -1160,8 +1160,68 @@ bool CoroutineStmtBuilder::makeGroDeclAndReturnStmt() { return true; } +// Create a static_cast\<T&&>(expr). +static Expr *castForMoving(Sema &S, Expr *E, QualType T = QualType()) { + if (T.isNull()) + T = E->getType(); + QualType TargetType = S.BuildReferenceType( + T, /*SpelledAsLValue*/ false, SourceLocation(), DeclarationName()); + SourceLocation ExprLoc = E->getLocStart(); + TypeSourceInfo *TargetLoc = + S.Context.getTrivialTypeSourceInfo(TargetType, ExprLoc); + + return S + .BuildCXXNamedCast(ExprLoc, tok::kw_static_cast, TargetLoc, E, + SourceRange(ExprLoc, ExprLoc), E->getSourceRange()) + .get(); +} + +/// \brief Build a variable declaration for move parameter. +static VarDecl *buildVarDecl(Sema &S, SourceLocation Loc, QualType Type, + StringRef Name) { + DeclContext *DC = S.CurContext; + IdentifierInfo *II = &S.PP.getIdentifierTable().get(Name); + TypeSourceInfo *TInfo = S.Context.getTrivialTypeSourceInfo(Type, Loc); + VarDecl *Decl = + VarDecl::Create(S.Context, DC, Loc, Loc, II, Type, TInfo, SC_None); + Decl->setImplicit(); + return Decl; +} + bool CoroutineStmtBuilder::makeParamMoves() { - // FIXME: Perform move-initialization of parameters into frame-local copies. + for (auto *paramDecl : FD.parameters()) { + auto Ty = paramDecl->getType(); + if (Ty->isDependentType()) + continue; + + // No need to copy scalars, llvm will take care of them. + if (Ty->getAsCXXRecordDecl()) { + if (!paramDecl->getIdentifier()) + continue; + + ExprResult ParamRef = + S.BuildDeclRefExpr(paramDecl, paramDecl->getType(), + ExprValueKind::VK_LValue, Loc); // FIXME: scope? + if (ParamRef.isInvalid()) + return false; + + Expr *RCast = castForMoving(S, ParamRef.get()); + + auto D = buildVarDecl(S, Loc, Ty, paramDecl->getIdentifier()->getName()); + + S.AddInitializerToDecl(D, RCast, /*DirectInit=*/true); + + // Convert decl to a statement. + StmtResult Stmt = S.ActOnDeclStmt(S.ConvertDeclToDeclGroup(D), Loc, Loc); + if (Stmt.isInvalid()) + return false; + + ParamMovesVector.push_back(Stmt.get()); + } + } + + // Convert to ArrayRef in CtorArgs structure that builder inherits from. + ParamMoves = ParamMovesVector; return true; } |