From 74e1c46a50d9a5f240c6dc7b0a5a33642d0a30a8 Mon Sep 17 00:00:00 2001 From: Alexander Kornienko Date: Wed, 3 Dec 2014 17:53:02 +0000 Subject: [PATCH] Make ArgumentsAdjuster an std::function. Reviewers: klimek Reviewed By: klimek Subscribers: klimek, cfe-commits Differential Revision: http://reviews.llvm.org/D6505 llvm-svn: 223248 --- clang/include/clang/Tooling/ArgumentsAdjusters.h | 74 ++++++++----------- clang/include/clang/Tooling/Tooling.h | 4 +- clang/lib/Tooling/ArgumentsAdjusters.cpp | 91 +++++++++++++----------- clang/lib/Tooling/CommonOptionsParser.cpp | 14 ++-- clang/lib/Tooling/Tooling.cpp | 17 +++-- clang/tools/clang-check/ClangCheck.cpp | 6 +- clang/unittests/Tooling/ToolingTest.cpp | 33 +++------ 7 files changed, 113 insertions(+), 126 deletions(-) diff --git a/clang/include/clang/Tooling/ArgumentsAdjusters.h b/clang/include/clang/Tooling/ArgumentsAdjusters.h index 30bca9b..e0292d8 100644 --- a/clang/include/clang/Tooling/ArgumentsAdjusters.h +++ b/clang/include/clang/Tooling/ArgumentsAdjusters.h @@ -7,74 +7,60 @@ // //===----------------------------------------------------------------------===// // -// This file declares base abstract class ArgumentsAdjuster and its descendants. -// These classes are intended to modify command line arguments obtained from -// a compilation database before they are used to run a frontend action. +// This file declares typedef ArgumentsAdjuster and functions to create several +// useful argument adjusters. +// ArgumentsAdjusters modify command line arguments obtained from a compilation +// database before they are used to run a frontend action. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_TOOLING_ARGUMENTSADJUSTERS_H #define LLVM_CLANG_TOOLING_ARGUMENTSADJUSTERS_H +#include #include #include namespace clang { - namespace tooling { /// \brief A sequence of command line arguments. typedef std::vector CommandLineArguments; -/// \brief Abstract interface for a command line adjusters. +/// \brief A prototype of a command line adjuster. /// -/// This abstract interface describes a command line argument adjuster, -/// which is responsible for command line arguments modification before -/// the arguments are used to run a frontend action. -class ArgumentsAdjuster { - virtual void anchor(); -public: - /// \brief Returns adjusted command line arguments. - /// - /// \param Args Input sequence of command line arguments. - /// - /// \returns Modified sequence of command line arguments. - virtual CommandLineArguments Adjust(const CommandLineArguments &Args) = 0; - virtual ~ArgumentsAdjuster() {} -}; +/// Command line argument adjuster is responsible for command line arguments +/// modification before the arguments are used to run a frontend action. +typedef std::function + ArgumentsAdjuster; -/// \brief Syntax check only command line adjuster. -/// -/// This class implements ArgumentsAdjuster interface and converts input -/// command line arguments to the "syntax check only" variant. -class ClangSyntaxOnlyAdjuster : public ArgumentsAdjuster { - CommandLineArguments Adjust(const CommandLineArguments &Args) override; -}; +/// \brief Gets an argument adjuster that converts input command line arguments +/// to the "syntax check only" variant. +ArgumentsAdjuster getClangSyntaxOnlyAdjuster(); -/// \brief An argument adjuster which removes output-related command line +/// \brief Gets an argument adjuster which removes output-related command line /// arguments. -class ClangStripOutputAdjuster : public ArgumentsAdjuster { - CommandLineArguments Adjust(const CommandLineArguments &Args) override; -}; +ArgumentsAdjuster getClangStripOutputAdjuster(); -class InsertArgumentAdjuster : public ArgumentsAdjuster { -public: - enum Position { BEGIN, END }; +enum class ArgumentInsertPosition { BEGIN, END }; - InsertArgumentAdjuster(const CommandLineArguments &Extra, Position Pos) - : Extra(Extra), Pos(Pos) {} +/// \brief Gets an argument adjuster which inserts \p Extra arguments in the +/// specified position. +ArgumentsAdjuster getInsertArgumentAdjuster(const CommandLineArguments &Extra, + ArgumentInsertPosition Pos); - InsertArgumentAdjuster(const char *Extra, Position Pos) - : Extra(1, std::string(Extra)), Pos(Pos) {} +/// \brief Gets an argument adjuster which inserts an \p Extra argument in the +/// specified position. +ArgumentsAdjuster getInsertArgumentAdjuster(const char *Extra, + ArgumentInsertPosition Pos); - CommandLineArguments Adjust(const CommandLineArguments &Args) override; +/// \brief Gets an argument adjuster which adjusts the arguments in sequence +/// with the \p First adjuster and then with the \p Second one. +ArgumentsAdjuster combineAdjusters(ArgumentsAdjuster First, + ArgumentsAdjuster Second); -private: - const CommandLineArguments Extra; - const Position Pos; -}; -} // end namespace tooling -} // end namespace clang +} // namespace tooling +} // namespace clang #endif // LLVM_CLANG_TOOLING_ARGUMENTSADJUSTERS_H diff --git a/clang/include/clang/Tooling/Tooling.h b/clang/include/clang/Tooling/Tooling.h index 55152ff..393cc1d 100644 --- a/clang/include/clang/Tooling/Tooling.h +++ b/clang/include/clang/Tooling/Tooling.h @@ -274,7 +274,7 @@ class ClangTool { /// /// \param Adjuster An argument adjuster, which will be run on the output of /// previous argument adjusters. - void appendArgumentsAdjuster(ArgumentsAdjuster *Adjuster); + void appendArgumentsAdjuster(ArgumentsAdjuster Adjuster); /// \brief Clear the command line arguments adjuster chain. void clearArgumentsAdjusters(); @@ -301,7 +301,7 @@ class ClangTool { // Contains a list of pairs (, ). std::vector< std::pair > MappedFileContents; - SmallVector, 2> ArgsAdjusters; + ArgumentsAdjuster ArgsAdjuster; DiagnosticConsumer *DiagConsumer; }; diff --git a/clang/lib/Tooling/ArgumentsAdjusters.cpp b/clang/lib/Tooling/ArgumentsAdjusters.cpp index 36ac34e..5a67db0 100644 --- a/clang/lib/Tooling/ArgumentsAdjusters.cpp +++ b/clang/lib/Tooling/ArgumentsAdjusters.cpp @@ -19,55 +19,66 @@ namespace clang { namespace tooling { -void ArgumentsAdjuster::anchor() { -} - /// Add -fsyntax-only option to the commnand line arguments. -CommandLineArguments -ClangSyntaxOnlyAdjuster::Adjust(const CommandLineArguments &Args) { - CommandLineArguments AdjustedArgs; - for (size_t i = 0, e = Args.size(); i != e; ++i) { - StringRef Arg = Args[i]; - // FIXME: Remove options that generate output. - if (!Arg.startswith("-fcolor-diagnostics") && - !Arg.startswith("-fdiagnostics-color")) - AdjustedArgs.push_back(Args[i]); - } - AdjustedArgs.push_back("-fsyntax-only"); - return AdjustedArgs; +ArgumentsAdjuster getClangSyntaxOnlyAdjuster() { + return [](const CommandLineArguments &Args) { + CommandLineArguments AdjustedArgs; + for (size_t i = 0, e = Args.size(); i != e; ++i) { + StringRef Arg = Args[i]; + // FIXME: Remove options that generate output. + if (!Arg.startswith("-fcolor-diagnostics") && + !Arg.startswith("-fdiagnostics-color")) + AdjustedArgs.push_back(Args[i]); + } + AdjustedArgs.push_back("-fsyntax-only"); + return AdjustedArgs; + }; } -CommandLineArguments -ClangStripOutputAdjuster::Adjust(const CommandLineArguments &Args) { - CommandLineArguments AdjustedArgs; - for (size_t i = 0, e = Args.size(); i < e; ++i) { - StringRef Arg = Args[i]; - if(!Arg.startswith("-o")) - AdjustedArgs.push_back(Args[i]); +ArgumentsAdjuster getClangStripOutputAdjuster() { + return [](const CommandLineArguments &Args) { + CommandLineArguments AdjustedArgs; + for (size_t i = 0, e = Args.size(); i < e; ++i) { + StringRef Arg = Args[i]; + if (!Arg.startswith("-o")) + AdjustedArgs.push_back(Args[i]); - if(Arg == "-o") { - // Output is specified as -o foo. Skip the next argument also. - ++i; + if (Arg == "-o") { + // Output is specified as -o foo. Skip the next argument also. + ++i; + } + // Else, the output is specified as -ofoo. Just do nothing. } - // Else, the output is specified as -ofoo. Just do nothing. - } - return AdjustedArgs; + return AdjustedArgs; + }; } -CommandLineArguments -InsertArgumentAdjuster::Adjust(const CommandLineArguments &Args) { - CommandLineArguments Return(Args); +ArgumentsAdjuster getInsertArgumentAdjuster(const CommandLineArguments &Extra, + ArgumentInsertPosition Pos) { + return [Extra, Pos](const CommandLineArguments &Args) { + CommandLineArguments Return(Args); + + CommandLineArguments::iterator I; + if (Pos == ArgumentInsertPosition::END) { + I = Return.end(); + } else { + I = Return.begin(); + ++I; // To leave the program name in place + } + + Return.insert(I, Extra.begin(), Extra.end()); + return Return; + }; +} - CommandLineArguments::iterator I; - if (Pos == END) { - I = Return.end(); - } else { - I = Return.begin(); - ++I; // To leave the program name in place - } +ArgumentsAdjuster getInsertArgumentAdjuster(const char *Extra, + ArgumentInsertPosition Pos) { + return getInsertArgumentAdjuster(CommandLineArguments(1, Extra), Pos); +} - Return.insert(I, Extra.begin(), Extra.end()); - return Return; +ArgumentsAdjuster combineAdjusters(ArgumentsAdjuster First, + ArgumentsAdjuster Second) { + return std::bind(Second, std::bind(First, std::placeholders::_1)); } } // end namespace tooling diff --git a/clang/lib/Tooling/CommonOptionsParser.cpp b/clang/lib/Tooling/CommonOptionsParser.cpp index f16a6be..91c74a4 100644 --- a/clang/lib/Tooling/CommonOptionsParser.cpp +++ b/clang/lib/Tooling/CommonOptionsParser.cpp @@ -60,8 +60,8 @@ public: std::unique_ptr Compilations) : Compilations(std::move(Compilations)) {} - void appendArgumentsAdjuster(std::unique_ptr Adjuster) { - Adjusters.push_back(std::move(Adjuster)); + void appendArgumentsAdjuster(ArgumentsAdjuster Adjuster) { + Adjusters.push_back(Adjuster); } std::vector @@ -79,13 +79,13 @@ public: private: std::unique_ptr Compilations; - std::vector> Adjusters; + std::vector Adjusters; std::vector adjustCommands(std::vector Commands) const { for (CompileCommand &Command : Commands) for (const auto &Adjuster : Adjusters) - Command.CommandLine = Adjuster->Adjust(Command.CommandLine); + Command.CommandLine = Adjuster(Command.CommandLine); return Commands; } }; @@ -142,10 +142,8 @@ CommonOptionsParser::CommonOptionsParser(int &argc, const char **argv, llvm::make_unique( std::move(Compilations)); AdjustingCompilations->appendArgumentsAdjuster( - llvm::make_unique(ArgsBefore, - InsertArgumentAdjuster::BEGIN)); + getInsertArgumentAdjuster(ArgsBefore, ArgumentInsertPosition::BEGIN)); AdjustingCompilations->appendArgumentsAdjuster( - llvm::make_unique(ArgsAfter, - InsertArgumentAdjuster::END)); + getInsertArgumentAdjuster(ArgsAfter, ArgumentInsertPosition::END)); Compilations = std::move(AdjustingCompilations); } diff --git a/clang/lib/Tooling/Tooling.cpp b/clang/lib/Tooling/Tooling.cpp index 95ef03e..60371fb 100644 --- a/clang/lib/Tooling/Tooling.cpp +++ b/clang/lib/Tooling/Tooling.cpp @@ -279,8 +279,8 @@ ClangTool::ClangTool(const CompilationDatabase &Compilations, ArrayRef SourcePaths) : Compilations(Compilations), SourcePaths(SourcePaths), Files(new FileManager(FileSystemOptions())), DiagConsumer(nullptr) { - appendArgumentsAdjuster(new ClangStripOutputAdjuster()); - appendArgumentsAdjuster(new ClangSyntaxOnlyAdjuster()); + appendArgumentsAdjuster(getClangStripOutputAdjuster()); + appendArgumentsAdjuster(getClangSyntaxOnlyAdjuster()); } ClangTool::~ClangTool() {} @@ -289,12 +289,15 @@ void ClangTool::mapVirtualFile(StringRef FilePath, StringRef Content) { MappedFileContents.push_back(std::make_pair(FilePath, Content)); } -void ClangTool::appendArgumentsAdjuster(ArgumentsAdjuster *Adjuster) { - ArgsAdjusters.push_back(std::unique_ptr(Adjuster)); +void ClangTool::appendArgumentsAdjuster(ArgumentsAdjuster Adjuster) { + if (ArgsAdjuster) + ArgsAdjuster = combineAdjusters(ArgsAdjuster, Adjuster); + else + ArgsAdjuster = Adjuster; } void ClangTool::clearArgumentsAdjusters() { - ArgsAdjusters.clear(); + ArgsAdjuster = nullptr; } int ClangTool::run(ToolAction *Action) { @@ -347,8 +350,8 @@ int ClangTool::run(ToolAction *Action) { llvm::report_fatal_error("Cannot chdir into \"" + Twine(CompileCommand.Directory) + "\n!"); std::vector CommandLine = CompileCommand.CommandLine; - for (const auto &Adjuster : ArgsAdjusters) - CommandLine = Adjuster->Adjust(CommandLine); + if (ArgsAdjuster) + CommandLine = ArgsAdjuster(CommandLine); assert(!CommandLine.empty()); CommandLine[0] = MainExecutable; // FIXME: We need a callback mechanism for the tool writer to output a diff --git a/clang/tools/clang-check/ClangCheck.cpp b/clang/tools/clang-check/ClangCheck.cpp index d92a8d5..50ba17b 100644 --- a/clang/tools/clang-check/ClangCheck.cpp +++ b/clang/tools/clang-check/ClangCheck.cpp @@ -155,12 +155,12 @@ int main(int argc, const char **argv) { // Clear adjusters because -fsyntax-only is inserted by the default chain. Tool.clearArgumentsAdjusters(); - Tool.appendArgumentsAdjuster(new ClangStripOutputAdjuster()); + Tool.appendArgumentsAdjuster(getClangStripOutputAdjuster()); // Running the analyzer requires --analyze. Other modes can work with the // -fsyntax-only option. - Tool.appendArgumentsAdjuster(new InsertArgumentAdjuster( - Analyze ? "--analyze" : "-fsyntax-only", InsertArgumentAdjuster::BEGIN)); + Tool.appendArgumentsAdjuster(getInsertArgumentAdjuster( + Analyze ? "--analyze" : "-fsyntax-only", ArgumentInsertPosition::BEGIN)); ClangCheckActionFactory CheckFactory; std::unique_ptr FrontendFactory; diff --git a/clang/unittests/Tooling/ToolingTest.cpp b/clang/unittests/Tooling/ToolingTest.cpp index 98b7008..5a93e38 100644 --- a/clang/unittests/Tooling/ToolingTest.cpp +++ b/clang/unittests/Tooling/ToolingTest.cpp @@ -19,6 +19,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/Config/llvm-config.h" #include "gtest/gtest.h" +#include #include namespace clang { @@ -260,25 +261,6 @@ TEST(runToolOnCodeWithArgs, TestNoDepFile) { EXPECT_FALSE(llvm::sys::fs::remove(DepFilePath.str())); } -struct CheckSyntaxOnlyAdjuster: public ArgumentsAdjuster { - bool &Found; - bool &Ran; - - CheckSyntaxOnlyAdjuster(bool &Found, bool &Ran) : Found(Found), Ran(Ran) { } - - virtual CommandLineArguments - Adjust(const CommandLineArguments &Args) override { - Ran = true; - for (unsigned I = 0, E = Args.size(); I != E; ++I) { - if (Args[I] == "-fsyntax-only") { - Found = true; - break; - } - } - return Args; - } -}; - TEST(ClangToolTest, ArgumentAdjusters) { FixedCompilationDatabase Compilations("/", std::vector()); @@ -290,15 +272,22 @@ TEST(ClangToolTest, ArgumentAdjusters) { bool Found = false; bool Ran = false; - Tool.appendArgumentsAdjuster(new CheckSyntaxOnlyAdjuster(Found, Ran)); + ArgumentsAdjuster CheckSyntaxOnlyAdjuster = + [&Found, &Ran](const CommandLineArguments &Args) { + Ran = true; + if (std::find(Args.begin(), Args.end(), "-fsyntax-only") != Args.end()) + Found = true; + return Args; + }; + Tool.appendArgumentsAdjuster(CheckSyntaxOnlyAdjuster); Tool.run(Action.get()); EXPECT_TRUE(Ran); EXPECT_TRUE(Found); Ran = Found = false; Tool.clearArgumentsAdjusters(); - Tool.appendArgumentsAdjuster(new CheckSyntaxOnlyAdjuster(Found, Ran)); - Tool.appendArgumentsAdjuster(new ClangSyntaxOnlyAdjuster()); + Tool.appendArgumentsAdjuster(CheckSyntaxOnlyAdjuster); + Tool.appendArgumentsAdjuster(getClangSyntaxOnlyAdjuster()); Tool.run(Action.get()); EXPECT_TRUE(Ran); EXPECT_FALSE(Found); -- 2.7.4