Index: lib/Driver/MSVCToolChain.cpp =================================================================== --- lib/Driver/MSVCToolChain.cpp +++ lib/Driver/MSVCToolChain.cpp @@ -283,6 +283,66 @@ return true; } +bool MSVCToolChain::getUniversalCRTSdkDir(std::string &path, + std::string &ucrtVersion) const +{ + // vcvarsqueryregistry.bat for Visual Studio 2015 queries the registry + // for the specific key "KitsRoot10". So do we. + if (!getSystemRegistryString( + "SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots", + "KitsRoot10", path, nullptr)) + return false; + + ucrtVersion.clear(); + + // Find the most recent version of Universal CRT. + // vcvarsqueryregistry.bat sorts entries in the include directory by names and + // uses the last one of the list. + // So we compare entry names lexicographically to find the greatest one. + std::error_code ec; + llvm::SmallString<128> includePath(path); + llvm::sys::path::append(includePath, "Include"); + for (llvm::sys::fs::directory_iterator dirIt(includePath, ec), dirEnd; + dirIt != dirEnd && !ec; dirIt.increment(ec)) { + if (!llvm::sys::fs::is_directory(dirIt->path())) + continue; + StringRef name = llvm::sys::path::filename(dirIt->path()); + if (name > ucrtVersion) + ucrtVersion = name; + } + + return !ucrtVersion.empty(); +} + +bool MSVCToolChain::getUniversalCRTLibraryPath(std::string &path) const +{ + std::string universalCRTSdkPath; + std::string ucrtVersion; + + path.clear(); + if (!getUniversalCRTSdkDir(universalCRTSdkPath, ucrtVersion)) + return false; + + llvm::SmallString<128> libPath(universalCRTSdkPath); + llvm::sys::path::append(libPath, "Lib", ucrtVersion, "ucrt"); + switch (getArch()) { + case llvm::Triple::x86: + llvm::sys::path::append(libPath, "x86"); + break; + case llvm::Triple::x86_64: + llvm::sys::path::append(libPath, "x64"); + break; + case llvm::Triple::arm: + llvm::sys::path::append(libPath, "arm"); + break; + default: + return false; + } + + path = libPath.str(); + return true; +} + // Get the location to use for Visual Studio binaries. The location priority // is: %VCINSTALLDIR% > %PATH% > newest copy of Visual Studio installed on // system (as reported by the registry). @@ -460,6 +520,14 @@ if (getVisualStudioInstallDir(VSDir)) { AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, VSDir, "VC\\include"); + std::string universalCRTSdkPath; + std::string ucrtVersion; + if (getUniversalCRTSdkDir(universalCRTSdkPath, ucrtVersion)) { + llvm::SmallString<128> ucrtIncludePath(universalCRTSdkPath); + llvm::sys::path::append(ucrtIncludePath, "Include", ucrtVersion, "ucrt"); + addSystemInclude(DriverArgs, CC1Args, ucrtIncludePath); + } + std::string WindowsSDKDir; int major, minor; if (getWindowsSDKDir(WindowsSDKDir, major, minor)) { Index: lib/Driver/ToolChains.h =================================================================== --- lib/Driver/ToolChains.h +++ lib/Driver/ToolChains.h @@ -836,6 +836,9 @@ bool getWindowsSDKDir(std::string &path, int &major, int &minor) const; bool getWindowsSDKLibraryPath(std::string &path) const; + bool getUniversalCRTSdkDir(std::string &path, + std::string &ucrtVersion) const; + bool getUniversalCRTLibraryPath(std::string &path) const; bool getVisualStudioInstallDir(std::string &path) const; bool getVisualStudioBinariesFolder(const char *clangProgramPath, std::string &path) const; Index: lib/Driver/Tools.cpp =================================================================== --- lib/Driver/Tools.cpp +++ lib/Driver/Tools.cpp @@ -8953,6 +8953,11 @@ Args.MakeArgString(std::string("-libpath:") + LibDir.c_str())); } + std::string UniversalCRTLibPath; + if (MSVC.getUniversalCRTLibraryPath(UniversalCRTLibPath)) + CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") + + UniversalCRTLibPath.c_str())); + std::string WindowsSdkLibPath; if (MSVC.getWindowsSDKLibraryPath(WindowsSdkLibPath)) CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") +