Index: include/clang/Tooling/ArgumentsAdjusters.h =================================================================== --- include/clang/Tooling/ArgumentsAdjusters.h +++ 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. -/// -/// 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() {} -}; - -/// \brief Syntax check only command line adjuster. +/// \brief A prototype of a 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; -}; +/// 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 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; -}; - -class InsertArgumentAdjuster : public ArgumentsAdjuster { -public: - enum Position { BEGIN, END }; - - InsertArgumentAdjuster(const CommandLineArguments &Extra, Position Pos) - : Extra(Extra), Pos(Pos) {} - - InsertArgumentAdjuster(const char *Extra, Position Pos) - : Extra(1, std::string(Extra)), Pos(Pos) {} - - CommandLineArguments Adjust(const CommandLineArguments &Args) override; - -private: - const CommandLineArguments Extra; - const Position Pos; -}; -} // end namespace tooling -} // end namespace clang +ArgumentsAdjuster getClangStripOutputAdjuster(); + +enum class ArgumentInsertPosition { BEGIN, END }; + +/// \brief Gets an argument adjuster which inserts \p Extra arguments in the +/// specified position. +ArgumentsAdjuster getInsertArgumentAdjuster(const CommandLineArguments &Extra, + ArgumentInsertPosition Pos); + +/// \brief Gets an argument adjuster which inserts an \p Extra argument in the +/// specified position. +ArgumentsAdjuster getInsertArgumentAdjuster(const char *Extra, + ArgumentInsertPosition Pos); + +/// \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); + +} // namespace tooling +} // namespace clang #endif // LLVM_CLANG_TOOLING_ARGUMENTSADJUSTERS_H Index: include/clang/Tooling/Tooling.h =================================================================== --- include/clang/Tooling/Tooling.h +++ include/clang/Tooling/Tooling.h @@ -274,7 +274,7 @@ /// /// \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 @@ // Contains a list of pairs (, ). std::vector< std::pair > MappedFileContents; - SmallVector, 2> ArgsAdjusters; + ArgumentsAdjuster ArgsAdjuster; DiagnosticConsumer *DiagConsumer; }; Index: lib/Tooling/ArgumentsAdjusters.cpp =================================================================== --- lib/Tooling/ArgumentsAdjusters.cpp +++ lib/Tooling/ArgumentsAdjusters.cpp @@ -19,55 +19,66 @@ namespace clang { namespace tooling { -void ArgumentsAdjuster::anchor() { +/// Add -fsyntax-only option to the commnand line arguments. +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; + }; } -/// 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 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; + } + // Else, the output is specified as -ofoo. Just do nothing. + } + 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]); - - if(Arg == "-o") { - // Output is specified as -o foo. Skip the next argument also. - ++i; +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 } - // Else, the output is specified as -ofoo. Just do nothing. - } - return AdjustedArgs; + + Return.insert(I, Extra.begin(), Extra.end()); + return Return; + }; } -CommandLineArguments -InsertArgumentAdjuster::Adjust(const CommandLineArguments &Args) { - CommandLineArguments Return(Args); - - 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 Index: lib/Tooling/CommonOptionsParser.cpp =================================================================== --- lib/Tooling/CommonOptionsParser.cpp +++ lib/Tooling/CommonOptionsParser.cpp @@ -60,8 +60,8 @@ 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 @@ 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 @@ 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); } Index: lib/Tooling/Tooling.cpp =================================================================== --- lib/Tooling/Tooling.cpp +++ lib/Tooling/Tooling.cpp @@ -279,8 +279,8 @@ 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 @@ 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 @@ 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 Index: tools/clang-check/ClangCheck.cpp =================================================================== --- tools/clang-check/ClangCheck.cpp +++ tools/clang-check/ClangCheck.cpp @@ -155,12 +155,12 @@ // 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; Index: unittests/Tooling/ToolingTest.cpp =================================================================== --- unittests/Tooling/ToolingTest.cpp +++ 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 @@ 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 @@ 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);