diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-05-15 00:13:29 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-05-15 00:13:29 +0000 |
commit | 3c9034cb7ff1d6c1e4ecd1b44c98f553df013c7c (patch) | |
tree | 51a260b4bf4837766cfd3d2f06de837b8ffc08df /lib/Sema/SemaStmt.cpp | |
parent | 67d438d39a1cc37c372a2684dc354f58d0169bb1 (diff) |
Recognize when the named return value optimization applies in a
"return" statement and mark the corresponding CXXConstructExpr as
elidable. Teach CodeGen that eliding a temporary is different from
eliding an object construction.
This is just a baby step toward NRVO.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@103849 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaStmt.cpp')
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 82 |
1 files changed, 37 insertions, 45 deletions
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index f9edbaff5f..d9210f6a1b 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -1058,6 +1058,31 @@ Sema::ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope) { return Owned(new (Context) BreakStmt(BreakLoc)); } +/// IsReturnCopyElidable - Whether returning @p RetExpr from a function that +/// returns a @p RetType fulfills the criteria for copy elision (C++0x 12.8p34). +static bool IsReturnCopyElidable(ASTContext &Ctx, QualType RetType, + Expr *RetExpr) { + QualType ExprType = RetExpr->getType(); + // - in a return statement in a function with ... + // ... a class return type ... + if (!RetType->isRecordType()) + return false; + // ... the same cv-unqualified type as the function return type ... + if (!Ctx.hasSameUnqualifiedType(RetType, ExprType)) + return false; + // ... the expression is the name of a non-volatile automatic object ... + // We ignore parentheses here. + // FIXME: Is this compliant? (Everyone else does it) + const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(RetExpr->IgnoreParens()); + if (!DR) + return false; + const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()); + if (!VD) + return false; + return VD->getKind() == Decl::Var && VD->hasLocalStorage() && + !VD->getType()->isReferenceType() && !VD->getType().isVolatileQualified(); +} + /// ActOnBlockReturnStmt - Utility routine to figure out block's return type. /// Action::OwningStmtResult @@ -1115,7 +1140,10 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { // the C version of which boils down to CheckSingleAssignmentConstraints. OwningExprResult Res = PerformCopyInitialization( InitializedEntity::InitializeResult(ReturnLoc, - FnRetType), + FnRetType, + IsReturnCopyElidable(Context, + FnRetType, + RetValExp)), SourceLocation(), Owned(RetValExp)); if (Res.isInvalid()) { @@ -1131,31 +1159,6 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { return Owned(new (Context) ReturnStmt(ReturnLoc, RetValExp)); } -/// IsReturnCopyElidable - Whether returning @p RetExpr from a function that -/// returns a @p RetType fulfills the criteria for copy elision (C++0x 12.8p15). -static bool IsReturnCopyElidable(ASTContext &Ctx, QualType RetType, - Expr *RetExpr) { - QualType ExprType = RetExpr->getType(); - // - in a return statement in a function with ... - // ... a class return type ... - if (!RetType->isRecordType()) - return false; - // ... the same cv-unqualified type as the function return type ... - if (!Ctx.hasSameUnqualifiedType(RetType, ExprType)) - return false; - // ... the expression is the name of a non-volatile automatic object ... - // We ignore parentheses here. - // FIXME: Is this compliant? - const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(RetExpr->IgnoreParens()); - if (!DR) - return false; - const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()); - if (!VD) - return false; - return VD->hasLocalStorage() && !VD->getType()->isReferenceType() - && !VD->getType().isVolatileQualified(); -} - Action::OwningStmtResult Sema::ActOnReturnStmt(SourceLocation ReturnLoc, ExprArg rex) { Expr *RetValExp = rex.takeAs<Expr>(); @@ -1214,29 +1217,18 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, ExprArg rex) { // overlap restriction of subclause 6.5.16.1 does not apply to the case of // function return. - // C++0x 12.8p15: When certain criteria are met, an implementation is - // allowed to omit the copy construction of a class object, [...] - // - in a return statement in a function with a class return type, when - // the expression is the name of a non-volatile automatic object with - // the same cv-unqualified type as the function return type, the copy - // operation can be omitted [...] - // C++0x 12.8p16: When the criteria for elision of a copy operation are met - // 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. - // Note that we only compute Elidable if we're in C++0x, since we don't - // care otherwise. - bool Elidable = getLangOptions().CPlusPlus0x ? - IsReturnCopyElidable(Context, FnRetType, RetValExp) : - false; - // FIXME: Elidable - (void)Elidable; - + // C++0x [class.copy]p34: + // + + // In C++ the return statement is handled via a copy initialization. // the C version of which boils down to CheckSingleAssignmentConstraints. OwningExprResult Res = PerformCopyInitialization( InitializedEntity::InitializeResult(ReturnLoc, - FnRetType), + FnRetType, + IsReturnCopyElidable(Context, + FnRetType, + RetValExp)), SourceLocation(), Owned(RetValExp)); if (Res.isInvalid()) { |