• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "CXCursor.h"
11 #include "Index_Internal.h"
12 #include "clang/AST/DeclGroup.h"
13 #include "clang/AST/DeclObjC.h"
14 #include "llvm/ADT/DenseSet.h"
15 #include <deque>
16 
17 namespace clang {
18   class FileEntry;
19   class MSPropertyDecl;
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     flags = 0;
93   }
DeclInfoDeclInfo94   DeclInfo(DInfoKind K,
95            bool isRedeclaration, bool isDefinition, bool isContainer)
96     : Kind(K) {
97     this->isRedeclaration = isRedeclaration;
98     this->isDefinition = isDefinition;
99     this->isContainer = isContainer;
100     attributes = 0;
101     numAttributes = 0;
102     declAsContainer = semanticContainer = lexicalContainer = 0;
103     flags = 0;
104   }
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   }
129 
130 private:
initObjCContainerDeclInfo131   void init(bool isForwardRef, bool isImplementation) {
132     if (isForwardRef)
133       ObjCContDeclInfo.kind = CXIdxObjCContainer_ForwardRef;
134     else if (isImplementation)
135       ObjCContDeclInfo.kind = CXIdxObjCContainer_Implementation;
136     else
137       ObjCContDeclInfo.kind = CXIdxObjCContainer_Interface;
138   }
139 };
140 
141 struct ObjCInterfaceDeclInfo : public ObjCContainerDeclInfo {
142   CXIdxObjCInterfaceDeclInfo ObjCInterDeclInfo;
143   CXIdxObjCProtocolRefListInfo ObjCProtoListInfo;
144 
ObjCInterfaceDeclInfoObjCInterfaceDeclInfo145   ObjCInterfaceDeclInfo(const ObjCInterfaceDecl *D)
146     : ObjCContainerDeclInfo(Info_ObjCInterface,
147                             /*isForwardRef=*/false,
148                           /*isRedeclaration=*/D->getPreviousDecl() != 0,
149                             /*isImplementation=*/false) { }
150 
classofObjCInterfaceDeclInfo151   static bool classof(const DeclInfo *D) {
152     return D->Kind == Info_ObjCInterface;
153   }
154 };
155 
156 struct ObjCProtocolDeclInfo : public ObjCContainerDeclInfo {
157   CXIdxObjCProtocolRefListInfo ObjCProtoRefListInfo;
158 
ObjCProtocolDeclInfoObjCProtocolDeclInfo159   ObjCProtocolDeclInfo(const ObjCProtocolDecl *D)
160     : ObjCContainerDeclInfo(Info_ObjCProtocol,
161                             /*isForwardRef=*/false,
162                             /*isRedeclaration=*/D->getPreviousDecl(),
163                             /*isImplementation=*/false) { }
164 
classofObjCProtocolDeclInfo165   static bool classof(const DeclInfo *D) {
166     return D->Kind == Info_ObjCProtocol;
167   }
168 };
169 
170 struct ObjCCategoryDeclInfo : public ObjCContainerDeclInfo {
171   CXIdxObjCCategoryDeclInfo ObjCCatDeclInfo;
172   CXIdxObjCProtocolRefListInfo ObjCProtoListInfo;
173 
ObjCCategoryDeclInfoObjCCategoryDeclInfo174   explicit ObjCCategoryDeclInfo(bool isImplementation)
175     : ObjCContainerDeclInfo(Info_ObjCCategory,
176                             /*isForwardRef=*/false,
177                             /*isRedeclaration=*/isImplementation,
178                             /*isImplementation=*/isImplementation) { }
179 
classofObjCCategoryDeclInfo180   static bool classof(const DeclInfo *D) {
181     return D->Kind == Info_ObjCCategory;
182   }
183 };
184 
185 struct ObjCPropertyDeclInfo : public DeclInfo {
186   CXIdxObjCPropertyDeclInfo ObjCPropDeclInfo;
187 
ObjCPropertyDeclInfoObjCPropertyDeclInfo188   ObjCPropertyDeclInfo()
189     : DeclInfo(Info_ObjCProperty,
190                /*isRedeclaration=*/false, /*isDefinition=*/false,
191                /*isContainer=*/false) { }
192 
classofObjCPropertyDeclInfo193   static bool classof(const DeclInfo *D) {
194     return D->Kind == Info_ObjCProperty;
195   }
196 };
197 
198 struct CXXClassDeclInfo : public DeclInfo {
199   CXIdxCXXClassDeclInfo CXXClassInfo;
200 
CXXClassDeclInfoCXXClassDeclInfo201   CXXClassDeclInfo(bool isRedeclaration, bool isDefinition)
202     : DeclInfo(Info_CXXClass, isRedeclaration, isDefinition, isDefinition) { }
203 
classofCXXClassDeclInfo204   static bool classof(const DeclInfo *D) {
205     return D->Kind == Info_CXXClass;
206   }
207 };
208 
209 struct AttrInfo : public CXIdxAttrInfo {
210   const Attr *A;
211 
AttrInfoAttrInfo212   AttrInfo(CXIdxAttrKind Kind, CXCursor C, CXIdxLoc Loc, const Attr *A) {
213     kind = Kind;
214     cursor = C;
215     loc = Loc;
216     this->A = A;
217   }
218 };
219 
220 struct IBOutletCollectionInfo : public AttrInfo {
221   EntityInfo ClassInfo;
222   CXIdxIBOutletCollectionAttrInfo IBCollInfo;
223 
IBOutletCollectionInfoIBOutletCollectionInfo224   IBOutletCollectionInfo(CXCursor C, CXIdxLoc Loc, const Attr *A) :
225     AttrInfo(CXIdxAttr_IBOutletCollection, C, Loc, A) {
226     assert(C.kind == CXCursor_IBOutletCollectionAttr);
227     IBCollInfo.objcClass = 0;
228   }
229 
230   IBOutletCollectionInfo(const IBOutletCollectionInfo &other);
231 
classofIBOutletCollectionInfo232   static bool classof(const AttrInfo *A) {
233     return A->kind == CXIdxAttr_IBOutletCollection;
234   }
235 };
236 
237 class AttrListInfo {
238   ScratchAlloc SA;
239 
240   SmallVector<AttrInfo, 2> Attrs;
241   SmallVector<IBOutletCollectionInfo, 2> IBCollAttrs;
242   SmallVector<CXIdxAttrInfo *, 2> CXAttrs;
243   unsigned ref_cnt;
244 
245   AttrListInfo(const AttrListInfo &) LLVM_DELETED_FUNCTION;
246   void operator=(const AttrListInfo &) LLVM_DELETED_FUNCTION;
247 public:
248   AttrListInfo(const Decl *D, IndexingContext &IdxCtx);
249 
250   static IntrusiveRefCntPtr<AttrListInfo> create(const Decl *D,
251                                                  IndexingContext &IdxCtx);
252 
getAttrs()253   const CXIdxAttrInfo *const *getAttrs() const {
254     if (CXAttrs.empty())
255       return 0;
256     return CXAttrs.data();
257   }
getNumAttrs()258   unsigned getNumAttrs() const { return (unsigned)CXAttrs.size(); }
259 
260   /// \brief Retain/Release only useful when we allocate a AttrListInfo from the
261   /// BumpPtrAllocator, and not from the stack; so that we keep a pointer
262   // in the EntityInfo
Retain()263   void Retain() { ++ref_cnt; }
Release()264   void Release() {
265     assert (ref_cnt > 0 && "Reference count is already zero.");
266     if (--ref_cnt == 0) {
267       // Memory is allocated from a BumpPtrAllocator, no need to delete it.
268       this->~AttrListInfo();
269     }
270   }
271 };
272 
273 struct RefFileOccurence {
274   const FileEntry *File;
275   const Decl *Dcl;
276 
RefFileOccurenceRefFileOccurence277   RefFileOccurence(const FileEntry *File, const Decl *Dcl)
278     : File(File), Dcl(Dcl) { }
279 };
280 
281 class IndexingContext {
282   ASTContext *Ctx;
283   CXClientData ClientData;
284   IndexerCallbacks &CB;
285   unsigned IndexOptions;
286   CXTranslationUnit CXTU;
287 
288   typedef llvm::DenseMap<const FileEntry *, CXIdxClientFile> FileMapTy;
289   typedef llvm::DenseMap<const DeclContext *, CXIdxClientContainer>
290     ContainerMapTy;
291   typedef llvm::DenseMap<const Decl *, CXIdxClientEntity> EntityMapTy;
292 
293   FileMapTy FileMap;
294   ContainerMapTy ContainerMap;
295   EntityMapTy EntityMap;
296 
297   llvm::DenseSet<RefFileOccurence> RefFileOccurences;
298 
299   std::deque<DeclGroupRef> TUDeclsInObjCContainer;
300 
301   llvm::BumpPtrAllocator StrScratch;
302   unsigned StrAdapterCount;
303   friend class ScratchAlloc;
304 
305   struct ObjCProtocolListInfo {
306     SmallVector<CXIdxObjCProtocolRefInfo, 4> ProtInfos;
307     SmallVector<EntityInfo, 4> ProtEntities;
308     SmallVector<CXIdxObjCProtocolRefInfo *, 4> Prots;
309 
getListInfoObjCProtocolListInfo310     CXIdxObjCProtocolRefListInfo getListInfo() const {
311       CXIdxObjCProtocolRefListInfo Info = { Prots.data(),
312                                             (unsigned)Prots.size() };
313       return Info;
314     }
315 
316     ObjCProtocolListInfo(const ObjCProtocolList &ProtList,
317                          IndexingContext &IdxCtx,
318                          ScratchAlloc &SA);
319   };
320 
321   struct CXXBasesListInfo {
322     SmallVector<CXIdxBaseClassInfo, 4> BaseInfos;
323     SmallVector<EntityInfo, 4> BaseEntities;
324     SmallVector<CXIdxBaseClassInfo *, 4> CXBases;
325 
getBasesCXXBasesListInfo326     const CXIdxBaseClassInfo *const *getBases() const {
327       return CXBases.data();
328     }
getNumBasesCXXBasesListInfo329     unsigned getNumBases() const { return (unsigned)CXBases.size(); }
330 
331     CXXBasesListInfo(const CXXRecordDecl *D,
332                      IndexingContext &IdxCtx, ScratchAlloc &SA);
333 
334   private:
335     SourceLocation getBaseLoc(const CXXBaseSpecifier &Base) const;
336   };
337 
338   friend class AttrListInfo;
339 
340 public:
IndexingContext(CXClientData clientData,IndexerCallbacks & indexCallbacks,unsigned indexOptions,CXTranslationUnit cxTU)341   IndexingContext(CXClientData clientData, IndexerCallbacks &indexCallbacks,
342                   unsigned indexOptions, CXTranslationUnit cxTU)
343     : Ctx(0), ClientData(clientData), CB(indexCallbacks),
344       IndexOptions(indexOptions), CXTU(cxTU),
345       StrScratch(/*size=*/1024), StrAdapterCount(0) { }
346 
getASTContext()347   ASTContext &getASTContext() const { return *Ctx; }
348 
349   void setASTContext(ASTContext &ctx);
350   void setPreprocessor(Preprocessor &PP);
351 
shouldSuppressRefs()352   bool shouldSuppressRefs() const {
353     return IndexOptions & CXIndexOpt_SuppressRedundantRefs;
354   }
355 
shouldIndexFunctionLocalSymbols()356   bool shouldIndexFunctionLocalSymbols() const {
357     return IndexOptions & CXIndexOpt_IndexFunctionLocalSymbols;
358   }
359 
shouldIndexImplicitTemplateInsts()360   bool shouldIndexImplicitTemplateInsts() const {
361     return IndexOptions & CXIndexOpt_IndexImplicitTemplateInstantiations;
362   }
363 
364   static bool isFunctionLocalDecl(const Decl *D);
365 
366   bool shouldAbort();
367 
hasDiagnosticCallback()368   bool hasDiagnosticCallback() const { return CB.diagnostic; }
369 
370   void enteredMainFile(const FileEntry *File);
371 
372   void ppIncludedFile(SourceLocation hashLoc,
373                       StringRef filename, const FileEntry *File,
374                       bool isImport, bool isAngled, bool isModuleImport);
375 
376   void importedModule(const ImportDecl *ImportD);
377   void importedPCH(const FileEntry *File);
378 
379   void startedTranslationUnit();
380 
381   void indexDecl(const Decl *D);
382 
383   void indexTagDecl(const TagDecl *D);
384 
385   void indexTypeSourceInfo(TypeSourceInfo *TInfo, const NamedDecl *Parent,
386                            const DeclContext *DC = 0);
387 
388   void indexTypeLoc(TypeLoc TL, const NamedDecl *Parent,
389                     const DeclContext *DC = 0);
390 
391   void indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
392                                    const NamedDecl *Parent,
393                                    const DeclContext *DC = 0);
394 
395   void indexDeclContext(const DeclContext *DC);
396 
397   void indexBody(const Stmt *S, const NamedDecl *Parent,
398                  const DeclContext *DC = 0);
399 
400   void handleDiagnosticSet(CXDiagnosticSet CXDiagSet);
401 
402   bool handleFunction(const FunctionDecl *FD);
403 
404   bool handleVar(const VarDecl *D);
405 
406   bool handleField(const FieldDecl *D);
407 
408   bool handleMSProperty(const MSPropertyDecl *D);
409 
410   bool handleEnumerator(const EnumConstantDecl *D);
411 
412   bool handleTagDecl(const TagDecl *D);
413 
414   bool handleTypedefName(const TypedefNameDecl *D);
415 
416   bool handleObjCInterface(const ObjCInterfaceDecl *D);
417   bool handleObjCImplementation(const ObjCImplementationDecl *D);
418 
419   bool handleObjCProtocol(const ObjCProtocolDecl *D);
420 
421   bool handleObjCCategory(const ObjCCategoryDecl *D);
422   bool handleObjCCategoryImpl(const ObjCCategoryImplDecl *D);
423 
424   bool handleObjCMethod(const ObjCMethodDecl *D);
425 
426   bool handleSynthesizedObjCProperty(const ObjCPropertyImplDecl *D);
427   bool handleSynthesizedObjCMethod(const ObjCMethodDecl *D, SourceLocation Loc,
428                                    const DeclContext *LexicalDC);
429 
430   bool handleObjCProperty(const ObjCPropertyDecl *D);
431 
432   bool handleNamespace(const NamespaceDecl *D);
433 
434   bool handleClassTemplate(const ClassTemplateDecl *D);
435   bool handleFunctionTemplate(const FunctionTemplateDecl *D);
436   bool handleTypeAliasTemplate(const TypeAliasTemplateDecl *D);
437 
438   bool handleReference(const NamedDecl *D, SourceLocation Loc, CXCursor Cursor,
439                        const NamedDecl *Parent,
440                        const DeclContext *DC,
441                        const Expr *E = 0,
442                        CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct);
443 
444   bool handleReference(const NamedDecl *D, SourceLocation Loc,
445                        const NamedDecl *Parent,
446                        const DeclContext *DC,
447                        const Expr *E = 0,
448                        CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct);
449 
450   bool isNotFromSourceFile(SourceLocation Loc) const;
451 
452   void indexTopLevelDecl(const Decl *D);
453   void indexTUDeclsInObjCContainer();
454   void indexDeclGroupRef(DeclGroupRef DG);
455 
addTUDeclInObjCContainer(DeclGroupRef DG)456   void addTUDeclInObjCContainer(DeclGroupRef DG) {
457     TUDeclsInObjCContainer.push_back(DG);
458   }
459 
460   void translateLoc(SourceLocation Loc, CXIdxClientFile *indexFile, CXFile *file,
461                     unsigned *line, unsigned *column, unsigned *offset);
462 
463   CXIdxClientContainer getClientContainerForDC(const DeclContext *DC) const;
464   void addContainerInMap(const DeclContext *DC, CXIdxClientContainer container);
465 
466   CXIdxClientEntity getClientEntity(const Decl *D) const;
467   void setClientEntity(const Decl *D, CXIdxClientEntity client);
468 
469   static bool isTemplateImplicitInstantiation(const Decl *D);
470 
471 private:
472   bool handleDecl(const NamedDecl *D,
473                   SourceLocation Loc, CXCursor Cursor,
474                   DeclInfo &DInfo,
475                   const DeclContext *LexicalDC = 0);
476 
477   bool handleObjCContainer(const ObjCContainerDecl *D,
478                            SourceLocation Loc, CXCursor Cursor,
479                            ObjCContainerDeclInfo &ContDInfo);
480 
481   bool handleCXXRecordDecl(const CXXRecordDecl *RD, const NamedDecl *OrigD);
482 
483   bool markEntityOccurrenceInFile(const NamedDecl *D, SourceLocation Loc);
484 
485   const NamedDecl *getEntityDecl(const NamedDecl *D) const;
486 
487   const DeclContext *getEntityContainer(const Decl *D) const;
488 
489   CXIdxClientFile getIndexFile(const FileEntry *File);
490 
491   CXIdxLoc getIndexLoc(SourceLocation Loc) const;
492 
493   void getEntityInfo(const NamedDecl *D,
494                      EntityInfo &EntityInfo,
495                      ScratchAlloc &SA);
496 
497   void getContainerInfo(const DeclContext *DC, ContainerInfo &ContInfo);
498 
getCursor(const Decl * D)499   CXCursor getCursor(const Decl *D) {
500     return cxcursor::MakeCXCursor(D, CXTU);
501   }
502 
503   CXCursor getRefCursor(const NamedDecl *D, SourceLocation Loc);
504 
505   static bool shouldIgnoreIfImplicit(const Decl *D);
506 };
507 
ScratchAlloc(IndexingContext & idxCtx)508 inline ScratchAlloc::ScratchAlloc(IndexingContext &idxCtx) : IdxCtx(idxCtx) {
509   ++IdxCtx.StrAdapterCount;
510 }
ScratchAlloc(const ScratchAlloc & SA)511 inline ScratchAlloc::ScratchAlloc(const ScratchAlloc &SA) : IdxCtx(SA.IdxCtx) {
512   ++IdxCtx.StrAdapterCount;
513 }
514 
~ScratchAlloc()515 inline ScratchAlloc::~ScratchAlloc() {
516   --IdxCtx.StrAdapterCount;
517   if (IdxCtx.StrAdapterCount == 0)
518     IdxCtx.StrScratch.Reset();
519 }
520 
521 template <typename T>
allocate()522 inline T *ScratchAlloc::allocate() {
523   return IdxCtx.StrScratch.Allocate<T>();
524 }
525 
526 }} // end clang::cxindex
527 
528 namespace llvm {
529   /// Define DenseMapInfo so that FileID's can be used as keys in DenseMap and
530   /// DenseSets.
531   template <>
532   struct DenseMapInfo<clang::cxindex::RefFileOccurence> {
533     static inline clang::cxindex::RefFileOccurence getEmptyKey() {
534       return clang::cxindex::RefFileOccurence(0, 0);
535     }
536 
537     static inline clang::cxindex::RefFileOccurence getTombstoneKey() {
538       return clang::cxindex::RefFileOccurence((const clang::FileEntry *)~0,
539                                               (const clang::Decl *)~0);
540     }
541 
542     static unsigned getHashValue(clang::cxindex::RefFileOccurence S) {
543       typedef std::pair<const clang::FileEntry *, const clang::Decl *> PairTy;
544       return DenseMapInfo<PairTy>::getHashValue(PairTy(S.File, S.Dcl));
545     }
546 
547     static bool isEqual(clang::cxindex::RefFileOccurence LHS,
548                         clang::cxindex::RefFileOccurence RHS) {
549       return LHS.File == RHS.File && LHS.Dcl == RHS.Dcl;
550     }
551   };
552 }
553