commit c31eeb2c4387cd35a0a75dabf87bffd225ade36f
parent 79b129ef21726edee03e003bdbf5eba0592ef494
Author: Kyle Milz <kyle@0x30.net>
Date: Sun, 4 Dec 2016 19:43:48 -0700
src: move most of inst_main.cc into inst_frontend.cc
Diffstat:
10 files changed, 158 insertions(+), 181 deletions(-)
diff --git a/man/citrun-check.1 b/man/citrun-check.1
@@ -74,8 +74,6 @@ The following table lists all possible events and describes them:
The total number of C/C++ source files that had rewriting attempted on them.
.It Qq Application link commands
Number of link commands detected and modified to include the runtime.
-.It Qq Rewrite parse {warnings,errors}
-The total number of parsing problems the rewriter had.
.It Qq Rewrite successes
The number of times the rewriter successfully transformed the entire source
file.
diff --git a/src/check.sh b/src/check.sh
@@ -45,12 +45,10 @@ fi
find $@ -name citrun.log -print0 | xargs -0 awk '
$0~/Found source file/ { summary[0] += 1 }
$0~/Link detected/ { summary[1] += 1 }
-$0~/warning:/ { summary[2] += 1 }
-$0~/error:/ { summary[3] += 1 }
-$0~/Rewriting successful/ { summary[4] += 1 }
-$0~/Rewriting failed/ { summary[5] += 1 }
-$0~/Rewritten source compile successful/ { summary[6] += 1 }
-$0~/Rewritten source compile failed/ { summary[7] += 1 }
+$0~/Rewriting successful/ { summary[2] += 1 }
+$0~/Rewriting failed/ { summary[3] += 1 }
+$0~/Rewritten source compile successful/ { summary[4] += 1 }
+$0~/Rewritten source compile failed/ { summary[5] += 1 }
$0~/Lines of source code/ { totals[0] += $2 }
$0~/Milliseconds spent rewriting source/ { totals[1] += $2 }
@@ -69,15 +67,13 @@ $0~/Errors rewriting source/ { totals[12] += $2 }
END {
summary_desc[0] = "Source files used as input"
summary_desc[1] = "Application link commands"
- summary_desc[2] = "Rewrite parse warnings"
- summary_desc[3] = "Rewrite parse errors"
- summary_desc[4] = "Rewrite successes"
- summary_desc[5] = "Rewrite failures"
- summary_desc[6] = "Rewritten source compile successes"
- summary_desc[7] = "Rewritten source compile failures"
+ summary_desc[2] = "Rewrite successes"
+ summary_desc[3] = "Rewrite failures"
+ summary_desc[4] = "Rewritten source compile successes"
+ summary_desc[5] = "Rewritten source compile failures"
print "Summary:"
- for (i = 0; i < 8; i++) {
+ for (i = 0; i < 6; i++) {
if (i != 0 && summary[i] == 0) continue
printf "%10i %s\n", summary[i], summary_desc[i]
}
diff --git a/src/inst_action.cc b/src/inst_action.cc
@@ -43,20 +43,20 @@ InstrumentAction::write_modified_src(clang::FileID const &fid)
if (m_is_citruninst) {
out_file += ".citrun";
- *m_log << "Writing modified source to '" << out_file << "'" << std::endl;
+ m_log << "Writing modified source to '" << out_file << "'" << std::endl;
}
std::error_code ec;
llvm::raw_fd_ostream output(out_file, ec, llvm::sys::fs::F_None);
if (ec.value()) {
- *m_log << "Error writing modified source '" << out_file
+ m_log << "Error writing modified source '" << out_file
<< "': " << ec.message() << std::endl;
return;
}
// Write the instrumented source file
m_TheRewriter.getEditBuffer(fid).write(output);
- *m_log << "Modified source written successfully." << std::endl;
+ m_log << "Modified source written successfully." << std::endl;
}
void
@@ -95,12 +95,12 @@ InstrumentAction::EndSourceFileAction()
clang::SourceLocation start = sm.getLocForStartOfFile(main_fid);
if (m_TheRewriter.InsertTextAfter(start, preamble.str())) {
- *m_log << "Failed to insert the instrumentation preabmle.";
+ m_log << "Failed to insert the instrumentation preabmle.";
return;
}
- *m_log << "Instrumentation of '" << m_compiler_file_name << "' finished:" << std::endl;
- *m_log << " " << num_lines << " Lines of source code" << std::endl;
+ m_log << "Instrumentation of '" << m_compiler_file_name << "' finished:" << std::endl;
+ m_log << " " << num_lines << " Lines of source code" << std::endl;
//
// Write out statistics from the AST visitor.
@@ -109,7 +109,7 @@ InstrumentAction::EndSourceFileAction()
for (int i = 0; i < NCOUNTERS; ++i) {
if (v.m_counters[i] == 0)
continue;
- *m_log << " " << v.m_counters[i] << " "
+ m_log << " " << v.m_counters[i] << " "
<< v.m_counter_descr[i] << std::endl;
}
diff --git a/src/inst_action.h b/src/inst_action.h
@@ -30,7 +30,7 @@ private:
// For each source file provided to the tool, a new FrontendAction is created.
class InstrumentAction : public clang::ASTFrontendAction {
public:
- InstrumentAction(InstrumentLogger *log, bool citruninst,
+ InstrumentAction(InstrumentLogger &log, bool citruninst,
std::string const &filename) :
m_log(log),
m_is_citruninst(citruninst),
@@ -45,7 +45,7 @@ private:
clang::Rewriter m_TheRewriter;
RewriteASTConsumer *m_InstrumentASTConsumer;
- InstrumentLogger *m_log;
+ InstrumentLogger& m_log;
bool m_is_citruninst;
std::string m_compiler_file_name;
};
diff --git a/src/inst_frontend.cc b/src/inst_frontend.cc
@@ -14,12 +14,14 @@
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//
#include "inst_frontend.h"
+#include "version.h" // citrun_major, citrun_minor
#include <sys/stat.h> // stat
#include <sys/time.h> // utimes
+#include <sys/utsname.h> // uname
#include <sys/wait.h> // waitpid
-#include <clang/Frontend/TextDiagnosticPrinter.h>
+#include <clang/Frontend/TextDiagnosticBuffer.h>
#include <clang/Tooling/CommonOptionsParser.h>
#include <clang/Tooling/Tooling.h>
#include <cstdio> // tmpnam
@@ -32,14 +34,87 @@
static llvm::cl::OptionCategory ToolingCategory("citrun-inst options");
-InstrumentFrontend::InstrumentFrontend(int argc, char *argv[],
- InstrumentLogger *l, bool is_citruninst) :
+InstrumentFrontend::InstrumentFrontend(int argc, char *argv[]) :
m_args(argv, argv + argc),
- m_log(l),
- m_is_citruninst(is_citruninst)
+ m_is_citruninst(false),
+ m_start_time(std::chrono::high_resolution_clock::now())
{
+
+ char *base_name;
+ if ((base_name = basename(m_args[0])) == NULL)
+ err(1, "basename");
+
+ if (std::strcmp(base_name, "citrun-inst") == 0)
+ m_is_citruninst = true;
+
+ if (m_is_citruninst)
+ m_log.set_citruninst();
+
+ m_log << "citrun-inst " << citrun_major << "." << citrun_minor << " ";
+
+ struct utsname utsname;
+ if (uname(&utsname) == -1)
+ m_log << "(Unknown OS)";
+ else {
+ m_log << "(" << utsname.sysname << "-" << utsname.release << " "
+ << utsname.machine << ")";
+ }
+ m_log << " '" << CITRUN_SHARE << "'" << std::endl;
+
+ if (m_is_citruninst) {
+ m_log << ">> Welcome to C It Run! Have a nice day." << std::endl;
+ } else {
+ // There's extra work to do if we're not running as citrun-inst.
+ m_log << "Tool called as '" << m_args[0] << "'";
+ if (std::strcmp(base_name, m_args[0]) != 0) {
+ m_log << ", changing to '" << base_name << "'";
+ m_args[0] = base_name;
+ }
+ m_log << std::endl;
+
+ setprogname("citrun-inst");
+ clean_PATH();
+ }
}
+void
+InstrumentFrontend::clean_PATH()
+{
+ char *path;
+ if ((path = std::getenv("PATH")) == NULL)
+ errx(1, "Error: PATH is not set.");
+
+ m_log << "PATH='" << path << "'" << std::endl;
+
+ // Filter CITRUN_SHARE out of PATH
+ std::stringstream path_ss(path);
+ std::ostringstream new_path;
+ std::string component;
+ bool first_component = 1;
+ bool found_citrun_path = 0;
+
+ while (std::getline(path_ss, component, ':')) {
+ if (component.compare(CITRUN_SHARE) == 0) {
+ found_citrun_path = 1;
+ continue;
+ }
+
+ if (first_component == 0)
+ new_path << ":";
+
+ // It wasn't CITRUN_SHARE, keep it
+ new_path << component;
+ first_component = 0;
+ }
+
+ if (!found_citrun_path)
+ errx(1, "Error: CITRUN_SHARE not in PATH.");
+
+ if (setenv("PATH", new_path.str().c_str(), 1))
+ err(1, "setenv");
+}
+
+
// Returns true if value ends with suffix, false otherwise.
static bool
ends_with(std::string const &value, std::string const &suffix)
@@ -87,7 +162,7 @@ InstrumentFrontend::save_if_srcfile(char *arg)
return;
m_source_files.push_back(arg);
- *m_log << "Found source file '" << arg << "'" << std::endl;
+ m_log << "Found source file '" << arg << "'" << std::endl;
if (m_is_citruninst)
// In this mode the modified source file is written to a
@@ -119,7 +194,7 @@ InstrumentFrontend::if_link_add_runtime(bool object_arg, bool compile_arg)
if (!linking)
return;
- *m_log << "Link detected, adding '"<< CITRUN_SHARE "/libcitrun.a"
+ m_log << "Link detected, adding '"<< CITRUN_SHARE "/libcitrun.a"
<< "' to command line." << std::endl;
m_args.push_back(const_cast<char *>(CITRUN_SHARE "/libcitrun.a"));
}
@@ -136,7 +211,7 @@ InstrumentFrontend::process_cmdline()
if (std::strcmp(arg, "-E") == 0 ||
std::strcmp(arg, "-MM") == 0) {
- *m_log << "Preprocessor argument found" << std::endl;
+ m_log << "Preprocessor argument found" << std::endl;
exec_compiler();
}
else if (std::strcmp(arg, "-o") == 0)
@@ -146,20 +221,20 @@ InstrumentFrontend::process_cmdline()
save_if_srcfile(arg);
}
- *m_log << "Command line is '" << cmd_line.str() << "'" << std::endl;
+ m_log << "Command line is '" << cmd_line.str() << "'" << std::endl;
if_link_add_runtime(object_arg, compile_arg);
if (m_source_files.size() != 0)
return;
- *m_log << "No source files found on command line." << std::endl;
+ m_log << "No source files found on command line." << std::endl;
if (m_is_citruninst)
exit(0);
exec_compiler();
}
-int
+void
InstrumentFrontend::instrument()
{
//
@@ -173,11 +248,11 @@ InstrumentFrontend::instrument()
clang_argv.push_back("--");
clang_argv.insert(clang_argv.end(), m_args.begin(), m_args.end());
#if defined(__OpenBSD__)
- clang_argv.push_back("-I/usr/local/lib/clang/3.8.0/include");
- *m_log << "Added clangtool argument '" << clang_argv.back() << "'.\n";
+ clang_argv.push_back("-I/usr/local/lib/clang/3.9.0/include");
+ m_log << "Added clangtool argument '" << clang_argv.back() << "'" << std::endl;
#elif defined(__APPLE__)
clang_argv.push_back("-I/opt/local/libexec/llvm-3.8/lib/clang/3.8.1/include");
- *m_log << "Added clangtool argument '" << clang_argv.back() << "'" << std::endl;
+ m_log << "Added clangtool argument '" << clang_argv.back() << "'" << std::endl;
#endif
int clang_argc = clang_argv.size();
@@ -186,24 +261,36 @@ InstrumentFrontend::instrument()
clang::tooling::ClangTool
Tool(op.getCompilations(), op.getSourcePathList());
- clang::DiagnosticOptions diags;
- clang::TextDiagnosticPrinter *log;
-
- //log = new clang::TextDiagnosticPrinter(m_log, &diags, false);
- // log->setPrefix(std::to_string(m_log->m_pid));
- //Tool.setDiagnosticConsumer(log);
+ clang::TextDiagnosticBuffer diag_buffer;
+ Tool.setDiagnosticConsumer(&diag_buffer);
std::unique_ptr<InstrumentActionFactory> f =
llvm::make_unique<InstrumentActionFactory>(m_log, m_is_citruninst, m_source_files);
- return Tool.run(f.get());
+ int ret = Tool.run(f.get());
+
+ m_log << "Rewriting " << (ret ? "failed." : "successful.") << std::endl;
+
+ std::chrono::high_resolution_clock::time_point now =
+ std::chrono::high_resolution_clock::now();
+ m_log << std::chrono::duration_cast<std::chrono::milliseconds>(now - m_start_time).count()
+ << " Milliseconds spent rewriting source." << std::endl;
+
+ if (m_is_citruninst)
+ exit(ret);
+ if (ret) {
+ // Rewriting failed. Original source files may be in an
+ // inconsistent state.
+ restore_original_src();
+ exec_compiler();
+ }
}
void
InstrumentFrontend::restore_original_src()
{
for (auto &tmp_file : m_temp_file_map) {
- *m_log << "Restored '" << tmp_file.first << "'" << std::endl;
+ m_log << "Restored '" << tmp_file.first << "'" << std::endl;
copy_file(tmp_file.first, tmp_file.second);
unlink(tmp_file.second.c_str());
@@ -213,11 +300,8 @@ InstrumentFrontend::restore_original_src()
void
InstrumentFrontend::exec_compiler()
{
- // XXX: Need to destroy log here.
- // m_log->m_outfile.flush();
-
if (m_is_citruninst) {
- *m_log << "Running as citrun-inst, not re-exec()'ing" << std::endl;
+ m_log << "Running as citrun-inst, not re-exec()'ing" << std::endl;
exit(0);
}
@@ -229,9 +313,6 @@ InstrumentFrontend::exec_compiler()
int
InstrumentFrontend::fork_compiler()
{
- // Otherwise we'll get two copies of buffers after fork().
- // m_log->m_outfile.flush();
-
pid_t child_pid;
if ((child_pid = fork()) < 0)
err(1, "fork");
@@ -240,7 +321,7 @@ InstrumentFrontend::fork_compiler()
// In child.
exec_compiler();
- *m_log << "Forked '" << m_args[0] << "' "
+ m_log << "Forked '" << m_args[0] << "' "
<< "pid is '" << child_pid << "'" << std::endl;
int status;
@@ -252,6 +333,9 @@ InstrumentFrontend::fork_compiler()
if (WIFEXITED(status))
exit = WEXITSTATUS(status);
- *m_log << "'" << child_pid << "' exited " << exit << "." << std::endl;
+ m_log << "'" << child_pid << "' exited " << exit << std::endl;
+
+ m_log << "Rewritten source compile "
+ << (exit ? "failed." : "successful.") << std::endl;
return exit;
}
diff --git a/src/inst_frontend.h b/src/inst_frontend.h
@@ -1,25 +1,28 @@
#include "inst_action.h" // InstrumentAction
#include "inst_log.h"
+#include <chrono> // std::chrono::high_resolution_clock
#include <string>
class InstrumentFrontend {
public:
- InstrumentFrontend(int, char *argv[], InstrumentLogger *, bool);
+ InstrumentFrontend(int, char *argv[]);
void process_cmdline();
- int instrument();
+ void instrument();
int fork_compiler();
void exec_compiler();
void restore_original_src();
private:
+ void clean_PATH();
void save_if_srcfile(char *);
void if_link_add_runtime(bool, bool);
std::vector<char *> m_args;
- InstrumentLogger *m_log;
+ InstrumentLogger m_log;
bool m_is_citruninst;
+ std::chrono::high_resolution_clock::time_point m_start_time;
std::vector<std::string> m_source_files;
std::map<std::string, std::string> m_temp_file_map;
};
@@ -29,8 +32,7 @@ private:
//
class InstrumentActionFactory : public clang::tooling::FrontendActionFactory {
public:
- InstrumentActionFactory(InstrumentLogger *log, bool citruninst,
- std::vector<std::string> const &src_files) :
+ InstrumentActionFactory(InstrumentLogger &log, bool citruninst, std::vector<std::string> const &src_files) :
m_log(log),
m_is_citruninst(citruninst),
m_source_files(src_files),
@@ -42,7 +44,7 @@ public:
}
private:
- InstrumentLogger *m_log;
+ InstrumentLogger& m_log;
bool m_is_citruninst;
std::vector<std::string> m_source_files;
int m_i;
diff --git a/src/inst_log.h b/src/inst_log.h
@@ -11,16 +11,17 @@ class InstrumentLogger : public std::ostream
{
class LogBuffer : public std::stringbuf
{
- bool m_iscitruninst;
pid_t m_pid;
std::error_code m_ec;
llvm::raw_fd_ostream m_outfile;
public:
- LogBuffer(const bool &is_citruninst) :
- m_iscitruninst(is_citruninst),
+ bool m_iscitruninst;
+
+ LogBuffer() :
m_pid(getpid()),
m_ec(),
- m_outfile("citrun.log", m_ec, llvm::sys::fs::F_Append)
+ m_outfile("citrun.log", m_ec, llvm::sys::fs::F_Append),
+ m_iscitruninst(false)
{
if (m_ec.value())
std::cerr << "Can't open citrun.log: " << m_ec.message();
@@ -41,10 +42,15 @@ class InstrumentLogger : public std::ostream
LogBuffer buffer;
public:
- InstrumentLogger(const bool &is_citruninst) :
+ InstrumentLogger() :
std::ostream(&buffer),
- buffer(is_citruninst)
+ buffer()
+ {
+ }
+
+ void set_citruninst()
{
+ buffer.m_iscitruninst = true;
}
};
diff --git a/src/inst_main.cc b/src/inst_main.cc
@@ -13,126 +13,18 @@
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//
-#include "inst_frontend.h" // InstrumentFrontend
-#include "version.h" // citrun_major, citrun_minor
-
-#include <sys/utsname.h> // uname
-
-#include <chrono> // std::chrono::high_resolution_clock
-#include <cstring> // strcmp
-#include <err.h>
-#include <libgen.h> // basename
-#include <sstream> // stringstream
-
-
-void
-clean_PATH(InstrumentLogger &llog)
-{
- char *path;
- if ((path = std::getenv("PATH")) == NULL)
- errx(1, "Error: PATH is not set.");
-
- llog << "PATH='" << path << "'" << std::endl;
-
- // Filter CITRUN_SHARE out of PATH
- std::stringstream path_ss(path);
- std::ostringstream new_path;
- std::string component;
- bool first_component = 1;
- bool found_citrun_path = 0;
-
- while (std::getline(path_ss, component, ':')) {
- if (component.compare(CITRUN_SHARE) == 0) {
- found_citrun_path = 1;
- continue;
- }
-
- if (first_component == 0)
- new_path << ":";
-
- // It wasn't CITRUN_SHARE, keep it
- new_path << component;
- first_component = 0;
- }
-
- if (!found_citrun_path)
- errx(1, "Error: CITRUN_SHARE not in PATH.");
-
- if (setenv("PATH", new_path.str().c_str(), 1))
- err(1, "setenv");
-}
-void
-print_toolinfo(InstrumentLogger &llog)
-{
- struct utsname utsname;
-
- llog << "citrun-inst " << citrun_major << "." << citrun_minor << " ";
- if (uname(&utsname) == -1)
- llog << "(Unknown OS) ";
- else {
- llog << "(" << utsname.sysname << "-"
- << utsname.release << " "
- << utsname.machine << ") ";
- }
- llog << "'" << CITRUN_SHARE << "'" << std::endl;
-}
+#include "inst_frontend.h" // InstrumentFrontend
int
main(int argc, char *argv[])
{
- std::chrono::high_resolution_clock::time_point m_start_time =
- std::chrono::high_resolution_clock::now();
-
- char *base_name;
- if ((base_name = basename(argv[0])) == NULL)
- err(1, "basename");
-
- bool is_citruninst = false;
- if (std::strcmp(base_name, "citrun-inst") == 0)
- is_citruninst = true;
-
- InstrumentLogger llog(is_citruninst);
- print_toolinfo(llog);
-
- if (is_citruninst) {
- llog << ">> Welcome to C It Run! Have a nice day." << std::endl;
- } else {
- // There's extra work to do if we're not running as citrun-inst.
- llog << "Tool called as '" << argv[0] << "'";
- if (std::strcmp(base_name, argv[0]) != 0) {
- llog << ", changing to '" << base_name << "'";
- argv[0] = base_name;
- }
- llog << std::endl;
-
- setprogname("citrun-inst");
- clean_PATH(llog);
- }
-
- InstrumentFrontend main(argc, argv, &llog, is_citruninst);
+ InstrumentFrontend main(argc, argv);
main.process_cmdline();
- int ret = main.instrument();
- llog << "Rewriting " << (ret ? "failed." : "successful.") << std::endl;
-
- std::chrono::high_resolution_clock::time_point now =
- std::chrono::high_resolution_clock::now();
- llog << std::chrono::duration_cast<std::chrono::milliseconds>(now - m_start_time).count()
- << " Milliseconds spent rewriting source." << std::endl;
-
- if (is_citruninst)
- return ret;
- if (ret) {
- // Rewriting failed. Original source files may be in an
- // inconsistent state.
- main.restore_original_src();
- main.exec_compiler();
- }
+ main.instrument();
- ret = main.fork_compiler();
- llog << "Rewritten source compile "
- << (ret ? "failed." : "successful.") << std::endl;
+ int ret = main.fork_compiler();
main.restore_original_src();
if (ret)
diff --git a/t/inst_fail.sh b/t/inst_fail.sh
@@ -17,7 +17,6 @@ ok "is citrun-wrap exit code 1" test $? -eq 1
cat <<EOF > check.good
Summary:
1 Source files used as input
- 1 Rewrite parse errors
1 Rewrite failures
Totals:
diff --git a/t/inst_log.sh b/t/inst_log.sh
@@ -57,7 +57,7 @@ Instrumentation of '' finished:
Modified source written successfully.
Rewriting successful.
Forked ''
-'' exited 0.
+'' exited 0
Rewritten source compile successful.
Restored ''
citrun-inst 0.0 () ''