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 12#include "clang/AST/RecursiveASTVisitor.h" 13 14using namespace clang; 15using namespace cxindex; 16 17namespace { 18 19class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> { 20 IndexingContext &IndexCtx; 21 const NamedDecl *Parent; 22 const DeclContext *ParentDC; 23 24public: 25 TypeIndexer(IndexingContext &indexCtx, const NamedDecl *parent, 26 const DeclContext *DC) 27 : IndexCtx(indexCtx), Parent(parent), ParentDC(DC) { } 28 29 bool shouldWalkTypesOfTypeLocs() const { return false; } 30 31 bool VisitTypedefTypeLoc(TypedefTypeLoc TL) { 32 IndexCtx.handleReference(TL.getTypedefNameDecl(), TL.getNameLoc(), 33 Parent, ParentDC); 34 return true; 35 } 36 37 bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { 38 IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC); 39 return true; 40 } 41 42 bool VisitTagTypeLoc(TagTypeLoc TL) { 43 TagDecl *D = TL.getDecl(); 44 if (D->getParentFunctionOrMethod()) 45 return true; 46 47 if (TL.isDefinition()) { 48 IndexCtx.indexTagDecl(D); 49 return true; 50 } 51 52 if (D->getLocation() == TL.getNameLoc()) 53 IndexCtx.handleTagDecl(D); 54 else 55 IndexCtx.handleReference(D, TL.getNameLoc(), 56 Parent, ParentDC); 57 return true; 58 } 59 60 bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { 61 IndexCtx.handleReference(TL.getIFaceDecl(), TL.getNameLoc(), 62 Parent, ParentDC); 63 return true; 64 } 65 66 bool VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) { 67 for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) { 68 IndexCtx.handleReference(TL.getProtocol(i), TL.getProtocolLoc(i), 69 Parent, ParentDC); 70 } 71 return true; 72 } 73 74 bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) { 75 if (const TemplateSpecializationType *T = TL.getTypePtr()) { 76 if (IndexCtx.shouldIndexImplicitTemplateInsts()) { 77 if (CXXRecordDecl *RD = T->getAsCXXRecordDecl()) 78 IndexCtx.handleReference(RD, TL.getTemplateNameLoc(), 79 Parent, ParentDC); 80 } else { 81 if (const TemplateDecl *D = T->getTemplateName().getAsTemplateDecl()) 82 IndexCtx.handleReference(D, TL.getTemplateNameLoc(), 83 Parent, ParentDC); 84 } 85 } 86 return true; 87 } 88 89 bool TraverseStmt(Stmt *S) { 90 IndexCtx.indexBody(S, Parent, ParentDC); 91 return true; 92 } 93}; 94 95} // anonymous namespace 96 97void IndexingContext::indexTypeSourceInfo(TypeSourceInfo *TInfo, 98 const NamedDecl *Parent, 99 const DeclContext *DC) { 100 if (!TInfo || TInfo->getTypeLoc().isNull()) 101 return; 102 103 indexTypeLoc(TInfo->getTypeLoc(), Parent, DC); 104} 105 106void IndexingContext::indexTypeLoc(TypeLoc TL, 107 const NamedDecl *Parent, 108 const DeclContext *DC) { 109 if (TL.isNull()) 110 return; 111 112 if (DC == 0) 113 DC = Parent->getLexicalDeclContext(); 114 TypeIndexer(*this, Parent, DC).TraverseTypeLoc(TL); 115} 116 117void IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, 118 const NamedDecl *Parent, 119 const DeclContext *DC) { 120 if (!NNS) 121 return; 122 123 if (NestedNameSpecifierLoc Prefix = NNS.getPrefix()) 124 indexNestedNameSpecifierLoc(Prefix, Parent, DC); 125 126 if (DC == 0) 127 DC = Parent->getLexicalDeclContext(); 128 SourceLocation Loc = NNS.getSourceRange().getBegin(); 129 130 switch (NNS.getNestedNameSpecifier()->getKind()) { 131 case NestedNameSpecifier::Identifier: 132 case NestedNameSpecifier::Global: 133 break; 134 135 case NestedNameSpecifier::Namespace: 136 handleReference(NNS.getNestedNameSpecifier()->getAsNamespace(), 137 Loc, Parent, DC); 138 break; 139 case NestedNameSpecifier::NamespaceAlias: 140 handleReference(NNS.getNestedNameSpecifier()->getAsNamespaceAlias(), 141 Loc, Parent, DC); 142 break; 143 144 case NestedNameSpecifier::TypeSpec: 145 case NestedNameSpecifier::TypeSpecWithTemplate: 146 indexTypeLoc(NNS.getTypeLoc(), Parent, DC); 147 break; 148 } 149} 150 151void IndexingContext::indexTagDecl(const TagDecl *D) { 152 if (handleTagDecl(D)) { 153 if (D->isThisDeclarationADefinition()) 154 indexDeclContext(D); 155 } 156} 157