IndexBody.cpp revision e422e45a6a89d450b8eca10f671b49874e87617a
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
12#include "clang/AST/RecursiveASTVisitor.h"
13#include "clang/Analysis/Support/SaveAndRestore.h"
14
15using namespace clang;
16using namespace cxindex;
17
18namespace {
19
20class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
21  IndexingContext &IndexCtx;
22  const NamedDecl *Parent;
23  const DeclContext *ParentDC;
24  bool InPseudoObject;
25
26  typedef RecursiveASTVisitor<BodyIndexer> base;
27public:
28  BodyIndexer(IndexingContext &indexCtx,
29              const NamedDecl *Parent, const DeclContext *DC)
30    : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC),
31      InPseudoObject(false) { }
32
33  bool shouldWalkTypesOfTypeLocs() const { return false; }
34
35  bool TraverseTypeLoc(TypeLoc TL) {
36    IndexCtx.indexTypeLoc(TL, Parent, ParentDC);
37    return true;
38  }
39
40  bool VisitDeclRefExpr(DeclRefExpr *E) {
41    IndexCtx.handleReference(E->getDecl(), E->getLocation(),
42                             Parent, ParentDC, E);
43    return true;
44  }
45
46  bool VisitMemberExpr(MemberExpr *E) {
47    IndexCtx.handleReference(E->getMemberDecl(), E->getMemberLoc(),
48                             Parent, ParentDC, E);
49    return true;
50  }
51
52  bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
53    IndexCtx.handleReference(E->getDecl(), E->getLocation(),
54                             Parent, ParentDC, E);
55    return true;
56  }
57
58  bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
59    if (TypeSourceInfo *Cls = E->getClassReceiverTypeInfo())
60      IndexCtx.indexTypeSourceInfo(Cls, Parent, ParentDC);
61
62    if (ObjCMethodDecl *MD = E->getMethodDecl())
63      IndexCtx.handleReference(MD, E->getSelectorStartLoc(),
64                               Parent, ParentDC, E,
65                               InPseudoObject ? CXIdxEntityRef_Implicit
66                                              : CXIdxEntityRef_Direct);
67    return true;
68  }
69
70  bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
71    if (E->isImplicitProperty()) {
72      if (ObjCMethodDecl *MD = E->getImplicitPropertyGetter())
73        IndexCtx.handleReference(MD, E->getLocation(), Parent, ParentDC, E,
74                                 CXIdxEntityRef_Implicit);
75      if (ObjCMethodDecl *MD = E->getImplicitPropertySetter())
76        IndexCtx.handleReference(MD, E->getLocation(), Parent, ParentDC, E,
77                                 CXIdxEntityRef_Implicit);
78    } else {
79      IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(),
80                               Parent, ParentDC, E);
81    }
82    return true;
83  }
84
85  bool TraversePseudoObjectExpr(PseudoObjectExpr *E) {
86    SaveAndRestore<bool> InPseudo(InPseudoObject, true);
87    return base::TraversePseudoObjectExpr(E);
88  }
89
90  bool VisitCXXConstructExpr(CXXConstructExpr *E) {
91    IndexCtx.handleReference(E->getConstructor(), E->getLocation(),
92                             Parent, ParentDC, E);
93    return true;
94  }
95};
96
97} // anonymous namespace
98
99void IndexingContext::indexBody(const Stmt *S, const NamedDecl *Parent,
100                                const DeclContext *DC) {
101  if (!S)
102    return;
103
104  if (DC == 0)
105    DC = Parent->getLexicalDeclContext();
106  BodyIndexer(*this, Parent, DC).TraverseStmt(const_cast<Stmt*>(S));
107}
108