1*67e74705SXin Li //===- IndexBody.cpp - Indexing statements --------------------------------===//
2*67e74705SXin Li //
3*67e74705SXin Li // The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li
10*67e74705SXin Li #include "IndexingContext.h"
11*67e74705SXin Li #include "clang/AST/RecursiveASTVisitor.h"
12*67e74705SXin Li
13*67e74705SXin Li using namespace clang;
14*67e74705SXin Li using namespace clang::index;
15*67e74705SXin Li
16*67e74705SXin Li namespace {
17*67e74705SXin Li
18*67e74705SXin Li class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
19*67e74705SXin Li IndexingContext &IndexCtx;
20*67e74705SXin Li const NamedDecl *Parent;
21*67e74705SXin Li const DeclContext *ParentDC;
22*67e74705SXin Li SmallVector<Stmt*, 16> StmtStack;
23*67e74705SXin Li
24*67e74705SXin Li typedef RecursiveASTVisitor<BodyIndexer> base;
25*67e74705SXin Li public:
BodyIndexer(IndexingContext & indexCtx,const NamedDecl * Parent,const DeclContext * DC)26*67e74705SXin Li BodyIndexer(IndexingContext &indexCtx,
27*67e74705SXin Li const NamedDecl *Parent, const DeclContext *DC)
28*67e74705SXin Li : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { }
29*67e74705SXin Li
shouldWalkTypesOfTypeLocs() const30*67e74705SXin Li bool shouldWalkTypesOfTypeLocs() const { return false; }
31*67e74705SXin Li
dataTraverseStmtPre(Stmt * S)32*67e74705SXin Li bool dataTraverseStmtPre(Stmt *S) {
33*67e74705SXin Li StmtStack.push_back(S);
34*67e74705SXin Li return true;
35*67e74705SXin Li }
36*67e74705SXin Li
dataTraverseStmtPost(Stmt * S)37*67e74705SXin Li bool dataTraverseStmtPost(Stmt *S) {
38*67e74705SXin Li assert(StmtStack.back() == S);
39*67e74705SXin Li StmtStack.pop_back();
40*67e74705SXin Li return true;
41*67e74705SXin Li }
42*67e74705SXin Li
TraverseTypeLoc(TypeLoc TL)43*67e74705SXin Li bool TraverseTypeLoc(TypeLoc TL) {
44*67e74705SXin Li IndexCtx.indexTypeLoc(TL, Parent, ParentDC);
45*67e74705SXin Li return true;
46*67e74705SXin Li }
47*67e74705SXin Li
TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS)48*67e74705SXin Li bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
49*67e74705SXin Li IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
50*67e74705SXin Li return true;
51*67e74705SXin Li }
52*67e74705SXin Li
getRolesForRef(const Expr * E,SmallVectorImpl<SymbolRelation> & Relations)53*67e74705SXin Li SymbolRoleSet getRolesForRef(const Expr *E,
54*67e74705SXin Li SmallVectorImpl<SymbolRelation> &Relations) {
55*67e74705SXin Li SymbolRoleSet Roles{};
56*67e74705SXin Li assert(!StmtStack.empty() && E == StmtStack.back());
57*67e74705SXin Li if (StmtStack.size() == 1)
58*67e74705SXin Li return Roles;
59*67e74705SXin Li auto It = StmtStack.end()-2;
60*67e74705SXin Li while (isa<CastExpr>(*It) || isa<ParenExpr>(*It)) {
61*67e74705SXin Li if (auto ICE = dyn_cast<ImplicitCastExpr>(*It)) {
62*67e74705SXin Li if (ICE->getCastKind() == CK_LValueToRValue)
63*67e74705SXin Li Roles |= (unsigned)(unsigned)SymbolRole::Read;
64*67e74705SXin Li }
65*67e74705SXin Li if (It == StmtStack.begin())
66*67e74705SXin Li break;
67*67e74705SXin Li --It;
68*67e74705SXin Li }
69*67e74705SXin Li const Stmt *Parent = *It;
70*67e74705SXin Li
71*67e74705SXin Li if (auto BO = dyn_cast<BinaryOperator>(Parent)) {
72*67e74705SXin Li if (BO->getOpcode() == BO_Assign && BO->getLHS()->IgnoreParenCasts() == E)
73*67e74705SXin Li Roles |= (unsigned)SymbolRole::Write;
74*67e74705SXin Li
75*67e74705SXin Li } else if (auto UO = dyn_cast<UnaryOperator>(Parent)) {
76*67e74705SXin Li if (UO->isIncrementDecrementOp()) {
77*67e74705SXin Li Roles |= (unsigned)SymbolRole::Read;
78*67e74705SXin Li Roles |= (unsigned)SymbolRole::Write;
79*67e74705SXin Li } else if (UO->getOpcode() == UO_AddrOf) {
80*67e74705SXin Li Roles |= (unsigned)SymbolRole::AddressOf;
81*67e74705SXin Li }
82*67e74705SXin Li
83*67e74705SXin Li } else if (auto CA = dyn_cast<CompoundAssignOperator>(Parent)) {
84*67e74705SXin Li if (CA->getLHS()->IgnoreParenCasts() == E) {
85*67e74705SXin Li Roles |= (unsigned)SymbolRole::Read;
86*67e74705SXin Li Roles |= (unsigned)SymbolRole::Write;
87*67e74705SXin Li }
88*67e74705SXin Li
89*67e74705SXin Li } else if (auto CE = dyn_cast<CallExpr>(Parent)) {
90*67e74705SXin Li if (CE->getCallee()->IgnoreParenCasts() == E) {
91*67e74705SXin Li addCallRole(Roles, Relations);
92*67e74705SXin Li if (auto *ME = dyn_cast<MemberExpr>(E)) {
93*67e74705SXin Li if (auto *CXXMD = dyn_cast_or_null<CXXMethodDecl>(ME->getMemberDecl()))
94*67e74705SXin Li if (CXXMD->isVirtual() && !ME->hasQualifier()) {
95*67e74705SXin Li Roles |= (unsigned)SymbolRole::Dynamic;
96*67e74705SXin Li auto BaseTy = ME->getBase()->IgnoreImpCasts()->getType();
97*67e74705SXin Li if (!BaseTy.isNull())
98*67e74705SXin Li if (auto *CXXRD = BaseTy->getPointeeCXXRecordDecl())
99*67e74705SXin Li Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy,
100*67e74705SXin Li CXXRD);
101*67e74705SXin Li }
102*67e74705SXin Li }
103*67e74705SXin Li } else if (auto CXXOp = dyn_cast<CXXOperatorCallExpr>(CE)) {
104*67e74705SXin Li if (CXXOp->getNumArgs() > 0 && CXXOp->getArg(0)->IgnoreParenCasts() == E) {
105*67e74705SXin Li OverloadedOperatorKind Op = CXXOp->getOperator();
106*67e74705SXin Li if (Op == OO_Equal) {
107*67e74705SXin Li Roles |= (unsigned)SymbolRole::Write;
108*67e74705SXin Li } else if ((Op >= OO_PlusEqual && Op <= OO_PipeEqual) ||
109*67e74705SXin Li Op == OO_LessLessEqual || Op == OO_GreaterGreaterEqual ||
110*67e74705SXin Li Op == OO_PlusPlus || Op == OO_MinusMinus) {
111*67e74705SXin Li Roles |= (unsigned)SymbolRole::Read;
112*67e74705SXin Li Roles |= (unsigned)SymbolRole::Write;
113*67e74705SXin Li } else if (Op == OO_Amp) {
114*67e74705SXin Li Roles |= (unsigned)SymbolRole::AddressOf;
115*67e74705SXin Li }
116*67e74705SXin Li }
117*67e74705SXin Li }
118*67e74705SXin Li }
119*67e74705SXin Li
120*67e74705SXin Li return Roles;
121*67e74705SXin Li }
122*67e74705SXin Li
addCallRole(SymbolRoleSet & Roles,SmallVectorImpl<SymbolRelation> & Relations)123*67e74705SXin Li void addCallRole(SymbolRoleSet &Roles,
124*67e74705SXin Li SmallVectorImpl<SymbolRelation> &Relations) {
125*67e74705SXin Li Roles |= (unsigned)SymbolRole::Call;
126*67e74705SXin Li if (auto *FD = dyn_cast<FunctionDecl>(ParentDC))
127*67e74705SXin Li Relations.emplace_back((unsigned)SymbolRole::RelationCalledBy, FD);
128*67e74705SXin Li else if (auto *MD = dyn_cast<ObjCMethodDecl>(ParentDC))
129*67e74705SXin Li Relations.emplace_back((unsigned)SymbolRole::RelationCalledBy, MD);
130*67e74705SXin Li }
131*67e74705SXin Li
VisitDeclRefExpr(DeclRefExpr * E)132*67e74705SXin Li bool VisitDeclRefExpr(DeclRefExpr *E) {
133*67e74705SXin Li SmallVector<SymbolRelation, 4> Relations;
134*67e74705SXin Li SymbolRoleSet Roles = getRolesForRef(E, Relations);
135*67e74705SXin Li return IndexCtx.handleReference(E->getDecl(), E->getLocation(),
136*67e74705SXin Li Parent, ParentDC, Roles, Relations, E);
137*67e74705SXin Li }
138*67e74705SXin Li
VisitMemberExpr(MemberExpr * E)139*67e74705SXin Li bool VisitMemberExpr(MemberExpr *E) {
140*67e74705SXin Li SourceLocation Loc = E->getMemberLoc();
141*67e74705SXin Li if (Loc.isInvalid())
142*67e74705SXin Li Loc = E->getLocStart();
143*67e74705SXin Li SmallVector<SymbolRelation, 4> Relations;
144*67e74705SXin Li SymbolRoleSet Roles = getRolesForRef(E, Relations);
145*67e74705SXin Li return IndexCtx.handleReference(E->getMemberDecl(), Loc,
146*67e74705SXin Li Parent, ParentDC, Roles, Relations, E);
147*67e74705SXin Li }
148*67e74705SXin Li
VisitDesignatedInitExpr(DesignatedInitExpr * E)149*67e74705SXin Li bool VisitDesignatedInitExpr(DesignatedInitExpr *E) {
150*67e74705SXin Li for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) {
151*67e74705SXin Li if (D.isFieldDesignator())
152*67e74705SXin Li return IndexCtx.handleReference(D.getField(), D.getFieldLoc(), Parent,
153*67e74705SXin Li ParentDC, SymbolRoleSet(), {}, E);
154*67e74705SXin Li }
155*67e74705SXin Li return true;
156*67e74705SXin Li }
157*67e74705SXin Li
VisitObjCIvarRefExpr(ObjCIvarRefExpr * E)158*67e74705SXin Li bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
159*67e74705SXin Li SmallVector<SymbolRelation, 4> Relations;
160*67e74705SXin Li SymbolRoleSet Roles = getRolesForRef(E, Relations);
161*67e74705SXin Li return IndexCtx.handleReference(E->getDecl(), E->getLocation(),
162*67e74705SXin Li Parent, ParentDC, Roles, Relations, E);
163*67e74705SXin Li }
164*67e74705SXin Li
VisitObjCMessageExpr(ObjCMessageExpr * E)165*67e74705SXin Li bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
166*67e74705SXin Li auto isDynamic = [](const ObjCMessageExpr *MsgE)->bool {
167*67e74705SXin Li if (MsgE->getReceiverKind() != ObjCMessageExpr::Instance)
168*67e74705SXin Li return false;
169*67e74705SXin Li if (auto *RecE = dyn_cast<ObjCMessageExpr>(
170*67e74705SXin Li MsgE->getInstanceReceiver()->IgnoreParenCasts())) {
171*67e74705SXin Li if (RecE->getMethodFamily() == OMF_alloc)
172*67e74705SXin Li return false;
173*67e74705SXin Li }
174*67e74705SXin Li return true;
175*67e74705SXin Li };
176*67e74705SXin Li
177*67e74705SXin Li if (ObjCMethodDecl *MD = E->getMethodDecl()) {
178*67e74705SXin Li SymbolRoleSet Roles{};
179*67e74705SXin Li SmallVector<SymbolRelation, 2> Relations;
180*67e74705SXin Li addCallRole(Roles, Relations);
181*67e74705SXin Li if (E->isImplicit())
182*67e74705SXin Li Roles |= (unsigned)SymbolRole::Implicit;
183*67e74705SXin Li
184*67e74705SXin Li if (isDynamic(E)) {
185*67e74705SXin Li Roles |= (unsigned)SymbolRole::Dynamic;
186*67e74705SXin Li if (auto *RecD = E->getReceiverInterface())
187*67e74705SXin Li Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy, RecD);
188*67e74705SXin Li }
189*67e74705SXin Li
190*67e74705SXin Li return IndexCtx.handleReference(MD, E->getSelectorStartLoc(),
191*67e74705SXin Li Parent, ParentDC, Roles, Relations, E);
192*67e74705SXin Li }
193*67e74705SXin Li return true;
194*67e74705SXin Li }
195*67e74705SXin Li
VisitObjCPropertyRefExpr(ObjCPropertyRefExpr * E)196*67e74705SXin Li bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
197*67e74705SXin Li if (E->isExplicitProperty())
198*67e74705SXin Li return IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(),
199*67e74705SXin Li Parent, ParentDC, SymbolRoleSet(), {}, E);
200*67e74705SXin Li
201*67e74705SXin Li // No need to do a handleReference for the objc method, because there will
202*67e74705SXin Li // be a message expr as part of PseudoObjectExpr.
203*67e74705SXin Li return true;
204*67e74705SXin Li }
205*67e74705SXin Li
VisitMSPropertyRefExpr(MSPropertyRefExpr * E)206*67e74705SXin Li bool VisitMSPropertyRefExpr(MSPropertyRefExpr *E) {
207*67e74705SXin Li return IndexCtx.handleReference(E->getPropertyDecl(), E->getMemberLoc(),
208*67e74705SXin Li Parent, ParentDC, SymbolRoleSet(), {}, E);
209*67e74705SXin Li }
210*67e74705SXin Li
VisitObjCProtocolExpr(ObjCProtocolExpr * E)211*67e74705SXin Li bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
212*67e74705SXin Li return IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(),
213*67e74705SXin Li Parent, ParentDC, SymbolRoleSet(), {}, E);
214*67e74705SXin Li }
215*67e74705SXin Li
passObjCLiteralMethodCall(const ObjCMethodDecl * MD,const Expr * E)216*67e74705SXin Li bool passObjCLiteralMethodCall(const ObjCMethodDecl *MD, const Expr *E) {
217*67e74705SXin Li SymbolRoleSet Roles{};
218*67e74705SXin Li SmallVector<SymbolRelation, 2> Relations;
219*67e74705SXin Li addCallRole(Roles, Relations);
220*67e74705SXin Li Roles |= (unsigned)SymbolRole::Implicit;
221*67e74705SXin Li return IndexCtx.handleReference(MD, E->getLocStart(),
222*67e74705SXin Li Parent, ParentDC, Roles, Relations, E);
223*67e74705SXin Li }
224*67e74705SXin Li
VisitObjCBoxedExpr(ObjCBoxedExpr * E)225*67e74705SXin Li bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) {
226*67e74705SXin Li if (ObjCMethodDecl *MD = E->getBoxingMethod()) {
227*67e74705SXin Li return passObjCLiteralMethodCall(MD, E);
228*67e74705SXin Li }
229*67e74705SXin Li return true;
230*67e74705SXin Li }
231*67e74705SXin Li
VisitObjCDictionaryLiteral(ObjCDictionaryLiteral * E)232*67e74705SXin Li bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
233*67e74705SXin Li if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod()) {
234*67e74705SXin Li return passObjCLiteralMethodCall(MD, E);
235*67e74705SXin Li }
236*67e74705SXin Li return true;
237*67e74705SXin Li }
238*67e74705SXin Li
VisitObjCArrayLiteral(ObjCArrayLiteral * E)239*67e74705SXin Li bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
240*67e74705SXin Li if (ObjCMethodDecl *MD = E->getArrayWithObjectsMethod()) {
241*67e74705SXin Li return passObjCLiteralMethodCall(MD, E);
242*67e74705SXin Li }
243*67e74705SXin Li return true;
244*67e74705SXin Li }
245*67e74705SXin Li
VisitCXXConstructExpr(CXXConstructExpr * E)246*67e74705SXin Li bool VisitCXXConstructExpr(CXXConstructExpr *E) {
247*67e74705SXin Li SymbolRoleSet Roles{};
248*67e74705SXin Li SmallVector<SymbolRelation, 2> Relations;
249*67e74705SXin Li addCallRole(Roles, Relations);
250*67e74705SXin Li return IndexCtx.handleReference(E->getConstructor(), E->getLocation(),
251*67e74705SXin Li Parent, ParentDC, Roles, Relations, E);
252*67e74705SXin Li }
253*67e74705SXin Li
TraverseCXXOperatorCallExpr(CXXOperatorCallExpr * E,DataRecursionQueue * Q=nullptr)254*67e74705SXin Li bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E,
255*67e74705SXin Li DataRecursionQueue *Q = nullptr) {
256*67e74705SXin Li if (E->getOperatorLoc().isInvalid())
257*67e74705SXin Li return true; // implicit.
258*67e74705SXin Li return base::TraverseCXXOperatorCallExpr(E, Q);
259*67e74705SXin Li }
260*67e74705SXin Li
VisitDeclStmt(DeclStmt * S)261*67e74705SXin Li bool VisitDeclStmt(DeclStmt *S) {
262*67e74705SXin Li if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
263*67e74705SXin Li IndexCtx.indexDeclGroupRef(S->getDeclGroup());
264*67e74705SXin Li return true;
265*67e74705SXin Li }
266*67e74705SXin Li
267*67e74705SXin Li DeclGroupRef DG = S->getDeclGroup();
268*67e74705SXin Li for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) {
269*67e74705SXin Li const Decl *D = *I;
270*67e74705SXin Li if (!D)
271*67e74705SXin Li continue;
272*67e74705SXin Li if (!IndexCtx.isFunctionLocalDecl(D))
273*67e74705SXin Li IndexCtx.indexTopLevelDecl(D);
274*67e74705SXin Li }
275*67e74705SXin Li
276*67e74705SXin Li return true;
277*67e74705SXin Li }
278*67e74705SXin Li
TraverseLambdaCapture(LambdaExpr * LE,const LambdaCapture * C)279*67e74705SXin Li bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C) {
280*67e74705SXin Li if (C->capturesThis() || C->capturesVLAType())
281*67e74705SXin Li return true;
282*67e74705SXin Li
283*67e74705SXin Li if (C->capturesVariable() && IndexCtx.shouldIndexFunctionLocalSymbols())
284*67e74705SXin Li return IndexCtx.handleReference(C->getCapturedVar(), C->getLocation(),
285*67e74705SXin Li Parent, ParentDC, SymbolRoleSet());
286*67e74705SXin Li
287*67e74705SXin Li // FIXME: Lambda init-captures.
288*67e74705SXin Li return true;
289*67e74705SXin Li }
290*67e74705SXin Li
291*67e74705SXin Li // RecursiveASTVisitor visits both syntactic and semantic forms, duplicating
292*67e74705SXin Li // the things that we visit. Make sure to only visit the semantic form.
293*67e74705SXin Li // Also visit things that are in the syntactic form but not the semantic one,
294*67e74705SXin Li // for example the indices in DesignatedInitExprs.
TraverseInitListExpr(InitListExpr * S,DataRecursionQueue * Q=nullptr)295*67e74705SXin Li bool TraverseInitListExpr(InitListExpr *S, DataRecursionQueue *Q = nullptr) {
296*67e74705SXin Li
297*67e74705SXin Li class SyntacticFormIndexer :
298*67e74705SXin Li public RecursiveASTVisitor<SyntacticFormIndexer> {
299*67e74705SXin Li IndexingContext &IndexCtx;
300*67e74705SXin Li const NamedDecl *Parent;
301*67e74705SXin Li const DeclContext *ParentDC;
302*67e74705SXin Li
303*67e74705SXin Li public:
304*67e74705SXin Li SyntacticFormIndexer(IndexingContext &indexCtx,
305*67e74705SXin Li const NamedDecl *Parent, const DeclContext *DC)
306*67e74705SXin Li : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { }
307*67e74705SXin Li
308*67e74705SXin Li bool shouldWalkTypesOfTypeLocs() const { return false; }
309*67e74705SXin Li
310*67e74705SXin Li bool VisitDesignatedInitExpr(DesignatedInitExpr *E) {
311*67e74705SXin Li for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) {
312*67e74705SXin Li if (D.isFieldDesignator())
313*67e74705SXin Li return IndexCtx.handleReference(D.getField(), D.getFieldLoc(),
314*67e74705SXin Li Parent, ParentDC, SymbolRoleSet(),
315*67e74705SXin Li {}, E);
316*67e74705SXin Li }
317*67e74705SXin Li return true;
318*67e74705SXin Li }
319*67e74705SXin Li };
320*67e74705SXin Li
321*67e74705SXin Li auto visitForm = [&](InitListExpr *Form) {
322*67e74705SXin Li for (Stmt *SubStmt : Form->children()) {
323*67e74705SXin Li if (!TraverseStmt(SubStmt, Q))
324*67e74705SXin Li return false;
325*67e74705SXin Li }
326*67e74705SXin Li return true;
327*67e74705SXin Li };
328*67e74705SXin Li
329*67e74705SXin Li InitListExpr *SemaForm = S->isSemanticForm() ? S : S->getSemanticForm();
330*67e74705SXin Li InitListExpr *SyntaxForm = S->isSemanticForm() ? S->getSyntacticForm() : S;
331*67e74705SXin Li
332*67e74705SXin Li if (SemaForm) {
333*67e74705SXin Li // Visit things present in syntactic form but not the semantic form.
334*67e74705SXin Li if (SyntaxForm) {
335*67e74705SXin Li SyntacticFormIndexer(IndexCtx, Parent, ParentDC).TraverseStmt(SyntaxForm);
336*67e74705SXin Li }
337*67e74705SXin Li return visitForm(SemaForm);
338*67e74705SXin Li }
339*67e74705SXin Li
340*67e74705SXin Li // No semantic, try the syntactic.
341*67e74705SXin Li if (SyntaxForm) {
342*67e74705SXin Li return visitForm(SyntaxForm);
343*67e74705SXin Li }
344*67e74705SXin Li
345*67e74705SXin Li return true;
346*67e74705SXin Li }
347*67e74705SXin Li };
348*67e74705SXin Li
349*67e74705SXin Li } // anonymous namespace
350*67e74705SXin Li
indexBody(const Stmt * S,const NamedDecl * Parent,const DeclContext * DC)351*67e74705SXin Li void IndexingContext::indexBody(const Stmt *S, const NamedDecl *Parent,
352*67e74705SXin Li const DeclContext *DC) {
353*67e74705SXin Li if (!S)
354*67e74705SXin Li return;
355*67e74705SXin Li
356*67e74705SXin Li if (!DC)
357*67e74705SXin Li DC = Parent->getLexicalDeclContext();
358*67e74705SXin Li BodyIndexer(*this, Parent, DC).TraverseStmt(const_cast<Stmt*>(S));
359*67e74705SXin Li }
360