|
| 1 | +From a3a24316087d0e1b4db0b8fee19cdee8b7968032 Mon Sep 17 00:00:00 2001 |
| 2 | +From: Louis Dionne < [email protected]> |
| 3 | +Date: Wed, 7 Oct 2020 14:27:55 -0400 |
| 4 | +Subject: [PATCH] [clang] Don't look into <sysroot> for C++ headers if they are |
| 5 | + found alongside the toolchain |
| 6 | + |
| 7 | +Currently, Clang looks for libc++ headers alongside the installation |
| 8 | +directory of Clang, and it also adds a search path for headers in the |
| 9 | +-isysroot. This is problematic if headers are found in both the toolchain |
| 10 | +and in the sysroot, since #include_next will end up finding the libc++ |
| 11 | +headers in the sysroot instead of the intended system headers. |
| 12 | + |
| 13 | +This patch changes the logic such that if the toolchain contains libc++ |
| 14 | +headers, no C++ header paths are added in the sysroot. However, if the |
| 15 | +toolchain does *not* contain libc++ headers, the sysroot is searched as |
| 16 | +usual. |
| 17 | + |
| 18 | +This should not be a breaking change, since any code that previously |
| 19 | +relied on some libc++ headers being found in the sysroot suffered from |
| 20 | +the #include_next issue described above, which renders any libc++ header |
| 21 | +basically useless. |
| 22 | + |
| 23 | +Differential Revision: https://reviews.llvm.org/D89001 |
| 24 | +--- |
| 25 | + clang/lib/Driver/ToolChains/Darwin.cpp | 47 +++++--- |
| 26 | + .../usr/include/c++/v1/.keep | 0 |
| 27 | + .../basic_darwin_sdk_usr_cxx_v1/usr/lib/.keep | 0 |
| 28 | + .../Driver/darwin-header-search-libcxx.cpp | 101 ++++++++++++++---- |
| 29 | + 4 files changed, 112 insertions(+), 36 deletions(-) |
| 30 | + create mode 100644 clang/test/Driver/Inputs/basic_darwin_sdk_usr_cxx_v1/usr/include/c++/v1/.keep |
| 31 | + create mode 100644 clang/test/Driver/Inputs/basic_darwin_sdk_usr_cxx_v1/usr/lib/.keep |
| 32 | + |
| 33 | +diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp |
| 34 | +index 46265c1b9f1a..b1fafaeb727a 100644 |
| 35 | +--- a/clang/lib/Driver/ToolChains/Darwin.cpp |
| 36 | ++++ b/clang/lib/Driver/ToolChains/Darwin.cpp |
| 37 | +@@ -1957,21 +1957,42 @@ void DarwinClang::AddClangCXXStdlibIncludeArgs( |
| 38 | + |
| 39 | + switch (GetCXXStdlibType(DriverArgs)) { |
| 40 | + case ToolChain::CST_Libcxx: { |
| 41 | +- // On Darwin, libc++ is installed alongside the compiler in |
| 42 | +- // include/c++/v1, so get from '<install>/bin' to '<install>/include/c++/v1'. |
| 43 | +- { |
| 44 | +- llvm::SmallString<128> P = llvm::StringRef(getDriver().getInstalledDir()); |
| 45 | +- // Note that P can be relative, so we have to '..' and not parent_path. |
| 46 | +- llvm::sys::path::append(P, "..", "include", "c++", "v1"); |
| 47 | +- addSystemInclude(DriverArgs, CC1Args, P); |
| 48 | ++ // On Darwin, libc++ can be installed in one of the following two places: |
| 49 | ++ // 1. Alongside the compiler in <install>/include/c++/v1 |
| 50 | ++ // 2. In a SDK (or a custom sysroot) in <sysroot>/usr/include/c++/v1 |
| 51 | ++ // |
| 52 | ++ // The precendence of paths is as listed above, i.e. we take the first path |
| 53 | ++ // that exists. Also note that we never include libc++ twice -- we take the |
| 54 | ++ // first path that exists and don't send the other paths to CC1 (otherwise |
| 55 | ++ // include_next could break). |
| 56 | ++ |
| 57 | ++ // Check for (1) |
| 58 | ++ // Get from '<install>/bin' to '<install>/include/c++/v1'. |
| 59 | ++ // Note that InstallBin can be relative, so we use '..' instead of |
| 60 | ++ // parent_path. |
| 61 | ++ llvm::SmallString<128> InstallBin = |
| 62 | ++ llvm::StringRef(getDriver().getInstalledDir()); // <install>/bin |
| 63 | ++ llvm::sys::path::append(InstallBin, "..", "include", "c++", "v1"); |
| 64 | ++ if (getVFS().exists(InstallBin)) { |
| 65 | ++ addSystemInclude(DriverArgs, CC1Args, InstallBin); |
| 66 | ++ return; |
| 67 | ++ } else if (DriverArgs.hasArg(options::OPT_v)) { |
| 68 | ++ llvm::errs() << "ignoring nonexistent directory \"" << InstallBin |
| 69 | ++ << "\"\n"; |
| 70 | + } |
| 71 | +- // Also add <sysroot>/usr/include/c++/v1 unless -nostdinc is used, |
| 72 | +- // to match the legacy behavior in CC1. |
| 73 | +- if (!DriverArgs.hasArg(options::OPT_nostdinc)) { |
| 74 | +- llvm::SmallString<128> P = Sysroot; |
| 75 | +- llvm::sys::path::append(P, "usr", "include", "c++", "v1"); |
| 76 | +- addSystemInclude(DriverArgs, CC1Args, P); |
| 77 | ++ |
| 78 | ++ // Otherwise, check for (2) |
| 79 | ++ llvm::SmallString<128> SysrootUsr = Sysroot; |
| 80 | ++ llvm::sys::path::append(SysrootUsr, "usr", "include", "c++", "v1"); |
| 81 | ++ if (getVFS().exists(SysrootUsr)) { |
| 82 | ++ addSystemInclude(DriverArgs, CC1Args, SysrootUsr); |
| 83 | ++ return; |
| 84 | ++ } else if (DriverArgs.hasArg(options::OPT_v)) { |
| 85 | ++ llvm::errs() << "ignoring nonexistent directory \"" << SysrootUsr |
| 86 | ++ << "\"\n"; |
| 87 | + } |
| 88 | ++ |
| 89 | ++ // Otherwise, don't add any path. |
| 90 | + break; |
| 91 | + } |
| 92 | + |
0 commit comments