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