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