Make ArgumentsAdjuster an std::function.

Reviewers: klimek

Reviewed By: klimek

Subscribers: klimek, cfe-commits

Differential Revision: http://reviews.llvm.org/D6505

llvm-svn: 223248
This commit is contained in:
Alexander Kornienko 2014-12-03 17:53:02 +00:00
parent 293d414380
commit 74e1c46a50
7 changed files with 116 additions and 129 deletions

View File

@ -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 <functional>
#include <string>
#include <vector>
namespace clang {
namespace tooling {
/// \brief A sequence of command line arguments.
typedef std::vector<std::string> 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<CommandLineArguments(const CommandLineArguments &)>
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

View File

@ -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 (<file name>, <file content>).
std::vector< std::pair<StringRef, StringRef> > MappedFileContents;
SmallVector<std::unique_ptr<ArgumentsAdjuster>, 2> ArgsAdjusters;
ArgumentsAdjuster ArgsAdjuster;
DiagnosticConsumer *DiagConsumer;
};

View File

@ -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;
}
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 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]);
}
// Else, the output is specified as -ofoo. Just do nothing.
}
return AdjustedArgs;
AdjustedArgs.push_back("-fsyntax-only");
return AdjustedArgs;
};
}
CommandLineArguments
InsertArgumentAdjuster::Adjust(const CommandLineArguments &Args) {
CommandLineArguments Return(Args);
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]);
CommandLineArguments::iterator I;
if (Pos == END) {
I = Return.end();
} else {
I = Return.begin();
++I; // To leave the program name in place
}
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;
};
}
Return.insert(I, Extra.begin(), Extra.end());
return Return;
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;
};
}
ArgumentsAdjuster getInsertArgumentAdjuster(const char *Extra,
ArgumentInsertPosition Pos) {
return getInsertArgumentAdjuster(CommandLineArguments(1, Extra), Pos);
}
ArgumentsAdjuster combineAdjusters(ArgumentsAdjuster First,
ArgumentsAdjuster Second) {
return std::bind(Second, std::bind(First, std::placeholders::_1));
}
} // end namespace tooling

View File

@ -60,8 +60,8 @@ public:
std::unique_ptr<CompilationDatabase> Compilations)
: Compilations(std::move(Compilations)) {}
void appendArgumentsAdjuster(std::unique_ptr<ArgumentsAdjuster> Adjuster) {
Adjusters.push_back(std::move(Adjuster));
void appendArgumentsAdjuster(ArgumentsAdjuster Adjuster) {
Adjusters.push_back(Adjuster);
}
std::vector<CompileCommand>
@ -79,13 +79,13 @@ public:
private:
std::unique_ptr<CompilationDatabase> Compilations;
std::vector<std::unique_ptr<ArgumentsAdjuster>> Adjusters;
std::vector<ArgumentsAdjuster> Adjusters;
std::vector<CompileCommand>
adjustCommands(std::vector<CompileCommand> 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<ArgumentsAdjustingCompilations>(
std::move(Compilations));
AdjustingCompilations->appendArgumentsAdjuster(
llvm::make_unique<InsertArgumentAdjuster>(ArgsBefore,
InsertArgumentAdjuster::BEGIN));
getInsertArgumentAdjuster(ArgsBefore, ArgumentInsertPosition::BEGIN));
AdjustingCompilations->appendArgumentsAdjuster(
llvm::make_unique<InsertArgumentAdjuster>(ArgsAfter,
InsertArgumentAdjuster::END));
getInsertArgumentAdjuster(ArgsAfter, ArgumentInsertPosition::END));
Compilations = std::move(AdjustingCompilations);
}

View File

@ -279,8 +279,8 @@ ClangTool::ClangTool(const CompilationDatabase &Compilations,
ArrayRef<std::string> 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<ArgumentsAdjuster>(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<std::string> 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

View File

@ -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<FrontendActionFactory> FrontendFactory;

View File

@ -19,6 +19,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/Config/llvm-config.h"
#include "gtest/gtest.h"
#include <algorithm>
#include <string>
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<std::string>());
@ -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);