IndexingContext.h revision 30a2805c2c85e6abfe3149293f83f60da018b2df
1//===- IndexingContext.h - Higher level API functions ------------------------===//
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 "Index_Internal.h"
11#include "CXCursor.h"
12
13#include "clang/AST/DeclObjC.h"
14#include "clang/AST/DeclGroup.h"
15#include "llvm/ADT/DenseSet.h"
16#include <deque>
17
18namespace clang {
19  class FileEntry;
20  class ObjCPropertyDecl;
21  class ClassTemplateDecl;
22  class FunctionTemplateDecl;
23  class TypeAliasTemplateDecl;
24  class ClassTemplateSpecializationDecl;
25
26namespace cxindex {
27  class IndexingContext;
28  class ScratchAlloc;
29  class AttrListInfo;
30
31struct EntityInfo : public CXIdxEntityInfo {
32  const NamedDecl *Dcl;
33  IndexingContext *IndexCtx;
34  IntrusiveRefCntPtr<AttrListInfo> AttrList;
35
36  EntityInfo() {
37    name = USR = 0;
38    attributes = 0;
39    numAttributes = 0;
40  }
41};
42
43struct ContainerInfo : public CXIdxContainerInfo {
44  const DeclContext *DC;
45  IndexingContext *IndexCtx;
46};
47
48struct DeclInfo : public CXIdxDeclInfo {
49  enum DInfoKind {
50    Info_Decl,
51
52    Info_ObjCContainer,
53      Info_ObjCInterface,
54      Info_ObjCProtocol,
55      Info_ObjCCategory,
56
57    Info_ObjCProperty,
58
59    Info_CXXClass
60  };
61
62  DInfoKind Kind;
63
64  EntityInfo EntInfo;
65  ContainerInfo SemanticContainer;
66  ContainerInfo LexicalContainer;
67  ContainerInfo DeclAsContainer;
68
69  DeclInfo(bool isRedeclaration, bool isDefinition, bool isContainer)
70    : Kind(Info_Decl) {
71    this->isRedeclaration = isRedeclaration;
72    this->isDefinition = isDefinition;
73    this->isContainer = isContainer;
74    attributes = 0;
75    numAttributes = 0;
76    declAsContainer = semanticContainer = lexicalContainer = 0;
77  }
78  DeclInfo(DInfoKind K,
79           bool isRedeclaration, bool isDefinition, bool isContainer)
80    : Kind(K) {
81    this->isRedeclaration = isRedeclaration;
82    this->isDefinition = isDefinition;
83    this->isContainer = isContainer;
84    attributes = 0;
85    numAttributes = 0;
86    declAsContainer = semanticContainer = lexicalContainer = 0;
87  }
88
89  static bool classof(const DeclInfo *) { return true; }
90};
91
92struct ObjCContainerDeclInfo : public DeclInfo {
93  CXIdxObjCContainerDeclInfo ObjCContDeclInfo;
94
95  ObjCContainerDeclInfo(bool isForwardRef,
96                        bool isRedeclaration,
97                        bool isImplementation)
98    : DeclInfo(Info_ObjCContainer, isRedeclaration,
99               /*isDefinition=*/!isForwardRef, /*isContainer=*/!isForwardRef) {
100    init(isForwardRef, isImplementation);
101  }
102  ObjCContainerDeclInfo(DInfoKind K,
103                        bool isForwardRef,
104                        bool isRedeclaration,
105                        bool isImplementation)
106    : DeclInfo(K, isRedeclaration, /*isDefinition=*/!isForwardRef,
107               /*isContainer=*/!isForwardRef) {
108    init(isForwardRef, isImplementation);
109  }
110
111  static bool classof(const DeclInfo *D) {
112    return Info_ObjCContainer <= D->Kind && D->Kind <= Info_ObjCCategory;
113  }
114  static bool classof(const ObjCContainerDeclInfo *D) { return true; }
115
116private:
117  void init(bool isForwardRef, bool isImplementation) {
118    if (isForwardRef)
119      ObjCContDeclInfo.kind = CXIdxObjCContainer_ForwardRef;
120    else if (isImplementation)
121      ObjCContDeclInfo.kind = CXIdxObjCContainer_Implementation;
122    else
123      ObjCContDeclInfo.kind = CXIdxObjCContainer_Interface;
124  }
125};
126
127struct ObjCInterfaceDeclInfo : public ObjCContainerDeclInfo {
128  CXIdxObjCInterfaceDeclInfo ObjCInterDeclInfo;
129  CXIdxObjCProtocolRefListInfo ObjCProtoListInfo;
130
131  ObjCInterfaceDeclInfo(const ObjCInterfaceDecl *D)
132    : ObjCContainerDeclInfo(Info_ObjCInterface,
133                            /*isForwardRef=*/false,
134                          /*isRedeclaration=*/D->getPreviousDecl() != 0,
135                            /*isImplementation=*/false) { }
136
137  static bool classof(const DeclInfo *D) {
138    return D->Kind == Info_ObjCInterface;
139  }
140  static bool classof(const ObjCInterfaceDeclInfo *D) { return true; }
141};
142
143struct ObjCProtocolDeclInfo : public ObjCContainerDeclInfo {
144  CXIdxObjCProtocolRefListInfo ObjCProtoRefListInfo;
145
146  ObjCProtocolDeclInfo(const ObjCProtocolDecl *D)
147    : ObjCContainerDeclInfo(Info_ObjCProtocol,
148                            /*isForwardRef=*/false,
149                            /*isRedeclaration=*/D->getPreviousDecl(),
150                            /*isImplementation=*/false) { }
151
152  static bool classof(const DeclInfo *D) {
153    return D->Kind == Info_ObjCProtocol;
154  }
155  static bool classof(const ObjCProtocolDeclInfo *D) { return true; }
156};
157
158struct ObjCCategoryDeclInfo : public ObjCContainerDeclInfo {
159  CXIdxObjCCategoryDeclInfo ObjCCatDeclInfo;
160  CXIdxObjCProtocolRefListInfo ObjCProtoListInfo;
161
162  explicit ObjCCategoryDeclInfo(bool isImplementation)
163    : ObjCContainerDeclInfo(Info_ObjCCategory,
164                            /*isForwardRef=*/false,
165                            /*isRedeclaration=*/isImplementation,
166                            /*isImplementation=*/isImplementation) { }
167
168  static bool classof(const DeclInfo *D) {
169    return D->Kind == Info_ObjCCategory;
170  }
171  static bool classof(const ObjCCategoryDeclInfo *D) { return true; }
172};
173
174struct ObjCPropertyDeclInfo : public DeclInfo {
175  CXIdxObjCPropertyDeclInfo ObjCPropDeclInfo;
176
177  ObjCPropertyDeclInfo()
178    : DeclInfo(Info_ObjCProperty,
179               /*isRedeclaration=*/false, /*isDefinition=*/false,
180               /*isContainer=*/false) { }
181
182  static bool classof(const DeclInfo *D) {
183    return D->Kind == Info_ObjCProperty;
184  }
185  static bool classof(const ObjCPropertyDeclInfo *D) { return true; }
186};
187
188struct CXXClassDeclInfo : public DeclInfo {
189  CXIdxCXXClassDeclInfo CXXClassInfo;
190
191  CXXClassDeclInfo(bool isRedeclaration, bool isDefinition)
192    : DeclInfo(Info_CXXClass, isRedeclaration, isDefinition, isDefinition) { }
193
194  static bool classof(const DeclInfo *D) {
195    return D->Kind == Info_CXXClass;
196  }
197  static bool classof(const CXXClassDeclInfo *D) { return true; }
198};
199
200struct AttrInfo : public CXIdxAttrInfo {
201  const Attr *A;
202
203  AttrInfo(CXIdxAttrKind Kind, CXCursor C, CXIdxLoc Loc, const Attr *A) {
204    kind = Kind;
205    cursor = C;
206    loc = Loc;
207    this->A = A;
208  }
209
210  static bool classof(const AttrInfo *) { return true; }
211};
212
213struct IBOutletCollectionInfo : public AttrInfo {
214  EntityInfo ClassInfo;
215  CXIdxIBOutletCollectionAttrInfo IBCollInfo;
216
217  IBOutletCollectionInfo(CXCursor C, CXIdxLoc Loc, const Attr *A) :
218    AttrInfo(CXIdxAttr_IBOutletCollection, C, Loc, A) {
219    assert(C.kind == CXCursor_IBOutletCollectionAttr);
220    IBCollInfo.objcClass = 0;
221  }
222
223  IBOutletCollectionInfo(const IBOutletCollectionInfo &other);
224
225  static bool classof(const AttrInfo *A) {
226    return A->kind == CXIdxAttr_IBOutletCollection;
227  }
228  static bool classof(const IBOutletCollectionInfo *D) { return true; }
229};
230
231class AttrListInfo {
232  SmallVector<AttrInfo, 2> Attrs;
233  SmallVector<IBOutletCollectionInfo, 2> IBCollAttrs;
234  SmallVector<CXIdxAttrInfo *, 2> CXAttrs;
235  unsigned ref_cnt;
236
237public:
238  AttrListInfo(const Decl *D,
239               IndexingContext &IdxCtx,
240               ScratchAlloc &SA);
241  AttrListInfo(const AttrListInfo &other);
242
243  const CXIdxAttrInfo *const *getAttrs() const {
244    if (CXAttrs.empty())
245      return 0;
246    return CXAttrs.data();
247  }
248  unsigned getNumAttrs() const { return (unsigned)CXAttrs.size(); }
249
250  /// \brief Retain/Release only useful when we allocate a AttrListInfo from the
251  /// BumpPtrAllocator, and not from the stack; so that we keep a pointer
252  // in the EntityInfo
253  void Retain() { ++ref_cnt; }
254  void Release() {
255    assert (ref_cnt > 0 && "Reference count is already zero.");
256    if (--ref_cnt == 0) {
257      // Memory is allocated from a BumpPtrAllocator, no need to delete it.
258      this->~AttrListInfo();
259    }
260  }
261};
262
263struct RefFileOccurence {
264  const FileEntry *File;
265  const Decl *Dcl;
266
267  RefFileOccurence(const FileEntry *File, const Decl *Dcl)
268    : File(File), Dcl(Dcl) { }
269};
270
271class IndexingContext {
272  ASTContext *Ctx;
273  CXClientData ClientData;
274  IndexerCallbacks &CB;
275  unsigned IndexOptions;
276  CXTranslationUnit CXTU;
277
278  typedef llvm::DenseMap<const FileEntry *, CXIdxClientFile> FileMapTy;
279  typedef llvm::DenseMap<const DeclContext *, CXIdxClientContainer>
280    ContainerMapTy;
281  typedef llvm::DenseMap<const Decl *, CXIdxClientEntity> EntityMapTy;
282
283  FileMapTy FileMap;
284  ContainerMapTy ContainerMap;
285  EntityMapTy EntityMap;
286
287  llvm::DenseSet<RefFileOccurence> RefFileOccurences;
288
289  std::deque<DeclGroupRef> TUDeclsInObjCContainer;
290
291  llvm::BumpPtrAllocator StrScratch;
292  unsigned StrAdapterCount;
293  friend class ScratchAlloc;
294
295  struct ObjCProtocolListInfo {
296    SmallVector<CXIdxObjCProtocolRefInfo, 4> ProtInfos;
297    SmallVector<EntityInfo, 4> ProtEntities;
298    SmallVector<CXIdxObjCProtocolRefInfo *, 4> Prots;
299
300    CXIdxObjCProtocolRefListInfo getListInfo() const {
301      CXIdxObjCProtocolRefListInfo Info = { Prots.data(),
302                                            (unsigned)Prots.size() };
303      return Info;
304    }
305
306    ObjCProtocolListInfo(const ObjCProtocolList &ProtList,
307                         IndexingContext &IdxCtx,
308                         ScratchAlloc &SA);
309  };
310
311  struct CXXBasesListInfo {
312    SmallVector<CXIdxBaseClassInfo, 4> BaseInfos;
313    SmallVector<EntityInfo, 4> BaseEntities;
314    SmallVector<CXIdxBaseClassInfo *, 4> CXBases;
315
316    const CXIdxBaseClassInfo *const *getBases() const {
317      return CXBases.data();
318    }
319    unsigned getNumBases() const { return (unsigned)CXBases.size(); }
320
321    CXXBasesListInfo(const CXXRecordDecl *D,
322                     IndexingContext &IdxCtx, ScratchAlloc &SA);
323
324  private:
325    SourceLocation getBaseLoc(const CXXBaseSpecifier &Base) const;
326  };
327
328  friend class AttrListInfo;
329
330public:
331  IndexingContext(CXClientData clientData, IndexerCallbacks &indexCallbacks,
332                  unsigned indexOptions, CXTranslationUnit cxTU)
333    : Ctx(0), ClientData(clientData), CB(indexCallbacks),
334      IndexOptions(indexOptions), CXTU(cxTU),
335      StrScratch(/*size=*/1024), StrAdapterCount(0) { }
336
337  ASTContext &getASTContext() const { return *Ctx; }
338
339  void setASTContext(ASTContext &ctx);
340  void setPreprocessor(Preprocessor &PP);
341
342  bool shouldSuppressRefs() const {
343    return IndexOptions & CXIndexOpt_SuppressRedundantRefs;
344  }
345
346  bool shouldIndexFunctionLocalSymbols() const {
347    return IndexOptions & CXIndexOpt_IndexFunctionLocalSymbols;
348  }
349
350  bool shouldIndexImplicitTemplateInsts() const {
351    return IndexOptions & CXIndexOpt_IndexImplicitTemplateInstantiations;
352  }
353
354  bool shouldAbort();
355
356  bool hasDiagnosticCallback() const { return CB.diagnostic; }
357
358  void enteredMainFile(const FileEntry *File);
359
360  void ppIncludedFile(SourceLocation hashLoc,
361                      StringRef filename, const FileEntry *File,
362                      bool isImport, bool isAngled);
363
364  void startedTranslationUnit();
365
366  void indexDecl(const Decl *D);
367
368  void indexTagDecl(const TagDecl *D);
369
370  void indexTypeSourceInfo(TypeSourceInfo *TInfo, const NamedDecl *Parent,
371                           const DeclContext *DC = 0);
372
373  void indexTypeLoc(TypeLoc TL, const NamedDecl *Parent,
374                    const DeclContext *DC = 0);
375
376  void indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
377                                   const NamedDecl *Parent,
378                                   const DeclContext *DC = 0);
379
380  void indexDeclContext(const DeclContext *DC);
381
382  void indexBody(const Stmt *S, const NamedDecl *Parent,
383                 const DeclContext *DC = 0);
384
385  void handleDiagnosticSet(CXDiagnosticSet CXDiagSet);
386
387  bool handleFunction(const FunctionDecl *FD);
388
389  bool handleVar(const VarDecl *D);
390
391  bool handleField(const FieldDecl *D);
392
393  bool handleEnumerator(const EnumConstantDecl *D);
394
395  bool handleTagDecl(const TagDecl *D);
396
397  bool handleTypedefName(const TypedefNameDecl *D);
398
399  bool handleObjCInterface(const ObjCInterfaceDecl *D);
400  bool handleObjCImplementation(const ObjCImplementationDecl *D);
401
402  bool handleObjCProtocol(const ObjCProtocolDecl *D);
403
404  bool handleObjCCategory(const ObjCCategoryDecl *D);
405  bool handleObjCCategoryImpl(const ObjCCategoryImplDecl *D);
406
407  bool handleObjCMethod(const ObjCMethodDecl *D);
408
409  bool handleSynthesizedObjCProperty(const ObjCPropertyImplDecl *D);
410  bool handleSynthesizedObjCMethod(const ObjCMethodDecl *D, SourceLocation Loc,
411                                   const DeclContext *LexicalDC);
412
413  bool handleObjCProperty(const ObjCPropertyDecl *D);
414
415  bool handleNamespace(const NamespaceDecl *D);
416
417  bool handleClassTemplate(const ClassTemplateDecl *D);
418  bool handleFunctionTemplate(const FunctionTemplateDecl *D);
419  bool handleTypeAliasTemplate(const TypeAliasTemplateDecl *D);
420
421  bool handleReference(const NamedDecl *D, SourceLocation Loc, CXCursor Cursor,
422                       const NamedDecl *Parent,
423                       const DeclContext *DC,
424                       const Expr *E = 0,
425                       CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct);
426
427  bool handleReference(const NamedDecl *D, SourceLocation Loc,
428                       const NamedDecl *Parent,
429                       const DeclContext *DC,
430                       const Expr *E = 0,
431                       CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct);
432
433  bool isNotFromSourceFile(SourceLocation Loc) const;
434
435  void indexTopLevelDecl(Decl *D);
436  void indexTUDeclsInObjCContainer();
437  void indexDeclGroupRef(DeclGroupRef DG);
438
439  void addTUDeclInObjCContainer(DeclGroupRef DG) {
440    TUDeclsInObjCContainer.push_back(DG);
441  }
442
443  void translateLoc(SourceLocation Loc, CXIdxClientFile *indexFile, CXFile *file,
444                    unsigned *line, unsigned *column, unsigned *offset);
445
446  CXIdxClientContainer getClientContainerForDC(const DeclContext *DC) const;
447  void addContainerInMap(const DeclContext *DC, CXIdxClientContainer container);
448
449  CXIdxClientEntity getClientEntity(const Decl *D) const;
450  void setClientEntity(const Decl *D, CXIdxClientEntity client);
451
452  static bool isTemplateImplicitInstantiation(const Decl *D);
453
454private:
455  bool handleDecl(const NamedDecl *D,
456                  SourceLocation Loc, CXCursor Cursor,
457                  DeclInfo &DInfo,
458                  const DeclContext *LexicalDC = 0);
459
460  bool handleObjCContainer(const ObjCContainerDecl *D,
461                           SourceLocation Loc, CXCursor Cursor,
462                           ObjCContainerDeclInfo &ContDInfo);
463
464  bool handleCXXRecordDecl(const CXXRecordDecl *RD, const NamedDecl *OrigD);
465
466  bool markEntityOccurrenceInFile(const NamedDecl *D, SourceLocation Loc);
467
468  const NamedDecl *getEntityDecl(const NamedDecl *D) const;
469
470  const DeclContext *getEntityContainer(const Decl *D) const;
471
472  CXIdxClientFile getIndexFile(const FileEntry *File);
473
474  CXIdxLoc getIndexLoc(SourceLocation Loc) const;
475
476  void getEntityInfo(const NamedDecl *D,
477                     EntityInfo &EntityInfo,
478                     ScratchAlloc &SA);
479
480  void getContainerInfo(const DeclContext *DC, ContainerInfo &ContInfo);
481
482  CXCursor getCursor(const Decl *D) {
483    return cxcursor::MakeCXCursor(const_cast<Decl*>(D), CXTU);
484  }
485
486  CXCursor getRefCursor(const NamedDecl *D, SourceLocation Loc);
487
488  static bool shouldIgnoreIfImplicit(const Decl *D);
489};
490
491class ScratchAlloc {
492  IndexingContext &IdxCtx;
493
494public:
495  explicit ScratchAlloc(IndexingContext &indexCtx) : IdxCtx(indexCtx) {
496    ++IdxCtx.StrAdapterCount;
497  }
498
499  ~ScratchAlloc() {
500    --IdxCtx.StrAdapterCount;
501    if (IdxCtx.StrAdapterCount == 0)
502      IdxCtx.StrScratch.Reset();
503  }
504
505  const char *toCStr(StringRef Str);
506  const char *copyCStr(StringRef Str);
507
508  template <typename T>
509  T *allocate() {
510    return IdxCtx.StrScratch.Allocate<T>();
511  }
512};
513
514}} // end clang::cxindex
515
516namespace llvm {
517  /// Define DenseMapInfo so that FileID's can be used as keys in DenseMap and
518  /// DenseSets.
519  template <>
520  struct DenseMapInfo<clang::cxindex::RefFileOccurence> {
521    static inline clang::cxindex::RefFileOccurence getEmptyKey() {
522      return clang::cxindex::RefFileOccurence(0, 0);
523    }
524
525    static inline clang::cxindex::RefFileOccurence getTombstoneKey() {
526      return clang::cxindex::RefFileOccurence((const clang::FileEntry *)~0,
527                                              (const clang::Decl *)~0);
528    }
529
530    static unsigned getHashValue(clang::cxindex::RefFileOccurence S) {
531      llvm::FoldingSetNodeID ID;
532      ID.AddPointer(S.File);
533      ID.AddPointer(S.Dcl);
534      return ID.ComputeHash();
535    }
536
537    static bool isEqual(clang::cxindex::RefFileOccurence LHS,
538                        clang::cxindex::RefFileOccurence RHS) {
539      return LHS.File == RHS.File && LHS.Dcl == RHS.Dcl;
540    }
541  };
542}
543