[clang] users/philnik777/add libcxx03 include strategy (PR #83723)

Nikolas Klauser via cfe-commits cfe-commits at lists.llvm.org
Sun Mar 3 04:49:03 PST 2024


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 <nikolasklauser at 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 <nikolasklauser at 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 \



More information about the cfe-commits mailing list