aboutsummaryrefslogtreecommitdiff
path: root/tools/clang-ast-dump/ClangASTDump.cpp
blob: 2b86fd6d2932d2a95ab36ebf27f49fbc29b26d79 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
//===- tools/clang-ast-dump/ClangASTDump.cpp - Clang AST Dump tool --------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements a clang-ast-dump tool that dumps specified parts
//  of an AST of a number of translation units.
//
//  Run with '-help' for details.
//
//  This tool uses the Clang Tooling infrastructure, see
//    http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html
//  for details on setting it up with LLVM source tree.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/CommandLine.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Tooling/CommandLineClangTool.h"
#include "clang/Tooling/Tooling.h"

using namespace clang::tooling;
using namespace llvm;

cl::opt<std::string> FilterString(
  "f",
  cl::desc("Filter string"),
  cl::Optional);

cl::opt<bool> ListAll(
  "l",
  cl::desc("List all filterable nodes"),
  cl::init(false),
  cl::Optional);

static const char *MoreHelpText =
    "-f <filter-string> can be used to dump only AST declaration nodes having\n"
    "\ta certain substring in a qualified name.\n"
    "\n"
    "-l \tlists qualified names of all filterable declaration nodes.\n"
    "\n";

namespace {

using namespace clang;

class SelectiveDumpVisitor :
     public RecursiveASTVisitor<SelectiveDumpVisitor> {
  typedef RecursiveASTVisitor<SelectiveDumpVisitor> base;
public:
  SelectiveDumpVisitor(const std::string &FilterString, bool ListAll)
      : FilterString(FilterString), ListAll(ListAll) {}

  ASTConsumer* newASTConsumer() {
    return new DumpConsumer(this);
  }

  bool shouldWalkTypesOfTypeLocs() const { return false; }

  void Run(TranslationUnitDecl *D) {
    if (ListAll) {
      llvm::outs().changeColor(llvm::raw_ostream::BLUE) <<
          "Listing all filterable nodes:\n";
      llvm::outs().resetColor();
      TraverseDecl(D);
      return;
    }

    if (FilterString.empty()) {
      llvm::outs().changeColor(llvm::raw_ostream::BLUE) <<
          "Dumping translation unit:\n";
      llvm::outs().resetColor();
      D->dumpXML(llvm::outs());
      return;
    }

    TraverseDecl(D);
  }

  bool TraverseDecl(Decl *D) {
    if (ListAll) {
      std::string Name = getName(D);
      if (!Name.empty())
        llvm::outs() << Name << "\n";
      return base::TraverseDecl(D);
    }

    if (filterMatches(D)) {
      llvm::outs().changeColor(llvm::raw_ostream::BLUE) <<
          "Dumping " << getName(D) << ":\n";
      llvm::outs().resetColor();
      D->dumpXML(llvm::outs());
      return true;
    }
    return base::TraverseDecl(D);
  }

private:
  std::string getName(Decl *D) {
    if (isa<NamedDecl>(D))
      return cast<NamedDecl>(D)->getQualifiedNameAsString();
    return "";
  }
  bool filterMatches(Decl *D) {
    return getName(D).find(FilterString) != std::string::npos;
  }

  class DumpConsumer : public ASTConsumer {
  public:
    DumpConsumer(SelectiveDumpVisitor *Visitor) : Visitor(Visitor) {}

    virtual void HandleTranslationUnit(ASTContext &Context) {
      Visitor->Context = &Context;
      Visitor->Run(Context.getTranslationUnitDecl());
    }

  private:
    SelectiveDumpVisitor *Visitor;
  };

  ASTContext *Context;
  std::string FilterString;
  bool ListAll;
};

} // namespace

int main(int argc, const char **argv) {
  CommandLineClangTool Tool;
  cl::extrahelp MoreHelp(MoreHelpText);
  Tool.initialize(argc, argv);
  SelectiveDumpVisitor Dumper(FilterString, ListAll);
  return Tool.run(newFrontendActionFactory(&Dumper));
}