plotfi created this revision.
plotfi added reviewers: compnerd, aaron.ballman.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This patch removes usage of FinalPhase from anywhere outside of the scope where 
it is used to do argument handling.
It also adds argument based trimming of the Phase list pulled out of the 
Types.def table.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D65993

Files:
  clang/include/clang/Driver/Types.h
  clang/lib/Driver/Driver.cpp
  clang/lib/Driver/Types.cpp

Index: clang/lib/Driver/Types.cpp
===================================================================
--- clang/lib/Driver/Types.cpp
+++ clang/lib/Driver/Types.cpp
@@ -6,10 +6,14 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/Options.h"
+#include "clang/Driver/DriverDiagnostic.h"
 #include "clang/Driver/Types.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/Option/Arg.h"
 #include <cassert>
 #include <cstring>
 
@@ -293,6 +297,60 @@
   assert(P.size() <= phases::MaxNumberOfPhases && "Too many phases in list");
 }
 
+void types::getCompilationPhases(const clang::driver::Driver &Driver,
+                                 llvm::opt::DerivedArgList &DAL, ID Id,
+                                 llvm::SmallVectorImpl<phases::ID> &P) {
+  llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> PhaseList;
+  types::getCompilationPhases(InputType, PL);
+
+  if (Driver->CCCIsCPP() || DAL.getLastArg(options::OPT_E) ||
+      DAL.getLastArg(options::OPT__SLASH_EP) ||
+      DAL.getLastArg(options::OPT_M, options::OPT_MM) ||
+      DAL.getLastArg(options::OPT__SLASH_P)) {
+    // Filter to compiler mode. When the compiler is run as a preprocessor then
+    // compilation is not an option.
+    // -S runs the compiler in Assembly listing mode.
+    for (auto Phase : PhaseList)
+      if (Phase <= phases::Preprocess)
+        P.push_back(Phase);
+  } else if (DAL.getLastArg(options::OPT__precompile)) {
+    // --precompile only runs up to precompilation.
+    // This is a clang extension and is not compatible with GCC.
+    for (auto Phase : PhaseList)
+      if (Phase <= phases::Precompile)
+        P.push_back(Phase);
+  } else if (DAL.getLastArg(options::OPT_fsyntax_only) ||
+             DAL.getLastArg(options::OPT_print_supported_cpus) ||
+             DAL.getLastArg(options::OPT_module_file_info) ||
+             DAL.getLastArg(options::OPT_verify_pch) ||
+             DAL.getLastArg(options::OPT_rewrite_objc) ||
+             DAL.getLastArg(options::OPT_rewrite_legacy_objc) ||
+             DAL.getLastArg(options::OPT__migrate) ||
+             DAL.getLastArg(options::OPT_emit_iterface_stubs) ||
+             DAL.getLastArg(options::OPT__analyze,
+                            options::OPT__analyze_auto) ||
+             DAL.getLastArg(options::OPT_emit_ast)) {
+    // -{fsyntax-only,-analyze,emit-ast} only run up to the compiler.
+    for (auto Phase : PhaseList)
+      if (Phase <= phases::Compile)
+        P.push_back(Phase);
+  } else if (DAL.getLastArg(options::OPT_S) ||
+             DAL.getLastArg(options::OPT_emit_llvm)) {
+    for (auto Phase : PhaseList)
+      if (Phase <= phases::Backend)
+        P.push_back(Phase);
+  } else if (DAL.getLastArg(options::OPT_c)) {
+    for (auto Phase : PhaseList)
+      if (Phase <= phases::Assemble)
+        P.push_back(Phase);
+  } else {
+    // Generally means, do every phase until Link.
+    for (auto Phase : PhaseList)
+      P.push_back(Phase);
+  }
+  llvm_unreachable("getCompilationPhases(): Reached end of function.")
+}
+
 ID types::lookupCXXTypeForCType(ID Id) {
   switch (Id) {
   default:
Index: clang/lib/Driver/Driver.cpp
===================================================================
--- clang/lib/Driver/Driver.cpp
+++ clang/lib/Driver/Driver.cpp
@@ -3157,17 +3157,6 @@
     return;
   }
 
-  Arg *FinalPhaseArg;
-  phases::ID FinalPhase = getFinalPhase(Args, &FinalPhaseArg);
-
-  if (FinalPhase == phases::Link) {
-    if (Args.hasArg(options::OPT_emit_llvm))
-      Diag(clang::diag::err_drv_emit_llvm_link);
-    if (IsCLMode() && LTOMode != LTOK_None &&
-        !Args.getLastArgValue(options::OPT_fuse_ld_EQ).equals_lower("lld"))
-      Diag(clang::diag::err_drv_lto_without_lld);
-  }
-
   // Reject -Z* at the top level, these options should never have been exposed
   // by gcc.
   if (Arg *A = Args.getLastArg(options::OPT_Z_Joined))
@@ -3220,15 +3209,6 @@
     Args.eraseArg(options::OPT__SLASH_Yc);
     YcArg = nullptr;
   }
-  if (FinalPhase == phases::Preprocess || Args.hasArg(options::OPT__SLASH_Y_)) {
-    // If only preprocessing or /Y- is used, all pch handling is disabled.
-    // Rather than check for it everywhere, just remove clang-cl pch-related
-    // flags here.
-    Args.eraseArg(options::OPT__SLASH_Fp);
-    Args.eraseArg(options::OPT__SLASH_Yc);
-    Args.eraseArg(options::OPT__SLASH_Yu);
-    YcArg = YuArg = nullptr;
-  }
 
   // Builder to be used to build offloading actions.
   OffloadingActionBuilder OffloadBuilder(C, Args, Inputs);
@@ -3237,70 +3217,117 @@
   HeaderModulePrecompileJobAction *HeaderModuleAction = nullptr;
   ActionList LinkerInputs;
 
-  unsigned LastPLSize = 0;
-  for (auto &I : Inputs) {
-    types::ID InputType = I.first;
-    const Arg *InputArg = I.second;
+  {
+    Arg *FinalPhaseArg;
+    phases::ID FinalPhase = getFinalPhase(Args, &FinalPhaseArg);
 
-    llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> PL;
-    types::getCompilationPhases(InputType, PL);
-    LastPLSize = PL.size();
-
-    // If the first step comes after the final phase we are doing as part of
-    // this compilation, warn the user about it.
-    phases::ID InitialPhase = PL[0];
-    if (InitialPhase > FinalPhase) {
-      if (InputArg->isClaimed())
-        continue;
+    if (FinalPhase == phases::Link) {
+      if (Args.hasArg(options::OPT_emit_llvm))
+        Diag(clang::diag::err_drv_emit_llvm_link);
+      if (IsCLMode() && LTOMode != LTOK_None &&
+          !Args.getLastArgValue(options::OPT_fuse_ld_EQ).equals_lower("lld"))
+        Diag(clang::diag::err_drv_lto_without_lld);
+    }
+
+    if (FinalPhase == phases::Preprocess ||
+        Args.hasArg(options::OPT__SLASH_Y_)) {
+      // If only preprocessing or /Y- is used, all pch handling is disabled.
+      // Rather than check for it everywhere, just remove clang-cl pch-related
+      // flags here.
+      Args.eraseArg(options::OPT__SLASH_Fp);
+      Args.eraseArg(options::OPT__SLASH_Yc);
+      Args.eraseArg(options::OPT__SLASH_Yu);
+      YcArg = YuArg = nullptr;
+    }
+
+    unsigned LastPLSize = 0;
+    for (auto &I : Inputs) {
+      types::ID InputType = I.first;
+      const Arg *InputArg = I.second;
 
-      // Claim here to avoid the more general unused warning.
-      InputArg->claim();
+      llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> PL;
+      types::getCompilationPhases(InputType, PL);
+      LastPLSize = PL.size();
+
+      // If the first step comes after the final phase we are doing as part of
+      // this compilation, warn the user about it.
+      phases::ID InitialPhase = PL[0];
+      if (InitialPhase > FinalPhase) {
+        if (InputArg->isClaimed())
+          continue;
+
+        // Claim here to avoid the more general unused warning.
+        InputArg->claim();
+
+        // Suppress all unused style warnings with -Qunused-arguments
+        if (Args.hasArg(options::OPT_Qunused_arguments))
+          continue;
 
-      // Suppress all unused style warnings with -Qunused-arguments
-      if (Args.hasArg(options::OPT_Qunused_arguments))
+        // Special case when final phase determined by binary name, rather than
+        // by a command-line argument with a corresponding Arg.
+        if (CCCIsCPP())
+          Diag(clang::diag::warn_drv_input_file_unused_by_cpp)
+              << InputArg->getAsString(Args) << getPhaseName(InitialPhase);
+        // Special case '-E' warning on a previously preprocessed file to make
+        // more sense.
+        else if (InitialPhase == phases::Compile &&
+                 (Args.getLastArg(options::OPT__SLASH_EP,
+                                  options::OPT__SLASH_P) ||
+                  Args.getLastArg(options::OPT_E) ||
+                  Args.getLastArg(options::OPT_M, options::OPT_MM)) &&
+                 getPreprocessedType(InputType) == types::TY_INVALID)
+          Diag(clang::diag::warn_drv_preprocessed_input_file_unused)
+              << InputArg->getAsString(Args) << !!FinalPhaseArg
+              << (FinalPhaseArg ? FinalPhaseArg->getOption().getName() : "");
+        else
+          Diag(clang::diag::warn_drv_input_file_unused)
+              << InputArg->getAsString(Args) << getPhaseName(InitialPhase)
+              << !!FinalPhaseArg
+              << (FinalPhaseArg ? FinalPhaseArg->getOption().getName() : "");
         continue;
+      }
 
-      // Special case when final phase determined by binary name, rather than
-      // by a command-line argument with a corresponding Arg.
-      if (CCCIsCPP())
-        Diag(clang::diag::warn_drv_input_file_unused_by_cpp)
-            << InputArg->getAsString(Args) << getPhaseName(InitialPhase);
-      // Special case '-E' warning on a previously preprocessed file to make
-      // more sense.
-      else if (InitialPhase == phases::Compile &&
-               FinalPhase == phases::Preprocess &&
-               getPreprocessedType(InputType) == types::TY_INVALID)
-        Diag(clang::diag::warn_drv_preprocessed_input_file_unused)
-            << InputArg->getAsString(Args) << !!FinalPhaseArg
-            << (FinalPhaseArg ? FinalPhaseArg->getOption().getName() : "");
-      else
-        Diag(clang::diag::warn_drv_input_file_unused)
-            << InputArg->getAsString(Args) << getPhaseName(InitialPhase)
-            << !!FinalPhaseArg
-            << (FinalPhaseArg ? FinalPhaseArg->getOption().getName() : "");
-      continue;
+      if (YcArg) {
+        // Add a separate precompile phase for the compile phase.
+        if (FinalPhase >= phases::Compile) {
+          const types::ID HeaderType = lookupHeaderTypeForSourceType(InputType);
+          llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> PCHPL;
+          types::getCompilationPhases(HeaderType, PCHPL);
+          // Build the pipeline for the pch file.
+          Action *ClangClPch = C.MakeAction<InputAction>(*InputArg, HeaderType);
+          for (phases::ID Phase : PCHPL)
+            ClangClPch = ConstructPhaseAction(C, Args, Phase, ClangClPch);
+          assert(ClangClPch);
+          Actions.push_back(ClangClPch);
+          // The driver currently exits after the first failed command.  This
+          // relies on that behavior, to make sure if the pch generation fails,
+          // the main compilation won't run.
+          // FIXME: If the main compilation fails, the PCH generation should
+          // probably not be considered successful either.
+        }
+      }
     }
 
-    if (YcArg) {
-      // Add a separate precompile phase for the compile phase.
-      if (FinalPhase >= phases::Compile) {
-        const types::ID HeaderType = lookupHeaderTypeForSourceType(InputType);
-        llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> PCHPL;
-        types::getCompilationPhases(HeaderType, PCHPL);
-        // Build the pipeline for the pch file.
-        Action *ClangClPch =
-            C.MakeAction<InputAction>(*InputArg, HeaderType);
-        for (phases::ID Phase : PCHPL)
-          ClangClPch = ConstructPhaseAction(C, Args, Phase, ClangClPch);
-        assert(ClangClPch);
-        Actions.push_back(ClangClPch);
-        // The driver currently exits after the first failed command.  This
-        // relies on that behavior, to make sure if the pch generation fails,
-        // the main compilation won't run.
-        // FIXME: If the main compilation fails, the PCH generation should
-        // probably not be considered successful either.
-      }
+    // If we are linking, claim any options which are obviously only used for
+    // compilation.
+    // FIXME: Understand why the last Phase List length is used here.
+    if (FinalPhase == phases::Link && LastPLSize == 1) {
+      Args.ClaimAllArgs(options::OPT_CompileOnly_Group);
+      Args.ClaimAllArgs(options::OPT_cl_compile_Group);
     }
+  }
+
+  for (auto &I : Inputs) {
+    types::ID InputType = I.first;
+    const Arg *InputArg = I.second;
+
+    llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> PL;
+    types::getCompilationPhases(*this, Args, InputType, PL);
+    if (!PL.size())
+      continue;
+
+    llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> FullPL;
+    types::getCompilationPhases(InputType, FullPL);
 
     // Build the pipeline for this file.
     Action *Current = C.MakeAction<InputAction>(*InputArg, InputType);
@@ -3312,13 +3339,9 @@
 
     for (phases::ID Phase : PL) {
 
-      // We are done if this step is past what the user requested.
-      if (Phase > FinalPhase)
-        break;
-
       // Add any offload action the host action depends on.
       Current = OffloadBuilder.addDeviceDependencesToHostAction(
-          Current, InputArg, Phase, FinalPhase, PL);
+          Current, InputArg, Phase, PL.back(), FullPL);
       if (!Current)
         break;
 
@@ -3379,14 +3402,6 @@
     Actions.push_back(LA);
   }
 
-  // If we are linking, claim any options which are obviously only used for
-  // compilation.
-  // FIXME: Understand why the last Phase List length is used here.
-  if (FinalPhase == phases::Link && LastPLSize == 1) {
-    Args.ClaimAllArgs(options::OPT_CompileOnly_Group);
-    Args.ClaimAllArgs(options::OPT_cl_compile_Group);
-  }
-
   // If --print-supported-cpus, -mcpu=? or -mtune=? is specified, build a custom
   // Compile phase that prints out supported cpu models and quits.
   if (Arg *A = Args.getLastArg(options::OPT_print_supported_cpus)) {
Index: clang/include/clang/Driver/Types.h
===================================================================
--- clang/include/clang/Driver/Types.h
+++ clang/include/clang/Driver/Types.h
@@ -11,12 +11,14 @@
 
 #include "clang/Driver/Phases.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/Option/ArgList.h"
 
 namespace llvm {
 class StringRef;
 }
 namespace clang {
 namespace driver {
+class Driver;
 namespace types {
   enum ID {
     TY_INVALID,
@@ -100,6 +102,9 @@
   void getCompilationPhases(
     ID Id,
     llvm::SmallVectorImpl<phases::ID> &Phases);
+  void getCompilationPhases(const clang::driver::Driver &Driver,
+                            llvm::opt::DerivedArgList &DAL, ID Id,
+                            llvm::SmallVectorImpl<phases::ID> &Phases);
 
   /// lookupCXXTypeForCType - Lookup CXX input type that corresponds to given
   /// C type (used for clang++ emulation of g++ behaviour)
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to