r297851 - Update clang-cl driver for MSVC 2017.

Zachary Turner via cfe-commits cfe-commits at lists.llvm.org
Wed Mar 15 09:07:35 PDT 2017


Author: zturner
Date: Wed Mar 15 11:07:35 2017
New Revision: 297851

URL: http://llvm.org/viewvc/llvm-project?rev=297851&view=rev
Log:
Update clang-cl driver for MSVC 2017.

2017 changes the way you find an installed copy of
Visual Studio as well as its internal directory layout.
As a result, clang-cl was unable to find VS2017 even
when you had run vcvarsall to set up a toolchain
environment.  This patch updates everything for 2017
and cleans up the way we handle a tiered search a la
environment -> installation -> PATH for which copy
of Visual Studio to bind to.

Patch originally by Hamza Sood, with some fixups for landing.

Differential Revision: https://reviews.llvm.org/D30758

Added:
    cfe/trunk/lib/Driver/ToolChains/MSVCSetupApi.h
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td
    cfe/trunk/lib/Driver/ToolChains/MSVC.cpp
    cfe/trunk/lib/Driver/ToolChains/MSVC.h
    cfe/trunk/test/Driver/cl-link-at-file.c

Modified: cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td?rev=297851&r1=297850&r2=297851&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td Wed Mar 15 11:07:35 2017
@@ -283,4 +283,8 @@ def warn_drv_ps4_sdk_dir : Warning<
 def err_drv_unsupported_linker : Error<"unsupported value '%0' for -linker option">;
 def err_drv_defsym_invalid_format : Error<"defsym must be of the form: sym=value: %0">;
 def err_drv_defsym_invalid_symval : Error<"Value is not an integer: %0">;
+def warn_drv_msvc_not_found : Warning<
+  "unable to find a Visual Studio installation; "
+  "try running Clang from a developer command prompt">,
+  InGroup<InvalidOrNonExistentDirectory>;
 }

Modified: cfe/trunk/lib/Driver/ToolChains/MSVC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/ToolChains/MSVC.cpp?rev=297851&r1=297850&r2=297851&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/ToolChains/MSVC.cpp (original)
+++ cfe/trunk/lib/Driver/ToolChains/MSVC.cpp Wed Mar 15 11:07:35 2017
@@ -7,9 +7,9 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "Darwin.h"
 #include "MSVC.h"
 #include "CommonArgs.h"
+#include "Darwin.h"
 #include "clang/Basic/CharInfo.h"
 #include "clang/Basic/Version.h"
 #include "clang/Driver/Compilation.h"
@@ -25,6 +25,8 @@
 #include "llvm/Support/ConvertUTF.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/Process.h"
 #include <cstdio>
@@ -42,6 +44,18 @@
     #define NOMINMAX
   #endif
   #include <windows.h>
+
+// Make sure this comes before MSVCSetupApi.h
+#include <comdef.h>
+
+#include "MSVCSetupApi.h"
+#include "llvm/Support/COM.h"
+_COM_SMARTPTR_TYPEDEF(ISetupConfiguration, __uuidof(ISetupConfiguration));
+_COM_SMARTPTR_TYPEDEF(ISetupConfiguration2, __uuidof(ISetupConfiguration2));
+_COM_SMARTPTR_TYPEDEF(ISetupHelper, __uuidof(ISetupHelper));
+_COM_SMARTPTR_TYPEDEF(IEnumSetupInstances, __uuidof(IEnumSetupInstances));
+_COM_SMARTPTR_TYPEDEF(ISetupInstance, __uuidof(ISetupInstance));
+_COM_SMARTPTR_TYPEDEF(ISetupInstance2, __uuidof(ISetupInstance2));
 #endif
 
 using namespace clang::driver;
@@ -50,24 +64,232 @@ using namespace clang::driver::tools;
 using namespace clang;
 using namespace llvm::opt;
 
+// Defined below.
+// Forward declare this so there aren't too many things above the constructor.
+static bool getSystemRegistryString(const char *keyPath, const char *valueName,
+                                    std::string &value, std::string *phValue);
+
+// Check various environment variables to try and find a toolchain.
+static bool findVCToolChainViaEnvironment(std::string &Path,
+                                          bool &IsVS2017OrNewer) {
+  // These variables are typically set by vcvarsall.bat
+  // when launching a developer command prompt.
+  if (llvm::Optional<std::string> VCToolsInstallDir =
+          llvm::sys::Process::GetEnv("VCToolsInstallDir")) {
+    // This is only set by newer Visual Studios, and it leads straight to
+    // the toolchain directory.
+    Path = std::move(*VCToolsInstallDir);
+    IsVS2017OrNewer = true;
+    return true;
+  }
+  if (llvm::Optional<std::string> VCInstallDir =
+          llvm::sys::Process::GetEnv("VCINSTALLDIR")) {
+    // If the previous variable isn't set but this one is, then we've found
+    // an older Visual Studio. This variable is set by newer Visual Studios too,
+    // so this check has to appear second.
+    // In older Visual Studios, the VC directory is the toolchain.
+    Path = std::move(*VCInstallDir);
+    IsVS2017OrNewer = false;
+    return true;
+  }
+
+  // We couldn't find any VC environment variables. Let's walk through PATH and
+  // see if it leads us to a VC toolchain bin directory. If it does, pick the
+  // first one that we find.
+  if (llvm::Optional<std::string> PathEnv =
+          llvm::sys::Process::GetEnv("PATH")) {
+    llvm::SmallVector<llvm::StringRef, 8> PathEntries;
+    llvm::StringRef(*PathEnv).split(PathEntries, llvm::sys::EnvPathSeparator);
+    for (llvm::StringRef PathEntry : PathEntries) {
+      if (PathEntry.empty())
+        continue;
+
+      llvm::SmallString<256> ExeTestPath;
+
+      // If cl.exe doesn't exist, then this definitely isn't a VC toolchain.
+      ExeTestPath = PathEntry;
+      llvm::sys::path::append(ExeTestPath, "cl.exe");
+      if (!llvm::sys::fs::exists(ExeTestPath))
+        continue;
+
+      // cl.exe existing isn't a conclusive test for a VC toolchain; clang also
+      // has a cl.exe. So let's check for link.exe too.
+      ExeTestPath = PathEntry;
+      llvm::sys::path::append(ExeTestPath, "link.exe");
+      if (!llvm::sys::fs::exists(ExeTestPath))
+        continue;
+
+      // whatever/VC/bin --> old toolchain, VC dir is toolchain dir.
+      if (llvm::sys::path::filename(PathEntry) == "bin") {
+        llvm::StringRef ParentPath = llvm::sys::path::parent_path(PathEntry);
+        if (llvm::sys::path::filename(ParentPath) == "VC") {
+          Path = ParentPath;
+          IsVS2017OrNewer = false;
+          return true;
+        }
+
+      } else {
+        // This could be a new (>=VS2017) toolchain. If it is, we should find
+        // path components with these prefixes when walking backwards through
+        // the path.
+        // Note: empty strings match anything.
+        llvm::StringRef ExpectedPrefixes[] = {"",     "Host",  "bin", "",
+                                              "MSVC", "Tools", "VC"};
+
+        auto It = llvm::sys::path::rbegin(PathEntry);
+        auto End = llvm::sys::path::rend(PathEntry);
+        for (llvm::StringRef Prefix : ExpectedPrefixes) {
+          if (It == End)
+            goto NotAToolChain;
+          if (!It->startswith(Prefix))
+            goto NotAToolChain;
+          ++It;
+        }
+
+        // We've found a new toolchain!
+        // Back up 3 times (/bin/Host/arch) to get the root path.
+        llvm::StringRef ToolChainPath(PathEntry);
+        for (int i = 0; i < 3; ++i)
+          ToolChainPath = llvm::sys::path::parent_path(ToolChainPath);
+
+        Path = ToolChainPath;
+        IsVS2017OrNewer = true;
+        return true;
+      }
+
+    NotAToolChain:
+      continue;
+    }
+  }
+  return false;
+}
+
+// Query the Setup Config server for installs, then pick the newest version
+// and find its default VC toolchain.
+// This is the preferred way to discover new Visual Studios, as they're no
+// longer listed in the registry.
+static bool findVCToolChainViaSetupConfig(std::string &Path,
+                                          bool &IsVS2017OrNewer) {
+#if !defined(USE_WIN32)
+  return false;
+#else
+  // FIXME: This really should be done once in the top-level program's main
+  // function, as it may have already been initialized with a different
+  // threading model otherwise.
+  llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::SingleThreaded);
+  HRESULT HR;
+
+  // _com_ptr_t will throw a _com_error if a COM calls fail.
+  // The LLVM coding standards forbid exception handling, so we'll have to
+  // stop them from being thrown in the first place.
+  // The destructor will put the regular error handler back when we leave
+  // this scope.
+  struct SuppressCOMErrorsRAII {
+    static void __stdcall handler(HRESULT hr, IErrorInfo *perrinfo) {}
+
+    SuppressCOMErrorsRAII() { _set_com_error_handler(handler); }
+
+    ~SuppressCOMErrorsRAII() { _set_com_error_handler(_com_raise_error); }
+
+  } COMErrorSuppressor;
+
+  ISetupConfigurationPtr Query;
+  HR = Query.CreateInstance(__uuidof(SetupConfiguration));
+  if (FAILED(HR))
+    return false;
+
+  IEnumSetupInstancesPtr EnumInstances;
+  HR = ISetupConfiguration2Ptr(Query)->EnumAllInstances(&EnumInstances);
+  if (FAILED(HR))
+    return false;
+
+  ISetupInstancePtr Instance;
+  HR = EnumInstances->Next(1, &Instance, nullptr);
+  if (HR != S_OK)
+    return false;
+
+  ISetupInstancePtr NewestInstance;
+  Optional<uint64_t> NewestVersionNum;
+  do {
+    bstr_t VersionString;
+    uint64_t VersionNum;
+    HR = Instance->GetInstallationVersion(VersionString.GetAddress());
+    if (FAILED(HR))
+      continue;
+    HR = ISetupHelperPtr(Query)->ParseVersion(VersionString, &VersionNum);
+    if (FAILED(HR))
+      continue;
+    if (!NewestVersionNum || (VersionNum > NewestVersionNum)) {
+      NewestInstance = Instance;
+      NewestVersionNum = VersionNum;
+    }
+  } while ((HR = EnumInstances->Next(1, &Instance, nullptr)) == S_OK);
+
+  if (!NewestInstance)
+    return false;
+
+  bstr_t VCPathWide;
+  HR = NewestInstance->ResolvePath(L"VC", VCPathWide.GetAddress());
+  if (FAILED(HR))
+    return false;
+
+  std::string VCRootPath;
+  llvm::convertWideToUTF8(std::wstring(VCPathWide), VCRootPath);
+
+  llvm::SmallString<256> ToolsVersionFilePath(VCRootPath);
+  llvm::sys::path::append(ToolsVersionFilePath, "Auxiliary", "Build",
+                          "Microsoft.VCToolsVersion.default.txt");
+
+  auto ToolsVersionFile = llvm::MemoryBuffer::getFile(ToolsVersionFilePath);
+  if (!ToolsVersionFile)
+    return false;
+
+  llvm::SmallString<256> ToolchainPath(VCRootPath);
+  llvm::sys::path::append(ToolchainPath, "Tools", "MSVC",
+                          ToolsVersionFile->get()->getBuffer().rtrim());
+  if (!llvm::sys::fs::is_directory(ToolchainPath))
+    return false;
+
+  Path = ToolchainPath.str();
+  IsVS2017OrNewer = true;
+  return true;
+#endif
+}
+
+// Look in the registry for Visual Studio installs, and use that to get
+// a toolchain path. VS2017 and newer don't get added to the registry.
+// So if we find something here, we know that it's an older version.
+static bool findVCToolChainViaRegistry(std::string &Path,
+                                       bool &IsVS2017OrNewer) {
+  std::string VSInstallPath;
+  if (getSystemRegistryString(R"(SOFTWARE\Microsoft\VisualStudio\$VERSION)",
+                              "InstallDir", VSInstallPath, nullptr) ||
+      getSystemRegistryString(R"(SOFTWARE\Microsoft\VCExpress\$VERSION)",
+                              "InstallDir", VSInstallPath, nullptr)) {
+    if (!VSInstallPath.empty()) {
+      llvm::SmallString<256> VCPath(llvm::StringRef(
+          VSInstallPath.c_str(), VSInstallPath.find(R"(\Common7\IDE)")));
+      llvm::sys::path::append(VCPath, "VC");
+
+      Path = VCPath.str();
+      IsVS2017OrNewer = false;
+      return true;
+    }
+  }
+  return false;
+}
+
 // Try to find Exe from a Visual Studio distribution.  This first tries to find
 // an installed copy of Visual Studio and, failing that, looks in the PATH,
 // making sure that whatever executable that's found is not a same-named exe
 // from clang itself to prevent clang from falling back to itself.
 static std::string FindVisualStudioExecutable(const ToolChain &TC,
-                                              const char *Exe,
-                                              const char *ClangProgramPath) {
+                                              const char *Exe) {
   const auto &MSVC = static_cast<const toolchains::MSVCToolChain &>(TC);
-  std::string visualStudioBinDir;
-  if (MSVC.getVisualStudioBinariesFolder(ClangProgramPath,
-                                         visualStudioBinDir)) {
-    SmallString<128> FilePath(visualStudioBinDir);
-    llvm::sys::path::append(FilePath, Exe);
-    if (llvm::sys::fs::can_execute(FilePath.c_str()))
-      return FilePath.str();
-  }
-
-  return Exe;
+  SmallString<128> FilePath(MSVC.getSubDirectoryPath(
+      toolchains::MSVCToolChain::SubDirectoryType::Bin));
+  llvm::sys::path::append(FilePath, Exe);
+  return llvm::sys::fs::can_execute(FilePath) ? FilePath.str() : Exe;
 }
 
 void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
@@ -76,7 +298,8 @@ void visualstudio::Linker::ConstructJob(
                                         const ArgList &Args,
                                         const char *LinkingOutput) const {
   ArgStringList CmdArgs;
-  const ToolChain &TC = getToolChain();
+
+  auto &TC = static_cast<const toolchains::MSVCToolChain &>(getToolChain());
 
   assert((Output.isFilename() || Output.isNothing()) && "invalid output");
   if (Output.isFilename())
@@ -92,37 +315,20 @@ void visualstudio::Linker::ConstructJob(
     // did not run vcvarsall), try to build a consistent link environment.  If
     // the environment variable is set however, assume the user knows what
     // they're doing.
-    std::string VisualStudioDir;
-    const auto &MSVC = static_cast<const toolchains::MSVCToolChain &>(TC);
-    if (MSVC.getVisualStudioInstallDir(VisualStudioDir)) {
-      SmallString<128> LibDir(VisualStudioDir);
-      llvm::sys::path::append(LibDir, "VC", "lib");
-      switch (MSVC.getArch()) {
-      case llvm::Triple::x86:
-        // x86 just puts the libraries directly in lib
-        break;
-      case llvm::Triple::x86_64:
-        llvm::sys::path::append(LibDir, "amd64");
-        break;
-      case llvm::Triple::arm:
-        llvm::sys::path::append(LibDir, "arm");
-        break;
-      default:
-        break;
-      }
-      CmdArgs.push_back(
-          Args.MakeArgString(std::string("-libpath:") + LibDir.c_str()));
-
-      if (MSVC.useUniversalCRT(VisualStudioDir)) {
-        std::string UniversalCRTLibPath;
-        if (MSVC.getUniversalCRTLibraryPath(UniversalCRTLibPath))
-          CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") +
-                                               UniversalCRTLibPath));
-      }
+    CmdArgs.push_back(Args.MakeArgString(
+        Twine("-libpath:") +
+        TC.getSubDirectoryPath(
+            toolchains::MSVCToolChain::SubDirectoryType::Lib)));
+
+    if (TC.useUniversalCRT()) {
+      std::string UniversalCRTLibPath;
+      if (TC.getUniversalCRTLibraryPath(UniversalCRTLibPath))
+        CmdArgs.push_back(
+            Args.MakeArgString(Twine("-libpath:") + UniversalCRTLibPath));
     }
 
     std::string WindowsSdkLibPath;
-    if (MSVC.getWindowsSDKLibraryPath(WindowsSdkLibPath))
+    if (TC.getWindowsSDKLibraryPath(WindowsSdkLibPath))
       CmdArgs.push_back(
           Args.MakeArgString(std::string("-libpath:") + WindowsSdkLibPath));
   }
@@ -247,8 +453,7 @@ void visualstudio::Linker::ConstructJob(
     // If we're using the MSVC linker, it's not sufficient to just use link
     // from the program PATH, because other environments like GnuWin32 install
     // their own link.exe which may come first.
-    linkPath = FindVisualStudioExecutable(TC, "link.exe",
-                                          C.getDriver().getClangProgramPath());
+    linkPath = FindVisualStudioExecutable(TC, "link.exe");
   } else {
     linkPath = Linker;
     llvm::sys::path::replace_extension(linkPath, "exe");
@@ -381,9 +586,7 @@ std::unique_ptr<Command> visualstudio::C
       Args.MakeArgString(std::string("/Fo") + Output.getFilename());
   CmdArgs.push_back(Fo);
 
-  const Driver &D = getToolChain().getDriver();
-  std::string Exec = FindVisualStudioExecutable(getToolChain(), "cl.exe",
-                                                D.getClangProgramPath());
+  std::string Exec = FindVisualStudioExecutable(getToolChain(), "cl.exe");
   return llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec),
                                     CmdArgs, Inputs);
 }
@@ -394,9 +597,19 @@ MSVCToolChain::MSVCToolChain(const Drive
   getProgramPaths().push_back(getDriver().getInstalledDir());
   if (getDriver().getInstalledDir() != getDriver().Dir)
     getProgramPaths().push_back(getDriver().Dir);
+
+  // Check the environment first, since that's probably the user telling us
+  // what they want to use.
+  // Failing that, just try to find the newest Visual Studio version we can
+  // and use its default VC toolchain.
+  findVCToolChainViaEnvironment(VCToolChainPath, IsVS2017OrNewer) ||
+      findVCToolChainViaSetupConfig(VCToolChainPath, IsVS2017OrNewer) ||
+      findVCToolChainViaRegistry(VCToolChainPath, IsVS2017OrNewer);
 }
 
 Tool *MSVCToolChain::buildLinker() const {
+  if (VCToolChainPath.empty())
+    getDriver().Diag(clang::diag::warn_drv_msvc_not_found);
   return new tools::visualstudio::Linker(*this);
 }
 
@@ -444,6 +657,72 @@ void MSVCToolChain::printVerboseInfo(raw
   CudaInstallation.print(OS);
 }
 
+// Windows SDKs and VC Toolchains group their contents into subdirectories based
+// on the target architecture. This function converts an llvm::Triple::ArchType
+// to the corresponding subdirectory name.
+static const char *llvmArchToWindowsSDKArch(llvm::Triple::ArchType Arch) {
+  using ArchType = llvm::Triple::ArchType;
+  switch (Arch) {
+  case ArchType::x86:
+    return "x86";
+  case ArchType::x86_64:
+    return "x64";
+  case ArchType::arm:
+    return "arm";
+  default:
+    return "";
+  }
+}
+
+// Similar to the above function, but for Visual Studios before VS2017.
+static const char *llvmArchToLegacyVCArch(llvm::Triple::ArchType Arch) {
+  using ArchType = llvm::Triple::ArchType;
+  switch (Arch) {
+  case ArchType::x86:
+    // x86 is default in legacy VC toolchains.
+    // e.g. x86 libs are directly in /lib as opposed to /lib/x86.
+    return "";
+  case ArchType::x86_64:
+    return "amd64";
+  case ArchType::arm:
+    return "arm";
+  default:
+    return "";
+  }
+}
+
+// Get the path to a specific subdirectory in the current toolchain for
+// a given target architecture.
+// VS2017 changed the VC toolchain layout, so this should be used instead
+// of hardcoding paths.
+std::string
+MSVCToolChain::getSubDirectoryPath(SubDirectoryType Type,
+                                   llvm::Triple::ArchType TargetArch) const {
+  llvm::SmallString<256> Path(VCToolChainPath);
+  switch (Type) {
+  case SubDirectoryType::Bin:
+    if (IsVS2017OrNewer) {
+      bool HostIsX64 =
+          llvm::Triple(llvm::sys::getProcessTriple()).isArch64Bit();
+      llvm::sys::path::append(Path, "bin", (HostIsX64 ? "HostX64" : "HostX86"),
+                              llvmArchToWindowsSDKArch(TargetArch));
+
+    } else {
+      llvm::sys::path::append(Path, "bin", llvmArchToLegacyVCArch(TargetArch));
+    }
+    break;
+  case SubDirectoryType::Include:
+    llvm::sys::path::append(Path, "include");
+    break;
+  case SubDirectoryType::Lib:
+    llvm::sys::path::append(
+        Path, "lib", IsVS2017OrNewer ? llvmArchToWindowsSDKArch(TargetArch)
+                                     : llvmArchToLegacyVCArch(TargetArch));
+    break;
+  }
+  return Path.str();
+}
+
 #ifdef USE_WIN32
 static bool readFullStringValue(HKEY hkey, const char *valueName,
                                 std::string &value) {
@@ -573,27 +852,12 @@ static bool getSystemRegistryString(cons
 #endif // USE_WIN32
 }
 
-// Convert LLVM's ArchType
-// to the corresponding name of Windows SDK libraries subfolder
-static StringRef getWindowsSDKArch(llvm::Triple::ArchType Arch) {
-  switch (Arch) {
-  case llvm::Triple::x86:
-    return "x86";
-  case llvm::Triple::x86_64:
-    return "x64";
-  case llvm::Triple::arm:
-    return "arm";
-  default:
-    return "";
-  }
-}
-
 // Find the most recent version of Universal CRT or Windows 10 SDK.
 // vcvarsqueryregistry.bat from Visual Studio 2015 sorts entries in the include
 // directory by name and uses the last one of the list.
 // So we compare entry names lexicographically to find the greatest one.
-static bool getWindows10SDKVersion(const std::string &SDKPath,
-                                   std::string &SDKVersion) {
+static bool getWindows10SDKVersionFromPath(const std::string &SDKPath,
+                                           std::string &SDKVersion) {
   SDKVersion.clear();
 
   std::error_code EC;
@@ -617,9 +881,9 @@ static bool getWindows10SDKVersion(const
 }
 
 /// \brief Get Windows SDK installation directory.
-bool MSVCToolChain::getWindowsSDKDir(std::string &Path, int &Major,
-                                     std::string &WindowsSDKIncludeVersion,
-                                     std::string &WindowsSDKLibVersion) const {
+static bool getWindowsSDKDir(std::string &Path, int &Major,
+                             std::string &WindowsSDKIncludeVersion,
+                             std::string &WindowsSDKLibVersion) {
   std::string RegistrySDKVersion;
   // Try the Windows registry.
   if (!getSystemRegistryString(
@@ -651,7 +915,7 @@ bool MSVCToolChain::getWindowsSDKDir(std
     return !WindowsSDKLibVersion.empty();
   }
   if (Major == 10) {
-    if (!getWindows10SDKVersion(Path, WindowsSDKIncludeVersion))
+    if (!getWindows10SDKVersionFromPath(Path, WindowsSDKIncludeVersion))
       return false;
     WindowsSDKLibVersion = WindowsSDKIncludeVersion;
     return true;
@@ -674,7 +938,10 @@ bool MSVCToolChain::getWindowsSDKLibrary
 
   llvm::SmallString<128> libPath(sdkPath);
   llvm::sys::path::append(libPath, "Lib");
-  if (sdkMajor <= 7) {
+  if (sdkMajor >= 8) {
+    llvm::sys::path::append(libPath, windowsSDKLibVersion, "um",
+                            llvmArchToWindowsSDKArch(getArch()));
+  } else {
     switch (getArch()) {
     // In Windows SDK 7.x, x86 libraries are directly in the Lib folder.
     case llvm::Triple::x86:
@@ -688,11 +955,6 @@ bool MSVCToolChain::getWindowsSDKLibrary
     default:
       return false;
     }
-  } else {
-    const StringRef archName = getWindowsSDKArch(getArch());
-    if (archName.empty())
-      return false;
-    llvm::sys::path::append(libPath, windowsSDKLibVersion, "um", archName);
   }
 
   path = libPath.str();
@@ -701,16 +963,14 @@ bool MSVCToolChain::getWindowsSDKLibrary
 
 // Check if the Include path of a specified version of Visual Studio contains
 // specific header files. If not, they are probably shipped with Universal CRT.
-bool clang::driver::toolchains::MSVCToolChain::useUniversalCRT(
-    std::string &VisualStudioDir) const {
-  llvm::SmallString<128> TestPath(VisualStudioDir);
-  llvm::sys::path::append(TestPath, "VC\\include\\stdlib.h");
-
+bool MSVCToolChain::useUniversalCRT() const {
+  llvm::SmallString<128> TestPath(
+      getSubDirectoryPath(SubDirectoryType::Include));
+  llvm::sys::path::append(TestPath, "stdlib.h");
   return !llvm::sys::fs::exists(TestPath);
 }
 
-bool MSVCToolChain::getUniversalCRTSdkDir(std::string &Path,
-                                          std::string &UCRTVersion) const {
+static bool getUniversalCRTSdkDir(std::string &Path, std::string &UCRTVersion) {
   // vcvarsqueryregistry.bat for Visual Studio 2015 queries the registry
   // for the specific key "KitsRoot10". So do we.
   if (!getSystemRegistryString(
@@ -718,7 +978,7 @@ bool MSVCToolChain::getUniversalCRTSdkDi
           Path, nullptr))
     return false;
 
-  return getWindows10SDKVersion(Path, UCRTVersion);
+  return getWindows10SDKVersionFromPath(Path, UCRTVersion);
 }
 
 bool MSVCToolChain::getUniversalCRTLibraryPath(std::string &Path) const {
@@ -729,7 +989,7 @@ bool MSVCToolChain::getUniversalCRTLibra
   if (!getUniversalCRTSdkDir(UniversalCRTSdkPath, UCRTVersion))
     return false;
 
-  StringRef ArchName = getWindowsSDKArch(getArch());
+  StringRef ArchName = llvmArchToWindowsSDKArch(getArch());
   if (ArchName.empty())
     return false;
 
@@ -740,104 +1000,18 @@ bool MSVCToolChain::getUniversalCRTLibra
   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).
-bool MSVCToolChain::getVisualStudioBinariesFolder(const char *clangProgramPath,
-                                                  std::string &path) const {
-  path.clear();
-
-  SmallString<128> BinDir;
-
-  // First check the environment variables that vsvars32.bat sets.
-  llvm::Optional<std::string> VcInstallDir =
-      llvm::sys::Process::GetEnv("VCINSTALLDIR");
-  if (VcInstallDir.hasValue()) {
-    BinDir = VcInstallDir.getValue();
-    llvm::sys::path::append(BinDir, "bin");
-  } else {
-    // Next walk the PATH, trying to find a cl.exe in the path.  If we find one,
-    // use that.  However, make sure it's not clang's cl.exe.
-    llvm::Optional<std::string> OptPath = llvm::sys::Process::GetEnv("PATH");
-    if (OptPath.hasValue()) {
-      const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'};
-      SmallVector<StringRef, 8> PathSegments;
-      llvm::SplitString(OptPath.getValue(), PathSegments, EnvPathSeparatorStr);
-
-      for (StringRef PathSegment : PathSegments) {
-        if (PathSegment.empty())
-          continue;
-
-        SmallString<128> FilePath(PathSegment);
-        llvm::sys::path::append(FilePath, "cl.exe");
-        // Checking if cl.exe exists is a small optimization over calling
-        // can_execute, which really only checks for existence but will also do
-        // extra checks for cl.exe.exe.  These add up when walking a long path.
-        if (llvm::sys::fs::exists(FilePath.c_str()) &&
-            !llvm::sys::fs::equivalent(FilePath.c_str(), clangProgramPath)) {
-          // If we found it on the PATH, use it exactly as is with no
-          // modifications.
-          path = PathSegment;
-          return true;
-        }
-      }
-    }
-
-    std::string installDir;
-    // With no VCINSTALLDIR and nothing on the PATH, if we can't find it in the
-    // registry then we have no choice but to fail.
-    if (!getVisualStudioInstallDir(installDir))
-      return false;
-
-    // Regardless of what binary we're ultimately trying to find, we make sure
-    // that this is a Visual Studio directory by checking for cl.exe.  We use
-    // cl.exe instead of other binaries like link.exe because programs such as
-    // GnuWin32 also have a utility called link.exe, so cl.exe is the least
-    // ambiguous.
-    BinDir = installDir;
-    llvm::sys::path::append(BinDir, "VC", "bin");
-    SmallString<128> ClPath(BinDir);
-    llvm::sys::path::append(ClPath, "cl.exe");
-
-    if (!llvm::sys::fs::can_execute(ClPath.c_str()))
-      return false;
-  }
-
-  if (BinDir.empty())
-    return false;
-
-  switch (getArch()) {
-  case llvm::Triple::x86:
-    break;
-  case llvm::Triple::x86_64:
-    llvm::sys::path::append(BinDir, "amd64");
-    break;
-  case llvm::Triple::arm:
-    llvm::sys::path::append(BinDir, "arm");
-    break;
-  default:
-    // Whatever this is, Visual Studio doesn't have a toolchain for it.
-    return false;
-  }
-  path = BinDir.str();
-  return true;
-}
-
-VersionTuple MSVCToolChain::getMSVCVersionFromTriple() const {
+static VersionTuple getMSVCVersionFromTriple(const llvm::Triple &Triple) {
   unsigned Major, Minor, Micro;
-  getTriple().getEnvironmentVersion(Major, Minor, Micro);
+  Triple.getEnvironmentVersion(Major, Minor, Micro);
   if (Major || Minor || Micro)
     return VersionTuple(Major, Minor, Micro);
   return VersionTuple();
 }
 
-VersionTuple MSVCToolChain::getMSVCVersionFromExe() const {
+static VersionTuple getMSVCVersionFromExe(const std::string &BinDir) {
   VersionTuple Version;
 #ifdef USE_WIN32
-  std::string BinPath;
-  if (!getVisualStudioBinariesFolder("", BinPath))
-    return Version;
-  SmallString<128> ClExe(BinPath);
+  SmallString<128> ClExe(BinDir);
   llvm::sys::path::append(ClExe, "cl.exe");
 
   std::wstring ClExeWide;
@@ -870,62 +1044,6 @@ VersionTuple MSVCToolChain::getMSVCVersi
   return Version;
 }
 
-// Get Visual Studio installation directory.
-bool MSVCToolChain::getVisualStudioInstallDir(std::string &path) const {
-  // First check the environment variables that vsvars32.bat sets.
-  if (llvm::Optional<std::string> VcInstallDir =
-          llvm::sys::Process::GetEnv("VCINSTALLDIR")) {
-    path = std::move(*VcInstallDir);
-    path = path.substr(0, path.find("\\VC"));
-    return true;
-  }
-
-  std::string vsIDEInstallDir;
-  std::string vsExpressIDEInstallDir;
-  // Then try the windows registry.
-  bool hasVCDir =
-      getSystemRegistryString("SOFTWARE\\Microsoft\\VisualStudio\\$VERSION",
-                              "InstallDir", vsIDEInstallDir, nullptr);
-  if (hasVCDir && !vsIDEInstallDir.empty()) {
-    path = vsIDEInstallDir.substr(0, vsIDEInstallDir.find("\\Common7\\IDE"));
-    return true;
-  }
-
-  bool hasVCExpressDir =
-      getSystemRegistryString("SOFTWARE\\Microsoft\\VCExpress\\$VERSION",
-                              "InstallDir", vsExpressIDEInstallDir, nullptr);
-  if (hasVCExpressDir && !vsExpressIDEInstallDir.empty()) {
-    path = vsExpressIDEInstallDir.substr(
-        0, vsIDEInstallDir.find("\\Common7\\IDE"));
-    return true;
-  }
-
-  // Try the environment.
-  std::string vcomntools;
-  if (llvm::Optional<std::string> vs120comntools =
-          llvm::sys::Process::GetEnv("VS120COMNTOOLS"))
-    vcomntools = std::move(*vs120comntools);
-  else if (llvm::Optional<std::string> vs100comntools =
-               llvm::sys::Process::GetEnv("VS100COMNTOOLS"))
-    vcomntools = std::move(*vs100comntools);
-  else if (llvm::Optional<std::string> vs90comntools =
-               llvm::sys::Process::GetEnv("VS90COMNTOOLS"))
-    vcomntools = std::move(*vs90comntools);
-  else if (llvm::Optional<std::string> vs80comntools =
-               llvm::sys::Process::GetEnv("VS80COMNTOOLS"))
-    vcomntools = std::move(*vs80comntools);
-
-  // Find any version we can.
-  if (!vcomntools.empty()) {
-    size_t p = vcomntools.find("\\Common7\\Tools");
-    if (p != std::string::npos)
-      vcomntools.resize(p);
-    path = std::move(vcomntools);
-    return true;
-  }
-  return false;
-}
-
 void MSVCToolChain::AddSystemIncludeWithSubfolder(
     const ArgList &DriverArgs, ArgStringList &CC1Args,
     const std::string &folder, const Twine &subfolder1, const Twine &subfolder2,
@@ -964,14 +1082,13 @@ void MSVCToolChain::AddClangSystemInclud
       return;
   }
 
-  std::string VSDir;
-
   // When built with access to the proper Windows APIs, try to actually find
   // the correct include paths first.
-  if (getVisualStudioInstallDir(VSDir)) {
-    AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, VSDir, "VC\\include");
+  if (!VCToolChainPath.empty()) {
+    addSystemInclude(DriverArgs, CC1Args,
+                     getSubDirectoryPath(SubDirectoryType::Include));
 
-    if (useUniversalCRT(VSDir)) {
+    if (useUniversalCRT()) {
       std::string UniversalCRTSdkPath;
       std::string UCRTVersion;
       if (getUniversalCRTSdkDir(UniversalCRTSdkPath, UCRTVersion)) {
@@ -1002,9 +1119,8 @@ void MSVCToolChain::AddClangSystemInclud
         AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
                                       "include");
       }
-    } else {
-      addSystemInclude(DriverArgs, CC1Args, VSDir);
     }
+
     return;
   }
 
@@ -1031,8 +1147,10 @@ VersionTuple MSVCToolChain::computeMSVCV
                                                const ArgList &Args) const {
   bool IsWindowsMSVC = getTriple().isWindowsMSVCEnvironment();
   VersionTuple MSVT = ToolChain::computeMSVCVersion(D, Args);
-  if (MSVT.empty()) MSVT = getMSVCVersionFromTriple();
-  if (MSVT.empty() && IsWindowsMSVC) MSVT = getMSVCVersionFromExe();
+  if (MSVT.empty())
+    MSVT = getMSVCVersionFromTriple(getTriple());
+  if (MSVT.empty() && IsWindowsMSVC)
+    MSVT = getMSVCVersionFromExe(getSubDirectoryPath(SubDirectoryType::Bin));
   if (MSVT.empty() &&
       Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
                    IsWindowsMSVC)) {

Modified: cfe/trunk/lib/Driver/ToolChains/MSVC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/ToolChains/MSVC.h?rev=297851&r1=297850&r2=297851&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/ToolChains/MSVC.h (original)
+++ cfe/trunk/lib/Driver/ToolChains/MSVC.h Wed Mar 15 11:07:35 2017
@@ -78,6 +78,22 @@ public:
   bool isPIEDefault() const override;
   bool isPICDefaultForced() const override;
 
+  enum class SubDirectoryType {
+    Bin,
+    Include,
+    Lib,
+  };
+  std::string getSubDirectoryPath(SubDirectoryType Type,
+                                  llvm::Triple::ArchType TargetArch) const;
+
+  // Convenience overload.
+  // Uses the current target arch.
+  std::string getSubDirectoryPath(SubDirectoryType Type) const {
+    return getSubDirectoryPath(Type, getArch());
+  }
+
+  bool getIsVS2017OrNewer() const { return IsVS2017OrNewer; }
+
   void
   AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
                             llvm::opt::ArgStringList &CC1Args) const override;
@@ -88,17 +104,10 @@ public:
   void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
                           llvm::opt::ArgStringList &CC1Args) const override;
 
-  bool getWindowsSDKDir(std::string &path, int &major,
-                        std::string &windowsSDKIncludeVersion,
-                        std::string &windowsSDKLibVersion) const;
   bool getWindowsSDKLibraryPath(std::string &path) const;
   /// \brief Check if Universal CRT should be used if available
-  bool useUniversalCRT(std::string &visualStudioDir) 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;
+  bool useUniversalCRT() const;
   VersionTuple
   computeMSVCVersion(const Driver *D,
                      const llvm::opt::ArgList &Args) const override;
@@ -120,9 +129,8 @@ protected:
   Tool *buildLinker() const override;
   Tool *buildAssembler() const override;
 private:
-  VersionTuple getMSVCVersionFromTriple() const;
-  VersionTuple getMSVCVersionFromExe() const;
-
+  std::string VCToolChainPath;
+  bool IsVS2017OrNewer;
   CudaInstallationDetector CudaInstallation;
 };
 

Added: cfe/trunk/lib/Driver/ToolChains/MSVCSetupApi.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/ToolChains/MSVCSetupApi.h?rev=297851&view=auto
==============================================================================
--- cfe/trunk/lib/Driver/ToolChains/MSVCSetupApi.h (added)
+++ cfe/trunk/lib/Driver/ToolChains/MSVCSetupApi.h Wed Mar 15 11:07:35 2017
@@ -0,0 +1,514 @@
+// <copyright file="Program.cpp" company="Microsoft Corporation">
+// Copyright (C) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+// </copyright>
+// <license>
+// The MIT License (MIT)
+//
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+// </license>
+
+#pragma once
+
+// Constants
+//
+#ifndef E_NOTFOUND
+#define E_NOTFOUND HRESULT_FROM_WIN32(ERROR_NOT_FOUND)
+#endif
+
+#ifndef E_FILENOTFOUND
+#define E_FILENOTFOUND HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)
+#endif
+
+// Enumerations
+//
+/// <summary>
+/// The state of an instance.
+/// </summary>
+enum InstanceState : unsigned {
+  /// <summary>
+  /// The instance state has not been determined.
+  /// </summary>
+  eNone = 0,
+
+  /// <summary>
+  /// The instance installation path exists.
+  /// </summary>
+  eLocal = 1,
+
+  /// <summary>
+  /// A product is registered to the instance.
+  /// </summary>
+  eRegistered = 2,
+
+  /// <summary>
+  /// No reboot is required for the instance.
+  /// </summary>
+  eNoRebootRequired = 4,
+
+  /// <summary>
+  /// The instance represents a complete install.
+  /// </summary>
+  eComplete = MAXUINT,
+};
+
+// Forward interface declarations
+//
+#ifndef __ISetupInstance_FWD_DEFINED__
+#define __ISetupInstance_FWD_DEFINED__
+typedef struct ISetupInstance ISetupInstance;
+#endif
+
+#ifndef __ISetupInstance2_FWD_DEFINED__
+#define __ISetupInstance2_FWD_DEFINED__
+typedef struct ISetupInstance2 ISetupInstance2;
+#endif
+
+#ifndef __IEnumSetupInstances_FWD_DEFINED__
+#define __IEnumSetupInstances_FWD_DEFINED__
+typedef struct IEnumSetupInstances IEnumSetupInstances;
+#endif
+
+#ifndef __ISetupConfiguration_FWD_DEFINED__
+#define __ISetupConfiguration_FWD_DEFINED__
+typedef struct ISetupConfiguration ISetupConfiguration;
+#endif
+
+#ifndef __ISetupConfiguration2_FWD_DEFINED__
+#define __ISetupConfiguration2_FWD_DEFINED__
+typedef struct ISetupConfiguration2 ISetupConfiguration2;
+#endif
+
+#ifndef __ISetupPackageReference_FWD_DEFINED__
+#define __ISetupPackageReference_FWD_DEFINED__
+typedef struct ISetupPackageReference ISetupPackageReference;
+#endif
+
+#ifndef __ISetupHelper_FWD_DEFINED__
+#define __ISetupHelper_FWD_DEFINED__
+typedef struct ISetupHelper ISetupHelper;
+#endif
+
+// Forward class declarations
+//
+#ifndef __SetupConfiguration_FWD_DEFINED__
+#define __SetupConfiguration_FWD_DEFINED__
+
+#ifdef __cplusplus
+typedef class SetupConfiguration SetupConfiguration;
+#endif
+
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Interface definitions
+//
+EXTERN_C const IID IID_ISetupInstance;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+/// <summary>
+/// Information about an instance of a product.
+/// </summary>
+struct DECLSPEC_UUID("B41463C3-8866-43B5-BC33-2B0676F7F42E")
+    DECLSPEC_NOVTABLE ISetupInstance : public IUnknown {
+  /// <summary>
+  /// Gets the instance identifier (should match the name of the parent instance
+  /// directory).
+  /// </summary>
+  /// <param name="pbstrInstanceId">The instance identifier.</param>
+  /// <returns>Standard HRESULT indicating success or failure, including
+  /// E_FILENOTFOUND if the instance state does not exist.</returns>
+  STDMETHOD(GetInstanceId)(_Out_ BSTR *pbstrInstanceId) = 0;
+
+  /// <summary>
+  /// Gets the local date and time when the installation was originally
+  /// installed.
+  /// </summary>
+  /// <param name="pInstallDate">The local date and time when the installation
+  /// was originally installed.</param>
+  /// <returns>Standard HRESULT indicating success or failure, including
+  /// E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the
+  /// property is not defined.</returns>
+  STDMETHOD(GetInstallDate)(_Out_ LPFILETIME pInstallDate) = 0;
+
+  /// <summary>
+  /// Gets the unique name of the installation, often indicating the branch and
+  /// other information used for telemetry.
+  /// </summary>
+  /// <param name="pbstrInstallationName">The unique name of the installation,
+  /// often indicating the branch and other information used for
+  /// telemetry.</param>
+  /// <returns>Standard HRESULT indicating success or failure, including
+  /// E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the
+  /// property is not defined.</returns>
+  STDMETHOD(GetInstallationName)(_Out_ BSTR *pbstrInstallationName) = 0;
+
+  /// <summary>
+  /// Gets the path to the installation root of the product.
+  /// </summary>
+  /// <param name="pbstrInstallationPath">The path to the installation root of
+  /// the product.</param>
+  /// <returns>Standard HRESULT indicating success or failure, including
+  /// E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the
+  /// property is not defined.</returns>
+  STDMETHOD(GetInstallationPath)(_Out_ BSTR *pbstrInstallationPath) = 0;
+
+  /// <summary>
+  /// Gets the version of the product installed in this instance.
+  /// </summary>
+  /// <param name="pbstrInstallationVersion">The version of the product
+  /// installed in this instance.</param>
+  /// <returns>Standard HRESULT indicating success or failure, including
+  /// E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the
+  /// property is not defined.</returns>
+  STDMETHOD(GetInstallationVersion)(_Out_ BSTR *pbstrInstallationVersion) = 0;
+
+  /// <summary>
+  /// Gets the display name (title) of the product installed in this instance.
+  /// </summary>
+  /// <param name="lcid">The LCID for the display name.</param>
+  /// <param name="pbstrDisplayName">The display name (title) of the product
+  /// installed in this instance.</param>
+  /// <returns>Standard HRESULT indicating success or failure, including
+  /// E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the
+  /// property is not defined.</returns>
+  STDMETHOD(GetDisplayName)(_In_ LCID lcid, _Out_ BSTR *pbstrDisplayName) = 0;
+
+  /// <summary>
+  /// Gets the description of the product installed in this instance.
+  /// </summary>
+  /// <param name="lcid">The LCID for the description.</param>
+  /// <param name="pbstrDescription">The description of the product installed in
+  /// this instance.</param>
+  /// <returns>Standard HRESULT indicating success or failure, including
+  /// E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the
+  /// property is not defined.</returns>
+  STDMETHOD(GetDescription)(_In_ LCID lcid, _Out_ BSTR *pbstrDescription) = 0;
+
+  /// <summary>
+  /// Resolves the optional relative path to the root path of the instance.
+  /// </summary>
+  /// <param name="pwszRelativePath">A relative path within the instance to
+  /// resolve, or NULL to get the root path.</param>
+  /// <param name="pbstrAbsolutePath">The full path to the optional relative
+  /// path within the instance. If the relative path is NULL, the root path will
+  /// always terminate in a backslash.</param>
+  /// <returns>Standard HRESULT indicating success or failure, including
+  /// E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the
+  /// property is not defined.</returns>
+  STDMETHOD(ResolvePath)
+  (_In_opt_z_ LPCOLESTR pwszRelativePath, _Out_ BSTR *pbstrAbsolutePath) = 0;
+};
+#endif
+
+EXTERN_C const IID IID_ISetupInstance2;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+/// <summary>
+/// Information about an instance of a product.
+/// </summary>
+struct DECLSPEC_UUID("89143C9A-05AF-49B0-B717-72E218A2185C")
+    DECLSPEC_NOVTABLE ISetupInstance2 : public ISetupInstance {
+  /// <summary>
+  /// Gets the state of the instance.
+  /// </summary>
+  /// <param name="pState">The state of the instance.</param>
+  /// <returns>Standard HRESULT indicating success or failure, including
+  /// E_FILENOTFOUND if the instance state does not exist.</returns>
+  STDMETHOD(GetState)(_Out_ InstanceState *pState) = 0;
+
+  /// <summary>
+  /// Gets an array of package references registered to the instance.
+  /// </summary>
+  /// <param name="ppsaPackages">Pointer to an array of <see
+  /// cref="ISetupPackageReference"/>.</param>
+  /// <returns>Standard HRESULT indicating success or failure, including
+  /// E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the
+  /// packages property is not defined.</returns>
+  STDMETHOD(GetPackages)(_Out_ LPSAFEARRAY *ppsaPackages) = 0;
+
+  /// <summary>
+  /// Gets a pointer to the <see cref="ISetupPackageReference"/> that represents
+  /// the registered product.
+  /// </summary>
+  /// <param name="ppPackage">Pointer to an instance of <see
+  /// cref="ISetupPackageReference"/>. This may be NULL if <see
+  /// cref="GetState"/> does not return <see cref="eComplete"/>.</param>
+  /// <returns>Standard HRESULT indicating success or failure, including
+  /// E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the
+  /// packages property is not defined.</returns>
+  STDMETHOD(GetProduct)
+  (_Outptr_result_maybenull_ ISetupPackageReference **ppPackage) = 0;
+
+  /// <summary>
+  /// Gets the relative path to the product application, if available.
+  /// </summary>
+  /// <param name="pbstrProductPath">The relative path to the product
+  /// application, if available.</param>
+  /// <returns>Standard HRESULT indicating success or failure, including
+  /// E_FILENOTFOUND if the instance state does not exist.</returns>
+  STDMETHOD(GetProductPath)
+  (_Outptr_result_maybenull_ BSTR *pbstrProductPath) = 0;
+};
+#endif
+
+EXTERN_C const IID IID_IEnumSetupInstances;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+/// <summary>
+/// A enumerator of installed <see cref="ISetupInstance"/> objects.
+/// </summary>
+struct DECLSPEC_UUID("6380BCFF-41D3-4B2E-8B2E-BF8A6810C848")
+    DECLSPEC_NOVTABLE IEnumSetupInstances : public IUnknown {
+  /// <summary>
+  /// Retrieves the next set of product instances in the enumeration sequence.
+  /// </summary>
+  /// <param name="celt">The number of product instances to retrieve.</param>
+  /// <param name="rgelt">A pointer to an array of <see
+  /// cref="ISetupInstance"/>.</param>
+  /// <param name="pceltFetched">A pointer to the number of product instances
+  /// retrieved. If celt is 1 this parameter may be NULL.</param>
+  /// <returns>S_OK if the number of elements were fetched, S_FALSE if nothing
+  /// was fetched (at end of enumeration), E_INVALIDARG if celt is greater than
+  /// 1 and pceltFetched is NULL, or E_OUTOFMEMORY if an <see
+  /// cref="ISetupInstance"/> could not be allocated.</returns>
+  STDMETHOD(Next)
+  (_In_ ULONG celt, _Out_writes_to_(celt, *pceltFetched) ISetupInstance **rgelt,
+   _Out_opt_ _Deref_out_range_(0, celt) ULONG *pceltFetched) = 0;
+
+  /// <summary>
+  /// Skips the next set of product instances in the enumeration sequence.
+  /// </summary>
+  /// <param name="celt">The number of product instances to skip.</param>
+  /// <returns>S_OK if the number of elements could be skipped; otherwise,
+  /// S_FALSE;</returns>
+  STDMETHOD(Skip)(_In_ ULONG celt) = 0;
+
+  /// <summary>
+  /// Resets the enumeration sequence to the beginning.
+  /// </summary>
+  /// <returns>Always returns S_OK;</returns>
+  STDMETHOD(Reset)(void) = 0;
+
+  /// <summary>
+  /// Creates a new enumeration object in the same state as the current
+  /// enumeration object: the new object points to the same place in the
+  /// enumeration sequence.
+  /// </summary>
+  /// <param name="ppenum">A pointer to a pointer to a new <see
+  /// cref="IEnumSetupInstances"/> interface. If the method fails, this
+  /// parameter is undefined.</param>
+  /// <returns>S_OK if a clone was returned; otherwise, E_OUTOFMEMORY.</returns>
+  STDMETHOD(Clone)(_Deref_out_opt_ IEnumSetupInstances **ppenum) = 0;
+};
+#endif
+
+EXTERN_C const IID IID_ISetupConfiguration;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+/// <summary>
+/// Gets information about product instances set up on the machine.
+/// </summary>
+struct DECLSPEC_UUID("42843719-DB4C-46C2-8E7C-64F1816EFD5B")
+    DECLSPEC_NOVTABLE ISetupConfiguration : public IUnknown {
+  /// <summary>
+  /// Enumerates all completed product instances installed.
+  /// </summary>
+  /// <param name="ppEnumInstances">An enumeration of completed, installed
+  /// product instances.</param>
+  /// <returns>Standard HRESULT indicating success or failure.</returns>
+  STDMETHOD(EnumInstances)(_Out_ IEnumSetupInstances **ppEnumInstances) = 0;
+
+  /// <summary>
+  /// Gets the instance for the current process path.
+  /// </summary>
+  /// <param name="ppInstance">The instance for the current process
+  /// path.</param>
+  /// <returns>The instance for the current process path, or E_NOTFOUND if not
+  /// found.</returns>
+  STDMETHOD(GetInstanceForCurrentProcess)
+  (_Out_ ISetupInstance **ppInstance) = 0;
+
+  /// <summary>
+  /// Gets the instance for the given path.
+  /// </summary>
+  /// <param name="ppInstance">The instance for the given path.</param>
+  /// <returns>The instance for the given path, or E_NOTFOUND if not
+  /// found.</returns>
+  STDMETHOD(GetInstanceForPath)
+  (_In_z_ LPCWSTR wzPath, _Out_ ISetupInstance **ppInstance) = 0;
+};
+#endif
+
+EXTERN_C const IID IID_ISetupConfiguration2;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+/// <summary>
+/// Gets information about product instances.
+/// </summary>
+struct DECLSPEC_UUID("26AAB78C-4A60-49D6-AF3B-3C35BC93365D")
+    DECLSPEC_NOVTABLE ISetupConfiguration2 : public ISetupConfiguration {
+  /// <summary>
+  /// Enumerates all product instances.
+  /// </summary>
+  /// <param name="ppEnumInstances">An enumeration of all product
+  /// instances.</param>
+  /// <returns>Standard HRESULT indicating success or failure.</returns>
+  STDMETHOD(EnumAllInstances)(_Out_ IEnumSetupInstances **ppEnumInstances) = 0;
+};
+#endif
+
+EXTERN_C const IID IID_ISetupPackageReference;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+/// <summary>
+/// A reference to a package.
+/// </summary>
+struct DECLSPEC_UUID("da8d8a16-b2b6-4487-a2f1-594ccccd6bf5")
+    DECLSPEC_NOVTABLE ISetupPackageReference : public IUnknown {
+  /// <summary>
+  /// Gets the general package identifier.
+  /// </summary>
+  /// <param name="pbstrId">The general package identifier.</param>
+  /// <returns>Standard HRESULT indicating success or failure.</returns>
+  STDMETHOD(GetId)(_Out_ BSTR *pbstrId) = 0;
+
+  /// <summary>
+  /// Gets the version of the package.
+  /// </summary>
+  /// <param name="pbstrVersion">The version of the package.</param>
+  /// <returns>Standard HRESULT indicating success or failure.</returns>
+  STDMETHOD(GetVersion)(_Out_ BSTR *pbstrVersion) = 0;
+
+  /// <summary>
+  /// Gets the target process architecture of the package.
+  /// </summary>
+  /// <param name="pbstrChip">The target process architecture of the
+  /// package.</param>
+  /// <returns>Standard HRESULT indicating success or failure.</returns>
+  STDMETHOD(GetChip)(_Out_ BSTR *pbstrChip) = 0;
+
+  /// <summary>
+  /// Gets the language and optional region identifier.
+  /// </summary>
+  /// <param name="pbstrLanguage">The language and optional region
+  /// identifier.</param>
+  /// <returns>Standard HRESULT indicating success or failure.</returns>
+  STDMETHOD(GetLanguage)(_Out_ BSTR *pbstrLanguage) = 0;
+
+  /// <summary>
+  /// Gets the build branch of the package.
+  /// </summary>
+  /// <param name="pbstrBranch">The build branch of the package.</param>
+  /// <returns>Standard HRESULT indicating success or failure.</returns>
+  STDMETHOD(GetBranch)(_Out_ BSTR *pbstrBranch) = 0;
+
+  /// <summary>
+  /// Gets the type of the package.
+  /// </summary>
+  /// <param name="pbstrType">The type of the package.</param>
+  /// <returns>Standard HRESULT indicating success or failure.</returns>
+  STDMETHOD(GetType)(_Out_ BSTR *pbstrType) = 0;
+
+  /// <summary>
+  /// Gets the unique identifier consisting of all defined tokens.
+  /// </summary>
+  /// <param name="pbstrUniqueId">The unique identifier consisting of all
+  /// defined tokens.</param>
+  /// <returns>Standard HRESULT indicating success or failure, including
+  /// E_UNEXPECTED if no Id was defined (required).</returns>
+  STDMETHOD(GetUniqueId)(_Out_ BSTR *pbstrUniqueId) = 0;
+};
+#endif
+
+EXTERN_C const IID IID_ISetupHelper;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+/// <summary>
+/// Helper functions.
+/// </summary>
+/// <remarks>
+/// You can query for this interface from the <see cref="SetupConfiguration"/>
+/// class.
+/// </remarks>
+struct DECLSPEC_UUID("42b21b78-6192-463e-87bf-d577838f1d5c")
+    DECLSPEC_NOVTABLE ISetupHelper : public IUnknown {
+  /// <summary>
+  /// Parses a dotted quad version string into a 64-bit unsigned integer.
+  /// </summary>
+  /// <param name="pwszVersion">The dotted quad version string to parse, e.g.
+  /// 1.2.3.4.</param>
+  /// <param name="pullVersion">A 64-bit unsigned integer representing the
+  /// version. You can compare this to other versions.</param>
+  /// <returns>Standard HRESULT indicating success or failure.</returns>
+  STDMETHOD(ParseVersion)
+  (_In_ LPCOLESTR pwszVersion, _Out_ PULONGLONG pullVersion) = 0;
+
+  /// <summary>
+  /// Parses a dotted quad version string into a 64-bit unsigned integer.
+  /// </summary>
+  /// <param name="pwszVersionRange">The string containing 1 or 2 dotted quad
+  /// version strings to parse, e.g. [1.0,) that means 1.0.0.0 or newer.</param>
+  /// <param name="pullMinVersion">A 64-bit unsigned integer representing the
+  /// minimum version, which may be 0. You can compare this to other
+  /// versions.</param>
+  /// <param name="pullMaxVersion">A 64-bit unsigned integer representing the
+  /// maximum version, which may be MAXULONGLONG. You can compare this to other
+  /// versions.</param>
+  /// <returns>Standard HRESULT indicating success or failure.</returns>
+  STDMETHOD(ParseVersionRange)
+  (_In_ LPCOLESTR pwszVersionRange, _Out_ PULONGLONG pullMinVersion,
+   _Out_ PULONGLONG pullMaxVersion) = 0;
+};
+#endif
+
+// Class declarations
+//
+EXTERN_C const CLSID CLSID_SetupConfiguration;
+
+#ifdef __cplusplus
+/// <summary>
+/// This class implements <see cref="ISetupConfiguration"/>, <see
+/// cref="ISetupConfiguration2"/>, and <see cref="ISetupHelper"/>.
+/// </summary>
+class DECLSPEC_UUID("177F0C4A-1CD3-4DE7-A32C-71DBBB9FA36D") SetupConfiguration;
+#endif
+
+// Function declarations
+//
+/// <summary>
+/// Gets an <see cref="ISetupConfiguration"/> that provides information about
+/// product instances installed on the machine.
+/// </summary>
+/// <param name="ppConfiguration">The <see cref="ISetupConfiguration"/> that
+/// provides information about product instances installed on the
+/// machine.</param>
+/// <param name="pReserved">Reserved for future use.</param>
+/// <returns>Standard HRESULT indicating success or failure.</returns>
+STDMETHODIMP GetSetupConfiguration(_Out_ ISetupConfiguration **ppConfiguration,
+                                   _Reserved_ LPVOID pReserved);
+
+#ifdef __cplusplus
+}
+#endif

Modified: cfe/trunk/test/Driver/cl-link-at-file.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/cl-link-at-file.c?rev=297851&r1=297850&r2=297851&view=diff
==============================================================================
--- cfe/trunk/test/Driver/cl-link-at-file.c (original)
+++ cfe/trunk/test/Driver/cl-link-at-file.c Wed Mar 15 11:07:35 2017
@@ -13,7 +13,6 @@
 // be clueless and will emit "argument unused" warnings. If PR17239 is properly
 // fixed, this should not happen because the "/link" option is restricted to
 // consume only remaining args in its response file.
-// ARGS-NOT: warning
 // ARGS-NOT: argument unused during compilation
 // Identify the linker command
 // ARGS: link.exe




More information about the cfe-commits mailing list