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/DataRecursiveASTVisitor.h" 12 13 using namespace clang; 14 using namespace cxindex; 15 16 namespace { 17 18 class BodyIndexer : public DataRecursiveASTVisitor<BodyIndexer> { 19 IndexingContext &IndexCtx; 20 const NamedDecl *Parent; 21 const DeclContext *ParentDC; 22 23 typedef DataRecursiveASTVisitor<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 (ObjCMethodDecl *MD = E->getMethodDecl()) 72 IndexCtx.handleReference(MD, E->getSelectorStartLoc(), 73 Parent, ParentDC, E, 74 E->isImplicit() ? CXIdxEntityRef_Implicit 75 : CXIdxEntityRef_Direct); 76 return true; 77 } 78 79 bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { 80 if (E->isExplicitProperty()) 81 IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(), 82 Parent, ParentDC, E); 83 84 // No need to do a handleReference for the objc method, because there will 85 // be a message expr as part of PseudoObjectExpr. 86 return true; 87 } 88 89 bool VisitMSPropertyRefExpr(MSPropertyRefExpr *E) { 90 IndexCtx.handleReference(E->getPropertyDecl(), E->getMemberLoc(), Parent, 91 ParentDC, E, CXIdxEntityRef_Direct); 92 return true; 93 } 94 95 bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) { 96 IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(), 97 Parent, ParentDC, E, CXIdxEntityRef_Direct); 98 return true; 99 } 100 101 bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) { 102 if (ObjCMethodDecl *MD = E->getBoxingMethod()) 103 IndexCtx.handleReference(MD, E->getLocStart(), 104 Parent, ParentDC, E, CXIdxEntityRef_Implicit); 105 return true; 106 } 107 108 bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) { 109 if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod()) 110 IndexCtx.handleReference(MD, E->getLocStart(), 111 Parent, ParentDC, E, CXIdxEntityRef_Implicit); 112 return true; 113 } 114 115 bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) { 116 if (ObjCMethodDecl *MD = E->getArrayWithObjectsMethod()) 117 IndexCtx.handleReference(MD, E->getLocStart(), 118 Parent, ParentDC, E, CXIdxEntityRef_Implicit); 119 return true; 120 } 121 122 bool VisitCXXConstructExpr(CXXConstructExpr *E) { 123 IndexCtx.handleReference(E->getConstructor(), E->getLocation(), 124 Parent, ParentDC, E); 125 return true; 126 } 127 128 bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E) { 129 if (E->getOperatorLoc().isInvalid()) 130 return true; // implicit. 131 return base::TraverseCXXOperatorCallExpr(E); 132 } 133 134 bool VisitDeclStmt(DeclStmt *S) { 135 if (IndexCtx.shouldIndexFunctionLocalSymbols()) { 136 IndexCtx.indexDeclGroupRef(S->getDeclGroup()); 137 return true; 138 } 139 140 DeclGroupRef DG = S->getDeclGroup(); 141 for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) { 142 const Decl *D = *I; 143 if (!D) 144 continue; 145 if (!IndexCtx.isFunctionLocalDecl(D)) 146 IndexCtx.indexTopLevelDecl(D); 147 } 148 149 return true; 150 } 151 152 bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C) { 153 if (C->capturesThis()) 154 return true; 155 156 if (C->capturesVariable() && IndexCtx.shouldIndexFunctionLocalSymbols()) 157 IndexCtx.handleReference(C->getCapturedVar(), C->getLocation(), Parent, 158 ParentDC); 159 160 // FIXME: Lambda init-captures. 161 return true; 162 } 163 164 }; 165 166 } // anonymous namespace 167 168 void IndexingContext::indexBody(const Stmt *S, const NamedDecl *Parent, 169 const DeclContext *DC) { 170 if (!S) 171 return; 172 173 if (!DC) 174 DC = Parent->getLexicalDeclContext(); 175 BodyIndexer(*this, Parent, DC).TraverseStmt(const_cast<Stmt*>(S)); 176 } 177