diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h --- a/clang/include/clang/Driver/ToolChain.h +++ b/clang/include/clang/Driver/ToolChain.h @@ -603,6 +603,9 @@ // given compilation arguments. virtual UnwindLibType GetUnwindLibType(const llvm::opt::ArgList &Args) const; + // Detect the highest available version of libc++ in include path. + virtual std::string detectLibcxxVersion(StringRef IncludePath) const; + /// AddClangCXXStdlibIncludeArgs - Add the clang -cc1 level arguments to set /// the include paths to use for the given C++ standard library type. virtual void diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -898,6 +898,29 @@ } } +std::string ToolChain::detectLibcxxVersion(StringRef IncludePath) const { + std::error_code EC; + int MaxVersion = 0; + std::string MaxVersionString; + SmallString<128> Path(IncludePath); + llvm::sys::path::append(Path, "c++"); + for (llvm::vfs::directory_iterator LI = getVFS().dir_begin(Path, EC), LE; + !EC && LI != LE; LI = LI.increment(EC)) { + StringRef VersionText = llvm::sys::path::filename(LI->path()); + int Version; + if (VersionText[0] == 'v' && + !VersionText.slice(1, StringRef::npos).getAsInteger(10, Version)) { + if (Version > MaxVersion) { + MaxVersion = Version; + MaxVersionString = std::string(VersionText); + } + } + } + if (!MaxVersion) + return ""; + return MaxVersionString; +} + void ToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const { // Header search paths should be handled by each of the subclasses. diff --git a/clang/lib/Driver/ToolChains/Fuchsia.cpp b/clang/lib/Driver/ToolChains/Fuchsia.cpp --- a/clang/lib/Driver/ToolChains/Fuchsia.cpp +++ b/clang/lib/Driver/ToolChains/Fuchsia.cpp @@ -365,7 +365,9 @@ switch (GetCXXStdlibType(DriverArgs)) { case ToolChain::CST_Libcxx: { SmallString<128> P(getDriver().Dir); - llvm::sys::path::append(P, "..", "include", "c++", "v1"); + llvm::sys::path::append(P, "..", "include"); + std::string Version = detectLibcxxVersion(P); + llvm::sys::path::append(P, "c++", Version); addSystemInclude(DriverArgs, CC1Args, P.str()); break; } diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/clang/lib/Driver/ToolChains/Gnu.cpp @@ -2892,32 +2892,13 @@ } } -static std::string DetectLibcxxIncludePath(llvm::vfs::FileSystem &vfs, - StringRef base) { - std::error_code EC; - int MaxVersion = 0; - std::string MaxVersionString; - for (llvm::vfs::directory_iterator LI = vfs.dir_begin(base, EC), LE; - !EC && LI != LE; LI = LI.increment(EC)) { - StringRef VersionText = llvm::sys::path::filename(LI->path()); - int Version; - if (VersionText[0] == 'v' && - !VersionText.slice(1, StringRef::npos).getAsInteger(10, Version)) { - if (Version > MaxVersion) { - MaxVersion = Version; - MaxVersionString = std::string(VersionText); - } - } - } - return MaxVersion ? (base + "/" + MaxVersionString).str() : ""; -} - void Generic_GCC::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const { auto AddIncludePath = [&](std::string Path) { - std::string IncludePath = DetectLibcxxIncludePath(getVFS(), Path); - if (IncludePath.empty() || !getVFS().exists(IncludePath)) + std::string Version = detectLibcxxVersion(Path); + std::string IncludePath = Path + "/c++/" + Version; + if (Version.empty() || !getVFS().exists(IncludePath)) return false; addSystemInclude(DriverArgs, CC1Args, IncludePath); return true; @@ -2925,15 +2906,15 @@ // Android never uses the libc++ headers installed alongside the toolchain, // which are generally incompatible with the NDK libraries anyway. if (!getTriple().isAndroid()) - if (AddIncludePath(getDriver().Dir + "/../include/c++")) + if (AddIncludePath(getDriver().Dir + "/../include")) return; // If this is a development, non-installed, clang, libcxx will // not be found at ../include/c++ but it likely to be found at // one of the following two locations: std::string SysRoot = computeSysRoot(); - if (AddIncludePath(SysRoot + "/usr/local/include/c++")) + if (AddIncludePath(SysRoot + "/usr/local/include")) return; - if (AddIncludePath(SysRoot + "/usr/include/c++")) + if (AddIncludePath(SysRoot + "/usr/include")) return; } diff --git a/clang/test/Driver/Inputs/basic_fuchsia_tree/include/c++/v1/.keep b/clang/test/Driver/Inputs/basic_fuchsia_tree/include/c++/v1/.keep new file mode 100644