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
17namespace clang {
18  class FileEntry;
19  class MSPropertyDecl;
20  class ObjCPropertyDecl;
21  class ClassTemplateDecl;
22  class FunctionTemplateDecl;
23  class TypeAliasTemplateDecl;
24  class ClassTemplateSpecializationDecl;
25
26namespace cxindex {
27  class IndexingContext;
28  class AttrListInfo;
29
30class ScratchAlloc {
31  IndexingContext &IdxCtx;
32
33public:
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
46struct EntityInfo : public CXIdxEntityInfo {
47  const NamedDecl *Dcl;
48  IndexingContext *IndexCtx;
49  IntrusiveRefCntPtr<AttrListInfo> AttrList;
50
51  EntityInfo() {
52    name = USR = nullptr;
53    attributes = nullptr;
54    numAttributes = 0;
55  }
56};
57
58struct ContainerInfo : public CXIdxContainerInfo {
59  const DeclContext *DC;
60  IndexingContext *IndexCtx;
61};
62
63struct 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
84  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 = nullptr;
90    numAttributes = 0;
91    declAsContainer = semanticContainer = lexicalContainer = nullptr;
92    flags = 0;
93  }
94  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 = nullptr;
101    numAttributes = 0;
102    declAsContainer = semanticContainer = lexicalContainer = nullptr;
103    flags = 0;
104  }
105};
106
107struct ObjCContainerDeclInfo : public DeclInfo {
108  CXIdxObjCContainerDeclInfo ObjCContDeclInfo;
109
110  ObjCContainerDeclInfo(bool isForwardRef,
111                        bool isRedeclaration,
112                        bool isImplementation)
113    : DeclInfo(Info_ObjCContainer, isRedeclaration,
114               /*isDefinition=*/!isForwardRef, /*isContainer=*/!isForwardRef) {
115    init(isForwardRef, isImplementation);
116  }
117  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
126  static bool classof(const DeclInfo *D) {
127    return Info_ObjCContainer <= D->Kind && D->Kind <= Info_ObjCCategory;
128  }
129
130private:
131  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
141struct ObjCInterfaceDeclInfo : public ObjCContainerDeclInfo {
142  CXIdxObjCInterfaceDeclInfo ObjCInterDeclInfo;
143  CXIdxObjCProtocolRefListInfo ObjCProtoListInfo;
144
145  ObjCInterfaceDeclInfo(const ObjCInterfaceDecl *D)
146    : ObjCContainerDeclInfo(Info_ObjCInterface,
147                            /*isForwardRef=*/false,
148                            /*isRedeclaration=*/D->getPreviousDecl() != nullptr,
149                            /*isImplementation=*/false) { }
150
151  static bool classof(const DeclInfo *D) {
152    return D->Kind == Info_ObjCInterface;
153  }
154};
155
156struct ObjCProtocolDeclInfo : public ObjCContainerDeclInfo {
157  CXIdxObjCProtocolRefListInfo ObjCProtoRefListInfo;
158
159  ObjCProtocolDeclInfo(const ObjCProtocolDecl *D)
160    : ObjCContainerDeclInfo(Info_ObjCProtocol,
161                            /*isForwardRef=*/false,
162                            /*isRedeclaration=*/D->getPreviousDecl(),
163                            /*isImplementation=*/false) { }
164
165  static bool classof(const DeclInfo *D) {
166    return D->Kind == Info_ObjCProtocol;
167  }
168};
169
170struct ObjCCategoryDeclInfo : public ObjCContainerDeclInfo {
171  CXIdxObjCCategoryDeclInfo ObjCCatDeclInfo;
172  CXIdxObjCProtocolRefListInfo ObjCProtoListInfo;
173
174  explicit ObjCCategoryDeclInfo(bool isImplementation)
175    : ObjCContainerDeclInfo(Info_ObjCCategory,
176                            /*isForwardRef=*/false,
177                            /*isRedeclaration=*/isImplementation,
178                            /*isImplementation=*/isImplementation) { }
179
180  static bool classof(const DeclInfo *D) {
181    return D->Kind == Info_ObjCCategory;
182  }
183};
184
185struct ObjCPropertyDeclInfo : public DeclInfo {
186  CXIdxObjCPropertyDeclInfo ObjCPropDeclInfo;
187
188  ObjCPropertyDeclInfo()
189    : DeclInfo(Info_ObjCProperty,
190               /*isRedeclaration=*/false, /*isDefinition=*/false,
191               /*isContainer=*/false) { }
192
193  static bool classof(const DeclInfo *D) {
194    return D->Kind == Info_ObjCProperty;
195  }
196};
197
198struct CXXClassDeclInfo : public DeclInfo {
199  CXIdxCXXClassDeclInfo CXXClassInfo;
200
201  CXXClassDeclInfo(bool isRedeclaration, bool isDefinition)
202    : DeclInfo(Info_CXXClass, isRedeclaration, isDefinition, isDefinition) { }
203
204  static bool classof(const DeclInfo *D) {
205    return D->Kind == Info_CXXClass;
206  }
207};
208
209struct AttrInfo : public CXIdxAttrInfo {
210  const Attr *A;
211
212  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
220struct IBOutletCollectionInfo : public AttrInfo {
221  EntityInfo ClassInfo;
222  CXIdxIBOutletCollectionAttrInfo IBCollInfo;
223
224  IBOutletCollectionInfo(CXCursor C, CXIdxLoc Loc, const Attr *A) :
225    AttrInfo(CXIdxAttr_IBOutletCollection, C, Loc, A) {
226    assert(C.kind == CXCursor_IBOutletCollectionAttr);
227    IBCollInfo.objcClass = nullptr;
228  }
229
230  IBOutletCollectionInfo(const IBOutletCollectionInfo &other);
231
232  static bool classof(const AttrInfo *A) {
233    return A->kind == CXIdxAttr_IBOutletCollection;
234  }
235};
236
237class 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;
247public:
248  AttrListInfo(const Decl *D, IndexingContext &IdxCtx);
249
250  static IntrusiveRefCntPtr<AttrListInfo> create(const Decl *D,
251                                                 IndexingContext &IdxCtx);
252
253  const CXIdxAttrInfo *const *getAttrs() const {
254    if (CXAttrs.empty())
255      return nullptr;
256    return CXAttrs.data();
257  }
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
263  void Retain() { ++ref_cnt; }
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
273class IndexingContext {
274  ASTContext *Ctx;
275  CXClientData ClientData;
276  IndexerCallbacks &CB;
277  unsigned IndexOptions;
278  CXTranslationUnit CXTU;
279
280  typedef llvm::DenseMap<const FileEntry *, CXIdxClientFile> FileMapTy;
281  typedef llvm::DenseMap<const DeclContext *, CXIdxClientContainer>
282    ContainerMapTy;
283  typedef llvm::DenseMap<const Decl *, CXIdxClientEntity> EntityMapTy;
284
285  FileMapTy FileMap;
286  ContainerMapTy ContainerMap;
287  EntityMapTy EntityMap;
288
289  typedef std::pair<const FileEntry *, const Decl *> RefFileOccurrence;
290  llvm::DenseSet<RefFileOccurrence> RefFileOccurrences;
291
292  std::deque<DeclGroupRef> TUDeclsInObjCContainer;
293
294  llvm::BumpPtrAllocator StrScratch;
295  unsigned StrAdapterCount;
296  friend class ScratchAlloc;
297
298  struct ObjCProtocolListInfo {
299    SmallVector<CXIdxObjCProtocolRefInfo, 4> ProtInfos;
300    SmallVector<EntityInfo, 4> ProtEntities;
301    SmallVector<CXIdxObjCProtocolRefInfo *, 4> Prots;
302
303    CXIdxObjCProtocolRefListInfo getListInfo() const {
304      CXIdxObjCProtocolRefListInfo Info = { Prots.data(),
305                                            (unsigned)Prots.size() };
306      return Info;
307    }
308
309    ObjCProtocolListInfo(const ObjCProtocolList &ProtList,
310                         IndexingContext &IdxCtx,
311                         ScratchAlloc &SA);
312  };
313
314  struct CXXBasesListInfo {
315    SmallVector<CXIdxBaseClassInfo, 4> BaseInfos;
316    SmallVector<EntityInfo, 4> BaseEntities;
317    SmallVector<CXIdxBaseClassInfo *, 4> CXBases;
318
319    const CXIdxBaseClassInfo *const *getBases() const {
320      return CXBases.data();
321    }
322    unsigned getNumBases() const { return (unsigned)CXBases.size(); }
323
324    CXXBasesListInfo(const CXXRecordDecl *D,
325                     IndexingContext &IdxCtx, ScratchAlloc &SA);
326
327  private:
328    SourceLocation getBaseLoc(const CXXBaseSpecifier &Base) const;
329  };
330
331  friend class AttrListInfo;
332
333public:
334  IndexingContext(CXClientData clientData, IndexerCallbacks &indexCallbacks,
335                  unsigned indexOptions, CXTranslationUnit cxTU)
336    : Ctx(nullptr), ClientData(clientData), CB(indexCallbacks),
337      IndexOptions(indexOptions), CXTU(cxTU),
338      StrScratch(), StrAdapterCount(0) { }
339
340  ASTContext &getASTContext() const { return *Ctx; }
341
342  void setASTContext(ASTContext &ctx);
343  void setPreprocessor(Preprocessor &PP);
344
345  bool shouldSuppressRefs() const {
346    return IndexOptions & CXIndexOpt_SuppressRedundantRefs;
347  }
348
349  bool shouldIndexFunctionLocalSymbols() const {
350    return IndexOptions & CXIndexOpt_IndexFunctionLocalSymbols;
351  }
352
353  bool shouldIndexImplicitTemplateInsts() const {
354    return IndexOptions & CXIndexOpt_IndexImplicitTemplateInstantiations;
355  }
356
357  static bool isFunctionLocalDecl(const Decl *D);
358
359  bool shouldAbort();
360
361  bool hasDiagnosticCallback() const { return CB.diagnostic; }
362
363  void enteredMainFile(const FileEntry *File);
364
365  void ppIncludedFile(SourceLocation hashLoc,
366                      StringRef filename, const FileEntry *File,
367                      bool isImport, bool isAngled, bool isModuleImport);
368
369  void importedModule(const ImportDecl *ImportD);
370  void importedPCH(const FileEntry *File);
371
372  void startedTranslationUnit();
373
374  void indexDecl(const Decl *D);
375
376  void indexTagDecl(const TagDecl *D);
377
378  void indexTypeSourceInfo(TypeSourceInfo *TInfo, const NamedDecl *Parent,
379                           const DeclContext *DC = nullptr);
380
381  void indexTypeLoc(TypeLoc TL, const NamedDecl *Parent,
382                    const DeclContext *DC = nullptr);
383
384  void indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
385                                   const NamedDecl *Parent,
386                                   const DeclContext *DC = nullptr);
387
388  void indexDeclContext(const DeclContext *DC);
389
390  void indexBody(const Stmt *S, const NamedDecl *Parent,
391                 const DeclContext *DC = nullptr);
392
393  void handleDiagnosticSet(CXDiagnosticSet CXDiagSet);
394
395  bool handleFunction(const FunctionDecl *FD);
396
397  bool handleVar(const VarDecl *D);
398
399  bool handleField(const FieldDecl *D);
400
401  bool handleMSProperty(const MSPropertyDecl *D);
402
403  bool handleEnumerator(const EnumConstantDecl *D);
404
405  bool handleTagDecl(const TagDecl *D);
406
407  bool handleTypedefName(const TypedefNameDecl *D);
408
409  bool handleObjCInterface(const ObjCInterfaceDecl *D);
410  bool handleObjCImplementation(const ObjCImplementationDecl *D);
411
412  bool handleObjCProtocol(const ObjCProtocolDecl *D);
413
414  bool handleObjCCategory(const ObjCCategoryDecl *D);
415  bool handleObjCCategoryImpl(const ObjCCategoryImplDecl *D);
416
417  bool handleObjCMethod(const ObjCMethodDecl *D);
418
419  bool handleSynthesizedObjCProperty(const ObjCPropertyImplDecl *D);
420  bool handleSynthesizedObjCMethod(const ObjCMethodDecl *D, SourceLocation Loc,
421                                   const DeclContext *LexicalDC);
422
423  bool handleObjCProperty(const ObjCPropertyDecl *D);
424
425  bool handleNamespace(const NamespaceDecl *D);
426
427  bool handleClassTemplate(const ClassTemplateDecl *D);
428  bool handleFunctionTemplate(const FunctionTemplateDecl *D);
429  bool handleTypeAliasTemplate(const TypeAliasTemplateDecl *D);
430
431  bool handleReference(const NamedDecl *D, SourceLocation Loc, CXCursor Cursor,
432                       const NamedDecl *Parent,
433                       const DeclContext *DC,
434                       const Expr *E = nullptr,
435                       CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct);
436
437  bool handleReference(const NamedDecl *D, SourceLocation Loc,
438                       const NamedDecl *Parent,
439                       const DeclContext *DC,
440                       const Expr *E = nullptr,
441                       CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct);
442
443  bool isNotFromSourceFile(SourceLocation Loc) const;
444
445  void indexTopLevelDecl(const Decl *D);
446  void indexTUDeclsInObjCContainer();
447  void indexDeclGroupRef(DeclGroupRef DG);
448
449  void addTUDeclInObjCContainer(DeclGroupRef DG) {
450    TUDeclsInObjCContainer.push_back(DG);
451  }
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
464private:
465  bool handleDecl(const NamedDecl *D,
466                  SourceLocation Loc, CXCursor Cursor,
467                  DeclInfo &DInfo,
468                  const DeclContext *LexicalDC = nullptr);
469
470  bool handleObjCContainer(const ObjCContainerDecl *D,
471                           SourceLocation Loc, CXCursor Cursor,
472                           ObjCContainerDeclInfo &ContDInfo);
473
474  bool handleCXXRecordDecl(const CXXRecordDecl *RD, const NamedDecl *OrigD);
475
476  bool markEntityOccurrenceInFile(const NamedDecl *D, SourceLocation Loc);
477
478  const NamedDecl *getEntityDecl(const NamedDecl *D) const;
479
480  const DeclContext *getEntityContainer(const Decl *D) const;
481
482  CXIdxClientFile getIndexFile(const FileEntry *File);
483
484  CXIdxLoc getIndexLoc(SourceLocation Loc) const;
485
486  void getEntityInfo(const NamedDecl *D,
487                     EntityInfo &EntityInfo,
488                     ScratchAlloc &SA);
489
490  void getContainerInfo(const DeclContext *DC, ContainerInfo &ContInfo);
491
492  CXCursor getCursor(const Decl *D) {
493    return cxcursor::MakeCXCursor(D, CXTU);
494  }
495
496  CXCursor getRefCursor(const NamedDecl *D, SourceLocation Loc);
497
498  static bool shouldIgnoreIfImplicit(const Decl *D);
499};
500
501inline ScratchAlloc::ScratchAlloc(IndexingContext &idxCtx) : IdxCtx(idxCtx) {
502  ++IdxCtx.StrAdapterCount;
503}
504inline ScratchAlloc::ScratchAlloc(const ScratchAlloc &SA) : IdxCtx(SA.IdxCtx) {
505  ++IdxCtx.StrAdapterCount;
506}
507
508inline ScratchAlloc::~ScratchAlloc() {
509  --IdxCtx.StrAdapterCount;
510  if (IdxCtx.StrAdapterCount == 0)
511    IdxCtx.StrScratch.Reset();
512}
513
514template <typename T>
515inline T *ScratchAlloc::allocate() {
516  return IdxCtx.StrScratch.Allocate<T>();
517}
518
519}} // end clang::cxindex
520