[cfe-commits] r160705 - in /cfe/trunk: include/clang/AST/ExprCXX.h include/clang/Sema/ScopeInfo.h include/clang/Sema/Sema.h include/clang/Sema/Template.h lib/AST/ExprCXX.cpp lib/Sema/SemaLambda.cpp lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/SemaTemplateVariadic.cpp lib/Sema/TreeTransform.h test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp test/SemaCXX/lambda-expressions.cpp
Richard Smith
richard-llvm at metafoo.co.uk
Tue Jul 24 20:56:55 PDT 2012
Author: rsmith
Date: Tue Jul 24 22:56:55 2012
New Revision: 160705
URL: http://llvm.org/viewvc/llvm-project?rev=160705&view=rev
Log:
PR12057: Allow variadic template pack expansions to cross lambda boundaries.
Rather than adding a ContainsUnexpandedParameterPack bit to essentially every
AST node, we tunnel the bit directly up to the surrounding lambda expression
when we reach a context where an unexpanded pack can not normally appear.
Thus any statement or declaration within a lambda can now potentially contain
an unexpanded parameter pack.
Modified:
cfe/trunk/include/clang/AST/ExprCXX.h
cfe/trunk/include/clang/Sema/ScopeInfo.h
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/include/clang/Sema/Template.h
cfe/trunk/lib/AST/ExprCXX.cpp
cfe/trunk/lib/Sema/SemaLambda.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
cfe/trunk/lib/Sema/TreeTransform.h
cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm
cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp
cfe/trunk/test/SemaCXX/lambda-expressions.cpp
Modified: cfe/trunk/include/clang/AST/ExprCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=160705&r1=160704&r2=160705&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Tue Jul 24 22:56:55 2012
@@ -1254,7 +1254,8 @@
ArrayRef<Expr *> CaptureInits,
ArrayRef<VarDecl *> ArrayIndexVars,
ArrayRef<unsigned> ArrayIndexStarts,
- SourceLocation ClosingBrace);
+ SourceLocation ClosingBrace,
+ bool ContainsUnexpandedParameterPack);
/// \brief Construct an empty lambda expression.
LambdaExpr(EmptyShell Empty, unsigned NumCaptures, bool HasArrayIndexVars)
@@ -1292,7 +1293,8 @@
ArrayRef<Expr *> CaptureInits,
ArrayRef<VarDecl *> ArrayIndexVars,
ArrayRef<unsigned> ArrayIndexStarts,
- SourceLocation ClosingBrace);
+ SourceLocation ClosingBrace,
+ bool ContainsUnexpandedParameterPack);
/// \brief Construct a new lambda expression that will be deserialized from
/// an external source.
Modified: cfe/trunk/include/clang/Sema/ScopeInfo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/ScopeInfo.h?rev=160705&r1=160704&r2=160705&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/ScopeInfo.h (original)
+++ cfe/trunk/include/clang/Sema/ScopeInfo.h Tue Jul 24 22:56:55 2012
@@ -344,6 +344,9 @@
/// \brief Whether any of the capture expressions requires cleanups.
bool ExprNeedsCleanups;
+ /// \brief Whether the lambda contains an unexpanded parameter pack.
+ bool ContainsUnexpandedParameterPack;
+
/// \brief Variables used to index into by-copy array captures.
llvm::SmallVector<VarDecl *, 4> ArrayIndexVars;
@@ -355,7 +358,7 @@
CXXMethodDecl *CallOperator)
: CapturingScopeInfo(Diag, ImpCap_None), Lambda(Lambda),
CallOperator(CallOperator), NumExplicitCaptures(0), Mutable(false),
- ExprNeedsCleanups(false)
+ ExprNeedsCleanups(false), ContainsUnexpandedParameterPack(false)
{
Kind = SK_Lambda;
}
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=160705&r1=160704&r2=160705&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Tue Jul 24 22:56:55 2012
@@ -5003,7 +5003,9 @@
/// parameter packs.
///
/// \param Unexpanded the set of unexpanded parameter packs.
- void DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
+ ///
+ /// \returns true if an error occurred, false otherwise.
+ bool DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
UnexpandedParameterPackContext UPPC,
ArrayRef<UnexpandedParameterPack> Unexpanded);
Modified: cfe/trunk/include/clang/Sema/Template.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Template.h?rev=160705&r1=160704&r2=160705&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Template.h (original)
+++ cfe/trunk/include/clang/Sema/Template.h Tue Jul 24 22:56:55 2012
@@ -372,8 +372,10 @@
public:
TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner,
const MultiLevelTemplateArgumentList &TemplateArgs)
- : SemaRef(SemaRef), SubstIndex(SemaRef, -1), Owner(Owner),
- TemplateArgs(TemplateArgs), LateAttrs(0), StartingScope(0) { }
+ : SemaRef(SemaRef),
+ SubstIndex(SemaRef, SemaRef.ArgumentPackSubstitutionIndex),
+ Owner(Owner), TemplateArgs(TemplateArgs), LateAttrs(0), StartingScope(0)
+ { }
// FIXME: Once we get closer to completion, replace these manually-written
// declarations with automatically-generated ones from
Modified: cfe/trunk/lib/AST/ExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=160705&r1=160704&r2=160705&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)
+++ cfe/trunk/lib/AST/ExprCXX.cpp Tue Jul 24 22:56:55 2012
@@ -790,10 +790,11 @@
ArrayRef<Expr *> CaptureInits,
ArrayRef<VarDecl *> ArrayIndexVars,
ArrayRef<unsigned> ArrayIndexStarts,
- SourceLocation ClosingBrace)
+ SourceLocation ClosingBrace,
+ bool ContainsUnexpandedParameterPack)
: Expr(LambdaExprClass, T, VK_RValue, OK_Ordinary,
T->isDependentType(), T->isDependentType(), T->isDependentType(),
- /*ContainsUnexpandedParameterPack=*/false),
+ ContainsUnexpandedParameterPack),
IntroducerRange(IntroducerRange),
NumCaptures(Captures.size()),
CaptureDefault(CaptureDefault),
@@ -850,7 +851,8 @@
ArrayRef<Expr *> CaptureInits,
ArrayRef<VarDecl *> ArrayIndexVars,
ArrayRef<unsigned> ArrayIndexStarts,
- SourceLocation ClosingBrace) {
+ SourceLocation ClosingBrace,
+ bool ContainsUnexpandedParameterPack) {
// Determine the type of the expression (i.e., the type of the
// function object we're creating).
QualType T = Context.getTypeDeclType(Class);
@@ -863,7 +865,7 @@
return new (Mem) LambdaExpr(T, IntroducerRange, CaptureDefault,
Captures, ExplicitParams, ExplicitResultType,
CaptureInits, ArrayIndexVars, ArrayIndexStarts,
- ClosingBrace);
+ ClosingBrace, ContainsUnexpandedParameterPack);
}
LambdaExpr *LambdaExpr::CreateDeserialized(ASTContext &C, unsigned NumCaptures,
Modified: cfe/trunk/lib/Sema/SemaLambda.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=160705&r1=160704&r2=160705&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLambda.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLambda.cpp Tue Jul 24 22:56:55 2012
@@ -375,6 +375,7 @@
TypeSourceInfo *MethodTyInfo;
bool ExplicitParams = true;
bool ExplicitResultType = true;
+ bool ContainsUnexpandedParameterPack = false;
SourceLocation EndLoc;
llvm::ArrayRef<ParmVarDecl *> Params;
if (ParamInfo.getNumTypeObjects() == 0) {
@@ -416,21 +417,8 @@
Proto.getNumArgs());
// Check for unexpanded parameter packs in the method type.
- // FIXME: We should allow unexpanded parameter packs here, but that would,
- // in turn, make the lambda expression contain unexpanded parameter packs.
- if (DiagnoseUnexpandedParameterPack(Intro.Range.getBegin(), MethodTyInfo,
- UPPC_Lambda)) {
- // Drop the parameters.
- Params = llvm::ArrayRef<ParmVarDecl *>();
- FunctionProtoType::ExtProtoInfo EPI;
- EPI.HasTrailingReturn = false;
- EPI.TypeQuals |= DeclSpec::TQ_const;
- QualType MethodTy = Context.getFunctionType(Context.DependentTy,
- /*Args=*/0, /*NumArgs=*/0, EPI);
- MethodTyInfo = Context.getTrivialTypeSourceInfo(MethodTy);
- ExplicitParams = false;
- ExplicitResultType = false;
- }
+ if (MethodTyInfo->getType()->containsUnexpandedParameterPack())
+ ContainsUnexpandedParameterPack = true;
}
CXXMethodDecl *Method = startLambdaDefinition(Class, Intro.Range,
@@ -571,8 +559,7 @@
// Just ignore the ellipsis.
}
} else if (Var->isParameterPack()) {
- Diag(C->Loc, diag::err_lambda_unexpanded_pack);
- continue;
+ ContainsUnexpandedParameterPack = true;
}
TryCaptureKind Kind = C->Kind == LCK_ByRef ? TryCapture_ExplicitByRef :
@@ -581,6 +568,8 @@
}
finishLambdaExplicitCaptures(LSI);
+ LSI->ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack;
+
// Add lambda parameters into scope.
addLambdaParameters(Method, CurScope);
@@ -743,6 +732,7 @@
bool ExplicitParams;
bool ExplicitResultType;
bool LambdaExprNeedsCleanups;
+ bool ContainsUnexpandedParameterPack;
llvm::SmallVector<VarDecl *, 4> ArrayIndexVars;
llvm::SmallVector<unsigned, 4> ArrayIndexStarts;
{
@@ -753,6 +743,7 @@
ExplicitParams = LSI->ExplicitParams;
ExplicitResultType = !LSI->HasImplicitReturnType;
LambdaExprNeedsCleanups = LSI->ExprNeedsCleanups;
+ ContainsUnexpandedParameterPack = LSI->ContainsUnexpandedParameterPack;
ArrayIndexVars.swap(LSI->ArrayIndexVars);
ArrayIndexStarts.swap(LSI->ArrayIndexStarts);
@@ -867,7 +858,8 @@
CaptureDefault, Captures,
ExplicitParams, ExplicitResultType,
CaptureInits, ArrayIndexVars,
- ArrayIndexStarts, Body->getLocEnd());
+ ArrayIndexStarts, Body->getLocEnd(),
+ ContainsUnexpandedParameterPack);
// C++11 [expr.prim.lambda]p2:
// A lambda-expression shall not appear in an unevaluated operand
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=160705&r1=160704&r2=160705&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Tue Jul 24 22:56:55 2012
@@ -838,6 +838,19 @@
return move(Result);
}
+ ExprResult TransformLambdaExpr(LambdaExpr *E) {
+ LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);
+ return TreeTransform<TemplateInstantiator>::TransformLambdaExpr(E);
+ }
+
+ ExprResult TransformLambdaScope(LambdaExpr *E,
+ CXXMethodDecl *CallOperator) {
+ CallOperator->setInstantiationOfMemberFunction(E->getCallOperator(),
+ TSK_ImplicitInstantiation);
+ return TreeTransform<TemplateInstantiator>::
+ TransformLambdaScope(E, CallOperator);
+ }
+
private:
ExprResult transformNonTypeTemplateParmRef(NonTypeTemplateParmDecl *parm,
SourceLocation loc,
Modified: cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp?rev=160705&r1=160704&r2=160705&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp Tue Jul 24 22:56:55 2012
@@ -12,6 +12,7 @@
#include "clang/Sema/Sema.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/ParsedTemplate.h"
+#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
#include "clang/AST/Expr.h"
@@ -34,10 +35,12 @@
SmallVectorImpl<UnexpandedParameterPack> &Unexpanded;
+ bool InLambda;
+
public:
explicit CollectUnexpandedParameterPacksVisitor(
SmallVectorImpl<UnexpandedParameterPack> &Unexpanded)
- : Unexpanded(Unexpanded) { }
+ : Unexpanded(Unexpanded), InLambda(false) { }
bool shouldWalkTypesOfTypeLocs() const { return false; }
@@ -107,17 +110,17 @@
/// \brief Suppress traversal into statements and expressions that
/// do not contain unexpanded parameter packs.
bool TraverseStmt(Stmt *S) {
- if (Expr *E = dyn_cast_or_null<Expr>(S))
- if (E->containsUnexpandedParameterPack())
- return inherited::TraverseStmt(E);
+ Expr *E = dyn_cast_or_null<Expr>(S);
+ if ((E && E->containsUnexpandedParameterPack()) || InLambda)
+ return inherited::TraverseStmt(S);
- return true;
+ return true;
}
/// \brief Suppress traversal into types that do not contain
/// unexpanded parameter packs.
bool TraverseType(QualType T) {
- if (!T.isNull() && T->containsUnexpandedParameterPack())
+ if ((!T.isNull() && T->containsUnexpandedParameterPack()) || InLambda)
return inherited::TraverseType(T);
return true;
@@ -126,8 +129,9 @@
/// \brief Suppress traversel into types with location information
/// that do not contain unexpanded parameter packs.
bool TraverseTypeLoc(TypeLoc TL) {
- if (!TL.getType().isNull() &&
- TL.getType()->containsUnexpandedParameterPack())
+ if ((!TL.getType().isNull() &&
+ TL.getType()->containsUnexpandedParameterPack()) ||
+ InLambda)
return inherited::TraverseTypeLoc(TL);
return true;
@@ -136,10 +140,10 @@
/// \brief Suppress traversal of non-parameter declarations, since
/// they cannot contain unexpanded parameter packs.
bool TraverseDecl(Decl *D) {
- if (D && isa<ParmVarDecl>(D))
+ if ((D && isa<ParmVarDecl>(D)) || InLambda)
return inherited::TraverseDecl(D);
- return true;
+ return true;
}
/// \brief Suppress traversal of template argument pack expansions.
@@ -157,17 +161,57 @@
return inherited::TraverseTemplateArgumentLoc(ArgLoc);
}
+
+ /// \brief Note whether we're traversing a lambda containing an unexpanded
+ /// parameter pack. In this case, the unexpanded pack can occur anywhere,
+ /// including all the places where we normally wouldn't look. Within a
+ /// lambda, we don't propagate the 'contains unexpanded parameter pack' bit
+ /// outside an expression.
+ bool TraverseLambdaExpr(LambdaExpr *Lambda) {
+ // The ContainsUnexpandedParameterPack bit on a lambda is always correct,
+ // even if it's contained within another lambda.
+ if (!Lambda->containsUnexpandedParameterPack())
+ return true;
+
+ bool WasInLambda = InLambda;
+ InLambda = true;
+
+ // If any capture names a function parameter pack, that pack is expanded
+ // when the lambda is expanded.
+ for (LambdaExpr::capture_iterator I = Lambda->capture_begin(),
+ E = Lambda->capture_end(); I != E; ++I)
+ if (VarDecl *VD = I->getCapturedVar())
+ if (VD->isParameterPack())
+ Unexpanded.push_back(std::make_pair(VD, I->getLocation()));
+
+ inherited::TraverseLambdaExpr(Lambda);
+
+ InLambda = WasInLambda;
+ return true;
+ }
};
}
/// \brief Diagnose all of the unexpanded parameter packs in the given
/// vector.
-void
+bool
Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
UnexpandedParameterPackContext UPPC,
ArrayRef<UnexpandedParameterPack> Unexpanded) {
if (Unexpanded.empty())
- return;
+ return false;
+
+ // If we are within a lambda expression, that lambda contains an unexpanded
+ // parameter pack, and we are done.
+ // FIXME: Store 'Unexpanded' on the lambda so we don't need to recompute it
+ // later.
+ for (unsigned N = FunctionScopes.size(); N; --N) {
+ if (sema::LambdaScopeInfo *LSI =
+ dyn_cast<sema::LambdaScopeInfo>(FunctionScopes[N-1])) {
+ LSI->ContainsUnexpandedParameterPack = true;
+ return false;
+ }
+ }
SmallVector<SourceLocation, 4> Locations;
SmallVector<IdentifierInfo *, 4> Names;
@@ -200,6 +244,7 @@
for (unsigned I = 0, N = Locations.size(); I != N; ++I)
DB << SourceRange(Locations[I]);
+ return true;
}
bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc,
@@ -215,8 +260,7 @@
CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseTypeLoc(
T->getTypeLoc());
assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
- DiagnoseUnexpandedParameterPacks(Loc, UPPC, Unexpanded);
- return true;
+ return DiagnoseUnexpandedParameterPacks(Loc, UPPC, Unexpanded);
}
bool Sema::DiagnoseUnexpandedParameterPack(Expr *E,
@@ -230,8 +274,7 @@
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseStmt(E);
assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
- DiagnoseUnexpandedParameterPacks(E->getLocStart(), UPPC, Unexpanded);
- return true;
+ return DiagnoseUnexpandedParameterPacks(E->getLocStart(), UPPC, Unexpanded);
}
bool Sema::DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS,
@@ -247,9 +290,8 @@
CollectUnexpandedParameterPacksVisitor(Unexpanded)
.TraverseNestedNameSpecifier(SS.getScopeRep());
assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
- DiagnoseUnexpandedParameterPacks(SS.getRange().getBegin(),
- UPPC, Unexpanded);
- return true;
+ return DiagnoseUnexpandedParameterPacks(SS.getRange().getBegin(),
+ UPPC, Unexpanded);
}
bool Sema::DiagnoseUnexpandedParameterPack(const DeclarationNameInfo &NameInfo,
@@ -284,8 +326,7 @@
CollectUnexpandedParameterPacksVisitor(Unexpanded)
.TraverseType(NameInfo.getName().getCXXNameType());
assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
- DiagnoseUnexpandedParameterPacks(NameInfo.getLoc(), UPPC, Unexpanded);
- return true;
+ return DiagnoseUnexpandedParameterPacks(NameInfo.getLoc(), UPPC, Unexpanded);
}
bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc,
@@ -299,8 +340,7 @@
CollectUnexpandedParameterPacksVisitor(Unexpanded)
.TraverseTemplateName(Template);
assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
- DiagnoseUnexpandedParameterPacks(Loc, UPPC, Unexpanded);
- return true;
+ return DiagnoseUnexpandedParameterPacks(Loc, UPPC, Unexpanded);
}
bool Sema::DiagnoseUnexpandedParameterPack(TemplateArgumentLoc Arg,
@@ -313,8 +353,7 @@
CollectUnexpandedParameterPacksVisitor(Unexpanded)
.TraverseTemplateArgumentLoc(Arg);
assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
- DiagnoseUnexpandedParameterPacks(Arg.getLocation(), UPPC, Unexpanded);
- return true;
+ return DiagnoseUnexpandedParameterPacks(Arg.getLocation(), UPPC, Unexpanded);
}
void Sema::collectUnexpandedParameterPacks(TemplateArgument Arg,
Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=160705&r1=160704&r2=160705&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Tue Jul 24 22:56:55 2012
@@ -571,6 +571,9 @@
StmtResult TransformCompoundStmt(CompoundStmt *S, bool IsStmtExpr);
ExprResult TransformCXXNamedCastExpr(CXXNamedCastExpr *E);
+ /// \brief Transform the captures and body of a lambda expression.
+ ExprResult TransformLambdaScope(LambdaExpr *E, CXXMethodDecl *CallOperator);
+
#define STMT(Node, Parent) \
StmtResult Transform##Node(Node *S);
#define EXPR(Node, Parent) \
@@ -7894,14 +7897,13 @@
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;
+ return ExprError();
// Build the call operator.
CXXMethodDecl *CallOperator
@@ -7910,11 +7912,14 @@
E->getCallOperator()->getLocEnd(),
Params);
getDerived().transformAttrs(E->getCallOperator(), CallOperator);
-
- // FIXME: Instantiation-specific.
- CallOperator->setInstantiationOfMemberFunction(E->getCallOperator(),
- TSK_ImplicitInstantiation);
+ return getDerived().TransformLambdaScope(E, CallOperator);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformLambdaScope(LambdaExpr *E,
+ CXXMethodDecl *CallOperator) {
// Introduce the context of the call operator.
Sema::ContextRAII SavedContext(getSema(), CallOperator);
@@ -7927,6 +7932,7 @@
E->isMutable());
// Transform captures.
+ bool Invalid = false;
bool FinishedExplicitCaptures = false;
for (LambdaExpr::capture_iterator C = E->capture_begin(),
CEnd = E->capture_end();
Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm?rev=160705&r1=160704&r2=160705&view=diff
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm (original)
+++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm Tue Jul 24 22:56:55 2012
@@ -89,6 +89,8 @@
namespace PR13117 {
struct A {
+ template<typename ... Args> static void f(Args...);
+
template<typename ... Args> static void f1()
{
(void)^(Args args) { // expected-error{{block contains unexpanded parameter pack 'Args'}}
@@ -97,9 +99,24 @@
template<typename ... Args> static void f2()
{
- (void)[](Args args) { // expected-error{{lambda contains unexpanded parameter pack 'Args'}}
+ // FIXME: Allow this.
+ f(
+ ^(Args args) // expected-error{{block contains unexpanded parameter pack 'Args'}}
+ { }
+ ... // expected-error{{pack expansion does not contain any unexpanded parameter packs}}
+ );
+ }
+
+ template<typename ... Args> static void f3()
+ {
+ (void)[](Args args) { // expected-error{{expression contains unexpanded parameter pack 'Args'}}
};
}
+
+ template<typename ... Args> static void f4()
+ {
+ f([](Args args) { } ...);
+ }
};
void g() {
Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp?rev=160705&r1=160704&r2=160705&view=diff
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp (original)
+++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp Tue Jul 24 22:56:55 2012
@@ -9,8 +9,8 @@
}
template<typename... Ts>
-void unsupported(Ts ...values) {
- auto unsup = [values] {}; // expected-error{{unexpanded function parameter pack capture is unsupported}}
+void unexpanded_capture(Ts ...values) {
+ auto unexp = [values] {}; // expected-error{{initializer contains unexpanded parameter pack 'values'}}
}
template<typename... Ts>
Modified: cfe/trunk/test/SemaCXX/lambda-expressions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/lambda-expressions.cpp?rev=160705&r1=160704&r2=160705&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/lambda-expressions.cpp (original)
+++ cfe/trunk/test/SemaCXX/lambda-expressions.cpp Tue Jul 24 22:56:55 2012
@@ -145,3 +145,79 @@
};
}
}
+
+namespace VariadicPackExpansion {
+ template<typename T, typename U> using Fst = T;
+ template<typename...Ts> bool g(Fst<bool, Ts> ...bools);
+ template<typename...Ts> bool f(Ts &&...ts) {
+ return g<Ts...>([&ts] {
+ if (!ts)
+ return false;
+ --ts;
+ return true;
+ } () ...);
+ }
+ void h() {
+ int a = 5, b = 2, c = 3;
+ while (f(a, b, c)) {
+ }
+ }
+
+ struct sink {
+ template<typename...Ts> sink(Ts &&...) {}
+ };
+
+ template<typename...Ts> void local_class() {
+ sink {
+ [] (Ts t) {
+ struct S : Ts {
+ void f(Ts t) {
+ Ts &that = *this;
+ that = t;
+ }
+ Ts g() { return *this; };
+ };
+ S s;
+ s.f(t);
+ return s;
+ } (Ts()).g() ...
+ };
+ };
+ struct X {}; struct Y {};
+ template void local_class<X, Y>();
+
+ template<typename...Ts> void nested(Ts ...ts) {
+ f(
+ // Each expansion of this lambda implicitly captures all of 'ts', because
+ // the inner lambda also expands 'ts'.
+ [&] {
+ return ts + [&] { return f(ts...); } ();
+ } () ...
+ );
+ }
+ template void nested(int, int, int);
+
+ template<typename...Ts> void nested2(Ts ...ts) { // expected-note 2{{here}}
+ // Capture all 'ts', use only one.
+ f([&ts...] { return ts; } ()...);
+ // Capture each 'ts', use it.
+ f([&ts] { return ts; } ()...);
+ // Capture all 'ts', use all of them.
+ f([&ts...] { return (int)f(ts...); } ());
+ // Capture each 'ts', use all of them. Ill-formed. In more detail:
+ //
+ // We instantiate two lambdas here; the first captures ts$0, the second
+ // captures ts$1. Both of them reference both ts parameters, so both are
+ // ill-formed because ts can't be implicitly captured.
+ //
+ // FIXME: This diagnostic does not explain what's happening. We should
+ // specify which 'ts' we're referring to in its diagnostic name. We should
+ // also say which slice of the pack expansion is being performed in the
+ // instantiation backtrace.
+ f([&ts] { return (int)f(ts...); } ()...); // \
+ // expected-error 2{{'ts' cannot be implicitly captured}} \
+ // expected-note 2{{lambda expression begins here}}
+ }
+ template void nested2(int); // ok
+ template void nested2(int, int); // expected-note {{in instantiation of}}
+}
More information about the cfe-commits
mailing list