diff options
author | Sebastian Redl <sebastian.redl@getdesigned.at> | 2009-04-12 17:16:29 +0000 |
---|---|---|
committer | Sebastian Redl <sebastian.redl@getdesigned.at> | 2009-04-12 17:16:29 +0000 |
commit | e2b6833d445c7a4ce64f1816c05f176ba1740aca (patch) | |
tree | 654e1620b4b2022776410b7c16c044fbdfe3af35 /lib/Sema/SemaStmt.cpp | |
parent | 36dc958556adb36efd060a2773e026727005e3a8 (diff) |
Parse deleted member functions. Parsing member declarations goes through a different code path that I forgot previously.
Implement the rvalue reference overload dance for returning local objects. Returning a local object first tries to find a move constructor now.
The error message when no move constructor is defined (or is not applicable) and the copy constructor is deleted is quite ugly, though.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68902 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaStmt.cpp')
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 47 |
1 files changed, 44 insertions, 3 deletions
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index d258ec3869..d2e158658c 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -754,6 +754,32 @@ 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.getCanonicalType(RetType).getUnqualifiedType() != + Ctx.getCanonicalType(ExprType).getUnqualifiedType()) + 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 = static_cast<Expr *>(rex.release()); @@ -800,16 +826,31 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, ExprArg rex) { if (!FnRetType->isDependentType() && !RetValExp->isTypeDependent()) { // we have a non-void function with an expression, continue checking - QualType RetValType = RetValExp->getType(); // C99 6.8.6.4p3(136): The return statement is not an assignment. The // 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; + // In C++ the return statement is handled via a copy initialization. // the C version of which boils down to CheckSingleAssignmentConstraints. - // FIXME: Leaks RetValExp. - if (PerformCopyInitialization(RetValExp, FnRetType, "returning")) + // FIXME: Leaks RetValExp on error. + if (PerformCopyInitialization(RetValExp, FnRetType, "returning", Elidable)) return StmtError(); if (RetValExp) CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc); |