-
Notifications
You must be signed in to change notification settings - Fork 5
/
ex01.cc
149 lines (125 loc) · 4.57 KB
/
ex01.cc
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
142
143
144
145
146
147
148
149
#include "clang/Driver/Options.h"
#include "clang/AST/AST.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Frontend/ASTConsumers.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
#include "clang/Rewrite/Core/Rewriter.h"
using namespace std;
using namespace llvm;
clang::Rewriter rewriter;
int numFunctions = 0;
class ExampleVisitor : public clang::RecursiveASTVisitor<ExampleVisitor>
{
private:
clang::ASTContext* ast_context_; // used for getting additional AST info
public:
explicit ExampleVisitor(clang::CompilerInstance* ci)
: ast_context_(&(ci->getASTContext())) // initialize private members
{
rewriter.setSourceMgr(ast_context_->getSourceManager(),
ast_context_->getLangOpts());
}
virtual bool VisitFunctionDecl(clang::FunctionDecl* func)
{
numFunctions++;
string funcName = func->getNameInfo().getName().getAsString();
if (funcName == "do_math")
{
rewriter.ReplaceText(func->getLocation(), funcName.length(),"add5");
errs() << "** Rewrote function def: " << funcName << "\n";
}
return true;
}
virtual bool VisitStmt(clang::Stmt* st)
{
if (clang::ReturnStmt *ret = dyn_cast<clang::ReturnStmt>(st))
{
rewriter.ReplaceText(ret->getRetValue()->getLocStart(), 6, "val");
errs() << "** Rewrote ReturnStmt\n";
}
if (clang::CallExpr* call = dyn_cast<clang::CallExpr>(st))
{
rewriter.ReplaceText(call->getLocStart(), 7, "add5");
errs() << "** Rewrote function call\n";
}
return true;
}
/*
virtual bool VisitReturnStmt(clang::ReturnStmt* ret) {
rewriter.ReplaceText(ret->getRetValue()->getLocStart(), 6, "val");
errs() << "** Rewrote ReturnStmt\n";
return true;
}
virtual bool VisitCallExpr(clang::CallExpr* call) {
rewriter.ReplaceText(call->getLocStart(), 7, "add5");
errs() << "** Rewrote function call\n";
return true;
}
*/
};
class ExampleASTConsumer : public clang::ASTConsumer
{
private:
ExampleVisitor* visitor_; // doesn't have to be private
public:
// override the constructor in order to pass CI
explicit ExampleASTConsumer(clang::CompilerInstance* ci)
: visitor_(new ExampleVisitor(ci)) // initialize the visitor_
{
}
// override this to call our ExampleVisitor on the entire source file
virtual void HandleTranslationUnit(clang::ASTContext& context)
{
/**
* we can use ASTContext to get the TranslationUnitDecl, which is
a single Decl that collectively represents the entire source file
*/
visitor_->TraverseDecl(context.getTranslationUnitDecl());
}
/*
// override this to call our ExampleVisitor on each top-level Decl
virtual bool HandleTopLevelDecl(clang::DeclGroupRef DG)
{
// a DeclGroupRef may have multiple Decls, so we iterate through each one
for (clang::DeclGroupRef::iterator i = DG.begin(), e = DG.end();
i != e; i++)
{
Decl *D = *i;
visitor_->TraverseDecl(D); // recursively visit each AST node
// in Decl "D"
}
return true;
}
*/
};
class ExampleFrontendAction : public clang::ASTFrontendAction
{
public:
virtual clang::ASTConsumer* CreateASTConsumer(clang::CompilerInstance& ci,
llvm::StringRef file)
{
return new ExampleASTConsumer(&ci); // pass CI pointer to ASTConsumer
}
};
int main(int argc, const char **argv)
{
// parse the command-line args passed to your code
cl::OptionCategory my_tool_category("my tool option");
clang::tooling::CommonOptionsParser op(argc, argv, my_tool_category);
// create a new Clang Tool instance (a LibTooling environment)
clang::tooling::ClangTool tool(op.getCompilations(),op.getSourcePathList());
// run the Clang Tool, creating a new FrontendAction (explained below)
int result = tool.run(
clang::tooling::newFrontendActionFactory<ExampleFrontendAction>().get()
);
errs() << "\nFound " << numFunctions << " functions.\n\n";
// print out the rewritten source code ("rewriter" is a global var.)
rewriter.getEditBuffer(
rewriter.getSourceMgr().getMainFileID()).write(errs());
return result;
}