diff options
author | Douglas Gregor <dgregor@apple.com> | 2012-02-09 10:18:50 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2012-02-09 10:18:50 +0000 |
commit | 54042f1bd78f1f1ea86be7d4af541462e127d2ed (patch) | |
tree | 5adac67898a64f117ef4f912044173465cc121ad /lib/Sema/SemaLambda.cpp | |
parent | 760b37bcae12f4bbc68bb6cabf6ed68d265b0826 (diff) |
Implement return type deduction for lambdas per C++11
[expr.prim.lambda]p4, including the current suggested resolution of
core isue 975, which allows multiple return statements so long as the
types match. ExtWarn when user code is actually making use of this
extension.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150168 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaLambda.cpp')
-rw-r--r-- | lib/Sema/SemaLambda.cpp | 47 |
1 files changed, 46 insertions, 1 deletions
diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index 6d8e6a1029..73ef229a6b 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -294,6 +294,7 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, bool LambdaExprNeedsCleanups; { LambdaScopeInfo *LSI = getCurLambda(); + CXXMethodDecl *CallOperator = LSI->CallOperator; Class = LSI->Lambda; IntroducerRange = LSI->IntroducerRange; ExplicitParams = LSI->ExplicitParams; @@ -342,6 +343,51 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, break; } + // C++11 [expr.prim.lambda]p4: + // If a lambda-expression does not include a + // trailing-return-type, it is as if the trailing-return-type + // denotes the following type: + // FIXME: Assumes current resolution to core issue 975. + if (LSI->HasImplicitReturnType) { + // - if there are no return statements in the + // compound-statement, or all return statements return + // either an expression of type void or no expression or + // braced-init-list, the type void; + if (LSI->ReturnType.isNull()) { + LSI->ReturnType = Context.VoidTy; + } else { + // C++11 [expr.prim.lambda]p4: + // - if the compound-statement is of the form + // + // { attribute-specifier-seq[opt] return expression ; } + // + // the type of the returned expression after + // lvalue-to-rvalue conversion (4.1), array-to-pointer + // conver- sion (4.2), and function-to-pointer conversion + // (4.3); + // + // Since we're accepting the resolution to a post-C++11 core + // issue with a non-trivial extension, provide a warning (by + // default). + CompoundStmt *CompoundBody = cast<CompoundStmt>(Body); + if (!(CompoundBody->size() == 1 && + isa<ReturnStmt>(*CompoundBody->body_begin())) && + !Context.hasSameType(LSI->ReturnType, Context.VoidTy)) + Diag(IntroducerRange.getBegin(), + diag::ext_lambda_implies_void_return); + } + + // Create a function type with the inferred return type. + const FunctionProtoType *Proto + = CallOperator->getType()->getAs<FunctionProtoType>(); + QualType FunctionTy + = Context.getFunctionType(LSI->ReturnType, + Proto->arg_type_begin(), + Proto->getNumArgs(), + Proto->getExtProtoInfo()); + CallOperator->setType(FunctionTy); + } + // Finalize the lambda class. SmallVector<Decl*, 4> Fields(Class->field_begin(), Class->field_end()); ActOnFields(0, Class->getLocation(), Class, Fields, @@ -351,7 +397,6 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, // C++ [expr.prim.lambda]p7: // The lambda-expression's compound-statement yields the // function-body (8.4) of the function call operator [...]. - CXXMethodDecl *CallOperator = LSI->CallOperator; ActOnFinishFunctionBody(CallOperator, Body, /*IsInstantation=*/false); CallOperator->setLexicalDeclContext(Class); } |