• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  
17  namespace clang {
18    class FileEntry;
19    class MSPropertyDecl;
20    class ObjCPropertyDecl;
21    class ClassTemplateDecl;
22    class FunctionTemplateDecl;
23    class TypeAliasTemplateDecl;
24    class ClassTemplateSpecializationDecl;
25  
26  namespace cxindex {
27    class IndexingContext;
28    class AttrListInfo;
29  
30  class ScratchAlloc {
31    IndexingContext &IdxCtx;
32  
33  public:
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  
46  struct EntityInfo : public CXIdxEntityInfo {
47    const NamedDecl *Dcl;
48    IndexingContext *IndexCtx;
49    IntrusiveRefCntPtr<AttrListInfo> AttrList;
50  
EntityInfoEntityInfo51    EntityInfo() {
52      name = USR = nullptr;
53      attributes = nullptr;
54      numAttributes = 0;
55    }
56  };
57  
58  struct ContainerInfo : public CXIdxContainerInfo {
59    const DeclContext *DC;
60    IndexingContext *IndexCtx;
61  };
62  
63  struct 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  
DeclInfoDeclInfo84    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    }
DeclInfoDeclInfo94    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  
107  struct ObjCContainerDeclInfo : public DeclInfo {
108    CXIdxObjCContainerDeclInfo ObjCContDeclInfo;
109  
ObjCContainerDeclInfoObjCContainerDeclInfo110    ObjCContainerDeclInfo(bool isForwardRef,
111                          bool isRedeclaration,
112                          bool isImplementation)
113      : DeclInfo(Info_ObjCContainer, isRedeclaration,
114                 /*isDefinition=*/!isForwardRef, /*isContainer=*/!isForwardRef) {
115      init(isForwardRef, isImplementation);
116    }
ObjCContainerDeclInfoObjCContainerDeclInfo117    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  
classofObjCContainerDeclInfo126    static bool classof(const DeclInfo *D) {
127      return Info_ObjCContainer <= D->Kind && D->Kind <= Info_ObjCCategory;
128    }
129  
130  private:
initObjCContainerDeclInfo131    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  
141  struct ObjCInterfaceDeclInfo : public ObjCContainerDeclInfo {
142    CXIdxObjCInterfaceDeclInfo ObjCInterDeclInfo;
143    CXIdxObjCProtocolRefListInfo ObjCProtoListInfo;
144  
ObjCInterfaceDeclInfoObjCInterfaceDeclInfo145    ObjCInterfaceDeclInfo(const ObjCInterfaceDecl *D)
146      : ObjCContainerDeclInfo(Info_ObjCInterface,
147                              /*isForwardRef=*/false,
148                              /*isRedeclaration=*/D->getPreviousDecl() != nullptr,
149                              /*isImplementation=*/false) { }
150  
classofObjCInterfaceDeclInfo151    static bool classof(const DeclInfo *D) {
152      return D->Kind == Info_ObjCInterface;
153    }
154  };
155  
156  struct ObjCProtocolDeclInfo : public ObjCContainerDeclInfo {
157    CXIdxObjCProtocolRefListInfo ObjCProtoRefListInfo;
158  
ObjCProtocolDeclInfoObjCProtocolDeclInfo159    ObjCProtocolDeclInfo(const ObjCProtocolDecl *D)
160      : ObjCContainerDeclInfo(Info_ObjCProtocol,
161                              /*isForwardRef=*/false,
162                              /*isRedeclaration=*/D->getPreviousDecl(),
163                              /*isImplementation=*/false) { }
164  
classofObjCProtocolDeclInfo165    static bool classof(const DeclInfo *D) {
166      return D->Kind == Info_ObjCProtocol;
167    }
168  };
169  
170  struct ObjCCategoryDeclInfo : public ObjCContainerDeclInfo {
171    CXIdxObjCCategoryDeclInfo ObjCCatDeclInfo;
172    CXIdxObjCProtocolRefListInfo ObjCProtoListInfo;
173  
ObjCCategoryDeclInfoObjCCategoryDeclInfo174    explicit ObjCCategoryDeclInfo(bool isImplementation)
175      : ObjCContainerDeclInfo(Info_ObjCCategory,
176                              /*isForwardRef=*/false,
177                              /*isRedeclaration=*/isImplementation,
178                              /*isImplementation=*/isImplementation) { }
179  
classofObjCCategoryDeclInfo180    static bool classof(const DeclInfo *D) {
181      return D->Kind == Info_ObjCCategory;
182    }
183  };
184  
185  struct ObjCPropertyDeclInfo : public DeclInfo {
186    CXIdxObjCPropertyDeclInfo ObjCPropDeclInfo;
187  
ObjCPropertyDeclInfoObjCPropertyDeclInfo188    ObjCPropertyDeclInfo()
189      : DeclInfo(Info_ObjCProperty,
190                 /*isRedeclaration=*/false, /*isDefinition=*/false,
191                 /*isContainer=*/false) { }
192  
classofObjCPropertyDeclInfo193    static bool classof(const DeclInfo *D) {
194      return D->Kind == Info_ObjCProperty;
195    }
196  };
197  
198  struct CXXClassDeclInfo : public DeclInfo {
199    CXIdxCXXClassDeclInfo CXXClassInfo;
200  
CXXClassDeclInfoCXXClassDeclInfo201    CXXClassDeclInfo(bool isRedeclaration, bool isDefinition)
202      : DeclInfo(Info_CXXClass, isRedeclaration, isDefinition, isDefinition) { }
203  
classofCXXClassDeclInfo204    static bool classof(const DeclInfo *D) {
205      return D->Kind == Info_CXXClass;
206    }
207  };
208  
209  struct AttrInfo : public CXIdxAttrInfo {
210    const Attr *A;
211  
AttrInfoAttrInfo212    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  
220  struct IBOutletCollectionInfo : public AttrInfo {
221    EntityInfo ClassInfo;
222    CXIdxIBOutletCollectionAttrInfo IBCollInfo;
223  
IBOutletCollectionInfoIBOutletCollectionInfo224    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  
classofIBOutletCollectionInfo232    static bool classof(const AttrInfo *A) {
233      return A->kind == CXIdxAttr_IBOutletCollection;
234    }
235  };
236  
237  class 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;
247  public:
248    AttrListInfo(const Decl *D, IndexingContext &IdxCtx);
249  
250    static IntrusiveRefCntPtr<AttrListInfo> create(const Decl *D,
251                                                   IndexingContext &IdxCtx);
252  
getAttrs()253    const CXIdxAttrInfo *const *getAttrs() const {
254      if (CXAttrs.empty())
255        return nullptr;
256      return CXAttrs.data();
257    }
getNumAttrs()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
Retain()263    void Retain() { ++ref_cnt; }
Release()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  
273  class 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  
getListInfoObjCProtocolListInfo303      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  
getBasesCXXBasesListInfo319      const CXIdxBaseClassInfo *const *getBases() const {
320        return CXBases.data();
321      }
getNumBasesCXXBasesListInfo322      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  
333  public:
IndexingContext(CXClientData clientData,IndexerCallbacks & indexCallbacks,unsigned indexOptions,CXTranslationUnit cxTU)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  
getASTContext()340    ASTContext &getASTContext() const { return *Ctx; }
341  
342    void setASTContext(ASTContext &ctx);
343    void setPreprocessor(Preprocessor &PP);
344  
shouldSuppressRefs()345    bool shouldSuppressRefs() const {
346      return IndexOptions & CXIndexOpt_SuppressRedundantRefs;
347    }
348  
shouldIndexFunctionLocalSymbols()349    bool shouldIndexFunctionLocalSymbols() const {
350      return IndexOptions & CXIndexOpt_IndexFunctionLocalSymbols;
351    }
352  
shouldIndexImplicitTemplateInsts()353    bool shouldIndexImplicitTemplateInsts() const {
354      return IndexOptions & CXIndexOpt_IndexImplicitTemplateInstantiations;
355    }
356  
357    static bool isFunctionLocalDecl(const Decl *D);
358  
359    bool shouldAbort();
360  
hasDiagnosticCallback()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  
addTUDeclInObjCContainer(DeclGroupRef DG)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  
464  private:
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  
getCursor(const Decl * D)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  
ScratchAlloc(IndexingContext & idxCtx)501  inline ScratchAlloc::ScratchAlloc(IndexingContext &idxCtx) : IdxCtx(idxCtx) {
502    ++IdxCtx.StrAdapterCount;
503  }
ScratchAlloc(const ScratchAlloc & SA)504  inline ScratchAlloc::ScratchAlloc(const ScratchAlloc &SA) : IdxCtx(SA.IdxCtx) {
505    ++IdxCtx.StrAdapterCount;
506  }
507  
~ScratchAlloc()508  inline ScratchAlloc::~ScratchAlloc() {
509    --IdxCtx.StrAdapterCount;
510    if (IdxCtx.StrAdapterCount == 0)
511      IdxCtx.StrScratch.Reset();
512  }
513  
514  template <typename T>
allocate()515  inline T *ScratchAlloc::allocate() {
516    return IdxCtx.StrScratch.Allocate<T>();
517  }
518  
519  }} // end clang::cxindex
520