Add support for warning flag processing.

BUG=5714569

Change-Id: I96567325df605c5eb0f0bf2f2371a1cea9718a5b
diff --git a/RSCCOptions.td b/RSCCOptions.td
index 2dc6b20..903a70e 100644
--- a/RSCCOptions.td
+++ b/RSCCOptions.td
@@ -77,6 +77,9 @@
   MetaVarName<"<value>">, HelpText<"<value> should be 'ar' or 'jc'">;
 def _bitcode_storage : Separate<"-s">, Alias<bitcode_storage>;
 
+def W : Joined<"-W">;
+def w : Flag<"-w">, HelpText<"Suppress all warnings">;
+
 //===----------------------------------------------------------------------===//
 // Dependency Output Options
 //===----------------------------------------------------------------------===//
diff --git a/llvm-rs-cc.cpp b/llvm-rs-cc.cpp
index 176abe3..f9f2a0b 100644
--- a/llvm-rs-cc.cpp
+++ b/llvm-rs-cc.cpp
@@ -29,6 +29,7 @@
 
 #include "clang/Frontend/DiagnosticOptions.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Frontend/Utils.h"
 
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
@@ -43,6 +44,7 @@
 
 #include "slang.h"
 #include "slang_assert.h"
+#include "slang_diagnostic_buffer.h"
 #include "slang_rs.h"
 #include "slang_rs_reflect_utils.h"
 
@@ -173,6 +175,11 @@
       DiagEngine.Report(clang::diag::err_drv_missing_argument)
         << Args->getArgString(MissingArgIndex) << MissingArgCount;
 
+    clang::DiagnosticOptions DiagOpts;
+    DiagOpts.IgnoreWarnings = Args->hasArg(OPT_w);
+    DiagOpts.Warnings = Args->getAllArgValues(OPT_W);
+    clang::ProcessWarningOptions(DiagEngine, DiagOpts);
+
     // Issue errors on unknown arguments.
     for (arg_iterator it = Args->filtered_begin(OPT_UNKNOWN),
         ie = Args->filtered_end(); it != ie; ++it)
@@ -343,6 +350,8 @@
   OS << ".\n";
   return;
 }
+#undef wrap_str
+#undef str
 
 int main(int argc, const char **argv) {
   std::set<std::string> SavedStrings;
@@ -359,24 +368,22 @@
   Argv0 = llvm::sys::path::stem(ArgVector[0]);
 
   // Setup diagnostic engine
-  clang::TextDiagnosticPrinter *DiagClient =
-    new clang::TextDiagnosticPrinter(llvm::errs(), clang::DiagnosticOptions());
-  DiagClient->setPrefix(Argv0);
+  slang::DiagnosticBuffer *DiagClient = new slang::DiagnosticBuffer();
 
   llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagIDs(
     new clang::DiagnosticIDs());
 
   clang::DiagnosticsEngine DiagEngine(DiagIDs, DiagClient, true);
 
-  clang::Diagnostic Diags(&DiagEngine);
-
   slang::Slang::GlobalInitialization();
 
   ParseArguments(ArgVector, Inputs, Opts, DiagEngine);
 
   // Exits when there's any error occurred during parsing the arguments
-  if (DiagEngine.hasErrorOccurred())
+  if (DiagEngine.hasErrorOccurred()) {
+    llvm::errs() << DiagClient->str();
     return 1;
+  }
 
   if (Opts.mShowHelp) {
     llvm::OwningPtr<OptTable> OptTbl(createRSCCOptTable());
@@ -393,6 +400,7 @@
   // No input file
   if (Inputs.empty()) {
     DiagEngine.Report(clang::diag::err_drv_no_input_files);
+    llvm::errs() << DiagClient->str();
     return 1;
   }
 
@@ -402,7 +410,8 @@
 
   llvm::OwningPtr<slang::SlangRS> Compiler(new slang::SlangRS());
 
-  Compiler->init(Opts.mTriple, Opts.mCPU, Opts.mFeatures);
+  Compiler->init(Opts.mTriple, Opts.mCPU, Opts.mFeatures, &DiagEngine,
+                 DiagClient);
 
   for (int i = 0, e = Inputs.size(); i != e; i++) {
     const char *InputFile = Inputs[i];
diff --git a/slang.cpp b/slang.cpp
index 446aaac..bb93f99 100644
--- a/slang.cpp
+++ b/slang.cpp
@@ -171,16 +171,6 @@
   exit(1);
 }
 
-void Slang::createDiagnostic() {
-  mDiagClient = new DiagnosticBuffer();
-
-  mDiagIDs = new clang::DiagnosticIDs();
-  mDiagEngine = new clang::DiagnosticsEngine(mDiagIDs, mDiagClient, true);
-  mDiag.reset(new clang::Diagnostic(mDiagEngine.getPtr()));
-
-  initDiagnostic();
-}
-
 void Slang::createTarget(const std::string &Triple, const std::string &CPU,
                          const std::vector<std::string> &Features) {
   if (!Triple.empty())
@@ -257,7 +247,7 @@
 clang::ASTConsumer *
 Slang::createBackend(const clang::CodeGenOptions& CodeGenOpts,
                      llvm::raw_ostream *OS, OutputType OT) {
-  return new Backend(mDiagEngine.getPtr(), CodeGenOpts, mTargetOpts,
+  return new Backend(mDiagEngine, CodeGenOpts, mTargetOpts,
                      &mPragmas, OS, OT);
 }
 
@@ -266,12 +256,17 @@
 }
 
 void Slang::init(const std::string &Triple, const std::string &CPU,
-                 const std::vector<std::string> &Features) {
+                 const std::vector<std::string> &Features,
+                 clang::DiagnosticsEngine *DiagEngine,
+                 DiagnosticBuffer *DiagClient) {
   if (mInitialized)
     return;
 
-  createDiagnostic();
-  llvm::install_fatal_error_handler(LLVMErrorHandler, mDiagEngine.getPtr());
+  mDiagEngine = DiagEngine;
+  mDiagClient = DiagClient;
+  mDiag.reset(new clang::Diagnostic(mDiagEngine));
+  initDiagnostic();
+  llvm::install_fatal_error_handler(LLVMErrorHandler, mDiagEngine);
 
   createTarget(Triple, CPU, Features);
   createFileManager();
@@ -334,7 +329,7 @@
     case OT_Dependency:
     case OT_Assembly:
     case OT_LLVMAssembly: {
-      OS = OpenOutputFile(OutputFile, 0, &Error, mDiagEngine.getPtr());
+      OS = OpenOutputFile(OutputFile, 0, &Error, mDiagEngine);
       break;
     }
     case OT_Nothing: {
@@ -343,7 +338,7 @@
     case OT_Object:
     case OT_Bitcode: {
       OS = OpenOutputFile(OutputFile, llvm::raw_fd_ostream::F_Binary,
-                          &Error, mDiagEngine.getPtr());
+                          &Error, mDiagEngine);
       break;
     }
     default: {
@@ -365,7 +360,7 @@
   llvm::sys::Path OutputFilePath(OutputFile);
   std::string Error;
 
-  mDOS.reset(OpenOutputFile(OutputFile, 0, &Error, mDiagEngine.getPtr()));
+  mDOS.reset(OpenOutputFile(OutputFile, 0, &Error, mDiagEngine));
   if (!Error.empty() || (mDOS.get() == NULL))
     return false;
 
diff --git a/slang.h b/slang.h
index 1350a95..2029e7a 100644
--- a/slang.h
+++ b/slang.h
@@ -79,19 +79,13 @@
   // Diagnostics Mediator (An interface for both Producer and Consumer)
   llvm::OwningPtr<clang::Diagnostic> mDiag;
 
-  // Diagnostics ID
-  llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> mDiagIDs;
-
   // Diagnostics Engine (Producer and Diagnostics Reporter)
-  llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> mDiagEngine;
+  clang::DiagnosticsEngine *mDiagEngine;
 
   // Diagnostics Consumer
   // NOTE: The ownership is taken by mDiagEngine after creation.
   DiagnosticBuffer *mDiagClient;
 
-  void createDiagnostic();
-
-
   // The target being compiled for
   clang::TargetOptions mTargetOpts;
   llvm::OwningPtr<clang::TargetInfo> mTarget;
@@ -173,7 +167,9 @@
   Slang();
 
   void init(const std::string &Triple, const std::string &CPU,
-            const std::vector<std::string> &Features);
+            const std::vector<std::string> &Features,
+            clang::DiagnosticsEngine *DiagEngine,
+            DiagnosticBuffer *DiagClient);
 
   virtual clang::ModuleKey loadModule(clang::SourceLocation ImportLoc,
                                       clang::IdentifierInfo &ModuleName,
diff --git a/tests/F_Werror/Werror.rs b/tests/F_Werror/Werror.rs
new file mode 100644
index 0000000..f069d88
--- /dev/null
+++ b/tests/F_Werror/Werror.rs
@@ -0,0 +1,7 @@
+// -Werror
+#pragma version(1)
+#pragma rs java_package_name(foo)
+
+static int foo() {
+}
+
diff --git a/tests/F_Werror/stderr.txt.expect b/tests/F_Werror/stderr.txt.expect
new file mode 100644
index 0000000..b58dd9f
--- /dev/null
+++ b/tests/F_Werror/stderr.txt.expect
@@ -0,0 +1 @@
+Werror.rs:6:1: error: control reaches end of non-void function
diff --git a/tests/F_Werror/stdout.txt.expect b/tests/F_Werror/stdout.txt.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/F_Werror/stdout.txt.expect
diff --git a/tests/F_set_target_api_foo/stderr.txt.expect b/tests/F_set_target_api_foo/stderr.txt.expect
index 1aa0561..1c56599 100644
--- a/tests/F_set_target_api_foo/stderr.txt.expect
+++ b/tests/F_set_target_api_foo/stderr.txt.expect
@@ -1 +1 @@
-llvm-rs-cc: error: invalid integral value 'foo' in '-target-api foo'
+error: invalid integral value 'foo' in '-target-api foo'
diff --git a/tests/P_ignore_warnings/ignore_warnings.rs b/tests/P_ignore_warnings/ignore_warnings.rs
new file mode 100644
index 0000000..76704d6
--- /dev/null
+++ b/tests/P_ignore_warnings/ignore_warnings.rs
@@ -0,0 +1,7 @@
+// -w
+#pragma version(1)
+#pragma rs java_package_name(foo)
+
+static int foo() {
+}
+
diff --git a/tests/P_ignore_warnings/stderr.txt.expect b/tests/P_ignore_warnings/stderr.txt.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/P_ignore_warnings/stderr.txt.expect
diff --git a/tests/P_ignore_warnings/stdout.txt.expect b/tests/P_ignore_warnings/stdout.txt.expect
new file mode 100644
index 0000000..5878c88
--- /dev/null
+++ b/tests/P_ignore_warnings/stdout.txt.expect
@@ -0,0 +1 @@
+Generating ScriptC_ignore_warnings.java ...