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