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
20namespace clang {
21  class FileEntry;
22  class MSPropertyDecl;
23  class ObjCPropertyDecl;
24  class ClassTemplateDecl;
25  class FunctionTemplateDecl;
26  class TypeAliasTemplateDecl;
27  class ClassTemplateSpecializationDecl;
28
29namespace cxindex {
30  class IndexingContext;
31  class AttrListInfo;
32
33class ScratchAlloc {
34  IndexingContext &IdxCtx;
35
36public:
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
49struct 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
61struct ContainerInfo : public CXIdxContainerInfo {
62  const DeclContext *DC;
63  IndexingContext *IndexCtx;
64};
65
66struct 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
110struct 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
133private:
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
144struct 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
159struct 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
173struct 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
188struct 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
201struct 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
212struct 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
223struct 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
240class 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;
250public:
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
276class 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
336public:
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
467private:
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
504inline ScratchAlloc::ScratchAlloc(IndexingContext &idxCtx) : IdxCtx(idxCtx) {
505  ++IdxCtx.StrAdapterCount;
506}
507inline ScratchAlloc::ScratchAlloc(const ScratchAlloc &SA) : IdxCtx(SA.IdxCtx) {
508  ++IdxCtx.StrAdapterCount;
509}
510
511inline ScratchAlloc::~ScratchAlloc() {
512  --IdxCtx.StrAdapterCount;
513  if (IdxCtx.StrAdapterCount == 0)
514    IdxCtx.StrScratch.Reset();
515}
516
517template <typename T>
518inline T *ScratchAlloc::allocate() {
519  return IdxCtx.StrScratch.Allocate<T>();
520}
521
522}} // end clang::cxindex
523
524#endif
525