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