xref: /freebsd/contrib/llvm-project/clang/lib/Index/IndexBody.cpp (revision e64bea71c21eb42e97aa615188ba91f6cce0d36d)
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(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, ParentDC);
54     return true;
55   }
56 
57   bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
58     IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, 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>(*It) || isa<ParenExpr>(*It)) {
70       if (auto ICE = dyn_cast<ImplicitCastExpr>(*It)) {
71         if (ICE->getCastKind() == CK_LValueToRValue)
72           Roles |= (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>(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>(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>(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>(Parent)) {
99       if (CE->getCallee()->IgnoreParenCasts() == E) {
100         addCallRole(Roles, Relations);
101         if (auto *ME = dyn_cast<MemberExpr>(E)) {
102           if (auto *CXXMD = dyn_cast_or_null<CXXMethodDecl>(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((unsigned)SymbolRole::RelationReceivedBy,
109                                          CXXRD);
110             }
111         }
112       } else if (auto CXXOp = dyn_cast<CXXOperatorCallExpr>(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>(ParentDC))
135       return;
136 
137     Roles |= (unsigned)SymbolRole::Call;
138     if (auto *FD = dyn_cast<FunctionDecl>(ParentDC))
139       Relations.emplace_back((unsigned)SymbolRole::RelationCalledBy, FD);
140     else if (auto *MD = dyn_cast<ObjCMethodDecl>(ParentDC))
141       Relations.emplace_back((unsigned)SymbolRole::RelationCalledBy, 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(TargetSymbols[0], Loc, Parent, ParentDC,
196                                     Roles, Relations, 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(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(E));
211   }
212 
213   bool VisitDesignatedInitExpr(DesignatedInitExpr *E) {
214     for (DesignatedInitExpr::Designator &D : llvm::reverse(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               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>(E))
253           E = BinOp->getLHS();
254         const auto *PRE = dyn_cast<ObjCPropertyRefExpr>(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>(Containing);
270       // Implicit property message sends are not 'implicit'.
271       if ((E->isImplicit() || IsPropCall) &&
272           !(IsPropCall &&
273             IsImplicitProperty(cast<PseudoObjectExpr>(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((unsigned)SymbolRole::RelationReceivedBy,
284                                    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(MD, E->getBeginLoc(), Parent, ParentDC,
345                                     Roles, Relations, 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(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(SubStmt, Q))
425           return false;
426       }
427       return true;
428     };
429 
430     auto visitSyntacticDesignatedInitExpr = [&](DesignatedInitExpr *E) -> bool {
431       for (DesignatedInitExpr::Designator &D : llvm::reverse(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         } else {
439           if (D.isArrayDesignator())
440             TraverseStmt(E->getArrayIndex(D));
441           else if (D.isArrayRangeDesignator()) {
442             TraverseStmt(E->getArrayRangeStart(D));
443             TraverseStmt(E->getArrayRangeEnd(D));
444           }
445         }
446       }
447       return true;
448     };
449 
450     InitListExpr *SemaForm = S->isSemanticForm() ? S : S->getSemanticForm();
451     InitListExpr *SyntaxForm = S->isSemanticForm() ? S->getSyntacticForm() : S;
452 
453     if (SemaForm) {
454       // Visit things present in syntactic form but not the semantic form.
455       if (SyntaxForm) {
456         for (Expr *init : SyntaxForm->inits()) {
457           if (auto *DIE = dyn_cast<DesignatedInitExpr>(init))
458             visitSyntacticDesignatedInitExpr(DIE);
459         }
460       }
461       return visitForm(SemaForm);
462     }
463 
464     // No semantic, try the syntactic.
465     if (SyntaxForm) {
466       return visitForm(SyntaxForm);
467     }
468 
469     return true;
470   }
471 
472   bool VisitOffsetOfExpr(OffsetOfExpr *S) {
473     for (unsigned I = 0, E = S->getNumComponents(); I != E; ++I) {
474       const OffsetOfNode &Component = S->getComponent(I);
475       if (Component.getKind() == OffsetOfNode::Field)
476         IndexCtx.handleReference(Component.getField(), Component.getEndLoc(),
477                                  Parent, ParentDC, SymbolRoleSet(), {});
478       // FIXME: Try to resolve dependent field references.
479     }
480     return true;
481   }
482 
483   bool VisitParmVarDecl(ParmVarDecl* D) {
484     // Index the parameters of lambda expression and requires expression.
485     if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
486       const auto *DC = D->getDeclContext();
487       if (DC && (isLambdaCallOperator(DC) || isa<RequiresExprBodyDecl>(DC)))
488         IndexCtx.handleDecl(D);
489     }
490     return true;
491   }
492 
493   bool VisitOverloadExpr(OverloadExpr *E) {
494     SmallVector<SymbolRelation, 4> Relations;
495     SymbolRoleSet Roles = getRolesForRef(E, Relations);
496     for (auto *D : E->decls())
497       IndexCtx.handleReference(D, E->getNameLoc(), Parent, ParentDC, Roles,
498                                Relations, E);
499     return true;
500   }
501 
502   bool VisitConceptSpecializationExpr(ConceptSpecializationExpr *R) {
503     IndexCtx.handleReference(R->getNamedConcept(), R->getConceptNameLoc(),
504                              Parent, ParentDC);
505     return true;
506   }
507 
508   bool TraverseTypeConstraint(const TypeConstraint *C) {
509     IndexCtx.handleReference(C->getNamedConcept(), C->getConceptNameLoc(),
510                              Parent, ParentDC);
511     return RecursiveASTVisitor::TraverseTypeConstraint(C);
512   }
513 };
514 
515 } // anonymous namespace
516 
517 void IndexingContext::indexBody(const Stmt *S, const NamedDecl *Parent,
518                                 const DeclContext *DC) {
519   if (!S)
520     return;
521 
522   if (!DC)
523     DC = Parent->getLexicalDeclContext();
524   BodyIndexer(*this, Parent, DC).TraverseStmt(const_cast<Stmt*>(S));
525 }
526