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 "RecursiveASTVisitor.h" 12 13 using namespace clang; 14 using namespace cxindex; 15 16 namespace { 17 18 class BodyIndexer : public cxindex::RecursiveASTVisitor<BodyIndexer> { 19 IndexingContext &IndexCtx; 20 const NamedDecl *Parent; 21 const DeclContext *ParentDC; 22 23 typedef RecursiveASTVisitor<BodyIndexer> base; 24 public: 25 BodyIndexer(IndexingContext &indexCtx, 26 const NamedDecl *Parent, const DeclContext *DC) 27 : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { } 28 29 bool shouldWalkTypesOfTypeLocs() const { return false; } 30 31 bool TraverseTypeLoc(TypeLoc TL) { 32 IndexCtx.indexTypeLoc(TL, 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 VisitDeclRefExpr(DeclRefExpr *E) { 42 IndexCtx.handleReference(E->getDecl(), E->getLocation(), 43 Parent, ParentDC, E); 44 return true; 45 } 46 47 bool VisitMemberExpr(MemberExpr *E) { 48 IndexCtx.handleReference(E->getMemberDecl(), E->getMemberLoc(), 49 Parent, ParentDC, E); 50 return true; 51 } 52 53 bool VisitDesignatedInitExpr(DesignatedInitExpr *E) { 54 for (DesignatedInitExpr::reverse_designators_iterator 55 D = E->designators_rbegin(), DEnd = E->designators_rend(); 56 D != DEnd; ++D) { 57 if (D->isFieldDesignator()) 58 IndexCtx.handleReference(D->getField(), D->getFieldLoc(), 59 Parent, ParentDC, E); 60 } 61 return true; 62 } 63 64 bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { 65 IndexCtx.handleReference(E->getDecl(), E->getLocation(), 66 Parent, ParentDC, E); 67 return true; 68 } 69 70 bool VisitObjCMessageExpr(ObjCMessageExpr *E) { 71 if (TypeSourceInfo *Cls = E->getClassReceiverTypeInfo()) 72 IndexCtx.indexTypeSourceInfo(Cls, Parent, ParentDC); 73 74 if (ObjCMethodDecl *MD = E->getMethodDecl()) 75 IndexCtx.handleReference(MD, E->getSelectorStartLoc(), 76 Parent, ParentDC, E, 77 E->isImplicit() ? CXIdxEntityRef_Implicit 78 : CXIdxEntityRef_Direct); 79 return true; 80 } 81 82 bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { 83 if (E->isExplicitProperty()) 84 IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(), 85 Parent, ParentDC, E); 86 87 // No need to do a handleReference for the objc method, because there will 88 // be a message expr as part of PseudoObjectExpr. 89 return true; 90 } 91 92 bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) { 93 IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(), 94 Parent, ParentDC, E, CXIdxEntityRef_Direct); 95 return true; 96 } 97 98 bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) { 99 if (ObjCMethodDecl *MD = E->getBoxingMethod()) 100 IndexCtx.handleReference(MD, E->getLocStart(), 101 Parent, ParentDC, E, CXIdxEntityRef_Implicit); 102 return true; 103 } 104 105 bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) { 106 if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod()) 107 IndexCtx.handleReference(MD, E->getLocStart(), 108 Parent, ParentDC, E, CXIdxEntityRef_Implicit); 109 return true; 110 } 111 112 bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) { 113 if (ObjCMethodDecl *MD = E->getArrayWithObjectsMethod()) 114 IndexCtx.handleReference(MD, E->getLocStart(), 115 Parent, ParentDC, E, CXIdxEntityRef_Implicit); 116 return true; 117 } 118 119 bool VisitCXXConstructExpr(CXXConstructExpr *E) { 120 IndexCtx.handleReference(E->getConstructor(), E->getLocation(), 121 Parent, ParentDC, E); 122 return true; 123 } 124 125 bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E) { 126 if (E->getOperatorLoc().isInvalid()) 127 return true; // implicit. 128 return base::TraverseCXXOperatorCallExpr(E); 129 } 130 131 bool VisitDeclStmt(DeclStmt *S) { 132 if (IndexCtx.shouldIndexFunctionLocalSymbols()) { 133 IndexCtx.indexDeclGroupRef(S->getDeclGroup()); 134 return true; 135 } 136 137 DeclGroupRef DG = S->getDeclGroup(); 138 for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) { 139 const Decl *D = *I; 140 if (!D) 141 continue; 142 if (!IndexCtx.isFunctionLocalDecl(D)) 143 IndexCtx.indexTopLevelDecl(D); 144 } 145 146 return true; 147 } 148 149 bool TraverseLambdaCapture(LambdaExpr::Capture C) { 150 if (C.capturesThis()) 151 return true; 152 153 if (IndexCtx.shouldIndexFunctionLocalSymbols()) 154 IndexCtx.handleReference(C.getCapturedVar(), C.getLocation(), 155 Parent, ParentDC); 156 return true; 157 } 158 159 }; 160 161 } // anonymous namespace 162 163 void IndexingContext::indexBody(const Stmt *S, const NamedDecl *Parent, 164 const DeclContext *DC) { 165 if (!S) 166 return; 167 168 if (DC == 0) 169 DC = Parent->getLexicalDeclContext(); 170 BodyIndexer(*this, Parent, DC).TraverseStmt(const_cast<Stmt*>(S)); 171 } 172