Coverage Report

Created: 2020-09-22 08:39

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Driver/ToolChains/MSVC.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- MSVC.cpp - MSVC ToolChain Implementations -------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "MSVC.h"
10
#include "CommonArgs.h"
11
#include "Darwin.h"
12
#include "clang/Basic/CharInfo.h"
13
#include "clang/Basic/Version.h"
14
#include "clang/Driver/Compilation.h"
15
#include "clang/Driver/Driver.h"
16
#include "clang/Driver/DriverDiagnostic.h"
17
#include "clang/Driver/Options.h"
18
#include "clang/Driver/SanitizerArgs.h"
19
#include "llvm/ADT/StringExtras.h"
20
#include "llvm/ADT/StringSwitch.h"
21
#include "llvm/Option/Arg.h"
22
#include "llvm/Option/ArgList.h"
23
#include "llvm/Support/ConvertUTF.h"
24
#include "llvm/Support/ErrorHandling.h"
25
#include "llvm/Support/FileSystem.h"
26
#include "llvm/Support/Host.h"
27
#include "llvm/Support/MemoryBuffer.h"
28
#include "llvm/Support/Path.h"
29
#include "llvm/Support/Process.h"
30
#include <cstdio>
31
32
#ifdef _WIN32
33
  #define WIN32_LEAN_AND_MEAN
34
  #define NOGDI
35
  #ifndef NOMINMAX
36
    #define NOMINMAX
37
  #endif
38
  #include <windows.h>
39
#endif
40
41
#ifdef _MSC_VER
42
// Don't support SetupApi on MinGW.
43
#define USE_MSVC_SETUP_API
44
45
// Make sure this comes before MSVCSetupApi.h
46
#include <comdef.h>
47
48
#include "MSVCSetupApi.h"
49
#include "llvm/Support/COM.h"
50
_COM_SMARTPTR_TYPEDEF(ISetupConfiguration, __uuidof(ISetupConfiguration));
51
_COM_SMARTPTR_TYPEDEF(ISetupConfiguration2, __uuidof(ISetupConfiguration2));
52
_COM_SMARTPTR_TYPEDEF(ISetupHelper, __uuidof(ISetupHelper));
53
_COM_SMARTPTR_TYPEDEF(IEnumSetupInstances, __uuidof(IEnumSetupInstances));
54
_COM_SMARTPTR_TYPEDEF(ISetupInstance, __uuidof(ISetupInstance));
55
_COM_SMARTPTR_TYPEDEF(ISetupInstance2, __uuidof(ISetupInstance2));
56
#endif
57
58
using namespace clang::driver;
59
using namespace clang::driver::toolchains;
60
using namespace clang::driver::tools;
61
using namespace clang;
62
using namespace llvm::opt;
63
64
// Defined below.
65
// Forward declare this so there aren't too many things above the constructor.
66
static bool getSystemRegistryString(const char *keyPath, const char *valueName,
67
                                    std::string &value, std::string *phValue);
68
69
// Check command line arguments to try and find a toolchain.
70
static bool
71
findVCToolChainViaCommandLine(const ArgList &Args, std::string &Path,
72
7.63k
                              MSVCToolChain::ToolsetLayout &VSLayout) {
73
  // Don't validate the input; trust the value supplied by the user.
74
  // The primary motivation is to prevent unnecessary file and registry access.
75
7.63k
  if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsdir)) {
76
2
    Path = A->getValue();
77
2
    VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
78
2
    return true;
79
2
  }
80
7.63k
  return false;
81
7.63k
}
82
83
// Check various environment variables to try and find a toolchain.
84
static bool findVCToolChainViaEnvironment(std::string &Path,
85
7.63k
                                          MSVCToolChain::ToolsetLayout &VSLayout) {
86
  // These variables are typically set by vcvarsall.bat
87
  // when launching a developer command prompt.
88
7.63k
  if (llvm::Optional<std::string> VCToolsInstallDir =
89
0
          llvm::sys::Process::GetEnv("VCToolsInstallDir")) {
90
    // This is only set by newer Visual Studios, and it leads straight to
91
    // the toolchain directory.
92
0
    Path = std::move(*VCToolsInstallDir);
93
0
    VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
94
0
    return true;
95
0
  }
96
7.63k
  if (llvm::Optional<std::string> VCInstallDir =
97
0
          llvm::sys::Process::GetEnv("VCINSTALLDIR")) {
98
    // If the previous variable isn't set but this one is, then we've found
99
    // an older Visual Studio. This variable is set by newer Visual Studios too,
100
    // so this check has to appear second.
101
    // In older Visual Studios, the VC directory is the toolchain.
102
0
    Path = std::move(*VCInstallDir);
103
0
    VSLayout = MSVCToolChain::ToolsetLayout::OlderVS;
104
0
    return true;
105
0
  }
106
107
  // We couldn't find any VC environment variables. Let's walk through PATH and
108
  // see if it leads us to a VC toolchain bin directory. If it does, pick the
109
  // first one that we find.
110
7.63k
  if (llvm::Optional<std::string> PathEnv =
111
7.63k
          llvm::sys::Process::GetEnv("PATH")) {
112
7.63k
    llvm::SmallVector<llvm::StringRef, 8> PathEntries;
113
7.63k
    llvm::StringRef(*PathEnv).split(PathEntries, llvm::sys::EnvPathSeparator);
114
61.7k
    for (llvm::StringRef PathEntry : PathEntries) {
115
61.7k
      if (PathEntry.empty())
116
0
        continue;
117
118
61.7k
      llvm::SmallString<256> ExeTestPath;
119
120
      // If cl.exe doesn't exist, then this definitely isn't a VC toolchain.
121
61.7k
      ExeTestPath = PathEntry;
122
61.7k
      llvm::sys::path::append(ExeTestPath, "cl.exe");
123
61.7k
      if (!llvm::sys::fs::exists(ExeTestPath))
124
61.7k
        continue;
125
126
      // cl.exe existing isn't a conclusive test for a VC toolchain; clang also
127
      // has a cl.exe. So let's check for link.exe too.
128
0
      ExeTestPath = PathEntry;
129
0
      llvm::sys::path::append(ExeTestPath, "link.exe");
130
0
      if (!llvm::sys::fs::exists(ExeTestPath))
131
0
        continue;
132
133
      // whatever/VC/bin --> old toolchain, VC dir is toolchain dir.
134
0
      llvm::StringRef TestPath = PathEntry;
135
0
      bool IsBin = llvm::sys::path::filename(TestPath).equals_lower("bin");
136
0
      if (!IsBin) {
137
        // Strip any architecture subdir like "amd64".
138
0
        TestPath = llvm::sys::path::parent_path(TestPath);
139
0
        IsBin = llvm::sys::path::filename(TestPath).equals_lower("bin");
140
0
      }
141
0
      if (IsBin) {
142
0
        llvm::StringRef ParentPath = llvm::sys::path::parent_path(TestPath);
143
0
        llvm::StringRef ParentFilename = llvm::sys::path::filename(ParentPath);
144
0
        if (ParentFilename == "VC") {
145
0
          Path = std::string(ParentPath);
146
0
          VSLayout = MSVCToolChain::ToolsetLayout::OlderVS;
147
0
          return true;
148
0
        }
149
0
        if (ParentFilename == "x86ret" || ParentFilename == "x86chk"
150
0
          || ParentFilename == "amd64ret" || ParentFilename == "amd64chk") {
151
0
          Path = std::string(ParentPath);
152
0
          VSLayout = MSVCToolChain::ToolsetLayout::DevDivInternal;
153
0
          return true;
154
0
        }
155
156
0
      } else {
157
        // This could be a new (>=VS2017) toolchain. If it is, we should find
158
        // path components with these prefixes when walking backwards through
159
        // the path.
160
        // Note: empty strings match anything.
161
0
        llvm::StringRef ExpectedPrefixes[] = {"",     "Host",  "bin", "",
162
0
                                              "MSVC", "Tools", "VC"};
163
164
0
        auto It = llvm::sys::path::rbegin(PathEntry);
165
0
        auto End = llvm::sys::path::rend(PathEntry);
166
0
        for (llvm::StringRef Prefix : ExpectedPrefixes) {
167
0
          if (It == End)
168
0
            goto NotAToolChain;
169
0
          if (!It->startswith(Prefix))
170
0
            goto NotAToolChain;
171
0
          ++It;
172
0
        }
173
174
        // We've found a new toolchain!
175
        // Back up 3 times (/bin/Host/arch) to get the root path.
176
0
        llvm::StringRef ToolChainPath(PathEntry);
177
0
        for (int i = 0; i < 3; ++i)
178
0
          ToolChainPath = llvm::sys::path::parent_path(ToolChainPath);
179
180
0
        Path = std::string(ToolChainPath);
181
0
        VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
182
0
        return true;
183
0
      }
184
185
0
    NotAToolChain:
186
0
      continue;
187
0
    }
188
7.63k
  }
189
7.63k
  return false;
190
7.63k
}
191
192
// Query the Setup Config server for installs, then pick the newest version
193
// and find its default VC toolchain.
194
// This is the preferred way to discover new Visual Studios, as they're no
195
// longer listed in the registry.
196
static bool findVCToolChainViaSetupConfig(std::string &Path,
197
7.63k
                                          MSVCToolChain::ToolsetLayout &VSLayout) {
198
7.63k
#if !defined(USE_MSVC_SETUP_API)
199
7.63k
  return false;
200
#else
201
  // FIXME: This really should be done once in the top-level program's main
202
  // function, as it may have already been initialized with a different
203
  // threading model otherwise.
204
  llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::SingleThreaded);
205
  HRESULT HR;
206
207
  // _com_ptr_t will throw a _com_error if a COM calls fail.
208
  // The LLVM coding standards forbid exception handling, so we'll have to
209
  // stop them from being thrown in the first place.
210
  // The destructor will put the regular error handler back when we leave
211
  // this scope.
212
  struct SuppressCOMErrorsRAII {
213
    static void __stdcall handler(HRESULT hr, IErrorInfo *perrinfo) {}
214
215
    SuppressCOMErrorsRAII() { _set_com_error_handler(handler); }
216
217
    ~SuppressCOMErrorsRAII() { _set_com_error_handler(_com_raise_error); }
218
219
  } COMErrorSuppressor;
220
221
  ISetupConfigurationPtr Query;
222
  HR = Query.CreateInstance(__uuidof(SetupConfiguration));
223
  if (FAILED(HR))
224
    return false;
225
226
  IEnumSetupInstancesPtr EnumInstances;
227
  HR = ISetupConfiguration2Ptr(Query)->EnumAllInstances(&EnumInstances);
228
  if (FAILED(HR))
229
    return false;
230
231
  ISetupInstancePtr Instance;
232
  HR = EnumInstances->Next(1, &Instance, nullptr);
233
  if (HR != S_OK)
234
    return false;
235
236
  ISetupInstancePtr NewestInstance;
237
  Optional<uint64_t> NewestVersionNum;
238
  do {
239
    bstr_t VersionString;
240
    uint64_t VersionNum;
241
    HR = Instance->GetInstallationVersion(VersionString.GetAddress());
242
    if (FAILED(HR))
243
      continue;
244
    HR = ISetupHelperPtr(Query)->ParseVersion(VersionString, &VersionNum);
245
    if (FAILED(HR))
246
      continue;
247
    if (!NewestVersionNum || (VersionNum > NewestVersionNum)) {
248
      NewestInstance = Instance;
249
      NewestVersionNum = VersionNum;
250
    }
251
  } while ((HR = EnumInstances->Next(1, &Instance, nullptr)) == S_OK);
252
253
  if (!NewestInstance)
254
    return false;
255
256
  bstr_t VCPathWide;
257
  HR = NewestInstance->ResolvePath(L"VC", VCPathWide.GetAddress());
258
  if (FAILED(HR))
259
    return false;
260
261
  std::string VCRootPath;
262
  llvm::convertWideToUTF8(std::wstring(VCPathWide), VCRootPath);
263
264
  llvm::SmallString<256> ToolsVersionFilePath(VCRootPath);
265
  llvm::sys::path::append(ToolsVersionFilePath, "Auxiliary", "Build",
266
                          "Microsoft.VCToolsVersion.default.txt");
267
268
  auto ToolsVersionFile = llvm::MemoryBuffer::getFile(ToolsVersionFilePath);
269
  if (!ToolsVersionFile)
270
    return false;
271
272
  llvm::SmallString<256> ToolchainPath(VCRootPath);
273
  llvm::sys::path::append(ToolchainPath, "Tools", "MSVC",
274
                          ToolsVersionFile->get()->getBuffer().rtrim());
275
  if (!llvm::sys::fs::is_directory(ToolchainPath))
276
    return false;
277
278
  Path = std::string(ToolchainPath.str());
279
  VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
280
  return true;
281
#endif
282
7.63k
}
283
284
// Look in the registry for Visual Studio installs, and use that to get
285
// a toolchain path. VS2017 and newer don't get added to the registry.
286
// So if we find something here, we know that it's an older version.
287
static bool findVCToolChainViaRegistry(std::string &Path,
288
7.63k
                                       MSVCToolChain::ToolsetLayout &VSLayout) {
289
7.63k
  std::string VSInstallPath;
290
7.63k
  if (getSystemRegistryString(R"(SOFTWARE\Microsoft\VisualStudio\$VERSION)",
291
7.63k
                              "InstallDir", VSInstallPath, nullptr) ||
292
7.63k
      getSystemRegistryString(R"(SOFTWARE\Microsoft\VCExpress\$VERSION)",
293
0
                              "InstallDir", VSInstallPath, nullptr)) {
294
0
    if (!VSInstallPath.empty()) {
295
0
      llvm::SmallString<256> VCPath(llvm::StringRef(
296
0
          VSInstallPath.c_str(), VSInstallPath.find(R"(\Common7\IDE)")));
297
0
      llvm::sys::path::append(VCPath, "VC");
298
299
0
      Path = std::string(VCPath.str());
300
0
      VSLayout = MSVCToolChain::ToolsetLayout::OlderVS;
301
0
      return true;
302
0
    }
303
7.63k
  }
304
7.63k
  return false;
305
7.63k
}
306
307
// Try to find Exe from a Visual Studio distribution.  This first tries to find
308
// an installed copy of Visual Studio and, failing that, looks in the PATH,
309
// making sure that whatever executable that's found is not a same-named exe
310
// from clang itself to prevent clang from falling back to itself.
311
static std::string FindVisualStudioExecutable(const ToolChain &TC,
312
377
                                              const char *Exe) {
313
377
  const auto &MSVC = static_cast<const toolchains::MSVCToolChain &>(TC);
314
377
  SmallString<128> FilePath(MSVC.getSubDirectoryPath(
315
377
      toolchains::MSVCToolChain::SubDirectoryType::Bin));
316
377
  llvm::sys::path::append(FilePath, Exe);
317
0
  return std::string(llvm::sys::fs::can_execute(FilePath) ? FilePath.str()
318
377
                                                          : Exe);
319
377
}
320
321
void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
322
                                        const InputInfo &Output,
323
                                        const InputInfoList &Inputs,
324
                                        const ArgList &Args,
325
365
                                        const char *LinkingOutput) const {
326
365
  ArgStringList CmdArgs;
327
328
365
  auto &TC = static_cast<const toolchains::MSVCToolChain &>(getToolChain());
329
330
365
  assert((Output.isFilename() || Output.isNothing()) && "invalid output");
331
365
  if (Output.isFilename())
332
365
    CmdArgs.push_back(
333
365
        Args.MakeArgString(std::string("-out:") + Output.getFilename()));
334
335
365
  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles) &&
336
363
      !C.getDriver().IsCLMode())
337
53
    CmdArgs.push_back("-defaultlib:libcmt");
338
339
365
  if (!llvm::sys::Process::GetEnv("LIB")) {
340
    // If the VC environment hasn't been configured (perhaps because the user
341
    // did not run vcvarsall), try to build a consistent link environment.  If
342
    // the environment variable is set however, assume the user knows what
343
    // they're doing.
344
363
    CmdArgs.push_back(Args.MakeArgString(
345
363
        Twine("-libpath:") +
346
363
        TC.getSubDirectoryPath(
347
363
            toolchains::MSVCToolChain::SubDirectoryType::Lib)));
348
349
363
    CmdArgs.push_back(Args.MakeArgString(
350
363
        Twine("-libpath:") +
351
363
        TC.getSubDirectoryPath(toolchains::MSVCToolChain::SubDirectoryType::Lib,
352
363
                               "atlmfc")));
353
354
363
    if (TC.useUniversalCRT()) {
355
363
      std::string UniversalCRTLibPath;
356
363
      if (TC.getUniversalCRTLibraryPath(UniversalCRTLibPath))
357
0
        CmdArgs.push_back(
358
0
            Args.MakeArgString(Twine("-libpath:") + UniversalCRTLibPath));
359
363
    }
360
361
363
    std::string WindowsSdkLibPath;
362
363
    if (TC.getWindowsSDKLibraryPath(WindowsSdkLibPath))
363
0
      CmdArgs.push_back(
364
0
          Args.MakeArgString(std::string("-libpath:") + WindowsSdkLibPath));
365
363
  }
366
367
  // Add the compiler-rt library directories to libpath if they exist to help
368
  // the linker find the various sanitizer, builtin, and profiling runtimes.
369
0
  for (const auto &LibPath : TC.getLibraryPaths()) {
370
0
    if (TC.getVFS().exists(LibPath))
371
0
      CmdArgs.push_back(Args.MakeArgString("-libpath:" + LibPath));
372
0
  }
373
365
  auto CRTPath = TC.getCompilerRTPath();
374
365
  if (TC.getVFS().exists(CRTPath))
375
0
    CmdArgs.push_back(Args.MakeArgString("-libpath:" + CRTPath));
376
377
365
  if (!C.getDriver().IsCLMode() && 
Args.hasArg(options::OPT_L)55
)
378
1
    for (const auto &LibPath : Args.getAllArgValues(options::OPT_L))
379
2
      CmdArgs.push_back(Args.MakeArgString("-libpath:" + LibPath));
380
381
365
  CmdArgs.push_back("-nologo");
382
383
365
  if (Args.hasArg(options::OPT_g_Group, options::OPT__SLASH_Z7,
384
365
                  options::OPT__SLASH_Zd))
385
6
    CmdArgs.push_back("-debug");
386
387
  // Pass on /Brepro if it was passed to the compiler.
388
  // Note that /Brepro maps to -mno-incremental-linker-compatible.
389
365
  bool DefaultIncrementalLinkerCompatible =
390
365
      C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment();
391
365
  if (!Args.hasFlag(options::OPT_mincremental_linker_compatible,
392
365
                    options::OPT_mno_incremental_linker_compatible,
393
365
                    DefaultIncrementalLinkerCompatible))
394
1
    CmdArgs.push_back("-Brepro");
395
396
365
  bool DLL = Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd,
397
365
                         options::OPT_shared);
398
365
  if (DLL) {
399
43
    CmdArgs.push_back(Args.MakeArgString("-dll"));
400
401
43
    SmallString<128> ImplibName(Output.getFilename());
402
43
    llvm::sys::path::replace_extension(ImplibName, "lib");
403
43
    CmdArgs.push_back(Args.MakeArgString(std::string("-implib:") + ImplibName));
404
43
  }
405
406
365
  if (TC.getSanitizerArgs().needsFuzzer()) {
407
0
    if (!Args.hasArg(options::OPT_shared))
408
0
      CmdArgs.push_back(
409
0
          Args.MakeArgString(std::string("-wholearchive:") +
410
0
                             TC.getCompilerRTArgString(Args, "fuzzer")));
411
0
    CmdArgs.push_back(Args.MakeArgString("-debug"));
412
    // Prevent the linker from padding sections we use for instrumentation
413
    // arrays.
414
0
    CmdArgs.push_back(Args.MakeArgString("-incremental:no"));
415
0
  }
416
417
365
  if (TC.getSanitizerArgs().needsAsanRt()) {
418
15
    CmdArgs.push_back(Args.MakeArgString("-debug"));
419
15
    CmdArgs.push_back(Args.MakeArgString("-incremental:no"));
420
15
    if (TC.getSanitizerArgs().needsSharedRt() ||
421
15
        Args.hasArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd)) {
422
1
      for (const auto &Lib : {"asan_dynamic", "asan_dynamic_runtime_thunk"})
423
2
        CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib));
424
      // Make sure the dynamic runtime thunk is not optimized out at link time
425
      // to ensure proper SEH handling.
426
1
      CmdArgs.push_back(Args.MakeArgString(
427
1
          TC.getArch() == llvm::Triple::x86
428
1
              ? "-include:___asan_seh_interceptor"
429
0
              : "-include:__asan_seh_interceptor"));
430
      // Make sure the linker consider all object files from the dynamic runtime
431
      // thunk.
432
1
      CmdArgs.push_back(Args.MakeArgString(std::string("-wholearchive:") +
433
1
          TC.getCompilerRT(Args, "asan_dynamic_runtime_thunk")));
434
14
    } else if (DLL) {
435
2
      CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dll_thunk"));
436
12
    } else {
437
24
      for (const auto &Lib : {"asan", "asan_cxx"}) {
438
24
        CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib));
439
        // Make sure the linker consider all object files from the static lib.
440
        // This is necessary because instrumented dlls need access to all the
441
        // interface exported by the static lib in the main executable.
442
24
        CmdArgs.push_back(Args.MakeArgString(std::string("-wholearchive:") +
443
24
            TC.getCompilerRT(Args, Lib)));
444
24
      }
445
12
    }
446
15
  }
447
448
365
  Args.AddAllArgValues(CmdArgs, options::OPT__SLASH_link);
449
450
  // Control Flow Guard checks
451
365
  if (Arg *A = Args.getLastArg(options::OPT__SLASH_guard)) {
452
6
    StringRef GuardArgs = A->getValue();
453
6
    if (GuardArgs.equals_lower("cf") || 
GuardArgs.equals_lower("cf,nochecks")5
) {
454
      // MSVC doesn't yet support the "nochecks" modifier.
455
2
      CmdArgs.push_back("-guard:cf");
456
4
    } else if (GuardArgs.equals_lower("cf-")) {
457
2
      CmdArgs.push_back("-guard:cf-");
458
2
    }
459
6
  }
460
461
365
  if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
462
8
                   options::OPT_fno_openmp, false)) {
463
8
    CmdArgs.push_back("-nodefaultlib:vcomp.lib");
464
8
    CmdArgs.push_back("-nodefaultlib:vcompd.lib");
465
8
    CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") +
466
8
                                         TC.getDriver().Dir + "/../lib"));
467
8
    switch (TC.getDriver().getOpenMPRuntime(Args)) {
468
3
    case Driver::OMPRT_OMP:
469
3
      CmdArgs.push_back("-defaultlib:libomp.lib");
470
3
      break;
471
3
    case Driver::OMPRT_IOMP5:
472
3
      CmdArgs.push_back("-defaultlib:libiomp5md.lib");
473
3
      break;
474
2
    case Driver::OMPRT_GOMP:
475
2
      break;
476
0
    case Driver::OMPRT_Unknown:
477
      // Already diagnosed.
478
0
      break;
479
365
    }
480
365
  }
481
482
  // Add compiler-rt lib in case if it was explicitly
483
  // specified as an argument for --rtlib option.
484
365
  if (!Args.hasArg(options::OPT_nostdlib)) {
485
363
    AddRunTimeLibs(TC, TC.getDriver(), CmdArgs, Args);
486
363
  }
487
488
  // Add filenames, libraries, and other linker inputs.
489
384
  for (const auto &Input : Inputs) {
490
384
    if (Input.isFilename()) {
491
379
      CmdArgs.push_back(Input.getFilename());
492
379
      continue;
493
379
    }
494
495
5
    const Arg &A = Input.getInputArg();
496
497
    // Render -l options differently for the MSVC linker.
498
5
    if (A.getOption().matches(options::OPT_l)) {
499
3
      StringRef Lib = A.getValue();
500
3
      const char *LinkLibArg;
501
3
      if (Lib.endswith(".lib"))
502
2
        LinkLibArg = Args.MakeArgString(Lib);
503
1
      else
504
1
        LinkLibArg = Args.MakeArgString(Lib + ".lib");
505
3
      CmdArgs.push_back(LinkLibArg);
506
3
      continue;
507
3
    }
508
509
    // Otherwise, this is some other kind of linker input option like -Wl, -z,
510
    // or -L. Render it, even if MSVC doesn't understand it.
511
2
    A.renderAsInput(Args, CmdArgs);
512
2
  }
513
514
365
  TC.addProfileRTLibs(Args, CmdArgs);
515
516
365
  std::vector<const char *> Environment;
517
518
  // We need to special case some linker paths.  In the case of lld, we need to
519
  // translate 'lld' into 'lld-link', and in the case of the regular msvc
520
  // linker, we need to use a special search algorithm.
521
365
  llvm::SmallString<128> linkPath;
522
365
  StringRef Linker = Args.getLastArgValue(options::OPT_fuse_ld_EQ, "link");
523
365
  if (Linker.equals_lower("lld"))
524
2
    Linker = "lld-link";
525
526
365
  if (Linker.equals_lower("link")) {
527
    // If we're using the MSVC linker, it's not sufficient to just use link
528
    // from the program PATH, because other environments like GnuWin32 install
529
    // their own link.exe which may come first.
530
362
    linkPath = FindVisualStudioExecutable(TC, "link.exe");
531
532
362
    if (!TC.FoundMSVCInstall() && 
!llvm::sys::fs::can_execute(linkPath)361
) {
533
361
      llvm::SmallString<128> ClPath;
534
361
      ClPath = TC.GetProgramPath("cl.exe");
535
361
      if (llvm::sys::fs::can_execute(ClPath)) {
536
5
        linkPath = llvm::sys::path::parent_path(ClPath);
537
5
        llvm::sys::path::append(linkPath, "link.exe");
538
5
        if (!llvm::sys::fs::can_execute(linkPath))
539
5
          C.getDriver().Diag(clang::diag::warn_drv_msvc_not_found);
540
356
      } else {
541
356
        C.getDriver().Diag(clang::diag::warn_drv_msvc_not_found);
542
356
      }
543
361
    }
544
545
#ifdef _WIN32
546
    // When cross-compiling with VS2017 or newer, link.exe expects to have
547
    // its containing bin directory at the top of PATH, followed by the
548
    // native target bin directory.
549
    // e.g. when compiling for x86 on an x64 host, PATH should start with:
550
    // /bin/Hostx64/x86;/bin/Hostx64/x64
551
    // This doesn't attempt to handle ToolsetLayout::DevDivInternal.
552
    if (TC.getIsVS2017OrNewer() &&
553
        llvm::Triple(llvm::sys::getProcessTriple()).getArch() != TC.getArch()) {
554
      auto HostArch = llvm::Triple(llvm::sys::getProcessTriple()).getArch();
555
556
      auto EnvBlockWide =
557
          std::unique_ptr<wchar_t[], decltype(&FreeEnvironmentStringsW)>(
558
              GetEnvironmentStringsW(), FreeEnvironmentStringsW);
559
      if (!EnvBlockWide)
560
        goto SkipSettingEnvironment;
561
562
      size_t EnvCount = 0;
563
      size_t EnvBlockLen = 0;
564
      while (EnvBlockWide[EnvBlockLen] != L'\0') {
565
        ++EnvCount;
566
        EnvBlockLen += std::wcslen(&EnvBlockWide[EnvBlockLen]) +
567
                       1 /*string null-terminator*/;
568
      }
569
      ++EnvBlockLen; // add the block null-terminator
570
571
      std::string EnvBlock;
572
      if (!llvm::convertUTF16ToUTF8String(
573
              llvm::ArrayRef<char>(reinterpret_cast<char *>(EnvBlockWide.get()),
574
                                   EnvBlockLen * sizeof(EnvBlockWide[0])),
575
              EnvBlock))
576
        goto SkipSettingEnvironment;
577
578
      Environment.reserve(EnvCount);
579
580
      // Now loop over each string in the block and copy them into the
581
      // environment vector, adjusting the PATH variable as needed when we
582
      // find it.
583
      for (const char *Cursor = EnvBlock.data(); *Cursor != '\0';) {
584
        llvm::StringRef EnvVar(Cursor);
585
        if (EnvVar.startswith_lower("path=")) {
586
          using SubDirectoryType = toolchains::MSVCToolChain::SubDirectoryType;
587
          constexpr size_t PrefixLen = 5; // strlen("path=")
588
          Environment.push_back(Args.MakeArgString(
589
              EnvVar.substr(0, PrefixLen) +
590
              TC.getSubDirectoryPath(SubDirectoryType::Bin) +
591
              llvm::Twine(llvm::sys::EnvPathSeparator) +
592
              TC.getSubDirectoryPath(SubDirectoryType::Bin, "", HostArch) +
593
              (EnvVar.size() > PrefixLen
594
                   ? llvm::Twine(llvm::sys::EnvPathSeparator) +
595
                         EnvVar.substr(PrefixLen)
596
                   : "")));
597
        } else {
598
          Environment.push_back(Args.MakeArgString(EnvVar));
599
        }
600
        Cursor += EnvVar.size() + 1 /*null-terminator*/;
601
      }
602
    }
603
  SkipSettingEnvironment:;
604
#endif
605
3
  } else {
606
3
    linkPath = TC.GetProgramPath(Linker.str().c_str());
607
3
  }
608
609
365
  auto LinkCmd =
610
365
      std::make_unique<Command>(JA, *this, ResponseFileSupport::AtFileUTF16(),
611
365
                                Args.MakeArgString(linkPath), CmdArgs, Inputs);
612
365
  if (!Environment.empty())
613
0
    LinkCmd->setEnvironment(Environment);
614
365
  C.addCommand(std::move(LinkCmd));
615
365
}
616
617
void visualstudio::Compiler::ConstructJob(Compilation &C, const JobAction &JA,
618
                                          const InputInfo &Output,
619
                                          const InputInfoList &Inputs,
620
                                          const ArgList &Args,
621
0
                                          const char *LinkingOutput) const {
622
0
  C.addCommand(GetCommand(C, JA, Output, Inputs, Args, LinkingOutput));
623
0
}
624
625
std::unique_ptr<Command> visualstudio::Compiler::GetCommand(
626
    Compilation &C, const JobAction &JA, const InputInfo &Output,
627
    const InputInfoList &Inputs, const ArgList &Args,
628
15
    const char *LinkingOutput) const {
629
15
  ArgStringList CmdArgs;
630
15
  CmdArgs.push_back("/nologo");
631
15
  CmdArgs.push_back("/c");  // Compile only.
632
15
  CmdArgs.push_back("/W0"); // No warnings.
633
634
  // The goal is to be able to invoke this tool correctly based on
635
  // any flag accepted by clang-cl.
636
637
  // These are spelled the same way in clang and cl.exe,.
638
15
  Args.AddAllArgs(CmdArgs, {options::OPT_D, options::OPT_U, options::OPT_I});
639
640
  // Optimization level.
641
15
  if (Arg *A = Args.getLastArg(options::OPT_fbuiltin, options::OPT_fno_builtin))
642
3
    CmdArgs.push_back(A->getOption().getID() == options::OPT_fbuiltin ? "/Oi"
643
0
                                                                      : "/Oi-");
644
15
  if (Arg *A = Args.getLastArg(options::OPT_O, options::OPT_O0)) {
645
6
    if (A->getOption().getID() == options::OPT_O0) {
646
1
      CmdArgs.push_back("/Od");
647
5
    } else {
648
5
      CmdArgs.push_back("/Og");
649
650
5
      StringRef OptLevel = A->getValue();
651
5
      if (OptLevel == "s" || 
OptLevel == "z"3
)
652
2
        CmdArgs.push_back("/Os");
653
3
      else
654
3
        CmdArgs.push_back("/Ot");
655
656
5
      CmdArgs.push_back("/Ob2");
657
5
    }
658
6
  }
659
15
  if (Arg *A = Args.getLastArg(options::OPT_fomit_frame_pointer,
660
4
                               options::OPT_fno_omit_frame_pointer))
661
4
    CmdArgs.push_back(A->getOption().getID() == options::OPT_fomit_frame_pointer
662
4
                          ? "/Oy"
663
0
                          : "/Oy-");
664
15
  if (!Args.hasArg(options::OPT_fwritable_strings))
665
15
    CmdArgs.push_back("/GF");
666
667
  // Flags for which clang-cl has an alias.
668
  // FIXME: How can we ensure this stays in sync with relevant clang-cl options?
669
670
15
  if (Args.hasFlag(options::OPT__SLASH_GR_, options::OPT__SLASH_GR,
671
15
                   /*Default=*/false))
672
3
    CmdArgs.push_back("/GR-");
673
674
15
  if (Args.hasFlag(options::OPT__SLASH_GS_, options::OPT__SLASH_GS,
675
15
                   /*Default=*/false))
676
2
    CmdArgs.push_back("/GS-");
677
678
15
  if (Arg *A = Args.getLastArg(options::OPT_ffunction_sections,
679
3
                               options::OPT_fno_function_sections))
680
3
    CmdArgs.push_back(A->getOption().getID() == options::OPT_ffunction_sections
681
2
                          ? "/Gy"
682
1
                          : "/Gy-");
683
15
  if (Arg *A = Args.getLastArg(options::OPT_fdata_sections,
684
1
                               options::OPT_fno_data_sections))
685
1
    CmdArgs.push_back(
686
1
        A->getOption().getID() == options::OPT_fdata_sections ? 
"/Gw"0
: "/Gw-");
687
15
  if (Args.hasArg(options::OPT_fsyntax_only))
688
0
    CmdArgs.push_back("/Zs");
689
15
  if (Args.hasArg(options::OPT_g_Flag, options::OPT_gline_tables_only,
690
15
                  options::OPT__SLASH_Z7))
691
1
    CmdArgs.push_back("/Z7");
692
693
15
  std::vector<std::string> Includes =
694
15
      Args.getAllArgValues(options::OPT_include);
695
15
  for (const auto &Include : Includes)
696
3
    CmdArgs.push_back(Args.MakeArgString(std::string("/FI") + Include));
697
698
  // Flags that can simply be passed through.
699
15
  Args.AddAllArgs(CmdArgs, options::OPT__SLASH_LD);
700
15
  Args.AddAllArgs(CmdArgs, options::OPT__SLASH_LDd);
701
15
  Args.AddAllArgs(CmdArgs, options::OPT__SLASH_GX);
702
15
  Args.AddAllArgs(CmdArgs, options::OPT__SLASH_GX_);
703
15
  Args.AddAllArgs(CmdArgs, options::OPT__SLASH_EH);
704
15
  Args.AddAllArgs(CmdArgs, options::OPT__SLASH_Zl);
705
706
  // The order of these flags is relevant, so pick the last one.
707
15
  if (Arg *A = Args.getLastArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd,
708
1
                               options::OPT__SLASH_MT, options::OPT__SLASH_MTd))
709
1
    A->render(Args, CmdArgs);
710
711
  // Use MSVC's default threadsafe statics behaviour unless there was a flag.
712
15
  if (Arg *A = Args.getLastArg(options::OPT_fthreadsafe_statics,
713
2
                               options::OPT_fno_threadsafe_statics)) {
714
2
    CmdArgs.push_back(A->getOption().getID() == options::OPT_fthreadsafe_statics
715
1
                          ? "/Zc:threadSafeInit"
716
1
                          : "/Zc:threadSafeInit-");
717
2
  }
718
719
  // Control Flow Guard checks
720
15
  if (Arg *A = Args.getLastArg(options::OPT__SLASH_guard)) {
721
1
    StringRef GuardArgs = A->getValue();
722
1
    if (GuardArgs.equals_lower("cf") || GuardArgs.equals_lower("cf,nochecks")) {
723
      // MSVC doesn't yet support the "nochecks" modifier.
724
0
      CmdArgs.push_back("/guard:cf");
725
1
    } else if (GuardArgs.equals_lower("cf-")) {
726
1
      CmdArgs.push_back("/guard:cf-");
727
1
    }
728
1
  }
729
730
  // Pass through all unknown arguments so that the fallback command can see
731
  // them too.
732
15
  Args.AddAllArgs(CmdArgs, options::OPT_UNKNOWN);
733
734
  // Input filename.
735
15
  assert(Inputs.size() == 1);
736
15
  const InputInfo &II = Inputs[0];
737
15
  assert(II.getType() == types::TY_C || II.getType() == types::TY_CXX);
738
13
  CmdArgs.push_back(II.getType() == types::TY_C ? "/Tc" : 
"/Tp"2
);
739
15
  if (II.isFilename())
740
15
    CmdArgs.push_back(II.getFilename());
741
0
  else
742
0
    II.getInputArg().renderAsInput(Args, CmdArgs);
743
744
  // Output filename.
745
15
  assert(Output.getType() == types::TY_Object);
746
15
  const char *Fo =
747
15
      Args.MakeArgString(std::string("/Fo") + Output.getFilename());
748
15
  CmdArgs.push_back(Fo);
749
750
15
  std::string Exec = FindVisualStudioExecutable(getToolChain(), "cl.exe");
751
15
  return std::make_unique<Command>(JA, *this,
752
15
                                   ResponseFileSupport::AtFileUTF16(),
753
15
                                   Args.MakeArgString(Exec), CmdArgs, Inputs);
754
15
}
755
756
MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple &Triple,
757
                             const ArgList &Args)
758
    : ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args),
759
7.63k
      RocmInstallation(D, Triple, Args) {
760
7.63k
  getProgramPaths().push_back(getDriver().getInstalledDir());
761
7.63k
  if (getDriver().getInstalledDir() != getDriver().Dir)
762
5
    getProgramPaths().push_back(getDriver().Dir);
763
764
  // Check the command line first, that's the user explicitly telling us what to
765
  // use. Check the environment next, in case we're being invoked from a VS
766
  // command prompt. Failing that, just try to find the newest Visual Studio
767
  // version we can and use its default VC toolchain.
768
7.63k
  findVCToolChainViaCommandLine(Args, VCToolChainPath, VSLayout) ||
769
7.63k
      findVCToolChainViaEnvironment(VCToolChainPath, VSLayout) ||
770
7.63k
      findVCToolChainViaSetupConfig(VCToolChainPath, VSLayout) ||
771
7.63k
      findVCToolChainViaRegistry(VCToolChainPath, VSLayout);
772
7.63k
}
773
774
365
Tool *MSVCToolChain::buildLinker() const {
775
365
  return new tools::visualstudio::Linker(*this);
776
365
}
777
778
3
Tool *MSVCToolChain::buildAssembler() const {
779
3
  if (getTriple().isOSBinFormatMachO())
780
2
    return new tools::darwin::Assembler(*this);
781
1
  getDriver().Diag(clang::diag::err_no_external_assembler);
782
1
  return nullptr;
783
1
}
784
785
46.1k
bool MSVCToolChain::IsIntegratedAssemblerDefault() const {
786
46.1k
  return true;
787
46.1k
}
788
789
7.65k
bool MSVCToolChain::IsUnwindTablesDefault(const ArgList &Args) const {
790
  // Don't emit unwind tables by default for MachO targets.
791
7.65k
  if (getTriple().isOSBinFormatMachO())
792
6
    return false;
793
794
  // All non-x86_32 Windows targets require unwind tables. However, LLVM
795
  // doesn't know how to generate them for all targets, so only enable
796
  // the ones that are actually implemented.
797
7.64k
  return getArch() == llvm::Triple::x86_64 ||
798
134
         getArch() == llvm::Triple::aarch64;
799
7.64k
}
800
801
7.66k
bool MSVCToolChain::isPICDefault() const {
802
7.66k
  return getArch() == llvm::Triple::x86_64;
803
7.66k
}
804
805
7.66k
bool MSVCToolChain::isPIEDefault() const {
806
7.66k
  return false;
807
7.66k
}
808
809
7.66k
bool MSVCToolChain::isPICDefaultForced() const {
810
7.66k
  return getArch() == llvm::Triple::x86_64;
811
7.66k
}
812
813
void MSVCToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs,
814
7
                                       ArgStringList &CC1Args) const {
815
7
  CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args);
816
7
}
817
818
void MSVCToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs,
819
5
                                      ArgStringList &CC1Args) const {
820
5
  RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args);
821
5
}
822
823
2
void MSVCToolChain::printVerboseInfo(raw_ostream &OS) const {
824
2
  CudaInstallation.print(OS);
825
2
  RocmInstallation.print(OS);
826
2
}
827
828
// Windows SDKs and VC Toolchains group their contents into subdirectories based
829
// on the target architecture. This function converts an llvm::Triple::ArchType
830
// to the corresponding subdirectory name.
831
17
static const char *llvmArchToWindowsSDKArch(llvm::Triple::ArchType Arch) {
832
17
  using ArchType = llvm::Triple::ArchType;
833
17
  switch (Arch) {
834
0
  case ArchType::x86:
835
0
    return "x86";
836
17
  case ArchType::x86_64:
837
17
    return "x64";
838
0
  case ArchType::arm:
839
0
    return "arm";
840
0
  case ArchType::aarch64:
841
0
    return "arm64";
842
0
  default:
843
0
    return "";
844
17
  }
845
17
}
846
847
// Similar to the above function, but for Visual Studios before VS2017.
848
17.0k
static const char *llvmArchToLegacyVCArch(llvm::Triple::ArchType Arch) {
849
17.0k
  using ArchType = llvm::Triple::ArchType;
850
17.0k
  switch (Arch) {
851
477
  case ArchType::x86:
852
    // x86 is default in legacy VC toolchains.
853
    // e.g. x86 libs are directly in /lib as opposed to /lib/x86.
854
477
    return "";
855
16.5k
  case ArchType::x86_64:
856
16.5k
    return "amd64";
857
51
  case ArchType::arm:
858
51
    return "arm";
859
22
  case ArchType::aarch64:
860
22
    return "arm64";
861
21
  default:
862
21
    return "";
863
17.0k
  }
864
17.0k
}
865
866
// Similar to the above function, but for DevDiv internal builds.
867
0
static const char *llvmArchToDevDivInternalArch(llvm::Triple::ArchType Arch) {
868
0
  using ArchType = llvm::Triple::ArchType;
869
0
  switch (Arch) {
870
0
  case ArchType::x86:
871
0
    return "i386";
872
0
  case ArchType::x86_64:
873
0
    return "amd64";
874
0
  case ArchType::arm:
875
0
    return "arm";
876
0
  case ArchType::aarch64:
877
0
    return "arm64";
878
0
  default:
879
0
    return "";
880
0
  }
881
0
}
882
883
// Get the path to a specific subdirectory in the current toolchain for
884
// a given target architecture.
885
// VS2017 changed the VC toolchain layout, so this should be used instead
886
// of hardcoding paths.
887
std::string
888
MSVCToolChain::getSubDirectoryPath(SubDirectoryType Type,
889
                                   llvm::StringRef SubdirParent,
890
17.1k
                                   llvm::Triple::ArchType TargetArch) const {
891
17.1k
  const char *SubdirName;
892
17.1k
  const char *IncludeName;
893
17.1k
  switch (VSLayout) {
894
17.0k
  case ToolsetLayout::OlderVS:
895
17.0k
    SubdirName = llvmArchToLegacyVCArch(TargetArch);
896
17.0k
    IncludeName = "include";
897
17.0k
    break;
898
17
  case ToolsetLayout::VS2017OrNewer:
899
17
    SubdirName = llvmArchToWindowsSDKArch(TargetArch);
900
17
    IncludeName = "include";
901
17
    break;
902
0
  case ToolsetLayout::DevDivInternal:
903
0
    SubdirName = llvmArchToDevDivInternalArch(TargetArch);
904
0
    IncludeName = "inc";
905
0
    break;
906
17.1k
  }
907
908
17.1k
  llvm::SmallString<256> Path(VCToolChainPath);
909
17.1k
  if (!SubdirParent.empty())
910
364
    llvm::sys::path::append(Path, SubdirParent);
911
912
17.1k
  switch (Type) {
913
16.0k
  case SubDirectoryType::Bin:
914
16.0k
    if (VSLayout == ToolsetLayout::VS2017OrNewer) {
915
8
      const bool HostIsX64 =
916
8
          llvm::Triple(llvm::sys::getProcessTriple()).isArch64Bit();
917
8
      const char *const HostName = HostIsX64 ? "Hostx64" : 
"Hostx86"0
;
918
8
      llvm::sys::path::append(Path, "bin", HostName, SubdirName);
919
16.0k
    } else { // OlderVS or DevDivInternal
920
16.0k
      llvm::sys::path::append(Path, "bin", SubdirName);
921
16.0k
    }
922
16.0k
    break;
923
366
  case SubDirectoryType::Include:
924
366
    llvm::sys::path::append(Path, IncludeName);
925
366
    break;
926
726
  case SubDirectoryType::Lib:
927
726
    llvm::sys::path::append(Path, "lib", SubdirName);
928
726
    break;
929
17.1k
  }
930
17.1k
  return std::string(Path.str());
931
17.1k
}
932
933
#ifdef _WIN32
934
static bool readFullStringValue(HKEY hkey, const char *valueName,
935
                                std::string &value) {
936
  std::wstring WideValueName;
937
  if (!llvm::ConvertUTF8toWide(valueName, WideValueName))
938
    return false;
939
940
  DWORD result = 0;
941
  DWORD valueSize = 0;
942
  DWORD type = 0;
943
  // First just query for the required size.
944
  result = RegQueryValueExW(hkey, WideValueName.c_str(), NULL, &type, NULL,
945
                            &valueSize);
946
  if (result != ERROR_SUCCESS || type != REG_SZ || !valueSize)
947
    return false;
948
  std::vector<BYTE> buffer(valueSize);
949
  result = RegQueryValueExW(hkey, WideValueName.c_str(), NULL, NULL, &buffer[0],
950
                            &valueSize);
951
  if (result == ERROR_SUCCESS) {
952
    std::wstring WideValue(reinterpret_cast<const wchar_t *>(buffer.data()),
953
                           valueSize / sizeof(wchar_t));
954
    if (valueSize && WideValue.back() == L'\0') {
955
      WideValue.pop_back();
956
    }
957
    // The destination buffer must be empty as an invariant of the conversion
958
    // function; but this function is sometimes called in a loop that passes in
959
    // the same buffer, however. Simply clear it out so we can overwrite it.
960
    value.clear();
961
    return llvm::convertWideToUTF8(WideValue, value);
962
  }
963
  return false;
964
}
965
#endif
966
967
/// Read registry string.
968
/// This also supports a means to look for high-versioned keys by use
969
/// of a $VERSION placeholder in the key path.
970
/// $VERSION in the key path is a placeholder for the version number,
971
/// causing the highest value path to be searched for and used.
972
/// I.e. "SOFTWARE\\Microsoft\\VisualStudio\\$VERSION".
973
/// There can be additional characters in the component.  Only the numeric
974
/// characters are compared.  This function only searches HKLM.
975
static bool getSystemRegistryString(const char *keyPath, const char *valueName,
976
16.0k
                                    std::string &value, std::string *phValue) {
977
16.0k
#ifndef _WIN32
978
16.0k
  return false;
979
#else
980
  HKEY hRootKey = HKEY_LOCAL_MACHINE;
981
  HKEY hKey = NULL;
982
  long lResult;
983
  bool returnValue = false;
984
985
  const char *placeHolder = strstr(keyPath, "$VERSION");
986
  std::string bestName;
987
  // If we have a $VERSION placeholder, do the highest-version search.
988
  if (placeHolder) {
989
    const char *keyEnd = placeHolder - 1;
990
    const char *nextKey = placeHolder;
991
    // Find end of previous key.
992
    while ((keyEnd > keyPath) && (*keyEnd != '\\'))
993
      keyEnd--;
994
    // Find end of key containing $VERSION.
995
    while (*nextKey && (*nextKey != '\\'))
996
      nextKey++;
997
    size_t partialKeyLength = keyEnd - keyPath;
998
    char partialKey[256];
999
    if (partialKeyLength >= sizeof(partialKey))
1000
      partialKeyLength = sizeof(partialKey) - 1;
1001
    strncpy(partialKey, keyPath, partialKeyLength);
1002
    partialKey[partialKeyLength] = '\0';
1003
    HKEY hTopKey = NULL;
1004
    lResult = RegOpenKeyExA(hRootKey, partialKey, 0, KEY_READ | KEY_WOW64_32KEY,
1005
                            &hTopKey);
1006
    if (lResult == ERROR_SUCCESS) {
1007
      char keyName[256];
1008
      double bestValue = 0.0;
1009
      DWORD index, size = sizeof(keyName) - 1;
1010
      for (index = 0; RegEnumKeyExA(hTopKey, index, keyName, &size, NULL, NULL,
1011
                                    NULL, NULL) == ERROR_SUCCESS;
1012
           index++) {
1013
        const char *sp = keyName;
1014
        while (*sp && !isDigit(*sp))
1015
          sp++;
1016
        if (!*sp)
1017
          continue;
1018
        const char *ep = sp + 1;
1019
        while (*ep && (isDigit(*ep) || (*ep == '.')))
1020
          ep++;
1021
        char numBuf[32];
1022
        strncpy(numBuf, sp, sizeof(numBuf) - 1);
1023
        numBuf[sizeof(numBuf) - 1] = '\0';
1024
        double dvalue = strtod(numBuf, NULL);
1025
        if (dvalue > bestValue) {
1026
          // Test that InstallDir is indeed there before keeping this index.
1027
          // Open the chosen key path remainder.
1028
          bestName = keyName;
1029
          // Append rest of key.
1030
          bestName.append(nextKey);
1031
          lResult = RegOpenKeyExA(hTopKey, bestName.c_str(), 0,
1032
                                  KEY_READ | KEY_WOW64_32KEY, &hKey);
1033
          if (lResult == ERROR_SUCCESS) {
1034
            if (readFullStringValue(hKey, valueName, value)) {
1035
              bestValue = dvalue;
1036
              if (phValue)
1037
                *phValue = bestName;
1038
              returnValue = true;
1039
            }
1040
            RegCloseKey(hKey);
1041
          }
1042
        }
1043
        size = sizeof(keyName) - 1;
1044
      }
1045
      RegCloseKey(hTopKey);
1046
    }
1047
  } else {
1048
    lResult =
1049
        RegOpenKeyExA(hRootKey, keyPath, 0, KEY_READ | KEY_WOW64_32KEY, &hKey);
1050
    if (lResult == ERROR_SUCCESS) {
1051
      if (readFullStringValue(hKey, valueName, value))
1052
        returnValue = true;
1053
      if (phValue)
1054
        phValue->clear();
1055
      RegCloseKey(hKey);
1056
    }
1057
  }
1058
  return returnValue;
1059
#endif // _WIN32
1060
16.0k
}
1061
1062
// Find the most recent version of Universal CRT or Windows 10 SDK.
1063
// vcvarsqueryregistry.bat from Visual Studio 2015 sorts entries in the include
1064
// directory by name and uses the last one of the list.
1065
// So we compare entry names lexicographically to find the greatest one.
1066
static bool getWindows10SDKVersionFromPath(const std::string &SDKPath,
1067
0
                                           std::string &SDKVersion) {
1068
0
  SDKVersion.clear();
1069
1070
0
  std::error_code EC;
1071
0
  llvm::SmallString<128> IncludePath(SDKPath);
1072
0
  llvm::sys::path::append(IncludePath, "Include");
1073
0
  for (llvm::sys::fs::directory_iterator DirIt(IncludePath, EC), DirEnd;
1074
0
       DirIt != DirEnd && !EC; DirIt.increment(EC)) {
1075
0
    if (!llvm::sys::fs::is_directory(DirIt->path()))
1076
0
      continue;
1077
0
    StringRef CandidateName = llvm::sys::path::filename(DirIt->path());
1078
    // If WDK is installed, there could be subfolders like "wdf" in the
1079
    // "Include" directory.
1080
    // Allow only directories which names start with "10.".
1081
0
    if (!CandidateName.startswith("10."))
1082
0
      continue;
1083
0
    if (CandidateName > SDKVersion)
1084
0
      SDKVersion = std::string(CandidateName);
1085
0
  }
1086
1087
0
  return !SDKVersion.empty();
1088
0
}
1089
1090
/// Get Windows SDK installation directory.
1091
static bool getWindowsSDKDir(std::string &Path, int &Major,
1092
                             std::string &WindowsSDKIncludeVersion,
1093
364
                             std::string &WindowsSDKLibVersion) {
1094
364
  std::string RegistrySDKVersion;
1095
  // Try the Windows registry.
1096
364
  if (!getSystemRegistryString(
1097
364
          "SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
1098
364
          "InstallationFolder", Path, &RegistrySDKVersion))
1099
364
    return false;
1100
0
  if (Path.empty() || RegistrySDKVersion.empty())
1101
0
    return false;
1102
1103
0
  WindowsSDKIncludeVersion.clear();
1104
0
  WindowsSDKLibVersion.clear();
1105
0
  Major = 0;
1106
0
  std::sscanf(RegistrySDKVersion.c_str(), "v%d.", &Major);
1107
0
  if (Major <= 7)
1108
0
    return true;
1109
0
  if (Major == 8) {
1110
    // Windows SDK 8.x installs libraries in a folder whose names depend on the
1111
    // version of the OS you're targeting.  By default choose the newest, which
1112
    // usually corresponds to the version of the OS you've installed the SDK on.
1113
0
    const char *Tests[] = {"winv6.3", "win8", "win7"};
1114
0
    for (const char *Test : Tests) {
1115
0
      llvm::SmallString<128> TestPath(Path);
1116
0
      llvm::sys::path::append(TestPath, "Lib", Test);
1117
0
      if (llvm::sys::fs::exists(TestPath.c_str())) {
1118
0
        WindowsSDKLibVersion = Test;
1119
0
        break;
1120
0
      }
1121
0
    }
1122
0
    return !WindowsSDKLibVersion.empty();
1123
0
  }
1124
0
  if (Major == 10) {
1125
0
    if (!getWindows10SDKVersionFromPath(Path, WindowsSDKIncludeVersion))
1126
0
      return false;
1127
0
    WindowsSDKLibVersion = WindowsSDKIncludeVersion;
1128
0
    return true;
1129
0
  }
1130
  // Unsupported SDK version
1131
0
  return false;
1132
0
}
1133
1134
// Gets the library path required to link against the Windows SDK.
1135
363
bool MSVCToolChain::getWindowsSDKLibraryPath(std::string &path) const {
1136
363
  std::string sdkPath;
1137
363
  int sdkMajor = 0;
1138
363
  std::string windowsSDKIncludeVersion;
1139
363
  std::string windowsSDKLibVersion;
1140
1141
363
  path.clear();
1142
363
  if (!getWindowsSDKDir(sdkPath, sdkMajor, windowsSDKIncludeVersion,
1143
363
                        windowsSDKLibVersion))
1144
363
    return false;
1145
1146
0
  llvm::SmallString<128> libPath(sdkPath);
1147
0
  llvm::sys::path::append(libPath, "Lib");
1148
0
  if (sdkMajor >= 8) {
1149
0
    llvm::sys::path::append(libPath, windowsSDKLibVersion, "um",
1150
0
                            llvmArchToWindowsSDKArch(getArch()));
1151
0
  } else {
1152
0
    switch (getArch()) {
1153
    // In Windows SDK 7.x, x86 libraries are directly in the Lib folder.
1154
0
    case llvm::Triple::x86:
1155
0
      break;
1156
0
    case llvm::Triple::x86_64:
1157
0
      llvm::sys::path::append(libPath, "x64");
1158
0
      break;
1159
0
    case llvm::Triple::arm:
1160
      // It is not necessary to link against Windows SDK 7.x when targeting ARM.
1161
0
      return false;
1162
0
    default:
1163
0
      return false;
1164
0
    }
1165
0
  }
1166
1167
0
  path = std::string(libPath.str());
1168
0
  return true;
1169
0
}
1170
1171
// Check if the Include path of a specified version of Visual Studio contains
1172
// specific header files. If not, they are probably shipped with Universal CRT.
1173
364
bool MSVCToolChain::useUniversalCRT() const {
1174
364
  llvm::SmallString<128> TestPath(
1175
364
      getSubDirectoryPath(SubDirectoryType::Include));
1176
364
  llvm::sys::path::append(TestPath, "stdlib.h");
1177
364
  return !llvm::sys::fs::exists(TestPath);
1178
364
}
1179
1180
364
static bool getUniversalCRTSdkDir(std::string &Path, std::string &UCRTVersion) {
1181
  // vcvarsqueryregistry.bat for Visual Studio 2015 queries the registry
1182
  // for the specific key "KitsRoot10". So do we.
1183
364
  if (!getSystemRegistryString(
1184
364
          "SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots", "KitsRoot10",
1185
364
          Path, nullptr))
1186
364
    return false;
1187
1188
0
  return getWindows10SDKVersionFromPath(Path, UCRTVersion);
1189
0
}
1190
1191
363
bool MSVCToolChain::getUniversalCRTLibraryPath(std::string &Path) const {
1192
363
  std::string UniversalCRTSdkPath;
1193
363
  std::string UCRTVersion;
1194
1195
363
  Path.clear();
1196
363
  if (!getUniversalCRTSdkDir(UniversalCRTSdkPath, UCRTVersion))
1197
363
    return false;
1198
1199
0
  StringRef ArchName = llvmArchToWindowsSDKArch(getArch());
1200
0
  if (ArchName.empty())
1201
0
    return false;
1202
1203
0
  llvm::SmallString<128> LibPath(UniversalCRTSdkPath);
1204
0
  llvm::sys::path::append(LibPath, "Lib", UCRTVersion, "ucrt", ArchName);
1205
1206
0
  Path = std::string(LibPath.str());
1207
0
  return true;
1208
0
}
1209
1210
15.6k
static VersionTuple getMSVCVersionFromTriple(const llvm::Triple &Triple) {
1211
15.6k
  unsigned Major, Minor, Micro;
1212
15.6k
  Triple.getEnvironmentVersion(Major, Minor, Micro);
1213
15.6k
  if (Major || 
Minor15.6k
||
Micro15.6k
)
1214
4
    return VersionTuple(Major, Minor, Micro);
1215
15.6k
  return VersionTuple();
1216
15.6k
}
1217
1218
15.6k
static VersionTuple getMSVCVersionFromExe(const std::string &BinDir) {
1219
15.6k
  VersionTuple Version;
1220
#ifdef _WIN32
1221
  SmallString<128> ClExe(BinDir);
1222
  llvm::sys::path::append(ClExe, "cl.exe");
1223
1224
  std::wstring ClExeWide;
1225
  if (!llvm::ConvertUTF8toWide(ClExe.c_str(), ClExeWide))
1226
    return Version;
1227
1228
  const DWORD VersionSize = ::GetFileVersionInfoSizeW(ClExeWide.c_str(),
1229
                                                      nullptr);
1230
  if (VersionSize == 0)
1231
    return Version;
1232
1233
  SmallVector<uint8_t, 4 * 1024> VersionBlock(VersionSize);
1234
  if (!::GetFileVersionInfoW(ClExeWide.c_str(), 0, VersionSize,
1235
                             VersionBlock.data()))
1236
    return Version;
1237
1238
  VS_FIXEDFILEINFO *FileInfo = nullptr;
1239
  UINT FileInfoSize = 0;
1240
  if (!::VerQueryValueW(VersionBlock.data(), L"\\",
1241
                        reinterpret_cast<LPVOID *>(&FileInfo), &FileInfoSize) ||
1242
      FileInfoSize < sizeof(*FileInfo))
1243
    return Version;
1244
1245
  const unsigned Major = (FileInfo->dwFileVersionMS >> 16) & 0xFFFF;
1246
  const unsigned Minor = (FileInfo->dwFileVersionMS      ) & 0xFFFF;
1247
  const unsigned Micro = (FileInfo->dwFileVersionLS >> 16) & 0xFFFF;
1248
1249
  Version = VersionTuple(Major, Minor, Micro);
1250
#endif
1251
15.6k
  return Version;
1252
15.6k
}
1253
1254
void MSVCToolChain::AddSystemIncludeWithSubfolder(
1255
    const ArgList &DriverArgs, ArgStringList &CC1Args,
1256
    const std::string &folder, const Twine &subfolder1, const Twine &subfolder2,
1257
7.68k
    const Twine &subfolder3) const {
1258
7.68k
  llvm::SmallString<128> path(folder);
1259
7.68k
  llvm::sys::path::append(path, subfolder1, subfolder2, subfolder3);
1260
7.68k
  addSystemInclude(DriverArgs, CC1Args, path);
1261
7.68k
}
1262
1263
void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
1264
7.68k
                                              ArgStringList &CC1Args) const {
1265
7.68k
  if (DriverArgs.hasArg(options::OPT_nostdinc))
1266
1
    return;
1267
1268
7.68k
  if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
1269
7.68k
    AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, getDriver().ResourceDir,
1270
7.68k
                                  "include");
1271
7.68k
  }
1272
1273
  // Add %INCLUDE%-like directories from the -imsvc flag.
1274
7.68k
  for (const auto &Path : DriverArgs.getAllArgValues(options::OPT__SLASH_imsvc))
1275
3
    addSystemInclude(DriverArgs, CC1Args, Path);
1276
1277
7.68k
  if (DriverArgs.hasArg(options::OPT_nostdlibinc))
1278
2
    return;
1279
1280
  // Honor %INCLUDE%. It should know essential search paths with vcvarsall.bat.
1281
  // Skip if the user expressly set a vctoolsdir
1282
7.68k
  if (!DriverArgs.getLastArg(options::OPT__SLASH_vctoolsdir)) {
1283
7.68k
    if (llvm::Optional<std::string> cl_include_dir =
1284
1
            llvm::sys::Process::GetEnv("INCLUDE")) {
1285
1
      SmallVector<StringRef, 8> Dirs;
1286
1
      StringRef(*cl_include_dir)
1287
1
          .split(Dirs, ";", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
1288
1
      for (StringRef Dir : Dirs)
1289
1
        addSystemInclude(DriverArgs, CC1Args, Dir);
1290
1
      if (!Dirs.empty())
1291
1
        return;
1292
7.68k
    }
1293
7.68k
  }
1294
1295
  // When built with access to the proper Windows APIs, try to actually find
1296
  // the correct include paths first.
1297
7.68k
  if (!VCToolChainPath.empty()) {
1298
1
    addSystemInclude(DriverArgs, CC1Args,
1299
1
                     getSubDirectoryPath(SubDirectoryType::Include));
1300
1
    addSystemInclude(DriverArgs, CC1Args,
1301
1
                     getSubDirectoryPath(SubDirectoryType::Include, "atlmfc"));
1302
1303
1
    if (useUniversalCRT()) {
1304
1
      std::string UniversalCRTSdkPath;
1305
1
      std::string UCRTVersion;
1306
1
      if (getUniversalCRTSdkDir(UniversalCRTSdkPath, UCRTVersion)) {
1307
0
        AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, UniversalCRTSdkPath,
1308
0
                                      "Include", UCRTVersion, "ucrt");
1309
0
      }
1310
1
    }
1311
1312
1
    std::string WindowsSDKDir;
1313
1
    int major;
1314
1
    std::string windowsSDKIncludeVersion;
1315
1
    std::string windowsSDKLibVersion;
1316
1
    if (getWindowsSDKDir(WindowsSDKDir, major, windowsSDKIncludeVersion,
1317
0
                         windowsSDKLibVersion)) {
1318
0
      if (major >= 8) {
1319
        // Note: windowsSDKIncludeVersion is empty for SDKs prior to v10.
1320
        // Anyway, llvm::sys::path::append is able to manage it.
1321
0
        AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
1322
0
                                      "include", windowsSDKIncludeVersion,
1323
0
                                      "shared");
1324
0
        AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
1325
0
                                      "include", windowsSDKIncludeVersion,
1326
0
                                      "um");
1327
0
        AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
1328
0
                                      "include", windowsSDKIncludeVersion,
1329
0
                                      "winrt");
1330
0
      } else {
1331
0
        AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
1332
0
                                      "include");
1333
0
      }
1334
0
    }
1335
1336
1
    return;
1337
1
  }
1338
1339
#if defined(_WIN32)
1340
  // As a fallback, select default install paths.
1341
  // FIXME: Don't guess drives and paths like this on Windows.
1342
  const StringRef Paths[] = {
1343
    "C:/Program Files/Microsoft Visual Studio 10.0/VC/include",
1344
    "C:/Program Files/Microsoft Visual Studio 9.0/VC/include",
1345
    "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include",
1346
    "C:/Program Files/Microsoft Visual Studio 8/VC/include",
1347
    "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include"
1348
  };
1349
  addSystemIncludes(DriverArgs, CC1Args, Paths);
1350
#endif
1351
7.68k
}
1352
1353
void MSVCToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
1354
6.37k
                                                 ArgStringList &CC1Args) const {
1355
  // FIXME: There should probably be logic here to find libc++ on Windows.
1356
6.37k
}
1357
1358
VersionTuple MSVCToolChain::computeMSVCVersion(const Driver *D,
1359
15.7k
                                               const ArgList &Args) const {
1360
15.7k
  bool IsWindowsMSVC = getTriple().isWindowsMSVCEnvironment();
1361
15.7k
  VersionTuple MSVT = ToolChain::computeMSVCVersion(D, Args);
1362
15.7k
  if (MSVT.empty())
1363
15.6k
    MSVT = getMSVCVersionFromTriple(getTriple());
1364
15.7k
  if (MSVT.empty() && 
IsWindowsMSVC15.6k
)
1365
15.6k
    MSVT = getMSVCVersionFromExe(getSubDirectoryPath(SubDirectoryType::Bin));
1366
15.7k
  if (MSVT.empty() &&
1367
15.6k
      Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
1368
15.6k
                   IsWindowsMSVC)) {
1369
    // -fms-compatibility-version=19.11 is default, aka 2017, 15.3
1370
15.6k
    MSVT = VersionTuple(19, 11);
1371
15.6k
  }
1372
15.7k
  return MSVT;
1373
15.7k
}
1374
1375
std::string
1376
MSVCToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
1377
8.03k
                                           types::ID InputType) const {
1378
  // The MSVC version doesn't care about the architecture, even though it
1379
  // may look at the triple internally.
1380
8.03k
  VersionTuple MSVT = computeMSVCVersion(/*D=*/nullptr, Args);
1381
8.03k
  MSVT = VersionTuple(MSVT.getMajor(), MSVT.getMinor().getValueOr(0),
1382
8.03k
                      MSVT.getSubminor().getValueOr(0));
1383
1384
  // For the rest of the triple, however, a computed architecture name may
1385
  // be needed.
1386
8.03k
  llvm::Triple Triple(ToolChain::ComputeEffectiveClangTriple(Args, InputType));
1387
8.03k
  if (Triple.getEnvironment() == llvm::Triple::MSVC) {
1388
8.02k
    StringRef ObjFmt = Triple.getEnvironmentName().split('-').second;
1389
8.02k
    if (ObjFmt.empty())
1390
8.02k
      Triple.setEnvironmentName((Twine("msvc") + MSVT.getAsString()).str());
1391
1
    else
1392
1
      Triple.setEnvironmentName(
1393
1
          (Twine("msvc") + MSVT.getAsString() + Twine('-') + ObjFmt).str());
1394
8.02k
  }
1395
8.03k
  return Triple.getTriple();
1396
8.03k
}
1397
1398
7.63k
SanitizerMask MSVCToolChain::getSupportedSanitizers() const {
1399
7.63k
  SanitizerMask Res = ToolChain::getSupportedSanitizers();
1400
7.63k
  Res |= SanitizerKind::Address;
1401
7.63k
  Res |= SanitizerKind::PointerCompare;
1402
7.63k
  Res |= SanitizerKind::PointerSubtract;
1403
7.63k
  Res |= SanitizerKind::Fuzzer;
1404
7.63k
  Res |= SanitizerKind::FuzzerNoLink;
1405
7.63k
  Res &= ~SanitizerKind::CFIMFCall;
1406
7.63k
  return Res;
1407
7.63k
}
1408
1409
static void TranslateOptArg(Arg *A, llvm::opt::DerivedArgList &DAL,
1410
                            bool SupportsForcingFramePointer,
1411
38
                            const char *ExpandChar, const OptTable &Opts) {
1412
38
  assert(A->getOption().matches(options::OPT__SLASH_O));
1413
1414
38
  StringRef OptStr = A->getValue();
1415
82
  for (size_t I = 0, E = OptStr.size(); I != E; 
++I44
) {
1416
44
    const char &OptChar = *(OptStr.data() + I);
1417
44
    switch (OptChar) {
1418
4
    default:
1419
4
      break;
1420
19
    case '1':
1421
19
    case '2':
1422
19
    case 'x':
1423
19
    case 'd':
1424
      // Ignore /O[12xd] flags that aren't the last one on the command line.
1425
      // Only the last one gets expanded.
1426
19
      if (&OptChar != ExpandChar) {
1427
0
        A->claim();
1428
0
        break;
1429
0
      }
1430
19
      if (OptChar == 'd') {
1431
4
        DAL.AddFlagArg(A, Opts.getOption(options::OPT_O0));
1432
15
      } else {
1433
15
        if (OptChar == '1') {
1434
2
          DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
1435
13
        } else if (OptChar == '2' || 
OptChar == 'x'4
) {
1436
13
          DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin));
1437
13
          DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
1438
13
        }
1439
15
        if (SupportsForcingFramePointer &&
1440
10
            !DAL.hasArgNoClaim(options::OPT_fno_omit_frame_pointer))
1441
8
          DAL.AddFlagArg(A, Opts.getOption(options::OPT_fomit_frame_pointer));
1442
15
        if (OptChar == '1' || 
OptChar == '2'13
)
1443
11
          DAL.AddFlagArg(A, Opts.getOption(options::OPT_ffunction_sections));
1444
15
      }
1445
19
      break;
1446
6
    case 'b':
1447
6
      if (I + 1 != E && isdigit(OptStr[I + 1])) {
1448
6
        switch (OptStr[I + 1]) {
1449
1
        case '0':
1450
1
          DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_inline));
1451
1
          break;
1452
2
        case '1':
1453
2
          DAL.AddFlagArg(A, Opts.getOption(options::OPT_finline_hint_functions));
1454
2
          break;
1455
3
        case '2':
1456
3
          DAL.AddFlagArg(A, Opts.getOption(options::OPT_finline_functions));
1457
3
          break;
1458
6
        }
1459
6
        ++I;
1460
6
      }
1461
6
      break;
1462
1
    case 'g':
1463
1
      A->claim();
1464
1
      break;
1465
3
    case 'i':
1466
3
      if (I + 1 != E && 
OptStr[I + 1] == '-'2
) {
1467
2
        ++I;
1468
2
        DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_builtin));
1469
1
      } else {
1470
1
        DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin));
1471
1
      }
1472
3
      break;
1473
4
    case 's':
1474
4
      DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
1475
4
      break;
1476
2
    case 't':
1477
2
      DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
1478
2
      break;
1479
5
    case 'y': {
1480
5
      bool OmitFramePointer = true;
1481
5
      if (I + 1 != E && 
OptStr[I + 1] == '-'4
) {
1482
4
        OmitFramePointer = false;
1483
4
        ++I;
1484
4
      }
1485
5
      if (SupportsForcingFramePointer) {
1486
4
        if (OmitFramePointer)
1487
0
          DAL.AddFlagArg(A,
1488
0
                         Opts.getOption(options::OPT_fomit_frame_pointer));
1489
4
        else
1490
4
          DAL.AddFlagArg(
1491
4
              A, Opts.getOption(options::OPT_fno_omit_frame_pointer));
1492
1
      } else {
1493
        // Don't warn about /Oy- in x86-64 builds (where
1494
        // SupportsForcingFramePointer is false).  The flag having no effect
1495
        // there is a compiler-internal optimization, and people shouldn't have
1496
        // to special-case their build files for x86-64 clang-cl.
1497
1
        A->claim();
1498
1
      }
1499
5
      break;
1500
6
    }
1501
44
    }
1502
44
  }
1503
38
}
1504
1505
static void TranslateDArg(Arg *A, llvm::opt::DerivedArgList &DAL,
1506
23
                          const OptTable &Opts) {
1507
23
  assert(A->getOption().matches(options::OPT_D));
1508
1509
23
  StringRef Val = A->getValue();
1510
23
  size_t Hash = Val.find('#');
1511
23
  if (Hash == StringRef::npos || 
Hash > Val.find('=')4
) {
1512
20
    DAL.append(A);
1513
20
    return;
1514
20
  }
1515
1516
3
  std::string NewVal = std::string(Val);
1517
3
  NewVal[Hash] = '=';
1518
3
  DAL.AddJoinedArg(A, Opts.getOption(options::OPT_D), NewVal);
1519
3
}
1520
1521
llvm::opt::DerivedArgList *
1522
MSVCToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
1523
                             StringRef BoundArch,
1524
7.65k
                             Action::OffloadKind OFK) const {
1525
7.65k
  DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
1526
7.65k
  const OptTable &Opts = getDriver().getOpts();
1527
1528
  // /Oy and /Oy- don't have an effect on X86-64
1529
7.65k
  bool SupportsForcingFramePointer = getArch() != llvm::Triple::x86_64;
1530
1531
  // The -O[12xd] flag actually expands to several flags.  We must desugar the
1532
  // flags so that options embedded can be negated.  For example, the '-O2' flag
1533
  // enables '-Oy'.  Expanding '-O2' into its constituent flags allows us to
1534
  // correctly handle '-O2 -Oy-' where the trailing '-Oy-' disables a single
1535
  // aspect of '-O2'.
1536
  //
1537
  // Note that this expansion logic only applies to the *last* of '[12xd]'.
1538
1539
  // First step is to search for the character we'd like to expand.
1540
7.65k
  const char *ExpandChar = nullptr;
1541
38
  for (Arg *A : Args.filtered(options::OPT__SLASH_O)) {
1542
38
    StringRef OptStr = A->getValue();
1543
94
    for (size_t I = 0, E = OptStr.size(); I != E; 
++I56
) {
1544
56
      char OptChar = OptStr[I];
1545
38
      char PrevChar = I > 0 ? 
OptStr[I - 1]18
: '0';
1546
56
      if (PrevChar == 'b') {
1547
        // OptChar does not expand; it's an argument to the previous char.
1548
6
        continue;
1549
6
      }
1550
50
      if (OptChar == '1' || 
OptChar == '2'48
||
OptChar == 'x'39
||
OptChar == 'd'35
)
1551
19
        ExpandChar = OptStr.data() + I;
1552
50
    }
1553
38
  }
1554
1555
77.2k
  for (Arg *A : Args) {
1556
77.2k
    if (A->getOption().matches(options::OPT__SLASH_O)) {
1557
      // The -O flag actually takes an amalgam of other options.  For example,
1558
      // '/Ogyb2' is equivalent to '/Og' '/Oy' '/Ob2'.
1559
38
      TranslateOptArg(A, *DAL, SupportsForcingFramePointer, ExpandChar, Opts);
1560
77.2k
    } else if (A->getOption().matches(options::OPT_D)) {
1561
      // Translate -Dfoo#bar into -Dfoo=bar.
1562
23
      TranslateDArg(A, *DAL, Opts);
1563
77.1k
    } else if (OFK != Action::OFK_HIP) {
1564
      // HIP Toolchain translates input args by itself.
1565
77.1k
      DAL->append(A);
1566
77.1k
    }
1567
77.2k
  }
1568
1569
7.65k
  return DAL;
1570
7.65k
}