diff options
author | Douglas Gregor <dgregor@apple.com> | 2012-02-14 22:28:59 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2012-02-14 22:28:59 +0000 |
commit | c6889e7ed16604c51994e1f11becf213fdc64eb3 (patch) | |
tree | cd67da6857b1e624c3c190e4a9e3648c606381fb /lib | |
parent | 57b9c4e9d85971e20ab0dac3eadabae672c43c62 (diff) |
Implement C++ core issue 974, which permits default arguments for
lambda expressions. Because these issue was pulled back from Ready
status at the Kona meeting, we still emit an ExtWarn when using
default arguments for lambda expressions.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150519 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 16 | ||||
-rw-r--r-- | lib/Sema/SemaLambda.cpp | 49 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 25 |
3 files changed, 55 insertions, 35 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 84063e5fd0..624dc5d1e6 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -585,11 +585,25 @@ void Sema::CheckCXXDefaultArguments(FunctionDecl *FD) { unsigned NumParams = FD->getNumParams(); unsigned p; + bool IsLambda = FD->getOverloadedOperator() == OO_Call && + isa<CXXMethodDecl>(FD) && + cast<CXXMethodDecl>(FD)->getParent()->isLambda(); + // Find first parameter with a default argument for (p = 0; p < NumParams; ++p) { ParmVarDecl *Param = FD->getParamDecl(p); - if (Param->hasDefaultArg()) + if (Param->hasDefaultArg()) { + // C++11 [expr.prim.lambda]p5: + // [...] Default arguments (8.3.6) shall not be specified in the + // parameter-declaration-clause of a lambda-declarator. + // + // FIXME: Core issue 974 strikes this sentence, we only provide an + // extension warning. + if (IsLambda) + Diag(Param->getLocation(), diag::ext_lambda_default_arguments) + << Param->getDefaultArgRange(); break; + } } // C++ [dcl.fct.default]p4: diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index 8b8a083a06..34ccb2d3dd 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -36,7 +36,8 @@ CXXRecordDecl *Sema::createLambdaClosureType(SourceRange IntroducerRange) { CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class, SourceRange IntroducerRange, TypeSourceInfo *MethodType, - SourceLocation EndLoc) { + SourceLocation EndLoc, + llvm::ArrayRef<ParmVarDecl *> Params) { // C++11 [expr.prim.lambda]p5: // The closure type for a lambda-expression has a public inline function // call operator (13.5.4) whose parameters and return type are described by @@ -66,6 +67,19 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class, // context, so that the Scope stack matches the lexical nesting. Method->setLexicalDeclContext(Class->getDeclContext()); + // Add parameters. + if (!Params.empty()) { + Method->setParams(Params); + CheckParmsForFunctionDef(const_cast<ParmVarDecl **>(Params.begin()), + const_cast<ParmVarDecl **>(Params.end()), + /*CheckParameterNames=*/false); + + for (CXXMethodDecl::param_iterator P = Method->param_begin(), + PEnd = Method->param_end(); + P != PEnd; ++P) + (*P)->setOwningFunction(Method); + } + return Method; } @@ -109,18 +123,11 @@ void Sema::finishLambdaExplicitCaptures(LambdaScopeInfo *LSI) { LSI->finishedExplicitCaptures(); } -void Sema::addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope, - llvm::ArrayRef<ParmVarDecl *> Params) { - CallOperator->setParams(Params); - CheckParmsForFunctionDef(const_cast<ParmVarDecl **>(Params.begin()), - const_cast<ParmVarDecl **>(Params.end()), - /*CheckParameterNames=*/false); - +void Sema::addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope) { // Introduce our parameters into the function scope for (unsigned p = 0, NumParams = CallOperator->getNumParams(); p < NumParams; ++p) { ParmVarDecl *Param = CallOperator->getParamDecl(p); - Param->setOwningFunction(CallOperator); // If this has an identifier, add it to the scope stack. if (CurScope && Param->getIdentifier()) { @@ -141,6 +148,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, bool ExplicitParams = true; bool ExplicitResultType = true; SourceLocation EndLoc; + llvm::ArrayRef<ParmVarDecl *> Params; if (ParamInfo.getNumTypeObjects() == 0) { // C++11 [expr.prim.lambda]p4: // If a lambda-expression does not include a lambda-declarator, it is as @@ -166,11 +174,6 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, if (!FTI.hasMutableQualifier()) FTI.TypeQuals |= DeclSpec::TQ_const; - // C++11 [expr.prim.lambda]p5: - // [...] Default arguments (8.3.6) shall not be specified in the - // parameter-declaration-clause of a lambda-declarator. - CheckExtraCXXDefaultArguments(ParamInfo); - MethodTyInfo = GetTypeForDeclarator(ParamInfo, CurScope); assert(MethodTyInfo && "no type from lambda-declarator"); EndLoc = ParamInfo.getSourceRange().getEnd(); @@ -178,10 +181,18 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, ExplicitResultType = MethodTyInfo->getType()->getAs<FunctionType>()->getResultType() != Context.DependentTy; + + TypeLoc TL = MethodTyInfo->getTypeLoc(); + FunctionProtoTypeLoc Proto = cast<FunctionProtoTypeLoc>(TL); + Params = llvm::ArrayRef<ParmVarDecl *>(Proto.getParmArray(), + Proto.getNumArgs()); } CXXMethodDecl *Method = startLambdaDefinition(Class, Intro.Range, - MethodTyInfo, EndLoc); + MethodTyInfo, EndLoc, Params); + + if (ExplicitParams) + CheckCXXDefaultArguments(Method); // Attributes on the lambda apply to the method. ProcessDeclAttributes(CurScope, Method, ParamInfo); @@ -325,12 +336,8 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, } finishLambdaExplicitCaptures(LSI); - // Set the parameters on the decl, if specified. - if (isa<FunctionProtoTypeLoc>(MethodTyInfo->getTypeLoc())) { - FunctionProtoTypeLoc Proto - = cast<FunctionProtoTypeLoc>(MethodTyInfo->getTypeLoc()); - addLambdaParameters(Method, CurScope, Proto.getParams()); - } + // Add lambda parameters into scope. + addLambdaParameters(Method, CurScope); // Enter a new evaluation context to insulate the lambda from any // cleanups from the enclosing full-expression. diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 4c69dd51f7..3293f7468d 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -7667,11 +7667,22 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { if (!MethodTy) return ExprError(); + // Transform lambda parameters. + bool Invalid = false; + llvm::SmallVector<QualType, 4> ParamTypes; + llvm::SmallVector<ParmVarDecl *, 4> Params; + if (getDerived().TransformFunctionTypeParams(E->getLocStart(), + E->getCallOperator()->param_begin(), + E->getCallOperator()->param_size(), + 0, ParamTypes, &Params)) + Invalid = true; + // Build the call operator. CXXMethodDecl *CallOperator = getSema().startLambdaDefinition(Class, E->getIntroducerRange(), MethodTy, - E->getCallOperator()->getLocEnd()); + E->getCallOperator()->getLocEnd(), + Params); getDerived().transformAttrs(E->getCallOperator(), CallOperator); // FIXME: Instantiation-specific. @@ -7690,7 +7701,6 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { E->isMutable()); // Transform captures. - bool Invalid = false; bool FinishedExplicitCaptures = false; for (LambdaExpr::capture_iterator C = E->capture_begin(), CEnd = E->capture_end(); @@ -7766,17 +7776,6 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { if (!FinishedExplicitCaptures) getSema().finishLambdaExplicitCaptures(LSI); - // Transform lambda parameters. - llvm::SmallVector<QualType, 4> ParamTypes; - llvm::SmallVector<ParmVarDecl *, 4> Params; - if (!getDerived().TransformFunctionTypeParams(E->getLocStart(), - E->getCallOperator()->param_begin(), - E->getCallOperator()->param_size(), - 0, ParamTypes, &Params)) - getSema().addLambdaParameters(CallOperator, /*CurScope=*/0, Params); - else - Invalid = true; - // Enter a new evaluation context to insulate the lambda from any // cleanups from the enclosing full-expression. |