[clang] [Clang][Driver] Ignore -fembed-bitcode for fat LTO (PR #235308)

Fangcao Wang via cfe-commits cfe-commits at lists.llvm.org
Sun Oct 25 18:57:51 PDT 2026


https://github.com/LittleMeepo updated https://github.com/llvm/llvm-project/pull/235308

>From 42bea8c9922989df853dee12d624eda737638ad7 Mon Sep 17 00:00:00 2001
From: Fangcao Wang <wangfangcao1 at huawei.com>
Date: Sat, 24 Oct 2026 21:53:29 +0800
Subject: [PATCH] [Clang][Driver] Ignore -fembed-bitcode for fat LTO

The driver already omits -fembed-bitcode (including its =all, =bitcode
and =marker forms) from cc1 commands for ordinary LTO. With fat LTO,
however, an AssembleJobAction forwards the option through
CollectArgsForIntegratedAssembler. This causes bitcode to be embedded
before the fat LTO pipeline's EmbedBitcodePass runs, which then reports
"Can only embed the module once".

For example:
  clang -flto -ffat-lto-objects -fembed-bitcode -c repro.c

Add a bool IsUsingLTO parameter to CollectArgsForIntegratedAssembler
and skip forwarding the embedding option when LTO is enabled. This
makes fat LTO silently ignore the option, matching ordinary LTO.
ClangAs::ConstructJob passes false because standalone assembler jobs
do not perform LTO.

Fixes #88041.
---
 clang/lib/Driver/ToolChains/Clang.cpp | 14 ++++++++------
 clang/test/Driver/embed-bitcode.c     | 12 ++++++++++++
 2 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 5a1c8531812bd3..52429772f306c8 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -2602,7 +2602,8 @@ static void AddARMImplicitITArgs(const ArgList &Args, ArgStringList &CmdArgs,
 static void CollectArgsForIntegratedAssembler(Compilation &C,
                                               const ArgList &Args,
                                               ArgStringList &CmdArgs,
-                                              const Driver &D) {
+                                              const Driver &D,
+                                              bool IsUsingLTO) {
   // Default to -mno-relax-all.
   //
   // Note: RISC-V requires an indirect jump for offsets larger than 1MiB. This
@@ -2953,9 +2954,9 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
     CmdArgs.push_back(Feature);
   }
 
-  // forward -fembed-bitcode to assmebler
-  if (C.getDriver().embedBitcodeEnabled() ||
-      C.getDriver().embedBitcodeMarkerOnly())
+  // LTO handles bitcode emission, including embedding it in fat objects.
+  if (!IsUsingLTO && (C.getDriver().embedBitcodeEnabled() ||
+                      C.getDriver().embedBitcodeMarkerOnly()))
     Args.AddLastArg(CmdArgs, options::OPT_fembed_bitcode_EQ);
 
   if (const char *AsSecureLogFile = getenv("AS_SECURE_LOG_FILE")) {
@@ -5546,7 +5547,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
   } else if (isa<AssembleJobAction>(JA)) {
     CmdArgs.push_back("-emit-obj");
 
-    CollectArgsForIntegratedAssembler(C, Args, CmdArgs, D);
+    CollectArgsForIntegratedAssembler(C, Args, CmdArgs, D, IsUsingLTO);
 
     // Also ignore explicit -force_cpusubtype_ALL option.
     (void)Args.hasArg(options::OPT_force__cpusubtype__ALL);
@@ -9553,7 +9554,8 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
   Args.ClaimAllArgs(options::OPT_W_Group);
 
   CollectArgsForIntegratedAssembler(C, Args, CmdArgs,
-                                    getToolChain().getDriver());
+                                    getToolChain().getDriver(),
+                                    /*IsUsingLTO=*/false);
 
   // Forward -Xclangas arguments to -cc1as
   for (auto Arg : Args.filtered(options::OPT_Xclangas)) {
diff --git a/clang/test/Driver/embed-bitcode.c b/clang/test/Driver/embed-bitcode.c
index a2987dc4e22732..98bb7692033904 100644
--- a/clang/test/Driver/embed-bitcode.c
+++ b/clang/test/Driver/embed-bitcode.c
@@ -34,6 +34,18 @@
 // CHECK-LTO-NOT: warning: argument unused during compilation: '-fembed-bitcode'
 // CHECK-LTO-NOT: -cc1
 // CHECK-LTO-NOT: -fembed-bitcode=all
+
+// RUN: %clang --target=x86_64-unknown-linux-gnu -c %s -flto -ffat-lto-objects -fembed-bitcode -### 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=CHECK-FAT-LTO --implicit-check-not=-fembed-bitcode
+// RUN: %clang --target=x86_64-unknown-linux-gnu -c %s -flto=full -ffat-lto-objects -fembed-bitcode -### 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=CHECK-FAT-LTO --implicit-check-not=-fembed-bitcode
+// RUN: %clang --target=x86_64-unknown-linux-gnu -c %s -flto=thin -ffat-lto-objects -fembed-bitcode -### 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=CHECK-FAT-LTO --implicit-check-not=-fembed-bitcode
+// CHECK-FAT-LTO: "-cc1"
+// CHECK-FAT-LTO-SAME: "-emit-obj"
+// CHECK-FAT-LTO-SAME: "-flto={{full|thin}}"
+// CHECK-FAT-LTO-SAME: "-ffat-lto-objects"
+
 // RUN: touch %t.o
 // RUN: %clang  -target armv7-apple-darwin -miphoneos-version-min=6.0 %t.o -fembed-bitcode  -fembed-bitcode-marker -mlinker-version=277  2>&1 -### | FileCheck %s -check-prefix=CHECK-LTO-MARKER-277
 // RUN: %clang  -target armv7-apple-darwin -miphoneos-version-min=6.0 %t.o -fembed-bitcode  -fembed-bitcode-marker -mlinker-version=278  2>&1 -### | FileCheck %s -check-prefix=CHECK-LTO-MARKER-278



More information about the cfe-commits mailing list