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