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), 338 StrScratch(), StrAdapterCount(0) { } 339 340 ASTContext &getASTContext() const { return *Ctx; } 341 CXTranslationUnit getCXTU() const { return CXTU; } 342 343 void setASTContext(ASTContext &ctx); 344 void setPreprocessor(std::shared_ptr<Preprocessor> PP) override; 345 346 bool shouldSuppressRefs() const { 347 return IndexOptions & CXIndexOpt_SuppressRedundantRefs; 348 } 349 350 bool shouldIndexFunctionLocalSymbols() const { 351 return IndexOptions & CXIndexOpt_IndexFunctionLocalSymbols; 352 } 353 354 bool shouldIndexImplicitTemplateInsts() const { 355 return IndexOptions & CXIndexOpt_IndexImplicitTemplateInstantiations; 356 } 357 358 static bool isFunctionLocalDecl(const Decl *D); 359 360 bool shouldAbort(); 361 362 bool hasDiagnosticCallback() const { return CB.diagnostic; } 363 364 void enteredMainFile(const FileEntry *File); 365 366 void ppIncludedFile(SourceLocation hashLoc, 367 StringRef filename, const FileEntry *File, 368 bool isImport, bool isAngled, bool isModuleImport); 369 370 void importedModule(const ImportDecl *ImportD); 371 void importedPCH(const FileEntry *File); 372 373 void startedTranslationUnit(); 374 375 void indexDiagnostics(); 376 377 void handleDiagnosticSet(CXDiagnosticSet CXDiagSet); 378 379 bool handleFunction(const FunctionDecl *FD); 380 381 bool handleVar(const VarDecl *D); 382 383 bool handleField(const FieldDecl *D); 384 385 bool handleEnumerator(const EnumConstantDecl *D); 386 387 bool handleTagDecl(const TagDecl *D); 388 389 bool handleTypedefName(const TypedefNameDecl *D); 390 391 bool handleObjCInterface(const ObjCInterfaceDecl *D); 392 bool handleObjCImplementation(const ObjCImplementationDecl *D); 393 394 bool handleObjCProtocol(const ObjCProtocolDecl *D); 395 396 bool handleObjCCategory(const ObjCCategoryDecl *D); 397 bool handleObjCCategoryImpl(const ObjCCategoryImplDecl *D); 398 399 bool handleObjCMethod(const ObjCMethodDecl *D, SourceLocation Loc); 400 401 bool handleSynthesizedObjCProperty(const ObjCPropertyImplDecl *D); 402 bool handleSynthesizedObjCMethod(const ObjCMethodDecl *D, SourceLocation Loc, 403 const DeclContext *LexicalDC); 404 405 bool handleObjCProperty(const ObjCPropertyDecl *D); 406 407 bool handleNamespace(const NamespaceDecl *D); 408 409 bool handleClassTemplate(const ClassTemplateDecl *D); 410 bool handleFunctionTemplate(const FunctionTemplateDecl *D); 411 bool handleTypeAliasTemplate(const TypeAliasTemplateDecl *D); 412 413 bool handleReference(const NamedDecl *D, SourceLocation Loc, CXCursor Cursor, 414 const NamedDecl *Parent, 415 const DeclContext *DC, 416 const Expr *E = nullptr, 417 CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct, 418 CXSymbolRole Role = CXSymbolRole_None); 419 420 bool isNotFromSourceFile(SourceLocation Loc) const; 421 422 void translateLoc(SourceLocation Loc, CXIdxClientFile *indexFile, CXFile *file, 423 unsigned *line, unsigned *column, unsigned *offset); 424 425 CXIdxClientContainer getClientContainerForDC(const DeclContext *DC) const; 426 void addContainerInMap(const DeclContext *DC, CXIdxClientContainer container); 427 428 CXIdxClientEntity getClientEntity(const Decl *D) const; 429 void setClientEntity(const Decl *D, CXIdxClientEntity client); 430 431 static bool isTemplateImplicitInstantiation(const Decl *D); 432 433 private: 434 bool handleDeclOccurrence(const Decl *D, index::SymbolRoleSet Roles, 435 ArrayRef<index::SymbolRelation> Relations, 436 SourceLocation Loc, ASTNodeInfo ASTNode) override; 437 438 bool handleModuleOccurrence(const ImportDecl *ImportD, const Module *Mod, 439 index::SymbolRoleSet Roles, 440 SourceLocation Loc) override; 441 442 void finish() override; 443 444 bool handleDecl(const NamedDecl *D, 445 SourceLocation Loc, CXCursor Cursor, 446 DeclInfo &DInfo, 447 const DeclContext *LexicalDC = nullptr, 448 const DeclContext *SemaDC = nullptr); 449 450 bool handleObjCContainer(const ObjCContainerDecl *D, 451 SourceLocation Loc, CXCursor Cursor, 452 ObjCContainerDeclInfo &ContDInfo); 453 454 bool handleCXXRecordDecl(const CXXRecordDecl *RD, const NamedDecl *OrigD); 455 456 bool markEntityOccurrenceInFile(const NamedDecl *D, SourceLocation Loc); 457 458 const NamedDecl *getEntityDecl(const NamedDecl *D) const; 459 460 const DeclContext *getEntityContainer(const Decl *D) const; 461 462 CXIdxClientFile getIndexFile(const FileEntry *File); 463 464 CXIdxLoc getIndexLoc(SourceLocation Loc) const; 465 466 void getEntityInfo(const NamedDecl *D, 467 EntityInfo &EntityInfo, 468 ScratchAlloc &SA); 469 470 void getContainerInfo(const DeclContext *DC, ContainerInfo &ContInfo); 471 472 CXCursor getCursor(const Decl *D) { 473 return cxcursor::MakeCXCursor(D, CXTU); 474 } 475 476 CXCursor getRefCursor(const NamedDecl *D, SourceLocation Loc); 477 478 static bool shouldIgnoreIfImplicit(const Decl *D); 479 }; 480 481 inline ScratchAlloc::ScratchAlloc(CXIndexDataConsumer &idxCtx) : IdxCtx(idxCtx) { 482 ++IdxCtx.StrAdapterCount; 483 } 484 inline ScratchAlloc::ScratchAlloc(const ScratchAlloc &SA) : IdxCtx(SA.IdxCtx) { 485 ++IdxCtx.StrAdapterCount; 486 } 487 488 inline ScratchAlloc::~ScratchAlloc() { 489 --IdxCtx.StrAdapterCount; 490 if (IdxCtx.StrAdapterCount == 0) 491 IdxCtx.StrScratch.Reset(); 492 } 493 494 template <typename T> 495 inline T *ScratchAlloc::allocate() { 496 return IdxCtx.StrScratch.Allocate<T>(); 497 } 498 499 }} // end clang::cxindex 500 501 #endif 502