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