summaryrefslogtreecommitdiffstats
path: root/pp-trace/PPTrace.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'pp-trace/PPTrace.cpp')
-rw-r--r--pp-trace/PPTrace.cpp243
1 files changed, 89 insertions, 154 deletions
diff --git a/pp-trace/PPTrace.cpp b/pp-trace/PPTrace.cpp
index 08e0f514..5155a8b2 100644
--- a/pp-trace/PPTrace.cpp
+++ b/pp-trace/PPTrace.cpp
@@ -1,9 +1,8 @@
//===--- tools/pp-trace/PPTrace.cpp - Clang preprocessor tracer -----------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -18,44 +17,22 @@
//
// The pp-trace tool supports the following general command line format:
//
-// pp-trace [pp-trace options] (source file) [compiler options]
+// pp-trace [options] file... [-- compiler options]
//
// Basically you put the pp-trace options first, then the source file or files,
-// and then any options you want to pass to the compiler.
-//
-// These are the pp-trace options:
-//
-// -ignore (callback list) Don't display output for a comma-separated
-// list of callbacks, i.e.:
-// -ignore "FileChanged,InclusionDirective"
-//
-// -output (file) Output trace to the given file in a YAML
-// format, e.g.:
-//
-// ---
-// - Callback: Name
-// Argument1: Value1
-// Argument2: Value2
-// (etc.)
-// ...
-//
-// Future Directions:
-//
-// 1. Add option opposite to "-ignore" that specifys a comma-separated option
-// list of callbacs. Perhaps "-only" or "-exclusive".
+// and then -- followed by any options you want to pass to the compiler.
//
//===----------------------------------------------------------------------===//
#include "PPCallbacksTracker.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
-#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Driver/Options.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Lex/Preprocessor.h"
-#include "clang/Tooling/CompilationDatabase.h"
+#include "clang/Tooling/Execution.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
@@ -63,168 +40,126 @@
#include "llvm/Option/Option.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/GlobPattern.h"
+#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/ToolOutputFile.h"
-#include <algorithm>
-#include <fstream>
-#include <iterator>
+#include "llvm/Support/WithColor.h"
#include <string>
#include <vector>
-using namespace clang;
-using namespace clang::tooling;
using namespace llvm;
-// Options:
+namespace clang {
+namespace pp_trace {
-// Collect the source files.
-static cl::list<std::string> SourcePaths(cl::Positional,
- cl::desc("<source0> [... <sourceN>]"),
- cl::OneOrMore);
+static cl::OptionCategory Cat("pp-trace options");
-// Option to specify a list or one or more callback names to ignore.
-static cl::opt<std::string> IgnoreCallbacks(
- "ignore", cl::init(""),
- cl::desc("Ignore callbacks, i.e. \"Callback1, Callback2...\"."));
+static cl::opt<std::string> Callbacks(
+ "callbacks", cl::init("*"),
+ cl::desc("Comma-separated list of globs describing the list of callbacks "
+ "to output. Globs are processed in order of appearance. Globs "
+ "with the '-' prefix remove callbacks from the set. e.g. "
+ "'*,-Macro*'."),
+ cl::cat(Cat));
-// Option to specify the trace output file name.
static cl::opt<std::string> OutputFileName(
- "output", cl::init(""),
- cl::desc("Output trace to the given file name or '-' for stdout."));
+ "output", cl::init("-"),
+ cl::desc("Output trace to the given file name or '-' for stdout."),
+ cl::cat(Cat));
-// Collect all other arguments, which will be passed to the front end.
-static cl::list<std::string>
- CC1Arguments(cl::ConsumeAfter,
- cl::desc("<arguments to be passed to front end>..."));
-
-// Frontend action stuff:
+LLVM_ATTRIBUTE_NORETURN static void error(Twine Message) {
+ WithColor::error() << Message << '\n';
+ exit(1);
+}
namespace {
-// Consumer is responsible for setting up the callbacks.
-class PPTraceConsumer : public ASTConsumer {
-public:
- PPTraceConsumer(SmallSet<std::string, 4> &Ignore,
- std::vector<CallbackCall> &CallbackCalls, Preprocessor &PP) {
- // PP takes ownership.
- PP.addPPCallbacks(llvm::make_unique<PPCallbacksTracker>(Ignore,
- CallbackCalls, PP));
- }
-};
-class PPTraceAction : public SyntaxOnlyAction {
+class PPTraceAction : public ASTFrontendAction {
public:
- PPTraceAction(SmallSet<std::string, 4> &Ignore,
- std::vector<CallbackCall> &CallbackCalls)
- : Ignore(Ignore), CallbackCalls(CallbackCalls) {}
+ PPTraceAction(const FilterType &Filters, raw_ostream &OS)
+ : Filters(Filters), OS(OS) {}
protected:
- std::unique_ptr<clang::ASTConsumer>
- CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override {
- return llvm::make_unique<PPTraceConsumer>(Ignore, CallbackCalls,
- CI.getPreprocessor());
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override {
+ Preprocessor &PP = CI.getPreprocessor();
+ PP.addPPCallbacks(
+ llvm::make_unique<PPCallbacksTracker>(Filters, CallbackCalls, PP));
+ return llvm::make_unique<ASTConsumer>();
+ }
+
+ void EndSourceFileAction() override {
+ OS << "---\n";
+ for (const CallbackCall &Callback : CallbackCalls) {
+ OS << "- Callback: " << Callback.Name << "\n";
+ for (const Argument &Arg : Callback.Arguments)
+ OS << " " << Arg.Name << ": " << Arg.Value << "\n";
+ }
+ OS << "...\n";
+
+ CallbackCalls.clear();
}
private:
- SmallSet<std::string, 4> &Ignore;
- std::vector<CallbackCall> &CallbackCalls;
+ const FilterType &Filters;
+ raw_ostream &OS;
+ std::vector<CallbackCall> CallbackCalls;
};
-class PPTraceFrontendActionFactory : public FrontendActionFactory {
+class PPTraceFrontendActionFactory : public tooling::FrontendActionFactory {
public:
- PPTraceFrontendActionFactory(SmallSet<std::string, 4> &Ignore,
- std::vector<CallbackCall> &CallbackCalls)
- : Ignore(Ignore), CallbackCalls(CallbackCalls) {}
+ PPTraceFrontendActionFactory(const FilterType &Filters, raw_ostream &OS)
+ : Filters(Filters), OS(OS) {}
- PPTraceAction *create() override {
- return new PPTraceAction(Ignore, CallbackCalls);
- }
+ PPTraceAction *create() override { return new PPTraceAction(Filters, OS); }
private:
- SmallSet<std::string, 4> &Ignore;
- std::vector<CallbackCall> &CallbackCalls;
+ const FilterType &Filters;
+ raw_ostream &OS;
};
} // namespace
-
-// Output the trace given its data structure and a stream.
-static int outputPPTrace(std::vector<CallbackCall> &CallbackCalls,
- llvm::raw_ostream &OS) {
- // Mark start of document.
- OS << "---\n";
-
- for (std::vector<CallbackCall>::const_iterator I = CallbackCalls.begin(),
- E = CallbackCalls.end();
- I != E; ++I) {
- const CallbackCall &Callback = *I;
- OS << "- Callback: " << Callback.Name << "\n";
-
- for (auto AI = Callback.Arguments.begin(), AE = Callback.Arguments.end();
- AI != AE; ++AI) {
- const Argument &Arg = *AI;
- OS << " " << Arg.Name << ": " << Arg.Value << "\n";
- }
- }
-
- // Mark end of document.
- OS << "...\n";
-
- return 0;
-}
-
-// Program entry point.
-int main(int Argc, const char **Argv) {
-
- // Parse command line.
- cl::ParseCommandLineOptions(Argc, Argv, "pp-trace.\n");
-
+} // namespace pp_trace
+} // namespace clang
+
+int main(int argc, const char **argv) {
+ using namespace clang::pp_trace;
+ InitLLVM X(argc, argv);
+ auto OptionsParser = clang::tooling::CommonOptionsParser::create(
+ argc, argv, Cat, llvm::cl::ZeroOrMore);
+ if (!OptionsParser)
+ error(toString(OptionsParser.takeError()));
// Parse the IgnoreCallbacks list into strings.
- SmallVector<StringRef, 32> IgnoreCallbacksStrings;
- StringRef(IgnoreCallbacks).split(IgnoreCallbacksStrings, ",",
- /*MaxSplit=*/ -1, /*KeepEmpty=*/false);
- SmallSet<std::string, 4> Ignore;
- for (SmallVector<StringRef, 32>::iterator I = IgnoreCallbacksStrings.begin(),
- E = IgnoreCallbacksStrings.end();
- I != E; ++I)
- Ignore.insert(*I);
-
- // Create the compilation database.
- SmallString<256> PathBuf;
- sys::fs::current_path(PathBuf);
- std::unique_ptr<CompilationDatabase> Compilations;
- Compilations.reset(
- new FixedCompilationDatabase(Twine(PathBuf), CC1Arguments));
-
- // Store the callback trace information here.
- std::vector<CallbackCall> CallbackCalls;
+ SmallVector<StringRef, 32> Patterns;
+ FilterType Filters;
+ StringRef(Callbacks).split(Patterns, ",",
+ /*MaxSplit=*/-1, /*KeepEmpty=*/false);
+ for (StringRef Pattern : Patterns) {
+ Pattern = Pattern.trim();
+ bool Enabled = !Pattern.consume_front("-");
+ Expected<GlobPattern> Pat = GlobPattern::create(Pattern);
+ if (Pat)
+ Filters.emplace_back(std::move(*Pat), Enabled);
+ else
+ error(toString(Pat.takeError()));
+ }
// Create the tool and run the compilation.
- ClangTool Tool(*Compilations, SourcePaths);
- PPTraceFrontendActionFactory Factory(Ignore, CallbackCalls);
+ clang::tooling::ClangTool Tool(OptionsParser->getCompilations(),
+ OptionsParser->getSourcePathList());
+
+ std::error_code EC;
+ llvm::ToolOutputFile Out(OutputFileName, EC, llvm::sys::fs::F_Text);
+ if (EC)
+ error(EC.message());
+ PPTraceFrontendActionFactory Factory(Filters, Out.os());
int HadErrors = Tool.run(&Factory);
// If we had errors, exit early.
if (HadErrors)
return HadErrors;
- // Do the output.
- if (!OutputFileName.size()) {
- HadErrors = outputPPTrace(CallbackCalls, llvm::outs());
- } else {
- // Set up output file.
- std::error_code EC;
- llvm::ToolOutputFile Out(OutputFileName, EC, llvm::sys::fs::F_Text);
- if (EC) {
- llvm::errs() << "pp-trace: error creating " << OutputFileName << ":"
- << EC.message() << "\n";
- return 1;
- }
-
- HadErrors = outputPPTrace(CallbackCalls, Out.os());
-
- // Tell ToolOutputFile that we want to keep the file.
- if (HadErrors == 0)
- Out.keep();
- }
+ Out.keep();
- return HadErrors;
+ return 0;
}