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