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:
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)128   bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
129     if (E->getOperatorLoc().isInvalid())
130       return true; // implicit.
131     return base::TraverseCXXOperatorCallExpr(E);
132   }
133 
VisitDeclStmt(DeclStmt * S)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 
TraverseLambdaCapture(LambdaExpr * LE,const LambdaCapture * C)152   bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C) {
153     if (C->capturesThis() || C->capturesVLAType())
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 
indexBody(const Stmt * S,const NamedDecl * Parent,const DeclContext * DC)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