Bug Summary

File:clang/lib/Driver/ToolChains/MSVC.cpp
Warning:line 1289, column 17
The left operand of '>=' is a garbage value

Annotated Source Code

Press '?' to see keyboard shortcuts

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