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 #include <deque> 20 21 namespace clang { 22 class FileEntry; 23 class MSPropertyDecl; 24 class ObjCPropertyDecl; 25 class ClassTemplateDecl; 26 class FunctionTemplateDecl; 27 class TypeAliasTemplateDecl; 28 class ClassTemplateSpecializationDecl; 29 30 namespace cxindex { 31 class CXIndexDataConsumer; 32 class AttrListInfo; 33 34 class ScratchAlloc { 35 CXIndexDataConsumer &IdxCtx; 36 37 public: 38 explicit ScratchAlloc(CXIndexDataConsumer &indexCtx); 39 ScratchAlloc(const ScratchAlloc &SA); 40 41 ~ScratchAlloc(); 42 43 const char *toCStr(StringRef Str); 44 const char *copyCStr(StringRef Str); 45 46 template <typename T> 47 T *allocate(); 48 }; 49 50 struct EntityInfo : public CXIdxEntityInfo { 51 const NamedDecl *Dcl; 52 CXIndexDataConsumer *IndexCtx; 53 IntrusiveRefCntPtr<AttrListInfo> AttrList; 54 55 EntityInfo() { 56 name = USR = nullptr; 57 attributes = nullptr; 58 numAttributes = 0; 59 } 60 }; 61 62 struct ContainerInfo : public CXIdxContainerInfo { 63 const DeclContext *DC; 64 CXIndexDataConsumer *IndexCtx; 65 }; 66 67 struct DeclInfo : public CXIdxDeclInfo { 68 enum DInfoKind { 69 Info_Decl, 70 71 Info_ObjCContainer, 72 Info_ObjCInterface, 73 Info_ObjCProtocol, 74 Info_ObjCCategory, 75 76 Info_ObjCProperty, 77 78 Info_CXXClass 79 }; 80 81 DInfoKind Kind; 82 83 EntityInfo EntInfo; 84 ContainerInfo SemanticContainer; 85 ContainerInfo LexicalContainer; 86 ContainerInfo DeclAsContainer; 87 88 DeclInfo(bool isRedeclaration, bool isDefinition, bool isContainer) 89 : Kind(Info_Decl) { 90 this->isRedeclaration = isRedeclaration; 91 this->isDefinition = isDefinition; 92 this->isContainer = isContainer; 93 attributes = nullptr; 94 numAttributes = 0; 95 declAsContainer = semanticContainer = lexicalContainer = nullptr; 96 flags = 0; 97 } 98 DeclInfo(DInfoKind K, 99 bool isRedeclaration, bool isDefinition, bool isContainer) 100 : Kind(K) { 101 this->isRedeclaration = isRedeclaration; 102 this->isDefinition = isDefinition; 103 this->isContainer = isContainer; 104 attributes = nullptr; 105 numAttributes = 0; 106 declAsContainer = semanticContainer = lexicalContainer = nullptr; 107 flags = 0; 108 } 109 }; 110 111 struct ObjCContainerDeclInfo : public DeclInfo { 112 CXIdxObjCContainerDeclInfo ObjCContDeclInfo; 113 114 ObjCContainerDeclInfo(bool isForwardRef, 115 bool isRedeclaration, 116 bool isImplementation) 117 : DeclInfo(Info_ObjCContainer, isRedeclaration, 118 /*isDefinition=*/!isForwardRef, /*isContainer=*/!isForwardRef) { 119 init(isForwardRef, isImplementation); 120 } 121 ObjCContainerDeclInfo(DInfoKind K, 122 bool isForwardRef, 123 bool isRedeclaration, 124 bool isImplementation) 125 : DeclInfo(K, isRedeclaration, /*isDefinition=*/!isForwardRef, 126 /*isContainer=*/!isForwardRef) { 127 init(isForwardRef, isImplementation); 128 } 129 130 static bool classof(const DeclInfo *D) { 131 return Info_ObjCContainer <= D->Kind && D->Kind <= Info_ObjCCategory; 132 } 133 134 private: 135 void init(bool isForwardRef, bool isImplementation) { 136 if (isForwardRef) 137 ObjCContDeclInfo.kind = CXIdxObjCContainer_ForwardRef; 138 else if (isImplementation) 139 ObjCContDeclInfo.kind = CXIdxObjCContainer_Implementation; 140 else 141 ObjCContDeclInfo.kind = CXIdxObjCContainer_Interface; 142 } 143 }; 144 145 struct ObjCInterfaceDeclInfo : public ObjCContainerDeclInfo { 146 CXIdxObjCInterfaceDeclInfo ObjCInterDeclInfo; 147 CXIdxObjCProtocolRefListInfo ObjCProtoListInfo; 148 149 ObjCInterfaceDeclInfo(const ObjCInterfaceDecl *D) 150 : ObjCContainerDeclInfo(Info_ObjCInterface, 151 /*isForwardRef=*/false, 152 /*isRedeclaration=*/D->getPreviousDecl() != nullptr, 153 /*isImplementation=*/false) { } 154 155 static bool classof(const DeclInfo *D) { 156 return D->Kind == Info_ObjCInterface; 157 } 158 }; 159 160 struct ObjCProtocolDeclInfo : public ObjCContainerDeclInfo { 161 CXIdxObjCProtocolRefListInfo ObjCProtoRefListInfo; 162 163 ObjCProtocolDeclInfo(const ObjCProtocolDecl *D) 164 : ObjCContainerDeclInfo(Info_ObjCProtocol, 165 /*isForwardRef=*/false, 166 /*isRedeclaration=*/D->getPreviousDecl(), 167 /*isImplementation=*/false) { } 168 169 static bool classof(const DeclInfo *D) { 170 return D->Kind == Info_ObjCProtocol; 171 } 172 }; 173 174 struct ObjCCategoryDeclInfo : public ObjCContainerDeclInfo { 175 CXIdxObjCCategoryDeclInfo ObjCCatDeclInfo; 176 CXIdxObjCProtocolRefListInfo ObjCProtoListInfo; 177 178 explicit ObjCCategoryDeclInfo(bool isImplementation) 179 : ObjCContainerDeclInfo(Info_ObjCCategory, 180 /*isForwardRef=*/false, 181 /*isRedeclaration=*/isImplementation, 182 /*isImplementation=*/isImplementation) { } 183 184 static bool classof(const DeclInfo *D) { 185 return D->Kind == Info_ObjCCategory; 186 } 187 }; 188 189 struct 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 }; 201 202 struct CXXClassDeclInfo : public DeclInfo { 203 CXIdxCXXClassDeclInfo CXXClassInfo; 204 205 CXXClassDeclInfo(bool isRedeclaration, bool isDefinition) 206 : DeclInfo(Info_CXXClass, isRedeclaration, isDefinition, isDefinition) { } 207 208 static bool classof(const DeclInfo *D) { 209 return D->Kind == Info_CXXClass; 210 } 211 }; 212 213 struct AttrInfo : public CXIdxAttrInfo { 214 const Attr *A; 215 216 AttrInfo(CXIdxAttrKind Kind, CXCursor C, CXIdxLoc Loc, const Attr *A) { 217 kind = Kind; 218 cursor = C; 219 loc = Loc; 220 this->A = A; 221 } 222 }; 223 224 struct IBOutletCollectionInfo : public AttrInfo { 225 EntityInfo ClassInfo; 226 CXIdxIBOutletCollectionAttrInfo IBCollInfo; 227 228 IBOutletCollectionInfo(CXCursor C, CXIdxLoc Loc, const Attr *A) : 229 AttrInfo(CXIdxAttr_IBOutletCollection, C, Loc, A) { 230 assert(C.kind == CXCursor_IBOutletCollectionAttr); 231 IBCollInfo.objcClass = nullptr; 232 } 233 234 IBOutletCollectionInfo(const IBOutletCollectionInfo &other); 235 236 static bool classof(const AttrInfo *A) { 237 return A->kind == CXIdxAttr_IBOutletCollection; 238 } 239 }; 240 241 class AttrListInfo { 242 ScratchAlloc SA; 243 244 SmallVector<AttrInfo, 2> Attrs; 245 SmallVector<IBOutletCollectionInfo, 2> IBCollAttrs; 246 SmallVector<CXIdxAttrInfo *, 2> CXAttrs; 247 unsigned ref_cnt; 248 249 AttrListInfo(const AttrListInfo &) = delete; 250 void operator=(const AttrListInfo &) = delete; 251 public: 252 AttrListInfo(const Decl *D, CXIndexDataConsumer &IdxCtx); 253 254 static IntrusiveRefCntPtr<AttrListInfo> create(const Decl *D, 255 CXIndexDataConsumer &IdxCtx); 256 257 const CXIdxAttrInfo *const *getAttrs() const { 258 if (CXAttrs.empty()) 259 return nullptr; 260 return CXAttrs.data(); 261 } 262 unsigned getNumAttrs() const { return (unsigned)CXAttrs.size(); } 263 264 /// \brief Retain/Release only useful when we allocate a AttrListInfo from the 265 /// BumpPtrAllocator, and not from the stack; so that we keep a pointer 266 // in the EntityInfo 267 void Retain() { ++ref_cnt; } 268 void Release() { 269 assert (ref_cnt > 0 && "Reference count is already zero."); 270 if (--ref_cnt == 0) { 271 // Memory is allocated from a BumpPtrAllocator, no need to delete it. 272 this->~AttrListInfo(); 273 } 274 } 275 }; 276 277 class CXIndexDataConsumer : public index::IndexDataConsumer { 278 ASTContext *Ctx; 279 CXClientData ClientData; 280 IndexerCallbacks &CB; 281 unsigned IndexOptions; 282 CXTranslationUnit CXTU; 283 284 typedef llvm::DenseMap<const FileEntry *, CXIdxClientFile> FileMapTy; 285 typedef llvm::DenseMap<const DeclContext *, CXIdxClientContainer> 286 ContainerMapTy; 287 typedef llvm::DenseMap<const Decl *, CXIdxClientEntity> EntityMapTy; 288 289 FileMapTy FileMap; 290 ContainerMapTy ContainerMap; 291 EntityMapTy EntityMap; 292 293 typedef std::pair<const FileEntry *, const Decl *> RefFileOccurrence; 294 llvm::DenseSet<RefFileOccurrence> RefFileOccurrences; 295 296 llvm::BumpPtrAllocator StrScratch; 297 unsigned StrAdapterCount; 298 friend class ScratchAlloc; 299 300 struct ObjCProtocolListInfo { 301 SmallVector<CXIdxObjCProtocolRefInfo, 4> ProtInfos; 302 SmallVector<EntityInfo, 4> ProtEntities; 303 SmallVector<CXIdxObjCProtocolRefInfo *, 4> Prots; 304 305 CXIdxObjCProtocolRefListInfo getListInfo() const { 306 CXIdxObjCProtocolRefListInfo Info = { Prots.data(), 307 (unsigned)Prots.size() }; 308 return Info; 309 } 310 311 ObjCProtocolListInfo(const ObjCProtocolList &ProtList, 312 CXIndexDataConsumer &IdxCtx, 313 ScratchAlloc &SA); 314 }; 315 316 struct CXXBasesListInfo { 317 SmallVector<CXIdxBaseClassInfo, 4> BaseInfos; 318 SmallVector<EntityInfo, 4> BaseEntities; 319 SmallVector<CXIdxBaseClassInfo *, 4> CXBases; 320 321 const CXIdxBaseClassInfo *const *getBases() const { 322 return CXBases.data(); 323 } 324 unsigned getNumBases() const { return (unsigned)CXBases.size(); } 325 326 CXXBasesListInfo(const CXXRecordDecl *D, 327 CXIndexDataConsumer &IdxCtx, ScratchAlloc &SA); 328 329 private: 330 SourceLocation getBaseLoc(const CXXBaseSpecifier &Base) const; 331 }; 332 333 friend class AttrListInfo; 334 335 public: 336 CXIndexDataConsumer(CXClientData clientData, IndexerCallbacks &indexCallbacks, 337 unsigned indexOptions, CXTranslationUnit cxTU) 338 : Ctx(nullptr), ClientData(clientData), CB(indexCallbacks), 339 IndexOptions(indexOptions), CXTU(cxTU), 340 StrScratch(), StrAdapterCount(0) { } 341 342 ASTContext &getASTContext() const { return *Ctx; } 343 CXTranslationUnit getCXTU() const { return CXTU; } 344 345 void setASTContext(ASTContext &ctx); 346 void setPreprocessor(Preprocessor &PP); 347 348 bool shouldSuppressRefs() const { 349 return IndexOptions & CXIndexOpt_SuppressRedundantRefs; 350 } 351 352 bool shouldIndexFunctionLocalSymbols() const { 353 return IndexOptions & CXIndexOpt_IndexFunctionLocalSymbols; 354 } 355 356 bool shouldIndexImplicitTemplateInsts() const { 357 return IndexOptions & CXIndexOpt_IndexImplicitTemplateInstantiations; 358 } 359 360 static bool isFunctionLocalDecl(const Decl *D); 361 362 bool shouldAbort(); 363 364 bool hasDiagnosticCallback() const { return CB.diagnostic; } 365 366 void enteredMainFile(const FileEntry *File); 367 368 void ppIncludedFile(SourceLocation hashLoc, 369 StringRef filename, const FileEntry *File, 370 bool isImport, bool isAngled, bool isModuleImport); 371 372 void importedModule(const ImportDecl *ImportD); 373 void importedPCH(const FileEntry *File); 374 375 void startedTranslationUnit(); 376 377 void indexDecl(const Decl *D); 378 379 void indexTagDecl(const TagDecl *D); 380 381 void indexTypeSourceInfo(TypeSourceInfo *TInfo, const NamedDecl *Parent, 382 const DeclContext *DC = nullptr); 383 384 void indexTypeLoc(TypeLoc TL, const NamedDecl *Parent, 385 const DeclContext *DC = nullptr); 386 387 void indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, 388 const NamedDecl *Parent, 389 const DeclContext *DC = nullptr); 390 391 void indexDeclContext(const DeclContext *DC); 392 393 void indexBody(const Stmt *S, const NamedDecl *Parent, 394 const DeclContext *DC = nullptr); 395 396 void indexDiagnostics(); 397 398 void handleDiagnosticSet(CXDiagnosticSet CXDiagSet); 399 400 bool handleFunction(const FunctionDecl *FD); 401 402 bool handleVar(const VarDecl *D); 403 404 bool handleField(const FieldDecl *D); 405 406 bool handleMSProperty(const MSPropertyDecl *D); 407 408 bool handleEnumerator(const EnumConstantDecl *D); 409 410 bool handleTagDecl(const TagDecl *D); 411 412 bool handleTypedefName(const TypedefNameDecl *D); 413 414 bool handleObjCInterface(const ObjCInterfaceDecl *D); 415 bool handleObjCImplementation(const ObjCImplementationDecl *D); 416 417 bool handleObjCProtocol(const ObjCProtocolDecl *D); 418 419 bool handleObjCCategory(const ObjCCategoryDecl *D); 420 bool handleObjCCategoryImpl(const ObjCCategoryImplDecl *D); 421 422 bool handleObjCMethod(const ObjCMethodDecl *D); 423 424 bool handleSynthesizedObjCProperty(const ObjCPropertyImplDecl *D); 425 bool handleSynthesizedObjCMethod(const ObjCMethodDecl *D, SourceLocation Loc, 426 const DeclContext *LexicalDC); 427 428 bool handleObjCProperty(const ObjCPropertyDecl *D); 429 430 bool handleNamespace(const NamespaceDecl *D); 431 432 bool handleClassTemplate(const ClassTemplateDecl *D); 433 bool handleFunctionTemplate(const FunctionTemplateDecl *D); 434 bool handleTypeAliasTemplate(const TypeAliasTemplateDecl *D); 435 436 bool handleReference(const NamedDecl *D, SourceLocation Loc, CXCursor Cursor, 437 const NamedDecl *Parent, 438 const DeclContext *DC, 439 const Expr *E = nullptr, 440 CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct); 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 448 bool isNotFromSourceFile(SourceLocation Loc) const; 449 450 void indexTopLevelDecl(const Decl *D); 451 void indexDeclGroupRef(DeclGroupRef DG); 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 handleDeclOccurence(const Decl *D, index::SymbolRoleSet Roles, 466 ArrayRef<index::SymbolRelation> Relations, 467 FileID FID, unsigned Offset, 468 ASTNodeInfo ASTNode) override; 469 470 bool handleModuleOccurence(const ImportDecl *ImportD, 471 index::SymbolRoleSet Roles, 472 FileID FID, unsigned Offset) 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 534