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