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