https://github.com/frobtech updated 
https://github.com/llvm/llvm-project/pull/236027

>From 13c174de0e0855d32b05fa2bfada27b62465db32 Mon Sep 17 00:00:00 2001
From: Roland McGrath <[email protected]>
Date: Tue, 27 Oct 2026 00:48:42 -0700
Subject: [PATCH 1/2] [clang][Driver] Set *LinkerIsLLD for all LLD linker paths
 in GetLinkerPath

ToolChain::GetLinkerPath(bool *LinkerIsLLD) previously only set
*LinkerIsLLD when -fuse-ld=lld (or CLANG_DEFAULT_LINKER=lld) was used
with a relative linker name or --ld-path=. It left *LinkerIsLLD false
when the toolchain's default linker is ld.lld (such as on Fuchsia,
FreeBSD, Android, Haiku, SerenityOS, Hexagon musl, or AMDGPU), when
--ld-path= or an absolute -fuse-ld= path pointed to an ld.lld or
ld64.lld binary without -fuse-ld=lld, or when falling back to a default
ld.lld linker. Conversely, when CLANG_DEFAULT_LINKER=lld was configured,
passing --ld-path= with a non-LLD linker (such as ld.bfd) without an
explicit -fuse-ld= option erroneously set *LinkerIsLLD to true.

Check whether the resolved linker filename matches ld.lld (or ld64.lld
on Darwin), including versioned (ld.lld-<ver>) and target-prefixed
(<triple>-ld.lld) names, across all code paths in GetLinkerPath. When
--ld-path= is specified, only treat -fuse-ld=lld as overriding the path
check when -fuse-ld=lld was explicitly passed on the command line.

This also allows removing the duplicate linker filename checks in
Hexagon's constructHexagonLinkArgs and tools::addLTOOptions.

Assisted-by: Gemini
---
 clang/lib/Driver/ToolChain.cpp             | 50 ++++++++++++++--------
 clang/lib/Driver/ToolChains/CommonArgs.cpp |  8 ++--
 clang/lib/Driver/ToolChains/Hexagon.cpp    |  6 +--
 clang/test/Driver/darwin-ld-demangle-lld.c | 15 ++++++-
 clang/test/Driver/fat-lto-objects.c        |  4 ++
 5 files changed, 56 insertions(+), 27 deletions(-)

diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index b3e7043a64fe56..7ffbf6f5911381 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -1310,9 +1310,26 @@ std::string ToolChain::GetLinkerPath(bool *LinkerIsLLD) 
const {
   if (LinkerIsLLD)
     *LinkerIsLLD = false;
 
+  auto IsLLDPath = [&](StringRef Path) {
+    StringRef Name = llvm::sys::path::filename(Path);
+    Name.consume_back_insensitive(".exe");
+    StringRef LLDName = Triple.isOSDarwin() ? "ld64.lld" : "ld.lld";
+    return Name.starts_with_insensitive(LLDName) ||
+           Name.ends_with_insensitive(LLDName);
+  };
+
+  auto GetDefaultLinkerPath = [&]() {
+    const char *DefaultLinker = getDefaultLinker();
+    if (LinkerIsLLD)
+      *LinkerIsLLD = IsLLDPath(DefaultLinker);
+    if (llvm::sys::path::is_absolute(DefaultLinker))
+      return std::string(DefaultLinker);
+    return GetProgramPath(DefaultLinker);
+  };
+
   // Get -fuse-ld= first to prevent -Wunused-command-line-argument. -fuse-ld= 
is
   // considered as the linker flavor, e.g. "bfd", "gold", or "lld".
-  const Arg* A = Args.getLastArg(options::OPT_fuse_ld_EQ);
+  const Arg *A = Args.getLastArg(options::OPT_fuse_ld_EQ);
   StringRef UseLinker = A ? A->getValue() : getDriver().getPreferredLinker();
 
   // --ld-path= takes precedence over -fuse-ld= and specifies the executable
@@ -1320,29 +1337,25 @@ std::string ToolChain::GetLinkerPath(bool *LinkerIsLLD) 
const {
   // contain a path component separator.
   // -fuse-ld=lld can be used with --ld-path= to inform clang that the binary
   // that --ld-path= points to is lld.
-  if (const Arg *A = Args.getLastArg(options::OPT_ld_path_EQ)) {
-    std::string Path(A->getValue());
+  if (const Arg *LdPathArg = Args.getLastArg(options::OPT_ld_path_EQ)) {
+    std::string Path(LdPathArg->getValue());
     if (!Path.empty()) {
       if (llvm::sys::path::parent_path(Path).empty())
-        Path = GetProgramPath(A->getValue());
+        Path = GetProgramPath(LdPathArg->getValue());
       if (llvm::sys::fs::can_execute(Path)) {
         if (LinkerIsLLD)
-          *LinkerIsLLD = UseLinker == "lld";
-        return std::string(Path);
+          *LinkerIsLLD = (A && UseLinker == "lld") || IsLLDPath(Path);
+        return Path;
       }
     }
-    getDriver().Diag(diag::err_drv_invalid_linker_name) << 
A->getAsString(Args);
-    return GetProgramPath(getDefaultLinker());
+    getDriver().Diag(diag::err_drv_invalid_linker_name)
+        << LdPathArg->getAsString(Args);
+    return GetDefaultLinkerPath();
   }
   // If we're passed -fuse-ld= with no argument, or with the argument ld,
   // then use whatever the default system linker is.
-  if (UseLinker.empty() || UseLinker == "ld") {
-    const char *DefaultLinker = getDefaultLinker();
-    if (llvm::sys::path::is_absolute(DefaultLinker))
-      return std::string(DefaultLinker);
-    else
-      return GetProgramPath(DefaultLinker);
-  }
+  if (UseLinker.empty() || UseLinker == "ld")
+    return GetDefaultLinkerPath();
 
   // Extending -fuse-ld= to an absolute or relative path is unexpected. 
Checking
   // for the linker flavor is brittle. In addition, prepending "ld." or "ld64."
@@ -1354,8 +1367,11 @@ std::string ToolChain::GetLinkerPath(bool *LinkerIsLLD) 
const {
   if (llvm::sys::path::is_absolute(UseLinker)) {
     // If we're passed what looks like an absolute path, don't attempt to
     // second-guess that.
-    if (llvm::sys::fs::can_execute(UseLinker))
+    if (llvm::sys::fs::can_execute(UseLinker)) {
+      if (LinkerIsLLD)
+        *LinkerIsLLD = IsLLDPath(UseLinker);
       return std::string(UseLinker);
+    }
   } else {
     llvm::SmallString<8> LinkerName;
     if (Triple.isOSDarwin())
@@ -1375,7 +1391,7 @@ std::string ToolChain::GetLinkerPath(bool *LinkerIsLLD) 
const {
   if (A)
     getDriver().Diag(diag::err_drv_invalid_linker_name) << 
A->getAsString(Args);
 
-  return GetProgramPath(getDefaultLinker());
+  return GetDefaultLinkerPath();
 }
 
 std::string ToolChain::GetStaticLibToolPath() const {
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp 
b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 39dcec2f823bdd..cdee3823945f63 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -1059,7 +1059,8 @@ void tools::addLTOOptions(const ToolChain &ToolChain, 
const ArgList &Args,
   const bool IsOSAIX = Triple.isOSAIX();
   const bool IsAMDGCN = Triple.isAMDGCN();
   StringRef Linker = Args.getLastArgValue(options::OPT_fuse_ld_EQ);
-  const char *LinkerPath = Args.MakeArgString(ToolChain.GetLinkerPath());
+  bool LinkerIsLLD = false;
+  (void)ToolChain.GetLinkerPath(&LinkerIsLLD);
   const Driver &D = ToolChain.getDriver();
   const bool IsFatLTO = Args.hasFlag(options::OPT_ffat_lto_objects,
                                      options::OPT_fno_fat_lto_objects, false);
@@ -1075,9 +1076,8 @@ void tools::addLTOOptions(const ToolChain &ToolChain, 
const ArgList &Args,
     Input = Inputs.begin();
   }
 
-  if (Linker != "lld" && Linker != "lld-link" &&
-      llvm::sys::path::filename(LinkerPath) != "ld.lld" &&
-      llvm::sys::path::stem(LinkerPath) != "ld.lld" && !Triple.isOSOpenBSD()) {
+  if (!LinkerIsLLD && Linker != "lld" && Linker != "lld-link" &&
+      !Triple.isOSOpenBSD()) {
     // Tell the linker to load the plugin. This has to come before
     // AddLinkerInputs as gold requires -plugin and AIX ld requires -bplugin to
     // come before any -plugin-opt/-bplugin_opt that -Wl might forward.
diff --git a/clang/lib/Driver/ToolChains/Hexagon.cpp 
b/clang/lib/Driver/ToolChains/Hexagon.cpp
index 9c823a847d6e33..6e9b23849f61ab 100644
--- a/clang/lib/Driver/ToolChains/Hexagon.cpp
+++ b/clang/lib/Driver/ToolChains/Hexagon.cpp
@@ -301,11 +301,7 @@ constructHexagonLinkArgs(Compilation &C, const JobAction 
&JA,
   bool IncStartFiles = !Args.hasArg(options::OPT_nostartfiles);
   bool IncDefLibs = !Args.hasArg(options::OPT_nodefaultlibs);
   bool UseLLD = false;
-  const char *Exec = Args.MakeArgString(HTC.GetLinkerPath(&UseLLD));
-  StringRef LinkerName = llvm::sys::path::filename(Exec);
-  UseLLD = UseLLD || LinkerName.starts_with("ld.lld") ||
-           LinkerName.ends_with("ld.lld") ||
-           llvm::sys::path::stem(Exec).ends_with("ld.lld");
+  (void)HTC.GetLinkerPath(&UseLLD);
   bool UseShared = IsShared && !IsStatic;
   StringRef CpuVer = toolchains::HexagonToolChain::GetTargetCPUVersion(Args);
 
diff --git a/clang/test/Driver/darwin-ld-demangle-lld.c 
b/clang/test/Driver/darwin-ld-demangle-lld.c
index 4edeb1058b933f..592ca2374bf644 100644
--- a/clang/test/Driver/darwin-ld-demangle-lld.c
+++ b/clang/test/Driver/darwin-ld-demangle-lld.c
@@ -1,4 +1,4 @@
-// With -fuse-ld=lld, -demangle is always passed to the linker on Darwin.
+// With LLD, -demangle is always passed to the linker on Darwin.
 
 // RUN: %clang --target=x86_64-apple-darwin -### -fuse-ld=lld \
 // RUN:   -B%S/Inputs/lld -mlinker-version=0 %s 2>&1 \
@@ -8,4 +8,17 @@
 // RUN:   --ld-path=%S/Inputs/lld/ld64.lld -mlinker-version=0 %s 2>&1 \
 // RUN:   | FileCheck %s
 
+// RUN: %clang --target=x86_64-apple-darwin -### \
+// RUN:   --ld-path=%S/Inputs/lld/ld64.lld -mlinker-version=0 %s 2>&1 \
+// RUN:   | FileCheck %s
+
+// RUN: %clang --target=x86_64-apple-darwin -### -Wno-fuse-ld-path \
+// RUN:   -fuse-ld=%S/Inputs/lld/ld64.lld -mlinker-version=0 %s 2>&1 \
+// RUN:   | FileCheck %s
+
+// RUN: %clang --target=x86_64-apple-darwin -### \
+// RUN:   --ld-path=%S/Inputs/lld/ld.lld -mlinker-version=0 %s 2>&1 \
+// RUN:   | FileCheck --check-prefix=NO-DEMANGLE %s
+
 // CHECK: "-demangle"
+// NO-DEMANGLE-NOT: "-demangle"
diff --git a/clang/test/Driver/fat-lto-objects.c 
b/clang/test/Driver/fat-lto-objects.c
index 84dd945e208b9e..b97ad0efb16c7c 100644
--- a/clang/test/Driver/fat-lto-objects.c
+++ b/clang/test/Driver/fat-lto-objects.c
@@ -60,5 +60,9 @@
 // RUN: %clang --target=x86_64-unknown-linux-gnu 
--sysroot=%S/Inputs/basic_cross_linux_tree %s \
 // RUN:   -fuse-ld=lld 
--ld-path=%S/Inputs/basic_cross_linux_tree/usr/x86_64-unknown-linux-gnu/bin/lld-wrapper
 \
 // RUN:   -flto -ffat-lto-objects -### 2>&1 | FileCheck --check-prefix=LTO %s
+// RUN: %clang --target=x86_64-unknown-linux-gnu 
--sysroot=%S/Inputs/basic_cross_linux_tree %s \
+// RUN:   --ld-path=%S/Inputs/lld/ld.lld -flto -ffat-lto-objects -### 2>&1 | 
FileCheck --check-prefix=LTO %s
+// RUN: %clang --target=x86_64-unknown-fuchsia %s \
+// RUN:   -B%S/Inputs/lld -flto -ffat-lto-objects -### 2>&1 | FileCheck 
--check-prefix=LTO %s
 // LTO: "--fat-lto-objects"
 // NOLTO-NOT: "--fat-lto-objects"

>From b999ec36e7ce97380c9925b2f4b6267fc9052171 Mon Sep 17 00:00:00 2001
From: Roland McGrath <[email protected]>
Date: Thu, 29 Oct 2026 12:46:00 -0700
Subject: [PATCH 2/2] [clang][Driver] Address review comments in CommonArgs and
 Hexagon

Remove redundant Linker != "lld" && Linker != "lld-link" check in
tools::addLTOOptions now covered by ToolChain::GetLinkerPath, and hoist
HTC.GetLinkerPath(&UseLLD) into hexagon::Linker::ConstructJob.

Assisted-by: Gemini
---
 clang/lib/Driver/ToolChains/CommonArgs.cpp |  4 +---
 clang/lib/Driver/ToolChains/Hexagon.cpp    | 21 +++++++++++----------
 2 files changed, 12 insertions(+), 13 deletions(-)

diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp 
b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index cdee3823945f63..6714e8594ee5b6 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -1058,7 +1058,6 @@ void tools::addLTOOptions(const ToolChain &ToolChain, 
const ArgList &Args,
   const llvm::Triple &Triple = ToolChain.getTriple();
   const bool IsOSAIX = Triple.isOSAIX();
   const bool IsAMDGCN = Triple.isAMDGCN();
-  StringRef Linker = Args.getLastArgValue(options::OPT_fuse_ld_EQ);
   bool LinkerIsLLD = false;
   (void)ToolChain.GetLinkerPath(&LinkerIsLLD);
   const Driver &D = ToolChain.getDriver();
@@ -1076,8 +1075,7 @@ void tools::addLTOOptions(const ToolChain &ToolChain, 
const ArgList &Args,
     Input = Inputs.begin();
   }
 
-  if (!LinkerIsLLD && Linker != "lld" && Linker != "lld-link" &&
-      !Triple.isOSOpenBSD()) {
+  if (!LinkerIsLLD && !Triple.isOSOpenBSD()) {
     // Tell the linker to load the plugin. This has to come before
     // AddLinkerInputs as gold requires -plugin and AIX ld requires -bplugin to
     // come before any -plugin-opt/-bplugin_opt that -Wl might forward.
diff --git a/clang/lib/Driver/ToolChains/Hexagon.cpp 
b/clang/lib/Driver/ToolChains/Hexagon.cpp
index 6e9b23849f61ab..c43dee12741ab2 100644
--- a/clang/lib/Driver/ToolChains/Hexagon.cpp
+++ b/clang/lib/Driver/ToolChains/Hexagon.cpp
@@ -281,12 +281,13 @@ void hexagon::Linker::RenderExtraToolArgs(const JobAction 
&JA,
                                           ArgStringList &CmdArgs) const {
 }
 
-static void
-constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
-                         const toolchains::HexagonToolChain &HTC,
-                         const InputInfo &Output, const InputInfoList &Inputs,
-                         const ArgList &Args, ArgStringList &CmdArgs,
-                         const char *LinkingOutput) {
+static void constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
+                                     const toolchains::HexagonToolChain &HTC,
+                                     const InputInfo &Output,
+                                     const InputInfoList &Inputs,
+                                     const ArgList &Args,
+                                     ArgStringList &CmdArgs,
+                                     const char *LinkingOutput, bool UseLLD) {
 
   const Driver &D = HTC.getDriver();
 
@@ -300,8 +301,6 @@ constructHexagonLinkArgs(Compilation &C, const JobAction 
&JA,
   bool IncStdLib = !Args.hasArg(options::OPT_nostdlib);
   bool IncStartFiles = !Args.hasArg(options::OPT_nostartfiles);
   bool IncDefLibs = !Args.hasArg(options::OPT_nodefaultlibs);
-  bool UseLLD = false;
-  (void)HTC.GetLinkerPath(&UseLLD);
   bool UseShared = IsShared && !IsStatic;
   StringRef CpuVer = toolchains::HexagonToolChain::GetTargetCPUVersion(Args);
 
@@ -547,11 +546,13 @@ void hexagon::Linker::ConstructJob(Compilation &C, const 
JobAction &JA,
                                    const char *LinkingOutput) const {
   auto &HTC = static_cast<const toolchains::HexagonToolChain&>(getToolChain());
 
+  bool UseLLD = false;
+  const char *Exec = Args.MakeArgString(HTC.GetLinkerPath(&UseLLD));
+
   ArgStringList CmdArgs;
   constructHexagonLinkArgs(C, JA, HTC, Output, Inputs, Args, CmdArgs,
-                           LinkingOutput);
+                           LinkingOutput, UseLLD);
 
-  const char *Exec = Args.MakeArgString(HTC.GetLinkerPath());
   C.addCommand(std::make_unique<Command>(JA, *this,
                                          ResponseFileSupport::AtFileCurCP(),
                                          Exec, CmdArgs, Inputs, Output));

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

Reply via email to