https://github.com/philnik777 created https://github.com/llvm/llvm-project/pull/83723
- [Clang][Driver] Merge the different strategies of how libc++ is included - [Clang][Driver] Add special-casing for including libc++ in C++03 >From 756f80f22744bb0f2bfb81e6c4010054f1279337 Mon Sep 17 00:00:00 2001 From: Nikolas Klauser <nikolasklau...@berlin.de> Date: Fri, 1 Mar 2024 20:49:30 +0100 Subject: [PATCH 1/2] [Clang][Driver] Merge the different strategies of how libc++ is included --- clang/include/clang/Driver/ToolChain.h | 41 ++++++++++++++++++++ clang/lib/Driver/ToolChain.cpp | 41 ++++++++++++++++++++ clang/lib/Driver/ToolChains/AIX.cpp | 10 ++--- clang/lib/Driver/ToolChains/BareMetal.cpp | 13 +++---- clang/lib/Driver/ToolChains/CrossWindows.cpp | 3 +- clang/lib/Driver/ToolChains/Darwin.cpp | 32 ++++++--------- clang/lib/Driver/ToolChains/FreeBSD.cpp | 5 ++- clang/lib/Driver/ToolChains/Fuchsia.cpp | 22 ++--------- clang/lib/Driver/ToolChains/Gnu.cpp | 6 +-- clang/lib/Driver/ToolChains/Haiku.cpp | 5 ++- clang/lib/Driver/ToolChains/Hexagon.cpp | 27 ++++++++----- clang/lib/Driver/ToolChains/MinGW.cpp | 16 +++----- clang/lib/Driver/ToolChains/MipsLinux.cpp | 7 ++-- clang/lib/Driver/ToolChains/NaCl.cpp | 16 ++++---- clang/lib/Driver/ToolChains/NetBSD.cpp | 20 +++++----- clang/lib/Driver/ToolChains/OHOS.cpp | 9 ++--- clang/lib/Driver/ToolChains/OpenBSD.cpp | 5 ++- clang/lib/Driver/ToolChains/WebAssembly.cpp | 4 +- clang/lib/Driver/ToolChains/ZOS.cpp | 22 ++++------- clang/lib/Driver/ToolChains/ZOS.h | 3 -- 20 files changed, 178 insertions(+), 129 deletions(-) diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h index fbe2e8fe8e88d8..c61cf2aa064ed5 100644 --- a/clang/include/clang/Driver/ToolChain.h +++ b/clang/include/clang/Driver/ToolChain.h @@ -705,6 +705,47 @@ class ToolChain { AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const; + struct IncludeStrategy { + enum AvailabilityOptions { + // Check whether the directory is exists before adding it to the + // include path. This is the case if AssumeAvailable isn't set. + CheckIfAvailable, + + // Don't check whether the directory exists. Just assume it does and add + // the include. + AssumeAvailable, + + // Use v<MaxNumber> that is inside `<IncludeRoot>/c++`. If not set, always + // uses v1. + UseMaxVersionAvailable, + }; + + IncludeStrategy(AvailabilityOptions Availability, + bool AddTargetDirIfAvailable = false, + bool PrintDebugStatements = false) + : Availability(Availability), + AddTargetDirIfAvailable(AddTargetDirIfAvailable), + PrintDebugStatements(PrintDebugStatements) {} + + LLVM_PREFERRED_TYPE(AvailabilityOptions) + unsigned Availability : 2; + + // Check whether the directory `<IncludeRoot>/<target-triple>/c++/v<N>` + // exists, and add it to the include path if it does. + LLVM_PREFERRED_TYPE(bool) + unsigned AddTargetDirIfAvailable : 1; + + // Whether to print a message if a checked directory isn't available. + LLVM_PREFERRED_TYPE(bool) + unsigned PrintDebugStatements : 1; + }; + + /// Helper function to implement AddClangCXXStdlibIncludeArgs for libc++. + bool AddLibcxxInclude(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args, + llvm::Twine IncludeRoot, + IncludeStrategy Strategy) const; + /// AddClangCXXStdlibIsystemArgs - Add the clang -cc1 level arguments to set /// the specified include paths for the C++ standard library. void AddClangCXXStdlibIsystemArgs(const llvm::opt::ArgList &DriverArgs, diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index 08b1fd01b3c0ac..42c9d6e91d3c35 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -40,6 +40,7 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/FileUtilities.h" #include "llvm/Support/Path.h" +#include "llvm/Support/WithColor.h" #include "llvm/Support/VersionTuple.h" #include "llvm/Support/VirtualFileSystem.h" #include "llvm/TargetParser/AArch64TargetParser.h" @@ -1250,6 +1251,46 @@ void ToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, DriverArgs.AddAllArgs(CC1Args, options::OPT_stdlib_EQ); } +bool ToolChain::AddLibcxxInclude(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args, + llvm::Twine IncludeRoot, + IncludeStrategy Strategy) const { + SmallString<128> Path; + IncludeRoot.toVector(Path); + + auto VersionDirName = + Strategy.Availability == IncludeStrategy::UseMaxVersionAvailable + ? detectLibcxxVersion(Path) + : "v1"; + + if (VersionDirName.empty()) + return false; + + if (Strategy.AddTargetDirIfAvailable) { + SmallString<128> TargetDir(Path); + llvm::sys::path::append(TargetDir, getTripleString(), "c++", + VersionDirName); + if (getVFS().exists(TargetDir)) + addSystemInclude(DriverArgs, CC1Args, TargetDir); + } + + llvm::sys::path::append(Path, "c++", VersionDirName); + + if ((Strategy.Availability != IncludeStrategy::AssumeAvailable || + Strategy.PrintDebugStatements) && + !D.getVFS().exists(Path)) { + if (Strategy.PrintDebugStatements) + WithColor::warning(errs(), "Clang") + << "ignoring nonexistent directory \"" << Path << "\"\n"; + + if (Strategy.Availability != IncludeStrategy::AssumeAvailable) + return false; + } + + addSystemInclude(DriverArgs, CC1Args, Path.str()); + return true; +} + void ToolChain::AddClangCXXStdlibIsystemArgs( const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const { diff --git a/clang/lib/Driver/ToolChains/AIX.cpp b/clang/lib/Driver/ToolChains/AIX.cpp index e6126ff62db3c9..017ab3182b1e46 100644 --- a/clang/lib/Driver/ToolChains/AIX.cpp +++ b/clang/lib/Driver/ToolChains/AIX.cpp @@ -404,11 +404,11 @@ void AIX::AddClangCXXStdlibIncludeArgs( llvm::report_fatal_error( "picking up libstdc++ headers is unimplemented on AIX"); case ToolChain::CST_Libcxx: { - llvm::StringRef Sysroot = GetHeaderSysroot(DriverArgs); - SmallString<128> PathCPP(Sysroot); - llvm::sys::path::append(PathCPP, "opt/IBM/openxlCSDK", "include", "c++", - "v1"); - addSystemInclude(DriverArgs, CC1Args, PathCPP.str()); + llvm::SmallString<128> Path = GetHeaderSysroot(DriverArgs); + llvm::sys::path::append(Path, "opt/IBM/openxlCSDK/include"); + ToolChain::AddLibcxxInclude(DriverArgs, CC1Args, Path, + IncludeStrategy::AssumeAvailable); + // Required in order to suppress conflicting C++ overloads in the system // libc headers that were used by XL C++. CC1Args.push_back("-D__LIBC_NO_CPP_MATH_OVERLOADS__"); diff --git a/clang/lib/Driver/ToolChains/BareMetal.cpp b/clang/lib/Driver/ToolChains/BareMetal.cpp index d5fc1d5dd25a8b..3f4edb1e82e5f2 100644 --- a/clang/lib/Driver/ToolChains/BareMetal.cpp +++ b/clang/lib/Driver/ToolChains/BareMetal.cpp @@ -309,14 +309,13 @@ void BareMetal::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, case ToolChain::CST_Libcxx: { // First check sysroot/usr/include/c++/v1 if it exists. SmallString<128> TargetDir(Dir); - llvm::sys::path::append(TargetDir, "usr", "include", "c++", "v1"); - if (D.getVFS().exists(TargetDir)) { - addSystemInclude(DriverArgs, CC1Args, TargetDir.str()); - break; + llvm::sys::path::append(TargetDir, "usr", "include"); + if (!ToolChain::AddLibcxxInclude(DriverArgs, CC1Args, TargetDir.str(), + IncludeStrategy::CheckIfAvailable)) { + llvm::sys::path::append(Dir, "include"); + ToolChain::AddLibcxxInclude(DriverArgs, CC1Args, Dir.str(), + IncludeStrategy::AssumeAvailable); } - // Add generic path if nothing else succeeded so far. - llvm::sys::path::append(Dir, "include", "c++", "v1"); - addSystemInclude(DriverArgs, CC1Args, Dir.str()); break; } case ToolChain::CST_Libstdcxx: { diff --git a/clang/lib/Driver/ToolChains/CrossWindows.cpp b/clang/lib/Driver/ToolChains/CrossWindows.cpp index 3c5dfba329cf8e..df8b7cbd253fc3 100644 --- a/clang/lib/Driver/ToolChains/CrossWindows.cpp +++ b/clang/lib/Driver/ToolChains/CrossWindows.cpp @@ -269,7 +269,8 @@ AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs, return; if (GetCXXStdlibType(DriverArgs) == ToolChain::CST_Libcxx) - addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include/c++/v1"); + ToolChain::AddLibcxxInclude(DriverArgs, CC1Args, SysRoot + "/usr/include", + IncludeStrategy::AssumeAvailable); } void CrossWindowsToolChain:: diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp index cc1219d69d9910..6eb72b705a2da0 100644 --- a/clang/lib/Driver/ToolChains/Darwin.cpp +++ b/clang/lib/Driver/ToolChains/Darwin.cpp @@ -2536,38 +2536,28 @@ void DarwinClang::AddClangCXXStdlibIncludeArgs( // parent_path. llvm::SmallString<128> InstallBin = llvm::StringRef(getDriver().getInstalledDir()); // <install>/bin - llvm::sys::path::append(InstallBin, "..", "include", "c++", "v1"); - if (getVFS().exists(InstallBin)) { - addSystemInclude(DriverArgs, CC1Args, InstallBin); + llvm::sys::path::append(InstallBin, "..", "include"); + IncludeStrategy Strategy = IncludeStrategy::CheckIfAvailable; + Strategy.PrintDebugStatements = DriverArgs.hasArg(options::OPT_v); + if (ToolChain::AddLibcxxInclude(DriverArgs, CC1Args, InstallBin.str(), + Strategy)) return; - } else if (DriverArgs.hasArg(options::OPT_v)) { - llvm::errs() << "ignoring nonexistent directory \"" << InstallBin - << "\"\n"; - } // (2) Check for the folder where the executable is located, if different. if (getDriver().getInstalledDir() != getDriver().Dir) { InstallBin = llvm::StringRef(getDriver().Dir); - llvm::sys::path::append(InstallBin, "..", "include", "c++", "v1"); - if (getVFS().exists(InstallBin)) { - addSystemInclude(DriverArgs, CC1Args, InstallBin); + llvm::sys::path::append(InstallBin, "..", "include"); + if (ToolChain::AddLibcxxInclude(DriverArgs, CC1Args, InstallBin.str(), + Strategy)) return; - } else if (DriverArgs.hasArg(options::OPT_v)) { - llvm::errs() << "ignoring nonexistent directory \"" << InstallBin - << "\"\n"; - } } // Otherwise, check for (3) llvm::SmallString<128> SysrootUsr = Sysroot; - llvm::sys::path::append(SysrootUsr, "usr", "include", "c++", "v1"); - if (getVFS().exists(SysrootUsr)) { - addSystemInclude(DriverArgs, CC1Args, SysrootUsr); + llvm::sys::path::append(SysrootUsr, "usr", "include"); + if (ToolChain::AddLibcxxInclude(DriverArgs, CC1Args, SysrootUsr.str(), + Strategy)) return; - } else if (DriverArgs.hasArg(options::OPT_v)) { - llvm::errs() << "ignoring nonexistent directory \"" << SysrootUsr - << "\"\n"; - } // Otherwise, don't add any path. break; diff --git a/clang/lib/Driver/ToolChains/FreeBSD.cpp b/clang/lib/Driver/ToolChains/FreeBSD.cpp index b7c9e0e51cdb66..66ff56ccbf5398 100644 --- a/clang/lib/Driver/ToolChains/FreeBSD.cpp +++ b/clang/lib/Driver/ToolChains/FreeBSD.cpp @@ -436,8 +436,9 @@ void FreeBSD::AddClangSystemIncludeArgs( void FreeBSD::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const { - addSystemInclude(DriverArgs, CC1Args, - concat(getDriver().SysRoot, "/usr/include/c++/v1")); + AddLibcxxInclude(DriverArgs, CC1Args, + concat(getDriver().SysRoot, "/usr/include"), + IncludeStrategy::AssumeAvailable); } void FreeBSD::AddCXXStdlibLibArgs(const ArgList &Args, diff --git a/clang/lib/Driver/ToolChains/Fuchsia.cpp b/clang/lib/Driver/ToolChains/Fuchsia.cpp index 14b838500becce..4b04062b0923ac 100644 --- a/clang/lib/Driver/ToolChains/Fuchsia.cpp +++ b/clang/lib/Driver/ToolChains/Fuchsia.cpp @@ -425,30 +425,14 @@ void Fuchsia::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, return; const Driver &D = getDriver(); - std::string Target = getTripleString(); - - auto AddCXXIncludePath = [&](StringRef Path) { - std::string Version = detectLibcxxVersion(Path); - if (Version.empty()) - return; - - // First add the per-target include path. - SmallString<128> TargetDir(Path); - llvm::sys::path::append(TargetDir, Target, "c++", Version); - if (getVFS().exists(TargetDir)) - addSystemInclude(DriverArgs, CC1Args, TargetDir); - - // Second add the generic one. - SmallString<128> Dir(Path); - llvm::sys::path::append(Dir, "c++", Version); - addSystemInclude(DriverArgs, CC1Args, Dir); - }; switch (GetCXXStdlibType(DriverArgs)) { case ToolChain::CST_Libcxx: { SmallString<128> P(D.Dir); llvm::sys::path::append(P, "..", "include"); - AddCXXIncludePath(P); + AddLibcxxInclude( + DriverArgs, CC1Args, P, + IncludeStrategy{IncludeStrategy::UseMaxVersionAvailable, true}); break; } diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp index a2526a2b903964..4e867624e8ef5d 100644 --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/clang/lib/Driver/ToolChains/Gnu.cpp @@ -3284,6 +3284,7 @@ Generic_GCC::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs, if (Version.empty()) return false; + // FIXME: This should be part of AddLibcxxInclude // First add the per-target include path if it exists. bool TargetDirExists = false; std::optional<std::string> TargetIncludeDir = getTargetSubDirPath(Path); @@ -3299,9 +3300,8 @@ Generic_GCC::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs, return false; // Second add the generic one. - SmallString<128> GenericDir(Path); - llvm::sys::path::append(GenericDir, "c++", Version); - addSystemInclude(DriverArgs, CC1Args, GenericDir); + ToolChain::AddLibcxxInclude(DriverArgs, CC1Args, Path, + IncludeStrategy::UseMaxVersionAvailable); return true; }; diff --git a/clang/lib/Driver/ToolChains/Haiku.cpp b/clang/lib/Driver/ToolChains/Haiku.cpp index e0d94035823fd3..5cd83b92eb9139 100644 --- a/clang/lib/Driver/ToolChains/Haiku.cpp +++ b/clang/lib/Driver/ToolChains/Haiku.cpp @@ -270,8 +270,9 @@ void Haiku::AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, void Haiku::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const { - addSystemInclude(DriverArgs, CC1Args, - concat(getDriver().SysRoot, "/boot/system/develop/headers/c++/v1")); + AddLibcxxInclude(DriverArgs, CC1Args, + concat(getDriver().SysRoot, "/boot/system/develop/headers"), + IncludeStrategy::AssumeAvailable); } Tool *Haiku::buildLinker() const { return new tools::haiku::Linker(*this); } diff --git a/clang/lib/Driver/ToolChains/Hexagon.cpp b/clang/lib/Driver/ToolChains/Hexagon.cpp index fa47c98901e145..7358c2a12132ca 100644 --- a/clang/lib/Driver/ToolChains/Hexagon.cpp +++ b/clang/lib/Driver/ToolChains/Hexagon.cpp @@ -737,18 +737,27 @@ void HexagonToolChain::addLibCxxIncludePaths( const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const { const Driver &D = getDriver(); - if (!D.SysRoot.empty() && getTriple().isMusl()) - addLibStdCXXIncludePaths(D.SysRoot + "/usr/include/c++/v1", "", "", - DriverArgs, CC1Args); - else if (getTriple().isMusl()) - addLibStdCXXIncludePaths("/usr/include/c++/v1", "", "", DriverArgs, - CC1Args); - else { + if (!D.SysRoot.empty() && getTriple().isMusl()) { + ToolChain::AddLibcxxInclude(DriverArgs, CC1Args, D.SysRoot + "/usr/include", + IncludeStrategy::AssumeAvailable); + // FIXME: Is this actually expected? (Same below) + addSystemInclude(DriverArgs, CC1Args, + D.SysRoot + "/usr/include/c++/v1/backward"); + } + else if (getTriple().isMusl()) { + ToolChain::AddLibcxxInclude(DriverArgs, CC1Args, "/usr/include", + IncludeStrategy::AssumeAvailable); + addSystemInclude(DriverArgs, CC1Args, "/usr/include/c++/v1/backward"); + } else { std::string TargetDir = getHexagonTargetDir(D.InstalledDir, D.PrefixDirs); - addLibStdCXXIncludePaths(TargetDir + "/hexagon/include/c++/v1", "", "", - DriverArgs, CC1Args); + ToolChain::AddLibcxxInclude(DriverArgs, CC1Args, + TargetDir + "/hexagon/include", + IncludeStrategy::AssumeAvailable); + addSystemInclude(DriverArgs, CC1Args, + TargetDir + "/hexagon/include/c++/v1/backward"); } } + void HexagonToolChain::addLibStdCxxIncludePaths( const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const { diff --git a/clang/lib/Driver/ToolChains/MinGW.cpp b/clang/lib/Driver/ToolChains/MinGW.cpp index 2b7fc104ea95aa..d13c5b736ab02e 100644 --- a/clang/lib/Driver/ToolChains/MinGW.cpp +++ b/clang/lib/Driver/ToolChains/MinGW.cpp @@ -745,16 +745,12 @@ void toolchains::MinGW::AddClangCXXStdlibIncludeArgs( switch (GetCXXStdlibType(DriverArgs)) { case ToolChain::CST_Libcxx: { - std::string TargetDir = (Base + "include" + Slash + getTripleString() + - Slash + "c++" + Slash + "v1") - .str(); - if (getDriver().getVFS().exists(TargetDir)) - addSystemInclude(DriverArgs, CC1Args, TargetDir); - addSystemInclude(DriverArgs, CC1Args, - Base + SubdirName + Slash + "include" + Slash + "c++" + - Slash + "v1"); - addSystemInclude(DriverArgs, CC1Args, - Base + "include" + Slash + "c++" + Slash + "v1"); + ToolChain::AddLibcxxInclude( + DriverArgs, CC1Args, Base + "include", + IncludeStrategy{IncludeStrategy::AssumeAvailable, true}); + ToolChain::AddLibcxxInclude(DriverArgs, CC1Args, + Base + SubdirName + Slash + "include", + IncludeStrategy::AssumeAvailable); break; } diff --git a/clang/lib/Driver/ToolChains/MipsLinux.cpp b/clang/lib/Driver/ToolChains/MipsLinux.cpp index 4183eccceedb4e..1ea85c402ca28e 100644 --- a/clang/lib/Driver/ToolChains/MipsLinux.cpp +++ b/clang/lib/Driver/ToolChains/MipsLinux.cpp @@ -97,11 +97,10 @@ void MipsLLVMToolChain::addLibCxxIncludePaths( llvm::opt::ArgStringList &CC1Args) const { if (const auto &Callback = Multilibs.includeDirsCallback()) { for (std::string Path : Callback(SelectedMultilibs.back())) { - Path = getDriver().getInstalledDir() + Path + "/c++/v1"; - if (llvm::sys::fs::exists(Path)) { - addSystemInclude(DriverArgs, CC1Args, Path); + if (ToolChain::AddLibcxxInclude(DriverArgs, CC1Args, + getDriver().getInstalledDir() + Path, + IncludeStrategy::CheckIfAvailable)) return; - } } } } diff --git a/clang/lib/Driver/ToolChains/NaCl.cpp b/clang/lib/Driver/ToolChains/NaCl.cpp index 22f038e5152ff2..57cd3cf29d9122 100644 --- a/clang/lib/Driver/ToolChains/NaCl.cpp +++ b/clang/lib/Driver/ToolChains/NaCl.cpp @@ -317,24 +317,22 @@ void NaClToolChain::addLibCxxIncludePaths( SmallString<128> P(D.Dir + "/../"); switch (getTriple().getArch()) { default: - break; + return; case llvm::Triple::arm: - llvm::sys::path::append(P, "arm-nacl/include/c++/v1"); - addSystemInclude(DriverArgs, CC1Args, P.str()); + llvm::sys::path::append(P, "arm-nacl/include"); break; case llvm::Triple::x86: - llvm::sys::path::append(P, "x86_64-nacl/include/c++/v1"); - addSystemInclude(DriverArgs, CC1Args, P.str()); + llvm::sys::path::append(P, "x86_64-nacl/include"); break; case llvm::Triple::x86_64: - llvm::sys::path::append(P, "x86_64-nacl/include/c++/v1"); - addSystemInclude(DriverArgs, CC1Args, P.str()); + llvm::sys::path::append(P, "x86_64-nacl/include"); break; case llvm::Triple::mipsel: - llvm::sys::path::append(P, "mipsel-nacl/include/c++/v1"); - addSystemInclude(DriverArgs, CC1Args, P.str()); + llvm::sys::path::append(P, "mipsel-nacl/include"); break; } + ToolChain::AddLibcxxInclude(DriverArgs, CC1Args, P, + IncludeStrategy::AssumeAvailable); } ToolChain::CXXStdlibType diff --git a/clang/lib/Driver/ToolChains/NetBSD.cpp b/clang/lib/Driver/ToolChains/NetBSD.cpp index 240bf5764b9cce..f6ccde40b06520 100644 --- a/clang/lib/Driver/ToolChains/NetBSD.cpp +++ b/clang/lib/Driver/ToolChains/NetBSD.cpp @@ -495,21 +495,21 @@ void NetBSD::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const { const std::string Candidates[] = { // directory relative to build tree - concat(getDriver().Dir, "/../include/c++/v1"), + concat(getDriver().Dir, "/../include"), // system install with full upstream path - concat(getDriver().SysRoot, "/usr/include/c++/v1"), - // system install from src - concat(getDriver().SysRoot, "/usr/include/c++"), + concat(getDriver().SysRoot, "/usr/include"), }; for (const auto &IncludePath : Candidates) { - if (!getVFS().exists(IncludePath + "/__config")) - continue; - - // Use the first candidate that looks valid. - addSystemInclude(DriverArgs, CC1Args, IncludePath); - return; + if (ToolChain::AddLibcxxInclude(DriverArgs, CC1Args, IncludePath, + IncludeStrategy::CheckIfAvailable)) + return; } + + // system install from src + auto NonV1Path = concat(getDriver().SysRoot, "/usr/include/c++"); + if (getVFS().exists(NonV1Path)) + addSystemInclude(DriverArgs, CC1Args, NonV1Path); } void NetBSD::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs, diff --git a/clang/lib/Driver/ToolChains/OHOS.cpp b/clang/lib/Driver/ToolChains/OHOS.cpp index 1e50c9d71d59cc..81d66ce492a306 100644 --- a/clang/lib/Driver/ToolChains/OHOS.cpp +++ b/clang/lib/Driver/ToolChains/OHOS.cpp @@ -242,12 +242,9 @@ void OHOS::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, switch (GetCXXStdlibType(DriverArgs)) { case ToolChain::CST_Libcxx: { std::string IncPath = makePath({getDriver().Dir, "..", "include"}); - std::string IncTargetPath = - makePath({IncPath, getMultiarchTriple(getTriple()), "c++", "v1"}); - if (getVFS().exists(IncTargetPath)) { - addSystemInclude(DriverArgs, CC1Args, makePath({IncPath, "c++", "v1"})); - addSystemInclude(DriverArgs, CC1Args, IncTargetPath); - } + ToolChain::AddLibcxxInclude( + DriverArgs, CC1Args, IncPath, + IncludeStrategy{IncludeStrategy::CheckIfAvailable, true}); break; } diff --git a/clang/lib/Driver/ToolChains/OpenBSD.cpp b/clang/lib/Driver/ToolChains/OpenBSD.cpp index fd6aa4d7e68447..bbdd4f8849a453 100644 --- a/clang/lib/Driver/ToolChains/OpenBSD.cpp +++ b/clang/lib/Driver/ToolChains/OpenBSD.cpp @@ -351,8 +351,9 @@ void OpenBSD::AddClangSystemIncludeArgs( void OpenBSD::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const { - addSystemInclude(DriverArgs, CC1Args, - concat(getDriver().SysRoot, "/usr/include/c++/v1")); + ToolChain::AddLibcxxInclude(DriverArgs, CC1Args, + concat(getDriver().SysRoot, "/usr/include"), + IncludeStrategy::AssumeAvailable); } void OpenBSD::AddCXXStdlibLibArgs(const ArgList &Args, diff --git a/clang/lib/Driver/ToolChains/WebAssembly.cpp b/clang/lib/Driver/ToolChains/WebAssembly.cpp index 57f4600727ec89..3b7bafaf9e93ae 100644 --- a/clang/lib/Driver/ToolChains/WebAssembly.cpp +++ b/clang/lib/Driver/ToolChains/WebAssembly.cpp @@ -507,6 +507,7 @@ void WebAssembly::addLibCxxIncludePaths( if (Version.empty()) return; + // FIXME: This should be part of AddLibcxxInclude // First add the per-target include path if the OS is known. if (IsKnownOs) { std::string TargetDir = LibPath + "/" + MultiarchTriple + "/c++/" + Version; @@ -514,7 +515,8 @@ void WebAssembly::addLibCxxIncludePaths( } // Second add the generic one. - addSystemInclude(DriverArgs, CC1Args, LibPath + "/c++/" + Version); + ToolChain::AddLibcxxInclude(DriverArgs, CC1Args, LibPath, + IncludeStrategy::UseMaxVersionAvailable); } void WebAssembly::addLibStdCXXIncludePaths( diff --git a/clang/lib/Driver/ToolChains/ZOS.cpp b/clang/lib/Driver/ToolChains/ZOS.cpp index 96dbf602e7c1fc..73292e3210b6b4 100644 --- a/clang/lib/Driver/ToolChains/ZOS.cpp +++ b/clang/lib/Driver/ToolChains/ZOS.cpp @@ -301,19 +301,6 @@ void ZOS::AddClangSystemIncludeArgs(const ArgList &DriverArgs, addSystemInclude(DriverArgs, CC1Args, "/usr/include"); } -void ZOS::TryAddIncludeFromPath(llvm::SmallString<128> Path, - const llvm::opt::ArgList &DriverArgs, - llvm::opt::ArgStringList &CC1Args) const { - if (!getVFS().exists(Path)) { - if (DriverArgs.hasArg(options::OPT_v)) - WithColor::warning(errs(), "Clang") - << "ignoring nonexistent directory \"" << Path << "\"\n"; - if (!DriverArgs.hasArg(options::OPT__HASH_HASH_HASH)) - return; - } - addSystemInclude(DriverArgs, CC1Args, Path); -} - void ZOS::AddClangCXXStdlibIncludeArgs( const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const { @@ -327,8 +314,13 @@ void ZOS::AddClangCXXStdlibIncludeArgs( // <install>/bin/../include/c++/v1 llvm::SmallString<128> InstallBin = llvm::StringRef(getDriver().getInstalledDir()); - llvm::sys::path::append(InstallBin, "..", "include", "c++", "v1"); - TryAddIncludeFromPath(InstallBin, DriverArgs, CC1Args); + llvm::sys::path::append(InstallBin, "..", "include"); + IncludeStrategy Strategy = DriverArgs.hasArg(options::OPT__HASH_HASH_HASH) + ? IncludeStrategy::AssumeAvailable + : IncludeStrategy::CheckIfAvailable; + Strategy.PrintDebugStatements = DriverArgs.hasArg(options::OPT_v); + + ToolChain::AddLibcxxInclude(DriverArgs, CC1Args, InstallBin, Strategy); break; } case ToolChain::CST_Libstdcxx: diff --git a/clang/lib/Driver/ToolChains/ZOS.h b/clang/lib/Driver/ToolChains/ZOS.h index 45204ba0a543c1..fb60171d33559b 100644 --- a/clang/lib/Driver/ToolChains/ZOS.h +++ b/clang/lib/Driver/ToolChains/ZOS.h @@ -61,9 +61,6 @@ class LLVM_LIBRARY_VISIBILITY ZOS : public ToolChain { } bool isPICDefaultForced() const override { return false; } - void TryAddIncludeFromPath(llvm::SmallString<128> Path, - const llvm::opt::ArgList &DriverArgs, - llvm::opt::ArgStringList &CC1Args) const; void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override; >From a4b3917ae30620d3dd4fdb6b0fd92f7563314145 Mon Sep 17 00:00:00 2001 From: Nikolas Klauser <nikolasklau...@berlin.de> Date: Sun, 3 Mar 2024 13:21:23 +0100 Subject: [PATCH 2/2] [Clang][Driver] Add special-casing for including libc++ in C++03 --- clang/include/clang/Driver/ToolChain.h | 6 ++++ clang/lib/Driver/ToolChain.cpp | 29 ++++++++++++++++--- .../usr/include/c++/c++03/.keep | 0 .../usr/bin/.keep | 0 .../usr/include/c++/v1/.keep | 0 .../x86_64-unknown-linux-gnu/c++/v1/.keep | 0 .../usr/lib/.keep | 0 .../usr/lib/x86_64-unknown-linux-gnu/.keep | 0 clang/test/Driver/linux-header-search.cpp | 18 ++++++++++++ 9 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 clang/test/Driver/Inputs/basic_linux_libcxx_tree/usr/include/c++/c++03/.keep create mode 100644 clang/test/Driver/Inputs/basic_linux_libcxx_tree_no_cxx03/usr/bin/.keep create mode 100644 clang/test/Driver/Inputs/basic_linux_libcxx_tree_no_cxx03/usr/include/c++/v1/.keep create mode 100644 clang/test/Driver/Inputs/basic_linux_libcxx_tree_no_cxx03/usr/include/x86_64-unknown-linux-gnu/c++/v1/.keep create mode 100644 clang/test/Driver/Inputs/basic_linux_libcxx_tree_no_cxx03/usr/lib/.keep create mode 100644 clang/test/Driver/Inputs/basic_linux_libcxx_tree_no_cxx03/usr/lib/x86_64-unknown-linux-gnu/.keep diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h index c61cf2aa064ed5..f8329ae3fc39dd 100644 --- a/clang/include/clang/Driver/ToolChain.h +++ b/clang/include/clang/Driver/ToolChain.h @@ -738,6 +738,12 @@ class ToolChain { // Whether to print a message if a checked directory isn't available. LLVM_PREFERRED_TYPE(bool) unsigned PrintDebugStatements : 1; + + private: + LLVM_PREFERRED_TYPE(bool) + unsigned CheckCxx03 : 1; + + friend class ToolChain; }; /// Helper function to implement AddClangCXXStdlibIncludeArgs for libc++. diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index 42c9d6e91d3c35..1e94a53f8a1d90 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -1255,13 +1255,20 @@ bool ToolChain::AddLibcxxInclude(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, llvm::Twine IncludeRoot, IncludeStrategy Strategy) const { + using namespace std::literals; + SmallString<128> Path; IncludeRoot.toVector(Path); - auto VersionDirName = - Strategy.Availability == IncludeStrategy::UseMaxVersionAvailable - ? detectLibcxxVersion(Path) - : "v1"; + auto VersionDirName = [&] { + if (Strategy.CheckCxx03) + return "c++03"s; + + if (Strategy.Availability == IncludeStrategy::UseMaxVersionAvailable) + return detectLibcxxVersion(Path); + + return "v1"s; + }(); if (VersionDirName.empty()) return false; @@ -1274,6 +1281,20 @@ bool ToolChain::AddLibcxxInclude(const llvm::opt::ArgList &DriverArgs, addSystemInclude(DriverArgs, CC1Args, TargetDir); } + if (const Arg *A = + DriverArgs.getLastArg(options::OPT_std_EQ, options::OPT_ansi); + !Strategy.CheckCxx03 && + (A && (A->getOption().matches(options::OPT_ansi) || + A->getValue() == "c++98"sv || A->getValue() == "c++03"sv || + A->getValue() == "gnu++98"sv || A->getValue() == "gnu++03"sv))) { + auto StrategyCopy = Strategy; + StrategyCopy.AddTargetDirIfAvailable = false; + StrategyCopy.Availability = IncludeStrategy::CheckIfAvailable; + StrategyCopy.CheckCxx03 = true; + if (AddLibcxxInclude(DriverArgs, CC1Args, IncludeRoot, StrategyCopy)) + return true; + } + llvm::sys::path::append(Path, "c++", VersionDirName); if ((Strategy.Availability != IncludeStrategy::AssumeAvailable || diff --git a/clang/test/Driver/Inputs/basic_linux_libcxx_tree/usr/include/c++/c++03/.keep b/clang/test/Driver/Inputs/basic_linux_libcxx_tree/usr/include/c++/c++03/.keep new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/clang/test/Driver/Inputs/basic_linux_libcxx_tree_no_cxx03/usr/bin/.keep b/clang/test/Driver/Inputs/basic_linux_libcxx_tree_no_cxx03/usr/bin/.keep new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/clang/test/Driver/Inputs/basic_linux_libcxx_tree_no_cxx03/usr/include/c++/v1/.keep b/clang/test/Driver/Inputs/basic_linux_libcxx_tree_no_cxx03/usr/include/c++/v1/.keep new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/clang/test/Driver/Inputs/basic_linux_libcxx_tree_no_cxx03/usr/include/x86_64-unknown-linux-gnu/c++/v1/.keep b/clang/test/Driver/Inputs/basic_linux_libcxx_tree_no_cxx03/usr/include/x86_64-unknown-linux-gnu/c++/v1/.keep new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/clang/test/Driver/Inputs/basic_linux_libcxx_tree_no_cxx03/usr/lib/.keep b/clang/test/Driver/Inputs/basic_linux_libcxx_tree_no_cxx03/usr/lib/.keep new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/clang/test/Driver/Inputs/basic_linux_libcxx_tree_no_cxx03/usr/lib/x86_64-unknown-linux-gnu/.keep b/clang/test/Driver/Inputs/basic_linux_libcxx_tree_no_cxx03/usr/lib/x86_64-unknown-linux-gnu/.keep new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/clang/test/Driver/linux-header-search.cpp b/clang/test/Driver/linux-header-search.cpp index dd4d6eb483a3fb..0cce3e91e6654e 100644 --- a/clang/test/Driver/linux-header-search.cpp +++ b/clang/test/Driver/linux-header-search.cpp @@ -1,6 +1,24 @@ // General tests that the header search paths detected by the driver and passed // to CC1 are sane. // + +// Test a simulated installation of libc++ in C++03 mode on Linux, both through sysroot and +// the installation path of Clang. +// RUN: %clang -### %s -fsyntax-only 2>&1 \ +// RUN: --target=x86_64-unknown-linux-gnu \ +// RUN: -stdlib=libc++ \ +// RUN: -std=c++03 \ +// RUN: -ccc-install-dir %S/Inputs/basic_linux_tree/usr/bin \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ +// RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree \ +// RUN: --gcc-toolchain="" \ +// RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBCXX-SYSROOT-CXX03 %s +// CHECK-BASIC-LIBCXX-SYSROOT-CXX03: "-cc1" +// CHECK-BASIC-LIBCXX-SYSROOT-CXX03: "-isysroot" "[[SYSROOT:[^"]+]]" +// CHECK-BASIC-LIBCXX-SYSROOT-CXX03: "-internal-isystem" "[[SYSROOT]][[SEP:/|\\\\]]usr[[SEP]]include[[SEP]]x86_64-unknown-linux-gnu[[SEP]]c++[[SEP]]v1" +// CHECK-BASIC-LIBCXX-SYSROOT-CXX03: "-internal-isystem" "[[SYSROOT]][[SEP]]usr[[SEP]]include[[SEP]]c++[[SEP]]c++03" +// CHECK-BASIC-LIBCXX-SYSROOT-CXX03: "-internal-isystem" "[[SYSROOT]]/usr/local/include" + // Test a simulated installation of libc++ on Linux, both through sysroot and // the installation path of Clang. // RUN: %clang -### %s -fsyntax-only 2>&1 \ _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits