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