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