brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.3 KiB · ba5a06a Raw
169 lines · cpp
1//===--- tools/pp-trace/PPTrace.cpp - Clang preprocessor tracer -----------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements pp-trace, a tool for displaying a textual trace10// of the Clang preprocessor activity.  It's based on a derivation of the11// PPCallbacks class, that once registerd with Clang, receives callback calls12// to its virtual members, and outputs the information passed to the callbacks13// in a high-level YAML format.14//15// The pp-trace tool also serves as the basis for a test of the PPCallbacks16// mechanism.17//18// The pp-trace tool supports the following general command line format:19//20//    pp-trace [options] file... [-- compiler options]21//22// Basically you put the pp-trace options first, then the source file or files,23// and then -- followed by any options you want to pass to the compiler.24//25//===----------------------------------------------------------------------===//26 27#include "PPCallbacksTracker.h"28#include "clang/AST/ASTConsumer.h"29#include "clang/AST/ASTContext.h"30#include "clang/Basic/SourceManager.h"31#include "clang/Frontend/CompilerInstance.h"32#include "clang/Frontend/FrontendAction.h"33#include "clang/Frontend/FrontendActions.h"34#include "clang/Lex/Preprocessor.h"35#include "clang/Options/Options.h"36#include "clang/Tooling/Execution.h"37#include "clang/Tooling/Tooling.h"38#include "llvm/Option/Arg.h"39#include "llvm/Option/ArgList.h"40#include "llvm/Option/OptTable.h"41#include "llvm/Option/Option.h"42#include "llvm/Support/CommandLine.h"43#include "llvm/Support/FileSystem.h"44#include "llvm/Support/GlobPattern.h"45#include "llvm/Support/InitLLVM.h"46#include "llvm/Support/Path.h"47#include "llvm/Support/ToolOutputFile.h"48#include "llvm/Support/WithColor.h"49#include <string>50#include <vector>51 52using namespace llvm;53 54namespace clang {55namespace pp_trace {56 57static cl::OptionCategory Cat("pp-trace options");58 59static cl::opt<std::string> Callbacks(60    "callbacks", cl::init("*"),61    cl::desc("Comma-separated list of globs describing the list of callbacks "62             "to output. Globs are processed in order of appearance. Globs "63             "with the '-' prefix remove callbacks from the set. e.g. "64             "'*,-Macro*'."),65    cl::cat(Cat));66 67static cl::opt<std::string> OutputFileName(68    "output", cl::init("-"),69    cl::desc("Output trace to the given file name or '-' for stdout."),70    cl::cat(Cat));71 72[[noreturn]] static void error(Twine Message) {73  WithColor::error() << Message << '\n';74  exit(1);75}76 77namespace {78 79class PPTraceAction : public ASTFrontendAction {80public:81  PPTraceAction(const FilterType &Filters, raw_ostream &OS)82      : Filters(Filters), OS(OS) {}83 84protected:85  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,86                                                 StringRef InFile) override {87    Preprocessor &PP = CI.getPreprocessor();88    PP.addPPCallbacks(89        std::make_unique<PPCallbacksTracker>(Filters, CallbackCalls, PP));90    return std::make_unique<ASTConsumer>();91  }92 93  void EndSourceFileAction() override {94    OS << "---\n";95    for (const CallbackCall &Callback : CallbackCalls) {96      OS << "- Callback: " << Callback.Name << "\n";97      for (const Argument &Arg : Callback.Arguments)98        OS << "  " << Arg.Name << ": " << Arg.Value << "\n";99    }100    OS << "...\n";101 102    CallbackCalls.clear();103  }104 105private:106  const FilterType &Filters;107  raw_ostream &OS;108  std::vector<CallbackCall> CallbackCalls;109};110 111class PPTraceFrontendActionFactory : public tooling::FrontendActionFactory {112public:113  PPTraceFrontendActionFactory(const FilterType &Filters, raw_ostream &OS)114      : Filters(Filters), OS(OS) {}115 116  std::unique_ptr<FrontendAction> create() override {117    return std::make_unique<PPTraceAction>(Filters, OS);118  }119 120private:121  const FilterType &Filters;122  raw_ostream &OS;123};124} // namespace125} // namespace pp_trace126} // namespace clang127 128int main(int argc, const char **argv) {129  using namespace clang::pp_trace;130  InitLLVM X(argc, argv);131  auto OptionsParser = clang::tooling::CommonOptionsParser::create(132      argc, argv, Cat, llvm::cl::ZeroOrMore);133  if (!OptionsParser)134    error(toString(OptionsParser.takeError()));135  // Parse the IgnoreCallbacks list into strings.136  SmallVector<StringRef, 32> Patterns;137  FilterType Filters;138  StringRef(Callbacks).split(Patterns, ",",139                             /*MaxSplit=*/-1, /*KeepEmpty=*/false);140  for (StringRef Pattern : Patterns) {141    Pattern = Pattern.trim();142    bool Enabled = !Pattern.consume_front("-");143    Expected<GlobPattern> Pat = GlobPattern::create(Pattern);144    if (Pat)145      Filters.emplace_back(std::move(*Pat), Enabled);146    else147      error(toString(Pat.takeError()));148  }149 150  // Create the tool and run the compilation.151  clang::tooling::ClangTool Tool(OptionsParser->getCompilations(),152                                 OptionsParser->getSourcePathList());153 154  std::error_code EC;155  llvm::ToolOutputFile Out(OutputFileName, EC, llvm::sys::fs::OF_TextWithCRLF);156  if (EC)157    error(EC.message());158  PPTraceFrontendActionFactory Factory(Filters, Out.os());159  int HadErrors = Tool.run(&Factory);160 161  // If we had errors, exit early.162  if (HadErrors)163    return HadErrors;164 165  Out.keep();166 167  return 0;168}169