First pass of semantic analysis for init-captures: check the initializer, build
a FieldDecl from it, and propagate both into the closure type and the
LambdaExpr.
You can't do much useful with them yet -- you can't use them within the body
of the lambda, because we don't have a representation for "the this of the
lambda, not the this of the enclosing context". We also don't have support or a
representation for a nested capture of an init-capture yet, which was intended
to work despite not being allowed by the current standard wording.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@181985 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 0646499..df8a526 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -940,12 +940,10 @@
RecordDecl::field_iterator Field = field_begin();
for (LambdaExpr::Capture *C = Lambda.Captures, *CEnd = C + Lambda.NumCaptures;
C != CEnd; ++C, ++Field) {
- if (C->capturesThis()) {
+ if (C->capturesThis())
ThisCapture = *Field;
- continue;
- }
-
- Captures[C->getCapturedVar()] = *Field;
+ else if (C->capturesVariable())
+ Captures[C->getCapturedVar()] = *Field;
}
}
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index 402d7b5..59e780a 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -811,7 +811,7 @@
LambdaExpr::Capture::Capture(SourceLocation Loc, bool Implicit,
LambdaCaptureKind Kind, VarDecl *Var,
SourceLocation EllipsisLoc)
- : VarAndBits(Var, 0), Loc(Loc), EllipsisLoc(EllipsisLoc)
+ : DeclAndBits(Var, 0), Loc(Loc), EllipsisLoc(EllipsisLoc)
{
unsigned Bits = 0;
if (Implicit)
@@ -828,15 +828,27 @@
case LCK_ByRef:
assert(Var && "capture must have a variable!");
break;
+
+ case LCK_Init:
+ llvm_unreachable("don't use this constructor for an init-capture");
}
- VarAndBits.setInt(Bits);
+ DeclAndBits.setInt(Bits);
}
+LambdaExpr::Capture::Capture(FieldDecl *Field)
+ : DeclAndBits(Field,
+ Field->getType()->isReferenceType() ? 0 : Capture_ByCopy),
+ Loc(Field->getLocation()), EllipsisLoc() {}
+
LambdaCaptureKind LambdaExpr::Capture::getCaptureKind() const {
- if (capturesThis())
+ Decl *D = DeclAndBits.getPointer();
+ if (!D)
return LCK_This;
- return (VarAndBits.getInt() & Capture_ByCopy)? LCK_ByCopy : LCK_ByRef;
+ if (isa<FieldDecl>(D))
+ return LCK_Init;
+
+ return (DeclAndBits.getInt() & Capture_ByCopy) ? LCK_ByCopy : LCK_ByRef;
}
LambdaExpr::LambdaExpr(QualType T,
diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp
index 5b29c07..7e85880 100644
--- a/lib/AST/Stmt.cpp
+++ b/lib/AST/Stmt.cpp
@@ -1128,7 +1128,7 @@
bool CapturedStmt::capturesVariable(const VarDecl *Var) const {
for (const_capture_iterator I = capture_begin(),
E = capture_end(); I != E; ++I) {
- if (I->capturesThis())
+ if (!I->capturesVariable())
continue;
// This does not handle variable redeclarations. This should be
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 9203dc1..2edb078 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -1387,6 +1387,13 @@
OS << '=';
OS << C->getCapturedVar()->getName();
break;
+
+ case LCK_Init:
+ if (C->getInitCaptureField()->getType()->isReferenceType())
+ OS << '&';
+ OS << C->getInitCaptureField()->getName();
+ PrintExpr(Node->getInitCaptureInit(C));
+ break;
}
}
OS << ']';
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index 8ade242..4a3448c 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -822,9 +822,17 @@
CEnd = S->explicit_capture_end();
C != CEnd; ++C) {
ID.AddInteger(C->getCaptureKind());
- if (C->capturesVariable()) {
+ switch (C->getCaptureKind()) {
+ case LCK_This:
+ break;
+ case LCK_ByRef:
+ case LCK_ByCopy:
VisitDecl(C->getCapturedVar());
ID.AddBoolean(C->isPackExpansion());
+ break;
+ case LCK_Init:
+ VisitDecl(C->getInitCaptureField());
+ break;
}
}
// Note: If we actually needed to be able to match lambda
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 86e2e18..8bc9a79 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -766,9 +766,6 @@
if (Tok.is(tok::identifier)) {
Id = Tok.getIdentifierInfo();
Loc = ConsumeToken();
-
- if (Tok.is(tok::ellipsis))
- EllipsisLoc = ConsumeToken();
} else if (Tok.is(tok::kw_this)) {
// FIXME: If we want to suggest a fixit here, will need to return more
// than just DiagnosticID. Perhaps full DiagnosticBuilder that can be
@@ -798,7 +795,8 @@
ConsumeToken();
Init = ParseInitializer();
- }
+ } else if (Tok.is(tok::ellipsis))
+ EllipsisLoc = ConsumeToken();
}
Intro.addCapture(Kind, Loc, Id, EllipsisLoc, Init);
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index fa2bfd2..8c612b4 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -9932,7 +9932,7 @@
if (Cap.isThisCapture())
continue;
BlockDecl::Capture NewCap(Cap.getVariable(), Cap.isBlockCapture(),
- Cap.isNested(), Cap.getCopyExpr());
+ Cap.isNested(), Cap.getInitExpr());
Captures.push_back(NewCap);
}
BSI->TheDecl->setCaptures(Context, Captures.begin(), Captures.end(),
@@ -11144,17 +11144,18 @@
cast<CapturingScopeInfo>(FunctionScopes[FunctionScopesIndex]);
// Check whether we've already captured it.
- if (CSI->CaptureMap.count(Var)) {
+ if (CSI->isCaptured(Var)) {
+ const CapturingScopeInfo::Capture &Cap = CSI->getCapture(Var);
+
// If we found a capture, any subcaptures are nested.
Nested = true;
// Retrieve the capture type for this variable.
- CaptureType = CSI->getCapture(Var).getCaptureType();
+ CaptureType = Cap.getCaptureType();
// Compute the type of an expression that refers to this variable.
DeclRefType = CaptureType.getNonReferenceType();
- const CapturingScopeInfo::Capture &Cap = CSI->getCapture(Var);
if (Cap.isCopyCapture() &&
!(isa<LambdaScopeInfo>(CSI) && cast<LambdaScopeInfo>(CSI)->Mutable))
DeclRefType.addConst();
diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp
index 4e11bb4..d647be3 100644
--- a/lib/Sema/SemaLambda.cpp
+++ b/lib/Sema/SemaLambda.cpp
@@ -18,6 +18,7 @@
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
+#include "TypeLocBuilder.h"
using namespace clang;
using namespace sema;
@@ -429,6 +430,88 @@
}
}
+FieldDecl *Sema::checkInitCapture(SourceLocation Loc, bool ByRef,
+ IdentifierInfo *Id, Expr *InitExpr) {
+ LambdaScopeInfo *LSI = getCurLambda();
+
+ // C++1y [expr.prim.lambda]p11:
+ // The type of [the] member corresponds to the type of a hypothetical
+ // variable declaration of the form "auto init-capture;"
+ QualType DeductType = Context.getAutoDeductType();
+ TypeLocBuilder TLB;
+ TLB.pushTypeSpec(DeductType).setNameLoc(Loc);
+ if (ByRef) {
+ DeductType = BuildReferenceType(DeductType, true, Loc, Id);
+ assert(!DeductType.isNull() && "can't build reference to auto");
+ TLB.push<ReferenceTypeLoc>(DeductType).setSigilLoc(Loc);
+ }
+
+ InitializationKind InitKind = InitializationKind::CreateDefault(Loc);
+ Expr *Init = InitExpr;
+ if (ParenListExpr *Parens = dyn_cast<ParenListExpr>(Init)) {
+ if (Parens->getNumExprs() == 1) {
+ Init = Parens->getExpr(0);
+ InitKind = InitializationKind::CreateDirect(
+ Loc, Parens->getLParenLoc(), Parens->getRParenLoc());
+ } else {
+ // C++1y [dcl.spec.auto]p3:
+ // In an initializer of the form ( expression-list ), the
+ // expression-list shall be a single assignment-expression.
+ if (Parens->getNumExprs() == 0)
+ Diag(Parens->getLocStart(), diag::err_init_capture_no_expression)
+ << Id;
+ else if (Parens->getNumExprs() > 1)
+ Diag(Parens->getExpr(1)->getLocStart(),
+ diag::err_init_capture_multiple_expressions)
+ << Id;
+ return 0;
+ }
+ } else if (isa<InitListExpr>(Init))
+ // We do not need to distinguish between direct-list-initialization
+ // and copy-list-initialization here, because we will always deduce
+ // std::initializer_list<T>, and direct- and copy-list-initialization
+ // always behave the same for such a type.
+ // FIXME: We should model whether an '=' was present.
+ InitKind = InitializationKind::CreateDirectList(Loc);
+ else
+ InitKind = InitializationKind::CreateCopy(Loc, Loc);
+ QualType DeducedType;
+ if (DeduceAutoType(TLB.getTemporaryTypeLoc(DeductType),
+ Init, DeducedType) == DAR_Failed) {
+ if (isa<InitListExpr>(Init))
+ Diag(Loc, diag::err_init_capture_deduction_failure_from_init_list)
+ << Id << Init->getSourceRange();
+ else
+ Diag(Loc, diag::err_init_capture_deduction_failure)
+ << Id << Init->getType() << Init->getSourceRange();
+ }
+ if (DeducedType.isNull())
+ return 0;
+
+ // [...] a non-static data member named by the identifier is declared in
+ // the closure type. This member is not a bit-field and not mutable.
+ // Core issue: the member is (probably...) public.
+ FieldDecl *NewFD = CheckFieldDecl(
+ Id, DeducedType, TLB.getTypeSourceInfo(Context, DeductType), LSI->Lambda,
+ Loc, /*Mutable*/ false, /*BitWidth*/ 0, ICIS_NoInit,
+ Loc, AS_public, /*PrevDecl*/ 0, /*Declarator*/ 0);
+ LSI->Lambda->addDecl(NewFD);
+
+ if (CurContext->isDependentContext()) {
+ LSI->addInitCapture(NewFD, InitExpr);
+ } else {
+ InitializedEntity Entity = InitializedEntity::InitializeMember(NewFD);
+ InitializationSequence InitSeq(*this, Entity, InitKind, Init);
+ if (!InitSeq.Diagnose(*this, Entity, InitKind, Init)) {
+ ExprResult InitResult = InitSeq.Perform(*this, Entity, InitKind, Init);
+ if (!InitResult.isInvalid())
+ LSI->addInitCapture(NewFD, InitResult.take());
+ }
+ }
+
+ return NewFD;
+}
+
void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
Declarator &ParamInfo,
Scope *CurScope) {
@@ -514,7 +597,10 @@
= enterLambdaScope(Method, Intro.Range, Intro.Default, ExplicitParams,
ExplicitResultType,
!Method->isConst());
-
+
+ // Distinct capture names, for diagnostics.
+ llvm::SmallSet<IdentifierInfo*, 8> CaptureNames;
+
// Handle explicit captures.
SourceLocation PrevCaptureLoc
= Intro.Default == LCD_None? Intro.Range.getBegin() : Intro.DefaultLoc;
@@ -559,16 +645,32 @@
continue;
}
- // FIXME: C++1y [expr.prim.lambda]p11
+ assert(C->Id && "missing identifier for capture");
+
if (C->Init.isInvalid())
continue;
if (C->Init.isUsable()) {
- Diag(C->Loc, diag::err_lambda_init_capture_unsupported);
+ // C++11 [expr.prim.lambda]p8:
+ // An identifier or this shall not appear more than once in a
+ // lambda-capture.
+ if (!CaptureNames.insert(C->Id))
+ Diag(C->Loc, diag::err_capture_more_than_once) << C->Id;
+
+ if (C->Init.get()->containsUnexpandedParameterPack())
+ ContainsUnexpandedParameterPack = true;
+
+ FieldDecl *NewFD = checkInitCapture(C->Loc, C->Kind == LCK_ByRef,
+ C->Id, C->Init.take());
+ // C++1y [expr.prim.lambda]p11:
+ // Within the lambda-expression's lambda-declarator and
+ // compound-statement, the identifier in the init-capture
+ // hides any declaration of the same name in scopes enclosing
+ // the lambda-expression.
+ if (NewFD)
+ PushOnScopeChains(NewFD, CurScope, false);
continue;
}
- assert(C->Id && "missing identifier for capture");
-
// C++11 [expr.prim.lambda]p8:
// If a lambda-capture includes a capture-default that is &, the
// identifiers in the lambda-capture shall not be preceded by &.
@@ -586,6 +688,9 @@
continue;
}
+ // C++11 [expr.prim.lambda]p10:
+ // The identifiers in a capture-list are looked up using the usual
+ // rules for unqualified name lookup (3.4.1)
DeclarationNameInfo Name(C->Id, C->Loc);
LookupResult R(*this, Name, LookupOrdinaryName);
LookupName(R, CurScope);
@@ -599,14 +704,27 @@
continue;
}
- // C++11 [expr.prim.lambda]p10:
- // The identifiers in a capture-list are looked up using the usual rules
- // for unqualified name lookup (3.4.1); each such lookup shall find a
- // variable with automatic storage duration declared in the reaching
- // scope of the local lambda expression.
- //
- // Note that the 'reaching scope' check happens in tryCaptureVariable().
VarDecl *Var = R.getAsSingle<VarDecl>();
+
+ // C++11 [expr.prim.lambda]p8:
+ // An identifier or this shall not appear more than once in a
+ // lambda-capture.
+ if (!CaptureNames.insert(C->Id)) {
+ if (Var && LSI->isCaptured(Var)) {
+ Diag(C->Loc, diag::err_capture_more_than_once)
+ << C->Id << SourceRange(LSI->getCapture(Var).getLocation())
+ << FixItHint::CreateRemoval(
+ SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
+ } else
+ // Previous capture was an init-capture: no fixit.
+ Diag(C->Loc, diag::err_capture_more_than_once) << C->Id;
+ continue;
+ }
+
+ // C++11 [expr.prim.lambda]p10:
+ // [...] each such lookup shall find a variable with automatic storage
+ // duration declared in the reaching scope of the local lambda expression.
+ // Note that the 'reaching scope' check happens in tryCaptureVariable().
if (!Var) {
Diag(C->Loc, diag::err_capture_does_not_name_variable) << C->Id;
continue;
@@ -622,18 +740,6 @@
continue;
}
- // C++11 [expr.prim.lambda]p8:
- // An identifier or this shall not appear more than once in a
- // lambda-capture.
- if (LSI->isCaptured(Var)) {
- Diag(C->Loc, diag::err_capture_more_than_once)
- << C->Id
- << SourceRange(LSI->getCapture(Var).getLocation())
- << FixItHint::CreateRemoval(
- SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
- continue;
- }
-
// C++11 [expr.prim.lambda]p23:
// A capture followed by an ellipsis is a pack expansion (14.5.3).
SourceLocation EllipsisLoc;
@@ -853,11 +959,17 @@
continue;
}
+ if (From.isInitCapture()) {
+ Captures.push_back(LambdaExpr::Capture(From.getInitCaptureField()));
+ CaptureInits.push_back(From.getInitExpr());
+ continue;
+ }
+
VarDecl *Var = From.getVariable();
LambdaCaptureKind Kind = From.isCopyCapture()? LCK_ByCopy : LCK_ByRef;
Captures.push_back(LambdaExpr::Capture(From.getLocation(), IsImplicit,
Kind, Var, From.getEllipsisLoc()));
- CaptureInits.push_back(From.getCopyExpr());
+ CaptureInits.push_back(From.getInitExpr());
}
switch (LSI->ImpCaptureStyle) {
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index 6d568c4..3cd1a11 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -3063,7 +3063,7 @@
if (Cap->isThisCapture()) {
Captures.push_back(CapturedStmt::Capture(Cap->getLocation(),
CapturedStmt::VCK_This));
- CaptureInits.push_back(Cap->getCopyExpr());
+ CaptureInits.push_back(Cap->getInitExpr());
continue;
}
@@ -3073,7 +3073,7 @@
Captures.push_back(CapturedStmt::Capture(Cap->getLocation(),
CapturedStmt::VCK_ByRef,
Cap->getVariable()));
- CaptureInits.push_back(Cap->getCopyExpr());
+ CaptureInits.push_back(Cap->getInitExpr());
}
}
diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp
index db885ae..3b82280 100644
--- a/lib/Sema/SemaTemplateVariadic.cpp
+++ b/lib/Sema/SemaTemplateVariadic.cpp
@@ -179,10 +179,14 @@
// 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())
+ E = Lambda->capture_end();
+ I != E; ++I) {
+ if (I->capturesVariable()) {
+ VarDecl *VD = I->getCapturedVar();
if (VD->isParameterPack())
Unexpanded.push_back(std::make_pair(VD, I->getLocation()));
+ }
+ }
inherited::TraverseLambdaExpr(Lambda);
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 253135f..95ea9bc 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -8074,6 +8074,22 @@
ExprResult
TreeTransform<Derived>::TransformLambdaScope(LambdaExpr *E,
CXXMethodDecl *CallOperator) {
+ bool Invalid = false;
+
+ // Transform any init-capture expressions before entering the scope of the
+ // lambda.
+ llvm::SmallVector<ExprResult, 8> InitCaptureExprs;
+ InitCaptureExprs.resize(E->explicit_capture_end() -
+ E->explicit_capture_begin());
+ for (LambdaExpr::capture_iterator C = E->capture_begin(),
+ CEnd = E->capture_end();
+ C != CEnd; ++C) {
+ if (!C->isInitCapture())
+ continue;
+ InitCaptureExprs[C - E->capture_begin()] =
+ getDerived().TransformExpr(E->getInitCaptureInit(C));
+ }
+
// Introduce the context of the call operator.
Sema::ContextRAII SavedContext(getSema(), CallOperator);
@@ -8086,7 +8102,6 @@
E->isMutable());
// Transform captures.
- bool Invalid = false;
bool FinishedExplicitCaptures = false;
for (LambdaExpr::capture_iterator C = E->capture_begin(),
CEnd = E->capture_end();
@@ -8104,6 +8119,26 @@
continue;
}
+ // Rebuild init-captures, including the implied field declaration.
+ if (C->isInitCapture()) {
+ ExprResult Init = InitCaptureExprs[C - E->capture_begin()];
+ if (Init.isInvalid()) {
+ Invalid = true;
+ continue;
+ }
+ FieldDecl *OldFD = C->getInitCaptureField();
+ FieldDecl *NewFD = getSema().checkInitCapture(
+ C->getLocation(), OldFD->getType()->isReferenceType(),
+ OldFD->getIdentifier(), Init.take());
+ if (!NewFD)
+ Invalid = true;
+ else
+ getDerived().transformedLocalDecl(OldFD, NewFD);
+ continue;
+ }
+
+ assert(C->capturesVariable() && "unexpected kind of lambda capture");
+
// Determine the capture kind for Sema.
Sema::TryCaptureKind Kind
= C->isImplicit()? Sema::TryCapture_Implicit
@@ -8120,8 +8155,10 @@
C->getLocation(),
Unexpanded,
ShouldExpand, RetainExpansion,
- NumExpansions))
- return ExprError();
+ NumExpansions)) {
+ Invalid = true;
+ continue;
+ }
if (ShouldExpand) {
// The transform has determined that we should perform an expansion;
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index b117b73..11c82da 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -1160,9 +1160,22 @@
SourceLocation Loc = ReadSourceLocation(Record, Idx);
bool IsImplicit = Record[Idx++];
LambdaCaptureKind Kind = static_cast<LambdaCaptureKind>(Record[Idx++]);
- VarDecl *Var = ReadDeclAs<VarDecl>(Record, Idx);
- SourceLocation EllipsisLoc = ReadSourceLocation(Record, Idx);
- *ToCapture++ = Capture(Loc, IsImplicit, Kind, Var, EllipsisLoc);
+ switch (Kind) {
+ case LCK_This:
+ *ToCapture++ = Capture(Loc, IsImplicit, Kind, 0, SourceLocation());
+ break;
+ case LCK_ByCopy:
+ case LCK_ByRef: {
+ VarDecl *Var = ReadDeclAs<VarDecl>(Record, Idx);
+ SourceLocation EllipsisLoc = ReadSourceLocation(Record, Idx);
+ *ToCapture++ = Capture(Loc, IsImplicit, Kind, Var, EllipsisLoc);
+ break;
+ }
+ case LCK_Init:
+ FieldDecl *Field = ReadDeclAs<FieldDecl>(Record, Idx);
+ *ToCapture++ = Capture(Field);
+ break;
+ }
}
}
}
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index dd5818f..ba6243a 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -5047,12 +5047,25 @@
LambdaExpr::Capture &Capture = Lambda.Captures[I];
AddSourceLocation(Capture.getLocation(), Record);
Record.push_back(Capture.isImplicit());
- Record.push_back(Capture.getCaptureKind()); // FIXME: stable!
- VarDecl *Var = Capture.capturesVariable()? Capture.getCapturedVar() : 0;
- AddDeclRef(Var, Record);
- AddSourceLocation(Capture.isPackExpansion()? Capture.getEllipsisLoc()
- : SourceLocation(),
- Record);
+ Record.push_back(Capture.getCaptureKind());
+ switch (Capture.getCaptureKind()) {
+ case LCK_This:
+ break;
+ case LCK_ByCopy:
+ case LCK_ByRef: {
+ VarDecl *Var =
+ Capture.capturesVariable() ? Capture.getCapturedVar() : 0;
+ AddDeclRef(Var, Record);
+ AddSourceLocation(Capture.isPackExpansion() ? Capture.getEllipsisLoc()
+ : SourceLocation(),
+ Record);
+ break;
+ }
+ case LCK_Init:
+ FieldDecl *Field = Capture.getInitCaptureField();
+ AddDeclRef(Field, Record);
+ break;
+ }
}
}
}