IndexingContext.h revision 996e6e564af7483e2d5e0b70df5fdb9f79ec4b5a
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 bool hasDiagnosticCallback() const { return CB.diagnostic; } 316 317 void enteredMainFile(const FileEntry *File); 318 319 void ppIncludedFile(SourceLocation hashLoc, 320 StringRef filename, const FileEntry *File, 321 bool isImport, bool isAngled); 322 323 void startedTranslationUnit(); 324 325 void indexDecl(const Decl *D); 326 327 void indexTagDecl(const TagDecl *D); 328 329 void indexTypeSourceInfo(TypeSourceInfo *TInfo, const NamedDecl *Parent, 330 const DeclContext *DC = 0); 331 332 void indexTypeLoc(TypeLoc TL, const NamedDecl *Parent, 333 const DeclContext *DC); 334 335 void indexDeclContext(const DeclContext *DC); 336 337 void indexBody(const Stmt *S, const DeclContext *DC); 338 339 void handleDiagnosticSet(CXDiagnosticSet CXDiagSet); 340 341 bool handleFunction(const FunctionDecl *FD); 342 343 bool handleVar(const VarDecl *D); 344 345 bool handleField(const FieldDecl *D); 346 347 bool handleEnumerator(const EnumConstantDecl *D); 348 349 bool handleTagDecl(const TagDecl *D); 350 351 bool handleTypedefName(const TypedefNameDecl *D); 352 353 bool handleObjCClass(const ObjCClassDecl *D); 354 bool handleObjCInterface(const ObjCInterfaceDecl *D); 355 bool handleObjCImplementation(const ObjCImplementationDecl *D); 356 357 bool handleObjCForwardProtocol(const ObjCProtocolDecl *D, 358 SourceLocation Loc, 359 bool isRedeclaration); 360 361 bool handleObjCProtocol(const ObjCProtocolDecl *D); 362 363 bool handleObjCCategory(const ObjCCategoryDecl *D); 364 bool handleObjCCategoryImpl(const ObjCCategoryImplDecl *D); 365 366 bool handleObjCMethod(const ObjCMethodDecl *D); 367 368 bool handleSynthesizedObjCProperty(const ObjCPropertyImplDecl *D); 369 bool handleSynthesizedObjCMethod(const ObjCMethodDecl *D, SourceLocation Loc); 370 371 bool handleObjCProperty(const ObjCPropertyDecl *D); 372 373 bool handleClassTemplate(const ClassTemplateDecl *D); 374 bool handleFunctionTemplate(const FunctionTemplateDecl *D); 375 bool handleTypeAliasTemplate(const TypeAliasTemplateDecl *D); 376 377 bool handleReference(const NamedDecl *D, SourceLocation Loc, CXCursor Cursor, 378 const NamedDecl *Parent, 379 const DeclContext *DC, 380 const Expr *E = 0, 381 CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct); 382 383 bool handleReference(const NamedDecl *D, SourceLocation Loc, 384 const NamedDecl *Parent, 385 const DeclContext *DC, 386 const Expr *E = 0, 387 CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct); 388 389 bool isNotFromSourceFile(SourceLocation Loc) const; 390 391 void indexTopLevelDecl(Decl *D); 392 void indexTUDeclsInObjCContainer(); 393 void indexDeclGroupRef(DeclGroupRef DG); 394 395 void addTUDeclInObjCContainer(DeclGroupRef DG) { 396 TUDeclsInObjCContainer.push_back(DG); 397 } 398 399 void translateLoc(SourceLocation Loc, CXIdxClientFile *indexFile, CXFile *file, 400 unsigned *line, unsigned *column, unsigned *offset); 401 402 CXIdxClientContainer getClientContainerForDC(const DeclContext *DC) const; 403 void addContainerInMap(const DeclContext *DC, CXIdxClientContainer container); 404 405 CXIdxClientEntity getClientEntity(const Decl *D) const; 406 void setClientEntity(const Decl *D, CXIdxClientEntity client); 407 408private: 409 bool handleDecl(const NamedDecl *D, 410 SourceLocation Loc, CXCursor Cursor, 411 DeclInfo &DInfo); 412 413 bool handleObjCContainer(const ObjCContainerDecl *D, 414 SourceLocation Loc, CXCursor Cursor, 415 ObjCContainerDeclInfo &ContDInfo); 416 417 bool handleCXXRecordDecl(const CXXRecordDecl *RD, const NamedDecl *OrigD); 418 419 bool markEntityOccurrenceInFile(const NamedDecl *D, SourceLocation Loc); 420 421 const NamedDecl *getEntityDecl(const NamedDecl *D) const; 422 423 const DeclContext *getEntityContainer(const Decl *D) const; 424 425 CXIdxClientContainer getClientContainer(const NamedDecl *D) const { 426 return getClientContainerForDC(D->getDeclContext()); 427 } 428 429 const DeclContext *getScopedContext(const DeclContext *DC) const; 430 431 CXIdxClientFile getIndexFile(const FileEntry *File); 432 433 CXIdxLoc getIndexLoc(SourceLocation Loc) const; 434 435 void getEntityInfo(const NamedDecl *D, 436 EntityInfo &EntityInfo, 437 StrAdapter &SA); 438 439 void getContainerInfo(const DeclContext *DC, ContainerInfo &ContInfo); 440 441 CXCursor getCursor(const Decl *D) { 442 return cxcursor::MakeCXCursor(const_cast<Decl*>(D), CXTU); 443 } 444 445 CXCursor getRefCursor(const NamedDecl *D, SourceLocation Loc); 446 447 static bool shouldIgnoreIfImplicit(const NamedDecl *D); 448}; 449 450}} // end clang::cxindex 451 452namespace llvm { 453 /// Define DenseMapInfo so that FileID's can be used as keys in DenseMap and 454 /// DenseSets. 455 template <> 456 struct DenseMapInfo<clang::cxindex::RefFileOccurence> { 457 static inline clang::cxindex::RefFileOccurence getEmptyKey() { 458 return clang::cxindex::RefFileOccurence(0, 0); 459 } 460 461 static inline clang::cxindex::RefFileOccurence getTombstoneKey() { 462 return clang::cxindex::RefFileOccurence((const clang::FileEntry *)~0, 463 (const clang::Decl *)~0); 464 } 465 466 static unsigned getHashValue(clang::cxindex::RefFileOccurence S) { 467 llvm::FoldingSetNodeID ID; 468 ID.AddPointer(S.File); 469 ID.AddPointer(S.Dcl); 470 return ID.ComputeHash(); 471 } 472 473 static bool isEqual(clang::cxindex::RefFileOccurence LHS, 474 clang::cxindex::RefFileOccurence RHS) { 475 return LHS.File == RHS.File && LHS.Dcl == RHS.Dcl; 476 } 477 }; 478} 479