Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/Index/IndexBody.cpp
35234 views
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/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"
16
17
using namespace clang;
18
using namespace clang::index;
19
20
namespace {
21
22
class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
23
IndexingContext &IndexCtx;
24
const NamedDecl *Parent;
25
const DeclContext *ParentDC;
26
SmallVector<Stmt*, 16> StmtStack;
27
28
typedef RecursiveASTVisitor<BodyIndexer> base;
29
30
Stmt *getParentStmt() const {
31
return StmtStack.size() < 2 ? nullptr : StmtStack.end()[-2];
32
}
33
public:
34
BodyIndexer(IndexingContext &indexCtx,
35
const NamedDecl *Parent, const DeclContext *DC)
36
: IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { }
37
38
bool shouldWalkTypesOfTypeLocs() const { return false; }
39
40
bool dataTraverseStmtPre(Stmt *S) {
41
StmtStack.push_back(S);
42
return true;
43
}
44
45
bool dataTraverseStmtPost(Stmt *S) {
46
assert(StmtStack.back() == S);
47
StmtStack.pop_back();
48
return true;
49
}
50
51
bool TraverseTypeLoc(TypeLoc TL) {
52
IndexCtx.indexTypeLoc(TL, Parent, ParentDC);
53
return true;
54
}
55
56
bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
57
IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
58
return true;
59
}
60
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)
66
return Roles;
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;
72
}
73
if (It == StmtStack.begin())
74
break;
75
--It;
76
}
77
const Stmt *Parent = *It;
78
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;
87
}
88
}
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;
95
}
96
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,
108
CXXRD);
109
}
110
}
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;
123
}
124
}
125
}
126
}
127
128
return Roles;
129
}
130
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);
138
}
139
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);
145
}
146
147
bool VisitGotoStmt(GotoStmt *S) {
148
return IndexCtx.handleReference(S->getLabel(), S->getLabelLoc(), Parent,
149
ParentDC);
150
}
151
152
bool VisitLabelStmt(LabelStmt *S) {
153
if (IndexCtx.shouldIndexFunctionLocalSymbols())
154
return IndexCtx.handleDecl(S->getDecl());
155
return true;
156
}
157
158
bool VisitMemberExpr(MemberExpr *E) {
159
SourceLocation Loc = E->getMemberLoc();
160
if (Loc.isInvalid())
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);
166
}
167
168
bool indexDependentReference(
169
const Expr *E, const Type *T, const DeclarationNameInfo &NameInfo,
170
llvm::function_ref<bool(const NamedDecl *ND)> Filter) {
171
if (!T)
172
return true;
173
const TemplateSpecializationType *TST =
174
T->getAs<TemplateSpecializationType>();
175
if (!TST)
176
return true;
177
TemplateName TN = TST->getTemplateName();
178
const ClassTemplateDecl *TD =
179
dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl());
180
if (!TD)
181
return true;
182
CXXRecordDecl *RD = TD->getTemplatedDecl();
183
if (!RD->hasDefinition())
184
return true;
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)
190
return true;
191
SourceLocation Loc = NameInfo.getLoc();
192
if (Loc.isInvalid())
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,
197
Relations, E);
198
}
199
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(); });
205
}
206
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(); });
213
}
214
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);
221
}
222
}
223
}
224
return true;
225
}
226
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);
232
}
233
234
bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
235
auto isDynamic = [](const ObjCMessageExpr *MsgE)->bool {
236
if (MsgE->getReceiverKind() != ObjCMessageExpr::Instance)
237
return false;
238
if (auto *RecE = dyn_cast<ObjCMessageExpr>(
239
MsgE->getInstanceReceiver()->IgnoreParenCasts())) {
240
if (RecE->getMethodFamily() == OMF_alloc)
241
return false;
242
}
243
return true;
244
};
245
246
if (ObjCMethodDecl *MD = E->getMethodDecl()) {
247
SymbolRoleSet Roles{};
248
SmallVector<SymbolRelation, 2> Relations;
249
addCallRole(Roles, Relations);
250
Stmt *Containing = getParentStmt();
251
252
auto IsImplicitProperty = [](const PseudoObjectExpr *POE) -> bool {
253
const auto *E = POE->getSyntacticForm();
254
if (const auto *BinOp = dyn_cast<BinaryOperator>(E))
255
E = BinOp->getLHS();
256
const auto *PRE = dyn_cast<ObjCPropertyRefExpr>(E);
257
if (!PRE)
258
return false;
259
if (PRE->isExplicitProperty())
260
return false;
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
264
// class properties.
265
if (Getter->isClassMethod() &&
266
Getter->getCanonicalDecl()->findPropertyDecl())
267
return false;
268
}
269
return true;
270
};
271
bool IsPropCall = isa_and_nonnull<PseudoObjectExpr>(Containing);
272
// Implicit property message sends are not 'implicit'.
273
if ((E->isImplicit() || IsPropCall) &&
274
!(IsPropCall &&
275
IsImplicitProperty(cast<PseudoObjectExpr>(Containing))))
276
Roles |= (unsigned)SymbolRole::Implicit;
277
278
if (isDynamic(E)) {
279
Roles |= (unsigned)SymbolRole::Dynamic;
280
281
auto addReceivers = [&](const ObjCObjectType *Ty) {
282
if (!Ty)
283
return;
284
if (const auto *clsD = Ty->getInterface()) {
285
Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy,
286
clsD);
287
}
288
for (const auto *protD : Ty->quals()) {
289
Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy,
290
protD);
291
}
292
};
293
QualType recT = E->getReceiverType();
294
if (const auto *Ptr = recT->getAs<ObjCObjectPointerType>())
295
addReceivers(Ptr->getObjectType());
296
else
297
addReceivers(recT->getAs<ObjCObjectType>());
298
}
299
300
return IndexCtx.handleReference(MD, E->getSelectorStartLoc(),
301
Parent, ParentDC, Roles, Relations, E);
302
}
303
return true;
304
}
305
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
315
// properties.
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);
322
}
323
}
324
}
325
326
// No need to do a handleReference for the objc method, because there will
327
// be a message expr as part of PseudoObjectExpr.
328
return true;
329
}
330
331
bool VisitMSPropertyRefExpr(MSPropertyRefExpr *E) {
332
return IndexCtx.handleReference(E->getPropertyDecl(), E->getMemberLoc(),
333
Parent, ParentDC, SymbolRoleSet(), {}, E);
334
}
335
336
bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
337
return IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(),
338
Parent, ParentDC, SymbolRoleSet(), {}, E);
339
}
340
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);
348
}
349
350
bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) {
351
if (ObjCMethodDecl *MD = E->getBoxingMethod()) {
352
return passObjCLiteralMethodCall(MD, E);
353
}
354
return true;
355
}
356
357
bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
358
if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod()) {
359
return passObjCLiteralMethodCall(MD, E);
360
}
361
return true;
362
}
363
364
bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
365
if (ObjCMethodDecl *MD = E->getArrayWithObjectsMethod()) {
366
return passObjCLiteralMethodCall(MD, E);
367
}
368
return true;
369
}
370
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);
377
}
378
379
bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E,
380
DataRecursionQueue *Q = nullptr) {
381
if (E->getOperatorLoc().isInvalid())
382
return true; // implicit.
383
return base::TraverseCXXOperatorCallExpr(E, Q);
384
}
385
386
bool VisitDeclStmt(DeclStmt *S) {
387
if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
388
IndexCtx.indexDeclGroupRef(S->getDeclGroup());
389
return true;
390
}
391
392
DeclGroupRef DG = S->getDeclGroup();
393
for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) {
394
const Decl *D = *I;
395
if (!D)
396
continue;
397
if (!isFunctionLocalSymbol(D))
398
IndexCtx.indexTopLevelDecl(D);
399
}
400
401
return true;
402
}
403
404
bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C,
405
Expr *Init) {
406
if (C->capturesThis() || C->capturesVLAType())
407
return true;
408
409
if (!base::TraverseStmt(Init))
410
return false;
411
412
if (C->capturesVariable() && IndexCtx.shouldIndexFunctionLocalSymbols())
413
return IndexCtx.handleReference(C->getCapturedVar(), C->getLocation(),
414
Parent, ParentDC, SymbolRoleSet());
415
416
return true;
417
}
418
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))
427
return false;
428
}
429
return true;
430
};
431
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);
439
}
440
}
441
}
442
return true;
443
};
444
445
InitListExpr *SemaForm = S->isSemanticForm() ? S : S->getSemanticForm();
446
InitListExpr *SyntaxForm = S->isSemanticForm() ? S->getSyntacticForm() : S;
447
448
if (SemaForm) {
449
// Visit things present in syntactic form but not the semantic form.
450
if (SyntaxForm) {
451
for (Expr *init : SyntaxForm->inits()) {
452
if (auto *DIE = dyn_cast<DesignatedInitExpr>(init))
453
visitSyntacticDesignatedInitExpr(DIE);
454
}
455
}
456
return visitForm(SemaForm);
457
}
458
459
// No semantic, try the syntactic.
460
if (SyntaxForm) {
461
return visitForm(SyntaxForm);
462
}
463
464
return true;
465
}
466
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.
474
}
475
return true;
476
}
477
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);
484
}
485
return true;
486
}
487
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,
493
Relations, E);
494
return true;
495
}
496
497
bool VisitConceptSpecializationExpr(ConceptSpecializationExpr *R) {
498
IndexCtx.handleReference(R->getNamedConcept(), R->getConceptNameLoc(),
499
Parent, ParentDC);
500
return true;
501
}
502
503
bool TraverseTypeConstraint(const TypeConstraint *C) {
504
IndexCtx.handleReference(C->getNamedConcept(), C->getConceptNameLoc(),
505
Parent, ParentDC);
506
return RecursiveASTVisitor::TraverseTypeConstraint(C);
507
}
508
};
509
510
} // anonymous namespace
511
512
void IndexingContext::indexBody(const Stmt *S, const NamedDecl *Parent,
513
const DeclContext *DC) {
514
if (!S)
515
return;
516
517
if (!DC)
518
DC = Parent->getLexicalDeclContext();
519
BodyIndexer(*this, Parent, DC).TraverseStmt(const_cast<Stmt*>(S));
520
}
521
522