Coverage Report

Created: 2021-01-23 06:44

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