[clang] a32a2b2 - [clang][driver] Add <executable>/../include/c++/v1 to include path on Darwin (#70817)

via cfe-commits cfe-commits at lists.llvm.org
Mon Nov 20 08:15:03 PST 2023


Author: Liviu Ionescu
Date: 2023-11-20T11:14:36-05:00
New Revision: a32a2b2ceb6b4c1bbcbcb39363c8dee44daf86ab

URL: https://github.com/llvm/llvm-project/commit/a32a2b2ceb6b4c1bbcbcb39363c8dee44daf86ab
DIFF: https://github.com/llvm/llvm-project/commit/a32a2b2ceb6b4c1bbcbcb39363c8dee44daf86ab.diff

LOG: [clang][driver] Add <executable>/../include/c++/v1 to include path on Darwin (#70817)

On macOS, when clang is invoked via a symlink, since the InstalledDir is
where the link is located, the C++ headers are not identified and the
default system headers from the SDK are used.

This can be undesirable if a toolchain is created by symlinking clang
into a directory and placing libc++ headers in that directory with the
intent of those headers overriding the SDK headers. This change solves
that problem by also looking for libc++ headers in the toolchain-relative
location of the executable symlink, if any.

Added: 
    

Modified: 
    clang/lib/Driver/ToolChains/Darwin.cpp
    clang/test/Driver/darwin-header-search-libcxx.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp
index 7481f6cab9a968d..7c3d4982d8f6a8c 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -2470,14 +2470,19 @@ void DarwinClang::AddClangCXXStdlibIncludeArgs(
 
   switch (GetCXXStdlibType(DriverArgs)) {
   case ToolChain::CST_Libcxx: {
-    // On Darwin, libc++ can be installed in one of the following two places:
-    // 1. Alongside the compiler in         <install>/include/c++/v1
-    // 2. In a SDK (or a custom sysroot) in <sysroot>/usr/include/c++/v1
+    // On Darwin, libc++ can be installed in one of the following places:
+    // 1. Alongside the compiler in <install>/include/c++/v1
+    // 2. Alongside the compiler in <clang-executable-folder>/../include/c++/v1
+    // 3. In a SDK (or a custom sysroot) in <sysroot>/usr/include/c++/v1
     //
-    // The precendence of paths is as listed above, i.e. we take the first path
-    // that exists. Also note that we never include libc++ twice -- we take the
-    // first path that exists and don't send the other paths to CC1 (otherwise
+    // The precedence of paths is as listed above, i.e. we take the first path
+    // that exists. Note that we never include libc++ twice -- we take the first
+    // path that exists and don't send the other paths to CC1 (otherwise
     // include_next could break).
+    //
+    // Also note that in most cases, (1) and (2) are exactly the same path.
+    // Those two paths will 
diff er only when the `clang` program being run
+    // is actually a symlink to the real executable.
 
     // Check for (1)
     // Get from '<install>/bin' to '<install>/include/c++/v1'.
@@ -2494,7 +2499,20 @@ void DarwinClang::AddClangCXXStdlibIncludeArgs(
                    << "\"\n";
     }
 
-    // Otherwise, check for (2)
+    // (2) Check for the folder where the executable is located, if 
diff erent.
+    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);
+        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)) {

diff  --git a/clang/test/Driver/darwin-header-search-libcxx.cpp b/clang/test/Driver/darwin-header-search-libcxx.cpp
index cc8ec9ceb89b3ab..8f530299d53c6d8 100644
--- a/clang/test/Driver/darwin-header-search-libcxx.cpp
+++ b/clang/test/Driver/darwin-header-search-libcxx.cpp
@@ -172,3 +172,60 @@
 // RUN:               --check-prefix=CHECK-LIBCXX-STDLIB-UNSPECIFIED %s
 // CHECK-LIBCXX-STDLIB-UNSPECIFIED: "-cc1"
 // CHECK-LIBCXX-STDLIB-UNSPECIFIED: "-internal-isystem" "[[SYSROOT]]/usr/include/c++/v1"
+
+// ----------------------------------------------------------------------------
+// On Darwin, libc++ can be installed in one of the following places:
+// 1. Alongside the compiler in <install>/include/c++/v1
+// 2. Alongside the compiler in <clang-executable-folder>/../include/c++/v1
+// 3. In a SDK (or a custom sysroot) in <sysroot>/usr/include/c++/v1
+
+// The build folders do not have an `include/c++/v1`; create a new
+// local folder hierarchy that meets this requirement.
+// Note: this might not work with weird RPATH configurations.
+// RUN: rm -rf %t/install
+// RUN: mkdir -pv %t/install/bin
+// RUN: cp %clang %t/install/bin/clang
+// RUN: mkdir -pv %t/install/include/c++/v1
+
+// Headers in (1) and in (2) -> (1) is preferred over (2)
+// RUN: rm -rf %t/symlinked1
+// RUN: mkdir -pv %t/symlinked1/bin
+// RUN: ln -svf %t/install/bin/clang %t/symlinked1/bin/clang
+// RUN: mkdir -pv %t/symlinked1/include/c++/v1
+
+// RUN: %t/symlinked1/bin/clang -### %s -fsyntax-only 2>&1 \
+// RUN:     --target=x86_64-apple-darwin \
+// RUN:     -stdlib=libc++ \
+// RUN:     -isysroot %S/Inputs/basic_darwin_sdk_usr_cxx_v1 \
+// RUN:   | FileCheck -DSYMLINKED=%t/symlinked1 \
+// RUN:               -DTOOLCHAIN=%t/install \
+// RUN:               -DSYSROOT=%S/Inputs/basic_darwin_sdk_usr_cxx_v1 \
+// RUN:               --check-prefix=CHECK-SYMLINKED-INCLUDE-CXX-V1 %s
+// CHECK-SYMLINKED-INCLUDE-CXX-V1: "-internal-isystem" "[[SYMLINKED]]/bin/../include/c++/v1"
+// CHECK-SYMLINKED-INCLUDE-CXX-V1-NOT: "-internal-isystem" "[[TOOLCHAIN]]/bin/../include/c++/v1"
+// CHECK-SYMLINKED-INCLUDE-CXX-V1-NOT: "-internal-isystem" "[[SYSROOT]]/usr/include/c++/v1"
+
+// Headers in (2) and in (3) -> (2) is preferred over (3)
+// RUN: rm -rf %t/symlinked2
+// RUN: mkdir -pv %t/symlinked2/bin
+// RUN: ln -svf %t/install/bin/clang %t/symlinked2/bin/clang
+
+// RUN: %t/symlinked2/bin/clang -### %s -fsyntax-only 2>&1 \
+// RUN:     --target=x86_64-apple-darwin \
+// RUN:     -stdlib=libc++ \
+// RUN:     -isysroot %S/Inputs/basic_darwin_sdk_usr_cxx_v1 \
+// RUN:   | FileCheck -DTOOLCHAIN=%t/install \
+// RUN:               -DSYSROOT=%S/Inputs/basic_darwin_sdk_usr_cxx_v1 \
+// RUN:               --check-prefix=CHECK-TOOLCHAIN-INCLUDE-CXX-V1 %s
+// CHECK-TOOLCHAIN-INCLUDE-CXX-V1: "-internal-isystem" "[[TOOLCHAIN]]/bin/../include/c++/v1"
+// CHECK-TOOLCHAIN-INCLUDE-CXX-V1-NOT: "-internal-isystem" "[[SYSROOT]]/usr/include/c++/v1"
+
+// Headers in (2) and nowhere else -> (2) is used
+// RUN: %t/symlinked2/bin/clang -### %s -fsyntax-only 2>&1 \
+// RUN:     --target=x86_64-apple-darwin \
+// RUN:     -stdlib=libc++ \
+// RUN:     -isysroot %S/Inputs/basic_darwin_sdk_usr_cxx_v1 \
+// RUN:   | FileCheck -DTOOLCHAIN=%t/install \
+// RUN:               -DSYSROOT=%S/Inputs/basic_darwin_sdk_no_libcxx \
+// RUN:               --check-prefix=CHECK-TOOLCHAIN-NO-SYSROOT %s
+// CHECK-TOOLCHAIN-NO-SYSROOT: "-internal-isystem" "[[TOOLCHAIN]]/bin/../include/c++/v1"


        


More information about the cfe-commits mailing list