1 | //===- IndexBody.cpp - Indexing statements --------------------------------===// |
---|---|
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "IndexingContext.h" |
10 | #include "clang/AST/ASTConcept.h" |
11 | #include "clang/AST/ASTLambda.h" |
12 | #include "clang/AST/DeclCXX.h" |
13 | #include "clang/AST/ExprConcepts.h" |
14 | #include "clang/AST/RecursiveASTVisitor.h" |
15 | #include "clang/AST/Type.h" |
16 | #include "clang/Sema/HeuristicResolver.h" |
17 | |
18 | using namespace clang; |
19 | using namespace clang::index; |
20 | |
21 | namespace { |
22 | |
23 | class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> { |
24 | IndexingContext &IndexCtx; |
25 | const NamedDecl *Parent; |
26 | const DeclContext *ParentDC; |
27 | SmallVector<Stmt*, 16> StmtStack; |
28 | |
29 | typedef RecursiveASTVisitor<BodyIndexer> base; |
30 | |
31 | Stmt *getParentStmt() const { |
32 | return StmtStack.size() < 2 ? nullptr : StmtStack.end()[-2]; |
33 | } |
34 | public: |
35 | BodyIndexer(IndexingContext &indexCtx, |
36 | const NamedDecl *Parent, const DeclContext *DC) |
37 | : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { } |
38 | |
39 | bool shouldWalkTypesOfTypeLocs() const { return false; } |
40 | |
41 | bool dataTraverseStmtPre(Stmt *S) { |
42 | StmtStack.push_back(Elt: S); |
43 | return true; |
44 | } |
45 | |
46 | bool dataTraverseStmtPost(Stmt *S) { |
47 | assert(StmtStack.back() == S); |
48 | StmtStack.pop_back(); |
49 | return true; |
50 | } |
51 | |
52 | bool TraverseTypeLoc(TypeLoc TL) { |
53 | IndexCtx.indexTypeLoc(TL, Parent, DC: ParentDC); |
54 | return true; |
55 | } |
56 | |
57 | bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { |
58 | IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, DC: ParentDC); |
59 | return true; |
60 | } |
61 | |
62 | SymbolRoleSet getRolesForRef(const Expr *E, |
63 | SmallVectorImpl<SymbolRelation> &Relations) { |
64 | SymbolRoleSet Roles{}; |
65 | assert(!StmtStack.empty() && E == StmtStack.back()); |
66 | if (StmtStack.size() == 1) |
67 | return Roles; |
68 | auto It = StmtStack.end()-2; |
69 | while (isa<CastExpr>(Val: *It) || isa<ParenExpr>(Val: *It)) { |
70 | if (auto ICE = dyn_cast<ImplicitCastExpr>(Val: *It)) { |
71 | if (ICE->getCastKind() == CK_LValueToRValue) |
72 | Roles |= (unsigned)(unsigned)SymbolRole::Read; |
73 | } |
74 | if (It == StmtStack.begin()) |
75 | break; |
76 | --It; |
77 | } |
78 | const Stmt *Parent = *It; |
79 | |
80 | if (auto BO = dyn_cast<BinaryOperator>(Val: Parent)) { |
81 | if (BO->getOpcode() == BO_Assign) { |
82 | if (BO->getLHS()->IgnoreParenCasts() == E) |
83 | Roles |= (unsigned)SymbolRole::Write; |
84 | } else if (auto CA = dyn_cast<CompoundAssignOperator>(Val: Parent)) { |
85 | if (CA->getLHS()->IgnoreParenCasts() == E) { |
86 | Roles |= (unsigned)SymbolRole::Read; |
87 | Roles |= (unsigned)SymbolRole::Write; |
88 | } |
89 | } |
90 | } else if (auto UO = dyn_cast<UnaryOperator>(Val: Parent)) { |
91 | if (UO->isIncrementDecrementOp()) { |
92 | Roles |= (unsigned)SymbolRole::Read; |
93 | Roles |= (unsigned)SymbolRole::Write; |
94 | } else if (UO->getOpcode() == UO_AddrOf) { |
95 | Roles |= (unsigned)SymbolRole::AddressOf; |
96 | } |
97 | |
98 | } else if (auto CE = dyn_cast<CallExpr>(Val: Parent)) { |
99 | if (CE->getCallee()->IgnoreParenCasts() == E) { |
100 | addCallRole(Roles, Relations); |
101 | if (auto *ME = dyn_cast<MemberExpr>(Val: E)) { |
102 | if (auto *CXXMD = dyn_cast_or_null<CXXMethodDecl>(Val: ME->getMemberDecl())) |
103 | if (CXXMD->isVirtual() && !ME->hasQualifier()) { |
104 | Roles |= (unsigned)SymbolRole::Dynamic; |
105 | auto BaseTy = ME->getBase()->IgnoreImpCasts()->getType(); |
106 | if (!BaseTy.isNull()) |
107 | if (auto *CXXRD = BaseTy->getPointeeCXXRecordDecl()) |
108 | Relations.emplace_back(Args: (unsigned)SymbolRole::RelationReceivedBy, |
109 | Args&: CXXRD); |
110 | } |
111 | } |
112 | } else if (auto CXXOp = dyn_cast<CXXOperatorCallExpr>(Val: CE)) { |
113 | if (CXXOp->getNumArgs() > 0 && CXXOp->getArg(0)->IgnoreParenCasts() == E) { |
114 | OverloadedOperatorKind Op = CXXOp->getOperator(); |
115 | if (Op == OO_Equal) { |
116 | Roles |= (unsigned)SymbolRole::Write; |
117 | } else if ((Op >= OO_PlusEqual && Op <= OO_PipeEqual) || |
118 | Op == OO_LessLessEqual || Op == OO_GreaterGreaterEqual || |
119 | Op == OO_PlusPlus || Op == OO_MinusMinus) { |
120 | Roles |= (unsigned)SymbolRole::Read; |
121 | Roles |= (unsigned)SymbolRole::Write; |
122 | } else if (Op == OO_Amp) { |
123 | Roles |= (unsigned)SymbolRole::AddressOf; |
124 | } |
125 | } |
126 | } |
127 | } |
128 | |
129 | return Roles; |
130 | } |
131 | |
132 | void addCallRole(SymbolRoleSet &Roles, |
133 | SmallVectorImpl<SymbolRelation> &Relations) { |
134 | if (isa<CXXDeductionGuideDecl>(Val: ParentDC)) |
135 | return; |
136 | |
137 | Roles |= (unsigned)SymbolRole::Call; |
138 | if (auto *FD = dyn_cast<FunctionDecl>(Val: ParentDC)) |
139 | Relations.emplace_back(Args: (unsigned)SymbolRole::RelationCalledBy, Args&: FD); |
140 | else if (auto *MD = dyn_cast<ObjCMethodDecl>(Val: ParentDC)) |
141 | Relations.emplace_back(Args: (unsigned)SymbolRole::RelationCalledBy, Args&: MD); |
142 | } |
143 | |
144 | bool VisitDeclRefExpr(DeclRefExpr *E) { |
145 | SmallVector<SymbolRelation, 4> Relations; |
146 | SymbolRoleSet Roles = getRolesForRef(E, Relations); |
147 | return IndexCtx.handleReference(E->getDecl(), E->getLocation(), |
148 | Parent, ParentDC, Roles, Relations, E); |
149 | } |
150 | |
151 | bool VisitGotoStmt(GotoStmt *S) { |
152 | return IndexCtx.handleReference(S->getLabel(), S->getLabelLoc(), Parent, |
153 | ParentDC); |
154 | } |
155 | |
156 | bool VisitCXXNewExpr(CXXNewExpr *E) { |
157 | if (E->isGlobalNew() || !E->getOperatorNew()) |
158 | return true; |
159 | return IndexCtx.handleReference(E->getOperatorNew(), E->getBeginLoc(), |
160 | Parent, ParentDC); |
161 | } |
162 | |
163 | bool VisitCXXDeleteExpr(CXXDeleteExpr *E) { |
164 | if (E->isGlobalDelete() || !E->getOperatorDelete()) |
165 | return true; |
166 | return IndexCtx.handleReference(E->getOperatorDelete(), E->getBeginLoc(), |
167 | Parent, ParentDC); |
168 | } |
169 | |
170 | bool VisitLabelStmt(LabelStmt *S) { |
171 | if (IndexCtx.shouldIndexFunctionLocalSymbols()) |
172 | return IndexCtx.handleDecl(S->getDecl()); |
173 | return true; |
174 | } |
175 | |
176 | bool VisitMemberExpr(MemberExpr *E) { |
177 | SourceLocation Loc = E->getMemberLoc(); |
178 | if (Loc.isInvalid()) |
179 | Loc = E->getBeginLoc(); |
180 | SmallVector<SymbolRelation, 4> Relations; |
181 | SymbolRoleSet Roles = getRolesForRef(E, Relations); |
182 | return IndexCtx.handleReference(E->getMemberDecl(), Loc, |
183 | Parent, ParentDC, Roles, Relations, E); |
184 | } |
185 | |
186 | bool indexDependentReference(const Expr *E, SourceLocation Loc, |
187 | std::vector<const NamedDecl *> TargetSymbols) { |
188 | // FIXME: Improve overload handling. |
189 | if (TargetSymbols.size() != 1) |
190 | return true; |
191 | if (Loc.isInvalid()) |
192 | Loc = E->getBeginLoc(); |
193 | SmallVector<SymbolRelation, 4> Relations; |
194 | SymbolRoleSet Roles = getRolesForRef(E, Relations); |
195 | return IndexCtx.handleReference(D: TargetSymbols[0], Loc, Parent, DC: ParentDC, |
196 | Roles, Relations, RefE: E); |
197 | } |
198 | |
199 | bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) { |
200 | auto *Resolver = IndexCtx.getResolver(); |
201 | assert(Resolver); |
202 | return indexDependentReference(E, E->getMemberNameInfo().getLoc(), |
203 | Resolver->resolveMemberExpr(ME: E)); |
204 | } |
205 | |
206 | bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) { |
207 | auto *Resolver = IndexCtx.getResolver(); |
208 | assert(Resolver); |
209 | return indexDependentReference(E, E->getNameInfo().getLoc(), |
210 | Resolver->resolveDeclRefExpr(RE: E)); |
211 | } |
212 | |
213 | bool VisitDesignatedInitExpr(DesignatedInitExpr *E) { |
214 | for (DesignatedInitExpr::Designator &D : llvm::reverse(C: E->designators())) { |
215 | if (D.isFieldDesignator()) { |
216 | if (const FieldDecl *FD = D.getFieldDecl()) { |
217 | return IndexCtx.handleReference(FD, D.getFieldLoc(), Parent, |
218 | ParentDC, SymbolRoleSet(), {}, E); |
219 | } |
220 | } |
221 | } |
222 | return true; |
223 | } |
224 | |
225 | bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { |
226 | SmallVector<SymbolRelation, 4> Relations; |
227 | SymbolRoleSet Roles = getRolesForRef(E, Relations); |
228 | return IndexCtx.handleReference(E->getDecl(), E->getLocation(), |
229 | Parent, ParentDC, Roles, Relations, E); |
230 | } |
231 | |
232 | bool VisitObjCMessageExpr(ObjCMessageExpr *E) { |
233 | auto isDynamic = [](const ObjCMessageExpr *MsgE)->bool { |
234 | if (MsgE->getReceiverKind() != ObjCMessageExpr::Instance) |
235 | return false; |
236 | if (auto *RecE = dyn_cast<ObjCMessageExpr>( |
237 | Val: MsgE->getInstanceReceiver()->IgnoreParenCasts())) { |
238 | if (RecE->getMethodFamily() == OMF_alloc) |
239 | return false; |
240 | } |
241 | return true; |
242 | }; |
243 | |
244 | if (ObjCMethodDecl *MD = E->getMethodDecl()) { |
245 | SymbolRoleSet Roles{}; |
246 | SmallVector<SymbolRelation, 2> Relations; |
247 | addCallRole(Roles, Relations); |
248 | Stmt *Containing = getParentStmt(); |
249 | |
250 | auto IsImplicitProperty = [](const PseudoObjectExpr *POE) -> bool { |
251 | const auto *E = POE->getSyntacticForm(); |
252 | if (const auto *BinOp = dyn_cast<BinaryOperator>(Val: E)) |
253 | E = BinOp->getLHS(); |
254 | const auto *PRE = dyn_cast<ObjCPropertyRefExpr>(Val: E); |
255 | if (!PRE) |
256 | return false; |
257 | if (PRE->isExplicitProperty()) |
258 | return false; |
259 | if (const ObjCMethodDecl *Getter = PRE->getImplicitPropertyGetter()) { |
260 | // Class properties that are explicitly defined using @property |
261 | // declarations are represented implicitly as there is no ivar for |
262 | // class properties. |
263 | if (Getter->isClassMethod() && |
264 | Getter->getCanonicalDecl()->findPropertyDecl()) |
265 | return false; |
266 | } |
267 | return true; |
268 | }; |
269 | bool IsPropCall = isa_and_nonnull<PseudoObjectExpr>(Val: Containing); |
270 | // Implicit property message sends are not 'implicit'. |
271 | if ((E->isImplicit() || IsPropCall) && |
272 | !(IsPropCall && |
273 | IsImplicitProperty(cast<PseudoObjectExpr>(Val: Containing)))) |
274 | Roles |= (unsigned)SymbolRole::Implicit; |
275 | |
276 | if (isDynamic(E)) { |
277 | Roles |= (unsigned)SymbolRole::Dynamic; |
278 | |
279 | auto addReceivers = [&](const ObjCObjectType *Ty) { |
280 | if (!Ty) |
281 | return; |
282 | if (const auto *clsD = Ty->getInterface()) { |
283 | Relations.emplace_back(Args: (unsigned)SymbolRole::RelationReceivedBy, |
284 | Args&: clsD); |
285 | } |
286 | for (const auto *protD : Ty->quals()) { |
287 | Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy, |
288 | protD); |
289 | } |
290 | }; |
291 | QualType recT = E->getReceiverType(); |
292 | if (const auto *Ptr = recT->getAs<ObjCObjectPointerType>()) |
293 | addReceivers(Ptr->getObjectType()); |
294 | else |
295 | addReceivers(recT->getAs<ObjCObjectType>()); |
296 | } |
297 | |
298 | return IndexCtx.handleReference(MD, E->getSelectorStartLoc(), |
299 | Parent, ParentDC, Roles, Relations, E); |
300 | } |
301 | return true; |
302 | } |
303 | |
304 | bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { |
305 | if (E->isExplicitProperty()) { |
306 | SmallVector<SymbolRelation, 2> Relations; |
307 | SymbolRoleSet Roles = getRolesForRef(E, Relations); |
308 | return IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(), |
309 | Parent, ParentDC, Roles, Relations, E); |
310 | } else if (const ObjCMethodDecl *Getter = E->getImplicitPropertyGetter()) { |
311 | // Class properties that are explicitly defined using @property |
312 | // declarations are represented implicitly as there is no ivar for class |
313 | // properties. |
314 | if (Getter->isClassMethod()) { |
315 | if (const auto *PD = Getter->getCanonicalDecl()->findPropertyDecl()) { |
316 | SmallVector<SymbolRelation, 2> Relations; |
317 | SymbolRoleSet Roles = getRolesForRef(E, Relations); |
318 | return IndexCtx.handleReference(PD, E->getLocation(), Parent, |
319 | ParentDC, Roles, Relations, E); |
320 | } |
321 | } |
322 | } |
323 | |
324 | // No need to do a handleReference for the objc method, because there will |
325 | // be a message expr as part of PseudoObjectExpr. |
326 | return true; |
327 | } |
328 | |
329 | bool VisitMSPropertyRefExpr(MSPropertyRefExpr *E) { |
330 | return IndexCtx.handleReference(E->getPropertyDecl(), E->getMemberLoc(), |
331 | Parent, ParentDC, SymbolRoleSet(), {}, E); |
332 | } |
333 | |
334 | bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) { |
335 | return IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(), |
336 | Parent, ParentDC, SymbolRoleSet(), {}, E); |
337 | } |
338 | |
339 | bool passObjCLiteralMethodCall(const ObjCMethodDecl *MD, const Expr *E) { |
340 | SymbolRoleSet Roles{}; |
341 | SmallVector<SymbolRelation, 2> Relations; |
342 | addCallRole(Roles, Relations); |
343 | Roles |= (unsigned)SymbolRole::Implicit; |
344 | return IndexCtx.handleReference(D: MD, Loc: E->getBeginLoc(), Parent, DC: ParentDC, |
345 | Roles, Relations, RefE: E); |
346 | } |
347 | |
348 | bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) { |
349 | if (ObjCMethodDecl *MD = E->getBoxingMethod()) { |
350 | return passObjCLiteralMethodCall(MD, E); |
351 | } |
352 | return true; |
353 | } |
354 | |
355 | bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) { |
356 | if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod()) { |
357 | return passObjCLiteralMethodCall(MD, E); |
358 | } |
359 | return true; |
360 | } |
361 | |
362 | bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) { |
363 | if (ObjCMethodDecl *MD = E->getArrayWithObjectsMethod()) { |
364 | return passObjCLiteralMethodCall(MD, E); |
365 | } |
366 | return true; |
367 | } |
368 | |
369 | bool VisitCXXConstructExpr(CXXConstructExpr *E) { |
370 | SymbolRoleSet Roles{}; |
371 | SmallVector<SymbolRelation, 2> Relations; |
372 | addCallRole(Roles, Relations); |
373 | return IndexCtx.handleReference(E->getConstructor(), E->getLocation(), |
374 | Parent, ParentDC, Roles, Relations, E); |
375 | } |
376 | |
377 | bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E, |
378 | DataRecursionQueue *Q = nullptr) { |
379 | if (E->getOperatorLoc().isInvalid()) |
380 | return true; // implicit. |
381 | return base::TraverseCXXOperatorCallExpr(E, Q); |
382 | } |
383 | |
384 | bool VisitDeclStmt(DeclStmt *S) { |
385 | if (IndexCtx.shouldIndexFunctionLocalSymbols()) { |
386 | IndexCtx.indexDeclGroupRef(DG: S->getDeclGroup()); |
387 | return true; |
388 | } |
389 | |
390 | DeclGroupRef DG = S->getDeclGroup(); |
391 | for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) { |
392 | const Decl *D = *I; |
393 | if (!D) |
394 | continue; |
395 | if (!isFunctionLocalSymbol(D)) |
396 | IndexCtx.indexTopLevelDecl(D); |
397 | } |
398 | |
399 | return true; |
400 | } |
401 | |
402 | bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C, |
403 | Expr *Init) { |
404 | if (C->capturesThis() || C->capturesVLAType()) |
405 | return true; |
406 | |
407 | if (!base::TraverseStmt(Init)) |
408 | return false; |
409 | |
410 | if (C->capturesVariable() && IndexCtx.shouldIndexFunctionLocalSymbols()) |
411 | return IndexCtx.handleReference(C->getCapturedVar(), C->getLocation(), |
412 | Parent, ParentDC, SymbolRoleSet()); |
413 | |
414 | return true; |
415 | } |
416 | |
417 | // RecursiveASTVisitor visits both syntactic and semantic forms, duplicating |
418 | // the things that we visit. Make sure to only visit the semantic form. |
419 | // Also visit things that are in the syntactic form but not the semantic one, |
420 | // for example the indices in DesignatedInitExprs. |
421 | bool TraverseInitListExpr(InitListExpr *S, DataRecursionQueue *Q = nullptr) { |
422 | auto visitForm = [&](InitListExpr *Form) { |
423 | for (Stmt *SubStmt : Form->children()) { |
424 | if (!TraverseStmt(S: SubStmt, Queue: Q)) |
425 | return false; |
426 | } |
427 | return true; |
428 | }; |
429 | |
430 | auto visitSyntacticDesignatedInitExpr = [&](DesignatedInitExpr *E) -> bool { |
431 | for (DesignatedInitExpr::Designator &D : llvm::reverse(C: E->designators())) { |
432 | if (D.isFieldDesignator()) { |
433 | if (const FieldDecl *FD = D.getFieldDecl()) { |
434 | return IndexCtx.handleReference(FD, D.getFieldLoc(), Parent, |
435 | ParentDC, SymbolRoleSet(), |
436 | /*Relations=*/{}, E); |
437 | } |
438 | } |
439 | } |
440 | return true; |
441 | }; |
442 | |
443 | InitListExpr *SemaForm = S->isSemanticForm() ? S : S->getSemanticForm(); |
444 | InitListExpr *SyntaxForm = S->isSemanticForm() ? S->getSyntacticForm() : S; |
445 | |
446 | if (SemaForm) { |
447 | // Visit things present in syntactic form but not the semantic form. |
448 | if (SyntaxForm) { |
449 | for (Expr *init : SyntaxForm->inits()) { |
450 | if (auto *DIE = dyn_cast<DesignatedInitExpr>(Val: init)) |
451 | visitSyntacticDesignatedInitExpr(DIE); |
452 | } |
453 | } |
454 | return visitForm(SemaForm); |
455 | } |
456 | |
457 | // No semantic, try the syntactic. |
458 | if (SyntaxForm) { |
459 | return visitForm(SyntaxForm); |
460 | } |
461 | |
462 | return true; |
463 | } |
464 | |
465 | bool VisitOffsetOfExpr(OffsetOfExpr *S) { |
466 | for (unsigned I = 0, E = S->getNumComponents(); I != E; ++I) { |
467 | const OffsetOfNode &Component = S->getComponent(Idx: I); |
468 | if (Component.getKind() == OffsetOfNode::Field) |
469 | IndexCtx.handleReference(Component.getField(), Component.getEndLoc(), |
470 | Parent, ParentDC, SymbolRoleSet(), {}); |
471 | // FIXME: Try to resolve dependent field references. |
472 | } |
473 | return true; |
474 | } |
475 | |
476 | bool VisitParmVarDecl(ParmVarDecl* D) { |
477 | // Index the parameters of lambda expression and requires expression. |
478 | if (IndexCtx.shouldIndexFunctionLocalSymbols()) { |
479 | const auto *DC = D->getDeclContext(); |
480 | if (DC && (isLambdaCallOperator(DC) || isa<RequiresExprBodyDecl>(DC))) |
481 | IndexCtx.handleDecl(D); |
482 | } |
483 | return true; |
484 | } |
485 | |
486 | bool VisitOverloadExpr(OverloadExpr *E) { |
487 | SmallVector<SymbolRelation, 4> Relations; |
488 | SymbolRoleSet Roles = getRolesForRef(E, Relations); |
489 | for (auto *D : E->decls()) |
490 | IndexCtx.handleReference(D, E->getNameLoc(), Parent, ParentDC, Roles, |
491 | Relations, E); |
492 | return true; |
493 | } |
494 | |
495 | bool VisitConceptSpecializationExpr(ConceptSpecializationExpr *R) { |
496 | IndexCtx.handleReference(R->getNamedConcept(), R->getConceptNameLoc(), |
497 | Parent, ParentDC); |
498 | return true; |
499 | } |
500 | |
501 | bool TraverseTypeConstraint(const TypeConstraint *C) { |
502 | IndexCtx.handleReference(C->getNamedConcept(), C->getConceptNameLoc(), |
503 | Parent, ParentDC); |
504 | return RecursiveASTVisitor::TraverseTypeConstraint(C); |
505 | } |
506 | }; |
507 | |
508 | } // anonymous namespace |
509 | |
510 | void IndexingContext::indexBody(const Stmt *S, const NamedDecl *Parent, |
511 | const DeclContext *DC) { |
512 | if (!S) |
513 | return; |
514 | |
515 | if (!DC) |
516 | DC = Parent->getLexicalDeclContext(); |
517 | BodyIndexer(*this, Parent, DC).TraverseStmt(S: const_cast<Stmt*>(S)); |
518 | } |
519 |
Definitions
- BodyIndexer
- getParentStmt
- BodyIndexer
- shouldWalkTypesOfTypeLocs
- dataTraverseStmtPre
- dataTraverseStmtPost
- TraverseTypeLoc
- TraverseNestedNameSpecifierLoc
- getRolesForRef
- addCallRole
- VisitDeclRefExpr
- VisitGotoStmt
- VisitCXXNewExpr
- VisitCXXDeleteExpr
- VisitLabelStmt
- VisitMemberExpr
- indexDependentReference
- VisitCXXDependentScopeMemberExpr
- VisitDependentScopeDeclRefExpr
- VisitDesignatedInitExpr
- VisitObjCIvarRefExpr
- VisitObjCMessageExpr
- VisitObjCPropertyRefExpr
- VisitMSPropertyRefExpr
- VisitObjCProtocolExpr
- passObjCLiteralMethodCall
- VisitObjCBoxedExpr
- VisitObjCDictionaryLiteral
- VisitObjCArrayLiteral
- VisitCXXConstructExpr
- TraverseCXXOperatorCallExpr
- VisitDeclStmt
- TraverseLambdaCapture
- TraverseInitListExpr
- VisitOffsetOfExpr
- VisitParmVarDecl
- VisitOverloadExpr
- VisitConceptSpecializationExpr
- TraverseTypeConstraint
Improve your Profiling and Debugging skills
Find out more