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