Coverage Report

Created: 2023-09-30 09:22

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