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 BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
19   IndexingContext &IndexCtx;
20   const NamedDecl *Parent;
21   const DeclContext *ParentDC;
22 
23   typedef RecursiveASTVisitor<BodyIndexer> base;
24 public:
BodyIndexer(IndexingContext & indexCtx,const NamedDecl * Parent,const DeclContext * DC)25   BodyIndexer(IndexingContext &indexCtx,
26               const NamedDecl *Parent, const DeclContext *DC)
27     : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { }
28 
shouldWalkTypesOfTypeLocs() const29   bool shouldWalkTypesOfTypeLocs() const { return false; }
30 
TraverseTypeLoc(TypeLoc TL)31   bool TraverseTypeLoc(TypeLoc TL) {
32     IndexCtx.indexTypeLoc(TL, Parent, ParentDC);
33     return true;
34   }
35 
TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS)36   bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
37     IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
38     return true;
39   }
40 
VisitDeclRefExpr(DeclRefExpr * E)41   bool VisitDeclRefExpr(DeclRefExpr *E) {
42     IndexCtx.handleReference(E->getDecl(), E->getLocation(),
43                              Parent, ParentDC, E);
44     return true;
45   }
46 
VisitMemberExpr(MemberExpr * E)47   bool VisitMemberExpr(MemberExpr *E) {
48     IndexCtx.handleReference(E->getMemberDecl(), E->getMemberLoc(),
49                              Parent, ParentDC, E);
50     return true;
51   }
52 
VisitDesignatedInitExpr(DesignatedInitExpr * E)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 
VisitObjCIvarRefExpr(ObjCIvarRefExpr * E)64   bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
65     IndexCtx.handleReference(E->getDecl(), E->getLocation(),
66                              Parent, ParentDC, E);
67     return true;
68   }
69 
VisitObjCMessageExpr(ObjCMessageExpr * E)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 
VisitObjCPropertyRefExpr(ObjCPropertyRefExpr * E)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 
VisitMSPropertyRefExpr(MSPropertyRefExpr * E)89   bool VisitMSPropertyRefExpr(MSPropertyRefExpr *E) {
90     IndexCtx.handleReference(E->getPropertyDecl(), E->getMemberLoc(), Parent,
91                              ParentDC, E, CXIdxEntityRef_Direct);
92     return true;
93   }
94 
VisitObjCProtocolExpr(ObjCProtocolExpr * E)95   bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
96     IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(),
97                              Parent, ParentDC, E, CXIdxEntityRef_Direct);
98     return true;
99   }
100 
VisitObjCBoxedExpr(ObjCBoxedExpr * E)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 
VisitObjCDictionaryLiteral(ObjCDictionaryLiteral * E)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 
VisitObjCArrayLiteral(ObjCArrayLiteral * E)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 
VisitCXXConstructExpr(CXXConstructExpr * E)122   bool VisitCXXConstructExpr(CXXConstructExpr *E) {
123     IndexCtx.handleReference(E->getConstructor(), E->getLocation(),
124                              Parent, ParentDC, E);
125     return true;
126   }
127 
TraverseCXXOperatorCallExpr(CXXOperatorCallExpr * E,DataRecursionQueue * Q=nullptr)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 
VisitDeclStmt(DeclStmt * S)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 
TraverseLambdaCapture(LambdaExpr * LE,const LambdaCapture * C)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 
indexBody(const Stmt * S,const NamedDecl * Parent,const DeclContext * DC)169 void 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