https://github.com/CendioOssman created 
https://github.com/llvm/llvm-project/pull/155219

Various fixes to make sure clang can find libstdc++ headers and library for 
current versions of gcc.

Tested with a cross-compiler setup, but should hopefully work correctly for a 
native setup as well.

Also adds support for statically linking libstdc++ and libgcc_s.

>From 4a3af37be0c4aad6bf0a35c7a236a8364fbd4aa6 Mon Sep 17 00:00:00 2001
From: Pierre Ossman <oss...@cendio.se>
Date: Thu, 21 Aug 2025 09:51:53 +0200
Subject: [PATCH 1/7] Allow subclass override of libstdc+++ for Darwin

---
 clang/lib/Driver/ToolChains/Darwin.cpp | 68 +++++++++++++++-----------
 clang/lib/Driver/ToolChains/Darwin.h   |  6 +++
 2 files changed, 45 insertions(+), 29 deletions(-)

diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp 
b/clang/lib/Driver/ToolChains/Darwin.cpp
index 234683f2f4882..9d5c1854f194b 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -2848,39 +2848,49 @@ void AppleMachO::AddCXXStdlibLibArgs(const ArgList 
&Args,
     break;
 
   case ToolChain::CST_Libstdcxx:
-    // Unfortunately, -lstdc++ doesn't always exist in the standard search 
path;
-    // it was previously found in the gcc lib dir. However, for all the Darwin
-    // platforms we care about it was -lstdc++.6, so we search for that
-    // explicitly if we can't see an obvious -lstdc++ candidate.
-
-    // Check in the sysroot first.
-    if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
-      SmallString<128> P(A->getValue());
-      llvm::sys::path::append(P, "usr", "lib", "libstdc++.dylib");
-
-      if (!getVFS().exists(P)) {
-        llvm::sys::path::remove_filename(P);
-        llvm::sys::path::append(P, "libstdc++.6.dylib");
-        if (getVFS().exists(P)) {
-          CmdArgs.push_back(Args.MakeArgString(P));
-          return;
-        }
-      }
-    }
+    AddGnuCPlusPlusStdlibLibArgs(Args, CmdArgs);
+    break;
+  }
+}
 
-    // Otherwise, look in the root.
-    // FIXME: This should be removed someday when we don't have to care about
-    // 10.6 and earlier, where /usr/lib/libstdc++.dylib does not exist.
-    if (!getVFS().exists("/usr/lib/libstdc++.dylib") &&
-        getVFS().exists("/usr/lib/libstdc++.6.dylib")) {
-      CmdArgs.push_back("/usr/lib/libstdc++.6.dylib");
-      return;
+void AppleMachO::AddGnuCPlusPlusStdlibLibArgs(
+    const ArgList &Args, ArgStringList &CmdArgs) const {
+  CmdArgs.push_back("-lstdc++");
+}
+
+void DarwinClang::AddGnuCPlusPlusStdlibLibArgs(
+    const ArgList &Args, ArgStringList &CmdArgs) const {
+  // Unfortunately, -lstdc++ doesn't always exist in the standard search path;
+  // it was previously found in the gcc lib dir. However, for all the Darwin
+  // platforms we care about it was -lstdc++.6, so we search for that
+  // explicitly if we can't see an obvious -lstdc++ candidate.
+
+  // Check in the sysroot first.
+  if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
+    SmallString<128> P(A->getValue());
+    llvm::sys::path::append(P, "usr", "lib", "libstdc++.dylib");
+
+    if (!getVFS().exists(P)) {
+      llvm::sys::path::remove_filename(P);
+      llvm::sys::path::append(P, "libstdc++.6.dylib");
+      if (getVFS().exists(P)) {
+        CmdArgs.push_back(Args.MakeArgString(P));
+        return;
+      }
     }
+  }
 
-    // Otherwise, let the linker search.
-    CmdArgs.push_back("-lstdc++");
-    break;
+  // Otherwise, look in the root.
+  // FIXME: This should be removed someday when we don't have to care about
+  // 10.6 and earlier, where /usr/lib/libstdc++.dylib does not exist.
+  if (!getVFS().exists("/usr/lib/libstdc++.dylib") &&
+      getVFS().exists("/usr/lib/libstdc++.6.dylib")) {
+    CmdArgs.push_back("/usr/lib/libstdc++.6.dylib");
+    return;
   }
+
+  // Otherwise, let the linker search.
+  CmdArgs.push_back("-lstdc++");
 }
 
 void DarwinClang::AddCCKextLibArgs(const ArgList &Args,
diff --git a/clang/lib/Driver/ToolChains/Darwin.h 
b/clang/lib/Driver/ToolChains/Darwin.h
index d1cfb6f4a5bf7..3cefe489f7cf4 100644
--- a/clang/lib/Driver/ToolChains/Darwin.h
+++ b/clang/lib/Driver/ToolChains/Darwin.h
@@ -338,6 +338,9 @@ class LLVM_LIBRARY_VISIBILITY AppleMachO : public MachO {
   virtual void
   AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs,
                               llvm::opt::ArgStringList &CC1Args) const;
+  virtual void
+  AddGnuCPlusPlusStdlibLibArgs(const llvm::opt::ArgList &Args,
+                               llvm::opt::ArgStringList &CmdArgs) const;
 };
 
 /// Darwin - The base Darwin tool chain.
@@ -689,6 +692,9 @@ class LLVM_LIBRARY_VISIBILITY DarwinClang : public Darwin {
   void
   AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs,
                               llvm::opt::ArgStringList &CC1Args) const 
override;
+  void
+  AddGnuCPlusPlusStdlibLibArgs(const llvm::opt::ArgList &Args,
+                               llvm::opt::ArgStringList &CmdArgs) const 
override;
 
   bool AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs,
                                    llvm::opt::ArgStringList &CC1Args,

>From 14fd23364a4627dad541dd84cd7f211fcc9de14e Mon Sep 17 00:00:00 2001
From: Pierre Ossman <oss...@cendio.se>
Date: Thu, 21 Aug 2025 10:03:10 +0200
Subject: [PATCH 2/7] Fix sysroot handling for libstdc++ for Darwin

---
 clang/lib/Driver/ToolChains/Darwin.cpp | 29 ++++++++------------------
 1 file changed, 9 insertions(+), 20 deletions(-)

diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp 
b/clang/lib/Driver/ToolChains/Darwin.cpp
index 9d5c1854f194b..afac7c7ff35a9 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -2865,31 +2865,20 @@ void DarwinClang::AddGnuCPlusPlusStdlibLibArgs(
   // platforms we care about it was -lstdc++.6, so we search for that
   // explicitly if we can't see an obvious -lstdc++ candidate.
 
-  // Check in the sysroot first.
-  if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
-    SmallString<128> P(A->getValue());
-    llvm::sys::path::append(P, "usr", "lib", "libstdc++.dylib");
-
-    if (!getVFS().exists(P)) {
-      llvm::sys::path::remove_filename(P);
-      llvm::sys::path::append(P, "libstdc++.6.dylib");
-      if (getVFS().exists(P)) {
-        CmdArgs.push_back(Args.MakeArgString(P));
-        return;
-      }
-    }
-  }
+  llvm::SmallString<128> UsrLibStdCxx = GetEffectiveSysroot(Args);
+  llvm::sys::path::append(UsrLibStdCxx, "usr", "lib", "libstdc++.dylib");
 
-  // Otherwise, look in the root.
   // FIXME: This should be removed someday when we don't have to care about
   // 10.6 and earlier, where /usr/lib/libstdc++.dylib does not exist.
-  if (!getVFS().exists("/usr/lib/libstdc++.dylib") &&
-      getVFS().exists("/usr/lib/libstdc++.6.dylib")) {
-    CmdArgs.push_back("/usr/lib/libstdc++.6.dylib");
-    return;
+  if (!getVFS().exists(UsrLibStdCxx)) {
+    llvm::sys::path::remove_filename(UsrLibStdCxx);
+    llvm::sys::path::append(UsrLibStdCxx, "libstdc++.6.dylib");
+    if (getVFS().exists(UsrLibStdCxx)) {
+      CmdArgs.push_back(Args.MakeArgString(UsrLibStdCxx));
+      return;
+    }
   }
 
-  // Otherwise, let the linker search.
   CmdArgs.push_back("-lstdc++");
 }
 

>From e731838f4473a1fa044f13bc9eb7f6e3e20caaf8 Mon Sep 17 00:00:00 2001
From: Pierre Ossman <oss...@cendio.se>
Date: Thu, 21 Aug 2025 10:39:11 +0200
Subject: [PATCH 3/7] Allow gcc detection on Darwin systems

---
 clang/lib/Driver/ToolChains/Gnu.cpp | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp 
b/clang/lib/Driver/ToolChains/Gnu.cpp
index 01b146db24f3e..e6f9452bc163b 100644
--- a/clang/lib/Driver/ToolChains/Gnu.cpp
+++ b/clang/lib/Driver/ToolChains/Gnu.cpp
@@ -1864,9 +1864,11 @@ static bool findBiarchMultilibs(const Driver &D,
                             .flag("-m64", /*Disallow=*/true)
                             .makeMultilib();
 
-  // GCC toolchain for IAMCU doesn't have crtbegin.o, so look for libgcc.a.
+  // GCC toolchain for IAMCU and Darwin doesn't have crtbegin.o, so look for 
libgcc.a.
   FilterNonExistent NonExistent(
-      Path, TargetTriple.isOSIAMCU() ? "/libgcc.a" : "/crtbegin.o", 
D.getVFS());
+      Path,
+      (TargetTriple.isOSIAMCU() || TargetTriple.isOSDarwin()) ? "/libgcc.a" : 
"/crtbegin.o",
+      D.getVFS());
 
   // Determine default multilib from: 32, 64, x32
   // Also handle cases such as 64 on 32, 32 on 64, etc.
@@ -2556,6 +2558,11 @@ void 
Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
     return;
   }
 
+  if (TargetTriple.isOSDarwin()) {
+    LibDirs.push_back("/lib");
+    return;
+  }
+
   switch (TargetTriple.getArch()) {
   case llvm::Triple::aarch64:
     LibDirs.append(begin(AArch64LibDirs), end(AArch64LibDirs));

>From e2743ef5f174ae4d742b3b3ad6377f667d7ad7cd Mon Sep 17 00:00:00 2001
From: Pierre Ossman <oss...@cendio.se>
Date: Thu, 21 Aug 2025 10:57:43 +0200
Subject: [PATCH 4/7] Always look for distribution supplied gcc

A cross compiling gcc is generally installed outside of the sysroot, so
we should always search the root system for our desired triple.
---
 clang/lib/Driver/ToolChains/Gnu.cpp | 6 ++----
 clang/test/Driver/pic.c             | 4 ++--
 2 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp 
b/clang/lib/Driver/ToolChains/Gnu.cpp
index e6f9452bc163b..1d17fb6753bd9 100644
--- a/clang/lib/Driver/ToolChains/Gnu.cpp
+++ b/clang/lib/Driver/ToolChains/Gnu.cpp
@@ -2163,10 +2163,8 @@ void Generic_GCC::GCCInstallationDetector::init(
 
     // Next, look for prefix(es) that correspond to distribution-supplied gcc
     // installations.
-    if (D.SysRoot.empty()) {
-      // Typically /usr.
-      AddDefaultGCCPrefixes(TargetTriple, Prefixes, D.SysRoot);
-    }
+    // Typically /usr.
+    AddDefaultGCCPrefixes(TargetTriple, Prefixes, "");
 
     // Try to respect gcc-config on Gentoo if --gcc-toolchain is not provided.
     // This avoids accidentally enforcing the system GCC version when using a
diff --git a/clang/test/Driver/pic.c b/clang/test/Driver/pic.c
index f5d0745422790..24bc26937dda3 100644
--- a/clang/test/Driver/pic.c
+++ b/clang/test/Driver/pic.c
@@ -26,8 +26,8 @@
 //
 // CHECK-PIE-LD: "{{.*}}ld{{(.exe)?}}"
 // CHECK-PIE-LD: "-pie"
-// CHECK-PIE-LD: "Scrt1.o" "crti.o" "crtbeginS.o"
-// CHECK-PIE-LD: "crtendS.o" "crtn.o"
+// CHECK-PIE-LD: "Scrt1.o" "crti.o" "{{.*}}crtbeginS.o"
+// CHECK-PIE-LD: "{{.*}}crtendS.o" "crtn.o"
 //
 // CHECK-NOPIE-LD: "-nopie"
 //

>From b6667b3d397eb0c17eb25aad91258eab68f1b3d6 Mon Sep 17 00:00:00 2001
From: Pierre Ossman <oss...@cendio.se>
Date: Thu, 21 Aug 2025 12:53:07 +0200
Subject: [PATCH 5/7] Respect added library paths for Darwin toolchain

---
 clang/lib/Driver/ToolChains/Darwin.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp 
b/clang/lib/Driver/ToolChains/Darwin.cpp
index afac7c7ff35a9..f4921dba9fd6d 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -681,6 +681,8 @@ void darwin::Linker::ConstructJob(Compilation &C, const 
JobAction &JA,
 
   Args.AddAllArgs(CmdArgs, options::OPT_L);
 
+  getToolChain().AddFilePathLibArgs(Args, CmdArgs);
+
   AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
   // Build the input file for -filelist (list of linker input files) in case we
   // need it later

>From 079c4ef6777300b469c35aa809a39b5bf5f204bd Mon Sep 17 00:00:00 2001
From: Pierre Ossman <oss...@cendio.se>
Date: Thu, 21 Aug 2025 11:00:45 +0200
Subject: [PATCH 6/7] Find proper gcc installations for Darwin

---
 clang/lib/Driver/ToolChains/Darwin.cpp | 109 +++++++++++++++++++++----
 clang/lib/Driver/ToolChains/Darwin.h   |  11 +++
 2 files changed, 103 insertions(+), 17 deletions(-)

diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp 
b/clang/lib/Driver/ToolChains/Darwin.cpp
index f4921dba9fd6d..6fde8cf931fa5 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -1179,7 +1179,31 @@ Tool *MachO::buildAssembler() const {
 
 DarwinClang::DarwinClang(const Driver &D, const llvm::Triple &Triple,
                          const ArgList &Args)
-    : Darwin(D, Triple, Args) {}
+    : Darwin(D, Triple, Args), GCCInstallation(D) {
+  GCCInstallation.init(Triple, Args);
+  if (GCCInstallation.isValid()) {
+    StringRef LibDir = GCCInstallation.getParentLibPath();
+    StringRef TripleStr = GCCInstallation.getTriple().str();
+    const Generic_GCC::GCCVersion &Version = GCCInstallation.getVersion();
+
+    std::string Path;
+
+    // Try /gcc/$triple/$version/
+    Path = LibDir.str() + "/gcc/" + TripleStr.str() + "/" + Version.Text;
+    if (getVFS().exists(Path))
+      getFilePaths().push_back(Path);
+
+    // Try /gcc/$triple/lib/
+    Path = LibDir.str() + "/gcc/" + TripleStr.str() + "/lib";
+    if (getVFS().exists(Path))
+      getFilePaths().push_back(Path);
+
+    // Try /../$triple/lib/
+    Path = LibDir.str() + "/../" + TripleStr.str() + "/lib";
+    if (getVFS().exists(Path))
+      getFilePaths().push_back(Path);
+  }
+}
 
 void DarwinClang::addClangWarningOptions(ArgStringList &CC1Args) const {
   // Always error about undefined 'TARGET_OS_*' macros.
@@ -2795,9 +2819,52 @@ void AppleMachO::AddGnuCPlusPlusIncludePaths(
     const llvm::opt::ArgList &DriverArgs,
     llvm::opt::ArgStringList &CC1Args) const {}
 
+bool DarwinClang::addLibStdCXXIncludePaths(Twine IncludeDir, StringRef Triple,
+                                           const llvm::opt::ArgList 
&DriverArgs,
+                                           llvm::opt::ArgStringList &CC1Args) 
const {
+  if (!getVFS().exists(IncludeDir))
+    return false;
+
+  // GPLUSPLUS_INCLUDE_DIR
+  addSystemInclude(DriverArgs, CC1Args, IncludeDir);
+  // GPLUSPLUS_TOOL_INCLUDE_DIR
+  addSystemInclude(DriverArgs, CC1Args, IncludeDir + "/" + Triple);
+  // GPLUSPLUS_BACKWARD_INCLUDE_DIR
+  addSystemInclude(DriverArgs, CC1Args, IncludeDir + "/backward");
+
+  return true;
+}
+
 void DarwinClang::AddGnuCPlusPlusIncludePaths(
     const llvm::opt::ArgList &DriverArgs,
     llvm::opt::ArgStringList &CC1Args) const {
+  if (GCCInstallation.isValid()) {
+    // This is a stripped down version of 
Generic_GCC::addGCCLibStdCxxIncludePaths.
+    StringRef LibDir = GCCInstallation.getParentLibPath();
+    StringRef TripleStr = GCCInstallation.getTriple().str();
+    const Generic_GCC::GCCVersion &Version = GCCInstallation.getVersion();
+
+    // Try /../$triple/include/c++/$version
+    if (addLibStdCXXIncludePaths(
+            LibDir.str() + "/../" + TripleStr + "/include/c++/" + Version.Text,
+            TripleStr, DriverArgs, CC1Args))
+      return;
+
+    // Try /gcc/$triple/$version/include/c++/
+    if (addLibStdCXXIncludePaths(LibDir.str() + "/gcc/" + TripleStr + "/" +
+                                    Version.Text + "/include/c++/",
+                                TripleStr, DriverArgs, CC1Args))
+      return;
+
+    // Try /../include/c++/$version
+    if (addLibStdCXXIncludePaths(LibDir.str() + "/../include/c++/" + 
Version.Text,
+                                TripleStr, DriverArgs, CC1Args))
+      return;
+
+    getDriver().Diag(diag::warn_drv_libstdcxx_not_found);
+    return;
+  }
+
   llvm::SmallString<128> UsrIncludeCxx = GetEffectiveSysroot(DriverArgs);
   llvm::sys::path::append(UsrIncludeCxx, "usr", "include", "c++");
 
@@ -2862,22 +2929,24 @@ void AppleMachO::AddGnuCPlusPlusStdlibLibArgs(
 
 void DarwinClang::AddGnuCPlusPlusStdlibLibArgs(
     const ArgList &Args, ArgStringList &CmdArgs) const {
-  // Unfortunately, -lstdc++ doesn't always exist in the standard search path;
-  // it was previously found in the gcc lib dir. However, for all the Darwin
-  // platforms we care about it was -lstdc++.6, so we search for that
-  // explicitly if we can't see an obvious -lstdc++ candidate.
-
-  llvm::SmallString<128> UsrLibStdCxx = GetEffectiveSysroot(Args);
-  llvm::sys::path::append(UsrLibStdCxx, "usr", "lib", "libstdc++.dylib");
-
-  // FIXME: This should be removed someday when we don't have to care about
-  // 10.6 and earlier, where /usr/lib/libstdc++.dylib does not exist.
-  if (!getVFS().exists(UsrLibStdCxx)) {
-    llvm::sys::path::remove_filename(UsrLibStdCxx);
-    llvm::sys::path::append(UsrLibStdCxx, "libstdc++.6.dylib");
-    if (getVFS().exists(UsrLibStdCxx)) {
-      CmdArgs.push_back(Args.MakeArgString(UsrLibStdCxx));
-      return;
+  if (!GCCInstallation.isValid()) {
+    // Unfortunately, -lstdc++ doesn't always exist in the standard search 
path;
+    // it was previously found in the gcc lib dir. However, for all the Darwin
+    // platforms we care about it was -lstdc++.6, so we search for that
+    // explicitly if we can't see an obvious -lstdc++ candidate.
+
+    llvm::SmallString<128> UsrLibStdCxx = GetEffectiveSysroot(Args);
+    llvm::sys::path::append(UsrLibStdCxx, "usr", "lib", "libstdc++.dylib");
+
+    // FIXME: This should be removed someday when we don't have to care about
+    // 10.6 and earlier, where /usr/lib/libstdc++.dylib does not exist.
+    if (!getVFS().exists(UsrLibStdCxx)) {
+      llvm::sys::path::remove_filename(UsrLibStdCxx);
+      llvm::sys::path::append(UsrLibStdCxx, "libstdc++.6.dylib");
+      if (getVFS().exists(UsrLibStdCxx)) {
+        CmdArgs.push_back(Args.MakeArgString(UsrLibStdCxx));
+        return;
+      }
     }
   }
 
@@ -3786,3 +3855,9 @@ void AppleMachO::printVerboseInfo(raw_ostream &OS) const {
   CudaInstallation->print(OS);
   RocmInstallation->print(OS);
 }
+
+void DarwinClang::printVerboseInfo(raw_ostream &OS) const {
+  // Print the information about how we detected the GCC installation.
+  GCCInstallation.print(OS);
+  Darwin::printVerboseInfo(OS);
+}
diff --git a/clang/lib/Driver/ToolChains/Darwin.h 
b/clang/lib/Driver/ToolChains/Darwin.h
index 3cefe489f7cf4..06990df8f7bbe 100644
--- a/clang/lib/Driver/ToolChains/Darwin.h
+++ b/clang/lib/Driver/ToolChains/Darwin.h
@@ -9,6 +9,7 @@
 #ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DARWIN_H
 #define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DARWIN_H
 
+#include "Gnu.h"
 #include "clang/Basic/DarwinSDKInfo.h"
 #include "clang/Basic/LangOptions.h"
 #include "clang/Driver/CudaInstallationDetector.h"
@@ -643,6 +644,9 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public AppleMachO {
 
 /// DarwinClang - The Darwin toolchain used by Clang.
 class LLVM_LIBRARY_VISIBILITY DarwinClang : public Darwin {
+protected:
+  Generic_GCC::GCCInstallationDetector GCCInstallation;
+
 public:
   DarwinClang(const Driver &D, const llvm::Triple &Triple,
               const llvm::opt::ArgList &Args);
@@ -673,6 +677,8 @@ class LLVM_LIBRARY_VISIBILITY DarwinClang : public Darwin {
   void AddLinkARCArgs(const llvm::opt::ArgList &Args,
                       llvm::opt::ArgStringList &CmdArgs) const override;
 
+  void printVerboseInfo(raw_ostream &OS) const override;
+
   unsigned GetDefaultDwarfVersion() const override;
   // Until dtrace (via CTF) and LLDB can deal with distributed debug info,
   // Darwin defaults to standalone/full debug info.
@@ -689,6 +695,11 @@ class LLVM_LIBRARY_VISIBILITY DarwinClang : public Darwin {
                                StringRef Sanitizer,
                                bool shared = true) const;
 
+  bool
+  addLibStdCXXIncludePaths(Twine IncludeDir, StringRef Triple,
+                           const llvm::opt::ArgList &DriverArgs,
+                           llvm::opt::ArgStringList &CC1Args) const;
+
   void
   AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs,
                               llvm::opt::ArgStringList &CC1Args) const 
override;

>From f180e434c2377b3c6857ad0297e313959be96afc Mon Sep 17 00:00:00 2001
From: Pierre Ossman <oss...@cendio.se>
Date: Fri, 22 Aug 2025 13:29:40 +0200
Subject: [PATCH 7/7] Handle -static-libstdc++ for libstdc++ on Darwin

---
 clang/lib/Driver/ToolChains/Darwin.cpp | 27 +++++++++++++++++---------
 1 file changed, 18 insertions(+), 9 deletions(-)

diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp 
b/clang/lib/Driver/ToolChains/Darwin.cpp
index 6fde8cf931fa5..f71b875d08c11 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -1573,14 +1573,6 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList 
&Args,
     return;
   }
 
-  // Reject -static-libgcc for now, we can deal with this when and if someone
-  // cares. This is useful in situations where someone wants to statically link
-  // something like libstdc++, and needs its runtime support routines.
-  if (const Arg *A = Args.getLastArg(options::OPT_static_libgcc)) {
-    getDriver().Diag(diag::err_drv_unsupported_opt) << A->getAsString(Args);
-    return;
-  }
-
   const SanitizerArgs &Sanitize = getSanitizerArgs(Args);
 
   if (!Sanitize.needsSharedRt()) {
@@ -2929,7 +2921,24 @@ void AppleMachO::AddGnuCPlusPlusStdlibLibArgs(
 
 void DarwinClang::AddGnuCPlusPlusStdlibLibArgs(
     const ArgList &Args, ArgStringList &CmdArgs) const {
-  if (!GCCInstallation.isValid()) {
+  if (GCCInstallation.isValid()) {
+    if (Args.hasArg(options::OPT_static_libstdcxx)) {
+      // ld64 doesn't support -Bstatic, so we need to find the actual library
+      for (const auto &Path : getFilePaths()) {
+        llvm::SmallString<128> UsrLibStdCxx(Path);
+        llvm::sys::path::append(UsrLibStdCxx, "libstdc++.a");
+        if (getVFS().exists(UsrLibStdCxx)) {
+          CmdArgs.push_back(Args.MakeArgString(UsrLibStdCxx));
+          // libstdcxx++ needs symbols from here
+          if (Args.hasArg(options::OPT_static_libgcc))
+            CmdArgs.push_back("-lgcc_eh");
+          else
+            CmdArgs.push_back("-lgcc_s.1");
+          return;
+        }
+      }
+    }
+  } else {
     // Unfortunately, -lstdc++ doesn't always exist in the standard search 
path;
     // it was previously found in the gcc lib dir. However, for all the Darwin
     // platforms we care about it was -lstdc++.6, so we search for that

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to