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 13using namespace clang; 14using namespace cxindex; 15 16namespace { 17 18class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> { 19 IndexingContext &IndexCtx; 20 const NamedDecl *Parent; 21 const DeclContext *ParentDC; 22 23 typedef RecursiveASTVisitor<BodyIndexer> base; 24public: 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 DataRecursionQueue *Q = nullptr) { 130 if (E->getOperatorLoc().isInvalid()) 131 return true; // implicit. 132 return base::TraverseCXXOperatorCallExpr(E, Q); 133 } 134 135 bool VisitDeclStmt(DeclStmt *S) { 136 if (IndexCtx.shouldIndexFunctionLocalSymbols()) { 137 IndexCtx.indexDeclGroupRef(S->getDeclGroup()); 138 return true; 139 } 140 141 DeclGroupRef DG = S->getDeclGroup(); 142 for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) { 143 const Decl *D = *I; 144 if (!D) 145 continue; 146 if (!IndexCtx.isFunctionLocalDecl(D)) 147 IndexCtx.indexTopLevelDecl(D); 148 } 149 150 return true; 151 } 152 153 bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C) { 154 if (C->capturesThis() || C->capturesVLAType()) 155 return true; 156 157 if (C->capturesVariable() && IndexCtx.shouldIndexFunctionLocalSymbols()) 158 IndexCtx.handleReference(C->getCapturedVar(), C->getLocation(), Parent, 159 ParentDC); 160 161 // FIXME: Lambda init-captures. 162 return true; 163 } 164 165}; 166 167} // anonymous namespace 168 169void IndexingContext::indexBody(const Stmt *S, const NamedDecl *Parent, 170 const DeclContext *DC) { 171 if (!S) 172 return; 173 174 if (!DC) 175 DC = Parent->getLexicalDeclContext(); 176 BodyIndexer(*this, Parent, DC).TraverseStmt(const_cast<Stmt*>(S)); 177} 178