IndexingContext.cpp revision 2957e6f8c4c2e58a4b9cb639949fea801970fe36
1//===- CIndexHigh.cpp - 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 "IndexingContext.h" 11#include "CXTranslationUnit.h" 12#include "CIndexDiagnostic.h" 13 14#include "clang/Frontend/ASTUnit.h" 15#include "clang/AST/DeclCXX.h" 16#include "clang/AST/DeclTemplate.h" 17 18using namespace clang; 19using namespace cxindex; 20using namespace cxcursor; 21 22IndexingContext::ObjCProtocolListInfo::ObjCProtocolListInfo( 23 const ObjCProtocolList &ProtList, 24 IndexingContext &IdxCtx, 25 StrAdapter &SA) { 26 ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin(); 27 for (ObjCInterfaceDecl::protocol_iterator 28 I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) { 29 SourceLocation Loc = *LI; 30 ObjCProtocolDecl *PD = *I; 31 ProtEntities.push_back(EntityInfo()); 32 IdxCtx.getEntityInfo(PD, ProtEntities.back(), SA); 33 CXIdxObjCProtocolRefInfo ProtInfo = { 0, 34 MakeCursorObjCProtocolRef(PD, Loc, IdxCtx.CXTU), 35 IdxCtx.getIndexLoc(Loc) }; 36 ProtInfos.push_back(ProtInfo); 37 } 38 39 for (unsigned i = 0, e = ProtInfos.size(); i != e; ++i) 40 ProtInfos[i].protocol = &ProtEntities[i]; 41 42 for (unsigned i = 0, e = ProtInfos.size(); i != e; ++i) 43 Prots.push_back(&ProtInfos[i]); 44} 45 46IndexingContext::AttrListInfo::AttrListInfo(const Decl *D, 47 IndexingContext &IdxCtx, 48 StrAdapter &SA) { 49 for (AttrVec::const_iterator AttrI = D->attr_begin(), AttrE = D->attr_end(); 50 AttrI != AttrE; ++AttrI) { 51 const Attr *A = *AttrI; 52 CXCursor C = MakeCXCursor(A, const_cast<Decl *>(D), IdxCtx.CXTU); 53 CXIdxLoc Loc = IdxCtx.getIndexLoc(A->getLocation()); 54 switch (C.kind) { 55 default: 56 Attrs.push_back(AttrInfo(CXIdxAttr_Unexposed, C, Loc, A)); 57 break; 58 case CXCursor_IBActionAttr: 59 Attrs.push_back(AttrInfo(CXIdxAttr_IBAction, C, Loc, A)); 60 break; 61 case CXCursor_IBOutletAttr: 62 Attrs.push_back(AttrInfo(CXIdxAttr_IBOutlet, C, Loc, A)); 63 break; 64 case CXCursor_IBOutletCollectionAttr: 65 IBCollAttrs.push_back(IBOutletCollectionInfo(C, Loc, A)); 66 break; 67 } 68 } 69 70 for (unsigned i = 0, e = IBCollAttrs.size(); i != e; ++i) { 71 IBOutletCollectionInfo &IBInfo = IBCollAttrs[i]; 72 CXAttrs.push_back(&IBInfo); 73 74 const IBOutletCollectionAttr * 75 IBAttr = cast<IBOutletCollectionAttr>(IBInfo.A); 76 IBInfo.IBCollInfo.attrInfo = &IBInfo; 77 IBInfo.IBCollInfo.classLoc = IdxCtx.getIndexLoc(IBAttr->getInterfaceLoc()); 78 IBInfo.IBCollInfo.objcClass = 0; 79 IBInfo.IBCollInfo.classCursor = clang_getNullCursor(); 80 QualType Ty = IBAttr->getInterface(); 81 if (const ObjCInterfaceType *InterTy = Ty->getAs<ObjCInterfaceType>()) { 82 if (const ObjCInterfaceDecl *InterD = InterTy->getInterface()) { 83 IdxCtx.getEntityInfo(InterD, IBInfo.ClassInfo, SA); 84 IBInfo.IBCollInfo.objcClass = &IBInfo.ClassInfo; 85 IBInfo.IBCollInfo.classCursor = MakeCursorObjCClassRef(InterD, 86 IBAttr->getInterfaceLoc(), IdxCtx.CXTU); 87 } 88 } 89 } 90 91 for (unsigned i = 0, e = Attrs.size(); i != e; ++i) 92 CXAttrs.push_back(&Attrs[i]); 93} 94 95IndexingContext::CXXBasesListInfo::CXXBasesListInfo(const CXXRecordDecl *D, 96 IndexingContext &IdxCtx, 97 IndexingContext::StrAdapter &SA) { 98 for (CXXRecordDecl::base_class_const_iterator 99 I = D->bases_begin(), E = D->bases_end(); I != E; ++I) { 100 const CXXBaseSpecifier &Base = *I; 101 BaseEntities.push_back(EntityInfo()); 102 const CXXRecordDecl *BaseRD = 0; 103 if (const RecordType *RT = Base.getType()->getAs<RecordType>()) 104 BaseRD = dyn_cast_or_null<CXXRecordDecl>(RT->getDecl()); 105 IdxCtx.getEntityInfo(BaseRD, BaseEntities.back(), SA); 106 CXIdxBaseClassInfo BaseInfo = { 0, 107 MakeCursorCXXBaseSpecifier(&Base, IdxCtx.CXTU), 108 IdxCtx.getIndexLoc(Base.getSourceRange().getBegin()) }; 109 BaseInfos.push_back(BaseInfo); 110 } 111 112 for (unsigned i = 0, e = BaseInfos.size(); i != e; ++i) { 113 if (BaseEntities[i].USR) 114 BaseInfos[i].base = &BaseEntities[i]; 115 } 116 117 for (unsigned i = 0, e = BaseInfos.size(); i != e; ++i) 118 CXBases.push_back(&BaseInfos[i]); 119} 120 121const char *IndexingContext::StrAdapter::toCStr(StringRef Str) { 122 if (Str.empty()) 123 return ""; 124 if (Str.data()[Str.size()] == '\0') 125 return Str.data(); 126 Scratch += Str; 127 Scratch.push_back('\0'); 128 return Scratch.data() + (Scratch.size() - Str.size() - 1); 129} 130 131void IndexingContext::setASTContext(ASTContext &ctx) { 132 Ctx = &ctx; 133 static_cast<ASTUnit*>(CXTU->TUData)->setASTContext(&ctx); 134} 135 136bool IndexingContext::shouldAbort() { 137 if (!CB.abortQuery) 138 return false; 139 return CB.abortQuery(ClientData, 0); 140} 141 142void IndexingContext::enteredMainFile(const FileEntry *File) { 143 if (File && CB.enteredMainFile) { 144 CXIdxClientFile idxFile = CB.enteredMainFile(ClientData, (CXFile)File, 0); 145 FileMap[File] = idxFile; 146 } 147} 148 149void IndexingContext::ppIncludedFile(SourceLocation hashLoc, 150 StringRef filename, 151 const FileEntry *File, 152 bool isImport, bool isAngled) { 153 if (!CB.ppIncludedFile) 154 return; 155 156 StrAdapter SA(*this); 157 CXIdxIncludedFileInfo Info = { getIndexLoc(hashLoc), 158 SA.toCStr(filename), 159 (CXFile)File, 160 isImport, isAngled }; 161 CXIdxClientFile idxFile = CB.ppIncludedFile(ClientData, &Info); 162 FileMap[File] = idxFile; 163} 164 165void IndexingContext::startedTranslationUnit() { 166 CXIdxClientContainer idxCont = 0; 167 if (CB.startedTranslationUnit) 168 idxCont = CB.startedTranslationUnit(ClientData, 0); 169 addContainerInMap(Ctx->getTranslationUnitDecl(), idxCont); 170} 171 172void IndexingContext::handleDiagnosticSet(CXDiagnostic CXDiagSet) { 173 if (!CB.diagnostic) 174 return; 175 176 CB.diagnostic(ClientData, CXDiagSet, 0); 177} 178 179bool IndexingContext::handleDecl(const NamedDecl *D, 180 SourceLocation Loc, CXCursor Cursor, 181 DeclInfo &DInfo) { 182 if (!CB.indexDeclaration || !D) 183 return false; 184 if (D->isImplicit() && shouldIgnoreIfImplicit(D)) 185 return false; 186 187 StrAdapter SA(*this); 188 getEntityInfo(D, DInfo.EntInfo, SA); 189 if (!DInfo.EntInfo.USR || Loc.isInvalid()) 190 return false; 191 192 markEntityOccurrenceInFile(D, Loc); 193 194 DInfo.entityInfo = &DInfo.EntInfo; 195 DInfo.cursor = Cursor; 196 DInfo.loc = getIndexLoc(Loc); 197 DInfo.isImplicit = D->isImplicit(); 198 199 AttrListInfo AttrList(D, *this, SA); 200 DInfo.attributes = AttrList.getAttrs(); 201 DInfo.numAttributes = AttrList.getNumAttrs(); 202 203 getContainerInfo(D->getDeclContext(), DInfo.Container); 204 DInfo.container = &DInfo.Container; 205 if (DInfo.isContainer) { 206 getContainerInfo(getEntityContainer(D), DInfo.DeclAsContainer); 207 DInfo.declAsContainer = &DInfo.DeclAsContainer; 208 } 209 210 CB.indexDeclaration(ClientData, &DInfo); 211 return true; 212} 213 214bool IndexingContext::handleObjCContainer(const ObjCContainerDecl *D, 215 SourceLocation Loc, CXCursor Cursor, 216 ObjCContainerDeclInfo &ContDInfo) { 217 ContDInfo.ObjCContDeclInfo.declInfo = &ContDInfo; 218 return handleDecl(D, Loc, Cursor, ContDInfo); 219} 220 221bool IndexingContext::handleFunction(const FunctionDecl *D) { 222 DeclInfo DInfo(!D->isFirstDeclaration(), D->isThisDeclarationADefinition(), 223 D->isThisDeclarationADefinition()); 224 return handleDecl(D, D->getLocation(), getCursor(D), DInfo); 225} 226 227bool IndexingContext::handleVar(const VarDecl *D) { 228 DeclInfo DInfo(!D->isFirstDeclaration(), D->isThisDeclarationADefinition(), 229 /*isContainer=*/false); 230 return handleDecl(D, D->getLocation(), getCursor(D), DInfo); 231} 232 233bool IndexingContext::handleField(const FieldDecl *D) { 234 DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/true, 235 /*isContainer=*/false); 236 return handleDecl(D, D->getLocation(), getCursor(D), DInfo); 237} 238 239bool IndexingContext::handleEnumerator(const EnumConstantDecl *D) { 240 DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/true, 241 /*isContainer=*/false); 242 return handleDecl(D, D->getLocation(), getCursor(D), DInfo); 243} 244 245bool IndexingContext::handleTagDecl(const TagDecl *D) { 246 if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(D)) 247 return handleCXXRecordDecl(CXXRD, D); 248 249 DeclInfo DInfo(!D->isFirstDeclaration(), D->isThisDeclarationADefinition(), 250 D->isThisDeclarationADefinition()); 251 return handleDecl(D, D->getLocation(), getCursor(D), DInfo); 252} 253 254bool IndexingContext::handleTypedefName(const TypedefNameDecl *D) { 255 DeclInfo DInfo(!D->isFirstDeclaration(), /*isDefinition=*/true, 256 /*isContainer=*/false); 257 return handleDecl(D, D->getLocation(), getCursor(D), DInfo); 258} 259 260bool IndexingContext::handleObjCClass(const ObjCClassDecl *D) { 261 const ObjCClassDecl::ObjCClassRef *Ref = D->getForwardDecl(); 262 ObjCInterfaceDecl *IFaceD = Ref->getInterface(); 263 SourceLocation Loc = Ref->getLocation(); 264 bool isRedeclaration = IFaceD->getLocation() != Loc; 265 266 ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/true, isRedeclaration, 267 /*isImplementation=*/false); 268 return handleObjCContainer(IFaceD, Loc, 269 MakeCursorObjCClassRef(IFaceD, Loc, CXTU), ContDInfo); 270} 271 272bool IndexingContext::handleObjCInterface(const ObjCInterfaceDecl *D) { 273 StrAdapter SA(*this); 274 275 CXIdxBaseClassInfo BaseClass; 276 EntityInfo BaseEntity; 277 BaseClass.cursor = clang_getNullCursor(); 278 if (ObjCInterfaceDecl *SuperD = D->getSuperClass()) { 279 getEntityInfo(SuperD, BaseEntity, SA); 280 SourceLocation SuperLoc = D->getSuperClassLoc(); 281 BaseClass.base = &BaseEntity; 282 BaseClass.cursor = MakeCursorObjCSuperClassRef(SuperD, SuperLoc, CXTU); 283 BaseClass.loc = getIndexLoc(SuperLoc); 284 } 285 286 ObjCProtocolListInfo ProtInfo(D->getReferencedProtocols(), *this, SA); 287 288 ObjCInterfaceDeclInfo InterInfo(D); 289 InterInfo.ObjCProtoListInfo = ProtInfo.getListInfo(); 290 InterInfo.ObjCInterDeclInfo.containerInfo = &InterInfo.ObjCContDeclInfo; 291 InterInfo.ObjCInterDeclInfo.superInfo = D->getSuperClass() ? &BaseClass : 0; 292 InterInfo.ObjCInterDeclInfo.protocols = &InterInfo.ObjCProtoListInfo; 293 294 return handleObjCContainer(D, D->getLocation(), getCursor(D), InterInfo); 295} 296 297bool IndexingContext::handleObjCImplementation( 298 const ObjCImplementationDecl *D) { 299 ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/false, 300 /*isRedeclaration=*/true, 301 /*isImplementation=*/true); 302 return handleObjCContainer(D, D->getLocation(), getCursor(D), ContDInfo); 303} 304 305bool IndexingContext::handleObjCForwardProtocol(const ObjCProtocolDecl *D, 306 SourceLocation Loc, 307 bool isRedeclaration) { 308 ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/true, 309 isRedeclaration, 310 /*isImplementation=*/false); 311 return handleObjCContainer(D, Loc, MakeCursorObjCProtocolRef(D, Loc, CXTU), 312 ContDInfo); 313} 314 315bool IndexingContext::handleObjCProtocol(const ObjCProtocolDecl *D) { 316 StrAdapter SA(*this); 317 ObjCProtocolListInfo ProtListInfo(D->getReferencedProtocols(), *this, SA); 318 319 ObjCProtocolDeclInfo ProtInfo(D); 320 ProtInfo.ObjCProtoRefListInfo = ProtListInfo.getListInfo(); 321 322 return handleObjCContainer(D, D->getLocation(), getCursor(D), ProtInfo); 323} 324 325bool IndexingContext::handleObjCCategory(const ObjCCategoryDecl *D) { 326 ObjCCategoryDeclInfo CatDInfo(/*isImplementation=*/false); 327 EntityInfo ClassEntity; 328 StrAdapter SA(*this); 329 const ObjCInterfaceDecl *IFaceD = D->getClassInterface(); 330 SourceLocation ClassLoc = D->getLocation(); 331 SourceLocation CategoryLoc = D->IsClassExtension() ? ClassLoc 332 : D->getCategoryNameLoc(); 333 getEntityInfo(IFaceD, ClassEntity, SA); 334 335 CatDInfo.ObjCCatDeclInfo.containerInfo = &CatDInfo.ObjCContDeclInfo; 336 if (IFaceD) { 337 CatDInfo.ObjCCatDeclInfo.objcClass = &ClassEntity; 338 CatDInfo.ObjCCatDeclInfo.classCursor = 339 MakeCursorObjCClassRef(IFaceD, ClassLoc, CXTU); 340 } else { 341 CatDInfo.ObjCCatDeclInfo.objcClass = 0; 342 CatDInfo.ObjCCatDeclInfo.classCursor = clang_getNullCursor(); 343 } 344 CatDInfo.ObjCCatDeclInfo.classLoc = getIndexLoc(ClassLoc); 345 return handleObjCContainer(D, CategoryLoc, getCursor(D), CatDInfo); 346} 347 348bool IndexingContext::handleObjCCategoryImpl(const ObjCCategoryImplDecl *D) { 349 const ObjCCategoryDecl *CatD = D->getCategoryDecl(); 350 ObjCCategoryDeclInfo CatDInfo(/*isImplementation=*/true); 351 EntityInfo ClassEntity; 352 StrAdapter SA(*this); 353 const ObjCInterfaceDecl *IFaceD = CatD->getClassInterface(); 354 SourceLocation ClassLoc = D->getLocation(); 355 SourceLocation CategoryLoc = ClassLoc; //FIXME: D->getCategoryNameLoc(); 356 getEntityInfo(IFaceD, ClassEntity, SA); 357 358 CatDInfo.ObjCCatDeclInfo.containerInfo = &CatDInfo.ObjCContDeclInfo; 359 if (IFaceD) { 360 CatDInfo.ObjCCatDeclInfo.objcClass = &ClassEntity; 361 CatDInfo.ObjCCatDeclInfo.classCursor = 362 MakeCursorObjCClassRef(IFaceD, ClassLoc, CXTU); 363 } else { 364 CatDInfo.ObjCCatDeclInfo.objcClass = 0; 365 CatDInfo.ObjCCatDeclInfo.classCursor = clang_getNullCursor(); 366 } 367 CatDInfo.ObjCCatDeclInfo.classLoc = getIndexLoc(ClassLoc); 368 return handleObjCContainer(D, CategoryLoc, getCursor(D), CatDInfo); 369} 370 371bool IndexingContext::handleObjCMethod(const ObjCMethodDecl *D) { 372 DeclInfo DInfo(!D->isCanonicalDecl(), D->isThisDeclarationADefinition(), 373 D->isThisDeclarationADefinition()); 374 return handleDecl(D, D->getLocation(), getCursor(D), DInfo); 375} 376 377bool IndexingContext::handleSynthesizedObjCProperty( 378 const ObjCPropertyImplDecl *D) { 379 ObjCPropertyDecl *PD = D->getPropertyDecl(); 380 return handleReference(PD, D->getLocation(), getCursor(D), 0, D->getDeclContext()); 381} 382 383bool IndexingContext::handleSynthesizedObjCMethod(const ObjCMethodDecl *D, 384 SourceLocation Loc) { 385 DeclInfo DInfo(/*isRedeclaration=*/true, /*isDefinition=*/true, 386 /*isContainer=*/false); 387 return handleDecl(D, Loc, getCursor(D), DInfo); 388} 389 390bool IndexingContext::handleObjCProperty(const ObjCPropertyDecl *D) { 391 DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/false, 392 /*isContainer=*/false); 393 return handleDecl(D, D->getLocation(), getCursor(D), DInfo); 394} 395 396bool IndexingContext::handleClassTemplate(const ClassTemplateDecl *D) { 397 return handleCXXRecordDecl(D->getTemplatedDecl(), D); 398} 399 400bool IndexingContext::handleFunctionTemplate(const FunctionTemplateDecl *D) { 401 DeclInfo DInfo(/*isRedeclaration=*/!D->isCanonicalDecl(), 402 /*isDefinition=*/D->isThisDeclarationADefinition(), 403 /*isContainer=*/D->isThisDeclarationADefinition()); 404 return handleDecl(D, D->getLocation(), getCursor(D), DInfo); 405} 406 407bool IndexingContext::handleTypeAliasTemplate(const TypeAliasTemplateDecl *D) { 408 DeclInfo DInfo(/*isRedeclaration=*/!D->isCanonicalDecl(), 409 /*isDefinition=*/true, /*isContainer=*/false); 410 return handleDecl(D, D->getLocation(), getCursor(D), DInfo); 411} 412 413bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc, 414 const NamedDecl *Parent, 415 const DeclContext *DC, 416 const Expr *E, 417 CXIdxEntityRefKind Kind) { 418 if (!D) 419 return false; 420 421 CXCursor Cursor = E ? MakeCXCursor(const_cast<Expr*>(E), 422 const_cast<Decl*>(cast<Decl>(DC)), CXTU) 423 : getRefCursor(D, Loc); 424 return handleReference(D, Loc, Cursor, Parent, DC, E, Kind); 425} 426 427bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc, 428 CXCursor Cursor, 429 const NamedDecl *Parent, 430 const DeclContext *DC, 431 const Expr *E, 432 CXIdxEntityRefKind Kind) { 433 if (!CB.indexEntityReference) 434 return false; 435 436 if (!D) 437 return false; 438 if (Loc.isInvalid()) 439 return false; 440 if (D->getParentFunctionOrMethod()) 441 return false; 442 if (isNotFromSourceFile(D->getLocation())) 443 return false; 444 if (D->isImplicit() && shouldIgnoreIfImplicit(D)) 445 return false; 446 447 if (suppressRefs()) { 448 if (markEntityOccurrenceInFile(D, Loc)) 449 return false; // already occurred. 450 } 451 452 StrAdapter SA(*this); 453 EntityInfo RefEntity, ParentEntity; 454 getEntityInfo(D, RefEntity, SA); 455 if (!RefEntity.USR) 456 return false; 457 458 getEntityInfo(Parent, ParentEntity, SA); 459 460 ContainerInfo Container; 461 getContainerInfo(DC, Container); 462 463 CXIdxEntityRefInfo Info = { Cursor, 464 getIndexLoc(Loc), 465 &RefEntity, 466 Parent ? &ParentEntity : 0, 467 &Container, 468 Kind }; 469 CB.indexEntityReference(ClientData, &Info); 470 return true; 471} 472 473bool IndexingContext::isNotFromSourceFile(SourceLocation Loc) const { 474 if (Loc.isInvalid()) 475 return true; 476 SourceManager &SM = Ctx->getSourceManager(); 477 SourceLocation FileLoc = SM.getFileLoc(Loc); 478 FileID FID = SM.getFileID(FileLoc); 479 return SM.getFileEntryForID(FID) == 0; 480} 481 482void IndexingContext::addContainerInMap(const DeclContext *DC, 483 CXIdxClientContainer container) { 484 if (!DC) 485 return; 486 487 assert(getScopedContext(DC) == DC); 488 ContainerMapTy::iterator I = ContainerMap.find(DC); 489 if (I == ContainerMap.end()) { 490 if (container) 491 ContainerMap[DC] = container; 492 return; 493 } 494 // Allow changing the container of a previously seen DeclContext so we 495 // can handle invalid user code, like a function re-definition. 496 if (container) 497 I->second = container; 498 else 499 ContainerMap.erase(I); 500} 501 502CXIdxClientEntity IndexingContext::getClientEntity(const Decl *D) const { 503 if (!D) 504 return 0; 505 EntityMapTy::const_iterator I = EntityMap.find(D); 506 if (I == EntityMap.end()) 507 return 0; 508 return I->second; 509} 510 511void IndexingContext::setClientEntity(const Decl *D, CXIdxClientEntity client) { 512 if (!D) 513 return; 514 EntityMap[D] = client; 515} 516 517bool IndexingContext::handleCXXRecordDecl(const CXXRecordDecl *RD, 518 const NamedDecl *OrigD) { 519 StrAdapter SA(*this); 520 CXXClassDeclInfo DInfo(/*isRedeclaration=*/!OrigD->isCanonicalDecl(), 521 /*isDefinition=*/RD->isThisDeclarationADefinition()); 522 CXXBasesListInfo BaseList(RD, *this, SA); 523 DInfo.CXXClassInfo.declInfo = &DInfo; 524 DInfo.CXXClassInfo.bases = BaseList.getBases(); 525 DInfo.CXXClassInfo.numBases = BaseList.getNumBases(); 526 527 return handleDecl(OrigD, OrigD->getLocation(), getCursor(OrigD), DInfo); 528} 529 530bool IndexingContext::markEntityOccurrenceInFile(const NamedDecl *D, 531 SourceLocation Loc) { 532 SourceManager &SM = Ctx->getSourceManager(); 533 SourceLocation FileLoc = SM.getFileLoc(Loc); 534 D = getEntityDecl(D); 535 536 std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc); 537 FileID FID = LocInfo.first; 538 if (FID.isInvalid()) 539 return true; 540 541 const FileEntry *FE = SM.getFileEntryForID(FID); 542 if (!FE) 543 return true; 544 RefFileOccurence RefOccur(FE, D); 545 std::pair<llvm::DenseSet<RefFileOccurence>::iterator, bool> 546 res = RefFileOccurences.insert(RefOccur); 547 if (!res.second) 548 return true; // already in map. 549 550 return false; 551} 552 553const NamedDecl *IndexingContext::getEntityDecl(const NamedDecl *D) const { 554 assert(D); 555 D = cast<NamedDecl>(D->getCanonicalDecl()); 556 557 if (const ObjCImplementationDecl * 558 ImplD = dyn_cast<ObjCImplementationDecl>(D)) { 559 return getEntityDecl(ImplD->getClassInterface()); 560 561 } else if (const ObjCCategoryImplDecl * 562 CatImplD = dyn_cast<ObjCCategoryImplDecl>(D)) { 563 return getEntityDecl(CatImplD->getCategoryDecl()); 564 } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 565 if (FunctionTemplateDecl *TemplD = FD->getDescribedFunctionTemplate()) 566 return getEntityDecl(TemplD); 567 } else if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { 568 if (ClassTemplateDecl *TemplD = RD->getDescribedClassTemplate()) 569 return getEntityDecl(TemplD); 570 } 571 572 return D; 573} 574 575const DeclContext * 576IndexingContext::getEntityContainer(const Decl *D) const { 577 const DeclContext *DC = dyn_cast<DeclContext>(D); 578 if (DC) 579 return DC; 580 581 if (const ClassTemplateDecl *ClassTempl = dyn_cast<ClassTemplateDecl>(D)) { 582 DC = ClassTempl->getTemplatedDecl(); 583 } if (const FunctionTemplateDecl * 584 FuncTempl = dyn_cast<FunctionTemplateDecl>(D)) { 585 DC = FuncTempl->getTemplatedDecl(); 586 } 587 588 return DC; 589} 590 591const DeclContext * 592IndexingContext::getScopedContext(const DeclContext *DC) const { 593 // Local contexts are ignored for indexing. 594 const DeclContext *FuncCtx = cast<Decl>(DC)->getParentFunctionOrMethod(); 595 if (FuncCtx) 596 return FuncCtx; 597 598 // We consider enums always scoped for indexing. 599 if (isa<TagDecl>(DC)) 600 return DC; 601 602 if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) { 603 if (NS->isAnonymousNamespace()) 604 return getScopedContext(NS->getParent()); 605 return NS; 606 } 607 608 return DC->getRedeclContext(); 609} 610 611CXIdxClientContainer 612IndexingContext::getClientContainerForDC(const DeclContext *DC) const { 613 if (!DC) 614 return 0; 615 616 DC = getScopedContext(DC); 617 ContainerMapTy::const_iterator I = ContainerMap.find(DC); 618 if (I == ContainerMap.end()) 619 return 0; 620 621 return I->second; 622} 623 624CXIdxClientFile IndexingContext::getIndexFile(const FileEntry *File) { 625 if (!File) 626 return 0; 627 628 FileMapTy::iterator FI = FileMap.find(File); 629 if (FI != FileMap.end()) 630 return FI->second; 631 632 return 0; 633} 634 635CXIdxLoc IndexingContext::getIndexLoc(SourceLocation Loc) const { 636 CXIdxLoc idxLoc = { {0, 0}, 0 }; 637 if (Loc.isInvalid()) 638 return idxLoc; 639 640 idxLoc.ptr_data[0] = (void*)this; 641 idxLoc.int_data = Loc.getRawEncoding(); 642 return idxLoc; 643} 644 645void IndexingContext::translateLoc(SourceLocation Loc, 646 CXIdxClientFile *indexFile, CXFile *file, 647 unsigned *line, unsigned *column, 648 unsigned *offset) { 649 if (Loc.isInvalid()) 650 return; 651 652 SourceManager &SM = Ctx->getSourceManager(); 653 Loc = SM.getFileLoc(Loc); 654 655 std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc); 656 FileID FID = LocInfo.first; 657 unsigned FileOffset = LocInfo.second; 658 659 if (FID.isInvalid()) 660 return; 661 662 const FileEntry *FE = SM.getFileEntryForID(FID); 663 if (indexFile) 664 *indexFile = getIndexFile(FE); 665 if (file) 666 *file = (void *)FE; 667 if (line) 668 *line = SM.getLineNumber(FID, FileOffset); 669 if (column) 670 *column = SM.getColumnNumber(FID, FileOffset); 671 if (offset) 672 *offset = FileOffset; 673} 674 675void IndexingContext::getEntityInfo(const NamedDecl *D, 676 EntityInfo &EntityInfo, 677 StrAdapter &SA) { 678 EntityInfo.name = EntityInfo.USR = 0; 679 if (!D) 680 return; 681 682 D = getEntityDecl(D); 683 EntityInfo.cursor = getCursor(D); 684 EntityInfo.Dcl = D; 685 EntityInfo.IndexCtx = this; 686 EntityInfo.kind = CXIdxEntity_Unexposed; 687 EntityInfo.templateKind = CXIdxEntity_NonTemplate; 688 689 if (const TagDecl *TD = dyn_cast<TagDecl>(D)) { 690 switch (TD->getTagKind()) { 691 case TTK_Struct: 692 EntityInfo.kind = CXIdxEntity_Struct; break; 693 case TTK_Union: 694 EntityInfo.kind = CXIdxEntity_Union; break; 695 case TTK_Class: 696 EntityInfo.kind = CXIdxEntity_CXXClass; break; 697 case TTK_Enum: 698 EntityInfo.kind = CXIdxEntity_Enum; break; 699 } 700 701 if (const CXXRecordDecl *CXXRec = dyn_cast<CXXRecordDecl>(D)) { 702 if (TD->getTagKind() == TTK_Struct && !CXXRec->isPOD()) 703 EntityInfo.kind = CXIdxEntity_CXXClass; 704 } 705 706 if (isa<ClassTemplatePartialSpecializationDecl>(D)) { 707 EntityInfo.templateKind = CXIdxEntity_TemplatePartialSpecialization; 708 } else if (isa<ClassTemplateSpecializationDecl>(D)) { 709 EntityInfo.templateKind = CXIdxEntity_TemplateSpecialization; 710 } 711 712 } else { 713 switch (D->getKind()) { 714 case Decl::Typedef: 715 EntityInfo.kind = CXIdxEntity_Typedef; break; 716 case Decl::Function: 717 EntityInfo.kind = CXIdxEntity_Function; 718 break; 719 case Decl::Var: 720 EntityInfo.kind = CXIdxEntity_Variable; 721 if (isa<CXXRecordDecl>(D->getDeclContext())) 722 EntityInfo.kind = CXIdxEntity_CXXStaticVariable; 723 break; 724 case Decl::Field: 725 EntityInfo.kind = CXIdxEntity_Field; break; 726 case Decl::EnumConstant: 727 EntityInfo.kind = CXIdxEntity_EnumConstant; break; 728 case Decl::ObjCInterface: 729 EntityInfo.kind = CXIdxEntity_ObjCClass; break; 730 case Decl::ObjCProtocol: 731 EntityInfo.kind = CXIdxEntity_ObjCProtocol; break; 732 case Decl::ObjCCategory: 733 EntityInfo.kind = CXIdxEntity_ObjCCategory; break; 734 case Decl::ObjCMethod: 735 if (cast<ObjCMethodDecl>(D)->isInstanceMethod()) 736 EntityInfo.kind = CXIdxEntity_ObjCInstanceMethod; 737 else 738 EntityInfo.kind = CXIdxEntity_ObjCClassMethod; 739 break; 740 case Decl::ObjCProperty: 741 EntityInfo.kind = CXIdxEntity_ObjCProperty; break; 742 case Decl::ObjCIvar: 743 EntityInfo.kind = CXIdxEntity_ObjCIvar; break; 744 case Decl::Namespace: 745 EntityInfo.kind = CXIdxEntity_CXXNamespace; break; 746 case Decl::NamespaceAlias: 747 EntityInfo.kind = CXIdxEntity_CXXNamespaceAlias; break; 748 case Decl::CXXConstructor: 749 EntityInfo.kind = CXIdxEntity_CXXConstructor; break; 750 case Decl::CXXDestructor: 751 EntityInfo.kind = CXIdxEntity_CXXDestructor; break; 752 case Decl::CXXConversion: 753 EntityInfo.kind = CXIdxEntity_CXXConversionFunction; break; 754 case Decl::CXXMethod: { 755 const CXXMethodDecl *MD = cast<CXXMethodDecl>(D); 756 if (MD->isStatic()) 757 EntityInfo.kind = CXIdxEntity_CXXStaticMethod; 758 else 759 EntityInfo.kind = CXIdxEntity_CXXInstanceMethod; 760 break; 761 } 762 case Decl::ClassTemplate: 763 EntityInfo.kind = CXIdxEntity_CXXClass; 764 EntityInfo.templateKind = CXIdxEntity_Template; 765 break; 766 case Decl::FunctionTemplate: 767 EntityInfo.kind = CXIdxEntity_Function; 768 EntityInfo.templateKind = CXIdxEntity_Template; 769 if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>( 770 cast<FunctionTemplateDecl>(D)->getTemplatedDecl())) { 771 if (isa<CXXConstructorDecl>(MD)) 772 EntityInfo.kind = CXIdxEntity_CXXConstructor; 773 else if (isa<CXXDestructorDecl>(MD)) 774 EntityInfo.kind = CXIdxEntity_CXXDestructor; 775 else if (isa<CXXConversionDecl>(MD)) 776 EntityInfo.kind = CXIdxEntity_CXXConversionFunction; 777 else { 778 if (MD->isStatic()) 779 EntityInfo.kind = CXIdxEntity_CXXStaticMethod; 780 else 781 EntityInfo.kind = CXIdxEntity_CXXInstanceMethod; 782 } 783 } 784 break; 785 case Decl::TypeAliasTemplate: 786 EntityInfo.kind = CXIdxEntity_CXXTypeAlias; 787 EntityInfo.templateKind = CXIdxEntity_Template; 788 break; 789 case Decl::TypeAlias: 790 EntityInfo.kind = CXIdxEntity_CXXTypeAlias; break; 791 default: 792 break; 793 } 794 } 795 796 if (EntityInfo.kind == CXIdxEntity_Unexposed) 797 return; 798 799 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 800 if (FD->getTemplatedKind() == 801 FunctionDecl::TK_FunctionTemplateSpecialization) 802 EntityInfo.templateKind = CXIdxEntity_TemplateSpecialization; 803 } 804 805 if (IdentifierInfo *II = D->getIdentifier()) { 806 EntityInfo.name = SA.toCStr(II->getName()); 807 808 } else if (isa<RecordDecl>(D) || isa<NamespaceDecl>(D)) { 809 EntityInfo.name = 0; // anonymous record/namespace. 810 811 } else { 812 unsigned Begin = SA.getCurSize(); 813 { 814 llvm::raw_svector_ostream OS(SA.getBuffer()); 815 D->printName(OS); 816 } 817 EntityInfo.name = SA.getCStr(Begin); 818 } 819 820 { 821 unsigned Begin = SA.getCurSize(); 822 bool Ignore = getDeclCursorUSR(D, SA.getBuffer()); 823 if (Ignore) { 824 EntityInfo.USR = 0; 825 } else { 826 EntityInfo.USR = SA.getCStr(Begin); 827 } 828 } 829} 830 831void IndexingContext::getContainerInfo(const DeclContext *DC, 832 ContainerInfo &ContInfo) { 833 ContInfo.cursor = getCursor(cast<Decl>(DC)); 834 ContInfo.DC = DC; 835 ContInfo.IndexCtx = this; 836} 837 838CXCursor IndexingContext::getRefCursor(const NamedDecl *D, SourceLocation Loc) { 839 if (const TypeDecl *TD = dyn_cast<TypeDecl>(D)) 840 return MakeCursorTypeRef(TD, Loc, CXTU); 841 if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) 842 return MakeCursorObjCClassRef(ID, Loc, CXTU); 843 if (const ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) 844 return MakeCursorObjCProtocolRef(PD, Loc, CXTU); 845 if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(D)) 846 return MakeCursorTemplateRef(Template, Loc, CXTU); 847 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(D)) 848 return MakeCursorNamespaceRef(Namespace, Loc, CXTU); 849 if (const NamespaceAliasDecl *Namespace = dyn_cast<NamespaceAliasDecl>(D)) 850 return MakeCursorNamespaceRef(Namespace, Loc, CXTU); 851 if (const FieldDecl *Field = dyn_cast<FieldDecl>(D)) 852 return MakeCursorMemberRef(Field, Loc, CXTU); 853 854 return clang_getNullCursor(); 855} 856 857bool IndexingContext::shouldIgnoreIfImplicit(const NamedDecl *D) { 858 if (isa<ObjCIvarDecl>(D)) 859 return false; 860 if (isa<ObjCMethodDecl>(D)) 861 return false; 862 return true; 863} 864