fxb created this revision.
fxb added reviewers: hans, erichkeane, thakis.
Herald added a subscriber: cfe-commits.

This replicates 'cl.exe' behavior and allows for both preprocessor output and
dependency information to be extraced with a single compiler invocation.

This is especially useful for compiler caching with tools like Mozilla's 
sccache.

See: https://github.com/mozilla/sccache/issues/246


Repository:
  rC Clang

https://reviews.llvm.org/D46394

Files:
  include/clang/Frontend/DependencyOutputOptions.h
  lib/Driver/ToolChains/Clang.cpp
  lib/Frontend/CompilerInvocation.cpp
  lib/Frontend/HeaderIncludeGen.cpp
  test/Driver/cl-options.c


Index: test/Driver/cl-options.c
===================================================================
--- test/Driver/cl-options.c
+++ test/Driver/cl-options.c
@@ -198,10 +198,8 @@
 // RUN: %clang_cl /E /showIncludes -### -- %s 2>&1 | FileCheck 
-check-prefix=showIncludes_E %s
 // RUN: %clang_cl /EP /showIncludes -### -- %s 2>&1 | FileCheck 
-check-prefix=showIncludes_E %s
 // RUN: %clang_cl /E /EP /showIncludes -### -- %s 2>&1 | FileCheck 
-check-prefix=showIncludes_E %s
-// showIncludes_E: warning: argument unused during compilation: 
'--show-includes'
-
-// RUN: %clang_cl /EP /P /showIncludes -### -- %s 2>&1 | FileCheck 
-check-prefix=showIncludes_E_And_P %s
-// showIncludes_E_And_P-NOT: warning: argument unused during compilation: 
'--show-includes'
+// RUN: %clang_cl /EP /P /showIncludes -### -- %s 2>&1 | FileCheck 
-check-prefix=showIncludes_E %s
+// showIncludes_E-NOT: warning: argument unused during compilation: 
'--show-includes'
 
 // /source-charset: should warn on everything except UTF-8.
 // RUN: %clang_cl /source-charset:utf-16 -### -- %s 2>&1 | FileCheck 
-check-prefix=source-charset-utf-16 %s
Index: lib/Frontend/HeaderIncludeGen.cpp
===================================================================
--- lib/Frontend/HeaderIncludeGen.cpp
+++ lib/Frontend/HeaderIncludeGen.cpp
@@ -80,7 +80,9 @@
                                    const DependencyOutputOptions &DepOpts,
                                    bool ShowAllHeaders, StringRef OutputPath,
                                    bool ShowDepth, bool MSStyle) {
-  raw_ostream *OutputFile = MSStyle ? &llvm::outs() : &llvm::errs();
+  raw_ostream *OutputFile = &llvm::errs();
+  if (MSStyle && !DepOpts.PrintShowIncludesToStderr)
+    OutputFile = &llvm::outs();
   bool OwnsOutputFile = false;
 
   // Open the output file, if used.
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -1131,6 +1131,12 @@
   Opts.HeaderIncludeOutputFile = Args.getLastArgValue(OPT_header_include_file);
   Opts.AddMissingHeaderDeps = Args.hasArg(OPT_MG);
   Opts.PrintShowIncludes = Args.hasArg(OPT_show_includes);
+  // Writing both /showIncludes and preprocessor output to stdout
+  // would produce interleaved output, so use stderr for /showIncludes.
+  // This behaves the same as cl.exe, when /E, /EP or /P are passed.
+  if (Opts.PrintShowIncludes &&
+      (Args.hasArg(options::OPT_E) || Args.hasArg(options::OPT_P)))
+    Opts.PrintShowIncludesToStderr = true;
   Opts.DOTOutputFile = Args.getLastArgValue(OPT_dependency_dot);
   Opts.ModuleDependencyOutputDir =
       Args.getLastArgValue(OPT_module_dependency_dir);
Index: lib/Driver/ToolChains/Clang.cpp
===================================================================
--- lib/Driver/ToolChains/Clang.cpp
+++ lib/Driver/ToolChains/Clang.cpp
@@ -5077,13 +5077,8 @@
     CmdArgs.push_back("--dependent-lib=oldnames");
   }
 
-  // Both /showIncludes and /E (and /EP) write to stdout. Allowing both
-  // would produce interleaved output, so ignore /showIncludes in such cases.
-  if ((!Args.hasArg(options::OPT_E) && !Args.hasArg(options::OPT__SLASH_EP)) ||
-      (Args.hasArg(options::OPT__SLASH_P) &&
-       Args.hasArg(options::OPT__SLASH_EP) && !Args.hasArg(options::OPT_E)))
-    if (Arg *A = Args.getLastArg(options::OPT_show_includes))
-      A->render(Args, CmdArgs);
+  if (Arg *A = Args.getLastArg(options::OPT_show_includes))
+    A->render(Args, CmdArgs);
 
   // This controls whether or not we emit RTTI data for polymorphic types.
   if (Args.hasFlag(options::OPT__SLASH_GR_, options::OPT__SLASH_GR,
Index: include/clang/Frontend/DependencyOutputOptions.h
===================================================================
--- include/clang/Frontend/DependencyOutputOptions.h
+++ include/clang/Frontend/DependencyOutputOptions.h
@@ -29,6 +29,8 @@
                                      /// problems.
   unsigned AddMissingHeaderDeps : 1; ///< Add missing headers to dependency 
list
   unsigned PrintShowIncludes : 1; ///< Print cl.exe style /showIncludes info.
+  unsigned
+      PrintShowIncludesToStderr : 1; ///< Print /showIncludes output to stderr.
   unsigned IncludeModuleFiles : 1; ///< Include module file dependencies.
 
   /// The format for the dependency file.
@@ -66,6 +68,7 @@
     UsePhonyTargets = 0;
     AddMissingHeaderDeps = 0;
     PrintShowIncludes = 0;
+    PrintShowIncludesToStderr = 0;
     IncludeModuleFiles = 0;
     OutputFormat = DependencyOutputFormat::Make;
   }


Index: test/Driver/cl-options.c
===================================================================
--- test/Driver/cl-options.c
+++ test/Driver/cl-options.c
@@ -198,10 +198,8 @@
 // RUN: %clang_cl /E /showIncludes -### -- %s 2>&1 | FileCheck -check-prefix=showIncludes_E %s
 // RUN: %clang_cl /EP /showIncludes -### -- %s 2>&1 | FileCheck -check-prefix=showIncludes_E %s
 // RUN: %clang_cl /E /EP /showIncludes -### -- %s 2>&1 | FileCheck -check-prefix=showIncludes_E %s
-// showIncludes_E: warning: argument unused during compilation: '--show-includes'
-
-// RUN: %clang_cl /EP /P /showIncludes -### -- %s 2>&1 | FileCheck -check-prefix=showIncludes_E_And_P %s
-// showIncludes_E_And_P-NOT: warning: argument unused during compilation: '--show-includes'
+// RUN: %clang_cl /EP /P /showIncludes -### -- %s 2>&1 | FileCheck -check-prefix=showIncludes_E %s
+// showIncludes_E-NOT: warning: argument unused during compilation: '--show-includes'
 
 // /source-charset: should warn on everything except UTF-8.
 // RUN: %clang_cl /source-charset:utf-16 -### -- %s 2>&1 | FileCheck -check-prefix=source-charset-utf-16 %s
Index: lib/Frontend/HeaderIncludeGen.cpp
===================================================================
--- lib/Frontend/HeaderIncludeGen.cpp
+++ lib/Frontend/HeaderIncludeGen.cpp
@@ -80,7 +80,9 @@
                                    const DependencyOutputOptions &DepOpts,
                                    bool ShowAllHeaders, StringRef OutputPath,
                                    bool ShowDepth, bool MSStyle) {
-  raw_ostream *OutputFile = MSStyle ? &llvm::outs() : &llvm::errs();
+  raw_ostream *OutputFile = &llvm::errs();
+  if (MSStyle && !DepOpts.PrintShowIncludesToStderr)
+    OutputFile = &llvm::outs();
   bool OwnsOutputFile = false;
 
   // Open the output file, if used.
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -1131,6 +1131,12 @@
   Opts.HeaderIncludeOutputFile = Args.getLastArgValue(OPT_header_include_file);
   Opts.AddMissingHeaderDeps = Args.hasArg(OPT_MG);
   Opts.PrintShowIncludes = Args.hasArg(OPT_show_includes);
+  // Writing both /showIncludes and preprocessor output to stdout
+  // would produce interleaved output, so use stderr for /showIncludes.
+  // This behaves the same as cl.exe, when /E, /EP or /P are passed.
+  if (Opts.PrintShowIncludes &&
+      (Args.hasArg(options::OPT_E) || Args.hasArg(options::OPT_P)))
+    Opts.PrintShowIncludesToStderr = true;
   Opts.DOTOutputFile = Args.getLastArgValue(OPT_dependency_dot);
   Opts.ModuleDependencyOutputDir =
       Args.getLastArgValue(OPT_module_dependency_dir);
Index: lib/Driver/ToolChains/Clang.cpp
===================================================================
--- lib/Driver/ToolChains/Clang.cpp
+++ lib/Driver/ToolChains/Clang.cpp
@@ -5077,13 +5077,8 @@
     CmdArgs.push_back("--dependent-lib=oldnames");
   }
 
-  // Both /showIncludes and /E (and /EP) write to stdout. Allowing both
-  // would produce interleaved output, so ignore /showIncludes in such cases.
-  if ((!Args.hasArg(options::OPT_E) && !Args.hasArg(options::OPT__SLASH_EP)) ||
-      (Args.hasArg(options::OPT__SLASH_P) &&
-       Args.hasArg(options::OPT__SLASH_EP) && !Args.hasArg(options::OPT_E)))
-    if (Arg *A = Args.getLastArg(options::OPT_show_includes))
-      A->render(Args, CmdArgs);
+  if (Arg *A = Args.getLastArg(options::OPT_show_includes))
+    A->render(Args, CmdArgs);
 
   // This controls whether or not we emit RTTI data for polymorphic types.
   if (Args.hasFlag(options::OPT__SLASH_GR_, options::OPT__SLASH_GR,
Index: include/clang/Frontend/DependencyOutputOptions.h
===================================================================
--- include/clang/Frontend/DependencyOutputOptions.h
+++ include/clang/Frontend/DependencyOutputOptions.h
@@ -29,6 +29,8 @@
                                      /// problems.
   unsigned AddMissingHeaderDeps : 1; ///< Add missing headers to dependency list
   unsigned PrintShowIncludes : 1; ///< Print cl.exe style /showIncludes info.
+  unsigned
+      PrintShowIncludesToStderr : 1; ///< Print /showIncludes output to stderr.
   unsigned IncludeModuleFiles : 1; ///< Include module file dependencies.
 
   /// The format for the dependency file.
@@ -66,6 +68,7 @@
     UsePhonyTargets = 0;
     AddMissingHeaderDeps = 0;
     PrintShowIncludes = 0;
+    PrintShowIncludesToStderr = 0;
     IncludeModuleFiles = 0;
     OutputFormat = DependencyOutputFormat::Make;
   }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to