Coverage Report

Created: 2023-09-30 09:22

/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/Option/Arg.h"
22
#include "llvm/Option/ArgList.h"
23
#include "llvm/Support/ConvertUTF.h"
24
#include "llvm/Support/ErrorHandling.h"
25
#include "llvm/Support/FileSystem.h"
26
#include "llvm/Support/MemoryBuffer.h"
27
#include "llvm/Support/Path.h"
28
#include "llvm/Support/Process.h"
29
#include "llvm/Support/VirtualFileSystem.h"
30
#include "llvm/TargetParser/Host.h"
31
#include <cstdio>
32
33
#ifdef _WIN32
34
  #define WIN32_LEAN_AND_MEAN
35
  #define NOGDI
36
  #ifndef NOMINMAX
37
    #define NOMINMAX
38
  #endif
39
  #include <windows.h>
40
#endif
41
42
using namespace clang::driver;
43
using namespace clang::driver::toolchains;
44
using namespace clang::driver::tools;
45
using namespace clang;
46
using namespace llvm::opt;
47
48
1.26k
static bool canExecute(llvm::vfs::FileSystem &VFS, StringRef Path) {
49
1.26k
  auto Status = VFS.status(Path);
50
1.26k
  if (!Status)
51
1.26k
    return false;
52
5
  return (Status->getPermissions() & llvm::sys::fs::perms::all_exe) != 0;
53
1.26k
}
54
55
// Try to find Exe from a Visual Studio distribution.  This first tries to find
56
// an installed copy of Visual Studio and, failing that, looks in the PATH,
57
// making sure that whatever executable that's found is not a same-named exe
58
// from clang itself to prevent clang from falling back to itself.
59
static std::string FindVisualStudioExecutable(const ToolChain &TC,
60
425
                                              const char *Exe) {
61
425
  const auto &MSVC = static_cast<const toolchains::MSVCToolChain &>(TC);
62
425
  SmallString<128> FilePath(
63
425
      MSVC.getSubDirectoryPath(llvm::SubDirectoryType::Bin));
64
425
  llvm::sys::path::append(FilePath, Exe);
65
425
  return std::string(canExecute(TC.getVFS(), FilePath) ? 
FilePath.str()0
: Exe);
66
425
}
67
68
void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
69
                                        const InputInfo &Output,
70
                                        const InputInfoList &Inputs,
71
                                        const ArgList &Args,
72
432
                                        const char *LinkingOutput) const {
73
432
  ArgStringList CmdArgs;
74
75
432
  auto &TC = static_cast<const toolchains::MSVCToolChain &>(getToolChain());
76
77
432
  assert((Output.isFilename() || Output.isNothing()) && "invalid output");
78
432
  if (Output.isFilename())
79
432
    CmdArgs.push_back(
80
432
        Args.MakeArgString(std::string("-out:") + Output.getFilename()));
81
82
432
  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles) &&
83
432
      
!C.getDriver().IsCLMode()430
&&
!C.getDriver().IsFlangMode()67
) {
84
67
    CmdArgs.push_back("-defaultlib:libcmt");
85
67
    CmdArgs.push_back("-defaultlib:oldnames");
86
67
  }
87
88
  // If the VC environment hasn't been configured (perhaps because the user
89
  // did not run vcvarsall), try to build a consistent link environment.  If
90
  // the environment variable is set however, assume the user knows what
91
  // they're doing. If the user passes /vctoolsdir or /winsdkdir, trust that
92
  // over env vars.
93
432
  if (const Arg *A = Args.getLastArg(options::OPT__SLASH_diasdkdir,
94
432
                                     options::OPT__SLASH_winsysroot)) {
95
    // cl.exe doesn't find the DIA SDK automatically, so this too requires
96
    // explicit flags and doesn't automatically look in "DIA SDK" relative
97
    // to the path we found for VCToolChainPath.
98
5
    llvm::SmallString<128> DIAPath(A->getValue());
99
5
    if (A->getOption().getID() == options::OPT__SLASH_winsysroot)
100
4
      llvm::sys::path::append(DIAPath, "DIA SDK");
101
102
    // The DIA SDK always uses the legacy vc arch, even in new MSVC versions.
103
5
    llvm::sys::path::append(DIAPath, "lib",
104
5
                            llvm::archToLegacyVCArch(TC.getArch()));
105
5
    CmdArgs.push_back(Args.MakeArgString(Twine("-libpath:") + DIAPath));
106
5
  }
107
432
  if (!llvm::sys::Process::GetEnv("LIB") ||
108
432
      Args.getLastArg(options::OPT__SLASH_vctoolsdir,
109
430
                      options::OPT__SLASH_winsysroot)) {
110
430
    CmdArgs.push_back(Args.MakeArgString(
111
430
        Twine("-libpath:") +
112
430
        TC.getSubDirectoryPath(llvm::SubDirectoryType::Lib)));
113
430
    CmdArgs.push_back(Args.MakeArgString(
114
430
        Twine("-libpath:") +
115
430
        TC.getSubDirectoryPath(llvm::SubDirectoryType::Lib, "atlmfc")));
116
430
  }
117
432
  if (!llvm::sys::Process::GetEnv("LIB") ||
118
432
      Args.getLastArg(options::OPT__SLASH_winsdkdir,
119
430
                      options::OPT__SLASH_winsysroot)) {
120
430
    if (TC.useUniversalCRT()) {
121
430
      std::string UniversalCRTLibPath;
122
430
      if (TC.getUniversalCRTLibraryPath(Args, UniversalCRTLibPath))
123
6
        CmdArgs.push_back(
124
6
            Args.MakeArgString(Twine("-libpath:") + UniversalCRTLibPath));
125
430
    }
126
430
    std::string WindowsSdkLibPath;
127
430
    if (TC.getWindowsSDKLibraryPath(Args, WindowsSdkLibPath))
128
6
      CmdArgs.push_back(
129
6
          Args.MakeArgString(std::string("-libpath:") + WindowsSdkLibPath));
130
430
  }
131
132
432
  if (C.getDriver().IsFlangMode()) {
133
0
    addFortranRuntimeLibraryPath(TC, Args, CmdArgs);
134
0
    addFortranRuntimeLibs(TC, CmdArgs);
135
136
    // Inform the MSVC linker that we're generating a console application, i.e.
137
    // one with `main` as the "user-defined" entry point. The `main` function is
138
    // defined in flang's runtime libraries.
139
0
    CmdArgs.push_back("/subsystem:console");
140
0
  }
141
142
  // Add the compiler-rt library directories to libpath if they exist to help
143
  // the linker find the various sanitizer, builtin, and profiling runtimes.
144
432
  for (const auto &LibPath : TC.getLibraryPaths()) {
145
0
    if (TC.getVFS().exists(LibPath))
146
0
      CmdArgs.push_back(Args.MakeArgString("-libpath:" + LibPath));
147
0
  }
148
432
  auto CRTPath = TC.getCompilerRTPath();
149
432
  if (TC.getVFS().exists(CRTPath))
150
3
    CmdArgs.push_back(Args.MakeArgString("-libpath:" + CRTPath));
151
152
432
  if (!C.getDriver().IsCLMode() && 
Args.hasArg(options::OPT_L)69
)
153
3
    for (const auto &LibPath : Args.getAllArgValues(options::OPT_L))
154
4
      CmdArgs.push_back(Args.MakeArgString("-libpath:" + LibPath));
155
156
432
  CmdArgs.push_back("-nologo");
157
158
432
  if (Args.hasArg(options::OPT_g_Group, options::OPT__SLASH_Z7))
159
13
    CmdArgs.push_back("-debug");
160
161
  // If we specify /hotpatch, let the linker add padding in front of each
162
  // function, like MSVC does.
163
432
  if (Args.hasArg(options::OPT_fms_hotpatch, options::OPT__SLASH_hotpatch))
164
2
    CmdArgs.push_back("-functionpadmin");
165
166
  // Pass on /Brepro if it was passed to the compiler.
167
  // Note that /Brepro maps to -mno-incremental-linker-compatible.
168
432
  bool DefaultIncrementalLinkerCompatible =
169
432
      C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment();
170
432
  if (!Args.hasFlag(options::OPT_mincremental_linker_compatible,
171
432
                    options::OPT_mno_incremental_linker_compatible,
172
432
                    DefaultIncrementalLinkerCompatible))
173
1
    CmdArgs.push_back("-Brepro");
174
175
432
  bool DLL = Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd,
176
432
                         options::OPT_shared);
177
432
  if (DLL) {
178
42
    CmdArgs.push_back(Args.MakeArgString("-dll"));
179
180
42
    SmallString<128> ImplibName(Output.getFilename());
181
42
    llvm::sys::path::replace_extension(ImplibName, "lib");
182
42
    CmdArgs.push_back(Args.MakeArgString(std::string("-implib:") + ImplibName));
183
42
  }
184
185
432
  if (TC.getSanitizerArgs(Args).needsFuzzer()) {
186
0
    if (!Args.hasArg(options::OPT_shared))
187
0
      CmdArgs.push_back(
188
0
          Args.MakeArgString(std::string("-wholearchive:") +
189
0
                             TC.getCompilerRTArgString(Args, "fuzzer")));
190
0
    CmdArgs.push_back(Args.MakeArgString("-debug"));
191
    // Prevent the linker from padding sections we use for instrumentation
192
    // arrays.
193
0
    CmdArgs.push_back(Args.MakeArgString("-incremental:no"));
194
0
  }
195
196
432
  if (TC.getSanitizerArgs(Args).needsAsanRt()) {
197
18
    CmdArgs.push_back(Args.MakeArgString("-debug"));
198
18
    CmdArgs.push_back(Args.MakeArgString("-incremental:no"));
199
18
    if (TC.getSanitizerArgs(Args).needsSharedRt() ||
200
18
        Args.hasArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd)) {
201
1
      for (const auto &Lib : {"asan_dynamic", "asan_dynamic_runtime_thunk"})
202
2
        CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib));
203
      // Make sure the dynamic runtime thunk is not optimized out at link time
204
      // to ensure proper SEH handling.
205
1
      CmdArgs.push_back(Args.MakeArgString(
206
1
          TC.getArch() == llvm::Triple::x86
207
1
              ? "-include:___asan_seh_interceptor"
208
1
              : 
"-include:__asan_seh_interceptor"0
));
209
      // Make sure the linker consider all object files from the dynamic runtime
210
      // thunk.
211
1
      CmdArgs.push_back(Args.MakeArgString(std::string("-wholearchive:") +
212
1
          TC.getCompilerRT(Args, "asan_dynamic_runtime_thunk")));
213
17
    } else if (DLL) {
214
2
      CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dll_thunk"));
215
15
    } else {
216
30
      for (const auto &Lib : {"asan", "asan_cxx"}) {
217
30
        CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib));
218
        // Make sure the linker consider all object files from the static lib.
219
        // This is necessary because instrumented dlls need access to all the
220
        // interface exported by the static lib in the main executable.
221
30
        CmdArgs.push_back(Args.MakeArgString(std::string("-wholearchive:") +
222
30
            TC.getCompilerRT(Args, Lib)));
223
30
      }
224
15
    }
225
18
  }
226
227
432
  Args.AddAllArgValues(CmdArgs, options::OPT__SLASH_link);
228
229
  // Control Flow Guard checks
230
432
  for (const Arg *A : Args.filtered(options::OPT__SLASH_guard)) {
231
9
    StringRef GuardArgs = A->getValue();
232
9
    if (GuardArgs.equals_insensitive("cf") ||
233
9
        
GuardArgs.equals_insensitive("cf,nochecks")7
) {
234
      // MSVC doesn't yet support the "nochecks" modifier.
235
3
      CmdArgs.push_back("-guard:cf");
236
6
    } else if (GuardArgs.equals_insensitive("cf-")) {
237
1
      CmdArgs.push_back("-guard:cf-");
238
5
    } else if (GuardArgs.equals_insensitive("ehcont")) {
239
2
      CmdArgs.push_back("-guard:ehcont");
240
3
    } else if (GuardArgs.equals_insensitive("ehcont-")) {
241
1
      CmdArgs.push_back("-guard:ehcont-");
242
1
    }
243
9
  }
244
245
432
  if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
246
432
                   options::OPT_fno_openmp, false)) {
247
8
    CmdArgs.push_back("-nodefaultlib:vcomp.lib");
248
8
    CmdArgs.push_back("-nodefaultlib:vcompd.lib");
249
8
    CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") +
250
8
                                         TC.getDriver().Dir + "/../lib"));
251
8
    switch (TC.getDriver().getOpenMPRuntime(Args)) {
252
3
    case Driver::OMPRT_OMP:
253
3
      CmdArgs.push_back("-defaultlib:libomp.lib");
254
3
      break;
255
3
    case Driver::OMPRT_IOMP5:
256
3
      CmdArgs.push_back("-defaultlib:libiomp5md.lib");
257
3
      break;
258
2
    case Driver::OMPRT_GOMP:
259
2
      break;
260
0
    case Driver::OMPRT_Unknown:
261
      // Already diagnosed.
262
0
      break;
263
8
    }
264
8
  }
265
266
  // Add compiler-rt lib in case if it was explicitly
267
  // specified as an argument for --rtlib option.
268
432
  if (!Args.hasArg(options::OPT_nostdlib)) {
269
430
    AddRunTimeLibs(TC, TC.getDriver(), CmdArgs, Args);
270
430
  }
271
272
432
  StringRef Linker =
273
432
      Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER);
274
432
  if (Linker.empty())
275
394
    Linker = "link";
276
  // We need to translate 'lld' into 'lld-link'.
277
38
  else if (Linker.equals_insensitive("lld"))
278
6
    Linker = "lld-link";
279
280
432
  if (Linker == "lld-link") {
281
7
    for (Arg *A : Args.filtered(options::OPT_vfsoverlay))
282
1
      CmdArgs.push_back(
283
1
          Args.MakeArgString(std::string("/vfsoverlay:") + A->getValue()));
284
285
7
    if (C.getDriver().isUsingLTO() &&
286
7
        Args.hasFlag(options::OPT_gsplit_dwarf, options::OPT_gno_split_dwarf,
287
1
                     false))
288
1
      CmdArgs.push_back(Args.MakeArgString(Twine("/dwodir:") +
289
1
                                           Output.getFilename() + "_dwo"));
290
7
  }
291
292
  // Add filenames, libraries, and other linker inputs.
293
466
  for (const auto &Input : Inputs) {
294
466
    if (Input.isFilename()) {
295
458
      CmdArgs.push_back(Input.getFilename());
296
458
      continue;
297
458
    }
298
299
8
    const Arg &A = Input.getInputArg();
300
301
    // Render -l options differently for the MSVC linker.
302
8
    if (A.getOption().matches(options::OPT_l)) {
303
5
      StringRef Lib = A.getValue();
304
5
      const char *LinkLibArg;
305
5
      if (Lib.endswith(".lib"))
306
3
        LinkLibArg = Args.MakeArgString(Lib);
307
2
      else
308
2
        LinkLibArg = Args.MakeArgString(Lib + ".lib");
309
5
      CmdArgs.push_back(LinkLibArg);
310
5
      continue;
311
5
    }
312
313
    // Otherwise, this is some other kind of linker input option like -Wl, -z,
314
    // or -L. Render it, even if MSVC doesn't understand it.
315
3
    A.renderAsInput(Args, CmdArgs);
316
3
  }
317
318
432
  addHIPRuntimeLibArgs(TC, C, Args, CmdArgs);
319
320
432
  TC.addProfileRTLibs(Args, CmdArgs);
321
322
432
  std::vector<const char *> Environment;
323
324
  // We need to special case some linker paths. In the case of the regular msvc
325
  // linker, we need to use a special search algorithm.
326
432
  llvm::SmallString<128> linkPath;
327
432
  if (Linker.equals_insensitive("link")) {
328
    // If we're using the MSVC linker, it's not sufficient to just use link
329
    // from the program PATH, because other environments like GnuWin32 install
330
    // their own link.exe which may come first.
331
425
    linkPath = FindVisualStudioExecutable(TC, "link.exe");
332
333
425
    if (!TC.FoundMSVCInstall() && 
!canExecute(TC.getVFS(), linkPath)419
) {
334
419
      llvm::SmallString<128> ClPath;
335
419
      ClPath = TC.GetProgramPath("cl.exe");
336
419
      if (canExecute(TC.getVFS(), ClPath)) {
337
5
        linkPath = llvm::sys::path::parent_path(ClPath);
338
5
        llvm::sys::path::append(linkPath, "link.exe");
339
5
        if (!canExecute(TC.getVFS(), linkPath))
340
5
          C.getDriver().Diag(clang::diag::warn_drv_msvc_not_found);
341
414
      } else {
342
414
        C.getDriver().Diag(clang::diag::warn_drv_msvc_not_found);
343
414
      }
344
419
    }
345
346
    // Clang handles passing the proper asan libs to the linker, which goes
347
    // against link.exe's /INFERASANLIBS which automatically finds asan libs.
348
425
    if (TC.getSanitizerArgs(Args).needsAsanRt())
349
17
      CmdArgs.push_back("/INFERASANLIBS:NO");
350
351
#ifdef _WIN32
352
    // When cross-compiling with VS2017 or newer, link.exe expects to have
353
    // its containing bin directory at the top of PATH, followed by the
354
    // native target bin directory.
355
    // e.g. when compiling for x86 on an x64 host, PATH should start with:
356
    // /bin/Hostx64/x86;/bin/Hostx64/x64
357
    // This doesn't attempt to handle llvm::ToolsetLayout::DevDivInternal.
358
    if (TC.getIsVS2017OrNewer() &&
359
        llvm::Triple(llvm::sys::getProcessTriple()).getArch() != TC.getArch()) {
360
      auto HostArch = llvm::Triple(llvm::sys::getProcessTriple()).getArch();
361
362
      auto EnvBlockWide =
363
          std::unique_ptr<wchar_t[], decltype(&FreeEnvironmentStringsW)>(
364
              GetEnvironmentStringsW(), FreeEnvironmentStringsW);
365
      if (!EnvBlockWide)
366
        goto SkipSettingEnvironment;
367
368
      size_t EnvCount = 0;
369
      size_t EnvBlockLen = 0;
370
      while (EnvBlockWide[EnvBlockLen] != L'\0') {
371
        ++EnvCount;
372
        EnvBlockLen += std::wcslen(&EnvBlockWide[EnvBlockLen]) +
373
                       1 /*string null-terminator*/;
374
      }
375
      ++EnvBlockLen; // add the block null-terminator
376
377
      std::string EnvBlock;
378
      if (!llvm::convertUTF16ToUTF8String(
379
              llvm::ArrayRef<char>(reinterpret_cast<char *>(EnvBlockWide.get()),
380
                                   EnvBlockLen * sizeof(EnvBlockWide[0])),
381
              EnvBlock))
382
        goto SkipSettingEnvironment;
383
384
      Environment.reserve(EnvCount);
385
386
      // Now loop over each string in the block and copy them into the
387
      // environment vector, adjusting the PATH variable as needed when we
388
      // find it.
389
      for (const char *Cursor = EnvBlock.data(); *Cursor != '\0';) {
390
        llvm::StringRef EnvVar(Cursor);
391
        if (EnvVar.starts_with_insensitive("path=")) {
392
          constexpr size_t PrefixLen = 5; // strlen("path=")
393
          Environment.push_back(Args.MakeArgString(
394
              EnvVar.substr(0, PrefixLen) +
395
              TC.getSubDirectoryPath(llvm::SubDirectoryType::Bin) +
396
              llvm::Twine(llvm::sys::EnvPathSeparator) +
397
              TC.getSubDirectoryPath(llvm::SubDirectoryType::Bin, HostArch) +
398
              (EnvVar.size() > PrefixLen
399
                   ? llvm::Twine(llvm::sys::EnvPathSeparator) +
400
                         EnvVar.substr(PrefixLen)
401
                   : "")));
402
        } else {
403
          Environment.push_back(Args.MakeArgString(EnvVar));
404
        }
405
        Cursor += EnvVar.size() + 1 /*null-terminator*/;
406
      }
407
    }
408
  SkipSettingEnvironment:;
409
#endif
410
425
  } else {
411
7
    linkPath = TC.GetProgramPath(Linker.str().c_str());
412
7
  }
413
414
432
  auto LinkCmd = std::make_unique<Command>(
415
432
      JA, *this, ResponseFileSupport::AtFileUTF16(),
416
432
      Args.MakeArgString(linkPath), CmdArgs, Inputs, Output);
417
432
  if (!Environment.empty())
418
0
    LinkCmd->setEnvironment(Environment);
419
432
  C.addCommand(std::move(LinkCmd));
420
432
}
421
422
MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple &Triple,
423
                             const ArgList &Args)
424
8.58k
    : ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args),
425
8.58k
      RocmInstallation(D, Triple, Args) {
426
8.58k
  getProgramPaths().push_back(getDriver().getInstalledDir());
427
8.58k
  if (getDriver().getInstalledDir() != getDriver().Dir)
428
5
    getProgramPaths().push_back(getDriver().Dir);
429
430
8.58k
  std::optional<llvm::StringRef> VCToolsDir, VCToolsVersion;
431
8.58k
  if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsdir))
432
5
    VCToolsDir = A->getValue();
433
8.58k
  if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsversion))
434
0
    VCToolsVersion = A->getValue();
435
8.58k
  if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsdkdir))
436
2
    WinSdkDir = A->getValue();
437
8.58k
  if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsdkversion))
438
1
    WinSdkVersion = A->getValue();
439
8.58k
  if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsysroot))
440
4
    WinSysRoot = A->getValue();
441
442
  // Check the command line first, that's the user explicitly telling us what to
443
  // use. Check the environment next, in case we're being invoked from a VS
444
  // command prompt. Failing that, just try to find the newest Visual Studio
445
  // version we can and use its default VC toolchain.
446
8.58k
  llvm::findVCToolChainViaCommandLine(getVFS(), VCToolsDir, VCToolsVersion,
447
8.58k
                                      WinSysRoot, VCToolChainPath, VSLayout) ||
448
8.58k
      llvm::findVCToolChainViaEnvironment(getVFS(), VCToolChainPath,
449
8.57k
                                          VSLayout) ||
450
8.58k
      llvm::findVCToolChainViaSetupConfig(getVFS(), VCToolsVersion,
451
8.57k
                                          VCToolChainPath, VSLayout) ||
452
8.58k
      
llvm::findVCToolChainViaRegistry(VCToolChainPath, VSLayout)8.57k
;
453
8.58k
}
454
455
432
Tool *MSVCToolChain::buildLinker() const {
456
432
  return new tools::visualstudio::Linker(*this);
457
432
}
458
459
3
Tool *MSVCToolChain::buildAssembler() const {
460
3
  if (getTriple().isOSBinFormatMachO())
461
2
    return new tools::darwin::Assembler(*this);
462
1
  getDriver().Diag(clang::diag::err_no_external_assembler);
463
1
  return nullptr;
464
3
}
465
466
ToolChain::UnwindTableLevel
467
17.1k
MSVCToolChain::getDefaultUnwindTableLevel(const ArgList &Args) const {
468
  // Don't emit unwind tables by default for MachO targets.
469
17.1k
  if (getTriple().isOSBinFormatMachO())
470
18
    return UnwindTableLevel::None;
471
472
  // All non-x86_32 Windows targets require unwind tables. However, LLVM
473
  // doesn't know how to generate them for all targets, so only enable
474
  // the ones that are actually implemented.
475
17.1k
  if (getArch() == llvm::Triple::x86_64 || 
getArch() == llvm::Triple::arm408
||
476
17.1k
      
getArch() == llvm::Triple::thumb338
||
getArch() == llvm::Triple::aarch64314
)
477
16.9k
    return UnwindTableLevel::Asynchronous;
478
479
268
  return UnwindTableLevel::None;
480
17.1k
}
481
482
8.63k
bool MSVCToolChain::isPICDefault() const {
483
8.63k
  return getArch() == llvm::Triple::x86_64 ||
484
8.63k
         
getArch() == llvm::Triple::aarch64209
;
485
8.63k
}
486
487
8.63k
bool MSVCToolChain::isPIEDefault(const llvm::opt::ArgList &Args) const {
488
8.63k
  return false;
489
8.63k
}
490
491
8.62k
bool MSVCToolChain::isPICDefaultForced() const {
492
8.62k
  return getArch() == llvm::Triple::x86_64 ||
493
8.62k
         
getArch() == llvm::Triple::aarch64205
;
494
8.62k
}
495
496
void MSVCToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs,
497
4
                                       ArgStringList &CC1Args) const {
498
4
  CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args);
499
4
}
500
501
void MSVCToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs,
502
10
                                      ArgStringList &CC1Args) const {
503
10
  RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args);
504
10
}
505
506
void MSVCToolChain::AddHIPRuntimeLibArgs(const ArgList &Args,
507
8
                                         ArgStringList &CmdArgs) const {
508
8
  CmdArgs.append({Args.MakeArgString(StringRef("-libpath:") +
509
8
                                     RocmInstallation.getLibPath()),
510
8
                  "amdhip64.lib"});
511
8
}
512
513
0
void MSVCToolChain::printVerboseInfo(raw_ostream &OS) const {
514
0
  CudaInstallation.print(OS);
515
0
  RocmInstallation.print(OS);
516
0
}
517
518
std::string
519
MSVCToolChain::getSubDirectoryPath(llvm::SubDirectoryType Type,
520
18.9k
                                   llvm::StringRef SubdirParent) const {
521
18.9k
  return llvm::getSubDirectoryPath(Type, VSLayout, VCToolChainPath, getArch(),
522
18.9k
                                   SubdirParent);
523
18.9k
}
524
525
std::string
526
MSVCToolChain::getSubDirectoryPath(llvm::SubDirectoryType Type,
527
0
                                   llvm::Triple::ArchType TargetArch) const {
528
0
  return llvm::getSubDirectoryPath(Type, VSLayout, VCToolChainPath, TargetArch,
529
0
                                   "");
530
0
}
531
532
// Find the most recent version of Universal CRT or Windows 10 SDK.
533
// vcvarsqueryregistry.bat from Visual Studio 2015 sorts entries in the include
534
// directory by name and uses the last one of the list.
535
// So we compare entry names lexicographically to find the greatest one.
536
// Gets the library path required to link against the Windows SDK.
537
bool MSVCToolChain::getWindowsSDKLibraryPath(const ArgList &Args,
538
430
                                             std::string &path) const {
539
430
  std::string sdkPath;
540
430
  int sdkMajor = 0;
541
430
  std::string windowsSDKIncludeVersion;
542
430
  std::string windowsSDKLibVersion;
543
544
430
  path.clear();
545
430
  if (!llvm::getWindowsSDKDir(getVFS(), WinSdkDir, WinSdkVersion, WinSysRoot,
546
430
                              sdkPath, sdkMajor, windowsSDKIncludeVersion,
547
430
                              windowsSDKLibVersion))
548
424
    return false;
549
550
6
  llvm::SmallString<128> libPath(sdkPath);
551
6
  llvm::sys::path::append(libPath, "Lib");
552
6
  if (sdkMajor >= 10)
553
3
    if (!(WinSdkDir.has_value() || 
WinSysRoot.has_value()1
) &&
554
3
        
WinSdkVersion.has_value()0
)
555
0
      windowsSDKLibVersion = *WinSdkVersion;
556
6
  if (sdkMajor >= 8)
557
3
    llvm::sys::path::append(libPath, windowsSDKLibVersion, "um");
558
6
  return llvm::appendArchToWindowsSDKLibPath(sdkMajor, libPath, getArch(),
559
6
                                             path);
560
430
}
561
562
436
bool MSVCToolChain::useUniversalCRT() const {
563
436
  return llvm::useUniversalCRT(VSLayout, VCToolChainPath, getArch(), getVFS());
564
436
}
565
566
bool MSVCToolChain::getUniversalCRTLibraryPath(const ArgList &Args,
567
430
                                               std::string &Path) const {
568
430
  std::string UniversalCRTSdkPath;
569
430
  std::string UCRTVersion;
570
571
430
  Path.clear();
572
430
  if (!llvm::getUniversalCRTSdkDir(getVFS(), WinSdkDir, WinSdkVersion,
573
430
                                   WinSysRoot, UniversalCRTSdkPath,
574
430
                                   UCRTVersion))
575
424
    return false;
576
577
6
  if (!(WinSdkDir.has_value() || 
WinSysRoot.has_value()4
) &&
578
6
      
WinSdkVersion.has_value()0
)
579
0
    UCRTVersion = *WinSdkVersion;
580
581
6
  StringRef ArchName = llvm::archToWindowsSDKArch(getArch());
582
6
  if (ArchName.empty())
583
0
    return false;
584
585
6
  llvm::SmallString<128> LibPath(UniversalCRTSdkPath);
586
6
  llvm::sys::path::append(LibPath, "Lib", UCRTVersion, "ucrt", ArchName);
587
588
6
  Path = std::string(LibPath.str());
589
6
  return true;
590
6
}
591
592
17.6k
static VersionTuple getMSVCVersionFromExe(const std::string &BinDir) {
593
17.6k
  VersionTuple Version;
594
#ifdef _WIN32
595
  SmallString<128> ClExe(BinDir);
596
  llvm::sys::path::append(ClExe, "cl.exe");
597
598
  std::wstring ClExeWide;
599
  if (!llvm::ConvertUTF8toWide(ClExe.c_str(), ClExeWide))
600
    return Version;
601
602
  const DWORD VersionSize = ::GetFileVersionInfoSizeW(ClExeWide.c_str(),
603
                                                      nullptr);
604
  if (VersionSize == 0)
605
    return Version;
606
607
  SmallVector<uint8_t, 4 * 1024> VersionBlock(VersionSize);
608
  if (!::GetFileVersionInfoW(ClExeWide.c_str(), 0, VersionSize,
609
                             VersionBlock.data()))
610
    return Version;
611
612
  VS_FIXEDFILEINFO *FileInfo = nullptr;
613
  UINT FileInfoSize = 0;
614
  if (!::VerQueryValueW(VersionBlock.data(), L"\\",
615
                        reinterpret_cast<LPVOID *>(&FileInfo), &FileInfoSize) ||
616
      FileInfoSize < sizeof(*FileInfo))
617
    return Version;
618
619
  const unsigned Major = (FileInfo->dwFileVersionMS >> 16) & 0xFFFF;
620
  const unsigned Minor = (FileInfo->dwFileVersionMS      ) & 0xFFFF;
621
  const unsigned Micro = (FileInfo->dwFileVersionLS >> 16) & 0xFFFF;
622
623
  Version = VersionTuple(Major, Minor, Micro);
624
#endif
625
17.6k
  return Version;
626
17.6k
}
627
628
void MSVCToolChain::AddSystemIncludeWithSubfolder(
629
    const ArgList &DriverArgs, ArgStringList &CC1Args,
630
    const std::string &folder, const Twine &subfolder1, const Twine &subfolder2,
631
8.65k
    const Twine &subfolder3) const {
632
8.65k
  llvm::SmallString<128> path(folder);
633
8.65k
  llvm::sys::path::append(path, subfolder1, subfolder2, subfolder3);
634
8.65k
  addSystemInclude(DriverArgs, CC1Args, path);
635
8.65k
}
636
637
void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
638
8.64k
                                              ArgStringList &CC1Args) const {
639
8.64k
  if (DriverArgs.hasArg(options::OPT_nostdinc))
640
8
    return;
641
642
8.63k
  if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
643
8.63k
    AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, getDriver().ResourceDir,
644
8.63k
                                  "include");
645
8.63k
  }
646
647
  // Add %INCLUDE%-like directories from the -imsvc flag.
648
8.63k
  for (const auto &Path : DriverArgs.getAllArgValues(options::OPT__SLASH_imsvc))
649
4
    addSystemInclude(DriverArgs, CC1Args, Path);
650
651
17.2k
  auto AddSystemIncludesFromEnv = [&](StringRef Var) -> bool {
652
17.2k
    if (auto Val = llvm::sys::Process::GetEnv(Var)) {
653
6
      SmallVector<StringRef, 8> Dirs;
654
6
      StringRef(*Val).split(Dirs, ";", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
655
6
      if (!Dirs.empty()) {
656
6
        addSystemIncludes(DriverArgs, CC1Args, Dirs);
657
6
        return true;
658
6
      }
659
6
    }
660
17.2k
    return false;
661
17.2k
  };
662
663
  // Add %INCLUDE%-like dirs via /external:env: flags.
664
8.63k
  for (const auto &Var :
665
8.63k
       DriverArgs.getAllArgValues(options::OPT__SLASH_external_env)) {
666
5
    AddSystemIncludesFromEnv(Var);
667
5
  }
668
669
  // Add DIA SDK include if requested.
670
8.63k
  if (const Arg *A = DriverArgs.getLastArg(options::OPT__SLASH_diasdkdir,
671
8.63k
                                           options::OPT__SLASH_winsysroot)) {
672
    // cl.exe doesn't find the DIA SDK automatically, so this too requires
673
    // explicit flags and doesn't automatically look in "DIA SDK" relative
674
    // to the path we found for VCToolChainPath.
675
5
    llvm::SmallString<128> DIASDKPath(A->getValue());
676
5
    if (A->getOption().getID() == options::OPT__SLASH_winsysroot)
677
4
      llvm::sys::path::append(DIASDKPath, "DIA SDK");
678
5
    AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, std::string(DIASDKPath),
679
5
                                  "include");
680
5
  }
681
682
8.63k
  if (DriverArgs.hasArg(options::OPT_nostdlibinc))
683
2
    return;
684
685
  // Honor %INCLUDE% and %EXTERNAL_INCLUDE%. It should have essential search
686
  // paths set by vcvarsall.bat. Skip if the user expressly set a vctoolsdir.
687
8.63k
  if (!DriverArgs.getLastArg(options::OPT__SLASH_vctoolsdir,
688
8.63k
                             options::OPT__SLASH_winsysroot)) {
689
8.62k
    bool Found = AddSystemIncludesFromEnv("INCLUDE");
690
8.62k
    Found |= AddSystemIncludesFromEnv("EXTERNAL_INCLUDE");
691
8.62k
    if (Found)
692
1
      return;
693
8.62k
  }
694
695
  // When built with access to the proper Windows APIs, try to actually find
696
  // the correct include paths first.
697
8.63k
  if (!VCToolChainPath.empty()) {
698
6
    addSystemInclude(DriverArgs, CC1Args,
699
6
                     getSubDirectoryPath(llvm::SubDirectoryType::Include));
700
6
    addSystemInclude(
701
6
        DriverArgs, CC1Args,
702
6
        getSubDirectoryPath(llvm::SubDirectoryType::Include, "atlmfc"));
703
704
6
    if (useUniversalCRT()) {
705
6
      std::string UniversalCRTSdkPath;
706
6
      std::string UCRTVersion;
707
6
      if (llvm::getUniversalCRTSdkDir(getVFS(), WinSdkDir, WinSdkVersion,
708
6
                                      WinSysRoot, UniversalCRTSdkPath,
709
6
                                      UCRTVersion)) {
710
6
        if (!(WinSdkDir.has_value() || 
WinSysRoot.has_value()4
) &&
711
6
            
WinSdkVersion.has_value()0
)
712
0
          UCRTVersion = *WinSdkVersion;
713
6
        AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, UniversalCRTSdkPath,
714
6
                                      "Include", UCRTVersion, "ucrt");
715
6
      }
716
6
    }
717
718
6
    std::string WindowsSDKDir;
719
6
    int major = 0;
720
6
    std::string windowsSDKIncludeVersion;
721
6
    std::string windowsSDKLibVersion;
722
6
    if (llvm::getWindowsSDKDir(getVFS(), WinSdkDir, WinSdkVersion, WinSysRoot,
723
6
                               WindowsSDKDir, major, windowsSDKIncludeVersion,
724
6
                               windowsSDKLibVersion)) {
725
6
      if (major >= 10)
726
3
        if (!(WinSdkDir.has_value() || 
WinSysRoot.has_value()1
) &&
727
3
            
WinSdkVersion.has_value()0
)
728
0
          windowsSDKIncludeVersion = windowsSDKLibVersion = *WinSdkVersion;
729
6
      if (major >= 8) {
730
        // Note: windowsSDKIncludeVersion is empty for SDKs prior to v10.
731
        // Anyway, llvm::sys::path::append is able to manage it.
732
3
        AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
733
3
                                      "Include", windowsSDKIncludeVersion,
734
3
                                      "shared");
735
3
        AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
736
3
                                      "Include", windowsSDKIncludeVersion,
737
3
                                      "um");
738
3
        AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
739
3
                                      "Include", windowsSDKIncludeVersion,
740
3
                                      "winrt");
741
3
        if (major >= 10) {
742
3
          llvm::VersionTuple Tuple;
743
3
          if (!Tuple.tryParse(windowsSDKIncludeVersion) &&
744
3
              Tuple.getSubminor().value_or(0) >= 17134) {
745
2
            AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
746
2
                                          "Include", windowsSDKIncludeVersion,
747
2
                                          "cppwinrt");
748
2
          }
749
3
        }
750
3
      } else {
751
3
        AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
752
3
                                      "Include");
753
3
      }
754
6
    }
755
756
6
    return;
757
6
  }
758
759
#if defined(_WIN32)
760
  // As a fallback, select default install paths.
761
  // FIXME: Don't guess drives and paths like this on Windows.
762
  const StringRef Paths[] = {
763
    "C:/Program Files/Microsoft Visual Studio 10.0/VC/include",
764
    "C:/Program Files/Microsoft Visual Studio 9.0/VC/include",
765
    "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include",
766
    "C:/Program Files/Microsoft Visual Studio 8/VC/include",
767
    "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include"
768
  };
769
  addSystemIncludes(DriverArgs, CC1Args, Paths);
770
#endif
771
8.63k
}
772
773
void MSVCToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
774
7.15k
                                                 ArgStringList &CC1Args) const {
775
  // FIXME: There should probably be logic here to find libc++ on Windows.
776
7.15k
}
777
778
VersionTuple MSVCToolChain::computeMSVCVersion(const Driver *D,
779
17.6k
                                               const ArgList &Args) const {
780
17.6k
  bool IsWindowsMSVC = getTriple().isWindowsMSVCEnvironment();
781
17.6k
  VersionTuple MSVT = ToolChain::computeMSVCVersion(D, Args);
782
17.6k
  if (MSVT.empty())
783
17.6k
    MSVT = getTriple().getEnvironmentVersion();
784
17.6k
  if (MSVT.empty() && 
IsWindowsMSVC17.6k
)
785
17.6k
    MSVT =
786
17.6k
        getMSVCVersionFromExe(getSubDirectoryPath(llvm::SubDirectoryType::Bin));
787
17.6k
  if (MSVT.empty() &&
788
17.6k
      Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
789
17.6k
                   IsWindowsMSVC)) {
790
    // -fms-compatibility-version=19.20 is default, aka 2019, 16.x
791
    // NOTE: when changing this value, also update
792
    // clang/docs/CommandGuide/clang.rst and clang/docs/UsersManual.rst
793
    // accordingly.
794
17.6k
    MSVT = VersionTuple(19, 20);
795
17.6k
  }
796
17.6k
  return MSVT;
797
17.6k
}
798
799
std::string
800
MSVCToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
801
9.07k
                                           types::ID InputType) const {
802
  // The MSVC version doesn't care about the architecture, even though it
803
  // may look at the triple internally.
804
9.07k
  VersionTuple MSVT = computeMSVCVersion(/*D=*/nullptr, Args);
805
9.07k
  MSVT = VersionTuple(MSVT.getMajor(), MSVT.getMinor().value_or(0),
806
9.07k
                      MSVT.getSubminor().value_or(0));
807
808
  // For the rest of the triple, however, a computed architecture name may
809
  // be needed.
810
9.07k
  llvm::Triple Triple(ToolChain::ComputeEffectiveClangTriple(Args, InputType));
811
9.07k
  if (Triple.getEnvironment() == llvm::Triple::MSVC) {
812
9.06k
    StringRef ObjFmt = Triple.getEnvironmentName().split('-').second;
813
9.06k
    if (ObjFmt.empty())
814
9.06k
      Triple.setEnvironmentName((Twine("msvc") + MSVT.getAsString()).str());
815
18.4E
    else
816
18.4E
      Triple.setEnvironmentName(
817
18.4E
          (Twine("msvc") + MSVT.getAsString() + Twine('-') + ObjFmt).str());
818
9.06k
  }
819
9.07k
  return Triple.getTriple();
820
9.07k
}
821
822
9.92k
SanitizerMask MSVCToolChain::getSupportedSanitizers() const {
823
9.92k
  SanitizerMask Res = ToolChain::getSupportedSanitizers();
824
9.92k
  Res |= SanitizerKind::Address;
825
9.92k
  Res |= SanitizerKind::PointerCompare;
826
9.92k
  Res |= SanitizerKind::PointerSubtract;
827
9.92k
  Res |= SanitizerKind::Fuzzer;
828
9.92k
  Res |= SanitizerKind::FuzzerNoLink;
829
9.92k
  Res &= ~SanitizerKind::CFIMFCall;
830
9.92k
  return Res;
831
9.92k
}
832
833
static void TranslateOptArg(Arg *A, llvm::opt::DerivedArgList &DAL,
834
                            bool SupportsForcingFramePointer,
835
31
                            const char *ExpandChar, const OptTable &Opts) {
836
31
  assert(A->getOption().matches(options::OPT__SLASH_O));
837
838
31
  StringRef OptStr = A->getValue();
839
68
  for (size_t I = 0, E = OptStr.size(); I != E; 
++I37
) {
840
37
    const char &OptChar = *(OptStr.data() + I);
841
37
    switch (OptChar) {
842
3
    default:
843
3
      break;
844
3
    case '1':
845
9
    case '2':
846
11
    case 'x':
847
14
    case 'd':
848
      // Ignore /O[12xd] flags that aren't the last one on the command line.
849
      // Only the last one gets expanded.
850
14
      if (&OptChar != ExpandChar) {
851
0
        A->claim();
852
0
        break;
853
0
      }
854
14
      if (OptChar == 'd') {
855
3
        DAL.AddFlagArg(A, Opts.getOption(options::OPT_O0));
856
11
      } else {
857
11
        if (OptChar == '1') {
858
1
          DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
859
10
        } else if (OptChar == '2' || 
OptChar == 'x'2
) {
860
10
          DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin));
861
10
          DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
862
10
        }
863
11
        if (SupportsForcingFramePointer &&
864
11
            
!DAL.hasArgNoClaim(options::OPT_fno_omit_frame_pointer)6
)
865
4
          DAL.AddFlagArg(A, Opts.getOption(options::OPT_fomit_frame_pointer));
866
11
        if (OptChar == '1' || 
OptChar == '2'10
)
867
9
          DAL.AddFlagArg(A, Opts.getOption(options::OPT_ffunction_sections));
868
11
      }
869
14
      break;
870
6
    case 'b':
871
6
      if (I + 1 != E && isdigit(OptStr[I + 1])) {
872
6
        switch (OptStr[I + 1]) {
873
1
        case '0':
874
1
          DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_inline));
875
1
          break;
876
2
        case '1':
877
2
          DAL.AddFlagArg(A, Opts.getOption(options::OPT_finline_hint_functions));
878
2
          break;
879
3
        case '2':
880
3
          DAL.AddFlagArg(A, Opts.getOption(options::OPT_finline_functions));
881
3
          break;
882
6
        }
883
6
        ++I;
884
6
      }
885
6
      break;
886
6
    case 'g':
887
1
      A->claim();
888
1
      break;
889
3
    case 'i':
890
3
      if (I + 1 != E && 
OptStr[I + 1] == '-'2
) {
891
2
        ++I;
892
2
        DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_builtin));
893
2
      } else {
894
1
        DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin));
895
1
      }
896
3
      break;
897
3
    case 's':
898
3
      DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
899
3
      break;
900
2
    case 't':
901
2
      DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
902
2
      break;
903
5
    case 'y': {
904
5
      bool OmitFramePointer = true;
905
5
      if (I + 1 != E && 
OptStr[I + 1] == '-'4
) {
906
4
        OmitFramePointer = false;
907
4
        ++I;
908
4
      }
909
5
      if (SupportsForcingFramePointer) {
910
4
        if (OmitFramePointer)
911
0
          DAL.AddFlagArg(A,
912
0
                         Opts.getOption(options::OPT_fomit_frame_pointer));
913
4
        else
914
4
          DAL.AddFlagArg(
915
4
              A, Opts.getOption(options::OPT_fno_omit_frame_pointer));
916
4
      } else {
917
        // Don't warn about /Oy- in x86-64 builds (where
918
        // SupportsForcingFramePointer is false).  The flag having no effect
919
        // there is a compiler-internal optimization, and people shouldn't have
920
        // to special-case their build files for x86-64 clang-cl.
921
1
        A->claim();
922
1
      }
923
5
      break;
924
6
    }
925
37
    }
926
37
  }
927
31
}
928
929
static void TranslateDArg(Arg *A, llvm::opt::DerivedArgList &DAL,
930
35
                          const OptTable &Opts) {
931
35
  assert(A->getOption().matches(options::OPT_D));
932
933
35
  StringRef Val = A->getValue();
934
35
  size_t Hash = Val.find('#');
935
35
  if (Hash == StringRef::npos || 
Hash > Val.find('=')4
) {
936
32
    DAL.append(A);
937
32
    return;
938
32
  }
939
940
3
  std::string NewVal = std::string(Val);
941
3
  NewVal[Hash] = '=';
942
3
  DAL.AddJoinedArg(A, Opts.getOption(options::OPT_D), NewVal);
943
3
}
944
945
static void TranslatePermissive(Arg *A, llvm::opt::DerivedArgList &DAL,
946
2
                                const OptTable &Opts) {
947
2
  DAL.AddFlagArg(A, Opts.getOption(options::OPT__SLASH_Zc_twoPhase_));
948
2
  DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_operator_names));
949
2
}
950
951
static void TranslatePermissiveMinus(Arg *A, llvm::opt::DerivedArgList &DAL,
952
3
                                     const OptTable &Opts) {
953
3
  DAL.AddFlagArg(A, Opts.getOption(options::OPT__SLASH_Zc_twoPhase));
954
3
  DAL.AddFlagArg(A, Opts.getOption(options::OPT_foperator_names));
955
3
}
956
957
llvm::opt::DerivedArgList *
958
MSVCToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
959
                             StringRef BoundArch,
960
8.59k
                             Action::OffloadKind OFK) const {
961
8.59k
  DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
962
8.59k
  const OptTable &Opts = getDriver().getOpts();
963
964
  // /Oy and /Oy- don't have an effect on X86-64
965
8.59k
  bool SupportsForcingFramePointer = getArch() != llvm::Triple::x86_64;
966
967
  // The -O[12xd] flag actually expands to several flags.  We must desugar the
968
  // flags so that options embedded can be negated.  For example, the '-O2' flag
969
  // enables '-Oy'.  Expanding '-O2' into its constituent flags allows us to
970
  // correctly handle '-O2 -Oy-' where the trailing '-Oy-' disables a single
971
  // aspect of '-O2'.
972
  //
973
  // Note that this expansion logic only applies to the *last* of '[12xd]'.
974
975
  // First step is to search for the character we'd like to expand.
976
8.59k
  const char *ExpandChar = nullptr;
977
8.59k
  for (Arg *A : Args.filtered(options::OPT__SLASH_O)) {
978
31
    StringRef OptStr = A->getValue();
979
80
    for (size_t I = 0, E = OptStr.size(); I != E; 
++I49
) {
980
49
      char OptChar = OptStr[I];
981
49
      char PrevChar = I > 0 ? 
OptStr[I - 1]18
:
'0'31
;
982
49
      if (PrevChar == 'b') {
983
        // OptChar does not expand; it's an argument to the previous char.
984
6
        continue;
985
6
      }
986
43
      if (OptChar == '1' || 
OptChar == '2'42
||
OptChar == 'x'34
||
OptChar == 'd'32
)
987
14
        ExpandChar = OptStr.data() + I;
988
43
    }
989
31
  }
990
991
86.9k
  for (Arg *A : Args) {
992
86.9k
    if (A->getOption().matches(options::OPT__SLASH_O)) {
993
      // The -O flag actually takes an amalgam of other options.  For example,
994
      // '/Ogyb2' is equivalent to '/Og' '/Oy' '/Ob2'.
995
31
      TranslateOptArg(A, *DAL, SupportsForcingFramePointer, ExpandChar, Opts);
996
86.9k
    } else if (A->getOption().matches(options::OPT_D)) {
997
      // Translate -Dfoo#bar into -Dfoo=bar.
998
35
      TranslateDArg(A, *DAL, Opts);
999
86.9k
    } else if (A->getOption().matches(options::OPT__SLASH_permissive)) {
1000
      // Expand /permissive
1001
2
      TranslatePermissive(A, *DAL, Opts);
1002
86.9k
    } else if (A->getOption().matches(options::OPT__SLASH_permissive_)) {
1003
      // Expand /permissive-
1004
3
      TranslatePermissiveMinus(A, *DAL, Opts);
1005
86.9k
    } else if (OFK != Action::OFK_HIP) {
1006
      // HIP Toolchain translates input args by itself.
1007
86.6k
      DAL->append(A);
1008
86.6k
    }
1009
86.9k
  }
1010
1011
8.59k
  return DAL;
1012
8.59k
}
1013
1014
void MSVCToolChain::addClangTargetOptions(
1015
    const ArgList &DriverArgs, ArgStringList &CC1Args,
1016
8.61k
    Action::OffloadKind DeviceOffloadKind) const {
1017
  // MSVC STL kindly allows removing all usages of typeid by defining
1018
  // _HAS_STATIC_RTTI to 0. Do so, when compiling with -fno-rtti
1019
8.61k
  if (DriverArgs.hasFlag(options::OPT_fno_rtti, options::OPT_frtti,
1020
8.61k
                         /*Default=*/false))
1021
1
    CC1Args.push_back("-D_HAS_STATIC_RTTI=0");
1022
8.61k
}