1 //===- IndexBody.cpp - Indexing statements --------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "IndexingContext.h"
10 #include "clang/AST/RecursiveASTVisitor.h"
11 #include "clang/AST/ASTLambda.h"
13 using namespace clang
;
14 using namespace clang::index
;
18 class BodyIndexer
: public RecursiveASTVisitor
<BodyIndexer
> {
19 IndexingContext
&IndexCtx
;
20 const NamedDecl
*Parent
;
21 const DeclContext
*ParentDC
;
22 SmallVector
<Stmt
*, 16> StmtStack
;
24 typedef RecursiveASTVisitor
<BodyIndexer
> base
;
26 Stmt
*getParentStmt() const {
27 return StmtStack
.size() < 2 ? nullptr : StmtStack
.end()[-2];
30 BodyIndexer(IndexingContext
&indexCtx
,
31 const NamedDecl
*Parent
, const DeclContext
*DC
)
32 : IndexCtx(indexCtx
), Parent(Parent
), ParentDC(DC
) { }
34 bool shouldWalkTypesOfTypeLocs() const { return false; }
36 bool dataTraverseStmtPre(Stmt
*S
) {
37 StmtStack
.push_back(S
);
41 bool dataTraverseStmtPost(Stmt
*S
) {
42 assert(StmtStack
.back() == S
);
47 bool TraverseTypeLoc(TypeLoc TL
) {
48 IndexCtx
.indexTypeLoc(TL
, Parent
, ParentDC
);
52 bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS
) {
53 IndexCtx
.indexNestedNameSpecifierLoc(NNS
, Parent
, ParentDC
);
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)
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
;
69 if (It
== StmtStack
.begin())
73 const Stmt
*Parent
= *It
;
75 if (auto BO
= dyn_cast
<BinaryOperator
>(Parent
)) {
76 if (BO
->getOpcode() == BO_Assign
&& BO
->getLHS()->IgnoreParenCasts() == E
)
77 Roles
|= (unsigned)SymbolRole::Write
;
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
;
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
;
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
,
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
;
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
);
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
);
143 bool VisitMemberExpr(MemberExpr
*E
) {
144 SourceLocation Loc
= E
->getMemberLoc();
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
);
153 bool indexDependentReference(
154 const Expr
*E
, const Type
*T
, const DeclarationNameInfo
&NameInfo
,
155 llvm::function_ref
<bool(const NamedDecl
*ND
)> Filter
) {
158 const TemplateSpecializationType
*TST
=
159 T
->getAs
<TemplateSpecializationType
>();
162 TemplateName TN
= TST
->getTemplateName();
163 const ClassTemplateDecl
*TD
=
164 dyn_cast_or_null
<ClassTemplateDecl
>(TN
.getAsTemplateDecl());
167 CXXRecordDecl
*RD
= TD
->getTemplatedDecl();
168 if (!RD
->hasDefinition())
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)
176 SourceLocation Loc
= NameInfo
.getLoc();
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
,
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(); });
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(); });
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
);
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
);
216 bool VisitObjCMessageExpr(ObjCMessageExpr
*E
) {
217 auto isDynamic
= [](const ObjCMessageExpr
*MsgE
)->bool {
218 if (MsgE
->getReceiverKind() != ObjCMessageExpr::Instance
)
220 if (auto *RecE
= dyn_cast
<ObjCMessageExpr
>(
221 MsgE
->getInstanceReceiver()->IgnoreParenCasts())) {
222 if (RecE
->getMethodFamily() == OMF_alloc
)
228 if (ObjCMethodDecl
*MD
= E
->getMethodDecl()) {
229 SymbolRoleSet Roles
{};
230 SmallVector
<SymbolRelation
, 2> Relations
;
231 addCallRole(Roles
, Relations
);
232 Stmt
*Containing
= getParentStmt();
234 auto IsImplicitProperty
= [](const PseudoObjectExpr
*POE
) -> bool {
235 const auto *E
= POE
->getSyntacticForm();
236 if (const auto *BinOp
= dyn_cast
<BinaryOperator
>(E
))
238 const auto *PRE
= dyn_cast
<ObjCPropertyRefExpr
>(E
);
241 if (PRE
->isExplicitProperty())
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
247 if (Getter
->isClassMethod() &&
248 Getter
->getCanonicalDecl()->findPropertyDecl())
253 bool IsPropCall
= Containing
&& isa
<PseudoObjectExpr
>(Containing
);
254 // Implicit property message sends are not 'implicit'.
255 if ((E
->isImplicit() || IsPropCall
) &&
257 IsImplicitProperty(cast
<PseudoObjectExpr
>(Containing
))))
258 Roles
|= (unsigned)SymbolRole::Implicit
;
261 Roles
|= (unsigned)SymbolRole::Dynamic
;
263 auto addReceivers
= [&](const ObjCObjectType
*Ty
) {
266 if (const auto *clsD
= Ty
->getInterface()) {
267 Relations
.emplace_back((unsigned)SymbolRole::RelationReceivedBy
,
270 for (const auto *protD
: Ty
->quals()) {
271 Relations
.emplace_back((unsigned)SymbolRole::RelationReceivedBy
,
275 QualType recT
= E
->getReceiverType();
276 if (const auto *Ptr
= recT
->getAs
<ObjCObjectPointerType
>())
277 addReceivers(Ptr
->getObjectType());
279 addReceivers(recT
->getAs
<ObjCObjectType
>());
282 return IndexCtx
.handleReference(MD
, E
->getSelectorStartLoc(),
283 Parent
, ParentDC
, Roles
, Relations
, E
);
288 bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr
*E
) {
289 if (E
->isExplicitProperty()) {
290 SmallVector
<SymbolRelation
, 2> Relations
;
291 SymbolRoleSet Roles
= getRolesForRef(E
, Relations
);
292 return IndexCtx
.handleReference(E
->getExplicitProperty(), E
->getLocation(),
293 Parent
, ParentDC
, Roles
, Relations
, E
);
294 } else if (const ObjCMethodDecl
*Getter
= E
->getImplicitPropertyGetter()) {
295 // Class properties that are explicitly defined using @property
296 // declarations are represented implicitly as there is no ivar for class
298 if (Getter
->isClassMethod()) {
299 if (const auto *PD
= Getter
->getCanonicalDecl()->findPropertyDecl()) {
300 SmallVector
<SymbolRelation
, 2> Relations
;
301 SymbolRoleSet Roles
= getRolesForRef(E
, Relations
);
302 return IndexCtx
.handleReference(PD
, E
->getLocation(), Parent
,
303 ParentDC
, Roles
, Relations
, E
);
308 // No need to do a handleReference for the objc method, because there will
309 // be a message expr as part of PseudoObjectExpr.
313 bool VisitMSPropertyRefExpr(MSPropertyRefExpr
*E
) {
314 return IndexCtx
.handleReference(E
->getPropertyDecl(), E
->getMemberLoc(),
315 Parent
, ParentDC
, SymbolRoleSet(), {}, E
);
318 bool VisitObjCProtocolExpr(ObjCProtocolExpr
*E
) {
319 return IndexCtx
.handleReference(E
->getProtocol(), E
->getProtocolIdLoc(),
320 Parent
, ParentDC
, SymbolRoleSet(), {}, E
);
323 bool passObjCLiteralMethodCall(const ObjCMethodDecl
*MD
, const Expr
*E
) {
324 SymbolRoleSet Roles
{};
325 SmallVector
<SymbolRelation
, 2> Relations
;
326 addCallRole(Roles
, Relations
);
327 Roles
|= (unsigned)SymbolRole::Implicit
;
328 return IndexCtx
.handleReference(MD
, E
->getBeginLoc(), Parent
, ParentDC
,
329 Roles
, Relations
, E
);
332 bool VisitObjCBoxedExpr(ObjCBoxedExpr
*E
) {
333 if (ObjCMethodDecl
*MD
= E
->getBoxingMethod()) {
334 return passObjCLiteralMethodCall(MD
, E
);
339 bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral
*E
) {
340 if (ObjCMethodDecl
*MD
= E
->getDictWithObjectsMethod()) {
341 return passObjCLiteralMethodCall(MD
, E
);
346 bool VisitObjCArrayLiteral(ObjCArrayLiteral
*E
) {
347 if (ObjCMethodDecl
*MD
= E
->getArrayWithObjectsMethod()) {
348 return passObjCLiteralMethodCall(MD
, E
);
353 bool VisitCXXConstructExpr(CXXConstructExpr
*E
) {
354 SymbolRoleSet Roles
{};
355 SmallVector
<SymbolRelation
, 2> Relations
;
356 addCallRole(Roles
, Relations
);
357 return IndexCtx
.handleReference(E
->getConstructor(), E
->getLocation(),
358 Parent
, ParentDC
, Roles
, Relations
, E
);
361 bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr
*E
,
362 DataRecursionQueue
*Q
= nullptr) {
363 if (E
->getOperatorLoc().isInvalid())
364 return true; // implicit.
365 return base::TraverseCXXOperatorCallExpr(E
, Q
);
368 bool VisitDeclStmt(DeclStmt
*S
) {
369 if (IndexCtx
.shouldIndexFunctionLocalSymbols()) {
370 IndexCtx
.indexDeclGroupRef(S
->getDeclGroup());
374 DeclGroupRef DG
= S
->getDeclGroup();
375 for (DeclGroupRef::iterator I
= DG
.begin(), E
= DG
.end(); I
!= E
; ++I
) {
379 if (!isFunctionLocalSymbol(D
))
380 IndexCtx
.indexTopLevelDecl(D
);
386 bool TraverseLambdaCapture(LambdaExpr
*LE
, const LambdaCapture
*C
,
388 if (C
->capturesThis() || C
->capturesVLAType())
391 if (!base::TraverseStmt(Init
))
394 if (C
->capturesVariable() && IndexCtx
.shouldIndexFunctionLocalSymbols())
395 return IndexCtx
.handleReference(C
->getCapturedVar(), C
->getLocation(),
396 Parent
, ParentDC
, SymbolRoleSet());
401 // RecursiveASTVisitor visits both syntactic and semantic forms, duplicating
402 // the things that we visit. Make sure to only visit the semantic form.
403 // Also visit things that are in the syntactic form but not the semantic one,
404 // for example the indices in DesignatedInitExprs.
405 bool TraverseInitListExpr(InitListExpr
*S
, DataRecursionQueue
*Q
= nullptr) {
406 auto visitForm
= [&](InitListExpr
*Form
) {
407 for (Stmt
*SubStmt
: Form
->children()) {
408 if (!TraverseStmt(SubStmt
, Q
))
414 auto visitSyntacticDesignatedInitExpr
= [&](DesignatedInitExpr
*E
) -> bool {
415 for (DesignatedInitExpr::Designator
&D
: llvm::reverse(E
->designators())) {
416 if (D
.isFieldDesignator() && D
.getField())
417 return IndexCtx
.handleReference(D
.getField(), D
.getFieldLoc(),
418 Parent
, ParentDC
, SymbolRoleSet(),
424 InitListExpr
*SemaForm
= S
->isSemanticForm() ? S
: S
->getSemanticForm();
425 InitListExpr
*SyntaxForm
= S
->isSemanticForm() ? S
->getSyntacticForm() : S
;
428 // Visit things present in syntactic form but not the semantic form.
430 for (Expr
*init
: SyntaxForm
->inits()) {
431 if (auto *DIE
= dyn_cast
<DesignatedInitExpr
>(init
))
432 visitSyntacticDesignatedInitExpr(DIE
);
435 return visitForm(SemaForm
);
438 // No semantic, try the syntactic.
440 return visitForm(SyntaxForm
);
446 bool VisitOffsetOfExpr(OffsetOfExpr
*S
) {
447 for (unsigned I
= 0, E
= S
->getNumComponents(); I
!= E
; ++I
) {
448 const OffsetOfNode
&Component
= S
->getComponent(I
);
449 if (Component
.getKind() == OffsetOfNode::Field
)
450 IndexCtx
.handleReference(Component
.getField(), Component
.getEndLoc(),
451 Parent
, ParentDC
, SymbolRoleSet(), {});
452 // FIXME: Try to resolve dependent field references.
457 bool VisitParmVarDecl(ParmVarDecl
* D
) {
458 // Index the parameters of lambda expression.
459 if (IndexCtx
.shouldIndexFunctionLocalSymbols()) {
460 const auto *DC
= D
->getDeclContext();
461 if (DC
&& isLambdaCallOperator(DC
))
462 IndexCtx
.handleDecl(D
);
467 bool VisitUnresolvedLookupExpr(UnresolvedLookupExpr
*E
) {
468 SmallVector
<SymbolRelation
, 4> Relations
;
469 SymbolRoleSet Roles
= getRolesForRef(E
, Relations
);
470 for (auto *D
: E
->decls())
471 IndexCtx
.handleReference(D
, E
->getNameLoc(), Parent
, ParentDC
, Roles
,
477 } // anonymous namespace
479 void IndexingContext::indexBody(const Stmt
*S
, const NamedDecl
*Parent
,
480 const DeclContext
*DC
) {
485 DC
= Parent
->getLexicalDeclContext();
486 BodyIndexer(*this, Parent
, DC
).TraverseStmt(const_cast<Stmt
*>(S
));