https://github.com/AdityaSinha149 updated 
https://github.com/llvm/llvm-project/pull/238477

>From 332d86e7cda0036804e6bd883b335efaef48a76c Mon Sep 17 00:00:00 2001
From: AdityaSinha149 <[email protected]>
Date: Tue, 3 Nov 2026 23:40:49 +0530
Subject: [PATCH] [clang][Driver] NFC: Share -B and --ld-path lookup helpers

---
 clang/include/clang/Driver/CommonArgs.h    | 16 ++++++++
 clang/lib/Driver/Driver.cpp                | 29 ++------------
 clang/lib/Driver/ToolChain.cpp             | 17 ++++----
 clang/lib/Driver/ToolChains/CommonArgs.cpp | 45 ++++++++++++++++++++++
 4 files changed, 73 insertions(+), 34 deletions(-)

diff --git a/clang/include/clang/Driver/CommonArgs.h 
b/clang/include/clang/Driver/CommonArgs.h
index 138e18f8641b90..c7b648f0001fcc 100644
--- a/clang/include/clang/Driver/CommonArgs.h
+++ b/clang/include/clang/Driver/CommonArgs.h
@@ -19,6 +19,7 @@
 #include "llvm/Option/Arg.h"
 #include "llvm/Option/ArgList.h"
 #include "llvm/Support/CodeGen.h"
+#include <optional>
 
 namespace clang {
 namespace driver {
@@ -40,6 +41,21 @@ OffloadJobsOpt parseOffloadJobs(const llvm::opt::ArgList 
&Args);
 void addPathIfExists(const Driver &D, const Twine &Path,
                      ToolChain::path_list &Paths);
 
+/// Appends the -B prefixes and then the COMPILER_PATH entries to
+/// \p PrefixDirs.
+void addPrefixDirs(const llvm::opt::ArgList &Args,
+                   SmallVectorImpl<std::string> &PrefixDirs);
+
+/// Looks for the program \p Name in \p PrefixDirs. \p Name is looked up in a
+/// prefix that is a directory and appended to any other prefix.
+std::optional<std::string>
+findProgramInPrefixDirs(StringRef Name, ArrayRef<std::string> PrefixDirs);
+
+/// Resolves the --ld-path= value \p LdPath. \p FoundPath is where the caller's
+/// program search found \p LdPath by name; it is used only when \p LdPath has
+/// no directory part. Returns std::nullopt if the result is not executable.
+std::optional<std::string> resolveLdPath(StringRef LdPath, StringRef 
FoundPath);
+
 void AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs,
                      const llvm::opt::ArgList &Args,
                      llvm::opt::ArgStringList &CmdArgs, const JobAction &JA);
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 37fb69baf6a3eb..fe861454b5ad68 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -1697,20 +1697,7 @@ Compilation *Driver::BuildCompilation(ArrayRef<const 
char *> ArgList) {
     TargetTriple = A->getValue();
   if (const Arg *A = Args.getLastArg(options::OPT_ccc_install_dir))
     Dir = A->getValue();
-  for (const Arg *A : Args.filtered(options::OPT_B)) {
-    A->claim();
-    PrefixDirs.push_back(A->getValue(0));
-  }
-  if (std::optional<std::string> CompilerPathValue =
-          llvm::sys::Process::GetEnv("COMPILER_PATH")) {
-    StringRef CompilerPath = *CompilerPathValue;
-    while (!CompilerPath.empty()) {
-      std::pair<StringRef, StringRef> Split =
-          CompilerPath.split(llvm::sys::EnvPathSeparator);
-      PrefixDirs.push_back(std::string(Split.first));
-      CompilerPath = Split.second;
-    }
-  }
+  tools::addPrefixDirs(Args, PrefixDirs);
   if (const Arg *A = Args.getLastArg(options::OPT__sysroot_EQ))
     SysRoot = A->getValue();
   if (const Arg *A = Args.getLastArg(options::OPT__dyld_prefix_EQ))
@@ -5985,17 +5972,9 @@ std::string Driver::GetProgramPath(StringRef Name, const 
ToolChain &TC) const {
 
   // Respect a limited subset of the '-Bprefix' functionality in GCC by
   // attempting to use this prefix when looking for program paths.
-  for (const auto &PrefixDir : PrefixDirs) {
-    if (llvm::sys::fs::is_directory(PrefixDir)) {
-      SmallString<128> P(PrefixDir);
-      if (ScanDirForExecutable(P, Name))
-        return std::string(P);
-    } else {
-      SmallString<128> P((PrefixDir + Name).str());
-      if (llvm::sys::fs::can_execute(Twine(P)))
-        return std::string(P);
-    }
-  }
+  if (std::optional<std::string> P =
+          tools::findProgramInPrefixDirs(Name, PrefixDirs))
+    return *P;
 
   const ToolChain::path_list &List = TC.getProgramPaths();
   for (const auto &TargetSpecificExecutable : TargetSpecificExecutables) {
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index b3e7043a64fe56..46e5ad52f28bdf 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -1321,15 +1321,14 @@ std::string ToolChain::GetLinkerPath(bool *LinkerIsLLD) 
const {
   // -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 (!Path.empty()) {
-      if (llvm::sys::path::parent_path(Path).empty())
-        Path = GetProgramPath(A->getValue());
-      if (llvm::sys::fs::can_execute(Path)) {
-        if (LinkerIsLLD)
-          *LinkerIsLLD = UseLinker == "lld";
-        return std::string(Path);
-      }
+    StringRef LdPath = A->getValue();
+    // An empty name must not be searched for: findProgramByName asserts.
+    std::string FoundPath = LdPath.empty() ? "" : 
GetProgramPath(A->getValue());
+    if (std::optional<std::string> Path =
+            tools::resolveLdPath(LdPath, FoundPath)) {
+      if (LinkerIsLLD)
+        *LinkerIsLLD = UseLinker == "lld";
+      return *Path;
     }
     getDriver().Diag(diag::err_drv_invalid_linker_name) << 
A->getAsString(Args);
     return GetProgramPath(getDefaultLinker());
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp 
b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 0590c297edf397..21e0a6f6ba1030 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -392,6 +392,51 @@ void tools::addPathIfExists(const Driver &D, const Twine 
&Path,
     Paths.push_back(Path.str());
 }
 
+void tools::addPrefixDirs(const ArgList &Args,
+                          SmallVectorImpl<std::string> &PrefixDirs) {
+  for (const Arg *A : Args.filtered(options::OPT_B)) {
+    A->claim();
+    PrefixDirs.push_back(A->getValue(0));
+  }
+  if (std::optional<std::string> CompilerPathValue =
+          llvm::sys::Process::GetEnv("COMPILER_PATH")) {
+    StringRef CompilerPath = *CompilerPathValue;
+    while (!CompilerPath.empty()) {
+      std::pair<StringRef, StringRef> Split =
+          CompilerPath.split(llvm::sys::EnvPathSeparator);
+      PrefixDirs.push_back(std::string(Split.first));
+      CompilerPath = Split.second;
+    }
+  }
+}
+
+std::optional<std::string>
+tools::findProgramInPrefixDirs(StringRef Name,
+                               ArrayRef<std::string> PrefixDirs) {
+  for (const std::string &PrefixDir : PrefixDirs) {
+    SmallString<128> P(PrefixDir);
+    if (llvm::sys::fs::is_directory(PrefixDir))
+      llvm::sys::path::append(P, Name);
+    else
+      P += Name;
+    if (llvm::sys::fs::can_execute(P))
+      return std::string(P);
+  }
+  return std::nullopt;
+}
+
+std::optional<std::string> tools::resolveLdPath(StringRef LdPath,
+                                                StringRef FoundPath) {
+  if (LdPath.empty())
+    return std::nullopt;
+  std::string Path = llvm::sys::path::parent_path(LdPath).empty()
+                         ? FoundPath.str()
+                         : LdPath.str();
+  if (!llvm::sys::fs::can_execute(Path))
+    return std::nullopt;
+  return Path;
+}
+
 void tools::handleTargetFeaturesGroup(const Driver &D,
                                       const llvm::Triple &Triple,
                                       const ArgList &Args,

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

Reply via email to