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