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