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
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 84063e5..624dc5d 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -585,11 +585,25 @@
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 8b8a083..34ccb2d 100644
--- a/lib/Sema/SemaLambda.cpp
+++ b/lib/Sema/SemaLambda.cpp
@@ -36,7 +36,8 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
}
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 4c69dd5..3293f74 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -7667,11 +7667,22 @@
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 @@
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 @@
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.