]> granicus.if.org Git - clang/blob - tools/libclang/IndexingContext.h
Header guard canonicalization, clang part.
[clang] / tools / libclang / IndexingContext.h
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
54   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
87   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   }
97   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
113   ObjCContainerDeclInfo(bool isForwardRef,
114                         bool isRedeclaration,
115                         bool isImplementation)
116     : DeclInfo(Info_ObjCContainer, isRedeclaration,
117                /*isDefinition=*/!isForwardRef, /*isContainer=*/!isForwardRef) {
118     init(isForwardRef, isImplementation);
119   }
120   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
129   static bool classof(const DeclInfo *D) {
130     return Info_ObjCContainer <= D->Kind && D->Kind <= Info_ObjCCategory;
131   }
132
133 private:
134   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
148   ObjCInterfaceDeclInfo(const ObjCInterfaceDecl *D)
149     : ObjCContainerDeclInfo(Info_ObjCInterface,
150                             /*isForwardRef=*/false,
151                             /*isRedeclaration=*/D->getPreviousDecl() != nullptr,
152                             /*isImplementation=*/false) { }
153
154   static bool classof(const DeclInfo *D) {
155     return D->Kind == Info_ObjCInterface;
156   }
157 };
158
159 struct ObjCProtocolDeclInfo : public ObjCContainerDeclInfo {
160   CXIdxObjCProtocolRefListInfo ObjCProtoRefListInfo;
161
162   ObjCProtocolDeclInfo(const ObjCProtocolDecl *D)
163     : ObjCContainerDeclInfo(Info_ObjCProtocol,
164                             /*isForwardRef=*/false,
165                             /*isRedeclaration=*/D->getPreviousDecl(),
166                             /*isImplementation=*/false) { }
167
168   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
177   explicit ObjCCategoryDeclInfo(bool isImplementation)
178     : ObjCContainerDeclInfo(Info_ObjCCategory,
179                             /*isForwardRef=*/false,
180                             /*isRedeclaration=*/isImplementation,
181                             /*isImplementation=*/isImplementation) { }
182
183   static bool classof(const DeclInfo *D) {
184     return D->Kind == Info_ObjCCategory;
185   }
186 };
187
188 struct ObjCPropertyDeclInfo : public DeclInfo {
189   CXIdxObjCPropertyDeclInfo ObjCPropDeclInfo;
190
191   ObjCPropertyDeclInfo()
192     : DeclInfo(Info_ObjCProperty,
193                /*isRedeclaration=*/false, /*isDefinition=*/false,
194                /*isContainer=*/false) { }
195
196   static bool classof(const DeclInfo *D) {
197     return D->Kind == Info_ObjCProperty;
198   }
199 };
200
201 struct CXXClassDeclInfo : public DeclInfo {
202   CXIdxCXXClassDeclInfo CXXClassInfo;
203
204   CXXClassDeclInfo(bool isRedeclaration, bool isDefinition)
205     : DeclInfo(Info_CXXClass, isRedeclaration, isDefinition, isDefinition) { }
206
207   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
215   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
227   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
235   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 &) LLVM_DELETED_FUNCTION;
249   void operator=(const AttrListInfo &) LLVM_DELETED_FUNCTION;
250 public:
251   AttrListInfo(const Decl *D, IndexingContext &IdxCtx);
252
253   static IntrusiveRefCntPtr<AttrListInfo> create(const Decl *D,
254                                                  IndexingContext &IdxCtx);
255
256   const CXIdxAttrInfo *const *getAttrs() const {
257     if (CXAttrs.empty())
258       return nullptr;
259     return CXAttrs.data();
260   }
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
266   void Retain() { ++ref_cnt; }
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
306     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
322     const CXIdxBaseClassInfo *const *getBases() const {
323       return CXBases.data();
324     }
325     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:
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
343   ASTContext &getASTContext() const { return *Ctx; }
344
345   void setASTContext(ASTContext &ctx);
346   void setPreprocessor(Preprocessor &PP);
347
348   bool shouldSuppressRefs() const {
349     return IndexOptions & CXIndexOpt_SuppressRedundantRefs;
350   }
351
352   bool shouldIndexFunctionLocalSymbols() const {
353     return IndexOptions & CXIndexOpt_IndexFunctionLocalSymbols;
354   }
355
356   bool shouldIndexImplicitTemplateInsts() const {
357     return IndexOptions & CXIndexOpt_IndexImplicitTemplateInstantiations;
358   }
359
360   static bool isFunctionLocalDecl(const Decl *D);
361
362   bool shouldAbort();
363
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
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
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
504 inline ScratchAlloc::ScratchAlloc(IndexingContext &idxCtx) : IdxCtx(idxCtx) {
505   ++IdxCtx.StrAdapterCount;
506 }
507 inline ScratchAlloc::ScratchAlloc(const ScratchAlloc &SA) : IdxCtx(SA.IdxCtx) {
508   ++IdxCtx.StrAdapterCount;
509 }
510
511 inline ScratchAlloc::~ScratchAlloc() {
512   --IdxCtx.StrAdapterCount;
513   if (IdxCtx.StrAdapterCount == 0)
514     IdxCtx.StrScratch.Reset();
515 }
516
517 template <typename T>
518 inline T *ScratchAlloc::allocate() {
519   return IdxCtx.StrScratch.Allocate<T>();
520 }
521
522 }} // end clang::cxindex
523
524 #endif