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