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