commit 14979e33bd59b1954f7e3a1d6346d7164ca31c7a
parent d5f4672cae53e239fea472038bfde568842e677f
Author: kyle <kyle@getaddrinfo.net>
Date: Thu, 29 Oct 2015 19:06:02 -0600
instrument: refactor astvisitor
- rename MyASTVisitor -> instrumenter
- move member function definitions out of class declaration
- regress declaration coverage
- add funtion call coverage
- generally switch from "linus[xx] = 1, xxx" to "(lines[xx] = 1, xxx)"
Diffstat:
5 files changed, 125 insertions(+), 113 deletions(-)
diff --git a/instrument/instrument.cpp b/instrument/instrument.cpp
@@ -18,6 +18,7 @@
#include "clang/Frontend/ASTConsumers.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Lexer.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
#include "clang/Rewrite/Core/Rewriter.h"
@@ -29,105 +30,116 @@ using namespace clang::tooling;
static llvm::cl::OptionCategory ToolingSampleCategory("Tooling Sample");
+
// By implementing RecursiveASTVisitor, we can specify which AST nodes
// we're interested in by overriding relevant methods.
-class MyASTVisitor : public RecursiveASTVisitor<MyASTVisitor> {
+class instrumenter : public RecursiveASTVisitor<instrumenter> {
public:
- MyASTVisitor(Rewriter &R) : TheRewriter(R) {}
+ instrumenter(Rewriter &R) : TheRewriter(R), SM(R.getSourceMgr()) {}
- bool VisitVarDecl(VarDecl *d) {
- // std::cout << "HERE" << std::endl;
- return true;
- }
- bool VisitStmt(Stmt *s) {
- std::stringstream ss;
- SourceManager &SM = TheRewriter.getSourceMgr();
- unsigned line = SM.getPresumedLineNumber(s->getLocStart());
+ bool VisitVarDecl(VarDecl *d);
+ bool VisitStmt(Stmt *s);
+ bool VisitFunctionDecl(FunctionDecl *f);
- ss << "lines[" << line << "] = 1";
+private:
+ Rewriter &TheRewriter;
+ SourceManager &SM;
+ LangOptions lopt;
- if (isa<IfStmt>(s)) {
- IfStmt *IfStatement = cast<IfStmt>(s);
- Stmt *Cond = IfStatement->getCond();
- ss << ", ";
- TheRewriter.InsertTextBefore(Cond->getLocStart(),
- ss.str());
- }
- else if (isa<ForStmt>(s)) {
- ForStmt *ForStatement = cast<ForStmt>(s);
- Stmt *Cond = ForStatement->getCond();
- ss << ", ";
- TheRewriter.InsertTextAfter(Cond->getLocStart(),
- ss.str());
- }
- else if (isa<ReturnStmt>(s)) {
- ReturnStmt *ReturnStatement = cast<ReturnStmt>(s);
- Expr *RetValue = ReturnStatement->getRetValue();
- ss << ", ";
- TheRewriter.InsertTextBefore(RetValue->getLocStart(),
- ss.str());
- }
- else if (isa<WhileStmt>(s)) {
- WhileStmt *WhileStatement = cast<WhileStmt>(s);
- Stmt *Cond = WhileStatement->getCond();
- ss << ", ";
- TheRewriter.InsertTextBefore(Cond->getLocStart(),
- ss.str());
- }
- else if (isa<BreakStmt>(s) || isa<ContinueStmt>(s) ||
- isa<DeclStmt>(s) || isa<SwitchStmt>(s) ||
- isa<SwitchCase>(s)) {
- ss << "; ";
- TheRewriter.InsertTextBefore(s->getLocStart(),
- ss.str());
- }
- else if (isa<CallExpr>(s)) {
- /* still has problems with f(x) + g(y) style code
- ss << ", ";
- TheRewriter.InsertTextBefore(s->getLocStart(),
- ss.str());
- */
- }
+ SourceLocation real_loc_end(Stmt *s);
+};
- return true;
+bool
+instrumenter::VisitVarDecl(VarDecl *d)
+{
+ // std::cout << "HERE" << std::endl;
+ return true;
+}
+
+bool
+instrumenter::VisitStmt(Stmt *s)
+{
+ std::stringstream ss;
+ unsigned line = SM.getPresumedLineNumber(s->getLocStart());
+ Stmt *stmt_to_inst;
+
+ if (isa<IfStmt>(s)) {
+ IfStmt *IfStatement = cast<IfStmt>(s);
+ stmt_to_inst = IfStatement->getCond();
+ }
+ else if (isa<ForStmt>(s)) {
+ ForStmt *ForStatement = cast<ForStmt>(s);
+ stmt_to_inst = ForStatement->getCond();
}
+ else if (isa<WhileStmt>(s)) {
+ WhileStmt *WhileStatement = cast<WhileStmt>(s);
+ stmt_to_inst = WhileStatement->getCond();
+ }
+ else if (isa<ReturnStmt>(s)) {
+ ReturnStmt *ReturnStatement = cast<ReturnStmt>(s);
+ stmt_to_inst = ReturnStatement->getRetValue();
+ }
+ /*
+ else if (isa<BreakStmt>(s) || isa<ContinueStmt>(s) ||
+ || isa<SwitchStmt>(s) || isa<SwitchCase>(s)) {
+ }
+ */
+ else if (isa<DeclStmt>(s)) {
+ }
+ else if (isa<CallExpr>(s)) {
+ stmt_to_inst = s;
+ }
+ else
+ return true;
+
+ ss << "(lines[" << line << "] = 1, ";
+ TheRewriter.InsertTextBefore(stmt_to_inst->getLocStart(), ss.str());
+ TheRewriter.InsertTextAfter(real_loc_end(stmt_to_inst), ")");
- bool VisitFunctionDecl(FunctionDecl *f) {
- // Only function definitions (with bodies), not declarations.
- if (f->hasBody()) {
- Stmt *FuncBody = f->getBody();
+ return true;
+}
+bool
+instrumenter::VisitFunctionDecl(FunctionDecl *f)
+{
+ // Only function definitions (with bodies), not declarations.
+ if (f->hasBody()) {
+ Stmt *FuncBody = f->getBody();
#if 0
- // Type name as string
- QualType QT = f->getReturnType();
- std::string TypeStr = QT.getAsString();
-
- // Function name
- DeclarationName DeclName = f->getNameInfo().getName();
- std::string FuncName = DeclName.getAsString();
-
- // Add comment before
- std::stringstream SSBefore;
- SSBefore << "// Begin function " << FuncName << " returning " << TypeStr
- << "\n";
- SourceLocation ST = f->getSourceRange().getBegin();
- TheRewriter.InsertText(ST, SSBefore.str(), true, true);
-
- // And after
- std::stringstream SSAfter;
- SSAfter << "\n// End function " << FuncName;
- ST = FuncBody->getLocEnd().getLocWithOffset(1);
- TheRewriter.InsertText(ST, SSAfter.str(), true, true);
+ // Type name as string
+ QualType QT = f->getReturnType();
+ std::string TypeStr = QT.getAsString();
+
+ // Function name
+ DeclarationName DeclName = f->getNameInfo().getName();
+ std::string FuncName = DeclName.getAsString();
+
+ // Add comment before
+ std::stringstream SSBefore;
+ SSBefore << "// Begin function " << FuncName << " returning " << TypeStr
+ << "\n";
+ SourceLocation ST = f->getSourceRange().getBegin();
+ TheRewriter.InsertText(ST, SSBefore.str(), true, true);
+
+ // And after
+ std::stringstream SSAfter;
+ SSAfter << "\n// End function " << FuncName;
+ ST = FuncBody->getLocEnd().getLocWithOffset(1);
+ TheRewriter.InsertText(ST, SSAfter.str(), true, true);
#endif
- }
-
- return true;
}
-private:
- Rewriter &TheRewriter;
-};
+ return true;
+}
+
+SourceLocation
+instrumenter::real_loc_end(Stmt *d)
+{
+ SourceLocation _e(d->getLocEnd());
+ return SourceLocation(Lexer::getLocForEndOfToken(_e, 0, SM, lopt));
+}
+
// Implementation of the ASTConsumer interface for reading an AST produced
// by the Clang parser.
@@ -147,7 +159,7 @@ public:
}
private:
- MyASTVisitor Visitor;
+ instrumenter Visitor;
};
// For each source file provided to the tool, a new FrontendAction is created.
diff --git a/tests/fibonacci/instrumented.c b/tests/fibonacci/instrumented.c
@@ -8,30 +8,30 @@ int size = 512;
long long
fibonacci(long long n)
{
- if (lines[9] = 1, n == 0)
- return lines[10] = 1, 0;
- else if (lines[11] = 1, n == 1)
- return lines[12] = 1, 1;
+ if ((lines[9] = 1, n == 0))
+ return (lines[10] = 1, 0);
+ else if ((lines[11] = 1, n == 1))
+ return (lines[12] = 1, 1);
- return lines[14] = 1, fibonacci(n - 1) + fibonacci(n - 2);
+ return (lines[14] = 1, (lines[14] = 1, fibonacci(n - 1)) + (lines[14] = 1, fibonacci(n - 2)));
}
int
main(int argc, char *argv[])
{
- lines[20] = 1; long long n;
- lines[21] = 1; const char *errstr = NULL;
+ long long n;
+ const char *errstr = NULL;
- if (lines[23] = 1, argc != 2) {
- printf("usage: %s <N>\n", argv[0]);
- return lines[25] = 1, 1;
+ if ((lines[23] = 1, argc != 2)) {
+ (lines[24] = 1, printf("usage: %s <N>\n", argv[0]));
+ return (lines[25] = 1, 1);
}
- n = strtonum(argv[1], LONG_MIN, LONG_MAX, &errstr);
- if (lines[29] = 1, errstr)
- err(1, "%s", errstr);
+ n = (lines[28] = 1, strtonum(argv[1], LONG_MIN, LONG_MAX, &errstr));
+ if ((lines[29] = 1, errstr))
+ (lines[30] = 1, err(1, "%s", errstr));
- printf("result: %lli\n", fibonacci(n));
+ (lines[32] = 1, printf("result: %lli\n", (lines[32] = 1, fibonacci(n))));
- return lines[34] = 1, 0;
+ return (lines[34] = 1, 0);
}
diff --git a/tests/hello_world/instrumented.c b/tests/hello_world/instrumented.c
@@ -5,6 +5,6 @@ int size = 77;
int
main(void)
{
- printf("hello, world\n");
- return lines[7] = 1, 0;
+ (lines[6] = 1, printf("hello, world\n"));
+ return (lines[7] = 1, 0);
}
diff --git a/tests/if_statement/instrumented.c b/tests/if_statement/instrumented.c
@@ -5,18 +5,18 @@ int size = 199;
int
main(int argc, char *argv[])
{
- if (lines[6] = 1, argc == 1)
- return lines[7] = 1, 1;
+ if ((lines[6] = 1, argc == 1))
+ return (lines[7] = 1, 1);
else
- exit(14);
+ (lines[9] = 1, exit(14));
- if (lines[11] = 1, argc == 2) {
- return lines[12] = 1, 5;
+ if ((lines[11] = 1, argc == 2)) {
+ return (lines[12] = 1, 5);
}
- else if (lines[14] = 1, argc == 3) {
- return lines[15] = 1, 0;
+ else if ((lines[14] = 1, argc == 3)) {
+ return (lines[15] = 1, 0);
}
else {
- exit(0);
+ (lines[18] = 1, exit(0));
}
}
diff --git a/tests/while_loops/instrumented.c b/tests/while_loops/instrumented.c
@@ -3,12 +3,12 @@ int size = 76;
int
main(void)
{
- lines[4] = 1; int i;
+ int i;
i = 0;
- while (lines[7] = 1, i < 10) {
+ while ((lines[7] = 1, i < 10)) {
i++;
}
- return lines[11] = 1, i;
+ return (lines[11] = 1, i);
}