1//===--- ASTVisitor.h - Visitor for an ASTContext ---------------*- C++ -*-===//
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//  This file defines the ASTVisitor interface.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_INDEX_ASTVISITOR_H
15#define LLVM_CLANG_INDEX_ASTVISITOR_H
16
17#include "clang/AST/DeclVisitor.h"
18#include "clang/AST/StmtVisitor.h"
19#include "clang/AST/TypeLocVisitor.h"
20
21namespace clang {
22
23namespace idx {
24
25/// \brief Traverses the full AST, both Decls and Stmts.
26template<typename ImplClass>
27class ASTVisitor : public DeclVisitor<ImplClass>,
28                   public StmtVisitor<ImplClass>,
29                   public TypeLocVisitor<ImplClass> {
30public:
31  ASTVisitor() : CurrentDecl(0) { }
32
33  Decl *CurrentDecl;
34
35  typedef ASTVisitor<ImplClass>  Base;
36  typedef DeclVisitor<ImplClass> BaseDeclVisitor;
37  typedef StmtVisitor<ImplClass> BaseStmtVisitor;
38  typedef TypeLocVisitor<ImplClass> BaseTypeLocVisitor;
39
40  using BaseStmtVisitor::Visit;
41
42  //===--------------------------------------------------------------------===//
43  // DeclVisitor
44  //===--------------------------------------------------------------------===//
45
46  void Visit(Decl *D) {
47    Decl *PrevDecl = CurrentDecl;
48    CurrentDecl = D;
49    BaseDeclVisitor::Visit(D);
50    CurrentDecl = PrevDecl;
51  }
52
53  void VisitDeclaratorDecl(DeclaratorDecl *D) {
54    BaseDeclVisitor::VisitDeclaratorDecl(D);
55    if (TypeSourceInfo *TInfo = D->getTypeSourceInfo())
56      Visit(TInfo->getTypeLoc());
57  }
58
59  void VisitFunctionDecl(FunctionDecl *D) {
60    BaseDeclVisitor::VisitFunctionDecl(D);
61    if (D->isThisDeclarationADefinition())
62      Visit(D->getBody());
63  }
64
65  void VisitObjCMethodDecl(ObjCMethodDecl *D) {
66    BaseDeclVisitor::VisitObjCMethodDecl(D);
67    if (D->getBody())
68      Visit(D->getBody());
69  }
70
71  void VisitBlockDecl(BlockDecl *D) {
72    BaseDeclVisitor::VisitBlockDecl(D);
73    Visit(D->getBody());
74  }
75
76  void VisitVarDecl(VarDecl *D) {
77    BaseDeclVisitor::VisitVarDecl(D);
78    if (Expr *Init = D->getInit())
79      Visit(Init);
80  }
81
82  void VisitDecl(Decl *D) {
83    if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D) || isa<BlockDecl>(D))
84      return;
85
86    if (DeclContext *DC = dyn_cast<DeclContext>(D))
87      static_cast<ImplClass*>(this)->VisitDeclContext(DC);
88  }
89
90  void VisitDeclContext(DeclContext *DC) {
91    for (DeclContext::decl_iterator
92           I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I)
93      Visit(*I);
94  }
95
96  //===--------------------------------------------------------------------===//
97  // StmtVisitor
98  //===--------------------------------------------------------------------===//
99
100  void VisitDeclStmt(DeclStmt *Node) {
101    for (DeclStmt::decl_iterator
102           I = Node->decl_begin(), E = Node->decl_end(); I != E; ++I)
103      Visit(*I);
104  }
105
106  void VisitBlockExpr(BlockExpr *Node) {
107    // The BlockDecl is also visited by 'VisitDeclContext()'.  No need to visit it twice.
108  }
109
110  void VisitStmt(Stmt *Node) {
111    for (Stmt::child_range I = Node->children(); I; ++I)
112      if (*I)
113        Visit(*I);
114  }
115
116  //===--------------------------------------------------------------------===//
117  // TypeLocVisitor
118  //===--------------------------------------------------------------------===//
119
120  void Visit(TypeLoc TL) {
121    for (; TL; TL = TL.getNextTypeLoc())
122      BaseTypeLocVisitor::Visit(TL);
123  }
124
125  void VisitArrayLoc(ArrayTypeLoc TL) {
126    BaseTypeLocVisitor::VisitArrayTypeLoc(TL);
127    if (TL.getSizeExpr())
128      Visit(TL.getSizeExpr());
129  }
130
131  void VisitFunctionTypeLoc(FunctionTypeLoc TL) {
132    BaseTypeLocVisitor::VisitFunctionTypeLoc(TL);
133    for (unsigned i = 0; i != TL.getNumArgs(); ++i)
134      Visit(TL.getArg(i));
135  }
136
137};
138
139} // namespace idx
140
141} // namespace clang
142
143#endif
144