ilya-biryukov created this revision. ilya-biryukov added reviewers: sammccall, arphaman. Herald added a reviewer: EricWF. Herald added subscribers: kadircet, christof, ioeric.
When they read compiler args from compile_commands.json. This change allows to run clang-based tools, like clang-tidy or clangd, built from head using the compile_commands.json file produced for XCode toolchains. On MacOS clang can find the C++ standard library relative to the compiler installation dir. The logic to do this was based on resource dir as an approximation of where the compiler is installed. This broke the tools that read 'compile_commands.json' and don't ship with the compiler, as they typically change resource dir. To workaround this, we now use compiler install dir detected by the driver to better mimic the behavior of the original compiler when replaying the compilations using other tools. Repository: rC Clang https://reviews.llvm.org/D54310 Files: include/clang/Lex/HeaderSearchOptions.h lib/Frontend/CompilerInvocation.cpp lib/Frontend/CreateInvocationFromCommandLine.cpp lib/Frontend/InitHeaderSearch.cpp lib/Tooling/Tooling.cpp test/Tooling/Inputs/mock-libcxx/include/c++/v1/mock_vector test/Tooling/clang-check-mac-libcxx.cpp
Index: test/Tooling/clang-check-mac-libcxx.cpp =================================================================== --- /dev/null +++ test/Tooling/clang-check-mac-libcxx.cpp @@ -0,0 +1,16 @@ +// 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" +// RUN: clang-check -p "%t" "%t/test.cpp" + +#include <mock_vector> +vector v; Index: test/Tooling/Inputs/mock-libcxx/include/c++/v1/mock_vector =================================================================== --- /dev/null +++ test/Tooling/Inputs/mock-libcxx/include/c++/v1/mock_vector @@ -0,0 +1 @@ +class vector {}; Index: lib/Tooling/Tooling.cpp =================================================================== --- lib/Tooling/Tooling.cpp +++ lib/Tooling/Tooling.cpp @@ -323,6 +323,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: lib/Frontend/InitHeaderSearch.cpp =================================================================== --- lib/Frontend/InitHeaderSearch.cpp +++ 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: lib/Frontend/CreateInvocationFromCommandLine.cpp =================================================================== --- lib/Frontend/CreateInvocationFromCommandLine.cpp +++ 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: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -1773,6 +1773,7 @@ if (const Arg *A = Args.getLastArg(OPT_stdlib_EQ)) Opts.UseLibcxx = (strcmp(A->getValue(), "libc++") == 0); Opts.ResourceDir = Args.getLastArgValue(OPT_resource_dir); + Opts.InstallDir = Opts.ResourceDir; // Canonicalize -fmodules-cache-path before storing it. SmallString<128> P(Args.getLastArgValue(OPT_fmodules_cache_path)); Index: include/clang/Lex/HeaderSearchOptions.h =================================================================== --- include/clang/Lex/HeaderSearchOptions.h +++ include/clang/Lex/HeaderSearchOptions.h @@ -108,6 +108,11 @@ /// etc.). std::string ResourceDir; + /// Compiler install dir as detected by the Driver. + /// 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;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits