1 //===- IndexingContext.h - Higher level API functions -----------*- 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_INDEXINGCONTEXT_H
11 #define LLVM_CLANG_TOOLS_LIBCLANG_INDEXINGCONTEXT_H
12
13 #include "CXCursor.h"
14 #include "Index_Internal.h"
15 #include "clang/AST/DeclGroup.h"
16 #include "clang/AST/DeclObjC.h"
17 #include "llvm/ADT/DenseSet.h"
18 #include <deque>
19
20 namespace clang {
21 class FileEntry;
22 class MSPropertyDecl;
23 class ObjCPropertyDecl;
24 class ClassTemplateDecl;
25 class FunctionTemplateDecl;
26 class TypeAliasTemplateDecl;
27 class ClassTemplateSpecializationDecl;
28
29 namespace cxindex {
30 class IndexingContext;
31 class AttrListInfo;
32
33 class ScratchAlloc {
34 IndexingContext &IdxCtx;
35
36 public:
37 explicit ScratchAlloc(IndexingContext &indexCtx);
38 ScratchAlloc(const ScratchAlloc &SA);
39
40 ~ScratchAlloc();
41
42 const char *toCStr(StringRef Str);
43 const char *copyCStr(StringRef Str);
44
45 template <typename T>
46 T *allocate();
47 };
48
49 struct EntityInfo : public CXIdxEntityInfo {
50 const NamedDecl *Dcl;
51 IndexingContext *IndexCtx;
52 IntrusiveRefCntPtr<AttrListInfo> AttrList;
53
EntityInfoEntityInfo54 EntityInfo() {
55 name = USR = nullptr;
56 attributes = nullptr;
57 numAttributes = 0;
58 }
59 };
60
61 struct ContainerInfo : public CXIdxContainerInfo {
62 const DeclContext *DC;
63 IndexingContext *IndexCtx;
64 };
65
66 struct DeclInfo : public CXIdxDeclInfo {
67 enum DInfoKind {
68 Info_Decl,
69
70 Info_ObjCContainer,
71 Info_ObjCInterface,
72 Info_ObjCProtocol,
73 Info_ObjCCategory,
74
75 Info_ObjCProperty,
76
77 Info_CXXClass
78 };
79
80 DInfoKind Kind;
81
82 EntityInfo EntInfo;
83 ContainerInfo SemanticContainer;
84 ContainerInfo LexicalContainer;
85 ContainerInfo DeclAsContainer;
86
DeclInfoDeclInfo87 DeclInfo(bool isRedeclaration, bool isDefinition, bool isContainer)
88 : Kind(Info_Decl) {
89 this->isRedeclaration = isRedeclaration;
90 this->isDefinition = isDefinition;
91 this->isContainer = isContainer;
92 attributes = nullptr;
93 numAttributes = 0;
94 declAsContainer = semanticContainer = lexicalContainer = nullptr;
95 flags = 0;
96 }
DeclInfoDeclInfo97 DeclInfo(DInfoKind K,
98 bool isRedeclaration, bool isDefinition, bool isContainer)
99 : Kind(K) {
100 this->isRedeclaration = isRedeclaration;
101 this->isDefinition = isDefinition;
102 this->isContainer = isContainer;
103 attributes = nullptr;
104 numAttributes = 0;
105 declAsContainer = semanticContainer = lexicalContainer = nullptr;
106 flags = 0;
107 }
108 };
109
110 struct ObjCContainerDeclInfo : public DeclInfo {
111 CXIdxObjCContainerDeclInfo ObjCContDeclInfo;
112
ObjCContainerDeclInfoObjCContainerDeclInfo113 ObjCContainerDeclInfo(bool isForwardRef,
114 bool isRedeclaration,
115 bool isImplementation)
116 : DeclInfo(Info_ObjCContainer, isRedeclaration,
117 /*isDefinition=*/!isForwardRef, /*isContainer=*/!isForwardRef) {
118 init(isForwardRef, isImplementation);
119 }
ObjCContainerDeclInfoObjCContainerDeclInfo120 ObjCContainerDeclInfo(DInfoKind K,
121 bool isForwardRef,
122 bool isRedeclaration,
123 bool isImplementation)
124 : DeclInfo(K, isRedeclaration, /*isDefinition=*/!isForwardRef,
125 /*isContainer=*/!isForwardRef) {
126 init(isForwardRef, isImplementation);
127 }
128
classofObjCContainerDeclInfo129 static bool classof(const DeclInfo *D) {
130 return Info_ObjCContainer <= D->Kind && D->Kind <= Info_ObjCCategory;
131 }
132
133 private:
initObjCContainerDeclInfo134 void init(bool isForwardRef, bool isImplementation) {
135 if (isForwardRef)
136 ObjCContDeclInfo.kind = CXIdxObjCContainer_ForwardRef;
137 else if (isImplementation)
138 ObjCContDeclInfo.kind = CXIdxObjCContainer_Implementation;
139 else
140 ObjCContDeclInfo.kind = CXIdxObjCContainer_Interface;
141 }
142 };
143
144 struct ObjCInterfaceDeclInfo : public ObjCContainerDeclInfo {
145 CXIdxObjCInterfaceDeclInfo ObjCInterDeclInfo;
146 CXIdxObjCProtocolRefListInfo ObjCProtoListInfo;
147
ObjCInterfaceDeclInfoObjCInterfaceDeclInfo148 ObjCInterfaceDeclInfo(const ObjCInterfaceDecl *D)
149 : ObjCContainerDeclInfo(Info_ObjCInterface,
150 /*isForwardRef=*/false,
151 /*isRedeclaration=*/D->getPreviousDecl() != nullptr,
152 /*isImplementation=*/false) { }
153
classofObjCInterfaceDeclInfo154 static bool classof(const DeclInfo *D) {
155 return D->Kind == Info_ObjCInterface;
156 }
157 };
158
159 struct ObjCProtocolDeclInfo : public ObjCContainerDeclInfo {
160 CXIdxObjCProtocolRefListInfo ObjCProtoRefListInfo;
161
ObjCProtocolDeclInfoObjCProtocolDeclInfo162 ObjCProtocolDeclInfo(const ObjCProtocolDecl *D)
163 : ObjCContainerDeclInfo(Info_ObjCProtocol,
164 /*isForwardRef=*/false,
165 /*isRedeclaration=*/D->getPreviousDecl(),
166 /*isImplementation=*/false) { }
167
classofObjCProtocolDeclInfo168 static bool classof(const DeclInfo *D) {
169 return D->Kind == Info_ObjCProtocol;
170 }
171 };
172
173 struct ObjCCategoryDeclInfo : public ObjCContainerDeclInfo {
174 CXIdxObjCCategoryDeclInfo ObjCCatDeclInfo;
175 CXIdxObjCProtocolRefListInfo ObjCProtoListInfo;
176
ObjCCategoryDeclInfoObjCCategoryDeclInfo177 explicit ObjCCategoryDeclInfo(bool isImplementation)
178 : ObjCContainerDeclInfo(Info_ObjCCategory,
179 /*isForwardRef=*/false,
180 /*isRedeclaration=*/isImplementation,
181 /*isImplementation=*/isImplementation) { }
182
classofObjCCategoryDeclInfo183 static bool classof(const DeclInfo *D) {
184 return D->Kind == Info_ObjCCategory;
185 }
186 };
187
188 struct ObjCPropertyDeclInfo : public DeclInfo {
189 CXIdxObjCPropertyDeclInfo ObjCPropDeclInfo;
190
ObjCPropertyDeclInfoObjCPropertyDeclInfo191 ObjCPropertyDeclInfo()
192 : DeclInfo(Info_ObjCProperty,
193 /*isRedeclaration=*/false, /*isDefinition=*/false,
194 /*isContainer=*/false) { }
195
classofObjCPropertyDeclInfo196 static bool classof(const DeclInfo *D) {
197 return D->Kind == Info_ObjCProperty;
198 }
199 };
200
201 struct CXXClassDeclInfo : public DeclInfo {
202 CXIdxCXXClassDeclInfo CXXClassInfo;
203
CXXClassDeclInfoCXXClassDeclInfo204 CXXClassDeclInfo(bool isRedeclaration, bool isDefinition)
205 : DeclInfo(Info_CXXClass, isRedeclaration, isDefinition, isDefinition) { }
206
classofCXXClassDeclInfo207 static bool classof(const DeclInfo *D) {
208 return D->Kind == Info_CXXClass;
209 }
210 };
211
212 struct AttrInfo : public CXIdxAttrInfo {
213 const Attr *A;
214
AttrInfoAttrInfo215 AttrInfo(CXIdxAttrKind Kind, CXCursor C, CXIdxLoc Loc, const Attr *A) {
216 kind = Kind;
217 cursor = C;
218 loc = Loc;
219 this->A = A;
220 }
221 };
222
223 struct IBOutletCollectionInfo : public AttrInfo {
224 EntityInfo ClassInfo;
225 CXIdxIBOutletCollectionAttrInfo IBCollInfo;
226
IBOutletCollectionInfoIBOutletCollectionInfo227 IBOutletCollectionInfo(CXCursor C, CXIdxLoc Loc, const Attr *A) :
228 AttrInfo(CXIdxAttr_IBOutletCollection, C, Loc, A) {
229 assert(C.kind == CXCursor_IBOutletCollectionAttr);
230 IBCollInfo.objcClass = nullptr;
231 }
232
233 IBOutletCollectionInfo(const IBOutletCollectionInfo &other);
234
classofIBOutletCollectionInfo235 static bool classof(const AttrInfo *A) {
236 return A->kind == CXIdxAttr_IBOutletCollection;
237 }
238 };
239
240 class AttrListInfo {
241 ScratchAlloc SA;
242
243 SmallVector<AttrInfo, 2> Attrs;
244 SmallVector<IBOutletCollectionInfo, 2> IBCollAttrs;
245 SmallVector<CXIdxAttrInfo *, 2> CXAttrs;
246 unsigned ref_cnt;
247
248 AttrListInfo(const AttrListInfo &) = delete;
249 void operator=(const AttrListInfo &) = delete;
250 public:
251 AttrListInfo(const Decl *D, IndexingContext &IdxCtx);
252
253 static IntrusiveRefCntPtr<AttrListInfo> create(const Decl *D,
254 IndexingContext &IdxCtx);
255
getAttrs()256 const CXIdxAttrInfo *const *getAttrs() const {
257 if (CXAttrs.empty())
258 return nullptr;
259 return CXAttrs.data();
260 }
getNumAttrs()261 unsigned getNumAttrs() const { return (unsigned)CXAttrs.size(); }
262
263 /// \brief Retain/Release only useful when we allocate a AttrListInfo from the
264 /// BumpPtrAllocator, and not from the stack; so that we keep a pointer
265 // in the EntityInfo
Retain()266 void Retain() { ++ref_cnt; }
Release()267 void Release() {
268 assert (ref_cnt > 0 && "Reference count is already zero.");
269 if (--ref_cnt == 0) {
270 // Memory is allocated from a BumpPtrAllocator, no need to delete it.
271 this->~AttrListInfo();
272 }
273 }
274 };
275
276 class IndexingContext {
277 ASTContext *Ctx;
278 CXClientData ClientData;
279 IndexerCallbacks &CB;
280 unsigned IndexOptions;
281 CXTranslationUnit CXTU;
282
283 typedef llvm::DenseMap<const FileEntry *, CXIdxClientFile> FileMapTy;
284 typedef llvm::DenseMap<const DeclContext *, CXIdxClientContainer>
285 ContainerMapTy;
286 typedef llvm::DenseMap<const Decl *, CXIdxClientEntity> EntityMapTy;
287
288 FileMapTy FileMap;
289 ContainerMapTy ContainerMap;
290 EntityMapTy EntityMap;
291
292 typedef std::pair<const FileEntry *, const Decl *> RefFileOccurrence;
293 llvm::DenseSet<RefFileOccurrence> RefFileOccurrences;
294
295 std::deque<DeclGroupRef> TUDeclsInObjCContainer;
296
297 llvm::BumpPtrAllocator StrScratch;
298 unsigned StrAdapterCount;
299 friend class ScratchAlloc;
300
301 struct ObjCProtocolListInfo {
302 SmallVector<CXIdxObjCProtocolRefInfo, 4> ProtInfos;
303 SmallVector<EntityInfo, 4> ProtEntities;
304 SmallVector<CXIdxObjCProtocolRefInfo *, 4> Prots;
305
getListInfoObjCProtocolListInfo306 CXIdxObjCProtocolRefListInfo getListInfo() const {
307 CXIdxObjCProtocolRefListInfo Info = { Prots.data(),
308 (unsigned)Prots.size() };
309 return Info;
310 }
311
312 ObjCProtocolListInfo(const ObjCProtocolList &ProtList,
313 IndexingContext &IdxCtx,
314 ScratchAlloc &SA);
315 };
316
317 struct CXXBasesListInfo {
318 SmallVector<CXIdxBaseClassInfo, 4> BaseInfos;
319 SmallVector<EntityInfo, 4> BaseEntities;
320 SmallVector<CXIdxBaseClassInfo *, 4> CXBases;
321
getBasesCXXBasesListInfo322 const CXIdxBaseClassInfo *const *getBases() const {
323 return CXBases.data();
324 }
getNumBasesCXXBasesListInfo325 unsigned getNumBases() const { return (unsigned)CXBases.size(); }
326
327 CXXBasesListInfo(const CXXRecordDecl *D,
328 IndexingContext &IdxCtx, ScratchAlloc &SA);
329
330 private:
331 SourceLocation getBaseLoc(const CXXBaseSpecifier &Base) const;
332 };
333
334 friend class AttrListInfo;
335
336 public:
IndexingContext(CXClientData clientData,IndexerCallbacks & indexCallbacks,unsigned indexOptions,CXTranslationUnit cxTU)337 IndexingContext(CXClientData clientData, IndexerCallbacks &indexCallbacks,
338 unsigned indexOptions, CXTranslationUnit cxTU)
339 : Ctx(nullptr), ClientData(clientData), CB(indexCallbacks),
340 IndexOptions(indexOptions), CXTU(cxTU),
341 StrScratch(), StrAdapterCount(0) { }
342
getASTContext()343 ASTContext &getASTContext() const { return *Ctx; }
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 handleDiagnosticSet(CXDiagnosticSet CXDiagSet);
397
398 bool handleFunction(const FunctionDecl *FD);
399
400 bool handleVar(const VarDecl *D);
401
402 bool handleField(const FieldDecl *D);
403
404 bool handleMSProperty(const MSPropertyDecl *D);
405
406 bool handleEnumerator(const EnumConstantDecl *D);
407
408 bool handleTagDecl(const TagDecl *D);
409
410 bool handleTypedefName(const TypedefNameDecl *D);
411
412 bool handleObjCInterface(const ObjCInterfaceDecl *D);
413 bool handleObjCImplementation(const ObjCImplementationDecl *D);
414
415 bool handleObjCProtocol(const ObjCProtocolDecl *D);
416
417 bool handleObjCCategory(const ObjCCategoryDecl *D);
418 bool handleObjCCategoryImpl(const ObjCCategoryImplDecl *D);
419
420 bool handleObjCMethod(const ObjCMethodDecl *D);
421
422 bool handleSynthesizedObjCProperty(const ObjCPropertyImplDecl *D);
423 bool handleSynthesizedObjCMethod(const ObjCMethodDecl *D, SourceLocation Loc,
424 const DeclContext *LexicalDC);
425
426 bool handleObjCProperty(const ObjCPropertyDecl *D);
427
428 bool handleNamespace(const NamespaceDecl *D);
429
430 bool handleClassTemplate(const ClassTemplateDecl *D);
431 bool handleFunctionTemplate(const FunctionTemplateDecl *D);
432 bool handleTypeAliasTemplate(const TypeAliasTemplateDecl *D);
433
434 bool handleReference(const NamedDecl *D, SourceLocation Loc, CXCursor Cursor,
435 const NamedDecl *Parent,
436 const DeclContext *DC,
437 const Expr *E = nullptr,
438 CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct);
439
440 bool handleReference(const NamedDecl *D, SourceLocation Loc,
441 const NamedDecl *Parent,
442 const DeclContext *DC,
443 const Expr *E = nullptr,
444 CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct);
445
446 bool isNotFromSourceFile(SourceLocation Loc) const;
447
448 void indexTopLevelDecl(const Decl *D);
449 void indexTUDeclsInObjCContainer();
450 void indexDeclGroupRef(DeclGroupRef DG);
451
addTUDeclInObjCContainer(DeclGroupRef DG)452 void addTUDeclInObjCContainer(DeclGroupRef DG) {
453 TUDeclsInObjCContainer.push_back(DG);
454 }
455
456 void translateLoc(SourceLocation Loc, CXIdxClientFile *indexFile, CXFile *file,
457 unsigned *line, unsigned *column, unsigned *offset);
458
459 CXIdxClientContainer getClientContainerForDC(const DeclContext *DC) const;
460 void addContainerInMap(const DeclContext *DC, CXIdxClientContainer container);
461
462 CXIdxClientEntity getClientEntity(const Decl *D) const;
463 void setClientEntity(const Decl *D, CXIdxClientEntity client);
464
465 static bool isTemplateImplicitInstantiation(const Decl *D);
466
467 private:
468 bool handleDecl(const NamedDecl *D,
469 SourceLocation Loc, CXCursor Cursor,
470 DeclInfo &DInfo,
471 const DeclContext *LexicalDC = nullptr);
472
473 bool handleObjCContainer(const ObjCContainerDecl *D,
474 SourceLocation Loc, CXCursor Cursor,
475 ObjCContainerDeclInfo &ContDInfo);
476
477 bool handleCXXRecordDecl(const CXXRecordDecl *RD, const NamedDecl *OrigD);
478
479 bool markEntityOccurrenceInFile(const NamedDecl *D, SourceLocation Loc);
480
481 const NamedDecl *getEntityDecl(const NamedDecl *D) const;
482
483 const DeclContext *getEntityContainer(const Decl *D) const;
484
485 CXIdxClientFile getIndexFile(const FileEntry *File);
486
487 CXIdxLoc getIndexLoc(SourceLocation Loc) const;
488
489 void getEntityInfo(const NamedDecl *D,
490 EntityInfo &EntityInfo,
491 ScratchAlloc &SA);
492
493 void getContainerInfo(const DeclContext *DC, ContainerInfo &ContInfo);
494
getCursor(const Decl * D)495 CXCursor getCursor(const Decl *D) {
496 return cxcursor::MakeCXCursor(D, CXTU);
497 }
498
499 CXCursor getRefCursor(const NamedDecl *D, SourceLocation Loc);
500
501 static bool shouldIgnoreIfImplicit(const Decl *D);
502 };
503
ScratchAlloc(IndexingContext & idxCtx)504 inline ScratchAlloc::ScratchAlloc(IndexingContext &idxCtx) : IdxCtx(idxCtx) {
505 ++IdxCtx.StrAdapterCount;
506 }
ScratchAlloc(const ScratchAlloc & SA)507 inline ScratchAlloc::ScratchAlloc(const ScratchAlloc &SA) : IdxCtx(SA.IdxCtx) {
508 ++IdxCtx.StrAdapterCount;
509 }
510
~ScratchAlloc()511 inline ScratchAlloc::~ScratchAlloc() {
512 --IdxCtx.StrAdapterCount;
513 if (IdxCtx.StrAdapterCount == 0)
514 IdxCtx.StrScratch.Reset();
515 }
516
517 template <typename T>
allocate()518 inline T *ScratchAlloc::allocate() {
519 return IdxCtx.StrScratch.Allocate<T>();
520 }
521
522 }} // end clang::cxindex
523
524 #endif
525