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 #ifndef LLVM_CLANG_TOOLS_LIBCLANG_INDEXINGCONTEXT_H 11 #define LLVM_CLANG_TOOLS_LIBCLANG_INDEXINGCONTEXT_H 12 13 #include "CXCursor.h" 14 #include "Index_Internal.h" 15 #include "clang/AST/DeclGroup.h" 16 #include "clang/AST/DeclObjC.h" 17 #include "llvm/ADT/DenseSet.h" 18 #include <deque> 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 IndexingContext; 31 class AttrListInfo; 32 33 class ScratchAlloc { 34 IndexingContext &IdxCtx; 35 36 public: 37 explicit ScratchAlloc(IndexingContext &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 IndexingContext *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 IndexingContext *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, IndexingContext &IdxCtx); 252 253 static IntrusiveRefCntPtr<AttrListInfo> create(const Decl *D, 254 IndexingContext &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 /// \brief 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 IndexingContext { 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 std::deque<DeclGroupRef> TUDeclsInObjCContainer; 296 297 llvm::BumpPtrAllocator StrScratch; 298 unsigned StrAdapterCount; 299 friend class ScratchAlloc; 300 301 struct ObjCProtocolListInfo { 302 SmallVector<CXIdxObjCProtocolRefInfo, 4> ProtInfos; 303 SmallVector<EntityInfo, 4> ProtEntities; 304 SmallVector<CXIdxObjCProtocolRefInfo *, 4> Prots; 305 306 CXIdxObjCProtocolRefListInfo getListInfo() const { 307 CXIdxObjCProtocolRefListInfo Info = { Prots.data(), 308 (unsigned)Prots.size() }; 309 return Info; 310 } 311 312 ObjCProtocolListInfo(const ObjCProtocolList &ProtList, 313 IndexingContext &IdxCtx, 314 ScratchAlloc &SA); 315 }; 316 317 struct CXXBasesListInfo { 318 SmallVector<CXIdxBaseClassInfo, 4> BaseInfos; 319 SmallVector<EntityInfo, 4> BaseEntities; 320 SmallVector<CXIdxBaseClassInfo *, 4> CXBases; 321 322 const CXIdxBaseClassInfo *const *getBases() const { 323 return CXBases.data(); 324 } 325 unsigned getNumBases() const { return (unsigned)CXBases.size(); } 326 327 CXXBasesListInfo(const CXXRecordDecl *D, 328 IndexingContext &IdxCtx, ScratchAlloc &SA); 329 330 private: 331 SourceLocation getBaseLoc(const CXXBaseSpecifier &Base) const; 332 }; 333 334 friend class AttrListInfo; 335 336 public: 337 IndexingContext(CXClientData clientData, IndexerCallbacks &indexCallbacks, 338 unsigned indexOptions, CXTranslationUnit cxTU) 339 : Ctx(nullptr), ClientData(clientData), CB(indexCallbacks), 340 IndexOptions(indexOptions), CXTU(cxTU), 341 StrScratch(), StrAdapterCount(0) { } 342 343 ASTContext &getASTContext() const { return *Ctx; } 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 handleDiagnosticSet(CXDiagnosticSet CXDiagSet); 397 398 bool handleFunction(const FunctionDecl *FD); 399 400 bool handleVar(const VarDecl *D); 401 402 bool handleField(const FieldDecl *D); 403 404 bool handleMSProperty(const MSPropertyDecl *D); 405 406 bool handleEnumerator(const EnumConstantDecl *D); 407 408 bool handleTagDecl(const TagDecl *D); 409 410 bool handleTypedefName(const TypedefNameDecl *D); 411 412 bool handleObjCInterface(const ObjCInterfaceDecl *D); 413 bool handleObjCImplementation(const ObjCImplementationDecl *D); 414 415 bool handleObjCProtocol(const ObjCProtocolDecl *D); 416 417 bool handleObjCCategory(const ObjCCategoryDecl *D); 418 bool handleObjCCategoryImpl(const ObjCCategoryImplDecl *D); 419 420 bool handleObjCMethod(const ObjCMethodDecl *D); 421 422 bool handleSynthesizedObjCProperty(const ObjCPropertyImplDecl *D); 423 bool handleSynthesizedObjCMethod(const ObjCMethodDecl *D, SourceLocation Loc, 424 const DeclContext *LexicalDC); 425 426 bool handleObjCProperty(const ObjCPropertyDecl *D); 427 428 bool handleNamespace(const NamespaceDecl *D); 429 430 bool handleClassTemplate(const ClassTemplateDecl *D); 431 bool handleFunctionTemplate(const FunctionTemplateDecl *D); 432 bool handleTypeAliasTemplate(const TypeAliasTemplateDecl *D); 433 434 bool handleReference(const NamedDecl *D, SourceLocation Loc, CXCursor Cursor, 435 const NamedDecl *Parent, 436 const DeclContext *DC, 437 const Expr *E = nullptr, 438 CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct); 439 440 bool handleReference(const NamedDecl *D, SourceLocation Loc, 441 const NamedDecl *Parent, 442 const DeclContext *DC, 443 const Expr *E = nullptr, 444 CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct); 445 446 bool isNotFromSourceFile(SourceLocation Loc) const; 447 448 void indexTopLevelDecl(const Decl *D); 449 void indexTUDeclsInObjCContainer(); 450 void indexDeclGroupRef(DeclGroupRef DG); 451 452 void addTUDeclInObjCContainer(DeclGroupRef DG) { 453 TUDeclsInObjCContainer.push_back(DG); 454 } 455 456 void translateLoc(SourceLocation Loc, CXIdxClientFile *indexFile, CXFile *file, 457 unsigned *line, unsigned *column, unsigned *offset); 458 459 CXIdxClientContainer getClientContainerForDC(const DeclContext *DC) const; 460 void addContainerInMap(const DeclContext *DC, CXIdxClientContainer container); 461 462 CXIdxClientEntity getClientEntity(const Decl *D) const; 463 void setClientEntity(const Decl *D, CXIdxClientEntity client); 464 465 static bool isTemplateImplicitInstantiation(const Decl *D); 466 467 private: 468 bool handleDecl(const NamedDecl *D, 469 SourceLocation Loc, CXCursor Cursor, 470 DeclInfo &DInfo, 471 const DeclContext *LexicalDC = nullptr); 472 473 bool handleObjCContainer(const ObjCContainerDecl *D, 474 SourceLocation Loc, CXCursor Cursor, 475 ObjCContainerDeclInfo &ContDInfo); 476 477 bool handleCXXRecordDecl(const CXXRecordDecl *RD, const NamedDecl *OrigD); 478 479 bool markEntityOccurrenceInFile(const NamedDecl *D, SourceLocation Loc); 480 481 const NamedDecl *getEntityDecl(const NamedDecl *D) const; 482 483 const DeclContext *getEntityContainer(const Decl *D) const; 484 485 CXIdxClientFile getIndexFile(const FileEntry *File); 486 487 CXIdxLoc getIndexLoc(SourceLocation Loc) const; 488 489 void getEntityInfo(const NamedDecl *D, 490 EntityInfo &EntityInfo, 491 ScratchAlloc &SA); 492 493 void getContainerInfo(const DeclContext *DC, ContainerInfo &ContInfo); 494 495 CXCursor getCursor(const Decl *D) { 496 return cxcursor::MakeCXCursor(D, CXTU); 497 } 498 499 CXCursor getRefCursor(const NamedDecl *D, SourceLocation Loc); 500 501 static bool shouldIgnoreIfImplicit(const Decl *D); 502 }; 503 504 inline ScratchAlloc::ScratchAlloc(IndexingContext &idxCtx) : IdxCtx(idxCtx) { 505 ++IdxCtx.StrAdapterCount; 506 } 507 inline ScratchAlloc::ScratchAlloc(const ScratchAlloc &SA) : IdxCtx(SA.IdxCtx) { 508 ++IdxCtx.StrAdapterCount; 509 } 510 511 inline ScratchAlloc::~ScratchAlloc() { 512 --IdxCtx.StrAdapterCount; 513 if (IdxCtx.StrAdapterCount == 0) 514 IdxCtx.StrScratch.Reset(); 515 } 516 517 template <typename T> 518 inline T *ScratchAlloc::allocate() { 519 return IdxCtx.StrScratch.Allocate<T>(); 520 } 521 522 }} // end clang::cxindex 523 524 #endif 525