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