/// \brief The source range that covers the lambda introducer ([...]).
SourceRange IntroducerRange;
+ /// \brief The source location of this lambda's capture-default ('=' or '&').
+ SourceLocation CaptureDefaultLoc;
+
/// \brief The number of captures.
unsigned NumCaptures : 16;
/// \brief Construct a lambda expression.
LambdaExpr(QualType T, SourceRange IntroducerRange,
LambdaCaptureDefault CaptureDefault,
+ SourceLocation CaptureDefaultLoc,
ArrayRef<Capture> Captures,
bool ExplicitParams,
bool ExplicitResultType,
public:
/// \brief Construct a new lambda expression.
- static LambdaExpr *Create(ASTContext &C,
+ static LambdaExpr *Create(ASTContext &C,
CXXRecordDecl *Class,
SourceRange IntroducerRange,
LambdaCaptureDefault CaptureDefault,
+ SourceLocation CaptureDefaultLoc,
ArrayRef<Capture> Captures,
bool ExplicitParams,
bool ExplicitResultType,
/// an external source.
static LambdaExpr *CreateDeserialized(ASTContext &C, unsigned NumCaptures,
unsigned NumArrayIndexVars);
-
+
/// \brief Determine the default capture kind for this lambda.
LambdaCaptureDefault getCaptureDefault() const {
return static_cast<LambdaCaptureDefault>(CaptureDefault);
}
+ /// \brief Retrieve the location of this lambda's capture-default, if any.
+ SourceLocation getCaptureDefaultLoc() const {
+ return CaptureDefaultLoc;
+ }
+
/// \brief An iterator that walks over the captures of the lambda,
/// both implicit and explicit.
typedef const Capture *capture_iterator;
/// \brief The class that describes the lambda.
CXXRecordDecl *Lambda;
- /// \brief The class that describes the lambda.
+ /// \brief The lambda's compiler-generated \c operator().
CXXMethodDecl *CallOperator;
/// \brief Source range covering the lambda introducer [...].
SourceRange IntroducerRange;
- /// \brief The number of captures in the \c Captures list that are
+ /// \brief Source location of the '&' or '=' specifying the default capture
+ /// type, if any.
+ SourceLocation CaptureDefaultLoc;
+
+ /// \brief The number of captures in the \c Captures list that are
/// explicit captures.
unsigned NumExplicitCaptures;
/// \brief Whether this is a mutable lambda.
bool Mutable;
-
+
/// \brief Whether the (empty) parameter list is explicit.
bool ExplicitParams;
/// \brief Offsets into the ArrayIndexVars array at which each capture starts
/// its list of array index variables.
SmallVector<unsigned, 4> ArrayIndexStarts;
-
+
LambdaScopeInfo(DiagnosticsEngine &Diag, CXXRecordDecl *Lambda,
CXXMethodDecl *CallOperator)
: CapturingScopeInfo(Diag, ImpCap_None), Lambda(Lambda),
virtual ~LambdaScopeInfo();
- /// \brief Note when
+ /// \brief Note when all explicit captures have been added.
void finishedExplicitCaptures() {
NumExplicitCaptures = Captures.size();
}
static bool classof(const FunctionScopeInfo *FSI) {
- return FSI->Kind == SK_Lambda;
+ return FSI->Kind == SK_Lambda;
}
};
sema::LambdaScopeInfo *enterLambdaScope(CXXMethodDecl *CallOperator,
SourceRange IntroducerRange,
LambdaCaptureDefault CaptureDefault,
+ SourceLocation CaptureDefaultLoc,
bool ExplicitParams,
bool ExplicitResultType,
bool Mutable);
return (DeclAndBits.getInt() & Capture_ByCopy) ? LCK_ByCopy : LCK_ByRef;
}
-LambdaExpr::LambdaExpr(QualType T,
+LambdaExpr::LambdaExpr(QualType T,
SourceRange IntroducerRange,
LambdaCaptureDefault CaptureDefault,
- ArrayRef<Capture> Captures,
+ SourceLocation CaptureDefaultLoc,
+ ArrayRef<Capture> Captures,
bool ExplicitParams,
bool ExplicitResultType,
ArrayRef<Expr *> CaptureInits,
T->isDependentType(), T->isDependentType(), T->isDependentType(),
ContainsUnexpandedParameterPack),
IntroducerRange(IntroducerRange),
+ CaptureDefaultLoc(CaptureDefaultLoc),
NumCaptures(Captures.size()),
CaptureDefault(CaptureDefault),
ExplicitParams(ExplicitParams),
}
}
-LambdaExpr *LambdaExpr::Create(ASTContext &Context,
+LambdaExpr *LambdaExpr::Create(ASTContext &Context,
CXXRecordDecl *Class,
SourceRange IntroducerRange,
LambdaCaptureDefault CaptureDefault,
- ArrayRef<Capture> Captures,
+ SourceLocation CaptureDefaultLoc,
+ ArrayRef<Capture> Captures,
bool ExplicitParams,
bool ExplicitResultType,
ArrayRef<Expr *> CaptureInits,
Size += sizeof(VarDecl *) * ArrayIndexVars.size();
}
void *Mem = Context.Allocate(Size);
- return new (Mem) LambdaExpr(T, IntroducerRange, CaptureDefault,
- Captures, ExplicitParams, ExplicitResultType,
+ return new (Mem) LambdaExpr(T, IntroducerRange,
+ CaptureDefault, CaptureDefaultLoc, Captures,
+ ExplicitParams, ExplicitResultType,
CaptureInits, ArrayIndexVars, ArrayIndexStarts,
ClosingBrace, ContainsUnexpandedParameterPack);
}
LambdaScopeInfo *Sema::enterLambdaScope(CXXMethodDecl *CallOperator,
SourceRange IntroducerRange,
LambdaCaptureDefault CaptureDefault,
+ SourceLocation CaptureDefaultLoc,
bool ExplicitParams,
bool ExplicitResultType,
bool Mutable) {
LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByval;
else if (CaptureDefault == LCD_ByRef)
LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByref;
+ LSI->CaptureDefaultLoc = CaptureDefaultLoc;
LSI->IntroducerRange = IntroducerRange;
LSI->ExplicitParams = ExplicitParams;
LSI->Mutable = Mutable;
// Introduce the lambda scope.
LambdaScopeInfo *LSI
- = enterLambdaScope(Method, Intro.Range, Intro.Default, ExplicitParams,
+ = enterLambdaScope(Method,
+ Intro.Range,
+ Intro.Default, Intro.DefaultLoc,
+ ExplicitParams,
ExplicitResultType,
!Method->isConst());
SmallVector<LambdaExpr::Capture, 4> Captures;
SmallVector<Expr *, 4> CaptureInits;
LambdaCaptureDefault CaptureDefault;
+ SourceLocation CaptureDefaultLoc;
CXXRecordDecl *Class;
CXXMethodDecl *CallOperator;
SourceRange IntroducerRange;
llvm_unreachable("block capture in lambda");
break;
}
+ CaptureDefaultLoc = LSI->CaptureDefaultLoc;
// C++11 [expr.prim.lambda]p4:
// If a lambda-expression does not include a
ExprNeedsCleanups = true;
LambdaExpr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange,
- CaptureDefault, Captures,
+ CaptureDefault, CaptureDefaultLoc,
+ Captures,
ExplicitParams, ExplicitResultType,
CaptureInits, ArrayIndexVars,
ArrayIndexStarts, Body->getLocEnd(),
sema::LambdaScopeInfo *LSI
= getSema().enterLambdaScope(CallOperator, E->getIntroducerRange(),
E->getCaptureDefault(),
+ E->getCaptureDefaultLoc(),
E->hasExplicitParameters(),
E->hasExplicitResultType(),
E->isMutable());
unsigned NumArrayIndexVars = Record[Idx++];
E->IntroducerRange = ReadSourceRange(Record, Idx);
E->CaptureDefault = static_cast<LambdaCaptureDefault>(Record[Idx++]);
+ E->CaptureDefaultLoc = ReadSourceLocation(Record, Idx);
E->ExplicitParams = Record[Idx++];
E->ExplicitResultType = Record[Idx++];
E->ClosingBrace = ReadSourceLocation(Record, Idx);
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file implements serialization for Statements and Expressions.
-//
+///
+/// \file
+/// \brief Implements serialization for Statements and Expressions.
+///
//===----------------------------------------------------------------------===//
#include "clang/Serialization/ASTWriter.h"
Record.push_back(NumArrayIndexVars);
Writer.AddSourceRange(E->IntroducerRange, Record);
Record.push_back(E->CaptureDefault); // FIXME: stable encoding
+ Writer.AddSourceLocation(E->CaptureDefaultLoc, Record);
Record.push_back(E->ExplicitParams);
Record.push_back(E->ExplicitResultType);
Writer.AddSourceLocation(E->ClosingBrace, Record);
return PendingBodies.empty();
}
private:
- std::stack<LambdaExpr *> PendingBodies;
+ std::stack<LambdaExpr *> PendingBodies;
+};
+
+// Matches the (optional) capture-default of a lambda-introducer.
+class LambdaDefaultCaptureVisitor
+ : public ExpectedLocationVisitor<LambdaDefaultCaptureVisitor> {
+public:
+ bool VisitLambdaExpr(LambdaExpr *Lambda) {
+ if (Lambda->getCaptureDefault() != LCD_None) {
+ Match("", Lambda->getCaptureDefaultLoc());
+ }
+ return true;
+ }
};
class TemplateArgumentLocTraverser
EXPECT_TRUE(Visitor.allBodiesHaveBeenTraversed());
}
+TEST(RecursiveASTVisitor, HasCaptureDefaultLoc) {
+ LambdaDefaultCaptureVisitor Visitor;
+ Visitor.ExpectMatch("", 1, 20);
+ EXPECT_TRUE(Visitor.runOver("void f() { int a; [=]{a;}; }",
+ LambdaDefaultCaptureVisitor::Lang_CXX11));
+}
+
} // end namespace clang