https://github.com/frederik-h updated 
https://github.com/llvm/llvm-project/pull/145056

>From 87c03ace23467a7d6cb7e466a02309b5b287a013 Mon Sep 17 00:00:00 2001
From: Frederik Harwath <fharw...@amd.com>
Date: Wed, 19 Feb 2025 16:01:56 +0100
Subject: [PATCH 1/7] [Clang] Take libstdc++ into account during GCC detection

The Generic_GCC::GCCInstallationDetector class always picks the latest
available GCC installation directory. This often breaks C++
compilation on systems on which this directory does not contain a
libstdc++ installation. On Ubuntu 22.04 systems, for instance, this
can happen if the "gcc-12" package gets installed without the
corresponding "g++-12" or "libstdc++-12" package in addition to the
default "g++-11" installation.

This patch changes the GCC installation selection, if compiling for
C++ using libstdc++, to consider only GCC installation directories
which also contain libstdc++. This is accomplished by enabling the
GCCInstallationDetector to reuse the existing functionality for
determinig the libstdc++ include directories which had to be
decoupled from its existing uses.
---
 clang/include/clang/Driver/Options.td         |   5 +-
 clang/include/clang/Driver/ToolChain.h        |  27 ++-
 clang/lib/Driver/ToolChain.cpp                |  25 ++-
 clang/lib/Driver/ToolChains/AVR.cpp           |   3 +-
 clang/lib/Driver/ToolChains/CSKYToolChain.cpp |   2 +-
 clang/lib/Driver/ToolChains/Gnu.cpp           | 191 ++++++++++++------
 clang/lib/Driver/ToolChains/Gnu.h             |  84 ++++++--
 clang/lib/Driver/ToolChains/Haiku.cpp         |   2 +-
 clang/lib/Driver/ToolChains/Hurd.cpp          |   2 +-
 clang/lib/Driver/ToolChains/Linux.cpp         |   2 +-
 clang/lib/Driver/ToolChains/MSP430.cpp        |   2 +-
 .../lib/Driver/ToolChains/RISCVToolchain.cpp  |   2 +-
 clang/lib/Driver/ToolChains/Solaris.cpp       |   2 +-
 .../gcc-11.2.0/include/c++/11.2.0/.keep       |   0
 .../gcc-12/include/c++/12/.keep               |   0
 clang/test/Driver/gcc-toolchain.cpp           |   5 -
 16 files changed, 245 insertions(+), 109 deletions(-)
 create mode 100644 
clang/test/Driver/Inputs/powerpc64le-linux-gnu-tree/gcc-11.2.0/include/c++/11.2.0/.keep
 create mode 100644 
clang/test/Driver/Inputs/powerpc64le-linux-gnu-tree/gcc-12/include/c++/12/.keep

diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index 6eabd9f76a792..65a63a990d8e3 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -732,8 +732,9 @@ def gcc_install_dir_EQ : Joined<["--"], "gcc-install-dir=">,
 def gcc_toolchain : Joined<["--"], "gcc-toolchain=">, Flags<[NoXarchOption]>,
   Visibility<[ClangOption, FlangOption]>,
   HelpText<
-    "Specify a directory where Clang can find 'include' and 
'lib{,32,64}/gcc{,-cross}/$triple/$version'. "
-    "Clang will use the GCC installation with the largest version">,
+    "Specify a directory to search for GCC installations (see 
--gcc-install-dir). "
+    "Picks the subdirectory with the largest GCC version, "
+    "skipping those without libstdc++ if the compile flags require it.">,
   HelpTextForVariants<[FlangOption],
     "Specify a directory where Flang can find 
'lib{,32,64}/gcc{,-cross}/$triple/$version'. "
     "Flang will use the GCC installation with the largest version">;
diff --git a/clang/include/clang/Driver/ToolChain.h 
b/clang/include/clang/Driver/ToolChain.h
index 7d1d8feebf35e..fe4e22caca5f5 100644
--- a/clang/include/clang/Driver/ToolChain.h
+++ b/clang/include/clang/Driver/ToolChain.h
@@ -226,25 +226,32 @@ class ToolChain {
 
   /// \name Utilities for implementing subclasses.
   ///@{
-  static void addSystemInclude(const llvm::opt::ArgList &DriverArgs,
-                               llvm::opt::ArgStringList &CC1Args,
-                               const Twine &Path);
   static void addExternCSystemInclude(const llvm::opt::ArgList &DriverArgs,
                                       llvm::opt::ArgStringList &CC1Args,
                                       const Twine &Path);
   static void
-      addExternCSystemIncludeIfExists(const llvm::opt::ArgList &DriverArgs,
-                                      llvm::opt::ArgStringList &CC1Args,
-                                      const Twine &Path);
-  static void addSystemIncludes(const llvm::opt::ArgList &DriverArgs,
-                                llvm::opt::ArgStringList &CC1Args,
-                                ArrayRef<StringRef> Paths);
-
+  addExternCSystemIncludeIfExists(const llvm::opt::ArgList &DriverArgs,
+                                  llvm::opt::ArgStringList &CC1Args,
+                                  const Twine &Path);
   static std::string concat(StringRef Path, const Twine &A, const Twine &B = 
"",
                             const Twine &C = "", const Twine &D = "");
+
+  /// Return the CXXStdlibType which has been selected based on the
+  /// type of ToolChain driver args, triple etc. if it is in use,
+  /// i.e. we are compiling for C++ and the stdlib has not been
+  /// disabled.
+  std::optional<CXXStdlibType> getCXXStdlibTypeInUse();
+
   ///@}
 
 public:
+  static void addSystemInclude(const llvm::opt::ArgList &DriverArgs,
+                               llvm::opt::ArgStringList &CC1Args,
+                               const Twine &Path);
+  static void addSystemIncludes(const llvm::opt::ArgList &DriverArgs,
+                                llvm::opt::ArgStringList &CC1Args,
+                                ArrayRef<StringRef> Paths);
+
   virtual ~ToolChain();
 
   // Accessors
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index ebc982096595e..58f5034ccd19f 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -104,6 +104,15 @@ ToolChain::ToolChain(const Driver &D, const llvm::Triple 
&T,
     addIfExists(getFilePaths(), Path);
 }
 
+std::optional<ToolChain::CXXStdlibType> ToolChain::getCXXStdlibTypeInUse() {
+  if (!(D.CCCIsCXX() &&
+        !Args.hasArg(options::OPT_nostdinc, options::OPT_nostdincxx,
+                     options::OPT_nostdlibinc)))
+    return std::nullopt;
+
+  return GetCXXStdlibType(Args);
+}
+
 llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
 ToolChain::executeToolChainProgram(StringRef Executable) const {
   llvm::SmallString<64> OutputFile;
@@ -1272,14 +1281,6 @@ ToolChain::CXXStdlibType 
ToolChain::GetCXXStdlibType(const ArgList &Args) const{
   return *cxxStdlibType;
 }
 
-/// Utility function to add a system include directory to CC1 arguments.
-/*static*/ void ToolChain::addSystemInclude(const ArgList &DriverArgs,
-                                            ArgStringList &CC1Args,
-                                            const Twine &Path) {
-  CC1Args.push_back("-internal-isystem");
-  CC1Args.push_back(DriverArgs.MakeArgString(Path));
-}
-
 /// Utility function to add a system include directory with extern "C"
 /// semantics to CC1 arguments.
 ///
@@ -1302,6 +1303,14 @@ void ToolChain::addExternCSystemIncludeIfExists(const 
ArgList &DriverArgs,
     addExternCSystemInclude(DriverArgs, CC1Args, Path);
 }
 
+/// Utility function to add a system include directory to CC1 arguments.
+/*static*/ void ToolChain::addSystemInclude(const ArgList &DriverArgs,
+                                            ArgStringList &CC1Args,
+                                            const Twine &Path) {
+  CC1Args.push_back("-internal-isystem");
+  CC1Args.push_back(DriverArgs.MakeArgString(Path));
+}
+
 /// Utility function to add a list of system include directories to CC1.
 /*static*/ void ToolChain::addSystemIncludes(const ArgList &DriverArgs,
                                              ArgStringList &CC1Args,
diff --git a/clang/lib/Driver/ToolChains/AVR.cpp 
b/clang/lib/Driver/ToolChains/AVR.cpp
index 08e906ac9e806..ef5806c4231b1 100644
--- a/clang/lib/Driver/ToolChains/AVR.cpp
+++ b/clang/lib/Driver/ToolChains/AVR.cpp
@@ -366,7 +366,8 @@ const StringRef PossibleAVRLibcLocations[] = {
 AVRToolChain::AVRToolChain(const Driver &D, const llvm::Triple &Triple,
                            const ArgList &Args)
     : Generic_ELF(D, Triple, Args) {
-  GCCInstallation.init(Triple, Args);
+
+  GCCInstallation.init(Triple, Args, getCXXStdlibTypeInUse());
 
   if (getCPUName(D, Args, Triple).empty())
     D.Diag(diag::warn_drv_avr_mcu_not_specified);
diff --git a/clang/lib/Driver/ToolChains/CSKYToolChain.cpp 
b/clang/lib/Driver/ToolChains/CSKYToolChain.cpp
index feb3bc922920f..c3f4dcf3ed342 100644
--- a/clang/lib/Driver/ToolChains/CSKYToolChain.cpp
+++ b/clang/lib/Driver/ToolChains/CSKYToolChain.cpp
@@ -35,7 +35,7 @@ static void addMultilibsFilePaths(const Driver &D, const 
MultilibSet &Multilibs,
 CSKYToolChain::CSKYToolChain(const Driver &D, const llvm::Triple &Triple,
                              const ArgList &Args)
     : Generic_ELF(D, Triple, Args) {
-  GCCInstallation.init(Triple, Args);
+  GCCInstallation.init(Triple, Args, getCXXStdlibTypeInUse());
   if (GCCInstallation.isValid()) {
     Multilibs = GCCInstallation.getMultilibs();
     SelectedMultilibs.assign({GCCInstallation.getMultilib()});
diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp 
b/clang/lib/Driver/ToolChains/Gnu.cpp
index f56eeda3cb5f6..5fdd690d01316 100644
--- a/clang/lib/Driver/ToolChains/Gnu.cpp
+++ b/clang/lib/Driver/ToolChains/Gnu.cpp
@@ -34,6 +34,7 @@
 #include "llvm/TargetParser/RISCVISAInfo.h"
 #include "llvm/TargetParser/TargetParser.h"
 #include <system_error>
+#include <algorithm>
 
 using namespace clang::driver;
 using namespace clang::driver::toolchains;
@@ -2171,7 +2172,10 @@ static llvm::StringRef getGCCToolchainDir(const ArgList 
&Args,
 /// necessary because the driver doesn't store the final version of the target
 /// triple.
 void Generic_GCC::GCCInstallationDetector::init(
-    const llvm::Triple &TargetTriple, const ArgList &Args) {
+    const llvm::Triple &TargetTriple, const ArgList &Args,
+    std::optional<ToolChain::CXXStdlibType> CxxLibType) {
+  RequireLibStdCxx = CxxLibType && CxxLibType == CXXStdlibType::CST_Libstdcxx;
+
   llvm::Triple BiarchVariantTriple = TargetTriple.isArch32Bit()
                                          ? TargetTriple.get64BitArchVariant()
                                          : TargetTriple.get32BitArchVariant();
@@ -2213,10 +2217,11 @@ void Generic_GCC::GCCInstallationDetector::init(
       StringRef TripleText =
           llvm::sys::path::filename(llvm::sys::path::parent_path(InstallDir));
 
-      Version = GCCVersion::Parse(VersionText);
-      GCCTriple.setTriple(TripleText);
-      GCCInstallPath = std::string(InstallDir);
-      GCCParentLibPath = GCCInstallPath + "/../../..";
+      SelectedInstallation.Version = GCCVersion::Parse(VersionText);
+      SelectedInstallation.GCCTriple.setTriple(TripleText);
+      SelectedInstallation.GCCInstallPath = std::string(InstallDir);
+      SelectedInstallation.GCCParentLibPath =
+          SelectedInstallation.GCCInstallPath + "/../../..";
       IsValid = true;
     }
     return;
@@ -2276,7 +2281,7 @@ void Generic_GCC::GCCInstallationDetector::init(
   // Loop over the various components which exist and select the best GCC
   // installation available. GCC installs are ranked by version number.
   const GCCVersion VersionZero = GCCVersion::Parse("0.0.0");
-  Version = VersionZero;
+  SelectedInstallation.Version = VersionZero;
   for (const std::string &Prefix : Prefixes) {
     auto &VFS = D.getVFS();
     if (!VFS.exists(Prefix))
@@ -2304,7 +2309,7 @@ void Generic_GCC::GCCInstallationDetector::init(
     }
 
     // Skip other prefixes once a GCC installation is found.
-    if (Version > VersionZero)
+    if (SelectedInstallation.Version > VersionZero)
       break;
   }
 }
@@ -2313,14 +2318,17 @@ void 
Generic_GCC::GCCInstallationDetector::print(raw_ostream &OS) const {
   for (const auto &InstallPath : CandidateGCCInstallPaths)
     OS << "Found candidate GCC installation: " << InstallPath << "\n";
 
-  if (!GCCInstallPath.empty())
-    OS << "Selected GCC installation: " << GCCInstallPath << "\n";
+  if (!SelectedInstallation.GCCInstallPath.empty())
+    OS << "Selected GCC installation: " << SelectedInstallation.GCCInstallPath
+       << "\n";
 
   for (const auto &Multilib : Multilibs)
     OS << "Candidate multilib: " << Multilib << "\n";
 
-  if (Multilibs.size() != 0 || !SelectedMultilib.isDefault())
-    OS << "Selected multilib: " << SelectedMultilib << "\n";
+  if (Multilibs.size() != 0 ||
+      !SelectedInstallation.SelectedMultilib.isDefault())
+    OS << "Selected multilib: " << SelectedInstallation.SelectedMultilib
+       << "\n";
 }
 
 bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const 
{
@@ -2842,9 +2850,9 @@ bool 
Generic_GCC::GCCInstallationDetector::ScanGCCForMultilibs(
   }
 
   Multilibs = Detected.Multilibs;
-  SelectedMultilib = Detected.SelectedMultilibs.empty()
-                         ? Multilib()
-                         : Detected.SelectedMultilibs.back();
+  SelectedInstallation.SelectedMultilib =
+      Detected.SelectedMultilibs.empty() ? Multilib()
+                                         : Detected.SelectedMultilibs.back();
   BiarchSibling = Detected.BiarchSibling;
 
   return true;
@@ -2883,6 +2891,7 @@ void 
Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
     if (!Suffix.Active)
       continue;
 
+    SmallVector<GCCInstallCandidate, 3> Installations;
     StringRef LibSuffix = Suffix.LibSuffix;
     std::error_code EC;
     for (llvm::vfs::directory_iterator
@@ -2896,20 +2905,40 @@ void 
Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
           continue; // Saw this path before; no need to look at it again.
       if (CandidateVersion.isOlderThan(4, 1, 1))
         continue;
-      if (CandidateVersion <= Version)
+      if (CandidateVersion <= SelectedInstallation.Version && IsValid)
         continue;
 
       if (!ScanGCCForMultilibs(TargetTriple, Args, LI->path(),
                                NeedsBiarchSuffix))
         continue;
 
-      Version = CandidateVersion;
-      GCCTriple.setTriple(CandidateTriple);
+      GCCInstallCandidate Installation;
+      Installation.Version = CandidateVersion;
+      Installation.GCCTriple.setTriple(CandidateTriple);
       // FIXME: We hack together the directory name here instead of
       // using LI to ensure stable path separators across Windows and
       // Linux.
-      GCCInstallPath = (LibDir + "/" + LibSuffix + "/" + VersionText).str();
-      GCCParentLibPath = (GCCInstallPath + "/../" + Suffix.ReversePath).str();
+      Installation.GCCInstallPath =
+          (LibDir + "/" + LibSuffix + "/" + VersionText).str();
+      Installation.GCCParentLibPath =
+          (Installation.GCCInstallPath + "/../" + Suffix.ReversePath).str();
+      Installation.SelectedMultilib = getMultilib();
+
+      Installations.push_back(Installation);
+      if (GCCInstallationHasRequiredLibs(Installation, Args)) {
+        SelectedInstallation = Installation;
+        IsValid = true;
+      }
+    }
+
+    // If no GCC installation has all required libs, pick the latest
+    // one. Otherwise we would, for instance, break C++ compilation
+    // for code which does not use anything from the stdlib but
+    // which gets compiled without "-nostdlib".
+    if (!IsValid && !Installations.empty()) {
+      SelectedInstallation = *std::max_element(
+          Installations.begin(), Installations.end(),
+          [](auto x, auto y) { return x.Version < y.Version; });
       IsValid = true;
     }
   }
@@ -2990,10 +3019,12 @@ bool 
Generic_GCC::GCCInstallationDetector::ScanGentooGccConfig(
                                    NeedsBiarchSuffix))
             continue;
 
-          Version = GCCVersion::Parse(ActiveVersion.second);
-          GCCInstallPath = GentooPath;
-          GCCParentLibPath = GentooPath + std::string("/../../..");
-          GCCTriple.setTriple(ActiveVersion.first);
+          SelectedInstallation.Version =
+              GCCVersion::Parse(ActiveVersion.second);
+          SelectedInstallation.GCCInstallPath = GentooPath;
+          SelectedInstallation.GCCParentLibPath =
+              GentooPath + std::string("/../../..");
+          SelectedInstallation.GCCTriple.setTriple(ActiveVersion.first);
           IsValid = true;
           return true;
         }
@@ -3196,8 +3227,9 @@ void Generic_GCC::AddMultilibIncludeArgs(const ArgList 
&DriverArgs,
   // gcc TOOL_INCLUDE_DIR.
   const llvm::Triple &GCCTriple = GCCInstallation.getTriple();
   std::string LibPath(GCCInstallation.getParentLibPath());
-  addSystemInclude(DriverArgs, CC1Args,
-                   Twine(LibPath) + "/../" + GCCTriple.str() + "/include");
+  ToolChain::addSystemInclude(DriverArgs, CC1Args,
+                              Twine(LibPath) + "/../" + GCCTriple.str() +
+                                  "/include");
 
   const auto &Callback = Multilibs.includeDirsCallback();
   if (Callback) {
@@ -3284,12 +3316,14 @@ Generic_GCC::addLibCxxIncludePaths(const 
llvm::opt::ArgList &DriverArgs,
     return;
 }
 
-bool Generic_GCC::addLibStdCXXIncludePaths(Twine IncludeDir, StringRef Triple,
-                                           Twine IncludeSuffix,
-                                           const llvm::opt::ArgList 
&DriverArgs,
-                                           llvm::opt::ArgStringList &CC1Args,
-                                           bool DetectDebian) const {
-  if (!getVFS().exists(IncludeDir))
+static bool addLibStdCXXIncludePaths(llvm::vfs::FileSystem &vfs,
+                                     Twine IncludeDir, StringRef Triple,
+                                     Twine IncludeSuffix,
+                                     const llvm::opt::ArgList &DriverArgs,
+                                     llvm::opt::ArgStringList &CC1Args,
+                                     bool DetectDebian = false) {
+
+  if (!vfs.exists(IncludeDir))
     return false;
 
   // Debian native gcc uses g++-multiarch-incdir.diff which uses
@@ -3301,39 +3335,48 @@ bool Generic_GCC::addLibStdCXXIncludePaths(Twine 
IncludeDir, StringRef Triple,
   std::string Path =
       (Include + "/" + Triple + Dir.substr(Include.size()) + IncludeSuffix)
           .str();
-  if (DetectDebian && !getVFS().exists(Path))
+  if (DetectDebian && !vfs.exists(Path))
     return false;
 
   // GPLUSPLUS_INCLUDE_DIR
-  addSystemInclude(DriverArgs, CC1Args, IncludeDir);
+  ToolChain::addSystemInclude(DriverArgs, CC1Args, IncludeDir);
   // GPLUSPLUS_TOOL_INCLUDE_DIR. If Triple is not empty, add a target-dependent
   // include directory.
   if (DetectDebian)
-    addSystemInclude(DriverArgs, CC1Args, Path);
+    ToolChain::addSystemInclude(DriverArgs, CC1Args, Path);
   else if (!Triple.empty())
-    addSystemInclude(DriverArgs, CC1Args,
-                     IncludeDir + "/" + Triple + IncludeSuffix);
+    ToolChain::addSystemInclude(DriverArgs, CC1Args,
+                                IncludeDir + "/" + Triple + IncludeSuffix);
   // GPLUSPLUS_BACKWARD_INCLUDE_DIR
-  addSystemInclude(DriverArgs, CC1Args, IncludeDir + "/backward");
+  ToolChain::addSystemInclude(DriverArgs, CC1Args, IncludeDir + "/backward");
   return true;
 }
 
-bool Generic_GCC::addGCCLibStdCxxIncludePaths(
-    const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
-    StringRef DebianMultiarch) const {
-  assert(GCCInstallation.isValid());
+bool Generic_GCC::addLibStdCXXIncludePaths(Twine IncludeDir, StringRef Triple,
+                                           Twine IncludeSuffix,
+                                           const llvm::opt::ArgList 
&DriverArgs,
+                                           llvm::opt::ArgStringList &CC1Args,
+                                           bool DetectDebian) const {
+  return ::addLibStdCXXIncludePaths(getVFS(), IncludeDir, Triple, 
IncludeSuffix,
+                                    DriverArgs, CC1Args, DetectDebian);
+}
+
+bool Generic_GCC::GCCInstallCandidate::addGCCLibStdCxxIncludePaths(
+    llvm::vfs::FileSystem &vfs, const llvm::opt::ArgList &DriverArgs,
+    llvm::opt::ArgStringList &CC1Args, StringRef DebianMultiarch) const {
 
   // By default, look for the C++ headers in an include directory adjacent to
   // the lib directory of the GCC installation. Note that this is expect to be
   // equivalent to '/usr/include/c++/X.Y' in almost all cases.
-  StringRef LibDir = GCCInstallation.getParentLibPath();
-  StringRef InstallDir = GCCInstallation.getInstallPath();
-  StringRef TripleStr = GCCInstallation.getTriple().str();
-  const Multilib &Multilib = GCCInstallation.getMultilib();
-  const GCCVersion &Version = GCCInstallation.getVersion();
+  StringRef LibDir = getParentLibPath();
+  StringRef InstallDir = getInstallPath();
+  StringRef TripleStr = getTriple().str();
+  const Multilib &Multilib = getMultilib();
+  const GCCVersion &Version = getVersion();
 
   // Try /../$triple/include/c++/$version (gcc --print-multiarch is not empty).
-  if (addLibStdCXXIncludePaths(
+  if (::addLibStdCXXIncludePaths(
+          vfs,
           LibDir.str() + "/../" + TripleStr + "/include/c++/" + Version.Text,
           TripleStr, Multilib.includeSuffix(), DriverArgs, CC1Args))
     return true;
@@ -3341,22 +3384,24 @@ bool Generic_GCC::addGCCLibStdCxxIncludePaths(
   // Try /gcc/$triple/$version/include/c++/ (gcc --print-multiarch is not
   // empty). Like above but for GCC built with
   // --enable-version-specific-runtime-libs.
-  if (addLibStdCXXIncludePaths(LibDir.str() + "/gcc/" + TripleStr + "/" +
-                                   Version.Text + "/include/c++/",
-                               TripleStr, Multilib.includeSuffix(), DriverArgs,
-                               CC1Args))
+  if (::addLibStdCXXIncludePaths(vfs,
+                                 LibDir.str() + "/gcc/" + TripleStr + "/" +
+                                     Version.Text + "/include/c++/",
+                                 TripleStr, Multilib.includeSuffix(),
+                                 DriverArgs, CC1Args))
     return true;
 
   // Detect Debian g++-multiarch-incdir.diff.
-  if (addLibStdCXXIncludePaths(LibDir.str() + "/../include/c++/" + 
Version.Text,
-                               DebianMultiarch, Multilib.includeSuffix(),
-                               DriverArgs, CC1Args, /*Debian=*/true))
+  if (::addLibStdCXXIncludePaths(
+          vfs, LibDir.str() + "/../include/c++/" + Version.Text,
+          DebianMultiarch, Multilib.includeSuffix(), DriverArgs, CC1Args,
+          /*Debian=*/true))
     return true;
 
   // Try /../include/c++/$version (gcc --print-multiarch is empty).
-  if (addLibStdCXXIncludePaths(LibDir.str() + "/../include/c++/" + 
Version.Text,
-                               TripleStr, Multilib.includeSuffix(), DriverArgs,
-                               CC1Args))
+  if (::addLibStdCXXIncludePaths(
+          vfs, LibDir.str() + "/../include/c++/" + Version.Text, TripleStr,
+          Multilib.includeSuffix(), DriverArgs, CC1Args))
     return true;
 
   // Otherwise, fall back on a bunch of options which don't use multiarch
@@ -3371,13 +3416,41 @@ bool Generic_GCC::addGCCLibStdCxxIncludePaths(
   };
 
   for (const auto &IncludePath : LibStdCXXIncludePathCandidates) {
-    if (addLibStdCXXIncludePaths(IncludePath, TripleStr,
-                                 Multilib.includeSuffix(), DriverArgs, 
CC1Args))
+    if (::addLibStdCXXIncludePaths(vfs, IncludePath, TripleStr,
+                                   Multilib.includeSuffix(), DriverArgs,
+                                   CC1Args))
       return true;
   }
   return false;
 }
 
+bool Generic_GCC::GCCInstallationDetector::GCCInstallationHasRequiredLibs(
+    const GCCInstallCandidate &GCCInstallation,
+    const llvm::opt::ArgList &DriverArgs) const {
+
+  if (!RequireLibStdCxx)
+    return true;
+
+  // The following function is meant to add the libstdc++ include
+  // paths to the CC1 argument list. Here we just want to know if this
+  // would succeed and hence we do not pass it the real arguments.
+  llvm::opt::ArgStringList dummyCC1Args;
+  StringRef TripleStr = GCCInstallation.getTriple().str();
+  StringRef DebianMultiarch =
+      getTriple().getArch() == llvm::Triple::x86 ? "i386-linux-gnu" : 
TripleStr;
+
+  bool found = GCCInstallation.addGCCLibStdCxxIncludePaths(
+      D.getVFS(), DriverArgs, dummyCC1Args, DebianMultiarch);
+  return found;
+}
+
+bool Generic_GCC::addGCCLibStdCxxIncludePaths(
+    const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
+    StringRef DebianMultiarch) const {
+  return GCCInstallation.getSelectedInstallation().addGCCLibStdCxxIncludePaths(
+      getVFS(), DriverArgs, CC1Args, DebianMultiarch);
+}
+
 void
 Generic_GCC::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
                                       llvm::opt::ArgStringList &CC1Args) const 
{
diff --git a/clang/lib/Driver/ToolChains/Gnu.h 
b/clang/lib/Driver/ToolChains/Gnu.h
index 3b8df71bbf9d3..faee6bd9758d6 100644
--- a/clang/lib/Driver/ToolChains/Gnu.h
+++ b/clang/lib/Driver/ToolChains/Gnu.h
@@ -184,6 +184,38 @@ class LLVM_LIBRARY_VISIBILITY Generic_GCC : public 
ToolChain {
     bool operator>=(const GCCVersion &RHS) const { return !(*this < RHS); }
   };
 
+  struct GCCInstallCandidate {
+    std::string GCCInstallPath;
+    std::string GCCParentLibPath;
+
+    llvm::Triple GCCTriple;
+
+    /// The primary multilib appropriate for the given flags.
+    Multilib SelectedMultilib;
+
+    GCCVersion Version;
+
+    /// Get the GCC triple for the detected install.
+    const llvm::Triple &getTriple() const { return GCCTriple; }
+
+    /// Get the detected GCC installation path.
+    StringRef getInstallPath() const { return GCCInstallPath; }
+
+    /// Get the detected GCC parent lib path.
+    StringRef getParentLibPath() const { return GCCParentLibPath; }
+
+    /// Get the detected Multilib
+    const Multilib &getMultilib() const { return SelectedMultilib; }
+
+    /// Get the detected GCC version string.
+    const GCCVersion &getVersion() const { return Version; }
+
+    bool addGCCLibStdCxxIncludePaths(llvm::vfs::FileSystem &vfs,
+                                     const llvm::opt::ArgList &DriverArgs,
+                                     llvm::opt::ArgStringList &CC1Args,
+                                     StringRef DebianMultiarch) const;
+  };
+
   /// This is a class to find a viable GCC installation for Clang to
   /// use.
   ///
@@ -192,21 +224,15 @@ class LLVM_LIBRARY_VISIBILITY Generic_GCC : public 
ToolChain {
   /// Driver, and has logic for fuzzing that where appropriate.
   class GCCInstallationDetector {
     bool IsValid;
-    llvm::Triple GCCTriple;
+
     const Driver &D;
 
-    // FIXME: These might be better as path objects.
-    std::string GCCInstallPath;
-    std::string GCCParentLibPath;
+    GCCInstallCandidate SelectedInstallation;
 
-    /// The primary multilib appropriate for the given flags.
-    Multilib SelectedMultilib;
     /// On Biarch systems, this corresponds to the default multilib when
     /// targeting the non-default multilib. Otherwise, it is empty.
     std::optional<Multilib> BiarchSibling;
 
-    GCCVersion Version;
-
     // We retain the list of install paths that were considered and rejected in
     // order to print out detailed information in verbose mode.
     std::set<std::string> CandidateGCCInstallPaths;
@@ -218,23 +244,40 @@ class LLVM_LIBRARY_VISIBILITY Generic_GCC : public 
ToolChain {
     const std::string GentooConfigDir = "/etc/env.d/gcc";
 
   public:
-    explicit GCCInstallationDetector(const Driver &D) : IsValid(false), D(D) {}
-    void init(const llvm::Triple &TargetTriple, const llvm::opt::ArgList 
&Args);
+    bool RequireLibStdCxx;
+
+    explicit GCCInstallationDetector(const Driver &D)
+        : IsValid(false), D(D), RequireLibStdCxx(false) {}
+
+    void init(const llvm::Triple &TargetTriple, const llvm::opt::ArgList &Args,
+              std::optional<ToolChain::CXXStdlibType> CxxLibType);
 
     /// Check whether we detected a valid GCC install.
     bool isValid() const { return IsValid; }
 
+    const GCCInstallCandidate &getSelectedInstallation() const {
+      return SelectedInstallation;
+    }
+
     /// Get the GCC triple for the detected install.
-    const llvm::Triple &getTriple() const { return GCCTriple; }
+    const llvm::Triple &getTriple() const {
+      return SelectedInstallation.GCCTriple;
+    }
 
     /// Get the detected GCC installation path.
-    StringRef getInstallPath() const { return GCCInstallPath; }
+    StringRef getInstallPath() const {
+      return SelectedInstallation.GCCInstallPath;
+    }
 
     /// Get the detected GCC parent lib path.
-    StringRef getParentLibPath() const { return GCCParentLibPath; }
+    StringRef getParentLibPath() const {
+      return SelectedInstallation.GCCParentLibPath;
+    }
 
     /// Get the detected Multilib
-    const Multilib &getMultilib() const { return SelectedMultilib; }
+    const Multilib &getMultilib() const {
+      return SelectedInstallation.SelectedMultilib;
+    }
 
     /// Get the whole MultilibSet
     const MultilibSet &getMultilibs() const { return Multilibs; }
@@ -244,7 +287,9 @@ class LLVM_LIBRARY_VISIBILITY Generic_GCC : public 
ToolChain {
     bool getBiarchSibling(Multilib &M) const;
 
     /// Get the detected GCC version string.
-    const GCCVersion &getVersion() const { return Version; }
+    const GCCVersion &getVersion() const {
+      return SelectedInstallation.Version;
+    }
 
     /// Print information about the detected GCC installation.
     void print(raw_ostream &OS) const;
@@ -262,9 +307,14 @@ class LLVM_LIBRARY_VISIBILITY Generic_GCC : public 
ToolChain {
                                SmallVectorImpl<std::string> &Prefixes,
                                StringRef SysRoot);
 
+    /// Checks if the \p GCCInstallation has the libs required
+    /// by the \p DriverArgs.
+    bool
+    GCCInstallationHasRequiredLibs(const GCCInstallCandidate &GCCInstallation,
+                                   const llvm::opt::ArgList &DriverArgs) const;
+
     bool ScanGCCForMultilibs(const llvm::Triple &TargetTriple,
-                             const llvm::opt::ArgList &Args,
-                             StringRef Path,
+                             const llvm::opt::ArgList &Args, StringRef Path,
                              bool NeedsBiarchSuffix = false);
 
     void ScanLibDirForGCCTriple(const llvm::Triple &TargetArch,
diff --git a/clang/lib/Driver/ToolChains/Haiku.cpp 
b/clang/lib/Driver/ToolChains/Haiku.cpp
index af74f43e48364..6c55a2f74724f 100644
--- a/clang/lib/Driver/ToolChains/Haiku.cpp
+++ b/clang/lib/Driver/ToolChains/Haiku.cpp
@@ -166,7 +166,7 @@ void haiku::Linker::ConstructJob(Compilation &C, const 
JobAction &JA,
 Haiku::Haiku(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
   : Generic_ELF(D, Triple, Args) {
 
-  GCCInstallation.init(Triple, Args);
+  GCCInstallation.init(Triple, Args, getCXXStdlibTypeInUse());
 
   getFilePaths().push_back(concat(getDriver().SysRoot, "/boot/system/lib"));
   getFilePaths().push_back(concat(getDriver().SysRoot, 
"/boot/system/develop/lib"));
diff --git a/clang/lib/Driver/ToolChains/Hurd.cpp 
b/clang/lib/Driver/ToolChains/Hurd.cpp
index 0bc114b90ffc0..efddd4b429869 100644
--- a/clang/lib/Driver/ToolChains/Hurd.cpp
+++ b/clang/lib/Driver/ToolChains/Hurd.cpp
@@ -71,7 +71,7 @@ static StringRef getOSLibDir(const llvm::Triple &Triple, 
const ArgList &Args) {
 
 Hurd::Hurd(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
     : Generic_ELF(D, Triple, Args) {
-  GCCInstallation.init(Triple, Args);
+  GCCInstallation.init(Triple, Args, getCXXStdlibTypeInUse());
   Multilibs = GCCInstallation.getMultilibs();
   SelectedMultilibs.assign({GCCInstallation.getMultilib()});
   std::string SysRoot = computeSysRoot();
diff --git a/clang/lib/Driver/ToolChains/Linux.cpp 
b/clang/lib/Driver/ToolChains/Linux.cpp
index 0767fe6c58796..86bf610026226 100644
--- a/clang/lib/Driver/ToolChains/Linux.cpp
+++ b/clang/lib/Driver/ToolChains/Linux.cpp
@@ -212,7 +212,7 @@ static StringRef getOSLibDir(const llvm::Triple &Triple, 
const ArgList &Args) {
 
 Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
     : Generic_ELF(D, Triple, Args) {
-  GCCInstallation.init(Triple, Args);
+  GCCInstallation.init(Triple, Args, getCXXStdlibTypeInUse());
   Multilibs = GCCInstallation.getMultilibs();
   SelectedMultilibs.assign({GCCInstallation.getMultilib()});
   llvm::Triple::ArchType Arch = Triple.getArch();
diff --git a/clang/lib/Driver/ToolChains/MSP430.cpp 
b/clang/lib/Driver/ToolChains/MSP430.cpp
index 07e875c64960e..ed515f0f1373c 100644
--- a/clang/lib/Driver/ToolChains/MSP430.cpp
+++ b/clang/lib/Driver/ToolChains/MSP430.cpp
@@ -112,7 +112,7 @@ MSP430ToolChain::MSP430ToolChain(const Driver &D, const 
llvm::Triple &Triple,
 
   StringRef MultilibSuf = "";
 
-  GCCInstallation.init(Triple, Args);
+  GCCInstallation.init(Triple, Args, getCXXStdlibTypeInUse());
   if (GCCInstallation.isValid()) {
     MultilibSuf = GCCInstallation.getMultilib().gccSuffix();
 
diff --git a/clang/lib/Driver/ToolChains/RISCVToolchain.cpp 
b/clang/lib/Driver/ToolChains/RISCVToolchain.cpp
index 624099d21ae12..e5d1e550f5453 100644
--- a/clang/lib/Driver/ToolChains/RISCVToolchain.cpp
+++ b/clang/lib/Driver/ToolChains/RISCVToolchain.cpp
@@ -50,7 +50,7 @@ bool RISCVToolChain::hasGCCToolchain(const Driver &D,
 RISCVToolChain::RISCVToolChain(const Driver &D, const llvm::Triple &Triple,
                                const ArgList &Args)
     : Generic_ELF(D, Triple, Args) {
-  GCCInstallation.init(Triple, Args);
+  GCCInstallation.init(Triple, Args, getCXXStdlibTypeInUse());
   if (GCCInstallation.isValid()) {
     Multilibs = GCCInstallation.getMultilibs();
     SelectedMultilibs.assign({GCCInstallation.getMultilib()});
diff --git a/clang/lib/Driver/ToolChains/Solaris.cpp 
b/clang/lib/Driver/ToolChains/Solaris.cpp
index fd3232b7c1b06..1153c2ac319cb 100644
--- a/clang/lib/Driver/ToolChains/Solaris.cpp
+++ b/clang/lib/Driver/ToolChains/Solaris.cpp
@@ -310,7 +310,7 @@ Solaris::Solaris(const Driver &D, const llvm::Triple 
&Triple,
                  const ArgList &Args)
     : Generic_ELF(D, Triple, Args) {
 
-  GCCInstallation.init(Triple, Args);
+  GCCInstallation.init(Triple, Args, getCXXStdlibTypeInUse());
 
   StringRef LibSuffix = getSolarisLibSuffix(Triple);
   path_list &Paths = getFilePaths();
diff --git 
a/clang/test/Driver/Inputs/powerpc64le-linux-gnu-tree/gcc-11.2.0/include/c++/11.2.0/.keep
 
b/clang/test/Driver/Inputs/powerpc64le-linux-gnu-tree/gcc-11.2.0/include/c++/11.2.0/.keep
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git 
a/clang/test/Driver/Inputs/powerpc64le-linux-gnu-tree/gcc-12/include/c++/12/.keep
 
b/clang/test/Driver/Inputs/powerpc64le-linux-gnu-tree/gcc-12/include/c++/12/.keep
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/clang/test/Driver/gcc-toolchain.cpp 
b/clang/test/Driver/gcc-toolchain.cpp
index 6d4ad417cfec6..a14e8d00af1ef 100644
--- a/clang/test/Driver/gcc-toolchain.cpp
+++ b/clang/test/Driver/gcc-toolchain.cpp
@@ -6,11 +6,6 @@
 // RUN:   --gcc-toolchain=%S/Inputs/ubuntu_14.04_multiarch_tree/usr 
-stdlib=libstdc++ --rtlib=libgcc --unwindlib=libgcc -no-pie 2>&1 | \
 // RUN:   FileCheck %s
 //
-// Additionally check that the legacy spelling of the flag works.
-// RUN: %clangxx %s -### --target=x86_64-linux-gnu --sysroot= \
-// RUN:   --gcc-toolchain=%S/Inputs/ubuntu_14.04_multiarch_tree/usr 
-stdlib=libstdc++ --rtlib=libgcc --unwindlib=libgcc -no-pie 2>&1 | \
-// RUN:   FileCheck %s
-//
 // Test for header search toolchain detection.
 // CHECK: "-internal-isystem"
 // CHECK: 
"[[TOOLCHAIN:[^"]+]]/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8"

>From b9ae7143b5bf2d325c38219d684c4afc3ec1104a Mon Sep 17 00:00:00 2001
From: Frederik Harwath <fharw...@amd.com>
Date: Tue, 1 Jul 2025 14:22:25 +0200
Subject: [PATCH 2/7] Adjustments suggested in Discourse discussion & Cleanup

* Always prefer GCC installations with libstdc++

Previously, GCC installation directories containing libstdc++
include directories were only preferred if the compiler flags
indicated that they might be required. This might lead to different
GCC installations directories being used for C and C++ compilation.

* Revert to old GCC version detection and inform about future behavior

Instead of actually preferring GCC installations containing libstdc++,
stick to the old logic. Inform about the directory that will be chosen
in the future.

* Add test for new warnings

* Make DebianMultiarch available to GCCInstallationHasLibStdcxxIncludePaths

The correct DebianMultiarch to use in the invocation of
GCCInstallation.addGCCLibStdCxxIncludePaths in
GCCInstallationHasLibStdcxxIncludePaths depends on the subclass
of Generic_GCC from which the latter function has been invoked.
This information is only available in a different place.

Add a function for converting the triple component of the
GCC installation directory to the GCCInstallationDetector. This
function is then adjusted from the different Generic_GCC subclasses.

* Revert some unnecessary changes and fix minor bugs.
---
 .../clang/Basic/DiagnosticDriverKinds.td      |   7 +-
 clang/include/clang/Driver/Options.td         |   5 +-
 clang/include/clang/Driver/ToolChain.h        |   6 -
 clang/lib/Driver/ToolChain.cpp                |   9 --
 clang/lib/Driver/ToolChains/AVR.cpp           |   2 +-
 clang/lib/Driver/ToolChains/CSKYToolChain.cpp |   2 +-
 clang/lib/Driver/ToolChains/Gnu.cpp           | 105 +++++++++++-------
 clang/lib/Driver/ToolChains/Gnu.h             |  40 +++++--
 clang/lib/Driver/ToolChains/Haiku.cpp         |   2 +-
 clang/lib/Driver/ToolChains/Hurd.cpp          |  16 +--
 clang/lib/Driver/ToolChains/Linux.cpp         |  20 ++--
 clang/lib/Driver/ToolChains/MSP430.cpp        |   2 +-
 .../lib/Driver/ToolChains/RISCVToolchain.cpp  |   2 +-
 clang/lib/Driver/ToolChains/Solaris.cpp       |   2 +-
 .../lib/gcc/x86_64-linux-gnu/10/crtbegin.o}   |   0
 .../usr/lib/gcc/x86_64-linux-gnu/10/crtend.o} |   0
 .../lib/gcc/x86_64-linux-gnu/11/crtbegin.o    |   0
 .../usr/lib/gcc/x86_64-linux-gnu/11/crtend.o  |   0
 .../lib/gcc/x86_64-linux-gnu/11/include/.keep |   0
 .../lib/gcc/x86_64-linux-gnu/12/crtbegin.o    |   0
 .../usr/lib/gcc/x86_64-linux-gnu/12/crtend.o  |   0
 .../lib/gcc/x86_64-linux-gnu/12/include/.keep |   0
 .../lib/gcc/x86_64-linux-gnu/10/crtbegin.o    |   0
 .../usr/lib/gcc/x86_64-linux-gnu/10/crtend.o  |   0
 .../lib/gcc/x86_64-linux-gnu/10/include/.keep |   0
 .../lib/gcc/x86_64-linux-gnu/11/crtbegin.o    |   0
 .../usr/lib/gcc/x86_64-linux-gnu/11/crtend.o  |   0
 .../lib/gcc/x86_64-linux-gnu/12/crtbegin.o    |   0
 .../usr/lib/gcc/x86_64-linux-gnu/12/crtend.o  |   0
 .../lib/gcc/x86_64-linux-gnu/12/include/.keep |   0
 .../lib/gcc/x86_64-linux-gnu/10/crtbegin.o    |   0
 .../usr/lib/gcc/x86_64-linux-gnu/10/crtend.o  |   0
 .../lib/gcc/x86_64-linux-gnu/10/include/.keep |   0
 .../lib/gcc/x86_64-linux-gnu/11/crtbegin.o    |   0
 .../usr/lib/gcc/x86_64-linux-gnu/11/crtend.o  |   0
 .../lib/gcc/x86_64-linux-gnu/12/crtbegin.o    |   0
 .../usr/lib/gcc/x86_64-linux-gnu/12/crtend.o  |   0
 clang/test/Driver/gcc-toolchain-libstdcxx.cpp |  28 +++++
 38 files changed, 152 insertions(+), 96 deletions(-)
 rename 
clang/test/Driver/Inputs/{powerpc64le-linux-gnu-tree/gcc-11.2.0/include/c++/11.2.0/.keep
 => gcc_toolchain_libstdcxx/gcc10/usr/lib/gcc/x86_64-linux-gnu/10/crtbegin.o} 
(100%)
 rename 
clang/test/Driver/Inputs/{powerpc64le-linux-gnu-tree/gcc-12/include/c++/12/.keep
 => gcc_toolchain_libstdcxx/gcc10/usr/lib/gcc/x86_64-linux-gnu/10/crtend.o} 
(100%)
 create mode 100644 
clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc10/usr/lib/gcc/x86_64-linux-gnu/11/crtbegin.o
 create mode 100644 
clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc10/usr/lib/gcc/x86_64-linux-gnu/11/crtend.o
 create mode 100644 
clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc10/usr/lib/gcc/x86_64-linux-gnu/11/include/.keep
 create mode 100644 
clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc10/usr/lib/gcc/x86_64-linux-gnu/12/crtbegin.o
 create mode 100644 
clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc10/usr/lib/gcc/x86_64-linux-gnu/12/crtend.o
 create mode 100644 
clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc10/usr/lib/gcc/x86_64-linux-gnu/12/include/.keep
 create mode 100644 
clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc11/usr/lib/gcc/x86_64-linux-gnu/10/crtbegin.o
 create mode 100644 
clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc11/usr/lib/gcc/x86_64-linux-gnu/10/crtend.o
 create mode 100644 
clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc11/usr/lib/gcc/x86_64-linux-gnu/10/include/.keep
 create mode 100644 
clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc11/usr/lib/gcc/x86_64-linux-gnu/11/crtbegin.o
 create mode 100644 
clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc11/usr/lib/gcc/x86_64-linux-gnu/11/crtend.o
 create mode 100644 
clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc11/usr/lib/gcc/x86_64-linux-gnu/12/crtbegin.o
 create mode 100644 
clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc11/usr/lib/gcc/x86_64-linux-gnu/12/crtend.o
 create mode 100644 
clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc11/usr/lib/gcc/x86_64-linux-gnu/12/include/.keep
 create mode 100644 
clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc12/usr/lib/gcc/x86_64-linux-gnu/10/crtbegin.o
 create mode 100644 
clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc12/usr/lib/gcc/x86_64-linux-gnu/10/crtend.o
 create mode 100644 
clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc12/usr/lib/gcc/x86_64-linux-gnu/10/include/.keep
 create mode 100644 
clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc12/usr/lib/gcc/x86_64-linux-gnu/11/crtbegin.o
 create mode 100644 
clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc12/usr/lib/gcc/x86_64-linux-gnu/11/crtend.o
 create mode 100644 
clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc12/usr/lib/gcc/x86_64-linux-gnu/12/crtbegin.o
 create mode 100644 
clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc12/usr/lib/gcc/x86_64-linux-gnu/12/crtend.o
 create mode 100644 clang/test/Driver/gcc-toolchain-libstdcxx.cpp

diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td 
b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 8d599c96eb4fb..fc7f8092ff149 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -841,4 +841,9 @@ def warn_missing_include_dirs : Warning<
 
 def err_drv_malformed_warning_suppression_mapping : Error<
   "failed to process suppression mapping file '%0': %1">;
-}
+
+def warn_drv_gcc_install_dir_libstdcxx : Warning<
+    "future releases of the clang compiler will prefer GCC installations "
+    "containing libstdc++ include directories; '%0' would be chosen over 
'%1'">,
+    InGroup<DiagGroup<"gcc-install-dir-libstdcxx">>;
+}
\ No newline at end of file
diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index 65a63a990d8e3..6eabd9f76a792 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -732,9 +732,8 @@ def gcc_install_dir_EQ : Joined<["--"], "gcc-install-dir=">,
 def gcc_toolchain : Joined<["--"], "gcc-toolchain=">, Flags<[NoXarchOption]>,
   Visibility<[ClangOption, FlangOption]>,
   HelpText<
-    "Specify a directory to search for GCC installations (see 
--gcc-install-dir). "
-    "Picks the subdirectory with the largest GCC version, "
-    "skipping those without libstdc++ if the compile flags require it.">,
+    "Specify a directory where Clang can find 'include' and 
'lib{,32,64}/gcc{,-cross}/$triple/$version'. "
+    "Clang will use the GCC installation with the largest version">,
   HelpTextForVariants<[FlangOption],
     "Specify a directory where Flang can find 
'lib{,32,64}/gcc{,-cross}/$triple/$version'. "
     "Flang will use the GCC installation with the largest version">;
diff --git a/clang/include/clang/Driver/ToolChain.h 
b/clang/include/clang/Driver/ToolChain.h
index fe4e22caca5f5..42e525c9d1289 100644
--- a/clang/include/clang/Driver/ToolChain.h
+++ b/clang/include/clang/Driver/ToolChain.h
@@ -236,12 +236,6 @@ class ToolChain {
   static std::string concat(StringRef Path, const Twine &A, const Twine &B = 
"",
                             const Twine &C = "", const Twine &D = "");
 
-  /// Return the CXXStdlibType which has been selected based on the
-  /// type of ToolChain driver args, triple etc. if it is in use,
-  /// i.e. we are compiling for C++ and the stdlib has not been
-  /// disabled.
-  std::optional<CXXStdlibType> getCXXStdlibTypeInUse();
-
   ///@}
 
 public:
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 58f5034ccd19f..3dcf7087a175d 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -104,15 +104,6 @@ ToolChain::ToolChain(const Driver &D, const llvm::Triple 
&T,
     addIfExists(getFilePaths(), Path);
 }
 
-std::optional<ToolChain::CXXStdlibType> ToolChain::getCXXStdlibTypeInUse() {
-  if (!(D.CCCIsCXX() &&
-        !Args.hasArg(options::OPT_nostdinc, options::OPT_nostdincxx,
-                     options::OPT_nostdlibinc)))
-    return std::nullopt;
-
-  return GetCXXStdlibType(Args);
-}
-
 llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
 ToolChain::executeToolChainProgram(StringRef Executable) const {
   llvm::SmallString<64> OutputFile;
diff --git a/clang/lib/Driver/ToolChains/AVR.cpp 
b/clang/lib/Driver/ToolChains/AVR.cpp
index ef5806c4231b1..13c42b4b94916 100644
--- a/clang/lib/Driver/ToolChains/AVR.cpp
+++ b/clang/lib/Driver/ToolChains/AVR.cpp
@@ -367,7 +367,7 @@ AVRToolChain::AVRToolChain(const Driver &D, const 
llvm::Triple &Triple,
                            const ArgList &Args)
     : Generic_ELF(D, Triple, Args) {
 
-  GCCInstallation.init(Triple, Args, getCXXStdlibTypeInUse());
+  GCCInstallation.init(Triple, Args);
 
   if (getCPUName(D, Args, Triple).empty())
     D.Diag(diag::warn_drv_avr_mcu_not_specified);
diff --git a/clang/lib/Driver/ToolChains/CSKYToolChain.cpp 
b/clang/lib/Driver/ToolChains/CSKYToolChain.cpp
index c3f4dcf3ed342..feb3bc922920f 100644
--- a/clang/lib/Driver/ToolChains/CSKYToolChain.cpp
+++ b/clang/lib/Driver/ToolChains/CSKYToolChain.cpp
@@ -35,7 +35,7 @@ static void addMultilibsFilePaths(const Driver &D, const 
MultilibSet &Multilibs,
 CSKYToolChain::CSKYToolChain(const Driver &D, const llvm::Triple &Triple,
                              const ArgList &Args)
     : Generic_ELF(D, Triple, Args) {
-  GCCInstallation.init(Triple, Args, getCXXStdlibTypeInUse());
+  GCCInstallation.init(Triple, Args);
   if (GCCInstallation.isValid()) {
     Multilibs = GCCInstallation.getMultilibs();
     SelectedMultilibs.assign({GCCInstallation.getMultilib()});
diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp 
b/clang/lib/Driver/ToolChains/Gnu.cpp
index 5fdd690d01316..5032044a40558 100644
--- a/clang/lib/Driver/ToolChains/Gnu.cpp
+++ b/clang/lib/Driver/ToolChains/Gnu.cpp
@@ -34,7 +34,6 @@
 #include "llvm/TargetParser/RISCVISAInfo.h"
 #include "llvm/TargetParser/TargetParser.h"
 #include <system_error>
-#include <algorithm>
 
 using namespace clang::driver;
 using namespace clang::driver::toolchains;
@@ -2172,10 +2171,7 @@ static llvm::StringRef getGCCToolchainDir(const ArgList 
&Args,
 /// necessary because the driver doesn't store the final version of the target
 /// triple.
 void Generic_GCC::GCCInstallationDetector::init(
-    const llvm::Triple &TargetTriple, const ArgList &Args,
-    std::optional<ToolChain::CXXStdlibType> CxxLibType) {
-  RequireLibStdCxx = CxxLibType && CxxLibType == CXXStdlibType::CST_Libstdcxx;
-
+    const llvm::Triple &TargetTriple, const ArgList &Args) {
   llvm::Triple BiarchVariantTriple = TargetTriple.isArch32Bit()
                                          ? TargetTriple.get64BitArchVariant()
                                          : TargetTriple.get32BitArchVariant();
@@ -2858,6 +2854,41 @@ bool 
Generic_GCC::GCCInstallationDetector::ScanGCCForMultilibs(
   return true;
 }
 
+bool Generic_GCC::GCCInstallationDetector::SelectGCCInstallationDirectory(
+    const SmallVector<Generic_GCC::GCCInstallCandidate, 3> &Installations,
+    const ArgList &Args,
+    Generic_GCC::GCCInstallCandidate &SelectedInstallation) const {
+  if (Installations.empty())
+    return false;
+
+  SelectedInstallation =
+      *max_element(Installations, [](const auto &Max, const auto &I) {
+        return I.Version > Max.Version;
+      });
+
+  // FIXME Start selecting installation with libstdc++ in clang 22,
+  // using the current way of selecting the installation as a fallback only.
+  // For now, warn if install with libstdc++ differs SelectedInstallation.
+  const GCCInstallCandidate *InstallWithIncludes = nullptr;
+  for (const auto &I : Installations) {
+    if ((!InstallWithIncludes || I.Version > InstallWithIncludes->Version) &&
+        GCCInstallationHasLibStdcxxIncludePaths(I, Args))
+      InstallWithIncludes = &I;
+  }
+
+  if (InstallWithIncludes && SelectedInstallation.GCCInstallPath !=
+                                 InstallWithIncludes->GCCInstallPath)
+    D.Diag(diag::warn_drv_gcc_install_dir_libstdcxx)
+        << InstallWithIncludes->GCCInstallPath
+        << SelectedInstallation.GCCInstallPath;
+
+  // TODO Warn if SelectedInstallation does not contain libstdc++ includes
+  // although compiler flags indicate that it is required (C++ compilation,
+  // libstdc++ not explicitly disabled).
+
+  return true;
+}
+
 void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
     const llvm::Triple &TargetTriple, const ArgList &Args,
     const std::string &LibDir, StringRef CandidateTriple,
@@ -2887,11 +2918,11 @@ void 
Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
        TargetTriple.getVendor() == llvm::Triple::Freescale ||
            TargetTriple.getVendor() == llvm::Triple::OpenEmbedded}};
 
+  SmallVector<GCCInstallCandidate, 3> Installations;
   for (auto &Suffix : Suffixes) {
     if (!Suffix.Active)
       continue;
 
-    SmallVector<GCCInstallCandidate, 3> Installations;
     StringRef LibSuffix = Suffix.LibSuffix;
     std::error_code EC;
     for (llvm::vfs::directory_iterator
@@ -2925,23 +2956,11 @@ void 
Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
       Installation.SelectedMultilib = getMultilib();
 
       Installations.push_back(Installation);
-      if (GCCInstallationHasRequiredLibs(Installation, Args)) {
-        SelectedInstallation = Installation;
-        IsValid = true;
-      }
-    }
-
-    // If no GCC installation has all required libs, pick the latest
-    // one. Otherwise we would, for instance, break C++ compilation
-    // for code which does not use anything from the stdlib but
-    // which gets compiled without "-nostdlib".
-    if (!IsValid && !Installations.empty()) {
-      SelectedInstallation = *std::max_element(
-          Installations.begin(), Installations.end(),
-          [](auto x, auto y) { return x.Version < y.Version; });
-      IsValid = true;
     }
   }
+
+  IsValid |=
+      SelectGCCInstallationDirectory(Installations, Args, 
SelectedInstallation);
 }
 
 bool Generic_GCC::GCCInstallationDetector::ScanGentooConfigs(
@@ -3424,29 +3443,30 @@ bool 
Generic_GCC::GCCInstallCandidate::addGCCLibStdCxxIncludePaths(
   return false;
 }
 
-bool Generic_GCC::GCCInstallationDetector::GCCInstallationHasRequiredLibs(
-    const GCCInstallCandidate &GCCInstallation,
-    const llvm::opt::ArgList &DriverArgs) const {
-
-  if (!RequireLibStdCxx)
-    return true;
-
-  // The following function is meant to add the libstdc++ include
-  // paths to the CC1 argument list. Here we just want to know if this
-  // would succeed and hence we do not pass it the real arguments.
-  llvm::opt::ArgStringList dummyCC1Args;
-  StringRef TripleStr = GCCInstallation.getTriple().str();
+bool Generic_GCC::GCCInstallationDetector::
+    GCCInstallationHasLibStdcxxIncludePaths(
+        const GCCInstallCandidate &GCCInstallation,
+        const llvm::opt::ArgList &DriverArgs) const {
   StringRef DebianMultiarch =
-      getTriple().getArch() == llvm::Triple::x86 ? "i386-linux-gnu" : 
TripleStr;
+      TripleToDebianMultiarch(GCCInstallation.getTriple());
 
-  bool found = GCCInstallation.addGCCLibStdCxxIncludePaths(
+  // The following function checks for libstdc++ include paths and
+  // adds them to the provided argument list.  Here we just need the
+  // check.
+  llvm::opt::ArgStringList dummyCC1Args;
+  return GCCInstallation.addGCCLibStdCxxIncludePaths(
       D.getVFS(), DriverArgs, dummyCC1Args, DebianMultiarch);
-  return found;
 }
 
 bool Generic_GCC::addGCCLibStdCxxIncludePaths(
-    const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
-    StringRef DebianMultiarch) const {
+    const llvm::opt::ArgList &DriverArgs,
+    llvm::opt::ArgStringList &CC1Args) const {
+  assert(GCCInstallation.isValid());
+
+  // Detect Debian g++-multiarch-incdir.diff.
+  StringRef DebianMultiarch =
+      GCCInstallation.TripleToDebianMultiarch(GCCInstallation.getTriple());
+
   return GCCInstallation.getSelectedInstallation().addGCCLibStdCxxIncludePaths(
       getVFS(), DriverArgs, CC1Args, DebianMultiarch);
 }
@@ -3454,10 +3474,11 @@ bool Generic_GCC::addGCCLibStdCxxIncludePaths(
 void
 Generic_GCC::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
                                       llvm::opt::ArgStringList &CC1Args) const 
{
-  if (GCCInstallation.isValid()) {
-    addGCCLibStdCxxIncludePaths(DriverArgs, CC1Args,
-                                GCCInstallation.getTriple().str());
-  }
+  if (!GCCInstallation.isValid())
+    return;
+
+  GCCInstallation.getSelectedInstallation().addGCCLibStdCxxIncludePaths(
+      getVFS(), DriverArgs, CC1Args, GCCInstallation.getTriple().str());
 }
 
 llvm::opt::DerivedArgList *
diff --git a/clang/lib/Driver/ToolChains/Gnu.h 
b/clang/lib/Driver/ToolChains/Gnu.h
index faee6bd9758d6..099436abf57c1 100644
--- a/clang/lib/Driver/ToolChains/Gnu.h
+++ b/clang/lib/Driver/ToolChains/Gnu.h
@@ -244,13 +244,23 @@ class LLVM_LIBRARY_VISIBILITY Generic_GCC : public 
ToolChain {
     const std::string GentooConfigDir = "/etc/env.d/gcc";
 
   public:
-    bool RequireLibStdCxx;
+    /// Function for converting a Triple to a Debian multiarch.  The
+    /// toolchains use this to adjust the target specific component of
+    /// include paths for Debian.
+    std::function<StringRef(const llvm::Triple &)> TripleToDebianMultiarch =
+        [](const llvm::Triple &T) {
+          StringRef S = T.str();
+          return S;
+        };
 
-    explicit GCCInstallationDetector(const Driver &D)
-        : IsValid(false), D(D), RequireLibStdCxx(false) {}
+    explicit GCCInstallationDetector(const Driver &D) : IsValid(false), D(D) {}
 
-    void init(const llvm::Triple &TargetTriple, const llvm::opt::ArgList &Args,
-              std::optional<ToolChain::CXXStdlibType> CxxLibType);
+    void init(const llvm::Triple &TargetTriple, const llvm::opt::ArgList 
&Args);
+
+    // TODO Replace isValid by changing SelectedInstallation into
+    // std::optional<SelectedInstallation>
+    // and move all accessors for fields of GCCInstallCandidate into
+    // that struct.
 
     /// Check whether we detected a valid GCC install.
     bool isValid() const { return IsValid; }
@@ -307,11 +317,18 @@ class LLVM_LIBRARY_VISIBILITY Generic_GCC : public 
ToolChain {
                                SmallVectorImpl<std::string> &Prefixes,
                                StringRef SysRoot);
 
-    /// Checks if the \p GCCInstallation has the libs required
-    /// by the \p DriverArgs.
-    bool
-    GCCInstallationHasRequiredLibs(const GCCInstallCandidate &GCCInstallation,
-                                   const llvm::opt::ArgList &DriverArgs) const;
+    /// Checks if the \p GCCInstallation has libstdc++ include
+    /// directories.
+    bool GCCInstallationHasLibStdcxxIncludePaths(
+        const GCCInstallCandidate &GCCInstallation,
+        const llvm::opt::ArgList &DriverArgs) const;
+
+    /// Select a GCC installation directory from \p Installations.
+    /// Set \p SelectedInstallation
+    bool SelectGCCInstallationDirectory(
+        const SmallVector<GCCInstallCandidate, 3> &Installations,
+        const llvm::opt::ArgList &Args,
+        GCCInstallCandidate &SelectedInstallation) const;
 
     bool ScanGCCForMultilibs(const llvm::Triple &TargetTriple,
                              const llvm::opt::ArgList &Args, StringRef Path,
@@ -399,8 +416,7 @@ class LLVM_LIBRARY_VISIBILITY Generic_GCC : public 
ToolChain {
                            llvm::opt::ArgStringList &CC1Args) const;
 
   bool addGCCLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
-                                   llvm::opt::ArgStringList &CC1Args,
-                                   StringRef DebianMultiarch) const;
+                                   llvm::opt::ArgStringList &CC) const;
 
   bool addLibStdCXXIncludePaths(Twine IncludeDir, StringRef Triple,
                                 Twine IncludeSuffix,
diff --git a/clang/lib/Driver/ToolChains/Haiku.cpp 
b/clang/lib/Driver/ToolChains/Haiku.cpp
index 6c55a2f74724f..af74f43e48364 100644
--- a/clang/lib/Driver/ToolChains/Haiku.cpp
+++ b/clang/lib/Driver/ToolChains/Haiku.cpp
@@ -166,7 +166,7 @@ void haiku::Linker::ConstructJob(Compilation &C, const 
JobAction &JA,
 Haiku::Haiku(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
   : Generic_ELF(D, Triple, Args) {
 
-  GCCInstallation.init(Triple, Args, getCXXStdlibTypeInUse());
+  GCCInstallation.init(Triple, Args);
 
   getFilePaths().push_back(concat(getDriver().SysRoot, "/boot/system/lib"));
   getFilePaths().push_back(concat(getDriver().SysRoot, 
"/boot/system/develop/lib"));
diff --git a/clang/lib/Driver/ToolChains/Hurd.cpp 
b/clang/lib/Driver/ToolChains/Hurd.cpp
index efddd4b429869..e0f3f239776aa 100644
--- a/clang/lib/Driver/ToolChains/Hurd.cpp
+++ b/clang/lib/Driver/ToolChains/Hurd.cpp
@@ -71,7 +71,14 @@ static StringRef getOSLibDir(const llvm::Triple &Triple, 
const ArgList &Args) {
 
 Hurd::Hurd(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
     : Generic_ELF(D, Triple, Args) {
-  GCCInstallation.init(Triple, Args, getCXXStdlibTypeInUse());
+  GCCInstallation.TripleToDebianMultiarch = [](const llvm::Triple &T) {
+    StringRef TripleStr = T.str();
+    StringRef DebianMultiarch =
+        T.getArch() == llvm::Triple::x86 ? "i386-gnu" : TripleStr;
+    return DebianMultiarch;
+  };
+
+  GCCInstallation.init(Triple, Args);
   Multilibs = GCCInstallation.getMultilibs();
   SelectedMultilibs.assign({GCCInstallation.getMultilib()});
   std::string SysRoot = computeSysRoot();
@@ -207,12 +214,7 @@ void Hurd::addLibStdCxxIncludePaths(const 
llvm::opt::ArgList &DriverArgs,
   if (!GCCInstallation.isValid())
     return;
 
-  StringRef TripleStr = GCCInstallation.getTriple().str();
-  StringRef DebianMultiarch =
-      GCCInstallation.getTriple().getArch() == llvm::Triple::x86 ? "i386-gnu"
-                                                                 : TripleStr;
-
-  addGCCLibStdCxxIncludePaths(DriverArgs, CC1Args, DebianMultiarch);
+  addGCCLibStdCxxIncludePaths(DriverArgs, CC1Args);
 }
 
 void Hurd::addExtraOpts(llvm::opt::ArgStringList &CmdArgs) const {
diff --git a/clang/lib/Driver/ToolChains/Linux.cpp 
b/clang/lib/Driver/ToolChains/Linux.cpp
index 86bf610026226..65977d56af030 100644
--- a/clang/lib/Driver/ToolChains/Linux.cpp
+++ b/clang/lib/Driver/ToolChains/Linux.cpp
@@ -212,7 +212,14 @@ static StringRef getOSLibDir(const llvm::Triple &Triple, 
const ArgList &Args) {
 
 Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
     : Generic_ELF(D, Triple, Args) {
-  GCCInstallation.init(Triple, Args, getCXXStdlibTypeInUse());
+  GCCInstallation.TripleToDebianMultiarch = [](const llvm::Triple &T) {
+    StringRef TripleStr = T.str();
+    StringRef DebianMultiarch =
+        T.getArch() == llvm::Triple::x86 ? "i386-linux-gnu" : TripleStr;
+    return DebianMultiarch;
+  };
+
+  GCCInstallation.init(Triple, Args);
   Multilibs = GCCInstallation.getMultilibs();
   SelectedMultilibs.assign({GCCInstallation.getMultilib()});
   llvm::Triple::ArchType Arch = Triple.getArch();
@@ -701,22 +708,15 @@ void Linux::addLibStdCxxIncludePaths(const 
llvm::opt::ArgList &DriverArgs,
   if (!GCCInstallation.isValid())
     return;
 
-  // Detect Debian g++-multiarch-incdir.diff.
-  StringRef TripleStr = GCCInstallation.getTriple().str();
-  StringRef DebianMultiarch =
-      GCCInstallation.getTriple().getArch() == llvm::Triple::x86
-          ? "i386-linux-gnu"
-          : TripleStr;
-
   // Try generic GCC detection first.
-  if (Generic_GCC::addGCCLibStdCxxIncludePaths(DriverArgs, CC1Args,
-                                               DebianMultiarch))
+  if (Generic_GCC::addGCCLibStdCxxIncludePaths(DriverArgs, CC1Args))
     return;
 
   StringRef LibDir = GCCInstallation.getParentLibPath();
   const Multilib &Multilib = GCCInstallation.getMultilib();
   const GCCVersion &Version = GCCInstallation.getVersion();
 
+  StringRef TripleStr = GCCInstallation.getTriple().str();
   const std::string LibStdCXXIncludePathCandidates[] = {
       // Android standalone toolchain has C++ headers in yet another place.
       LibDir.str() + "/../" + TripleStr.str() + "/include/c++/" + Version.Text,
diff --git a/clang/lib/Driver/ToolChains/MSP430.cpp 
b/clang/lib/Driver/ToolChains/MSP430.cpp
index ed515f0f1373c..07e875c64960e 100644
--- a/clang/lib/Driver/ToolChains/MSP430.cpp
+++ b/clang/lib/Driver/ToolChains/MSP430.cpp
@@ -112,7 +112,7 @@ MSP430ToolChain::MSP430ToolChain(const Driver &D, const 
llvm::Triple &Triple,
 
   StringRef MultilibSuf = "";
 
-  GCCInstallation.init(Triple, Args, getCXXStdlibTypeInUse());
+  GCCInstallation.init(Triple, Args);
   if (GCCInstallation.isValid()) {
     MultilibSuf = GCCInstallation.getMultilib().gccSuffix();
 
diff --git a/clang/lib/Driver/ToolChains/RISCVToolchain.cpp 
b/clang/lib/Driver/ToolChains/RISCVToolchain.cpp
index e5d1e550f5453..624099d21ae12 100644
--- a/clang/lib/Driver/ToolChains/RISCVToolchain.cpp
+++ b/clang/lib/Driver/ToolChains/RISCVToolchain.cpp
@@ -50,7 +50,7 @@ bool RISCVToolChain::hasGCCToolchain(const Driver &D,
 RISCVToolChain::RISCVToolChain(const Driver &D, const llvm::Triple &Triple,
                                const ArgList &Args)
     : Generic_ELF(D, Triple, Args) {
-  GCCInstallation.init(Triple, Args, getCXXStdlibTypeInUse());
+  GCCInstallation.init(Triple, Args);
   if (GCCInstallation.isValid()) {
     Multilibs = GCCInstallation.getMultilibs();
     SelectedMultilibs.assign({GCCInstallation.getMultilib()});
diff --git a/clang/lib/Driver/ToolChains/Solaris.cpp 
b/clang/lib/Driver/ToolChains/Solaris.cpp
index 1153c2ac319cb..fd3232b7c1b06 100644
--- a/clang/lib/Driver/ToolChains/Solaris.cpp
+++ b/clang/lib/Driver/ToolChains/Solaris.cpp
@@ -310,7 +310,7 @@ Solaris::Solaris(const Driver &D, const llvm::Triple 
&Triple,
                  const ArgList &Args)
     : Generic_ELF(D, Triple, Args) {
 
-  GCCInstallation.init(Triple, Args, getCXXStdlibTypeInUse());
+  GCCInstallation.init(Triple, Args);
 
   StringRef LibSuffix = getSolarisLibSuffix(Triple);
   path_list &Paths = getFilePaths();
diff --git 
a/clang/test/Driver/Inputs/powerpc64le-linux-gnu-tree/gcc-11.2.0/include/c++/11.2.0/.keep
 
b/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc10/usr/lib/gcc/x86_64-linux-gnu/10/crtbegin.o
similarity index 100%
rename from 
clang/test/Driver/Inputs/powerpc64le-linux-gnu-tree/gcc-11.2.0/include/c++/11.2.0/.keep
rename to 
clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc10/usr/lib/gcc/x86_64-linux-gnu/10/crtbegin.o
diff --git 
a/clang/test/Driver/Inputs/powerpc64le-linux-gnu-tree/gcc-12/include/c++/12/.keep
 
b/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc10/usr/lib/gcc/x86_64-linux-gnu/10/crtend.o
similarity index 100%
rename from 
clang/test/Driver/Inputs/powerpc64le-linux-gnu-tree/gcc-12/include/c++/12/.keep
rename to 
clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc10/usr/lib/gcc/x86_64-linux-gnu/10/crtend.o
diff --git 
a/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc10/usr/lib/gcc/x86_64-linux-gnu/11/crtbegin.o
 
b/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc10/usr/lib/gcc/x86_64-linux-gnu/11/crtbegin.o
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git 
a/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc10/usr/lib/gcc/x86_64-linux-gnu/11/crtend.o
 
b/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc10/usr/lib/gcc/x86_64-linux-gnu/11/crtend.o
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git 
a/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc10/usr/lib/gcc/x86_64-linux-gnu/11/include/.keep
 
b/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc10/usr/lib/gcc/x86_64-linux-gnu/11/include/.keep
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git 
a/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc10/usr/lib/gcc/x86_64-linux-gnu/12/crtbegin.o
 
b/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc10/usr/lib/gcc/x86_64-linux-gnu/12/crtbegin.o
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git 
a/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc10/usr/lib/gcc/x86_64-linux-gnu/12/crtend.o
 
b/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc10/usr/lib/gcc/x86_64-linux-gnu/12/crtend.o
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git 
a/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc10/usr/lib/gcc/x86_64-linux-gnu/12/include/.keep
 
b/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc10/usr/lib/gcc/x86_64-linux-gnu/12/include/.keep
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git 
a/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc11/usr/lib/gcc/x86_64-linux-gnu/10/crtbegin.o
 
b/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc11/usr/lib/gcc/x86_64-linux-gnu/10/crtbegin.o
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git 
a/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc11/usr/lib/gcc/x86_64-linux-gnu/10/crtend.o
 
b/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc11/usr/lib/gcc/x86_64-linux-gnu/10/crtend.o
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git 
a/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc11/usr/lib/gcc/x86_64-linux-gnu/10/include/.keep
 
b/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc11/usr/lib/gcc/x86_64-linux-gnu/10/include/.keep
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git 
a/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc11/usr/lib/gcc/x86_64-linux-gnu/11/crtbegin.o
 
b/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc11/usr/lib/gcc/x86_64-linux-gnu/11/crtbegin.o
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git 
a/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc11/usr/lib/gcc/x86_64-linux-gnu/11/crtend.o
 
b/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc11/usr/lib/gcc/x86_64-linux-gnu/11/crtend.o
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git 
a/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc11/usr/lib/gcc/x86_64-linux-gnu/12/crtbegin.o
 
b/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc11/usr/lib/gcc/x86_64-linux-gnu/12/crtbegin.o
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git 
a/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc11/usr/lib/gcc/x86_64-linux-gnu/12/crtend.o
 
b/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc11/usr/lib/gcc/x86_64-linux-gnu/12/crtend.o
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git 
a/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc11/usr/lib/gcc/x86_64-linux-gnu/12/include/.keep
 
b/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc11/usr/lib/gcc/x86_64-linux-gnu/12/include/.keep
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git 
a/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc12/usr/lib/gcc/x86_64-linux-gnu/10/crtbegin.o
 
b/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc12/usr/lib/gcc/x86_64-linux-gnu/10/crtbegin.o
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git 
a/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc12/usr/lib/gcc/x86_64-linux-gnu/10/crtend.o
 
b/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc12/usr/lib/gcc/x86_64-linux-gnu/10/crtend.o
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git 
a/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc12/usr/lib/gcc/x86_64-linux-gnu/10/include/.keep
 
b/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc12/usr/lib/gcc/x86_64-linux-gnu/10/include/.keep
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git 
a/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc12/usr/lib/gcc/x86_64-linux-gnu/11/crtbegin.o
 
b/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc12/usr/lib/gcc/x86_64-linux-gnu/11/crtbegin.o
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git 
a/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc12/usr/lib/gcc/x86_64-linux-gnu/11/crtend.o
 
b/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc12/usr/lib/gcc/x86_64-linux-gnu/11/crtend.o
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git 
a/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc12/usr/lib/gcc/x86_64-linux-gnu/12/crtbegin.o
 
b/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc12/usr/lib/gcc/x86_64-linux-gnu/12/crtbegin.o
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git 
a/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc12/usr/lib/gcc/x86_64-linux-gnu/12/crtend.o
 
b/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc12/usr/lib/gcc/x86_64-linux-gnu/12/crtend.o
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/clang/test/Driver/gcc-toolchain-libstdcxx.cpp 
b/clang/test/Driver/gcc-toolchain-libstdcxx.cpp
new file mode 100644
index 0000000000000..6ec1674500022
--- /dev/null
+++ b/clang/test/Driver/gcc-toolchain-libstdcxx.cpp
@@ -0,0 +1,28 @@
+// UNSUPPORTED: system-windows
+
+// This file tests that the GCC installation directory detection takes
+// the libstdc++ includes into account.  In each directory
+// Inputs/gcc_toolchain_libstdcxx/gccX, the installation directory for
+// gcc X should be picked in the future since it is the directory with
+// the largest version number which also contains the libstdc++
+// include directory.
+
+// RUN: %clang --gcc-toolchain=%S/Inputs/gcc_toolchain_libstdcxx/gcc10/usr -v 
2>&1 |& FileCheck %s --check-prefix=GCC10
+// GCC10: clang: warning: future releases of the clang compiler will prefer 
GCC installations containing libstdc++ include directories; 
'[[PREFIX:.*gcc_toolchain_libstdcxx/gcc10/usr/lib/gcc/x86_64-linux-gnu]]/10' 
would be chosen over '[[PREFIX]]/12' [-Wgcc-install-dir-libstdcxx]
+// GCC10: Found candidate GCC installation: [[PREFIX]]/10
+// GCC10: Found candidate GCC installation: [[PREFIX]]/11
+// GCC10: Found candidate GCC installation: [[PREFIX]]/12
+// GCC10: Selected GCC installation: [[PREFIX]]/12
+
+// RUN: %clang --gcc-toolchain=%S/Inputs/gcc_toolchain_libstdcxx/gcc11/usr -v 
2>&1 |& FileCheck %s --check-prefix=ONLY_GCC11
+// ONLY_GCC11: clang: warning: future releases of the clang compiler will 
prefer GCC installations containing libstdc++ include directories; 
'[[PREFIX:.*gcc_toolchain_libstdcxx/gcc11/usr/lib/gcc/x86_64-linux-gnu]]/11' 
would be chosen over '[[PREFIX]]/12' [-Wgcc-install-dir-libstdcxx]
+// ONLY_GCC11: Found candidate GCC installation: [[PREFIX]]/10
+// ONLY_GCC11: Found candidate GCC installation: [[PREFIX]]/11
+// ONLY_GCC11: Found candidate GCC installation: [[PREFIX]]/12
+// ONLY_GCC11: Selected GCC installation: [[PREFIX]]/12
+
+// RUN: %clang --gcc-toolchain=%S/Inputs/gcc_toolchain_libstdcxx/gcc12/usr -v 
2>&1 |& FileCheck %s --check-prefix=GCC12
+// GCC12: Found candidate GCC installation: 
[[PREFIX:.*gcc_toolchain_libstdcxx/gcc12/usr/lib/gcc/x86_64-linux-gnu]]/10
+// GCC12: Found candidate GCC installation: [[PREFIX]]/11
+// GCC12: Found candidate GCC installation: [[PREFIX]]/12
+// GCC12: Selected GCC installation: [[PREFIX]]/12

>From d1271ef4c8920bd00f69a79407af2ea62c54394f Mon Sep 17 00:00:00 2001
From: Frederik Harwath <fharw...@amd.com>
Date: Tue, 8 Jul 2025 17:00:18 +0200
Subject: [PATCH 3/7] Remove some unnecessary code movement

---
 .../clang/Basic/DiagnosticDriverKinds.td      |  2 --
 clang/include/clang/Driver/ToolChain.h        | 23 ++++++++-----------
 clang/lib/Driver/ToolChain.cpp                | 16 ++++++-------
 clang/lib/Driver/ToolChains/Managarm.cpp      |  4 +---
 4 files changed, 19 insertions(+), 26 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td 
b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 7f27f1e64cd7f..c91517f9796ff 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -874,11 +874,9 @@ def warn_drv_openacc_without_cir
     : Warning<"OpenACC directives will result in no runtime behavior; use "
               "-fclangir to enable runtime effect">,
       InGroup<SourceUsesOpenACC>;
-}
 
 def warn_drv_gcc_install_dir_libstdcxx : Warning<
     "future releases of the clang compiler will prefer GCC installations "
     "containing libstdc++ include directories; '%0' would be chosen over 
'%1'">,
     InGroup<DiagGroup<"gcc-install-dir-libstdcxx">>;
 }
-
diff --git a/clang/include/clang/Driver/ToolChain.h 
b/clang/include/clang/Driver/ToolChain.h
index a441aa65a87c5..61c70bd4c0288 100644
--- a/clang/include/clang/Driver/ToolChain.h
+++ b/clang/include/clang/Driver/ToolChain.h
@@ -228,29 +228,26 @@ class ToolChain {
   static void addSystemFrameworkInclude(const llvm::opt::ArgList &DriverArgs,
                                         llvm::opt::ArgStringList &CC1Args,
                                         const Twine &Path);
-
   static void addExternCSystemInclude(const llvm::opt::ArgList &DriverArgs,
                                       llvm::opt::ArgStringList &CC1Args,
                                       const Twine &Path);
-  static std::string concat(StringRef Path, const Twine &A, const Twine &B = 
"",
-                            const Twine &C = "", const Twine &D = "");
-  ///@}
-
-public:
-  static void addSystemInclude(const llvm::opt::ArgList &DriverArgs,
-                               llvm::opt::ArgStringList &CC1Args,
-                               const Twine &Path);
   static void
-  addExternCSystemIncludeIfExists(const llvm::opt::ArgList &DriverArgs,
-                                  llvm::opt::ArgStringList &CC1Args,
-                                  const Twine &Path);
+      addExternCSystemIncludeIfExists(const llvm::opt::ArgList &DriverArgs,
+                                      llvm::opt::ArgStringList &CC1Args,
+                                      const Twine &Path);
   static void addSystemFrameworkIncludes(const llvm::opt::ArgList &DriverArgs,
                                          llvm::opt::ArgStringList &CC1Args,
                                          ArrayRef<StringRef> Paths);
   static void addSystemIncludes(const llvm::opt::ArgList &DriverArgs,
                                 llvm::opt::ArgStringList &CC1Args,
                                 ArrayRef<StringRef> Paths);
-
+  static std::string concat(StringRef Path, const Twine &A, const Twine &B = 
"",
+                            const Twine &C = "", const Twine &D = "");
+  ///@}
+public:
+  static void addSystemInclude(const llvm::opt::ArgList &DriverArgs,
+                               llvm::opt::ArgStringList &CC1Args,
+                               const Twine &Path);
   virtual ~ToolChain();
 
   // Accessors
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index c9769d818d344..c8b6283e4dad0 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -1370,6 +1370,14 @@ ToolChain::CXXStdlibType 
ToolChain::GetCXXStdlibType(const ArgList &Args) const{
   return *cxxStdlibType;
 }
 
+/// Utility function to add a system framework directory to CC1 arguments.
+void ToolChain::addSystemFrameworkInclude(const llvm::opt::ArgList &DriverArgs,
+                                          llvm::opt::ArgStringList &CC1Args,
+                                          const Twine &Path) {
+  CC1Args.push_back("-internal-iframework");
+  CC1Args.push_back(DriverArgs.MakeArgString(Path));
+}
+
 /// Utility function to add a system include directory with extern "C"
 /// semantics to CC1 arguments.
 ///
@@ -1400,14 +1408,6 @@ void ToolChain::addExternCSystemIncludeIfExists(const 
ArgList &DriverArgs,
   CC1Args.push_back(DriverArgs.MakeArgString(Path));
 }
 
-/// Utility function to add a system framework directory to CC1 arguments.
-void ToolChain::addSystemFrameworkInclude(const llvm::opt::ArgList &DriverArgs,
-                                          llvm::opt::ArgStringList &CC1Args,
-                                          const Twine &Path) {
-  CC1Args.push_back("-internal-iframework");
-  CC1Args.push_back(DriverArgs.MakeArgString(Path));
-}
-
 /// Utility function to add a list of system framework directories to CC1.
 void ToolChain::addSystemFrameworkIncludes(const ArgList &DriverArgs,
                                            ArgStringList &CC1Args,
diff --git a/clang/lib/Driver/ToolChains/Managarm.cpp 
b/clang/lib/Driver/ToolChains/Managarm.cpp
index 0f56f0f6aad77..da4a9072317f4 100644
--- a/clang/lib/Driver/ToolChains/Managarm.cpp
+++ b/clang/lib/Driver/ToolChains/Managarm.cpp
@@ -193,10 +193,8 @@ void Managarm::addLibStdCxxIncludePaths(
   if (!GCCInstallation.isValid())
     return;
 
-  StringRef TripleStr = GCCInstallation.getTriple().str();
-
   // Try generic GCC detection.
-  Generic_GCC::addGCCLibStdCxxIncludePaths(DriverArgs, CC1Args, TripleStr);
+  addGCCLibStdCxxIncludePaths(DriverArgs, CC1Args);
 }
 
 SanitizerMask Managarm::getSupportedSanitizers() const {

>From f37db8df9b01883ce75cf95ae0ba33bb282c4c39 Mon Sep 17 00:00:00 2001
From: Frederik Harwath <fharw...@amd.com>
Date: Tue, 8 Jul 2025 17:25:51 +0200
Subject: [PATCH 4/7] Correct spelling mistakes

---
 clang/lib/Driver/ToolChains/Gnu.cpp | 5 +++--
 clang/lib/Driver/ToolChains/Gnu.h   | 2 +-
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp 
b/clang/lib/Driver/ToolChains/Gnu.cpp
index e52b1cbcbdbc7..21686cc01d180 100644
--- a/clang/lib/Driver/ToolChains/Gnu.cpp
+++ b/clang/lib/Driver/ToolChains/Gnu.cpp
@@ -2805,8 +2805,9 @@ bool 
Generic_GCC::GCCInstallationDetector::SelectGCCInstallationDirectory(
       });
 
   // FIXME Start selecting installation with libstdc++ in clang 22,
-  // using the current way of selecting the installation as a fallback only.
-  // For now, warn if install with libstdc++ differs SelectedInstallation.
+  // using the current way of selecting the installation as a fallback
+  // only.  For now, warn if the installation with libstdc++ differs
+  // from SelectedInstallation.
   const GCCInstallCandidate *InstallWithIncludes = nullptr;
   for (const auto &I : Installations) {
     if ((!InstallWithIncludes || I.Version > InstallWithIncludes->Version) &&
diff --git a/clang/lib/Driver/ToolChains/Gnu.h 
b/clang/lib/Driver/ToolChains/Gnu.h
index 099436abf57c1..ba766ba0f02bb 100644
--- a/clang/lib/Driver/ToolChains/Gnu.h
+++ b/clang/lib/Driver/ToolChains/Gnu.h
@@ -244,7 +244,7 @@ class LLVM_LIBRARY_VISIBILITY Generic_GCC : public 
ToolChain {
     const std::string GentooConfigDir = "/etc/env.d/gcc";
 
   public:
-    /// Function for converting a Triple to a Debian multiarch.  The
+    /// Function for converting a triple to a Debian multiarch.  The
     /// toolchains use this to adjust the target specific component of
     /// include paths for Debian.
     std::function<StringRef(const llvm::Triple &)> TripleToDebianMultiarch =

>From 07fb1afdad3179b7a00e1b88c301b12ab92aca35 Mon Sep 17 00:00:00 2001
From: Frederik Harwath <fharw...@amd.com>
Date: Tue, 8 Jul 2025 17:27:49 +0200
Subject: [PATCH 5/7] Fix comment

---
 clang/lib/Driver/ToolChains/Gnu.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/lib/Driver/ToolChains/Gnu.h 
b/clang/lib/Driver/ToolChains/Gnu.h
index ba766ba0f02bb..19642336ee2e8 100644
--- a/clang/lib/Driver/ToolChains/Gnu.h
+++ b/clang/lib/Driver/ToolChains/Gnu.h
@@ -323,8 +323,8 @@ class LLVM_LIBRARY_VISIBILITY Generic_GCC : public 
ToolChain {
         const GCCInstallCandidate &GCCInstallation,
         const llvm::opt::ArgList &DriverArgs) const;
 
-    /// Select a GCC installation directory from \p Installations.
-    /// Set \p SelectedInstallation
+    /// Select a GCC installation directory from \p Installations and
+    /// set \p SelectedInstallation accordingly.
     bool SelectGCCInstallationDirectory(
         const SmallVector<GCCInstallCandidate, 3> &Installations,
         const llvm::opt::ArgList &Args,

>From 90d6164ef1ead89696e0a0d2b4de58f5fae10bbe Mon Sep 17 00:00:00 2001
From: Frederik Harwath <fharw...@amd.com>
Date: Tue, 8 Jul 2025 18:31:11 +0200
Subject: [PATCH 6/7] Add .keep files to empty directories

---
 .../gcc10/usr/lib/gcc/x86_64-linux-gnu/10/include/c++/.keep       | 0
 .../gcc11/usr/lib/gcc/x86_64-linux-gnu/11/include/c++/.keep       | 0
 .../gcc12/usr/lib/gcc/x86_64-linux-gnu/11/include/c++/.keep       | 0
 .../gcc12/usr/lib/gcc/x86_64-linux-gnu/12/include/c++/.keep       | 0
 4 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 
clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc10/usr/lib/gcc/x86_64-linux-gnu/10/include/c++/.keep
 create mode 100644 
clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc11/usr/lib/gcc/x86_64-linux-gnu/11/include/c++/.keep
 create mode 100644 
clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc12/usr/lib/gcc/x86_64-linux-gnu/11/include/c++/.keep
 create mode 100644 
clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc12/usr/lib/gcc/x86_64-linux-gnu/12/include/c++/.keep

diff --git 
a/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc10/usr/lib/gcc/x86_64-linux-gnu/10/include/c++/.keep
 
b/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc10/usr/lib/gcc/x86_64-linux-gnu/10/include/c++/.keep
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git 
a/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc11/usr/lib/gcc/x86_64-linux-gnu/11/include/c++/.keep
 
b/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc11/usr/lib/gcc/x86_64-linux-gnu/11/include/c++/.keep
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git 
a/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc12/usr/lib/gcc/x86_64-linux-gnu/11/include/c++/.keep
 
b/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc12/usr/lib/gcc/x86_64-linux-gnu/11/include/c++/.keep
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git 
a/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc12/usr/lib/gcc/x86_64-linux-gnu/12/include/c++/.keep
 
b/clang/test/Driver/Inputs/gcc_toolchain_libstdcxx/gcc12/usr/lib/gcc/x86_64-linux-gnu/12/include/c++/.keep
new file mode 100644
index 0000000000000..e69de29bb2d1d

>From 3d7fc7050a5dbb261489c4a4865fc727e1fba376 Mon Sep 17 00:00:00 2001
From: Frederik Harwath <fharw...@amd.com>
Date: Wed, 9 Jul 2025 10:23:18 +0200
Subject: [PATCH 7/7] Remove whitespace changes and reintroduce deleted FIXME

---
 clang/include/clang/Driver/ToolChain.h | 2 ++
 clang/lib/Driver/ToolChains/AVR.cpp    | 1 -
 clang/lib/Driver/ToolChains/Gnu.h      | 1 +
 3 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/clang/include/clang/Driver/ToolChain.h 
b/clang/include/clang/Driver/ToolChain.h
index 61c70bd4c0288..b1d1ae2e111c9 100644
--- a/clang/include/clang/Driver/ToolChain.h
+++ b/clang/include/clang/Driver/ToolChain.h
@@ -241,9 +241,11 @@ class ToolChain {
   static void addSystemIncludes(const llvm::opt::ArgList &DriverArgs,
                                 llvm::opt::ArgStringList &CC1Args,
                                 ArrayRef<StringRef> Paths);
+
   static std::string concat(StringRef Path, const Twine &A, const Twine &B = 
"",
                             const Twine &C = "", const Twine &D = "");
   ///@}
+
 public:
   static void addSystemInclude(const llvm::opt::ArgList &DriverArgs,
                                llvm::opt::ArgStringList &CC1Args,
diff --git a/clang/lib/Driver/ToolChains/AVR.cpp 
b/clang/lib/Driver/ToolChains/AVR.cpp
index 5b275c1f8be54..731076d9754a9 100644
--- a/clang/lib/Driver/ToolChains/AVR.cpp
+++ b/clang/lib/Driver/ToolChains/AVR.cpp
@@ -433,7 +433,6 @@ const StringRef PossibleAVRLibcLocations[] = {
 AVRToolChain::AVRToolChain(const Driver &D, const llvm::Triple &Triple,
                            const ArgList &Args)
     : Generic_ELF(D, Triple, Args) {
-
   GCCInstallation.init(Triple, Args);
 
   if (getCPUName(D, Args, Triple).empty())
diff --git a/clang/lib/Driver/ToolChains/Gnu.h 
b/clang/lib/Driver/ToolChains/Gnu.h
index 19642336ee2e8..1842ef5a548be 100644
--- a/clang/lib/Driver/ToolChains/Gnu.h
+++ b/clang/lib/Driver/ToolChains/Gnu.h
@@ -185,6 +185,7 @@ class LLVM_LIBRARY_VISIBILITY Generic_GCC : public 
ToolChain {
   };
 
   struct GCCInstallCandidate {
+    // FIXME: These might be better as path objects.
     std::string GCCInstallPath;
     std::string GCCParentLibPath;
 

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

Reply via email to