https://github.com/estewart08 updated 
https://github.com/llvm/llvm-project/pull/213164

>From 54b8a2a7df65d27415aa4125e2d93d13069c2df0 Mon Sep 17 00:00:00 2001
From: Ethan Stewart <[email protected]>
Date: Mon, 27 Jul 2026 15:24:46 -0500
Subject: [PATCH] [clang][Driver] - Set FinalPhase to Precompile for PCH

Currently, a PCH compilation without --precompile, -c, or -S will
have a link FinalPhase. If there happens to be a linker flag present
on a precompiled header compilation then clang will output an error:
clang -x c++-header test.h -lm -o test.h.pch
clang: error: cannot specify -o when generating multiple output files

The Driver should be smart enough to ignore the flags.
This is done by checking for TY_PCH and setting the FinalPhase
to phases::Precompile.

This was originaly noticed when a clang config file had some
linker flags. I have included that case in the lit test as well.

Assisted-by: AI for initial diagnosis/recommendations (Claude Opus 4.8)
---
 clang/lib/Driver/Driver.cpp                   | 15 ++++++++++++++-
 clang/test/Driver/pch-ignore-linker-flags.cpp | 13 +++++++++++++
 2 files changed, 27 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/Driver/pch-ignore-linker-flags.cpp

diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 38795f7c2ae7a..ca1c9bef997c6 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -358,6 +358,11 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL,
   Arg *PhaseArg = nullptr;
   phases::ID FinalPhase;
 
+  // Collect -x for PCH check below
+  Arg *XArg = DAL.getLastArg(options::OPT_x);
+  types::ID XTy = XArg ? types::lookupTypeForTypeSpecifier(XArg->getValue())
+                       : types::TY_INVALID;
+
   // -{E,EP,P,M,MM} only run the preprocessor.
   if (CCCIsCPP() || (PhaseArg = DAL.getLastArg(options::OPT_E)) ||
       (PhaseArg = DAL.getLastArg(options::OPT__SLASH_EP)) ||
@@ -376,6 +381,7 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL,
              (PhaseArg = DAL.getLastArg(options::OPT_fmodule_header,
                                         options::OPT_fmodule_header_EQ))) {
     FinalPhase = phases::Precompile;
+
     // -{fsyntax-only,-analyze,emit-ast} only run up to the compiler.
   } else if ((PhaseArg = DAL.getLastArg(options::OPT_fsyntax_only)) ||
              (PhaseArg = DAL.getLastArg(options::OPT_print_supported_cpus)) ||
@@ -401,7 +407,14 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL,
   } else if ((PhaseArg = DAL.getLastArg(options::OPT_emit_interface_stubs))) {
     FinalPhase = phases::IfsMerge;
 
-  // Otherwise do everything.
+    // PCH compilation (with no -c/-S/--precompile) should not have a
+    // link final phase
+  } else if (XArg && XTy != types::TY_INVALID &&
+             types::getPrecompiledType(XTy) == types::TY_PCH) {
+    PhaseArg = XArg;
+    FinalPhase = phases::Precompile;
+
+    // Otherwise do everything.
   } else
     FinalPhase = phases::Link;
 
diff --git a/clang/test/Driver/pch-ignore-linker-flags.cpp 
b/clang/test/Driver/pch-ignore-linker-flags.cpp
new file mode 100644
index 0000000000000..4964e2239aa38
--- /dev/null
+++ b/clang/test/Driver/pch-ignore-linker-flags.cpp
@@ -0,0 +1,13 @@
+// // RUN: rm -rf %t
+// // RUN: mkdir -p %t
+//
+// // Create PCH and ignore linker flags.
+// // RUN: %clang -x c++-header %S/Inputs/pchfile.h -lm -o %t/pchfile.h.pch 
-### 2>&1 | FileCheck %s -check-prefix=CHECK-IGNORE-LINK-FLAGS,CHECK-EMIT-PCH
+// // RUN: %clang -x c++-header %S/Inputs/pchfile.h -lm -### 2>&1 | FileCheck 
%s -check-prefix=CHECK-IGNORE-LINK-FLAGS,CHECK-EMIT-PCH
+// // RUN: %clang --config %S/Inputs/config-l.cfg -x c++-header 
%S/Inputs/pchfile.h -o %t/pchfile.h.pch -### 2>&1 | FileCheck %s 
-check-prefix=CHECK-IGNORE-LINK-FLAGS-CFG,CHECK-EMIT-PCH
+//
+// // CHECK-IGNORE-LINK-FLAGS: warning: -lm: 'linker' input unused
+// // CHECK-IGNORE-LINK-FLAGS-NOT: clang: error: cannot specify -o when 
generating multiple output files
+// // CHECK-EMIT-PCH: -emit-pch
+// // CHECK-IGNORE-LINK-FLAGS-CFG: -Wall
+// // CHECK-IGNORE-LINK-FLAGS-CFG-NOT: -lm --as-needed -Bstatic -lhappy 
-Bdynamic

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

Reply via email to