Coverage Report

Created: 2022-01-18 06:27

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