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