From: Douglas Gregor Date: Fri, 21 Jan 2011 21:08:57 +0000 (+0000) Subject: Generalize the NRVO move-construction-based initialization routine. No functionality... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=07f402cff25354c5f06f307f19b0c57c09d964bd;p=clang Generalize the NRVO move-construction-based initialization routine. No functionality change git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@123996 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 108a60b4f7..6e989ac006 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1025,6 +1025,11 @@ public: bool DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType); + ExprResult PerformMoveOrCopyInitialization(const InitializedEntity &Entity, + const VarDecl *NRVOCandidate, + QualType ResultType, + Expr *Value); + ExprResult PerformCopyInitialization(const InitializedEntity &Entity, SourceLocation EqualLoc, ExprResult Init); diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 015dcbb8c9..72d28e6ca0 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -1137,37 +1137,34 @@ const VarDecl *Sema::getCopyElisionCandidate(QualType ReturnType, return 0; } -/// \brief Perform the initialization of a return value. +/// \brief Perform the initialization of a potentially-movable value, which +/// is the result of return value. /// /// This routine implements C++0x [class.copy]p33, which attempts to treat /// returned lvalues as rvalues in certain cases (to prefer move construction), /// then falls back to treating them as lvalues if that failed. -static ExprResult initializeReturnValue(Sema &S, - const VarDecl *NRVOCandidate, - SourceLocation ReturnLoc, - QualType ResultType, - Expr *RetValExp) { +ExprResult +Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity, + const VarDecl *NRVOCandidate, + QualType ResultType, + Expr *Value) { // C++0x [class.copy]p33: // When the criteria for elision of a copy operation are met or would // be met save for the fact that the source object is a function // parameter, and the object to be copied is designated by an lvalue, // overload resolution to select the constructor for the copy is first // performed as if the object were designated by an rvalue. - InitializedEntity Entity = InitializedEntity::InitializeResult(ReturnLoc, - ResultType, - NRVOCandidate != 0); - ExprResult Res = ExprError(); - if (NRVOCandidate || S.getCopyElisionCandidate(ResultType, RetValExp, true)) { + if (NRVOCandidate || getCopyElisionCandidate(ResultType, Value, true)) { ImplicitCastExpr AsRvalue(ImplicitCastExpr::OnStack, - RetValExp->getType(), CK_LValueToRValue, - RetValExp, VK_XValue); + Value->getType(), CK_LValueToRValue, + Value, VK_XValue); Expr *InitExpr = &AsRvalue; InitializationKind Kind - = InitializationKind::CreateCopy(RetValExp->getLocStart(), - RetValExp->getLocStart()); - InitializationSequence Seq(S, Entity, Kind, &InitExpr, 1); + = InitializationKind::CreateCopy(Value->getLocStart(), + Value->getLocStart()); + InitializationSequence Seq(*this, Entity, Kind, &InitExpr, 1); // [...] If overload resolution fails, or if the type of the first // parameter of the selected constructor is not an rvalue reference @@ -1185,25 +1182,24 @@ static ExprResult initializeReturnValue(Sema &S, = cast(Step->Function.Function); const RValueReferenceType *RRefType - = Constructor->getParamDecl(0)->getType() - ->getAs(); + = Constructor->getParamDecl(0)->getType() + ->getAs(); // If we don't meet the criteria, break out now. if (!RRefType || - !S.Context.hasSameUnqualifiedType(RRefType->getPointeeType(), - ResultType)) + !Context.hasSameUnqualifiedType(RRefType->getPointeeType(), + Context.getTypeDeclType(Constructor->getParent()))) break; // Promote "AsRvalue" to the heap, since we now need this // expression node to persist. - RetValExp = ImplicitCastExpr::Create(S.Context, - RetValExp->getType(), - CK_LValueToRValue, - RetValExp, 0, VK_XValue); + Value = ImplicitCastExpr::Create(Context, Value->getType(), + CK_LValueToRValue, Value, 0, + VK_XValue); // Complete type-checking the initialization of the return type // using the constructor we found. - Res = Seq.Perform(S, Entity, Kind, MultiExprArg(&RetValExp, 1)); + Res = Seq.Perform(*this, Entity, Kind, MultiExprArg(&Value, 1)); } } } @@ -1212,7 +1208,7 @@ static ExprResult initializeReturnValue(Sema &S, // above, or overload resolution failed. Either way, we need to try // (again) now with the return value expression as written. if (Res.isInvalid()) - Res = S.PerformCopyInitialization(Entity, SourceLocation(), RetValExp); + Res = PerformCopyInitialization(Entity, SourceLocation(), Value); return Res; } @@ -1273,8 +1269,11 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { // In C++ the return statement is handled via a copy initialization. // the C version of which boils down to CheckSingleAssignmentConstraints. NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, false); - ExprResult Res = initializeReturnValue(*this, NRVOCandidate, ReturnLoc, - FnRetType, RetValExp); + InitializedEntity Entity = InitializedEntity::InitializeResult(ReturnLoc, + FnRetType, + NRVOCandidate != 0); + ExprResult Res = PerformMoveOrCopyInitialization(Entity, NRVOCandidate, + FnRetType, RetValExp); if (Res.isInvalid()) { // FIXME: Cleanup temporaries here, anyway? return StmtError(); @@ -1367,8 +1366,11 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { // In C++ the return statement is handled via a copy initialization. // the C version of which boils down to CheckSingleAssignmentConstraints. NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, false); - ExprResult Res = initializeReturnValue(*this, NRVOCandidate, ReturnLoc, - FnRetType, RetValExp); + InitializedEntity Entity = InitializedEntity::InitializeResult(ReturnLoc, + FnRetType, + NRVOCandidate != 0); + ExprResult Res = PerformMoveOrCopyInitialization(Entity, NRVOCandidate, + FnRetType, RetValExp); if (Res.isInvalid()) { // FIXME: Cleanup temporaries here, anyway? return StmtError();