Coverage Report

Created: 2021-09-21 08:58

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