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