• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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