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/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"
17 using namespace clang
;
18 using namespace clang::index
;
22 class BodyIndexer
: public RecursiveASTVisitor
<BodyIndexer
> {
23 IndexingContext
&IndexCtx
;
24 const NamedDecl
*Parent
;
25 const DeclContext
*ParentDC
;
26 SmallVector
<Stmt
*, 16> StmtStack
;
28 typedef RecursiveASTVisitor
<BodyIndexer
> base
;
30 Stmt
*getParentStmt() const {
31 return StmtStack
.size() < 2 ? nullptr : StmtStack
.end()[-2];
34 BodyIndexer(IndexingContext
&indexCtx
,
35 const NamedDecl
*Parent
, const DeclContext
*DC
)
36 : IndexCtx(indexCtx
), Parent(Parent
), ParentDC(DC
) { }
38 bool shouldWalkTypesOfTypeLocs() const { return false; }
40 bool dataTraverseStmtPre(Stmt
*S
) {
41 StmtStack
.push_back(S
);
45 bool dataTraverseStmtPost(Stmt
*S
) {
46 assert(StmtStack
.back() == S
);
51 bool TraverseTypeLoc(TypeLoc TL
) {
52 IndexCtx
.indexTypeLoc(TL
, Parent
, ParentDC
);
56 bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS
) {
57 IndexCtx
.indexNestedNameSpecifierLoc(NNS
, Parent
, ParentDC
);
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)
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
;
73 if (It
== StmtStack
.begin())
77 const Stmt
*Parent
= *It
;
79 if (auto BO
= dyn_cast
<BinaryOperator
>(Parent
)) {
80 if (BO
->getOpcode() == BO_Assign
) {
81 if (BO
->getLHS()->IgnoreParenCasts() == E
)
82 Roles
|= (unsigned)SymbolRole::Write
;
83 } else if (auto CA
= dyn_cast
<CompoundAssignOperator
>(Parent
)) {
84 if (CA
->getLHS()->IgnoreParenCasts() == E
) {
85 Roles
|= (unsigned)SymbolRole::Read
;
86 Roles
|= (unsigned)SymbolRole::Write
;
89 } else if (auto UO
= dyn_cast
<UnaryOperator
>(Parent
)) {
90 if (UO
->isIncrementDecrementOp()) {
91 Roles
|= (unsigned)SymbolRole::Read
;
92 Roles
|= (unsigned)SymbolRole::Write
;
93 } else if (UO
->getOpcode() == UO_AddrOf
) {
94 Roles
|= (unsigned)SymbolRole::AddressOf
;
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
,
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
;
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
);
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
);
147 bool VisitGotoStmt(GotoStmt
*S
) {
148 return IndexCtx
.handleReference(S
->getLabel(), S
->getLabelLoc(), Parent
,
152 bool VisitLabelStmt(LabelStmt
*S
) {
153 if (IndexCtx
.shouldIndexFunctionLocalSymbols())
154 return IndexCtx
.handleDecl(S
->getDecl());
158 bool VisitMemberExpr(MemberExpr
*E
) {
159 SourceLocation Loc
= E
->getMemberLoc();
161 Loc
= E
->getBeginLoc();
162 SmallVector
<SymbolRelation
, 4> Relations
;
163 SymbolRoleSet Roles
= getRolesForRef(E
, Relations
);
164 return IndexCtx
.handleReference(E
->getMemberDecl(), Loc
,
165 Parent
, ParentDC
, Roles
, Relations
, E
);
168 bool indexDependentReference(
169 const Expr
*E
, const Type
*T
, const DeclarationNameInfo
&NameInfo
,
170 llvm::function_ref
<bool(const NamedDecl
*ND
)> Filter
) {
173 const TemplateSpecializationType
*TST
=
174 T
->getAs
<TemplateSpecializationType
>();
177 TemplateName TN
= TST
->getTemplateName();
178 const ClassTemplateDecl
*TD
=
179 dyn_cast_or_null
<ClassTemplateDecl
>(TN
.getAsTemplateDecl());
182 CXXRecordDecl
*RD
= TD
->getTemplatedDecl();
183 if (!RD
->hasDefinition())
185 RD
= RD
->getDefinition();
186 std::vector
<const NamedDecl
*> Symbols
=
187 RD
->lookupDependentName(NameInfo
.getName(), Filter
);
188 // FIXME: Improve overload handling.
189 if (Symbols
.size() != 1)
191 SourceLocation Loc
= NameInfo
.getLoc();
193 Loc
= E
->getBeginLoc();
194 SmallVector
<SymbolRelation
, 4> Relations
;
195 SymbolRoleSet Roles
= getRolesForRef(E
, Relations
);
196 return IndexCtx
.handleReference(Symbols
[0], Loc
, Parent
, ParentDC
, Roles
,
200 bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr
*E
) {
201 const DeclarationNameInfo
&Info
= E
->getMemberNameInfo();
202 return indexDependentReference(
203 E
, E
->getBaseType().getTypePtrOrNull(), Info
,
204 [](const NamedDecl
*D
) { return D
->isCXXInstanceMember(); });
207 bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr
*E
) {
208 const DeclarationNameInfo
&Info
= E
->getNameInfo();
209 const NestedNameSpecifier
*NNS
= E
->getQualifier();
210 return indexDependentReference(
211 E
, NNS
->getAsType(), Info
,
212 [](const NamedDecl
*D
) { return !D
->isCXXInstanceMember(); });
215 bool VisitDesignatedInitExpr(DesignatedInitExpr
*E
) {
216 for (DesignatedInitExpr::Designator
&D
: llvm::reverse(E
->designators())) {
217 if (D
.isFieldDesignator()) {
218 if (const FieldDecl
*FD
= D
.getFieldDecl()) {
219 return IndexCtx
.handleReference(FD
, D
.getFieldLoc(), Parent
,
220 ParentDC
, SymbolRoleSet(), {}, E
);
227 bool VisitObjCIvarRefExpr(ObjCIvarRefExpr
*E
) {
228 SmallVector
<SymbolRelation
, 4> Relations
;
229 SymbolRoleSet Roles
= getRolesForRef(E
, Relations
);
230 return IndexCtx
.handleReference(E
->getDecl(), E
->getLocation(),
231 Parent
, ParentDC
, Roles
, Relations
, E
);
234 bool VisitObjCMessageExpr(ObjCMessageExpr
*E
) {
235 auto isDynamic
= [](const ObjCMessageExpr
*MsgE
)->bool {
236 if (MsgE
->getReceiverKind() != ObjCMessageExpr::Instance
)
238 if (auto *RecE
= dyn_cast
<ObjCMessageExpr
>(
239 MsgE
->getInstanceReceiver()->IgnoreParenCasts())) {
240 if (RecE
->getMethodFamily() == OMF_alloc
)
246 if (ObjCMethodDecl
*MD
= E
->getMethodDecl()) {
247 SymbolRoleSet Roles
{};
248 SmallVector
<SymbolRelation
, 2> Relations
;
249 addCallRole(Roles
, Relations
);
250 Stmt
*Containing
= getParentStmt();
252 auto IsImplicitProperty
= [](const PseudoObjectExpr
*POE
) -> bool {
253 const auto *E
= POE
->getSyntacticForm();
254 if (const auto *BinOp
= dyn_cast
<BinaryOperator
>(E
))
256 const auto *PRE
= dyn_cast
<ObjCPropertyRefExpr
>(E
);
259 if (PRE
->isExplicitProperty())
261 if (const ObjCMethodDecl
*Getter
= PRE
->getImplicitPropertyGetter()) {
262 // Class properties that are explicitly defined using @property
263 // declarations are represented implicitly as there is no ivar for
265 if (Getter
->isClassMethod() &&
266 Getter
->getCanonicalDecl()->findPropertyDecl())
271 bool IsPropCall
= Containing
&& isa
<PseudoObjectExpr
>(Containing
);
272 // Implicit property message sends are not 'implicit'.
273 if ((E
->isImplicit() || IsPropCall
) &&
275 IsImplicitProperty(cast
<PseudoObjectExpr
>(Containing
))))
276 Roles
|= (unsigned)SymbolRole::Implicit
;
279 Roles
|= (unsigned)SymbolRole::Dynamic
;
281 auto addReceivers
= [&](const ObjCObjectType
*Ty
) {
284 if (const auto *clsD
= Ty
->getInterface()) {
285 Relations
.emplace_back((unsigned)SymbolRole::RelationReceivedBy
,
288 for (const auto *protD
: Ty
->quals()) {
289 Relations
.emplace_back((unsigned)SymbolRole::RelationReceivedBy
,
293 QualType recT
= E
->getReceiverType();
294 if (const auto *Ptr
= recT
->getAs
<ObjCObjectPointerType
>())
295 addReceivers(Ptr
->getObjectType());
297 addReceivers(recT
->getAs
<ObjCObjectType
>());
300 return IndexCtx
.handleReference(MD
, E
->getSelectorStartLoc(),
301 Parent
, ParentDC
, Roles
, Relations
, E
);
306 bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr
*E
) {
307 if (E
->isExplicitProperty()) {
308 SmallVector
<SymbolRelation
, 2> Relations
;
309 SymbolRoleSet Roles
= getRolesForRef(E
, Relations
);
310 return IndexCtx
.handleReference(E
->getExplicitProperty(), E
->getLocation(),
311 Parent
, ParentDC
, Roles
, Relations
, E
);
312 } else if (const ObjCMethodDecl
*Getter
= E
->getImplicitPropertyGetter()) {
313 // Class properties that are explicitly defined using @property
314 // declarations are represented implicitly as there is no ivar for class
316 if (Getter
->isClassMethod()) {
317 if (const auto *PD
= Getter
->getCanonicalDecl()->findPropertyDecl()) {
318 SmallVector
<SymbolRelation
, 2> Relations
;
319 SymbolRoleSet Roles
= getRolesForRef(E
, Relations
);
320 return IndexCtx
.handleReference(PD
, E
->getLocation(), Parent
,
321 ParentDC
, Roles
, Relations
, E
);
326 // No need to do a handleReference for the objc method, because there will
327 // be a message expr as part of PseudoObjectExpr.
331 bool VisitMSPropertyRefExpr(MSPropertyRefExpr
*E
) {
332 return IndexCtx
.handleReference(E
->getPropertyDecl(), E
->getMemberLoc(),
333 Parent
, ParentDC
, SymbolRoleSet(), {}, E
);
336 bool VisitObjCProtocolExpr(ObjCProtocolExpr
*E
) {
337 return IndexCtx
.handleReference(E
->getProtocol(), E
->getProtocolIdLoc(),
338 Parent
, ParentDC
, SymbolRoleSet(), {}, E
);
341 bool passObjCLiteralMethodCall(const ObjCMethodDecl
*MD
, const Expr
*E
) {
342 SymbolRoleSet Roles
{};
343 SmallVector
<SymbolRelation
, 2> Relations
;
344 addCallRole(Roles
, Relations
);
345 Roles
|= (unsigned)SymbolRole::Implicit
;
346 return IndexCtx
.handleReference(MD
, E
->getBeginLoc(), Parent
, ParentDC
,
347 Roles
, Relations
, E
);
350 bool VisitObjCBoxedExpr(ObjCBoxedExpr
*E
) {
351 if (ObjCMethodDecl
*MD
= E
->getBoxingMethod()) {
352 return passObjCLiteralMethodCall(MD
, E
);
357 bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral
*E
) {
358 if (ObjCMethodDecl
*MD
= E
->getDictWithObjectsMethod()) {
359 return passObjCLiteralMethodCall(MD
, E
);
364 bool VisitObjCArrayLiteral(ObjCArrayLiteral
*E
) {
365 if (ObjCMethodDecl
*MD
= E
->getArrayWithObjectsMethod()) {
366 return passObjCLiteralMethodCall(MD
, E
);
371 bool VisitCXXConstructExpr(CXXConstructExpr
*E
) {
372 SymbolRoleSet Roles
{};
373 SmallVector
<SymbolRelation
, 2> Relations
;
374 addCallRole(Roles
, Relations
);
375 return IndexCtx
.handleReference(E
->getConstructor(), E
->getLocation(),
376 Parent
, ParentDC
, Roles
, Relations
, E
);
379 bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr
*E
,
380 DataRecursionQueue
*Q
= nullptr) {
381 if (E
->getOperatorLoc().isInvalid())
382 return true; // implicit.
383 return base::TraverseCXXOperatorCallExpr(E
, Q
);
386 bool VisitDeclStmt(DeclStmt
*S
) {
387 if (IndexCtx
.shouldIndexFunctionLocalSymbols()) {
388 IndexCtx
.indexDeclGroupRef(S
->getDeclGroup());
392 DeclGroupRef DG
= S
->getDeclGroup();
393 for (DeclGroupRef::iterator I
= DG
.begin(), E
= DG
.end(); I
!= E
; ++I
) {
397 if (!isFunctionLocalSymbol(D
))
398 IndexCtx
.indexTopLevelDecl(D
);
404 bool TraverseLambdaCapture(LambdaExpr
*LE
, const LambdaCapture
*C
,
406 if (C
->capturesThis() || C
->capturesVLAType())
409 if (!base::TraverseStmt(Init
))
412 if (C
->capturesVariable() && IndexCtx
.shouldIndexFunctionLocalSymbols())
413 return IndexCtx
.handleReference(C
->getCapturedVar(), C
->getLocation(),
414 Parent
, ParentDC
, SymbolRoleSet());
419 // RecursiveASTVisitor visits both syntactic and semantic forms, duplicating
420 // the things that we visit. Make sure to only visit the semantic form.
421 // Also visit things that are in the syntactic form but not the semantic one,
422 // for example the indices in DesignatedInitExprs.
423 bool TraverseInitListExpr(InitListExpr
*S
, DataRecursionQueue
*Q
= nullptr) {
424 auto visitForm
= [&](InitListExpr
*Form
) {
425 for (Stmt
*SubStmt
: Form
->children()) {
426 if (!TraverseStmt(SubStmt
, Q
))
432 auto visitSyntacticDesignatedInitExpr
= [&](DesignatedInitExpr
*E
) -> bool {
433 for (DesignatedInitExpr::Designator
&D
: llvm::reverse(E
->designators())) {
434 if (D
.isFieldDesignator()) {
435 if (const FieldDecl
*FD
= D
.getFieldDecl()) {
436 return IndexCtx
.handleReference(FD
, D
.getFieldLoc(), Parent
,
437 ParentDC
, SymbolRoleSet(),
438 /*Relations=*/{}, E
);
445 InitListExpr
*SemaForm
= S
->isSemanticForm() ? S
: S
->getSemanticForm();
446 InitListExpr
*SyntaxForm
= S
->isSemanticForm() ? S
->getSyntacticForm() : S
;
449 // Visit things present in syntactic form but not the semantic form.
451 for (Expr
*init
: SyntaxForm
->inits()) {
452 if (auto *DIE
= dyn_cast
<DesignatedInitExpr
>(init
))
453 visitSyntacticDesignatedInitExpr(DIE
);
456 return visitForm(SemaForm
);
459 // No semantic, try the syntactic.
461 return visitForm(SyntaxForm
);
467 bool VisitOffsetOfExpr(OffsetOfExpr
*S
) {
468 for (unsigned I
= 0, E
= S
->getNumComponents(); I
!= E
; ++I
) {
469 const OffsetOfNode
&Component
= S
->getComponent(I
);
470 if (Component
.getKind() == OffsetOfNode::Field
)
471 IndexCtx
.handleReference(Component
.getField(), Component
.getEndLoc(),
472 Parent
, ParentDC
, SymbolRoleSet(), {});
473 // FIXME: Try to resolve dependent field references.
478 bool VisitParmVarDecl(ParmVarDecl
* D
) {
479 // Index the parameters of lambda expression and requires expression.
480 if (IndexCtx
.shouldIndexFunctionLocalSymbols()) {
481 const auto *DC
= D
->getDeclContext();
482 if (DC
&& (isLambdaCallOperator(DC
) || isa
<RequiresExprBodyDecl
>(DC
)))
483 IndexCtx
.handleDecl(D
);
488 bool VisitOverloadExpr(OverloadExpr
*E
) {
489 SmallVector
<SymbolRelation
, 4> Relations
;
490 SymbolRoleSet Roles
= getRolesForRef(E
, Relations
);
491 for (auto *D
: E
->decls())
492 IndexCtx
.handleReference(D
, E
->getNameLoc(), Parent
, ParentDC
, Roles
,
497 bool VisitConceptSpecializationExpr(ConceptSpecializationExpr
*R
) {
498 IndexCtx
.handleReference(R
->getNamedConcept(), R
->getConceptNameLoc(),
503 bool TraverseTypeConstraint(const TypeConstraint
*C
) {
504 IndexCtx
.handleReference(C
->getNamedConcept(), C
->getConceptNameLoc(),
506 return RecursiveASTVisitor::TraverseTypeConstraint(C
);
510 } // anonymous namespace
512 void IndexingContext::indexBody(const Stmt
*S
, const NamedDecl
*Parent
,
513 const DeclContext
*DC
) {
518 DC
= Parent
->getLexicalDeclContext();
519 BodyIndexer(*this, Parent
, DC
).TraverseStmt(const_cast<Stmt
*>(S
));