Coverage Report

Created: 2020-02-15 09:57

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