Index: cfe/trunk/include/clang/Lex/HeaderSearchOptions.h =================================================================== --- cfe/trunk/include/clang/Lex/HeaderSearchOptions.h +++ cfe/trunk/include/clang/Lex/HeaderSearchOptions.h @@ -108,6 +108,13 @@ /// etc.). std::string ResourceDir; + /// Compiler install dir as detected by the Driver. + /// This is typically the directory that contains the clang executable, i.e. + /// the 'bin/' subdir of a clang distribution. + /// Only used to add include dirs for libc++ on Darwin. Please avoid relying + /// on this field for other purposes. + std::string InstallDir; + /// The directory used for the module cache. std::string ModuleCachePath; Index: cfe/trunk/lib/Frontend/CreateInvocationFromCommandLine.cpp =================================================================== --- cfe/trunk/lib/Frontend/CreateInvocationFromCommandLine.cpp +++ cfe/trunk/lib/Frontend/CreateInvocationFromCommandLine.cpp @@ -11,17 +11,18 @@ // //===----------------------------------------------------------------------===// -#include "clang/Frontend/Utils.h" #include "clang/Basic/DiagnosticOptions.h" +#include "clang/Driver/Action.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/Driver.h" -#include "clang/Driver/Action.h" #include "clang/Driver/Options.h" #include "clang/Driver/Tool.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendDiagnostic.h" +#include "clang/Frontend/Utils.h" #include "llvm/Option/ArgList.h" #include "llvm/Support/Host.h" +#include "llvm/Support/Path.h" using namespace clang; using namespace llvm::opt; @@ -102,5 +103,8 @@ CCArgs.size(), *Diags)) return nullptr; + // Patch up the install dir, so we find the same standard library as the + // original compiler on MacOS. + CI->getHeaderSearchOpts().InstallDir = TheDriver.getInstalledDir(); return CI; } Index: cfe/trunk/lib/Frontend/InitHeaderSearch.cpp =================================================================== --- cfe/trunk/lib/Frontend/InitHeaderSearch.cpp +++ cfe/trunk/lib/Frontend/InitHeaderSearch.cpp @@ -476,14 +476,9 @@ if (triple.isOSDarwin()) { // On Darwin, libc++ may be installed alongside the compiler in // include/c++/v1. - if (!HSOpts.ResourceDir.empty()) { - // Remove version from foo/lib/clang/version - StringRef NoVer = llvm::sys::path::parent_path(HSOpts.ResourceDir); - // Remove clang from foo/lib/clang - StringRef Lib = llvm::sys::path::parent_path(NoVer); - // Remove lib from foo/lib - SmallString<128> P = llvm::sys::path::parent_path(Lib); - + if (!HSOpts.InstallDir.empty()) { + // Get from foo/bin to foo. + SmallString<128> P(llvm::sys::path::parent_path(HSOpts.InstallDir)); // Get foo/include/c++/v1 llvm::sys::path::append(P, "include", "c++", "v1"); AddUnmappedPath(P, CXXSystem, false); Index: cfe/trunk/lib/Tooling/Tooling.cpp =================================================================== --- cfe/trunk/lib/Tooling/Tooling.cpp +++ cfe/trunk/lib/Tooling/Tooling.cpp @@ -327,6 +327,9 @@ Invocation->getPreprocessorOpts().addRemappedFile(It.getKey(), Input.release()); } + // Patch up the install dir, so we find the same standard library as the + // original compiler on MacOS. + Invocation->getHeaderSearchOpts().InstallDir = Driver->getInstalledDir(); return runInvocation(BinaryName, Compilation.get(), std::move(Invocation), std::move(PCHContainerOps)); } Index: cfe/trunk/test/Tooling/Inputs/mock-libcxx/include/c++/v1/mock_vector =================================================================== --- cfe/trunk/test/Tooling/Inputs/mock-libcxx/include/c++/v1/mock_vector +++ cfe/trunk/test/Tooling/Inputs/mock-libcxx/include/c++/v1/mock_vector @@ -0,0 +1 @@ +class vector {}; Index: cfe/trunk/test/Tooling/clang-check-mac-libcxx-abspath.cpp =================================================================== --- cfe/trunk/test/Tooling/clang-check-mac-libcxx-abspath.cpp +++ cfe/trunk/test/Tooling/clang-check-mac-libcxx-abspath.cpp @@ -0,0 +1,17 @@ +// Clang on MacOS can find libc++ living beside the installed compiler. +// This test makes sure our libTooling-based tools emulate this properly. +// +// RUN: rm -rf %t +// RUN: mkdir %t +// +// Install the mock libc++ (simulates the libc++ directory structure). +// RUN: cp -r %S/Inputs/mock-libcxx %t/ +// +// Pretend clang is installed beside the mock library that we provided. +// RUN: echo '[{"directory":"%t","command":"%t/mock-libcxx/bin/clang++ -stdlib=libc++ -target x86_64-apple-darwin -c test.cpp","file":"test.cpp"}]' | sed -e 's/\\/\//g' > %t/compile_commands.json +// RUN: cp "%s" "%t/test.cpp" +// clang-check will produce an error code if the mock library is not found. +// RUN: clang-check -p "%t" "%t/test.cpp" + +#include +vector v; Index: cfe/trunk/test/Tooling/clang-check-mac-libcxx-relpath.cpp =================================================================== --- cfe/trunk/test/Tooling/clang-check-mac-libcxx-relpath.cpp +++ cfe/trunk/test/Tooling/clang-check-mac-libcxx-relpath.cpp @@ -0,0 +1,17 @@ +// Clang on MacOS can find libc++ living beside the installed compiler. +// This test makes sure our libTooling-based tools emulate this properly. +// +// RUN: rm -rf %t +// RUN: mkdir %t +// +// Install the mock libc++ (simulates the libc++ directory structure). +// RUN: cp -r %S/Inputs/mock-libcxx %t/ +// +// Pretend clang is installed beside the mock library that we provided. +// RUN: echo '[{"directory":"%t","command":"mock-libcxx/bin/clang++ -stdlib=libc++ -target x86_64-apple-darwin -c test.cpp","file":"test.cpp"}]' | sed -e 's/\\/\//g' > %t/compile_commands.json +// RUN: cp "%s" "%t/test.cpp" +// clang-check will produce an error code if the mock library is not found. +// RUN: clang-check -p "%t" "%t/test.cpp" + +#include +vector v;