]> granicus.if.org Git - clang/commitdiff
Enables chaining of argument adjusters in clang tools.
authorManuel Klimek <klimek@google.com>
Tue, 4 Jun 2013 14:44:44 +0000 (14:44 +0000)
committerManuel Klimek <klimek@google.com>
Tue, 4 Jun 2013 14:44:44 +0000 (14:44 +0000)
This enables changing clang-check to get extra arguments.

Patch by Pavel Labath.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@183227 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Tooling/Tooling.h
lib/Tooling/Tooling.cpp
unittests/Tooling/ToolingTest.cpp

index 7de0a1fe2a5b86208055143ef4c6562620d1a198..dc8163e553fa044bae0177a09a90b9b67088ddc5 100644 (file)
@@ -175,8 +175,8 @@ class ToolInvocation {
 /// 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.
+/// a frontend action. One could install an additional command line
+/// arguments adjuster by calling the appendArgumentsAdjuster() method.
 class ClangTool {
  public:
   /// \brief Constructs a clang tool to run over a list of files.
@@ -188,7 +188,7 @@ class ClangTool {
   ClangTool(const CompilationDatabase &Compilations,
             ArrayRef<std::string> SourcePaths);
 
-  virtual ~ClangTool() {}
+  virtual ~ClangTool() { clearArgumentsAdjusters(); }
 
   /// \brief Map a virtual file to be used while running the tool.
   ///
@@ -199,8 +199,20 @@ class ClangTool {
   /// \brief Install command line arguments adjuster.
   ///
   /// \param Adjuster Command line arguments adjuster.
+  //
+  /// FIXME: Function is deprecated. Use (clear/append)ArgumentsAdjuster instead.
+  /// Remove it once all callers are gone.
   void setArgumentsAdjuster(ArgumentsAdjuster *Adjuster);
 
+  /// \brief Append a command line arguments adjuster to the adjuster chain.
+  ///
+  /// \param Adjuster An argument adjuster, which will be run on the output of
+  ///        previous argument adjusters.
+  void appendArgumentsAdjuster(ArgumentsAdjuster *Adjuster);
+
+  /// \brief Clear the command line arguments adjuster chain.
+  void clearArgumentsAdjusters();
+
   /// Runs a frontend action over all files specified in the command line.
   ///
   /// \param ActionFactory Factory generating the frontend actions. The function
@@ -221,7 +233,7 @@ class ClangTool {
   // Contains a list of pairs (<file name>, <file content>).
   std::vector< std::pair<StringRef, StringRef> > MappedFileContents;
 
-  OwningPtr<ArgumentsAdjuster> ArgsAdjuster;
+  SmallVector<ArgumentsAdjuster *, 1> ArgsAdjusters;
 };
 
 template <typename T>
index 52855f657f64c2bf8a447591a9c5a0cae3b66d47..cdb9bc71ee2bba0819520ce855ca4f5d62554616 100644 (file)
@@ -237,7 +237,7 @@ void ToolInvocation::addFileMappingsTo(SourceManager &Sources) {
 ClangTool::ClangTool(const CompilationDatabase &Compilations,
                      ArrayRef<std::string> SourcePaths)
     : Files((FileSystemOptions())),
-      ArgsAdjuster(new ClangSyntaxOnlyAdjuster()) {
+      ArgsAdjusters(1, new ClangSyntaxOnlyAdjuster()) {
   for (unsigned I = 0, E = SourcePaths.size(); I != E; ++I) {
     SmallString<1024> File(getAbsolutePath(SourcePaths[I]));
 
@@ -264,7 +264,18 @@ void ClangTool::mapVirtualFile(StringRef FilePath, StringRef Content) {
 }
 
 void ClangTool::setArgumentsAdjuster(ArgumentsAdjuster *Adjuster) {
-  ArgsAdjuster.reset(Adjuster);
+  clearArgumentsAdjusters();
+  appendArgumentsAdjuster(Adjuster);
+}
+
+void ClangTool::appendArgumentsAdjuster(ArgumentsAdjuster *Adjuster) {
+  ArgsAdjusters.push_back(Adjuster);
+}
+
+void ClangTool::clearArgumentsAdjusters() {
+  for (unsigned I = 0, E = ArgsAdjusters.size(); I != E; ++I)
+    delete ArgsAdjusters[I];
+  ArgsAdjusters.clear();
 }
 
 int ClangTool::run(FrontendActionFactory *ActionFactory) {
@@ -292,8 +303,9 @@ int ClangTool::run(FrontendActionFactory *ActionFactory) {
     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 =
-      ArgsAdjuster->Adjust(CompileCommands[I].second.CommandLine);
+    std::vector<std::string> CommandLine = CompileCommands[I].second.CommandLine;
+    for (unsigned I = 0, E = ArgsAdjusters.size(); I != E; ++I)
+      CommandLine = ArgsAdjusters[I]->Adjust(CommandLine);
     assert(!CommandLine.empty());
     CommandLine[0] = MainExecutable;
     // FIXME: We need a callback mechanism for the tool writer to output a
index d96366dcd582cc02d33edeb0b11323a900f7fb83..e435ea92e235c4759e4262895a4b38f3205e4d92 100644 (file)
@@ -193,5 +193,46 @@ TEST(runToolOnCode, TestSkipFunctionBody) {
                              "int skipMeNot() { an_error_here }"));
 }
 
+struct CheckSyntaxOnlyAdjuster: public ArgumentsAdjuster {
+  bool &Found;
+  bool &Ran;
+
+  CheckSyntaxOnlyAdjuster(bool &Found, bool &Ran) : Found(Found), Ran(Ran) { }
+
+  virtual CommandLineArguments
+  Adjust(const CommandLineArguments &Args) LLVM_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>());
+
+  ClangTool Tool(Compilations, std::vector<std::string>(1, "/a.cc"));
+  Tool.mapVirtualFile("/a.cc", "void a() {}");
+
+  bool Found = false;
+  bool Ran = false;
+  Tool.appendArgumentsAdjuster(new CheckSyntaxOnlyAdjuster(Found, Ran));
+  Tool.run(newFrontendActionFactory<SyntaxOnlyAction>());
+  EXPECT_TRUE(Ran);
+  EXPECT_TRUE(Found);
+
+  Ran = Found = false;
+  Tool.clearArgumentsAdjusters();
+  Tool.appendArgumentsAdjuster(new CheckSyntaxOnlyAdjuster(Found, Ran));
+  Tool.appendArgumentsAdjuster(new ClangSyntaxOnlyAdjuster());
+  Tool.run(newFrontendActionFactory<SyntaxOnlyAction>());
+  EXPECT_TRUE(Ran);
+  EXPECT_FALSE(Found);
+}
+
 } // end namespace tooling
 } // end namespace clang