Coverage Report

Created: 2023-11-11 10:31

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/tools/libclang/CXIndexDataConsumer.h
Line
Count
Source (jump to first uncovered line)
1
//===- CXIndexDataConsumer.h - Index data consumer for libclang--*- C++ -*-===//
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
#ifndef LLVM_CLANG_TOOLS_LIBCLANG_CXINDEXDATACONSUMER_H
10
#define LLVM_CLANG_TOOLS_LIBCLANG_CXINDEXDATACONSUMER_H
11
12
#include "CXCursor.h"
13
#include "Index_Internal.h"
14
#include "clang/Index/IndexDataConsumer.h"
15
#include "clang/AST/DeclGroup.h"
16
#include "clang/AST/DeclObjC.h"
17
#include "llvm/ADT/DenseSet.h"
18
19
namespace clang {
20
  class FileEntry;
21
  class MSPropertyDecl;
22
  class ObjCPropertyDecl;
23
  class ClassTemplateDecl;
24
  class FunctionTemplateDecl;
25
  class TypeAliasTemplateDecl;
26
  class ClassTemplateSpecializationDecl;
27
28
namespace cxindex {
29
  class CXIndexDataConsumer;
30
  class AttrListInfo;
31
32
class ScratchAlloc {
33
  CXIndexDataConsumer &IdxCtx;
34
35
public:
36
  explicit ScratchAlloc(CXIndexDataConsumer &indexCtx);
37
  ScratchAlloc(const ScratchAlloc &SA);
38
39
  ~ScratchAlloc();
40
41
  const char *toCStr(StringRef Str);
42
  const char *copyCStr(StringRef Str);
43
44
  template <typename T>
45
  T *allocate();
46
};
47
48
struct EntityInfo : public CXIdxEntityInfo {
49
  const NamedDecl *Dcl;
50
  CXIndexDataConsumer *IndexCtx;
51
  IntrusiveRefCntPtr<AttrListInfo> AttrList;
52
53
4.30k
  EntityInfo() {
54
4.30k
    name = USR = nullptr;
55
4.30k
    attributes = nullptr;
56
4.30k
    numAttributes = 0;
57
4.30k
  }
58
};
59
60
struct ContainerInfo : public CXIdxContainerInfo {
61
  const DeclContext *DC;
62
  CXIndexDataConsumer *IndexCtx;
63
};
64
  
65
struct DeclInfo : public CXIdxDeclInfo {
66
  enum DInfoKind {
67
    Info_Decl,
68
69
    Info_ObjCContainer,
70
      Info_ObjCInterface,
71
      Info_ObjCProtocol,
72
      Info_ObjCCategory,
73
74
    Info_ObjCProperty,
75
76
    Info_CXXClass
77
  };
78
  
79
  DInfoKind Kind;
80
81
  EntityInfo EntInfo;
82
  ContainerInfo SemanticContainer;
83
  ContainerInfo LexicalContainer;
84
  ContainerInfo DeclAsContainer;
85
86
  DeclInfo(bool isRedeclaration, bool isDefinition, bool isContainer)
87
354
    : Kind(Info_Decl) {
88
354
    this->isRedeclaration = isRedeclaration;
89
354
    this->isDefinition = isDefinition;
90
354
    this->isContainer = isContainer;
91
354
    attributes = nullptr;
92
354
    numAttributes = 0;
93
354
    declAsContainer = semanticContainer = lexicalContainer = nullptr;
94
354
    flags = 0;
95
354
  }
96
  DeclInfo(DInfoKind K,
97
           bool isRedeclaration, bool isDefinition, bool isContainer)
98
89
    : Kind(K) {
99
89
    this->isRedeclaration = isRedeclaration;
100
89
    this->isDefinition = isDefinition;
101
89
    this->isContainer = isContainer;
102
89
    attributes = nullptr;
103
89
    numAttributes = 0;
104
89
    declAsContainer = semanticContainer = lexicalContainer = nullptr;
105
89
    flags = 0;
106
89
  }
107
};
108
109
struct ObjCContainerDeclInfo : public DeclInfo {
110
  CXIdxObjCContainerDeclInfo ObjCContDeclInfo;
111
112
  ObjCContainerDeclInfo(bool isForwardRef,
113
                        bool isRedeclaration,
114
                        bool isImplementation)
115
10
    : DeclInfo(Info_ObjCContainer, isRedeclaration,
116
10
               /*isDefinition=*/!isForwardRef, /*isContainer=*/!isForwardRef) {
117
10
    init(isForwardRef, isImplementation);
118
10
  }
119
  ObjCContainerDeclInfo(DInfoKind K,
120
                        bool isForwardRef,
121
                        bool isRedeclaration,
122
                        bool isImplementation)
123
30
    : DeclInfo(K, isRedeclaration, /*isDefinition=*/!isForwardRef,
124
30
               /*isContainer=*/!isForwardRef) {
125
30
    init(isForwardRef, isImplementation);
126
30
  }
127
128
40
  static bool classof(const DeclInfo *D) {
129
40
    return Info_ObjCContainer <= D->Kind && D->Kind <= Info_ObjCCategory;
130
40
  }
131
132
private:
133
40
  void init(bool isForwardRef, bool isImplementation) {
134
40
    if (isForwardRef)
135
6
      ObjCContDeclInfo.kind = CXIdxObjCContainer_ForwardRef;
136
34
    else if (isImplementation)
137
4
      ObjCContDeclInfo.kind = CXIdxObjCContainer_Implementation;
138
30
    else
139
30
      ObjCContDeclInfo.kind = CXIdxObjCContainer_Interface;
140
40
  }
141
};
142
143
struct ObjCInterfaceDeclInfo : public ObjCContainerDeclInfo {
144
  CXIdxObjCInterfaceDeclInfo ObjCInterDeclInfo;
145
  CXIdxObjCProtocolRefListInfo ObjCProtoListInfo;
146
147
  ObjCInterfaceDeclInfo(const ObjCInterfaceDecl *D)
148
21
    : ObjCContainerDeclInfo(Info_ObjCInterface,
149
21
                            /*isForwardRef=*/false,
150
21
                            /*isRedeclaration=*/D->getPreviousDecl() != nullptr,
151
21
                            /*isImplementation=*/false) { }
152
153
886
  static bool classof(const DeclInfo *D) {
154
886
    return D->Kind == Info_ObjCInterface;
155
886
  }
156
};
157
158
struct ObjCProtocolDeclInfo : public ObjCContainerDeclInfo {
159
  CXIdxObjCProtocolRefListInfo ObjCProtoRefListInfo;
160
161
  ObjCProtocolDeclInfo(const ObjCProtocolDecl *D)
162
4
    : ObjCContainerDeclInfo(Info_ObjCProtocol,
163
4
                            /*isForwardRef=*/false,
164
4
                            /*isRedeclaration=*/D->getPreviousDecl(),
165
4
                            /*isImplementation=*/false) { }
166
167
422
  static bool classof(const DeclInfo *D) {
168
422
    return D->Kind == Info_ObjCProtocol;
169
422
  }
170
};
171
172
struct ObjCCategoryDeclInfo : public ObjCContainerDeclInfo {
173
  CXIdxObjCCategoryDeclInfo ObjCCatDeclInfo;
174
  CXIdxObjCProtocolRefListInfo ObjCProtoListInfo;
175
176
  explicit ObjCCategoryDeclInfo(bool isImplementation)
177
5
    : ObjCContainerDeclInfo(Info_ObjCCategory,
178
5
                            /*isForwardRef=*/false,
179
5
                            /*isRedeclaration=*/isImplementation,
180
5
                            /*isImplementation=*/isImplementation) { }
181
182
861
  static bool classof(const DeclInfo *D) {
183
861
    return D->Kind == Info_ObjCCategory;
184
861
  }
185
};
186
187
struct ObjCPropertyDeclInfo : public DeclInfo {
188
  CXIdxObjCPropertyDeclInfo ObjCPropDeclInfo;
189
190
  ObjCPropertyDeclInfo()
191
8
    : DeclInfo(Info_ObjCProperty,
192
8
               /*isRedeclaration=*/false, /*isDefinition=*/false,
193
8
               /*isContainer=*/false) { }
194
195
443
  static bool classof(const DeclInfo *D) {
196
443
    return D->Kind == Info_ObjCProperty;
197
443
  }
198
};
199
200
struct CXXClassDeclInfo : public DeclInfo {
201
  CXIdxCXXClassDeclInfo CXXClassInfo;
202
203
  CXXClassDeclInfo(bool isRedeclaration, bool isDefinition)
204
41
    : DeclInfo(Info_CXXClass, isRedeclaration, isDefinition, isDefinition) { }
205
206
443
  static bool classof(const DeclInfo *D) {
207
443
    return D->Kind == Info_CXXClass;
208
443
  }
209
};
210
211
struct AttrInfo : public CXIdxAttrInfo {
212
  const Attr *A;
213
214
87
  AttrInfo(CXIdxAttrKind Kind, CXCursor C, CXIdxLoc Loc, const Attr *A) {
215
87
    kind = Kind;
216
87
    cursor = C;
217
87
    loc = Loc;
218
87
    this->A = A;
219
87
  }
220
};
221
222
struct IBOutletCollectionInfo : public AttrInfo {
223
  EntityInfo ClassInfo;
224
  CXIdxIBOutletCollectionAttrInfo IBCollInfo;
225
226
  IBOutletCollectionInfo(CXCursor C, CXIdxLoc Loc, const Attr *A) :
227
3
    AttrInfo(CXIdxAttr_IBOutletCollection, C, Loc, A) {
228
3
    assert(C.kind == CXCursor_IBOutletCollectionAttr);
229
3
    IBCollInfo.objcClass = nullptr;
230
3
  }
231
232
  IBOutletCollectionInfo(const IBOutletCollectionInfo &other);
233
234
0
  static bool classof(const AttrInfo *A) {
235
0
    return A->kind == CXIdxAttr_IBOutletCollection;
236
0
  }
237
};
238
239
class AttrListInfo {
240
  ScratchAlloc SA;
241
242
  SmallVector<AttrInfo, 2> Attrs;
243
  SmallVector<IBOutletCollectionInfo, 2> IBCollAttrs;
244
  SmallVector<CXIdxAttrInfo *, 2> CXAttrs;
245
  unsigned ref_cnt;
246
247
  AttrListInfo(const AttrListInfo &) = delete;
248
  void operator=(const AttrListInfo &) = delete;
249
public:
250
  AttrListInfo(const Decl *D, CXIndexDataConsumer &IdxCtx);
251
252
  static IntrusiveRefCntPtr<AttrListInfo> create(const Decl *D,
253
                                                 CXIndexDataConsumer &IdxCtx);
254
255
63
  const CXIdxAttrInfo *const *getAttrs() const {
256
63
    if (CXAttrs.empty())
257
0
      return nullptr;
258
63
    return CXAttrs.data();
259
63
  }
260
63
  unsigned getNumAttrs() const { return (unsigned)CXAttrs.size(); }
261
262
  /// Retain/Release only useful when we allocate a AttrListInfo from the
263
  /// BumpPtrAllocator, and not from the stack; so that we keep a pointer
264
  // in the EntityInfo
265
63
  void Retain() { ++ref_cnt; }
266
63
  void Release() {
267
63
    assert (ref_cnt > 0 && "Reference count is already zero.");
268
63
    if (--ref_cnt == 0) {
269
      // Memory is allocated from a BumpPtrAllocator, no need to delete it.
270
63
      this->~AttrListInfo();
271
63
    }
272
63
  }
273
};
274
275
class CXIndexDataConsumer : public index::IndexDataConsumer {
276
  ASTContext *Ctx;
277
  CXClientData ClientData;
278
  IndexerCallbacks &CB;
279
  unsigned IndexOptions;
280
  CXTranslationUnit CXTU;
281
  
282
  typedef llvm::DenseMap<const FileEntry *, CXIdxClientFile> FileMapTy;
283
  typedef llvm::DenseMap<const DeclContext *, CXIdxClientContainer>
284
    ContainerMapTy;
285
  typedef llvm::DenseMap<const Decl *, CXIdxClientEntity> EntityMapTy;
286
287
  FileMapTy FileMap;
288
  ContainerMapTy ContainerMap;
289
  EntityMapTy EntityMap;
290
291
  typedef std::pair<const FileEntry *, const Decl *> RefFileOccurrence;
292
  llvm::DenseSet<RefFileOccurrence> RefFileOccurrences;
293
294
  llvm::BumpPtrAllocator StrScratch;
295
  unsigned StrAdapterCount;
296
  friend class ScratchAlloc;
297
298
  struct ObjCProtocolListInfo {
299
    SmallVector<CXIdxObjCProtocolRefInfo, 4> ProtInfos;
300
    SmallVector<EntityInfo, 4> ProtEntities;
301
    SmallVector<CXIdxObjCProtocolRefInfo *, 4> Prots;
302
303
30
    CXIdxObjCProtocolRefListInfo getListInfo() const {
304
30
      CXIdxObjCProtocolRefListInfo Info = { Prots.data(),
305
30
                                            (unsigned)Prots.size() };
306
30
      return Info;
307
30
    }
308
309
    ObjCProtocolListInfo(const ObjCProtocolList &ProtList,
310
                         CXIndexDataConsumer &IdxCtx,
311
                         ScratchAlloc &SA);
312
  };
313
314
  struct CXXBasesListInfo {
315
    SmallVector<CXIdxBaseClassInfo, 4> BaseInfos;
316
    SmallVector<EntityInfo, 4> BaseEntities;
317
    SmallVector<CXIdxBaseClassInfo *, 4> CXBases;
318
319
43
    const CXIdxBaseClassInfo *const *getBases() const {
320
43
      return CXBases.data();
321
43
    }
322
44
    unsigned getNumBases() const { return (unsigned)CXBases.size(); }
323
324
    CXXBasesListInfo(const CXXRecordDecl *D,
325
                     CXIndexDataConsumer &IdxCtx, ScratchAlloc &SA);
326
327
  private:
328
    SourceLocation getBaseLoc(const CXXBaseSpecifier &Base) const;
329
  };
330
331
  friend class AttrListInfo;
332
333
public:
334
  CXIndexDataConsumer(CXClientData clientData, IndexerCallbacks &indexCallbacks,
335
                      unsigned indexOptions, CXTranslationUnit cxTU)
336
54
      : Ctx(nullptr), ClientData(clientData), CB(indexCallbacks),
337
54
        IndexOptions(indexOptions), CXTU(cxTU), StrAdapterCount(0) {}
338
339
2.36k
  ASTContext &getASTContext() const { return *Ctx; }
340
1.88k
  CXTranslationUnit getCXTU() const { return CXTU; }
341
342
  void setASTContext(ASTContext &ctx);
343
  void setPreprocessor(std::shared_ptr<Preprocessor> PP) override;
344
345
2.41k
  bool shouldSuppressRefs() const {
346
2.41k
    return IndexOptions & CXIndexOpt_SuppressRedundantRefs;
347
2.41k
  }
348
349
2.35k
  bool shouldIndexFunctionLocalSymbols() const {
350
2.35k
    return IndexOptions & CXIndexOpt_IndexFunctionLocalSymbols;
351
2.35k
  }
352
353
135
  bool shouldIndexImplicitTemplateInsts() const {
354
135
    return IndexOptions & CXIndexOpt_IndexImplicitTemplateInstantiations;
355
135
  }
356
357
  static bool isFunctionLocalDecl(const Decl *D);
358
359
  bool shouldAbort();
360
361
63
  bool hasDiagnosticCallback() const { return CB.diagnostic; }
362
363
  void enteredMainFile(OptionalFileEntryRef File);
364
365
  void ppIncludedFile(SourceLocation hashLoc, StringRef filename,
366
                      OptionalFileEntryRef File, bool isImport, bool isAngled,
367
                      bool isModuleImport);
368
369
  void importedModule(const ImportDecl *ImportD);
370
  void importedPCH(FileEntryRef File);
371
372
  void startedTranslationUnit();
373
374
  void indexDiagnostics();
375
376
  void handleDiagnosticSet(CXDiagnosticSet CXDiagSet);
377
378
  bool handleFunction(const FunctionDecl *FD);
379
380
  bool handleVar(const VarDecl *D);
381
382
  bool handleField(const FieldDecl *D);
383
384
  bool handleEnumerator(const EnumConstantDecl *D);
385
386
  bool handleTagDecl(const TagDecl *D);
387
  
388
  bool handleTypedefName(const TypedefNameDecl *D);
389
390
  bool handleObjCInterface(const ObjCInterfaceDecl *D);
391
  bool handleObjCImplementation(const ObjCImplementationDecl *D);
392
393
  bool handleObjCProtocol(const ObjCProtocolDecl *D);
394
395
  bool handleObjCCategory(const ObjCCategoryDecl *D);
396
  bool handleObjCCategoryImpl(const ObjCCategoryImplDecl *D);
397
398
  bool handleObjCMethod(const ObjCMethodDecl *D, SourceLocation Loc);
399
400
  bool handleSynthesizedObjCProperty(const ObjCPropertyImplDecl *D);
401
  bool handleSynthesizedObjCMethod(const ObjCMethodDecl *D, SourceLocation Loc,
402
                                   const DeclContext *LexicalDC);
403
404
  bool handleObjCProperty(const ObjCPropertyDecl *D);
405
406
  bool handleNamespace(const NamespaceDecl *D);
407
408
  bool handleClassTemplate(const ClassTemplateDecl *D);
409
  bool handleFunctionTemplate(const FunctionTemplateDecl *D);
410
  bool handleTypeAliasTemplate(const TypeAliasTemplateDecl *D);
411
412
  bool handleConcept(const ConceptDecl *D);
413
414
  bool handleReference(const NamedDecl *D, SourceLocation Loc, CXCursor Cursor,
415
                       const NamedDecl *Parent,
416
                       const DeclContext *DC,
417
                       const Expr *E = nullptr,
418
                       CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct,
419
                       CXSymbolRole Role = CXSymbolRole_None);
420
421
  bool isNotFromSourceFile(SourceLocation Loc) const;
422
423
  void translateLoc(SourceLocation Loc, CXIdxClientFile *indexFile, CXFile *file,
424
                    unsigned *line, unsigned *column, unsigned *offset);
425
426
  CXIdxClientContainer getClientContainerForDC(const DeclContext *DC) const;
427
  void addContainerInMap(const DeclContext *DC, CXIdxClientContainer container);
428
429
  CXIdxClientEntity getClientEntity(const Decl *D) const;
430
  void setClientEntity(const Decl *D, CXIdxClientEntity client);
431
432
  static bool isTemplateImplicitInstantiation(const Decl *D);
433
434
private:
435
  bool handleDeclOccurrence(const Decl *D, index::SymbolRoleSet Roles,
436
                            ArrayRef<index::SymbolRelation> Relations,
437
                            SourceLocation Loc, ASTNodeInfo ASTNode) override;
438
439
  bool handleModuleOccurrence(const ImportDecl *ImportD, const Module *Mod,
440
                              index::SymbolRoleSet Roles,
441
                              SourceLocation Loc) override;
442
443
  void finish() override;
444
445
  bool handleDecl(const NamedDecl *D,
446
                  SourceLocation Loc, CXCursor Cursor,
447
                  DeclInfo &DInfo,
448
                  const DeclContext *LexicalDC = nullptr,
449
                  const DeclContext *SemaDC = nullptr);
450
451
  bool handleObjCContainer(const ObjCContainerDecl *D,
452
                           SourceLocation Loc, CXCursor Cursor,
453
                           ObjCContainerDeclInfo &ContDInfo);
454
455
  bool handleCXXRecordDecl(const CXXRecordDecl *RD, const NamedDecl *OrigD);
456
457
  bool markEntityOccurrenceInFile(const NamedDecl *D, SourceLocation Loc);
458
459
  const NamedDecl *getEntityDecl(const NamedDecl *D) const;
460
461
  const DeclContext *getEntityContainer(const Decl *D) const;
462
463
  CXIdxClientFile getIndexFile(const FileEntry *File);
464
  
465
  CXIdxLoc getIndexLoc(SourceLocation Loc) const;
466
467
  void getEntityInfo(const NamedDecl *D,
468
                     EntityInfo &EntityInfo,
469
                     ScratchAlloc &SA);
470
471
  void getContainerInfo(const DeclContext *DC, ContainerInfo &ContInfo);
472
473
7.21k
  CXCursor getCursor(const Decl *D) {
474
7.21k
    return cxcursor::MakeCXCursor(D, CXTU);
475
7.21k
  }
476
477
  CXCursor getRefCursor(const NamedDecl *D, SourceLocation Loc);
478
479
  static bool shouldIgnoreIfImplicit(const Decl *D);
480
};
481
482
2.59k
inline ScratchAlloc::ScratchAlloc(CXIndexDataConsumer &idxCtx) : IdxCtx(idxCtx) {
483
2.59k
  ++IdxCtx.StrAdapterCount;
484
2.59k
}
485
inline ScratchAlloc::ScratchAlloc(const ScratchAlloc &SA) : IdxCtx(SA.IdxCtx) {
486
  ++IdxCtx.StrAdapterCount;
487
}
488
489
2.59k
inline ScratchAlloc::~ScratchAlloc() {
490
2.59k
  --IdxCtx.StrAdapterCount;
491
2.59k
  if (IdxCtx.StrAdapterCount == 0)
492
2.39k
    IdxCtx.StrScratch.Reset();
493
2.59k
}
494
495
template <typename T>
496
63
inline T *ScratchAlloc::allocate() {
497
63
  return IdxCtx.StrScratch.Allocate<T>();
498
63
}
499
500
}} // end clang::cxindex
501
502
#endif