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