[clang] [Clang] Take libstdc++ into account during GCC detection (PR #145056)
Frederik Harwath via cfe-commits
cfe-commits at lists.llvm.org
Wed Jul 9 01:25:38 PDT 2025
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 <fharwath at 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 <fharwath at 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 <fharwath at 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 <fharwath at 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 <fharwath at 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 <fharwath at 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 <fharwath at 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;
More information about the cfe-commits
mailing list