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