Coverage Report

Created: 2022-01-25 06:29

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