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