Declare abstract class ArgumentsAdjuster. 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.

Define class ClangSyntaxOnlyAdjuster implements ArgumentsAdjuster interface.
This class converts input command line arguments to the "syntax check only"
variant.

Reviewed by Manuel Klimek.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@156478 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Tooling/ArgumentsAdjusters.h b/include/clang/Tooling/ArgumentsAdjusters.h
new file mode 100644
index 0000000..28d2a38
--- /dev/null
+++ b/include/clang/Tooling/ArgumentsAdjusters.h
@@ -0,0 +1,56 @@
+//===--- ArgumentsAdjusters.h - Command line arguments adjuster -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// 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.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_ARGUMENTSADJUSTERS_H
+#define LLVM_CLANG_TOOLING_ARGUMENTSADJUSTERS_H
+
+#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.
+///
+/// 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 {
+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;
+};
+
+/// \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 {
+  virtual CommandLineArguments Adjust(const CommandLineArguments &Args);
+};
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_ARGUMENTSADJUSTERS_H
+
diff --git a/include/clang/Tooling/Tooling.h b/include/clang/Tooling/Tooling.h
index ff66616..ecf1418 100644
--- a/include/clang/Tooling/Tooling.h
+++ b/include/clang/Tooling/Tooling.h
@@ -35,6 +35,7 @@
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/Driver/Util.h"
+#include "clang/Tooling/ArgumentsAdjusters.h"
 #include "clang/Tooling/CompilationDatabase.h"
 #include <string>
 #include <vector>
@@ -138,6 +139,10 @@
 /// \brief Utility to run a FrontendAction over a set of files.
 ///
 /// This class is written to be usable for command line utilities.
+/// By default the class uses ClangSyntaxOnlyAdjuster to modify
+/// command line arguments before the arguments are used to run
+/// a frontend action. One could install another command line
+/// arguments adjuster by call setArgumentsAdjuster() method.
 class ClangTool {
  public:
   /// \brief Constructs a clang tool to run over a list of files.
@@ -155,6 +160,11 @@
   /// \param Content A null terminated buffer of the file's content.
   void mapVirtualFile(StringRef FilePath, StringRef Content);
 
+  /// \brief Install command line arguments adjuster.
+  ///
+  /// \param Adjuster Command line arguments adjuster.
+  void setArgumentsAdjuster(ArgumentsAdjuster *Adjuster);
+
   /// Runs a frontend action over all files specified in the command line.
   ///
   /// \param ActionFactory Factory generating the frontend actions. The function
@@ -174,6 +184,8 @@
   FileManager Files;
   // Contains a list of pairs (<file name>, <file content>).
   std::vector< std::pair<StringRef, StringRef> > MappedFileContents;
+
+  llvm::OwningPtr<ArgumentsAdjuster> ArgsAdjuster;
 };
 
 template <typename T>
diff --git a/lib/Tooling/ArgumentsAdjusters.cpp b/lib/Tooling/ArgumentsAdjusters.cpp
new file mode 100644
index 0000000..73ad398
--- /dev/null
+++ b/lib/Tooling/ArgumentsAdjusters.cpp
@@ -0,0 +1,31 @@
+//===--- ArgumentsAdjusters.cpp - Command line arguments adjuster ---------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains definitions of classes which implement ArgumentsAdjuster
+// interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Tooling/ArgumentsAdjusters.h"
+
+namespace clang {
+namespace tooling {
+
+/// Add -fsyntax-only option to the commnand line arguments.
+CommandLineArguments
+ClangSyntaxOnlyAdjuster::Adjust(const CommandLineArguments &Args) {
+  CommandLineArguments AdjustedArgs = Args;
+  // FIXME: Remove options that generate output.
+  AdjustedArgs.push_back("-fsyntax-only");
+  return AdjustedArgs;
+}
+
+} // end namespace tooling
+} // end namespace clang
+
diff --git a/lib/Tooling/CMakeLists.txt b/lib/Tooling/CMakeLists.txt
index b84b211..6604551 100644
--- a/lib/Tooling/CMakeLists.txt
+++ b/lib/Tooling/CMakeLists.txt
@@ -4,4 +4,5 @@
 add_clang_library(clangTooling
   CompilationDatabase.cpp
   Tooling.cpp
+  ArgumentsAdjusters.cpp
   )
diff --git a/lib/Tooling/Tooling.cpp b/lib/Tooling/Tooling.cpp
index 9b4d4e2..abd6703 100644
--- a/lib/Tooling/Tooling.cpp
+++ b/lib/Tooling/Tooling.cpp
@@ -12,6 +12,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "clang/Tooling/ArgumentsAdjusters.h"
 #include "clang/Tooling/Tooling.h"
 #include "clang/Tooling/CompilationDatabase.h"
 #include "clang/Driver/Compilation.h"
@@ -253,7 +254,8 @@
 
 ClangTool::ClangTool(const CompilationDatabase &Compilations,
                      ArrayRef<std::string> SourcePaths)
-    : Files((FileSystemOptions())) {
+    : Files((FileSystemOptions())),
+      ArgsAdjuster(new ClangSyntaxOnlyAdjuster()) {
   llvm::SmallString<1024> BaseDirectory;
   if (const char *PWD = ::getenv("PWD"))
     BaseDirectory = PWD;
@@ -285,6 +287,10 @@
   MappedFileContents.push_back(std::make_pair(FilePath, Content));
 }
 
+void ClangTool::setArgumentsAdjuster(ArgumentsAdjuster *Adjuster) {
+  ArgsAdjuster.reset(Adjuster);
+}
+
 int ClangTool::run(FrontendActionFactory *ActionFactory) {
   bool ProcessingFailed = false;
   for (unsigned I = 0; I < CompileCommands.size(); ++I) {
@@ -299,8 +305,8 @@
     if (chdir(CompileCommands[I].second.Directory.c_str()))
       llvm::report_fatal_error("Cannot chdir into \"" +
                                CompileCommands[I].second.Directory + "\n!");
-    std::vector<std::string> &CommandLine =
-      CompileCommands[I].second.CommandLine;
+    std::vector<std::string> CommandLine =
+      ArgsAdjuster->Adjust(CompileCommands[I].second.CommandLine);
     llvm::outs() << "Processing: " << File << ".\n";
     ToolInvocation Invocation(CommandLine, ActionFactory->create(), &Files);
     for (int I = 0, E = MappedFileContents.size(); I != E; ++I) {
diff --git a/test/Tooling/multi-jobs.cpp b/test/Tooling/multi-jobs.cpp
new file mode 100644
index 0000000..e330d18
--- /dev/null
+++ b/test/Tooling/multi-jobs.cpp
@@ -0,0 +1,8 @@
+// RUN: clang-check . "%s" -- -no-integrated-as -c 2>&1 | FileCheck %s
+
+// CHECK: C++ requires
+invalid;
+
+// FIXME: clang-check doesn't like gcc driver on cygming.
+// XFAIL: cygwin,mingw32,win32
+