xref: /aosp_15_r20/external/clang/lib/Index/IndexBody.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
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