https://github.com/Meinersbur updated 
https://github.com/llvm/llvm-project/pull/225678

>From ee4cebf43ee6d8a351534c5812e92256a9d530ed Mon Sep 17 00:00:00 2001
From: Michael Kruse <[email protected]>
Date: Tue, 22 Sep 2026 18:48:29 +0200
Subject: [PATCH 1/5] Reapply "[Clang][Driver] Final phase also determined by
 input (#218802)" (#225416)

This reverts commit 976c919fbc123e7fd7058223c23ad9c312477b4b.
---
 clang/include/clang/Driver/Driver.h |  1 +
 clang/include/clang/Driver/Types.h  |  6 ++--
 clang/lib/Driver/Driver.cpp         | 51 ++++++++++++++++++++++-------
 clang/lib/Driver/Types.cpp          |  5 +--
 clang/test/Driver/Inputs/object0.o  |  0
 clang/test/Driver/aix-ld.c          |  2 +-
 clang/test/Driver/pch-inputs.h      | 48 +++++++++++++++++++++++++++
 7 files changed, 95 insertions(+), 18 deletions(-)
 create mode 100644 clang/test/Driver/Inputs/object0.o
 create mode 100644 clang/test/Driver/pch-inputs.h

diff --git a/clang/include/clang/Driver/Driver.h 
b/clang/include/clang/Driver/Driver.h
index 15b6fdcb8a574..e653d8e3a2dbe 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -339,6 +339,7 @@ class Driver {
   //       modes. Fold this functionality into Types::getCompilationPhases and
   //       handleArguments.
   phases::ID getFinalPhase(const llvm::opt::DerivedArgList &DAL,
+                           llvm::ArrayRef<InputTy>,
                            llvm::opt::Arg **FinalPhaseArg = nullptr) const;
 
   llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
diff --git a/clang/include/clang/Driver/Types.h 
b/clang/include/clang/Driver/Types.h
index 9dd89e1904a4f..9ec456773716d 100644
--- a/clang/include/clang/Driver/Types.h
+++ b/clang/include/clang/Driver/Types.h
@@ -115,9 +115,9 @@ namespace types {
   /// done for type 'Id' up until including LastPhase.
   llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases>
   getCompilationPhases(ID Id, phases::ID LastPhase = phases::IfsMerge);
-  llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases>
-  getCompilationPhases(const clang::driver::Driver &Driver,
-                       llvm::opt::DerivedArgList &DAL, ID Id);
+  llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> 
getCompilationPhases(
+      const clang::driver::Driver &Driver, llvm::opt::DerivedArgList &DAL,
+      llvm::ArrayRef<std::pair<ID, const llvm::opt::Arg *>> Inputs, ID Id);
 
   /// lookupCXXTypeForCType - Lookup CXX input type that corresponds to given
   /// C type (used for clang++ emulation of g++ behaviour)
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 7649941a68b1c..7a742e404bf5c 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -352,8 +352,10 @@ InputArgList Driver::ParseArgStrings(ArrayRef<const char 
*> ArgStrings,
 
 // Determine which compilation mode we are in. We look for options which
 // affect the phase, starting with the earliest phases, and record which
-// option we used to determine the final phase.
+// option we used to determine the final phase. In absence of any explicit
+// action command line option, derive the compilation mode from the inputs.
 phases::ID Driver::getFinalPhase(const DerivedArgList &DAL,
+                                 llvm::ArrayRef<InputTy> Inputs,
                                  Arg **FinalPhaseArg) const {
   Arg *PhaseArg = nullptr;
   phases::ID FinalPhase;
@@ -401,9 +403,33 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL,
   } else if ((PhaseArg = DAL.getLastArg(options::OPT_emit_interface_stubs))) {
     FinalPhase = phases::IfsMerge;
 
-    // Otherwise do everything.
-  } else
-    FinalPhase = phases::Link;
+    // Otherwise autodetect from last phase triggered by input file.
+  } else {
+    FinalPhase = phases::Preprocess;
+    bool AnyPhase = false;
+    for (auto &I : Inputs) {
+      types::ID InputType = I.first;
+      const Arg *InputArg = I.second;
+
+      // Linker options should not trigger more phases.
+      if (InputArg->getOption().hasFlag(options::LinkerInput))
+        continue;
+
+      // Relies on the compilation phases being ordered.
+      auto PL = types::getCompilationPhases(InputType);
+      if (PL.empty())
+        continue;
+
+      phases::ID LastPL = PL.back();
+      if (LastPL > FinalPhase)
+        FinalPhase = LastPL;
+      AnyPhase = true;
+    }
+
+    // Fall back to "do everything" when consistency check fails.
+    if (!AnyPhase || FinalPhase > phases::Link)
+      FinalPhase = phases::Link;
+  }
 
   if (FinalPhaseArg)
     *FinalPhaseArg = PhaseArg;
@@ -1849,7 +1875,8 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char 
*> ArgList) {
   BuildInputs(C->getDefaultToolChain(), *TranslatedArgs, Inputs);
   if (HasConfigFileTail && Inputs.size()) {
     Arg *FinalPhaseArg;
-    if (getFinalPhase(*TranslatedArgs, &FinalPhaseArg) == phases::Link) {
+    if (getFinalPhase(*TranslatedArgs, Inputs, &FinalPhaseArg) ==
+        phases::Link) {
       DerivedArgList TranslatedLinkerIns(*CfgOptionsTail);
       for (Arg *A : *CfgOptionsTail)
         TranslatedLinkerIns.append(A);
@@ -3434,7 +3461,7 @@ void Driver::handleArguments(Compilation &C, 
DerivedArgList &Args,
   }
 
   Arg *FinalPhaseArg;
-  phases::ID FinalPhase = getFinalPhase(Args, &FinalPhaseArg);
+  phases::ID FinalPhase = getFinalPhase(Args, Inputs, &FinalPhaseArg);
 
   if (FinalPhase == phases::Link) {
     if (Args.hasArgNoClaim(options::OPT_hipstdpar)) {
@@ -3531,8 +3558,8 @@ void Driver::handleArguments(Compilation &C, 
DerivedArgList &Args,
       else
         Diag(clang::diag::warn_drv_input_file_unused)
             << InputArg->getAsString(Args) << getPhaseName(InitialPhase)
-            << !!FinalPhaseArg
-            << (FinalPhaseArg ? FinalPhaseArg->getOption().getName() : "");
+            << !FinalPhaseArg
+            << (FinalPhaseArg ? FinalPhaseArg->getSpelling() : "");
       continue;
     }
 
@@ -3613,7 +3640,7 @@ void Driver::BuildActions(Compilation &C, DerivedArgList 
&Args,
       C.isOffloadingHostKind(Action::OFK_HIP) && offloadDeviceOnly() &&
       Args.hasArg(options::OPT_hip_link) &&
       Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false) &&
-      getFinalPhase(Args) == phases::Link &&
+      getFinalPhase(Args, Inputs) == phases::Link &&
       !Args.hasArg(options::OPT_emit_llvm) &&
       Args.hasFlag(options::OPT_gpu_bundle_output,
                    options::OPT_no_gpu_bundle_output, true);
@@ -3627,7 +3654,7 @@ void Driver::BuildActions(Compilation &C, DerivedArgList 
&Args,
     types::ID InputType = I.first;
     const Arg *InputArg = I.second;
 
-    auto PL = types::getCompilationPhases(*this, Args, InputType);
+    auto PL = types::getCompilationPhases(*this, Args, Inputs, InputType);
     if (PL.empty())
       continue;
 
@@ -4125,7 +4152,7 @@ Driver::BuildOffloadingActions(Compilation &C, 
llvm::opt::DerivedArgList &Args,
   // Don't build offloading actions if we do not have a compile action. If
   // preprocessing only ignore embedding.
   if (!(isa<CompileJobAction>(HostAction) ||
-        getFinalPhase(Args) == phases::Preprocess))
+        getFinalPhase(Args, {Input}) == phases::Preprocess))
     return HostAction;
 
   bool UsesLLVMOffloading = Args.hasArg(
@@ -4178,7 +4205,7 @@ Driver::BuildOffloadingActions(Compilation &C, 
llvm::opt::DerivedArgList &Args,
             .isOSDarwin())
       HostAction->setCannotBeCollapsedWithNextDependentAction();
 
-    auto PL = types::getCompilationPhases(*this, Args, InputType);
+    auto PL = types::getCompilationPhases(*this, Args, {Input}, InputType);
 
     for (phases::ID Phase : PL) {
       if (Phase == phases::Link) {
diff --git a/clang/lib/Driver/Types.cpp b/clang/lib/Driver/Types.cpp
index 4cca8acd515d7..618fb402af728 100644
--- a/clang/lib/Driver/Types.cpp
+++ b/clang/lib/Driver/Types.cpp
@@ -429,8 +429,9 @@ types::getCompilationPhases(ID Id, phases::ID LastPhase) {
 
 llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases>
 types::getCompilationPhases(const clang::driver::Driver &Driver,
-                            llvm::opt::DerivedArgList &DAL, ID Id) {
-  return types::getCompilationPhases(Id, Driver.getFinalPhase(DAL));
+                            llvm::opt::DerivedArgList &DAL,
+                            llvm::ArrayRef<InputTy> Inputs, ID Id) {
+  return types::getCompilationPhases(Id, Driver.getFinalPhase(DAL, Inputs));
 }
 
 ID types::lookupCXXTypeForCType(ID Id) {
diff --git a/clang/test/Driver/Inputs/object0.o 
b/clang/test/Driver/Inputs/object0.o
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/clang/test/Driver/aix-ld.c b/clang/test/Driver/aix-ld.c
index bedd224eeca9c..641908afc8d98 100644
--- a/clang/test/Driver/aix-ld.c
+++ b/clang/test/Driver/aix-ld.c
@@ -1171,4 +1171,4 @@
 // RUN:        -K \
 // RUN:        -c \
 // RUN:   | FileCheck --check-prefixes=CHECK-K-UNUSED %s
-// CHECK-K-UNUSED: clang: warning: -K: 'linker' input unused 
[-Wunused-command-line-argument]
+// CHECK-K-UNUSED: clang: warning: -K: 'linker' input unused when '-c' is 
present [-Wunused-command-line-argument]
diff --git a/clang/test/Driver/pch-inputs.h b/clang/test/Driver/pch-inputs.h
new file mode 100644
index 0000000000000..fa6f94f996915
--- /dev/null
+++ b/clang/test/Driver/pch-inputs.h
@@ -0,0 +1,48 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+
+// Warn about linker options being ignored when not linking
+// RUN: %clang %s -lfoo -o %t/tmp1.pch -### 2>&1 | FileCheck %s 
--check-prefix=UNUSED-L,SINGLEHEADER
+// RUN: %clang %s -x c++-header -lfoo -o %t/tmp1.pch -### 2>&1 | FileCheck %s 
--check-prefix=UNUSED-L,SINGLEHEADER
+// UNUSED-L: clang: warning: -lfoo: 'linker' input unused 
[-Wunused-command-line-argument]
+
+// RUN: %clang %s -Wl,--whole-archive -o %t/tmp1.pch -### 2>&1 | FileCheck %s 
--check-prefix=UNUSED-WL,SINGLEHEADER
+// UNUSED-WL: clang: warning: -Wl,--whole-archive: 'linker' input unused 
[-Wunused-command-line-argument]
+
+// RUN: %clang %S/Inputs/header1.h %S/Inputs/header2.h -lfoo -### 2>&1 | 
FileCheck %s --check-prefix=UNUSED-L,MULTIHEADER
+
+
+// Error with single -o when there are multiple output files
+// RUN: not %clang %S/Inputs/header1.h %S/Inputs/header2.h -lfoo -o 
%t/tmp2.pch -### 2>&1 | FileCheck %s --check-prefix=UNUSED-L,MULTIOUTPUT
+// MULTIOUTPUT: clang: error: cannot specify -o when generating multiple 
output files
+
+// An actual linker input file (object0.o) triggers an error, not a warning
+// RUN: not %clang %s %S/Inputs/object0.o -o %t/tmp3.pch -### 2>&1 | FileCheck 
%s --check-prefix=MULTIOUTPUT
+
+// Other input types that do not link
+// RUN: %clang -x cl-header %s -Xlinker -somelinkerflag -### 2>&1 | FileCheck 
%s --check-prefix=UNUSED-XLINKER
+// RUN: %clang -x objective-c++-header %s -Xlinker -somelinkerflag -### 2>&1 | 
FileCheck %s --check-prefix=UNUSED-XLINKER
+// RUN: %clang -x hlsl %s -Xlinker -somelinkerflag -### 2>&1 | FileCheck %s 
--check-prefix=UNUSED-XLINKER
+// UNUSED-XLINKER: clang: warning: -Xlinker -somelinkerflag: 'linker' input 
unused [-Wunused-command-line-argument]
+
+
+// Normal case: Single header file input compiles to .pch even without 
--precompile
+// RUN: %clang %s -o %t/tmp1.pch -### 2>&1 | FileCheck %s 
--check-prefix=SINGLEHEADER
+// SINGLEHEADER: "-cc1"
+// SINGLEHEADER: "-emit-pch"
+// SINGLEHEADER: "-o"
+// SINGLEHEADER: tmp1.pch"
+
+
+// Multiple header files input compiles to one .pch each even without 
--precompile
+// RUN: %clang %S/Inputs/header1.h %S/Inputs/header2.h -### 2>&1 | FileCheck 
%s --check-prefix=MULTIHEADER
+// MULTIHEADER: "-cc1"
+// MULTIHEADER: "-emit-pch"
+// MULTIHEADER: "-o"
+// MULTIHEADER: header1.h.pch"
+// MULTIHEADER: "-cc1"
+// MULTIHEADER: "-emit-pch"
+// MULTIHEADER: "-o"
+// MULTIHEADER: header2.h.pch"
+
+

>From f6e7d49caa85f136de08e75f33366057b62b49b2 Mon Sep 17 00:00:00 2001
From: Michael Kruse <[email protected]>
Date: Wed, 23 Sep 2026 11:23:41 +0200
Subject: [PATCH 2/5] Prototype

---
 clang/include/clang/Driver/Compilation.h |  6 ++++
 clang/include/clang/Driver/Driver.h      |  4 +--
 clang/include/clang/Driver/Types.h       |  2 +-
 clang/lib/Driver/Driver.cpp              | 36 ++++++++++++------------
 clang/lib/Driver/Types.cpp               |  4 +--
 5 files changed, 29 insertions(+), 23 deletions(-)

diff --git a/clang/include/clang/Driver/Compilation.h 
b/clang/include/clang/Driver/Compilation.h
index 825806b6cfe33..55cfdeddc3939 100644
--- a/clang/include/clang/Driver/Compilation.h
+++ b/clang/include/clang/Driver/Compilation.h
@@ -13,6 +13,7 @@
 #include "clang/Basic/OffloadArch.h"
 #include "clang/Driver/Action.h"
 #include "clang/Driver/Job.h"
+#include "clang/Driver/Phases.h"
 #include "clang/Driver/Util.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
@@ -64,6 +65,11 @@ class Compilation {
   /// The original (untranslated) input argument list.
   llvm::opt::InputArgList *Args;
 
+       public:
+          phases::ID FinalPhase; 
+               llvm::opt:: Arg *FinalPhaseArg;
+         private:
+
   /// The driver translated arguments. Note that toolchains may perform their
   /// own argument translation.
   llvm::opt::DerivedArgList *TranslatedArgs;
diff --git a/clang/include/clang/Driver/Driver.h 
b/clang/include/clang/Driver/Driver.h
index e653d8e3a2dbe..eebedc985f23c 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -338,9 +338,9 @@ class Driver {
   // TODO: Much of what getFinalPhase returns are not actually true compiler
   //       modes. Fold this functionality into Types::getCompilationPhases and
   //       handleArguments.
-  phases::ID getFinalPhase(const llvm::opt::DerivedArgList &DAL,
+   phases::ID getFinalPhase(const llvm::opt::DerivedArgList &DAL,
                            llvm::ArrayRef<InputTy>,
-                           llvm::opt::Arg **FinalPhaseArg = nullptr) const;
+                           llvm::opt::Arg **FinalPhaseArg = nullptr) const  ;
 
   llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
   executeProgram(llvm::ArrayRef<llvm::StringRef> Args) const;
diff --git a/clang/include/clang/Driver/Types.h 
b/clang/include/clang/Driver/Types.h
index 9ec456773716d..f192a773a493a 100644
--- a/clang/include/clang/Driver/Types.h
+++ b/clang/include/clang/Driver/Types.h
@@ -117,7 +117,7 @@ namespace types {
   getCompilationPhases(ID Id, phases::ID LastPhase = phases::IfsMerge);
   llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> 
getCompilationPhases(
       const clang::driver::Driver &Driver, llvm::opt::DerivedArgList &DAL,
-      llvm::ArrayRef<std::pair<ID, const llvm::opt::Arg *>> Inputs, ID Id);
+      llvm::ArrayRef<std::pair<ID, const llvm::opt::Arg *>> Inputs, ID Id, 
phases::ID FinalPhase);
 
   /// lookupCXXTypeForCType - Lookup CXX input type that corresponds to given
   /// C type (used for clang++ emulation of g++ behaviour)
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 7a742e404bf5c..fce60d2566787 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -1873,9 +1873,10 @@ Compilation *Driver::BuildCompilation(ArrayRef<const 
char *> ArgList) {
   // Construct the list of inputs.
   InputList Inputs;
   BuildInputs(C->getDefaultToolChain(), *TranslatedArgs, Inputs);
-  if (HasConfigFileTail && Inputs.size()) {
-    Arg *FinalPhaseArg;
-    if (getFinalPhase(*TranslatedArgs, Inputs, &FinalPhaseArg) ==
+       C->FinalPhase  = getFinalPhase(*TranslatedArgs, Inputs, 
&C->FinalPhaseArg) ;
+       auto FinalPhase = C->FinalPhase;
+  if (HasConfigFileTail && Inputs.size()) {    
+    if (FinalPhase==
         phases::Link) {
       DerivedArgList TranslatedLinkerIns(*CfgOptionsTail);
       for (Arg *A : *CfgOptionsTail)
@@ -3460,10 +3461,9 @@ void Driver::handleArguments(Compilation &C, 
DerivedArgList &Args,
     YcArg = nullptr;
   }
 
-  Arg *FinalPhaseArg;
-  phases::ID FinalPhase = getFinalPhase(Args, Inputs, &FinalPhaseArg);
 
-  if (FinalPhase == phases::Link) {
+
+  if (C.FinalPhase == phases::Link) {
     if (Args.hasArgNoClaim(options::OPT_hipstdpar)) {
       Args.AddFlagArg(nullptr, getOpts().getOption(options::OPT_hip_link));
       Args.AddFlagArg(nullptr,
@@ -3498,7 +3498,7 @@ void Driver::handleArguments(Compilation &C, 
DerivedArgList &Args,
     }
   }
 
-  if (FinalPhase == phases::Preprocess || Args.hasArg(options::OPT__SLASH_Y_)) 
{
+  if (C.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.
@@ -3516,7 +3516,7 @@ void Driver::handleArguments(Compilation &C, 
DerivedArgList &Args,
     Args.eraseArg(options::OPT_include_pch);
   }
 
-  bool LinkOnly = phases::Link == FinalPhase && Inputs.size() > 0;
+  bool LinkOnly = phases::Link == C.FinalPhase && Inputs.size() > 0;
   for (auto &I : Inputs) {
     types::ID InputType = I.first;
     const Arg *InputArg = I.second;
@@ -3528,7 +3528,7 @@ void Driver::handleArguments(Compilation &C, 
DerivedArgList &Args,
 
     // If the first step comes after the final phase we are doing as part of
     // this compilation, warn the user about it.
-    if (InitialPhase > FinalPhase) {
+    if (InitialPhase > C.FinalPhase) {
       if (InputArg->isClaimed())
         continue;
 
@@ -3553,19 +3553,19 @@ void Driver::handleArguments(Compilation &C, 
DerivedArgList &Args,
                 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() : "");
+            << InputArg->getAsString(Args) << !!C.FinalPhaseArg
+            << (C.FinalPhaseArg ? C.FinalPhaseArg->getOption().getName() : "");
       else
         Diag(clang::diag::warn_drv_input_file_unused)
             << InputArg->getAsString(Args) << getPhaseName(InitialPhase)
-            << !FinalPhaseArg
-            << (FinalPhaseArg ? FinalPhaseArg->getSpelling() : "");
+            << !C.FinalPhaseArg
+            << (C.FinalPhaseArg ? C.FinalPhaseArg->getSpelling() : "");
       continue;
     }
 
     if (YcArg) {
       // Add a separate precompile phase for the compile phase.
-      if (FinalPhase >= phases::Compile) {
+      if (C.FinalPhase >= phases::Compile) {
         const types::ID HeaderType = lookupHeaderTypeForSourceType(InputType);
         // Build the pipeline for the pch file.
         Action *ClangClPch = C.MakeAction<InputAction>(*InputArg, HeaderType);
@@ -3640,7 +3640,7 @@ void Driver::BuildActions(Compilation &C, DerivedArgList 
&Args,
       C.isOffloadingHostKind(Action::OFK_HIP) && offloadDeviceOnly() &&
       Args.hasArg(options::OPT_hip_link) &&
       Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false) &&
-      getFinalPhase(Args, Inputs) == phases::Link &&
+     C.FinalPhase == phases::Link &&
       !Args.hasArg(options::OPT_emit_llvm) &&
       Args.hasFlag(options::OPT_gpu_bundle_output,
                    options::OPT_no_gpu_bundle_output, true);
@@ -3654,7 +3654,7 @@ void Driver::BuildActions(Compilation &C, DerivedArgList 
&Args,
     types::ID InputType = I.first;
     const Arg *InputArg = I.second;
 
-    auto PL = types::getCompilationPhases(*this, Args, Inputs, InputType);
+    auto PL = types::getCompilationPhases(*this, Args, Inputs, InputType, 
C.FinalPhase);
     if (PL.empty())
       continue;
 
@@ -4152,7 +4152,7 @@ Driver::BuildOffloadingActions(Compilation &C, 
llvm::opt::DerivedArgList &Args,
   // Don't build offloading actions if we do not have a compile action. If
   // preprocessing only ignore embedding.
   if (!(isa<CompileJobAction>(HostAction) ||
-        getFinalPhase(Args, {Input}) == phases::Preprocess))
+        C.FinalPhase == phases::Preprocess))
     return HostAction;
 
   bool UsesLLVMOffloading = Args.hasArg(
@@ -4205,7 +4205,7 @@ Driver::BuildOffloadingActions(Compilation &C, 
llvm::opt::DerivedArgList &Args,
             .isOSDarwin())
       HostAction->setCannotBeCollapsedWithNextDependentAction();
 
-    auto PL = types::getCompilationPhases(*this, Args, {Input}, InputType);
+    auto PL = types::getCompilationPhases(*this, Args, {Input}, InputType, 
C.FinalPhase);
 
     for (phases::ID Phase : PL) {
       if (Phase == phases::Link) {
diff --git a/clang/lib/Driver/Types.cpp b/clang/lib/Driver/Types.cpp
index 618fb402af728..11292d9240877 100644
--- a/clang/lib/Driver/Types.cpp
+++ b/clang/lib/Driver/Types.cpp
@@ -430,8 +430,8 @@ types::getCompilationPhases(ID Id, phases::ID LastPhase) {
 llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases>
 types::getCompilationPhases(const clang::driver::Driver &Driver,
                             llvm::opt::DerivedArgList &DAL,
-                            llvm::ArrayRef<InputTy> Inputs, ID Id) {
-  return types::getCompilationPhases(Id, Driver.getFinalPhase(DAL, Inputs));
+                            llvm::ArrayRef<InputTy> Inputs, ID Id, phases::ID 
FinalPhase) {
+  return types::getCompilationPhases(Id, FinalPhase);
 }
 
 ID types::lookupCXXTypeForCType(ID Id) {

>From f11061c51e0e7e011612fb1195e377ca2acda8ec Mon Sep 17 00:00:00 2001
From: Michael Kruse <[email protected]>
Date: Wed, 23 Sep 2026 12:26:09 +0200
Subject: [PATCH 3/5] Fix fix O(n^2) regression

---
 clang/include/clang/Driver/Compilation.h | 21 +++++++---
 clang/include/clang/Driver/Driver.h      | 10 +++--
 clang/include/clang/Driver/Types.h       |  3 +-
 clang/lib/Driver/Driver.cpp              | 53 +++++++++++++++---------
 clang/lib/Driver/Types.cpp               |  3 +-
 clang/test/Driver/aix-ld.c               |  2 +-
 clang/test/Driver/pch-inputs.h           |  8 ++--
 7 files changed, 64 insertions(+), 36 deletions(-)

diff --git a/clang/include/clang/Driver/Compilation.h 
b/clang/include/clang/Driver/Compilation.h
index 55cfdeddc3939..f98fc66b6cb1b 100644
--- a/clang/include/clang/Driver/Compilation.h
+++ b/clang/include/clang/Driver/Compilation.h
@@ -65,15 +65,17 @@ class Compilation {
   /// The original (untranslated) input argument list.
   llvm::opt::InputArgList *Args;
 
-       public:
-          phases::ID FinalPhase; 
-               llvm::opt:: Arg *FinalPhaseArg;
-         private:
-
   /// The driver translated arguments. Note that toolchains may perform their
   /// own argument translation.
   llvm::opt::DerivedArgList *TranslatedArgs;
 
+  /// Which compilation phase is supposed to be the last job.
+  phases::ID FinalPhase;
+
+  /// Which compiler argument determined what the \p FinalPhase should be (used
+  /// for diagnostics).
+  llvm::opt::Arg *FinalPhaseArg = nullptr;
+
   /// The list of actions we've created via MakeAction.  This is not accessible
   /// to consumers; it's here just to manage ownership.
   std::vector<std::unique_ptr<Action>> AllActions;
@@ -207,6 +209,15 @@ class Compilation {
 
   llvm::opt::DerivedArgList &getArgs() { return *TranslatedArgs; }
 
+  void setFinalPhase(phases::ID FinalPhase, llvm::opt::Arg *FinalPhaseArg) {
+    this->FinalPhase = FinalPhase;
+    this->FinalPhaseArg = FinalPhaseArg;
+  }
+
+  phases::ID getFinalPhase() const { return FinalPhase; }
+
+  llvm::opt::Arg *getFinalPhaseArg() const { return FinalPhaseArg; }
+
   ActionList &getActions() { return Actions; }
   const ActionList &getActions() const { return Actions; }
 
diff --git a/clang/include/clang/Driver/Driver.h 
b/clang/include/clang/Driver/Driver.h
index eebedc985f23c..fa4eef66e3dea 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -332,16 +332,20 @@ class Driver {
   LLVM_PREFERRED_TYPE(bool)
   unsigned ProbePrecompiled : 1;
 
-public:
   // getFinalPhase - Determine which compilation mode we are in and record
   // which option we used to determine the final phase.
   // TODO: Much of what getFinalPhase returns are not actually true compiler
   //       modes. Fold this functionality into Types::getCompilationPhases and
   //       handleArguments.
-   phases::ID getFinalPhase(const llvm::opt::DerivedArgList &DAL,
+  phases::ID getFinalPhase(const llvm::opt::DerivedArgList &DAL,
                            llvm::ArrayRef<InputTy>,
-                           llvm::opt::Arg **FinalPhaseArg = nullptr) const  ;
+                           llvm::opt::Arg **FinalPhaseArg = nullptr) const;
+
+  /// Set the final phase in \p C based on compiler arguments, driver state, 
and
+  /// the \p Inputs to be processed.
+  void updateFinalPhase(Compilation &C, llvm::ArrayRef<InputTy> Inputs) const;
 
+public:
   llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
   executeProgram(llvm::ArrayRef<llvm::StringRef> Args) const;
 
diff --git a/clang/include/clang/Driver/Types.h 
b/clang/include/clang/Driver/Types.h
index f192a773a493a..e4f3536ed1c6e 100644
--- a/clang/include/clang/Driver/Types.h
+++ b/clang/include/clang/Driver/Types.h
@@ -117,7 +117,8 @@ namespace types {
   getCompilationPhases(ID Id, phases::ID LastPhase = phases::IfsMerge);
   llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> 
getCompilationPhases(
       const clang::driver::Driver &Driver, llvm::opt::DerivedArgList &DAL,
-      llvm::ArrayRef<std::pair<ID, const llvm::opt::Arg *>> Inputs, ID Id, 
phases::ID FinalPhase);
+      llvm::ArrayRef<std::pair<ID, const llvm::opt::Arg *>> Inputs, ID Id,
+      phases::ID FinalPhase);
 
   /// lookupCXXTypeForCType - Lookup CXX input type that corresponds to given
   /// C type (used for clang++ emulation of g++ behaviour)
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index fce60d2566787..8f3d4f803810f 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -437,6 +437,13 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL,
   return FinalPhase;
 }
 
+void Driver::updateFinalPhase(Compilation &C,
+                              llvm::ArrayRef<InputTy> Inputs) const {
+  Arg *FinalPhaseArg = nullptr;
+  phases ::ID FinalPhase = getFinalPhase(C.getArgs(), Inputs, &FinalPhaseArg);
+  C.setFinalPhase(FinalPhase, FinalPhaseArg);
+}
+
 llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
 Driver::executeProgram(llvm::ArrayRef<llvm::StringRef> Args) const {
   llvm::SmallString<64> OutputFile;
@@ -1873,15 +1880,17 @@ Compilation *Driver::BuildCompilation(ArrayRef<const 
char *> ArgList) {
   // Construct the list of inputs.
   InputList Inputs;
   BuildInputs(C->getDefaultToolChain(), *TranslatedArgs, Inputs);
-       C->FinalPhase  = getFinalPhase(*TranslatedArgs, Inputs, 
&C->FinalPhaseArg) ;
-       auto FinalPhase = C->FinalPhase;
-  if (HasConfigFileTail && Inputs.size()) {    
-    if (FinalPhase==
-        phases::Link) {
+  updateFinalPhase(*C, Inputs);
+  phases::ID FinalPhase = C->getFinalPhase();
+
+  if (HasConfigFileTail && Inputs.size()) {
+    if (FinalPhase == phases::Link) {
       DerivedArgList TranslatedLinkerIns(*CfgOptionsTail);
       for (Arg *A : *CfgOptionsTail)
         TranslatedLinkerIns.append(A);
       BuildInputs(C->getDefaultToolChain(), TranslatedLinkerIns, Inputs);
+      updateFinalPhase(*C, Inputs);
+      FinalPhase = C->getFinalPhase();
     }
   }
 
@@ -2149,6 +2158,7 @@ void Driver::generateCompilationDiagnostics(
   // Construct the list of inputs.
   InputList Inputs;
   BuildInputs(C.getDefaultToolChain(), C.getArgs(), Inputs);
+  updateFinalPhase(C, Inputs);
 
   ArgStringList IRInputs;
   for (InputList::iterator it = Inputs.begin(), ie = Inputs.end(); it != ie;) {
@@ -3461,9 +3471,10 @@ void Driver::handleArguments(Compilation &C, 
DerivedArgList &Args,
     YcArg = nullptr;
   }
 
+  phases::ID FinalPhase = C.getFinalPhase();
+  llvm::opt::Arg *FinalPhaseArg = C.getFinalPhaseArg();
 
-
-  if (C.FinalPhase == phases::Link) {
+  if (FinalPhase == phases::Link) {
     if (Args.hasArgNoClaim(options::OPT_hipstdpar)) {
       Args.AddFlagArg(nullptr, getOpts().getOption(options::OPT_hip_link));
       Args.AddFlagArg(nullptr,
@@ -3498,7 +3509,7 @@ void Driver::handleArguments(Compilation &C, 
DerivedArgList &Args,
     }
   }
 
-  if (C.FinalPhase == phases::Preprocess || 
Args.hasArg(options::OPT__SLASH_Y_)) {
+  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.
@@ -3516,7 +3527,7 @@ void Driver::handleArguments(Compilation &C, 
DerivedArgList &Args,
     Args.eraseArg(options::OPT_include_pch);
   }
 
-  bool LinkOnly = phases::Link == C.FinalPhase && Inputs.size() > 0;
+  bool LinkOnly = phases::Link == FinalPhase && Inputs.size() > 0;
   for (auto &I : Inputs) {
     types::ID InputType = I.first;
     const Arg *InputArg = I.second;
@@ -3528,7 +3539,7 @@ void Driver::handleArguments(Compilation &C, 
DerivedArgList &Args,
 
     // If the first step comes after the final phase we are doing as part of
     // this compilation, warn the user about it.
-    if (InitialPhase > C.FinalPhase) {
+    if (InitialPhase > FinalPhase) {
       if (InputArg->isClaimed())
         continue;
 
@@ -3553,19 +3564,19 @@ void Driver::handleArguments(Compilation &C, 
DerivedArgList &Args,
                 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) << !!C.FinalPhaseArg
-            << (C.FinalPhaseArg ? C.FinalPhaseArg->getOption().getName() : "");
+            << InputArg->getAsString(Args) << !!FinalPhaseArg
+            << (FinalPhaseArg ? FinalPhaseArg->getOption().getName() : "");
       else
         Diag(clang::diag::warn_drv_input_file_unused)
             << InputArg->getAsString(Args) << getPhaseName(InitialPhase)
-            << !C.FinalPhaseArg
-            << (C.FinalPhaseArg ? C.FinalPhaseArg->getSpelling() : "");
+            << !!FinalPhaseArg
+            << (FinalPhaseArg ? FinalPhaseArg->getSpelling() : "");
       continue;
     }
 
     if (YcArg) {
       // Add a separate precompile phase for the compile phase.
-      if (C.FinalPhase >= phases::Compile) {
+      if (FinalPhase >= phases::Compile) {
         const types::ID HeaderType = lookupHeaderTypeForSourceType(InputType);
         // Build the pipeline for the pch file.
         Action *ClangClPch = C.MakeAction<InputAction>(*InputArg, HeaderType);
@@ -3636,12 +3647,12 @@ void Driver::BuildActions(Compilation &C, 
DerivedArgList &Args,
   Args.ClaimAllArgs(options::OPT_no_offload_new_driver);
   Args.ClaimAllArgs(options::OPT_offload_new_driver);
 
+  phases::ID FinalPhase = C.getFinalPhase();
   bool HIPRDCDeviceOnlyFatBin =
       C.isOffloadingHostKind(Action::OFK_HIP) && offloadDeviceOnly() &&
       Args.hasArg(options::OPT_hip_link) &&
       Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false) &&
-     C.FinalPhase == phases::Link &&
-      !Args.hasArg(options::OPT_emit_llvm) &&
+      FinalPhase == phases::Link && !Args.hasArg(options::OPT_emit_llvm) &&
       Args.hasFlag(options::OPT_gpu_bundle_output,
                    options::OPT_no_gpu_bundle_output, true);
 
@@ -3654,7 +3665,8 @@ void Driver::BuildActions(Compilation &C, DerivedArgList 
&Args,
     types::ID InputType = I.first;
     const Arg *InputArg = I.second;
 
-    auto PL = types::getCompilationPhases(*this, Args, Inputs, InputType, 
C.FinalPhase);
+    auto PL =
+        types::getCompilationPhases(*this, Args, Inputs, InputType, 
FinalPhase);
     if (PL.empty())
       continue;
 
@@ -4152,7 +4164,7 @@ Driver::BuildOffloadingActions(Compilation &C, 
llvm::opt::DerivedArgList &Args,
   // Don't build offloading actions if we do not have a compile action. If
   // preprocessing only ignore embedding.
   if (!(isa<CompileJobAction>(HostAction) ||
-        C.FinalPhase == phases::Preprocess))
+        C.getFinalPhase() == phases::Preprocess))
     return HostAction;
 
   bool UsesLLVMOffloading = Args.hasArg(
@@ -4205,7 +4217,8 @@ Driver::BuildOffloadingActions(Compilation &C, 
llvm::opt::DerivedArgList &Args,
             .isOSDarwin())
       HostAction->setCannotBeCollapsedWithNextDependentAction();
 
-    auto PL = types::getCompilationPhases(*this, Args, {Input}, InputType, 
C.FinalPhase);
+    auto PL = types::getCompilationPhases(*this, Args, {Input}, InputType,
+                                          C.getFinalPhase());
 
     for (phases::ID Phase : PL) {
       if (Phase == phases::Link) {
diff --git a/clang/lib/Driver/Types.cpp b/clang/lib/Driver/Types.cpp
index 11292d9240877..e04d3c9a05ace 100644
--- a/clang/lib/Driver/Types.cpp
+++ b/clang/lib/Driver/Types.cpp
@@ -430,7 +430,8 @@ types::getCompilationPhases(ID Id, phases::ID LastPhase) {
 llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases>
 types::getCompilationPhases(const clang::driver::Driver &Driver,
                             llvm::opt::DerivedArgList &DAL,
-                            llvm::ArrayRef<InputTy> Inputs, ID Id, phases::ID 
FinalPhase) {
+                            llvm::ArrayRef<InputTy> Inputs, ID Id,
+                            phases::ID FinalPhase) {
   return types::getCompilationPhases(Id, FinalPhase);
 }
 
diff --git a/clang/test/Driver/aix-ld.c b/clang/test/Driver/aix-ld.c
index 641908afc8d98..bedd224eeca9c 100644
--- a/clang/test/Driver/aix-ld.c
+++ b/clang/test/Driver/aix-ld.c
@@ -1171,4 +1171,4 @@
 // RUN:        -K \
 // RUN:        -c \
 // RUN:   | FileCheck --check-prefixes=CHECK-K-UNUSED %s
-// CHECK-K-UNUSED: clang: warning: -K: 'linker' input unused when '-c' is 
present [-Wunused-command-line-argument]
+// CHECK-K-UNUSED: clang: warning: -K: 'linker' input unused 
[-Wunused-command-line-argument]
diff --git a/clang/test/Driver/pch-inputs.h b/clang/test/Driver/pch-inputs.h
index fa6f94f996915..a1108e7bba40d 100644
--- a/clang/test/Driver/pch-inputs.h
+++ b/clang/test/Driver/pch-inputs.h
@@ -4,10 +4,10 @@
 // Warn about linker options being ignored when not linking
 // RUN: %clang %s -lfoo -o %t/tmp1.pch -### 2>&1 | FileCheck %s 
--check-prefix=UNUSED-L,SINGLEHEADER
 // RUN: %clang %s -x c++-header -lfoo -o %t/tmp1.pch -### 2>&1 | FileCheck %s 
--check-prefix=UNUSED-L,SINGLEHEADER
-// UNUSED-L: clang: warning: -lfoo: 'linker' input unused 
[-Wunused-command-line-argument]
+// UNUSED-L: clang: warning: -lfoo: 'linker' input unused when '' is present 
[-Wunused-command-line-argument]
 
 // RUN: %clang %s -Wl,--whole-archive -o %t/tmp1.pch -### 2>&1 | FileCheck %s 
--check-prefix=UNUSED-WL,SINGLEHEADER
-// UNUSED-WL: clang: warning: -Wl,--whole-archive: 'linker' input unused 
[-Wunused-command-line-argument]
+// UNUSED-WL: clang: warning: -Wl,--whole-archive: 'linker' input unused when 
'' is present [-Wunused-command-line-argument]
 
 // RUN: %clang %S/Inputs/header1.h %S/Inputs/header2.h -lfoo -### 2>&1 | 
FileCheck %s --check-prefix=UNUSED-L,MULTIHEADER
 
@@ -23,7 +23,7 @@
 // RUN: %clang -x cl-header %s -Xlinker -somelinkerflag -### 2>&1 | FileCheck 
%s --check-prefix=UNUSED-XLINKER
 // RUN: %clang -x objective-c++-header %s -Xlinker -somelinkerflag -### 2>&1 | 
FileCheck %s --check-prefix=UNUSED-XLINKER
 // RUN: %clang -x hlsl %s -Xlinker -somelinkerflag -### 2>&1 | FileCheck %s 
--check-prefix=UNUSED-XLINKER
-// UNUSED-XLINKER: clang: warning: -Xlinker -somelinkerflag: 'linker' input 
unused [-Wunused-command-line-argument]
+// UNUSED-XLINKER: clang: warning: -Xlinker -somelinkerflag: 'linker' input 
unused when '' is present [-Wunused-command-line-argument]
 
 
 // Normal case: Single header file input compiles to .pch even without 
--precompile
@@ -44,5 +44,3 @@
 // MULTIHEADER: "-emit-pch"
 // MULTIHEADER: "-o"
 // MULTIHEADER: header2.h.pch"
-
-

>From c7d46dc90faa9929b370169374516d035c9a975f Mon Sep 17 00:00:00 2001
From: Michael Kruse <[email protected]>
Date: Wed, 23 Sep 2026 12:49:04 +0200
Subject: [PATCH 4/5] clang-format

---
 clang/lib/Driver/Driver.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 8f3d4f803810f..cba622553a3f3 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -440,7 +440,7 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL,
 void Driver::updateFinalPhase(Compilation &C,
                               llvm::ArrayRef<InputTy> Inputs) const {
   Arg *FinalPhaseArg = nullptr;
-  phases ::ID FinalPhase = getFinalPhase(C.getArgs(), Inputs, &FinalPhaseArg);
+  phases::ID FinalPhase = getFinalPhase(C.getArgs(), Inputs, &FinalPhaseArg);
   C.setFinalPhase(FinalPhase, FinalPhaseArg);
 }
 

>From 89dfc3118f61980986669a0eeab7501b74f23e4b Mon Sep 17 00:00:00 2001
From: Michael Kruse <[email protected]>
Date: Thu, 24 Sep 2026 00:55:07 +0200
Subject: [PATCH 5/5] address review by @MaskRay

---
 clang/test/Driver/pch-inputs.h | 32 ++++++++++++++++----------------
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/clang/test/Driver/pch-inputs.h b/clang/test/Driver/pch-inputs.h
index a1108e7bba40d..a1f9f4ea4f7a9 100644
--- a/clang/test/Driver/pch-inputs.h
+++ b/clang/test/Driver/pch-inputs.h
@@ -4,17 +4,17 @@
 // Warn about linker options being ignored when not linking
 // RUN: %clang %s -lfoo -o %t/tmp1.pch -### 2>&1 | FileCheck %s 
--check-prefix=UNUSED-L,SINGLEHEADER
 // RUN: %clang %s -x c++-header -lfoo -o %t/tmp1.pch -### 2>&1 | FileCheck %s 
--check-prefix=UNUSED-L,SINGLEHEADER
-// UNUSED-L: clang: warning: -lfoo: 'linker' input unused when '' is present 
[-Wunused-command-line-argument]
+// UNUSED-L: warning: -lfoo: 'linker' input unused when '' is present 
[-Wunused-command-line-argument]
 
 // RUN: %clang %s -Wl,--whole-archive -o %t/tmp1.pch -### 2>&1 | FileCheck %s 
--check-prefix=UNUSED-WL,SINGLEHEADER
-// UNUSED-WL: clang: warning: -Wl,--whole-archive: 'linker' input unused when 
'' is present [-Wunused-command-line-argument]
+// UNUSED-WL: warning: -Wl,--whole-archive: 'linker' input unused when '' is 
present [-Wunused-command-line-argument]
 
 // RUN: %clang %S/Inputs/header1.h %S/Inputs/header2.h -lfoo -### 2>&1 | 
FileCheck %s --check-prefix=UNUSED-L,MULTIHEADER
 
 
 // Error with single -o when there are multiple output files
 // RUN: not %clang %S/Inputs/header1.h %S/Inputs/header2.h -lfoo -o 
%t/tmp2.pch -### 2>&1 | FileCheck %s --check-prefix=UNUSED-L,MULTIOUTPUT
-// MULTIOUTPUT: clang: error: cannot specify -o when generating multiple 
output files
+// MULTIOUTPUT: error: cannot specify -o when generating multiple output files
 
 // An actual linker input file (object0.o) triggers an error, not a warning
 // RUN: not %clang %s %S/Inputs/object0.o -o %t/tmp3.pch -### 2>&1 | FileCheck 
%s --check-prefix=MULTIOUTPUT
@@ -23,24 +23,24 @@
 // RUN: %clang -x cl-header %s -Xlinker -somelinkerflag -### 2>&1 | FileCheck 
%s --check-prefix=UNUSED-XLINKER
 // RUN: %clang -x objective-c++-header %s -Xlinker -somelinkerflag -### 2>&1 | 
FileCheck %s --check-prefix=UNUSED-XLINKER
 // RUN: %clang -x hlsl %s -Xlinker -somelinkerflag -### 2>&1 | FileCheck %s 
--check-prefix=UNUSED-XLINKER
-// UNUSED-XLINKER: clang: warning: -Xlinker -somelinkerflag: 'linker' input 
unused when '' is present [-Wunused-command-line-argument]
+// UNUSED-XLINKER: warning: -Xlinker -somelinkerflag: 'linker' input unused 
when '' is present [-Wunused-command-line-argument]
 
 
 // Normal case: Single header file input compiles to .pch even without 
--precompile
 // RUN: %clang %s -o %t/tmp1.pch -### 2>&1 | FileCheck %s 
--check-prefix=SINGLEHEADER
-// SINGLEHEADER: "-cc1"
-// SINGLEHEADER: "-emit-pch"
-// SINGLEHEADER: "-o"
-// SINGLEHEADER: tmp1.pch"
+// SINGLEHEADER:      "-cc1"
+// SINGLEHEADER-SAME: "-emit-pch"
+// SINGLEHEADER-SAME: "-o"
+// SINGLEHEADER-SAME: tmp1.pch"
 
 
 // Multiple header files input compiles to one .pch each even without 
--precompile
 // RUN: %clang %S/Inputs/header1.h %S/Inputs/header2.h -### 2>&1 | FileCheck 
%s --check-prefix=MULTIHEADER
-// MULTIHEADER: "-cc1"
-// MULTIHEADER: "-emit-pch"
-// MULTIHEADER: "-o"
-// MULTIHEADER: header1.h.pch"
-// MULTIHEADER: "-cc1"
-// MULTIHEADER: "-emit-pch"
-// MULTIHEADER: "-o"
-// MULTIHEADER: header2.h.pch"
+// MULTIHEADER:      "-cc1"
+// MULTIHEADER-SAME: "-emit-pch"
+// MULTIHEADER-SAME: "-o"
+// MULTIHEADER-SAME: header1.h.pch"
+// MULTIHEADER:      "-cc1"
+// MULTIHEADER-SAME: "-emit-pch"
+// MULTIHEADER-SAME: "-o"
+// MULTIHEADER-SAME: header2.h.pch"

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to