[PATCH] Add the ability to set an output file.

Manuel Klimek klimek at google.com
Fri Nov 15 02:29:49 PST 2013


    - Add a test.

Hi pcc,

http://llvm-reviews.chandlerc.com/D2184

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D2184?vs=5562&id=5565#toc

Files:
  clang-query/Query.cpp
  clang-query/Query.h
  clang-query/QueryParser.cpp
  clang-query/QuerySession.h
  clang-query/tool/ClangQuery.cpp
  test/clang-query/output-file.c

Index: clang-query/Query.cpp
===================================================================
--- clang-query/Query.cpp
+++ clang-query/Query.cpp
@@ -40,7 +40,10 @@
         "  set output (diag|print|dump)  "
         "Set whether to print bindings as diagnostics,\n"
         "                                "
-        "AST pretty prints or AST dumps.\n\n";
+        "AST pretty prints or AST dumps.\n"
+        "  set output-file <file-name>   "
+        "Set an optional output file to write to.\n"
+        "\n";
   return true;
 }
 
Index: clang-query/Query.h
===================================================================
--- clang-query/Query.h
+++ clang-query/Query.h
@@ -30,7 +30,8 @@
   QK_Help,
   QK_Match,
   QK_SetBool,
-  QK_SetOutputKind
+  QK_SetOutputKind,
+  QK_SetString
 };
 
 class QuerySession;
@@ -96,6 +97,10 @@
   static const QueryKind value = QK_SetOutputKind;
 };
 
+template <> struct SetQueryKind<std::string> {
+  static const QueryKind value = QK_SetString;
+};
+
 /// Query for "set VAR VALUE".
 template <typename T> struct SetQuery : Query {
   SetQuery(T QuerySession::*Var, T Value)
Index: clang-query/QueryParser.cpp
===================================================================
--- clang-query/QueryParser.cpp
+++ clang-query/QueryParser.cpp
@@ -57,6 +57,11 @@
   return new SetQuery<bool>(Var, Value);
 }
 
+static QueryRef ParseSetString(std::string QuerySession::*Var,
+                               StringRef ValStr) {
+  return new SetQuery<std::string>(Var, ValStr);
+}
+
 static QueryRef ParseSetOutputKind(StringRef ValStr) {
   unsigned OutKind = StringSwitch<unsigned>(ValStr)
                          .Case("diag", OK_Diag)
@@ -89,7 +94,8 @@
 enum ParsedQueryVariable {
   PQV_Invalid,
   PQV_Output,
-  PQV_BindRoot
+  PQV_BindRoot,
+  PQV_SetOutputFile
 };
 
 QueryRef ParseQuery(StringRef Line) {
@@ -133,6 +139,7 @@
     ParsedQueryVariable Var = StringSwitch<ParsedQueryVariable>(VarStr)
                 .Case("output", PQV_Output)
                 .Case("bind-root", PQV_BindRoot)
+                .Case("output-file", PQV_SetOutputFile)
                 .Default(PQV_Invalid);
     if (Var == PQV_Invalid)
       return new InvalidQuery("unknown variable: '" + VarStr + "'");
@@ -149,6 +156,9 @@
     case PQV_BindRoot:
       Q = ParseSetBool(&QuerySession::BindRoot, ValStr);
       break;
+    case PQV_SetOutputFile:
+      Q = ParseSetString(&QuerySession::OutputFileName, ValStr);
+      break;
     case PQV_Invalid:
       llvm_unreachable("Invalid query kind");
     }
Index: clang-query/QuerySession.h
===================================================================
--- clang-query/QuerySession.h
+++ clang-query/QuerySession.h
@@ -25,9 +25,33 @@
   QuerySession(llvm::ArrayRef<ASTUnit *> ASTs)
       : ASTs(ASTs), OutKind(OK_Diag), BindRoot(true) {}
 
+  bool run(QueryRef Query, llvm::raw_ostream &OS) {
+    if (OutputFileName.empty()) {
+      // If there is no output file, use the output stream directly, so
+      // we get colors if the stream supports it.
+      return Query->run(OS, *this);
+    }
+    std::string O;
+    llvm::raw_string_ostream SS(O);
+    bool Result = Query->run(SS, *this);
+    SS.flush();
+    OS << O;
+    std::string ErrorInfo;
+    llvm::raw_fd_ostream FS(OutputFileName.c_str(), ErrorInfo,
+                            llvm::sys::fs::F_Append);
+    if (!ErrorInfo.empty()) {
+      OS << "\nWarning: Could not open output file \"" << OutputFileName
+         << "\".\n";
+    } else {
+      FS << O;
+    }
+    return Result;
+  }
+
   llvm::ArrayRef<ASTUnit *> ASTs;
   OutputKind OutKind;
   bool BindRoot;
+  std::string OutputFileName;
 };
 
 } // namespace query
Index: clang-query/tool/ClangQuery.cpp
===================================================================
--- clang-query/tool/ClangQuery.cpp
+++ clang-query/tool/ClangQuery.cpp
@@ -104,7 +104,7 @@
                                          E = Commands.end();
          I != E; ++I) {
       QueryRef Q = ParseQuery(I->c_str());
-      if (!Q->run(llvm::outs(), QS))
+      if (!QS.run(Q, llvm::outs()))
         return 1;
     }
   } else if (!CommandFiles.empty()) {
@@ -121,7 +121,7 @@
         std::getline(Input, Line);
 
         QueryRef Q = ParseQuery(Line.c_str());
-        if (!Q->run(llvm::outs(), QS))
+        if (!QS.run(Q, llvm::outs()))
           return 1;
       }
     }
@@ -143,7 +143,7 @@
       history(Hist, &Event, H_ENTER, Line);
 
       QueryRef Q = ParseQuery(Line);
-      Q->run(llvm::outs(), QS);
+      QS.run(Q, llvm::outs());
     }
 
     history_end(Hist);
Index: test/clang-query/output-file.c
===================================================================
--- /dev/null
+++ test/clang-query/output-file.c
@@ -0,0 +1,6 @@
+// RUN: clang-query -c "set output-file %t" -c "match functionDecl()" %s --
+// RUN: FileCheck %s < %t
+// REQUIRES: libedit
+
+// CHECK: output-file.c:6:1: note: "root" binds here
+void foo(void) {}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D2184.2.patch
Type: text/x-patch
Size: 4970 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20131115/0e5c3bc2/attachment.bin>


More information about the cfe-commits mailing list