Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/Index/IndexDecl.cpp
35233 views
1
//===- IndexDecl.cpp - Indexing declarations ------------------------------===//
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/Attr.h"
12
#include "clang/AST/Decl.h"
13
#include "clang/AST/DeclTemplate.h"
14
#include "clang/AST/DeclVisitor.h"
15
#include "clang/Index/IndexDataConsumer.h"
16
#include "clang/Index/IndexSymbol.h"
17
18
using namespace clang;
19
using namespace index;
20
21
#define TRY_DECL(D,CALL_EXPR) \
22
do { \
23
if (!IndexCtx.shouldIndex(D)) return true; \
24
if (!CALL_EXPR) \
25
return false; \
26
} while (0)
27
28
#define TRY_TO(CALL_EXPR) \
29
do { \
30
if (!CALL_EXPR) \
31
return false; \
32
} while (0)
33
34
namespace {
35
36
class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {
37
IndexingContext &IndexCtx;
38
39
public:
40
explicit IndexingDeclVisitor(IndexingContext &indexCtx)
41
: IndexCtx(indexCtx) { }
42
43
bool Handled = true;
44
45
bool VisitDecl(const Decl *D) {
46
Handled = false;
47
return true;
48
}
49
50
void handleTemplateArgumentLoc(const TemplateArgumentLoc &TALoc,
51
const NamedDecl *Parent,
52
const DeclContext *DC) {
53
const TemplateArgumentLocInfo &LocInfo = TALoc.getLocInfo();
54
switch (TALoc.getArgument().getKind()) {
55
case TemplateArgument::Expression:
56
IndexCtx.indexBody(LocInfo.getAsExpr(), Parent, DC);
57
break;
58
case TemplateArgument::Type:
59
IndexCtx.indexTypeSourceInfo(LocInfo.getAsTypeSourceInfo(), Parent, DC);
60
break;
61
case TemplateArgument::Template:
62
case TemplateArgument::TemplateExpansion:
63
IndexCtx.indexNestedNameSpecifierLoc(TALoc.getTemplateQualifierLoc(),
64
Parent, DC);
65
if (const TemplateDecl *TD = TALoc.getArgument()
66
.getAsTemplateOrTemplatePattern()
67
.getAsTemplateDecl()) {
68
if (const NamedDecl *TTD = TD->getTemplatedDecl())
69
IndexCtx.handleReference(TTD, TALoc.getTemplateNameLoc(), Parent, DC);
70
}
71
break;
72
default:
73
break;
74
}
75
}
76
77
/// Returns true if the given method has been defined explicitly by the
78
/// user.
79
static bool hasUserDefined(const ObjCMethodDecl *D,
80
const ObjCImplDecl *Container) {
81
const ObjCMethodDecl *MD = Container->getMethod(D->getSelector(),
82
D->isInstanceMethod());
83
return MD && !MD->isImplicit() && MD->isThisDeclarationADefinition() &&
84
!MD->isSynthesizedAccessorStub();
85
}
86
87
88
void handleDeclarator(const DeclaratorDecl *D,
89
const NamedDecl *Parent = nullptr,
90
bool isIBType = false) {
91
if (!Parent) Parent = D;
92
93
IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), Parent,
94
Parent->getLexicalDeclContext(),
95
/*isBase=*/false, isIBType);
96
IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent);
97
auto IndexDefaultParmeterArgument = [&](const ParmVarDecl *Parm,
98
const NamedDecl *Parent) {
99
if (Parm->hasDefaultArg() && !Parm->hasUninstantiatedDefaultArg() &&
100
!Parm->hasUnparsedDefaultArg())
101
IndexCtx.indexBody(Parm->getDefaultArg(), Parent);
102
};
103
if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
104
if (const ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) {
105
auto *DC = Parm->getDeclContext();
106
if (auto *FD = dyn_cast<FunctionDecl>(DC)) {
107
if (IndexCtx.shouldIndexParametersInDeclarations() ||
108
FD->isThisDeclarationADefinition())
109
IndexCtx.handleDecl(Parm);
110
} else if (auto *MD = dyn_cast<ObjCMethodDecl>(DC)) {
111
if (MD->isThisDeclarationADefinition())
112
IndexCtx.handleDecl(Parm);
113
} else {
114
IndexCtx.handleDecl(Parm);
115
}
116
} else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
117
if (IndexCtx.shouldIndexParametersInDeclarations() ||
118
FD->isThisDeclarationADefinition()) {
119
for (const auto *PI : FD->parameters()) {
120
IndexDefaultParmeterArgument(PI, D);
121
IndexCtx.handleDecl(PI);
122
}
123
}
124
}
125
} else {
126
// Index the default parameter value for function definitions.
127
if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
128
if (FD->isThisDeclarationADefinition()) {
129
for (const auto *PV : FD->parameters()) {
130
IndexDefaultParmeterArgument(PV, D);
131
}
132
}
133
}
134
}
135
if (auto *C = D->getTrailingRequiresClause())
136
IndexCtx.indexBody(C, Parent);
137
}
138
139
bool handleObjCMethod(const ObjCMethodDecl *D,
140
const ObjCPropertyDecl *AssociatedProp = nullptr) {
141
SmallVector<SymbolRelation, 4> Relations;
142
SmallVector<const ObjCMethodDecl*, 4> Overriden;
143
144
D->getOverriddenMethods(Overriden);
145
for(auto overridden: Overriden) {
146
Relations.emplace_back((unsigned) SymbolRole::RelationOverrideOf,
147
overridden);
148
}
149
if (AssociatedProp)
150
Relations.emplace_back((unsigned)SymbolRole::RelationAccessorOf,
151
AssociatedProp);
152
153
// getLocation() returns beginning token of a method declaration, but for
154
// indexing purposes we want to point to the base name.
155
SourceLocation MethodLoc = D->getSelectorStartLoc();
156
if (MethodLoc.isInvalid())
157
MethodLoc = D->getLocation();
158
159
SourceLocation AttrLoc;
160
161
// check for (getter=/setter=)
162
if (AssociatedProp) {
163
bool isGetter = !D->param_size();
164
AttrLoc = isGetter ?
165
AssociatedProp->getGetterNameLoc():
166
AssociatedProp->getSetterNameLoc();
167
}
168
169
SymbolRoleSet Roles = (SymbolRoleSet)SymbolRole::Dynamic;
170
if (D->isImplicit()) {
171
if (AttrLoc.isValid()) {
172
MethodLoc = AttrLoc;
173
} else {
174
Roles |= (SymbolRoleSet)SymbolRole::Implicit;
175
}
176
} else if (AttrLoc.isValid()) {
177
IndexCtx.handleReference(D, AttrLoc, cast<NamedDecl>(D->getDeclContext()),
178
D->getDeclContext(), 0);
179
}
180
181
TRY_DECL(D, IndexCtx.handleDecl(D, MethodLoc, Roles, Relations));
182
IndexCtx.indexTypeSourceInfo(D->getReturnTypeSourceInfo(), D);
183
bool hasIBActionAndFirst = D->hasAttr<IBActionAttr>();
184
for (const auto *I : D->parameters()) {
185
handleDeclarator(I, D, /*isIBType=*/hasIBActionAndFirst);
186
hasIBActionAndFirst = false;
187
}
188
189
if (D->isThisDeclarationADefinition()) {
190
const Stmt *Body = D->getBody();
191
if (Body) {
192
IndexCtx.indexBody(Body, D, D);
193
}
194
}
195
return true;
196
}
197
198
/// Gather the declarations which the given declaration \D overrides in a
199
/// pseudo-override manner.
200
///
201
/// Pseudo-overrides occur when a class template specialization declares
202
/// a declaration that has the same name as a similar declaration in the
203
/// non-specialized template.
204
void
205
gatherTemplatePseudoOverrides(const NamedDecl *D,
206
SmallVectorImpl<SymbolRelation> &Relations) {
207
if (!IndexCtx.getLangOpts().CPlusPlus)
208
return;
209
const auto *CTSD =
210
dyn_cast<ClassTemplateSpecializationDecl>(D->getLexicalDeclContext());
211
if (!CTSD)
212
return;
213
llvm::PointerUnion<ClassTemplateDecl *,
214
ClassTemplatePartialSpecializationDecl *>
215
Template = CTSD->getSpecializedTemplateOrPartial();
216
if (const auto *CTD = Template.dyn_cast<ClassTemplateDecl *>()) {
217
const CXXRecordDecl *Pattern = CTD->getTemplatedDecl();
218
bool TypeOverride = isa<TypeDecl>(D);
219
for (const NamedDecl *ND : Pattern->lookup(D->getDeclName())) {
220
if (const auto *CTD = dyn_cast<ClassTemplateDecl>(ND))
221
ND = CTD->getTemplatedDecl();
222
if (ND->isImplicit())
223
continue;
224
// Types can override other types.
225
if (!TypeOverride) {
226
if (ND->getKind() != D->getKind())
227
continue;
228
} else if (!isa<TypeDecl>(ND))
229
continue;
230
if (const auto *FD = dyn_cast<FunctionDecl>(ND)) {
231
const auto *DFD = cast<FunctionDecl>(D);
232
// Function overrides are approximated using the number of parameters.
233
if (FD->getStorageClass() != DFD->getStorageClass() ||
234
FD->getNumParams() != DFD->getNumParams())
235
continue;
236
}
237
Relations.emplace_back(
238
SymbolRoleSet(SymbolRole::RelationSpecializationOf), ND);
239
}
240
}
241
}
242
243
bool VisitFunctionDecl(const FunctionDecl *D) {
244
SymbolRoleSet Roles{};
245
SmallVector<SymbolRelation, 4> Relations;
246
if (auto *CXXMD = dyn_cast<CXXMethodDecl>(D)) {
247
if (CXXMD->isVirtual())
248
Roles |= (unsigned)SymbolRole::Dynamic;
249
for (const CXXMethodDecl *O : CXXMD->overridden_methods()) {
250
Relations.emplace_back((unsigned)SymbolRole::RelationOverrideOf, O);
251
}
252
}
253
gatherTemplatePseudoOverrides(D, Relations);
254
if (const auto *Base = D->getPrimaryTemplate())
255
Relations.push_back(
256
SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf),
257
Base->getTemplatedDecl()));
258
259
TRY_DECL(D, IndexCtx.handleDecl(D, Roles, Relations));
260
handleDeclarator(D);
261
262
if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
263
IndexCtx.handleReference(Ctor->getParent(), Ctor->getLocation(),
264
Ctor->getParent(), Ctor->getDeclContext(),
265
(unsigned)SymbolRole::NameReference);
266
267
// Constructor initializers.
268
for (const auto *Init : Ctor->inits()) {
269
if (Init->isWritten()) {
270
IndexCtx.indexTypeSourceInfo(Init->getTypeSourceInfo(), D);
271
if (const FieldDecl *Member = Init->getAnyMember())
272
IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D,
273
(unsigned)SymbolRole::Write);
274
IndexCtx.indexBody(Init->getInit(), D, D);
275
}
276
}
277
} else if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(D)) {
278
if (auto TypeNameInfo = Dtor->getNameInfo().getNamedTypeInfo()) {
279
IndexCtx.handleReference(Dtor->getParent(),
280
TypeNameInfo->getTypeLoc().getBeginLoc(),
281
Dtor->getParent(), Dtor->getDeclContext(),
282
(unsigned)SymbolRole::NameReference);
283
}
284
} else if (const auto *Guide = dyn_cast<CXXDeductionGuideDecl>(D)) {
285
IndexCtx.handleReference(Guide->getDeducedTemplate()->getTemplatedDecl(),
286
Guide->getLocation(), Guide,
287
Guide->getDeclContext());
288
}
289
// Template specialization arguments.
290
if (const ASTTemplateArgumentListInfo *TemplateArgInfo =
291
D->getTemplateSpecializationArgsAsWritten()) {
292
for (const auto &Arg : TemplateArgInfo->arguments())
293
handleTemplateArgumentLoc(Arg, D, D->getLexicalDeclContext());
294
}
295
296
if (D->isThisDeclarationADefinition()) {
297
const Stmt *Body = D->getBody();
298
if (Body) {
299
IndexCtx.indexBody(Body, D, D);
300
}
301
}
302
return true;
303
}
304
305
bool VisitVarDecl(const VarDecl *D) {
306
SmallVector<SymbolRelation, 4> Relations;
307
gatherTemplatePseudoOverrides(D, Relations);
308
TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
309
handleDeclarator(D);
310
IndexCtx.indexBody(D->getInit(), D);
311
return true;
312
}
313
314
bool VisitDecompositionDecl(const DecompositionDecl *D) {
315
for (const auto *Binding : D->bindings())
316
TRY_DECL(Binding, IndexCtx.handleDecl(Binding));
317
return Base::VisitDecompositionDecl(D);
318
}
319
320
bool VisitFieldDecl(const FieldDecl *D) {
321
SmallVector<SymbolRelation, 4> Relations;
322
gatherTemplatePseudoOverrides(D, Relations);
323
TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
324
handleDeclarator(D);
325
if (D->isBitField())
326
IndexCtx.indexBody(D->getBitWidth(), D);
327
else if (D->hasInClassInitializer())
328
IndexCtx.indexBody(D->getInClassInitializer(), D);
329
return true;
330
}
331
332
bool VisitObjCIvarDecl(const ObjCIvarDecl *D) {
333
if (D->getSynthesize()) {
334
// handled in VisitObjCPropertyImplDecl
335
return true;
336
}
337
TRY_DECL(D, IndexCtx.handleDecl(D));
338
handleDeclarator(D);
339
return true;
340
}
341
342
bool VisitMSPropertyDecl(const MSPropertyDecl *D) {
343
TRY_DECL(D, IndexCtx.handleDecl(D));
344
handleDeclarator(D);
345
return true;
346
}
347
348
bool VisitEnumConstantDecl(const EnumConstantDecl *D) {
349
TRY_DECL(D, IndexCtx.handleDecl(D));
350
IndexCtx.indexBody(D->getInitExpr(), D);
351
return true;
352
}
353
354
bool VisitTypedefNameDecl(const TypedefNameDecl *D) {
355
if (!D->isTransparentTag()) {
356
SmallVector<SymbolRelation, 4> Relations;
357
gatherTemplatePseudoOverrides(D, Relations);
358
TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
359
IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
360
}
361
return true;
362
}
363
364
bool VisitTagDecl(const TagDecl *D) {
365
// Non-free standing tags are handled in indexTypeSourceInfo.
366
if (D->isFreeStanding()) {
367
if (D->isThisDeclarationADefinition()) {
368
SmallVector<SymbolRelation, 4> Relations;
369
gatherTemplatePseudoOverrides(D, Relations);
370
IndexCtx.indexTagDecl(D, Relations);
371
} else {
372
SmallVector<SymbolRelation, 1> Relations;
373
gatherTemplatePseudoOverrides(D, Relations);
374
return IndexCtx.handleDecl(D, D->getLocation(), SymbolRoleSet(),
375
Relations, D->getLexicalDeclContext());
376
}
377
}
378
return true;
379
}
380
381
bool VisitEnumDecl(const EnumDecl *ED) {
382
TRY_TO(VisitTagDecl(ED));
383
// Indexing for enumdecl itself is handled inside TagDecl, we just want to
384
// visit integer-base here, which is different than other TagDecl bases.
385
if (auto *TSI = ED->getIntegerTypeSourceInfo())
386
IndexCtx.indexTypeSourceInfo(TSI, ED, ED, /*isBase=*/true);
387
return true;
388
}
389
390
bool handleReferencedProtocols(const ObjCProtocolList &ProtList,
391
const ObjCContainerDecl *ContD,
392
SourceLocation SuperLoc) {
393
ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin();
394
for (ObjCInterfaceDecl::protocol_iterator
395
I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) {
396
SourceLocation Loc = *LI;
397
ObjCProtocolDecl *PD = *I;
398
SymbolRoleSet roles{};
399
if (Loc == SuperLoc)
400
roles |= (SymbolRoleSet)SymbolRole::Implicit;
401
TRY_TO(IndexCtx.handleReference(PD, Loc, ContD, ContD, roles,
402
SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, ContD}));
403
}
404
return true;
405
}
406
407
bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
408
if (D->isThisDeclarationADefinition()) {
409
TRY_DECL(D, IndexCtx.handleDecl(D));
410
SourceLocation SuperLoc = D->getSuperClassLoc();
411
if (auto *SuperD = D->getSuperClass()) {
412
bool hasSuperTypedef = false;
413
if (auto *TInfo = D->getSuperClassTInfo()) {
414
if (auto *TT = TInfo->getType()->getAs<TypedefType>()) {
415
if (auto *TD = TT->getDecl()) {
416
hasSuperTypedef = true;
417
TRY_TO(IndexCtx.handleReference(TD, SuperLoc, D, D,
418
SymbolRoleSet()));
419
}
420
}
421
}
422
SymbolRoleSet superRoles{};
423
if (hasSuperTypedef)
424
superRoles |= (SymbolRoleSet)SymbolRole::Implicit;
425
TRY_TO(IndexCtx.handleReference(SuperD, SuperLoc, D, D, superRoles,
426
SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, D}));
427
}
428
TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
429
SuperLoc));
430
TRY_TO(IndexCtx.indexDeclContext(D));
431
} else {
432
return IndexCtx.handleReference(D, D->getLocation(), nullptr,
433
D->getDeclContext(), SymbolRoleSet());
434
}
435
return true;
436
}
437
438
bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
439
if (D->isThisDeclarationADefinition()) {
440
TRY_DECL(D, IndexCtx.handleDecl(D));
441
TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
442
/*SuperLoc=*/SourceLocation()));
443
TRY_TO(IndexCtx.indexDeclContext(D));
444
} else {
445
return IndexCtx.handleReference(D, D->getLocation(), nullptr,
446
D->getDeclContext(), SymbolRoleSet());
447
}
448
return true;
449
}
450
451
bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) {
452
const ObjCInterfaceDecl *Class = D->getClassInterface();
453
if (!Class)
454
return true;
455
456
if (Class->isImplicitInterfaceDecl())
457
IndexCtx.handleDecl(Class);
458
459
TRY_DECL(D, IndexCtx.handleDecl(D));
460
461
// Visit implicit @synthesize property implementations first as their
462
// location is reported at the name of the @implementation block. This
463
// serves no purpose other than to simplify the FileCheck-based tests.
464
for (const auto *I : D->property_impls()) {
465
if (I->getLocation().isInvalid())
466
IndexCtx.indexDecl(I);
467
}
468
for (const auto *I : D->decls()) {
469
if (!isa<ObjCPropertyImplDecl>(I) ||
470
cast<ObjCPropertyImplDecl>(I)->getLocation().isValid())
471
IndexCtx.indexDecl(I);
472
}
473
474
return true;
475
}
476
477
bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
478
if (!IndexCtx.shouldIndex(D))
479
return true;
480
const ObjCInterfaceDecl *C = D->getClassInterface();
481
if (!C)
482
return true;
483
TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D, SymbolRoleSet(),
484
SymbolRelation{
485
(unsigned)SymbolRole::RelationExtendedBy, D
486
}));
487
SourceLocation CategoryLoc = D->getCategoryNameLoc();
488
if (!CategoryLoc.isValid())
489
CategoryLoc = D->getLocation();
490
TRY_TO(IndexCtx.handleDecl(D, CategoryLoc));
491
TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
492
/*SuperLoc=*/SourceLocation()));
493
TRY_TO(IndexCtx.indexDeclContext(D));
494
return true;
495
}
496
497
bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
498
const ObjCCategoryDecl *Cat = D->getCategoryDecl();
499
if (!Cat)
500
return true;
501
const ObjCInterfaceDecl *C = D->getClassInterface();
502
if (C)
503
TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D,
504
SymbolRoleSet()));
505
SourceLocation CategoryLoc = D->getCategoryNameLoc();
506
if (!CategoryLoc.isValid())
507
CategoryLoc = D->getLocation();
508
TRY_DECL(D, IndexCtx.handleDecl(D, CategoryLoc));
509
IndexCtx.indexDeclContext(D);
510
return true;
511
}
512
513
bool VisitObjCMethodDecl(const ObjCMethodDecl *D) {
514
// Methods associated with a property, even user-declared ones, are
515
// handled when we handle the property.
516
if (D->isPropertyAccessor())
517
return true;
518
519
handleObjCMethod(D);
520
return true;
521
}
522
523
bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
524
if (ObjCMethodDecl *MD = D->getGetterMethodDecl())
525
if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
526
handleObjCMethod(MD, D);
527
if (ObjCMethodDecl *MD = D->getSetterMethodDecl())
528
if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
529
handleObjCMethod(MD, D);
530
TRY_DECL(D, IndexCtx.handleDecl(D));
531
if (IBOutletCollectionAttr *attr = D->getAttr<IBOutletCollectionAttr>())
532
IndexCtx.indexTypeSourceInfo(attr->getInterfaceLoc(), D,
533
D->getLexicalDeclContext(), false, true);
534
IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
535
return true;
536
}
537
538
bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
539
ObjCPropertyDecl *PD = D->getPropertyDecl();
540
auto *Container = cast<ObjCImplDecl>(D->getDeclContext());
541
SourceLocation Loc = D->getLocation();
542
SymbolRoleSet Roles = 0;
543
SmallVector<SymbolRelation, 1> Relations;
544
545
if (ObjCIvarDecl *ID = D->getPropertyIvarDecl())
546
Relations.push_back({(SymbolRoleSet)SymbolRole::RelationAccessorOf, ID});
547
if (Loc.isInvalid()) {
548
Loc = Container->getLocation();
549
Roles |= (SymbolRoleSet)SymbolRole::Implicit;
550
}
551
TRY_DECL(D, IndexCtx.handleDecl(D, Loc, Roles, Relations));
552
553
if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
554
return true;
555
556
assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize);
557
SymbolRoleSet AccessorMethodRoles =
558
SymbolRoleSet(SymbolRole::Dynamic) | SymbolRoleSet(SymbolRole::Implicit);
559
if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) {
560
if (MD->isPropertyAccessor() && !hasUserDefined(MD, Container))
561
IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container);
562
}
563
if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) {
564
if (MD->isPropertyAccessor() && !hasUserDefined(MD, Container))
565
IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container);
566
}
567
if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) {
568
if (IvarD->getSynthesize()) {
569
// For synthesized ivars, use the location of its name in the
570
// corresponding @synthesize. If there isn't one, use the containing
571
// @implementation's location, rather than the property's location,
572
// otherwise the header file containing the @interface will have different
573
// indexing contents based on whether the @implementation was present or
574
// not in the translation unit.
575
SymbolRoleSet IvarRoles = 0;
576
SourceLocation IvarLoc = D->getPropertyIvarDeclLoc();
577
if (D->getLocation().isInvalid()) {
578
IvarLoc = Container->getLocation();
579
IvarRoles = (SymbolRoleSet)SymbolRole::Implicit;
580
} else if (D->getLocation() == IvarLoc) {
581
IvarRoles = (SymbolRoleSet)SymbolRole::Implicit;
582
}
583
TRY_DECL(IvarD, IndexCtx.handleDecl(IvarD, IvarLoc, IvarRoles));
584
} else {
585
IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), nullptr,
586
D->getDeclContext(), SymbolRoleSet());
587
}
588
}
589
return true;
590
}
591
592
bool VisitNamespaceDecl(const NamespaceDecl *D) {
593
TRY_DECL(D, IndexCtx.handleDecl(D));
594
IndexCtx.indexDeclContext(D);
595
return true;
596
}
597
598
bool VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) {
599
TRY_DECL(D, IndexCtx.handleDecl(D));
600
IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
601
IndexCtx.handleReference(D->getAliasedNamespace(), D->getTargetNameLoc(), D,
602
D->getLexicalDeclContext());
603
return true;
604
}
605
606
bool VisitUsingDecl(const UsingDecl *D) {
607
IndexCtx.handleDecl(D);
608
609
const DeclContext *DC = D->getDeclContext()->getRedeclContext();
610
const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
611
IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
612
D->getLexicalDeclContext());
613
for (const auto *I : D->shadows()) {
614
// Skip unresolved using decls - we already have a decl for the using
615
// itself, so there's not much point adding another decl or reference to
616
// refer to the same location.
617
if (isa<UnresolvedUsingIfExistsDecl>(I->getUnderlyingDecl()))
618
continue;
619
620
IndexCtx.handleReference(I->getUnderlyingDecl(), D->getLocation(), Parent,
621
D->getLexicalDeclContext(), SymbolRoleSet());
622
}
623
return true;
624
}
625
626
bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
627
const DeclContext *DC = D->getDeclContext()->getRedeclContext();
628
const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
629
630
// NNS for the local 'using namespace' directives is visited by the body
631
// visitor.
632
if (!D->getParentFunctionOrMethod())
633
IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
634
D->getLexicalDeclContext());
635
636
return IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(),
637
D->getLocation(), Parent,
638
D->getLexicalDeclContext(),
639
SymbolRoleSet());
640
}
641
642
bool VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) {
643
TRY_DECL(D, IndexCtx.handleDecl(D));
644
const DeclContext *DC = D->getDeclContext()->getRedeclContext();
645
const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
646
IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
647
D->getLexicalDeclContext());
648
return true;
649
}
650
651
bool VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) {
652
TRY_DECL(D, IndexCtx.handleDecl(D));
653
const DeclContext *DC = D->getDeclContext()->getRedeclContext();
654
const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
655
IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
656
D->getLexicalDeclContext());
657
return true;
658
}
659
660
bool VisitClassTemplateSpecializationDecl(const
661
ClassTemplateSpecializationDecl *D) {
662
// FIXME: Notify subsequent callbacks if info comes from implicit
663
// instantiation.
664
llvm::PointerUnion<ClassTemplateDecl *,
665
ClassTemplatePartialSpecializationDecl *>
666
Template = D->getSpecializedTemplateOrPartial();
667
const Decl *SpecializationOf =
668
Template.is<ClassTemplateDecl *>()
669
? (Decl *)Template.get<ClassTemplateDecl *>()
670
: Template.get<ClassTemplatePartialSpecializationDecl *>();
671
if (!D->isThisDeclarationADefinition())
672
IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
673
IndexCtx.indexTagDecl(
674
D, SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf),
675
SpecializationOf));
676
// Template specialization arguments.
677
if (const ASTTemplateArgumentListInfo *TemplateArgInfo =
678
D->getTemplateArgsAsWritten()) {
679
for (const auto &Arg : TemplateArgInfo->arguments())
680
handleTemplateArgumentLoc(Arg, D, D->getLexicalDeclContext());
681
}
682
return true;
683
}
684
685
static bool shouldIndexTemplateParameterDefaultValue(const NamedDecl *D) {
686
// We want to index the template parameters only once when indexing the
687
// canonical declaration.
688
if (!D)
689
return false;
690
if (const auto *FD = dyn_cast<FunctionDecl>(D))
691
return FD->getCanonicalDecl() == FD;
692
else if (const auto *TD = dyn_cast<TagDecl>(D))
693
return TD->getCanonicalDecl() == TD;
694
else if (const auto *VD = dyn_cast<VarDecl>(D))
695
return VD->getCanonicalDecl() == VD;
696
return true;
697
}
698
699
void indexTemplateParameters(TemplateParameterList *Params,
700
const NamedDecl *Parent) {
701
for (const NamedDecl *TP : *Params) {
702
if (IndexCtx.shouldIndexTemplateParameters())
703
IndexCtx.handleDecl(TP);
704
if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(TP)) {
705
if (TTP->hasDefaultArgument())
706
handleTemplateArgumentLoc(TTP->getDefaultArgument(), Parent,
707
TP->getLexicalDeclContext());
708
if (auto *C = TTP->getTypeConstraint())
709
IndexCtx.handleReference(C->getNamedConcept(), C->getConceptNameLoc(),
710
Parent, TTP->getLexicalDeclContext());
711
} else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TP)) {
712
IndexCtx.indexTypeSourceInfo(NTTP->getTypeSourceInfo(), Parent);
713
if (NTTP->hasDefaultArgument())
714
handleTemplateArgumentLoc(NTTP->getDefaultArgument(), Parent,
715
TP->getLexicalDeclContext());
716
} else if (const auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(TP)) {
717
if (TTPD->hasDefaultArgument())
718
handleTemplateArgumentLoc(TTPD->getDefaultArgument(), Parent,
719
TP->getLexicalDeclContext());
720
}
721
}
722
if (auto *R = Params->getRequiresClause())
723
IndexCtx.indexBody(R, Parent);
724
}
725
726
bool VisitTemplateDecl(const TemplateDecl *D) {
727
const NamedDecl *Parent = D->getTemplatedDecl();
728
if (!Parent)
729
return true;
730
731
// Index the default values for the template parameters.
732
auto *Params = D->getTemplateParameters();
733
if (Params && shouldIndexTemplateParameterDefaultValue(Parent)) {
734
indexTemplateParameters(Params, Parent);
735
}
736
737
return Visit(Parent);
738
}
739
740
bool VisitConceptDecl(const ConceptDecl *D) {
741
if (auto *Params = D->getTemplateParameters())
742
indexTemplateParameters(Params, D);
743
if (auto *E = D->getConstraintExpr())
744
IndexCtx.indexBody(E, D);
745
return IndexCtx.handleDecl(D);
746
}
747
748
bool VisitFriendDecl(const FriendDecl *D) {
749
if (auto ND = D->getFriendDecl()) {
750
// FIXME: Ignore a class template in a dependent context, these are not
751
// linked properly with their redeclarations, ending up with duplicate
752
// USRs.
753
// See comment "Friend templates are visible in fairly strange ways." in
754
// SemaTemplate.cpp which precedes code that prevents the friend template
755
// from becoming visible from the enclosing context.
756
if (isa<ClassTemplateDecl>(ND) && D->getDeclContext()->isDependentContext())
757
return true;
758
return Visit(ND);
759
}
760
if (auto Ty = D->getFriendType()) {
761
IndexCtx.indexTypeSourceInfo(Ty, cast<NamedDecl>(D->getDeclContext()));
762
}
763
return true;
764
}
765
766
bool VisitImportDecl(const ImportDecl *D) {
767
return IndexCtx.importedModule(D);
768
}
769
770
bool VisitStaticAssertDecl(const StaticAssertDecl *D) {
771
IndexCtx.indexBody(D->getAssertExpr(),
772
dyn_cast<NamedDecl>(D->getDeclContext()),
773
D->getLexicalDeclContext());
774
return true;
775
}
776
};
777
778
} // anonymous namespace
779
780
bool IndexingContext::indexDecl(const Decl *D) {
781
if (D->isImplicit() && shouldIgnoreIfImplicit(D))
782
return true;
783
784
if (isTemplateImplicitInstantiation(D) && !shouldIndexImplicitInstantiation())
785
return true;
786
787
IndexingDeclVisitor Visitor(*this);
788
bool ShouldContinue = Visitor.Visit(D);
789
if (!ShouldContinue)
790
return false;
791
792
if (!Visitor.Handled && isa<DeclContext>(D))
793
return indexDeclContext(cast<DeclContext>(D));
794
795
return true;
796
}
797
798
bool IndexingContext::indexDeclContext(const DeclContext *DC) {
799
for (const auto *I : DC->decls())
800
if (!indexDecl(I))
801
return false;
802
return true;
803
}
804
805
bool IndexingContext::indexTopLevelDecl(const Decl *D) {
806
if (!D || D->getLocation().isInvalid())
807
return true;
808
809
if (isa<ObjCMethodDecl>(D))
810
return true; // Wait for the objc container.
811
812
if (IndexOpts.ShouldTraverseDecl && !IndexOpts.ShouldTraverseDecl(D))
813
return true; // skip
814
815
return indexDecl(D);
816
}
817
818
bool IndexingContext::indexDeclGroupRef(DeclGroupRef DG) {
819
for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
820
if (!indexTopLevelDecl(*I))
821
return false;
822
return true;
823
}
824
825