aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaStmt.cpp
diff options
context:
space:
mode:
authorSebastian Redl <sebastian.redl@getdesigned.at>2009-04-12 17:16:29 +0000
committerSebastian Redl <sebastian.redl@getdesigned.at>2009-04-12 17:16:29 +0000
commite2b6833d445c7a4ce64f1816c05f176ba1740aca (patch)
tree654e1620b4b2022776410b7c16c044fbdfe3af35 /lib/Sema/SemaStmt.cpp
parent36dc958556adb36efd060a2773e026727005e3a8 (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.cpp47
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);