1 //===- IndexingContext.h - Higher level API functions ------------------------===//
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 #include "Index_Internal.h"
11 #include "CXCursor.h"
12
13 #include "clang/AST/DeclObjC.h"
14 #include "clang/AST/DeclGroup.h"
15 #include "llvm/ADT/DenseSet.h"
16 #include <deque>
17
18 namespace clang {
19 class FileEntry;
20 class ObjCPropertyDecl;
21 class ClassTemplateDecl;
22 class FunctionTemplateDecl;
23 class TypeAliasTemplateDecl;
24 class ClassTemplateSpecializationDecl;
25
26 namespace cxindex {
27 class IndexingContext;
28 class AttrListInfo;
29
30 class ScratchAlloc {
31 IndexingContext &IdxCtx;
32
33 public:
34 explicit ScratchAlloc(IndexingContext &indexCtx);
35 ScratchAlloc(const ScratchAlloc &SA);
36
37 ~ScratchAlloc();
38
39 const char *toCStr(StringRef Str);
40 const char *copyCStr(StringRef Str);
41
42 template <typename T>
43 T *allocate();
44 };
45
46 struct EntityInfo : public CXIdxEntityInfo {
47 const NamedDecl *Dcl;
48 IndexingContext *IndexCtx;
49 IntrusiveRefCntPtr<AttrListInfo> AttrList;
50
EntityInfoEntityInfo51 EntityInfo() {
52 name = USR = 0;
53 attributes = 0;
54 numAttributes = 0;
55 }
56 };
57
58 struct ContainerInfo : public CXIdxContainerInfo {
59 const DeclContext *DC;
60 IndexingContext *IndexCtx;
61 };
62
63 struct DeclInfo : public CXIdxDeclInfo {
64 enum DInfoKind {
65 Info_Decl,
66
67 Info_ObjCContainer,
68 Info_ObjCInterface,
69 Info_ObjCProtocol,
70 Info_ObjCCategory,
71
72 Info_ObjCProperty,
73
74 Info_CXXClass
75 };
76
77 DInfoKind Kind;
78
79 EntityInfo EntInfo;
80 ContainerInfo SemanticContainer;
81 ContainerInfo LexicalContainer;
82 ContainerInfo DeclAsContainer;
83
DeclInfoDeclInfo84 DeclInfo(bool isRedeclaration, bool isDefinition, bool isContainer)
85 : Kind(Info_Decl) {
86 this->isRedeclaration = isRedeclaration;
87 this->isDefinition = isDefinition;
88 this->isContainer = isContainer;
89 attributes = 0;
90 numAttributes = 0;
91 declAsContainer = semanticContainer = lexicalContainer = 0;
92 }
DeclInfoDeclInfo93 DeclInfo(DInfoKind K,
94 bool isRedeclaration, bool isDefinition, bool isContainer)
95 : Kind(K) {
96 this->isRedeclaration = isRedeclaration;
97 this->isDefinition = isDefinition;
98 this->isContainer = isContainer;
99 attributes = 0;
100 numAttributes = 0;
101 declAsContainer = semanticContainer = lexicalContainer = 0;
102 }
103
classofDeclInfo104 static bool classof(const DeclInfo *) { return true; }
105 };
106
107 struct ObjCContainerDeclInfo : public DeclInfo {
108 CXIdxObjCContainerDeclInfo ObjCContDeclInfo;
109
ObjCContainerDeclInfoObjCContainerDeclInfo110 ObjCContainerDeclInfo(bool isForwardRef,
111 bool isRedeclaration,
112 bool isImplementation)
113 : DeclInfo(Info_ObjCContainer, isRedeclaration,
114 /*isDefinition=*/!isForwardRef, /*isContainer=*/!isForwardRef) {
115 init(isForwardRef, isImplementation);
116 }
ObjCContainerDeclInfoObjCContainerDeclInfo117 ObjCContainerDeclInfo(DInfoKind K,
118 bool isForwardRef,
119 bool isRedeclaration,
120 bool isImplementation)
121 : DeclInfo(K, isRedeclaration, /*isDefinition=*/!isForwardRef,
122 /*isContainer=*/!isForwardRef) {
123 init(isForwardRef, isImplementation);
124 }
125
classofObjCContainerDeclInfo126 static bool classof(const DeclInfo *D) {
127 return Info_ObjCContainer <= D->Kind && D->Kind <= Info_ObjCCategory;
128 }
classofObjCContainerDeclInfo129 static bool classof(const ObjCContainerDeclInfo *D) { return true; }
130
131 private:
initObjCContainerDeclInfo132 void init(bool isForwardRef, bool isImplementation) {
133 if (isForwardRef)
134 ObjCContDeclInfo.kind = CXIdxObjCContainer_ForwardRef;
135 else if (isImplementation)
136 ObjCContDeclInfo.kind = CXIdxObjCContainer_Implementation;
137 else
138 ObjCContDeclInfo.kind = CXIdxObjCContainer_Interface;
139 }
140 };
141
142 struct ObjCInterfaceDeclInfo : public ObjCContainerDeclInfo {
143 CXIdxObjCInterfaceDeclInfo ObjCInterDeclInfo;
144 CXIdxObjCProtocolRefListInfo ObjCProtoListInfo;
145
ObjCInterfaceDeclInfoObjCInterfaceDeclInfo146 ObjCInterfaceDeclInfo(const ObjCInterfaceDecl *D)
147 : ObjCContainerDeclInfo(Info_ObjCInterface,
148 /*isForwardRef=*/false,
149 /*isRedeclaration=*/D->getPreviousDecl() != 0,
150 /*isImplementation=*/false) { }
151
classofObjCInterfaceDeclInfo152 static bool classof(const DeclInfo *D) {
153 return D->Kind == Info_ObjCInterface;
154 }
classofObjCInterfaceDeclInfo155 static bool classof(const ObjCInterfaceDeclInfo *D) { return true; }
156 };
157
158 struct ObjCProtocolDeclInfo : public ObjCContainerDeclInfo {
159 CXIdxObjCProtocolRefListInfo ObjCProtoRefListInfo;
160
ObjCProtocolDeclInfoObjCProtocolDeclInfo161 ObjCProtocolDeclInfo(const ObjCProtocolDecl *D)
162 : ObjCContainerDeclInfo(Info_ObjCProtocol,
163 /*isForwardRef=*/false,
164 /*isRedeclaration=*/D->getPreviousDecl(),
165 /*isImplementation=*/false) { }
166
classofObjCProtocolDeclInfo167 static bool classof(const DeclInfo *D) {
168 return D->Kind == Info_ObjCProtocol;
169 }
classofObjCProtocolDeclInfo170 static bool classof(const ObjCProtocolDeclInfo *D) { return true; }
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 }
classofObjCCategoryDeclInfo186 static bool classof(const ObjCCategoryDeclInfo *D) { return true; }
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 }
classofObjCPropertyDeclInfo200 static bool classof(const ObjCPropertyDeclInfo *D) { return true; }
201 };
202
203 struct CXXClassDeclInfo : public DeclInfo {
204 CXIdxCXXClassDeclInfo CXXClassInfo;
205
CXXClassDeclInfoCXXClassDeclInfo206 CXXClassDeclInfo(bool isRedeclaration, bool isDefinition)
207 : DeclInfo(Info_CXXClass, isRedeclaration, isDefinition, isDefinition) { }
208
classofCXXClassDeclInfo209 static bool classof(const DeclInfo *D) {
210 return D->Kind == Info_CXXClass;
211 }
classofCXXClassDeclInfo212 static bool classof(const CXXClassDeclInfo *D) { return true; }
213 };
214
215 struct AttrInfo : public CXIdxAttrInfo {
216 const Attr *A;
217
AttrInfoAttrInfo218 AttrInfo(CXIdxAttrKind Kind, CXCursor C, CXIdxLoc Loc, const Attr *A) {
219 kind = Kind;
220 cursor = C;
221 loc = Loc;
222 this->A = A;
223 }
224
classofAttrInfo225 static bool classof(const AttrInfo *) { return true; }
226 };
227
228 struct IBOutletCollectionInfo : public AttrInfo {
229 EntityInfo ClassInfo;
230 CXIdxIBOutletCollectionAttrInfo IBCollInfo;
231
IBOutletCollectionInfoIBOutletCollectionInfo232 IBOutletCollectionInfo(CXCursor C, CXIdxLoc Loc, const Attr *A) :
233 AttrInfo(CXIdxAttr_IBOutletCollection, C, Loc, A) {
234 assert(C.kind == CXCursor_IBOutletCollectionAttr);
235 IBCollInfo.objcClass = 0;
236 }
237
238 IBOutletCollectionInfo(const IBOutletCollectionInfo &other);
239
classofIBOutletCollectionInfo240 static bool classof(const AttrInfo *A) {
241 return A->kind == CXIdxAttr_IBOutletCollection;
242 }
classofIBOutletCollectionInfo243 static bool classof(const IBOutletCollectionInfo *D) { return true; }
244 };
245
246 class AttrListInfo {
247 ScratchAlloc SA;
248
249 SmallVector<AttrInfo, 2> Attrs;
250 SmallVector<IBOutletCollectionInfo, 2> IBCollAttrs;
251 SmallVector<CXIdxAttrInfo *, 2> CXAttrs;
252 unsigned ref_cnt;
253
254 AttrListInfo(const AttrListInfo&); // DO NOT IMPLEMENT
255 void operator=(const AttrListInfo&); // DO NOT IMPLEMENT
256 public:
257 AttrListInfo(const Decl *D, IndexingContext &IdxCtx);
258
259 static IntrusiveRefCntPtr<AttrListInfo> create(const Decl *D,
260 IndexingContext &IdxCtx);
261
getAttrs()262 const CXIdxAttrInfo *const *getAttrs() const {
263 if (CXAttrs.empty())
264 return 0;
265 return CXAttrs.data();
266 }
getNumAttrs()267 unsigned getNumAttrs() const { return (unsigned)CXAttrs.size(); }
268
269 /// \brief Retain/Release only useful when we allocate a AttrListInfo from the
270 /// BumpPtrAllocator, and not from the stack; so that we keep a pointer
271 // in the EntityInfo
Retain()272 void Retain() { ++ref_cnt; }
Release()273 void Release() {
274 assert (ref_cnt > 0 && "Reference count is already zero.");
275 if (--ref_cnt == 0) {
276 // Memory is allocated from a BumpPtrAllocator, no need to delete it.
277 this->~AttrListInfo();
278 }
279 }
280 };
281
282 struct RefFileOccurence {
283 const FileEntry *File;
284 const Decl *Dcl;
285
RefFileOccurenceRefFileOccurence286 RefFileOccurence(const FileEntry *File, const Decl *Dcl)
287 : File(File), Dcl(Dcl) { }
288 };
289
290 class IndexingContext {
291 ASTContext *Ctx;
292 CXClientData ClientData;
293 IndexerCallbacks &CB;
294 unsigned IndexOptions;
295 CXTranslationUnit CXTU;
296
297 typedef llvm::DenseMap<const FileEntry *, CXIdxClientFile> FileMapTy;
298 typedef llvm::DenseMap<const DeclContext *, CXIdxClientContainer>
299 ContainerMapTy;
300 typedef llvm::DenseMap<const Decl *, CXIdxClientEntity> EntityMapTy;
301
302 FileMapTy FileMap;
303 ContainerMapTy ContainerMap;
304 EntityMapTy EntityMap;
305
306 llvm::DenseSet<RefFileOccurence> RefFileOccurences;
307
308 std::deque<DeclGroupRef> TUDeclsInObjCContainer;
309
310 llvm::BumpPtrAllocator StrScratch;
311 unsigned StrAdapterCount;
312 friend class ScratchAlloc;
313
314 struct ObjCProtocolListInfo {
315 SmallVector<CXIdxObjCProtocolRefInfo, 4> ProtInfos;
316 SmallVector<EntityInfo, 4> ProtEntities;
317 SmallVector<CXIdxObjCProtocolRefInfo *, 4> Prots;
318
getListInfoObjCProtocolListInfo319 CXIdxObjCProtocolRefListInfo getListInfo() const {
320 CXIdxObjCProtocolRefListInfo Info = { Prots.data(),
321 (unsigned)Prots.size() };
322 return Info;
323 }
324
325 ObjCProtocolListInfo(const ObjCProtocolList &ProtList,
326 IndexingContext &IdxCtx,
327 ScratchAlloc &SA);
328 };
329
330 struct CXXBasesListInfo {
331 SmallVector<CXIdxBaseClassInfo, 4> BaseInfos;
332 SmallVector<EntityInfo, 4> BaseEntities;
333 SmallVector<CXIdxBaseClassInfo *, 4> CXBases;
334
getBasesCXXBasesListInfo335 const CXIdxBaseClassInfo *const *getBases() const {
336 return CXBases.data();
337 }
getNumBasesCXXBasesListInfo338 unsigned getNumBases() const { return (unsigned)CXBases.size(); }
339
340 CXXBasesListInfo(const CXXRecordDecl *D,
341 IndexingContext &IdxCtx, ScratchAlloc &SA);
342
343 private:
344 SourceLocation getBaseLoc(const CXXBaseSpecifier &Base) const;
345 };
346
347 friend class AttrListInfo;
348
349 public:
IndexingContext(CXClientData clientData,IndexerCallbacks & indexCallbacks,unsigned indexOptions,CXTranslationUnit cxTU)350 IndexingContext(CXClientData clientData, IndexerCallbacks &indexCallbacks,
351 unsigned indexOptions, CXTranslationUnit cxTU)
352 : Ctx(0), ClientData(clientData), CB(indexCallbacks),
353 IndexOptions(indexOptions), CXTU(cxTU),
354 StrScratch(/*size=*/1024), StrAdapterCount(0) { }
355
getASTContext()356 ASTContext &getASTContext() const { return *Ctx; }
357
358 void setASTContext(ASTContext &ctx);
359 void setPreprocessor(Preprocessor &PP);
360
shouldSuppressRefs()361 bool shouldSuppressRefs() const {
362 return IndexOptions & CXIndexOpt_SuppressRedundantRefs;
363 }
364
shouldIndexFunctionLocalSymbols()365 bool shouldIndexFunctionLocalSymbols() const {
366 return IndexOptions & CXIndexOpt_IndexFunctionLocalSymbols;
367 }
368
shouldIndexImplicitTemplateInsts()369 bool shouldIndexImplicitTemplateInsts() const {
370 return IndexOptions & CXIndexOpt_IndexImplicitTemplateInstantiations;
371 }
372
373 bool shouldAbort();
374
hasDiagnosticCallback()375 bool hasDiagnosticCallback() const { return CB.diagnostic; }
376
377 void enteredMainFile(const FileEntry *File);
378
379 void ppIncludedFile(SourceLocation hashLoc,
380 StringRef filename, const FileEntry *File,
381 bool isImport, bool isAngled);
382
383 void startedTranslationUnit();
384
385 void indexDecl(const Decl *D);
386
387 void indexTagDecl(const TagDecl *D);
388
389 void indexTypeSourceInfo(TypeSourceInfo *TInfo, const NamedDecl *Parent,
390 const DeclContext *DC = 0);
391
392 void indexTypeLoc(TypeLoc TL, const NamedDecl *Parent,
393 const DeclContext *DC = 0);
394
395 void indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
396 const NamedDecl *Parent,
397 const DeclContext *DC = 0);
398
399 void indexDeclContext(const DeclContext *DC);
400
401 void indexBody(const Stmt *S, const NamedDecl *Parent,
402 const DeclContext *DC = 0);
403
404 void handleDiagnosticSet(CXDiagnosticSet CXDiagSet);
405
406 bool handleFunction(const FunctionDecl *FD);
407
408 bool handleVar(const VarDecl *D);
409
410 bool handleField(const FieldDecl *D);
411
412 bool handleEnumerator(const EnumConstantDecl *D);
413
414 bool handleTagDecl(const TagDecl *D);
415
416 bool handleTypedefName(const TypedefNameDecl *D);
417
418 bool handleObjCInterface(const ObjCInterfaceDecl *D);
419 bool handleObjCImplementation(const ObjCImplementationDecl *D);
420
421 bool handleObjCProtocol(const ObjCProtocolDecl *D);
422
423 bool handleObjCCategory(const ObjCCategoryDecl *D);
424 bool handleObjCCategoryImpl(const ObjCCategoryImplDecl *D);
425
426 bool handleObjCMethod(const ObjCMethodDecl *D);
427
428 bool handleSynthesizedObjCProperty(const ObjCPropertyImplDecl *D);
429 bool handleSynthesizedObjCMethod(const ObjCMethodDecl *D, SourceLocation Loc,
430 const DeclContext *LexicalDC);
431
432 bool handleObjCProperty(const ObjCPropertyDecl *D);
433
434 bool handleNamespace(const NamespaceDecl *D);
435
436 bool handleClassTemplate(const ClassTemplateDecl *D);
437 bool handleFunctionTemplate(const FunctionTemplateDecl *D);
438 bool handleTypeAliasTemplate(const TypeAliasTemplateDecl *D);
439
440 bool handleReference(const NamedDecl *D, SourceLocation Loc, CXCursor Cursor,
441 const NamedDecl *Parent,
442 const DeclContext *DC,
443 const Expr *E = 0,
444 CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct);
445
446 bool handleReference(const NamedDecl *D, SourceLocation Loc,
447 const NamedDecl *Parent,
448 const DeclContext *DC,
449 const Expr *E = 0,
450 CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct);
451
452 bool isNotFromSourceFile(SourceLocation Loc) const;
453
454 void indexTopLevelDecl(Decl *D);
455 void indexTUDeclsInObjCContainer();
456 void indexDeclGroupRef(DeclGroupRef DG);
457
addTUDeclInObjCContainer(DeclGroupRef DG)458 void addTUDeclInObjCContainer(DeclGroupRef DG) {
459 TUDeclsInObjCContainer.push_back(DG);
460 }
461
462 void translateLoc(SourceLocation Loc, CXIdxClientFile *indexFile, CXFile *file,
463 unsigned *line, unsigned *column, unsigned *offset);
464
465 CXIdxClientContainer getClientContainerForDC(const DeclContext *DC) const;
466 void addContainerInMap(const DeclContext *DC, CXIdxClientContainer container);
467
468 CXIdxClientEntity getClientEntity(const Decl *D) const;
469 void setClientEntity(const Decl *D, CXIdxClientEntity client);
470
471 static bool isTemplateImplicitInstantiation(const Decl *D);
472
473 private:
474 bool handleDecl(const NamedDecl *D,
475 SourceLocation Loc, CXCursor Cursor,
476 DeclInfo &DInfo,
477 const DeclContext *LexicalDC = 0);
478
479 bool handleObjCContainer(const ObjCContainerDecl *D,
480 SourceLocation Loc, CXCursor Cursor,
481 ObjCContainerDeclInfo &ContDInfo);
482
483 bool handleCXXRecordDecl(const CXXRecordDecl *RD, const NamedDecl *OrigD);
484
485 bool markEntityOccurrenceInFile(const NamedDecl *D, SourceLocation Loc);
486
487 const NamedDecl *getEntityDecl(const NamedDecl *D) const;
488
489 const DeclContext *getEntityContainer(const Decl *D) const;
490
491 CXIdxClientFile getIndexFile(const FileEntry *File);
492
493 CXIdxLoc getIndexLoc(SourceLocation Loc) const;
494
495 void getEntityInfo(const NamedDecl *D,
496 EntityInfo &EntityInfo,
497 ScratchAlloc &SA);
498
499 void getContainerInfo(const DeclContext *DC, ContainerInfo &ContInfo);
500
getCursor(const Decl * D)501 CXCursor getCursor(const Decl *D) {
502 return cxcursor::MakeCXCursor(const_cast<Decl*>(D), CXTU);
503 }
504
505 CXCursor getRefCursor(const NamedDecl *D, SourceLocation Loc);
506
507 static bool shouldIgnoreIfImplicit(const Decl *D);
508 };
509
ScratchAlloc(IndexingContext & idxCtx)510 inline ScratchAlloc::ScratchAlloc(IndexingContext &idxCtx) : IdxCtx(idxCtx) {
511 ++IdxCtx.StrAdapterCount;
512 }
ScratchAlloc(const ScratchAlloc & SA)513 inline ScratchAlloc::ScratchAlloc(const ScratchAlloc &SA) : IdxCtx(SA.IdxCtx) {
514 ++IdxCtx.StrAdapterCount;
515 }
516
~ScratchAlloc()517 inline ScratchAlloc::~ScratchAlloc() {
518 --IdxCtx.StrAdapterCount;
519 if (IdxCtx.StrAdapterCount == 0)
520 IdxCtx.StrScratch.Reset();
521 }
522
523 template <typename T>
allocate()524 inline T *ScratchAlloc::allocate() {
525 return IdxCtx.StrScratch.Allocate<T>();
526 }
527
528 }} // end clang::cxindex
529
530 namespace llvm {
531 /// Define DenseMapInfo so that FileID's can be used as keys in DenseMap and
532 /// DenseSets.
533 template <>
534 struct DenseMapInfo<clang::cxindex::RefFileOccurence> {
535 static inline clang::cxindex::RefFileOccurence getEmptyKey() {
536 return clang::cxindex::RefFileOccurence(0, 0);
537 }
538
539 static inline clang::cxindex::RefFileOccurence getTombstoneKey() {
540 return clang::cxindex::RefFileOccurence((const clang::FileEntry *)~0,
541 (const clang::Decl *)~0);
542 }
543
544 static unsigned getHashValue(clang::cxindex::RefFileOccurence S) {
545 typedef std::pair<const clang::FileEntry *, const clang::Decl *> PairTy;
546 return DenseMapInfo<PairTy>::getHashValue(PairTy(S.File, S.Dcl));
547 }
548
549 static bool isEqual(clang::cxindex::RefFileOccurence LHS,
550 clang::cxindex::RefFileOccurence RHS) {
551 return LHS.File == RHS.File && LHS.Dcl == RHS.Dcl;
552 }
553 };
554 }
555