1 //===--- ToolChains.cpp - ToolChain Implementations -----------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "ToolChains.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 "llvm/ADT/StringExtras.h"
19 #include "llvm/Config/llvm-config.h"
20 #include "llvm/Option/Arg.h"
21 #include "llvm/Option/ArgList.h"
22 #include "llvm/Support/ConvertUTF.h"
23 #include "llvm/Support/ErrorHandling.h"
24 #include "llvm/Support/FileSystem.h"
25 #include "llvm/Support/Process.h"
28 // Include the necessary headers to interface with the Windows registry and
30 #if defined(LLVM_ON_WIN32)
35 #define WIN32_LEAN_AND_MEAN
43 using namespace clang::driver;
44 using namespace clang::driver::toolchains;
45 using namespace clang;
46 using namespace llvm::opt;
48 MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple& Triple,
50 : ToolChain(D, Triple, Args) {
51 getProgramPaths().push_back(getDriver().getInstalledDir());
52 if (getDriver().getInstalledDir() != getDriver().Dir)
53 getProgramPaths().push_back(getDriver().Dir);
56 Tool *MSVCToolChain::buildLinker() const {
57 return new tools::visualstudio::Linker(*this);
60 Tool *MSVCToolChain::buildAssembler() const {
61 if (getTriple().isOSBinFormatMachO())
62 return new tools::darwin::Assembler(*this);
63 getDriver().Diag(clang::diag::err_no_external_assembler);
67 bool MSVCToolChain::IsIntegratedAssemblerDefault() const {
71 bool MSVCToolChain::IsUnwindTablesDefault() const {
72 // Emit unwind tables by default on Win64. All non-x86_32 Windows platforms
73 // such as ARM and PPC actually require unwind tables, but LLVM doesn't know
74 // how to generate them yet.
76 // Don't emit unwind tables by default for MachO targets.
77 if (getTriple().isOSBinFormatMachO())
80 return getArch() == llvm::Triple::x86_64;
83 bool MSVCToolChain::isPICDefault() const {
84 return getArch() == llvm::Triple::x86_64;
87 bool MSVCToolChain::isPIEDefault() const {
91 bool MSVCToolChain::isPICDefaultForced() const {
92 return getArch() == llvm::Triple::x86_64;
96 static bool readFullStringValue(HKEY hkey, const char *valueName,
98 std::wstring WideValueName;
99 if (!llvm::ConvertUTF8toWide(valueName, WideValueName))
105 // First just query for the required size.
106 result = RegQueryValueExW(hkey, WideValueName.c_str(), NULL, &type, NULL,
108 if (result != ERROR_SUCCESS || type != REG_SZ || !valueSize)
110 std::vector<BYTE> buffer(valueSize);
111 result = RegQueryValueExW(hkey, WideValueName.c_str(), NULL, NULL, &buffer[0],
113 if (result == ERROR_SUCCESS) {
114 std::wstring WideValue(reinterpret_cast<const wchar_t *>(buffer.data()),
115 valueSize / sizeof(wchar_t));
116 // The destination buffer must be empty as an invariant of the conversion
117 // function; but this function is sometimes called in a loop that passes in
118 // the same buffer, however. Simply clear it out so we can overwrite it.
120 return llvm::convertWideToUTF8(WideValue, value);
126 /// \brief Read registry string.
127 /// This also supports a means to look for high-versioned keys by use
128 /// of a $VERSION placeholder in the key path.
129 /// $VERSION in the key path is a placeholder for the version number,
130 /// causing the highest value path to be searched for and used.
131 /// I.e. "SOFTWARE\\Microsoft\\VisualStudio\\$VERSION".
132 /// There can be additional characters in the component. Only the numeric
133 /// characters are compared. This function only searches HKLM.
134 static bool getSystemRegistryString(const char *keyPath, const char *valueName,
135 std::string &value, std::string *phValue) {
139 HKEY hRootKey = HKEY_LOCAL_MACHINE;
142 bool returnValue = false;
144 const char *placeHolder = strstr(keyPath, "$VERSION");
145 std::string bestName;
146 // If we have a $VERSION placeholder, do the highest-version search.
148 const char *keyEnd = placeHolder - 1;
149 const char *nextKey = placeHolder;
150 // Find end of previous key.
151 while ((keyEnd > keyPath) && (*keyEnd != '\\'))
153 // Find end of key containing $VERSION.
154 while (*nextKey && (*nextKey != '\\'))
156 size_t partialKeyLength = keyEnd - keyPath;
157 char partialKey[256];
158 if (partialKeyLength >= sizeof(partialKey))
159 partialKeyLength = sizeof(partialKey) - 1;
160 strncpy(partialKey, keyPath, partialKeyLength);
161 partialKey[partialKeyLength] = '\0';
163 lResult = RegOpenKeyExA(hRootKey, partialKey, 0, KEY_READ | KEY_WOW64_32KEY,
165 if (lResult == ERROR_SUCCESS) {
167 double bestValue = 0.0;
168 DWORD index, size = sizeof(keyName) - 1;
169 for (index = 0; RegEnumKeyExA(hTopKey, index, keyName, &size, NULL, NULL,
170 NULL, NULL) == ERROR_SUCCESS;
172 const char *sp = keyName;
173 while (*sp && !isDigit(*sp))
177 const char *ep = sp + 1;
178 while (*ep && (isDigit(*ep) || (*ep == '.')))
181 strncpy(numBuf, sp, sizeof(numBuf) - 1);
182 numBuf[sizeof(numBuf) - 1] = '\0';
183 double dvalue = strtod(numBuf, NULL);
184 if (dvalue > bestValue) {
185 // Test that InstallDir is indeed there before keeping this index.
186 // Open the chosen key path remainder.
188 // Append rest of key.
189 bestName.append(nextKey);
190 lResult = RegOpenKeyExA(hTopKey, bestName.c_str(), 0,
191 KEY_READ | KEY_WOW64_32KEY, &hKey);
192 if (lResult == ERROR_SUCCESS) {
193 lResult = readFullStringValue(hKey, valueName, value);
194 if (lResult == ERROR_SUCCESS) {
203 size = sizeof(keyName) - 1;
205 RegCloseKey(hTopKey);
209 RegOpenKeyExA(hRootKey, keyPath, 0, KEY_READ | KEY_WOW64_32KEY, &hKey);
210 if (lResult == ERROR_SUCCESS) {
211 lResult = readFullStringValue(hKey, valueName, value);
212 if (lResult == ERROR_SUCCESS)
223 // Convert LLVM's ArchType
224 // to the corresponding name of Windows SDK libraries subfolder
225 static StringRef getWindowsSDKArch(llvm::Triple::ArchType Arch) {
227 case llvm::Triple::x86:
229 case llvm::Triple::x86_64:
231 case llvm::Triple::arm:
238 // Find the most recent version of Universal CRT or Windows 10 SDK.
239 // vcvarsqueryregistry.bat from Visual Studio 2015 sorts entries in the include
240 // directory by name and uses the last one of the list.
241 // So we compare entry names lexicographically to find the greatest one.
242 static bool getWindows10SDKVersion(const std::string &SDKPath,
243 std::string &SDKVersion) {
247 llvm::SmallString<128> IncludePath(SDKPath);
248 llvm::sys::path::append(IncludePath, "Include");
249 for (llvm::sys::fs::directory_iterator DirIt(IncludePath, EC), DirEnd;
250 DirIt != DirEnd && !EC; DirIt.increment(EC)) {
251 if (!llvm::sys::fs::is_directory(DirIt->path()))
253 StringRef CandidateName = llvm::sys::path::filename(DirIt->path());
254 // If WDK is installed, there could be subfolders like "wdf" in the
255 // "Include" directory.
256 // Allow only directories which names start with "10.".
257 if (!CandidateName.startswith("10."))
259 if (CandidateName > SDKVersion)
260 SDKVersion = CandidateName;
263 return !SDKVersion.empty();
266 /// \brief Get Windows SDK installation directory.
267 bool MSVCToolChain::getWindowsSDKDir(std::string &Path, int &Major,
268 std::string &WindowsSDKIncludeVersion,
269 std::string &WindowsSDKLibVersion) const {
270 std::string RegistrySDKVersion;
271 // Try the Windows registry.
272 if (!getSystemRegistryString(
273 "SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
274 "InstallationFolder", Path, &RegistrySDKVersion))
276 if (Path.empty() || RegistrySDKVersion.empty())
279 WindowsSDKIncludeVersion.clear();
280 WindowsSDKLibVersion.clear();
282 std::sscanf(RegistrySDKVersion.c_str(), "v%d.", &Major);
286 // Windows SDK 8.x installs libraries in a folder whose names depend on the
287 // version of the OS you're targeting. By default choose the newest, which
288 // usually corresponds to the version of the OS you've installed the SDK on.
289 const char *Tests[] = {"winv6.3", "win8", "win7"};
290 for (const char *Test : Tests) {
291 llvm::SmallString<128> TestPath(Path);
292 llvm::sys::path::append(TestPath, "Lib", Test);
293 if (llvm::sys::fs::exists(TestPath.c_str())) {
294 WindowsSDKLibVersion = Test;
298 return !WindowsSDKLibVersion.empty();
301 if (!getWindows10SDKVersion(Path, WindowsSDKIncludeVersion))
303 WindowsSDKLibVersion = WindowsSDKIncludeVersion;
306 // Unsupported SDK version
310 // Gets the library path required to link against the Windows SDK.
311 bool MSVCToolChain::getWindowsSDKLibraryPath(std::string &path) const {
314 std::string windowsSDKIncludeVersion;
315 std::string windowsSDKLibVersion;
318 if (!getWindowsSDKDir(sdkPath, sdkMajor, windowsSDKIncludeVersion,
319 windowsSDKLibVersion))
322 llvm::SmallString<128> libPath(sdkPath);
323 llvm::sys::path::append(libPath, "Lib");
326 // In Windows SDK 7.x, x86 libraries are directly in the Lib folder.
327 case llvm::Triple::x86:
329 case llvm::Triple::x86_64:
330 llvm::sys::path::append(libPath, "x64");
332 case llvm::Triple::arm:
333 // It is not necessary to link against Windows SDK 7.x when targeting ARM.
339 const StringRef archName = getWindowsSDKArch(getArch());
340 if (archName.empty())
342 llvm::sys::path::append(libPath, windowsSDKLibVersion, "um", archName);
345 path = libPath.str();
349 // Check if the Include path of a specified version of Visual Studio contains
350 // specific header files. If not, they are probably shipped with Universal CRT.
351 bool clang::driver::toolchains::MSVCToolChain::useUniversalCRT(
352 std::string &VisualStudioDir) const {
353 llvm::SmallString<128> TestPath(VisualStudioDir);
354 llvm::sys::path::append(TestPath, "VC\\include\\stdlib.h");
356 return !llvm::sys::fs::exists(TestPath);
359 bool MSVCToolChain::getUniversalCRTSdkDir(std::string &Path,
360 std::string &UCRTVersion) const {
361 // vcvarsqueryregistry.bat for Visual Studio 2015 queries the registry
362 // for the specific key "KitsRoot10". So do we.
363 if (!getSystemRegistryString(
364 "SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots", "KitsRoot10",
368 return getWindows10SDKVersion(Path, UCRTVersion);
371 bool MSVCToolChain::getUniversalCRTLibraryPath(std::string &Path) const {
372 std::string UniversalCRTSdkPath;
373 std::string UCRTVersion;
376 if (!getUniversalCRTSdkDir(UniversalCRTSdkPath, UCRTVersion))
379 StringRef ArchName = getWindowsSDKArch(getArch());
380 if (ArchName.empty())
383 llvm::SmallString<128> LibPath(UniversalCRTSdkPath);
384 llvm::sys::path::append(LibPath, "Lib", UCRTVersion, "ucrt", ArchName);
386 Path = LibPath.str();
390 // Get the location to use for Visual Studio binaries. The location priority
391 // is: %VCINSTALLDIR% > %PATH% > newest copy of Visual Studio installed on
392 // system (as reported by the registry).
393 bool MSVCToolChain::getVisualStudioBinariesFolder(const char *clangProgramPath,
394 std::string &path) const {
397 SmallString<128> BinDir;
399 // First check the environment variables that vsvars32.bat sets.
400 llvm::Optional<std::string> VcInstallDir =
401 llvm::sys::Process::GetEnv("VCINSTALLDIR");
402 if (VcInstallDir.hasValue()) {
403 BinDir = VcInstallDir.getValue();
404 llvm::sys::path::append(BinDir, "bin");
406 // Next walk the PATH, trying to find a cl.exe in the path. If we find one,
407 // use that. However, make sure it's not clang's cl.exe.
408 llvm::Optional<std::string> OptPath = llvm::sys::Process::GetEnv("PATH");
409 if (OptPath.hasValue()) {
410 const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'};
411 SmallVector<StringRef, 8> PathSegments;
412 llvm::SplitString(OptPath.getValue(), PathSegments, EnvPathSeparatorStr);
414 for (StringRef PathSegment : PathSegments) {
415 if (PathSegment.empty())
418 SmallString<128> FilePath(PathSegment);
419 llvm::sys::path::append(FilePath, "cl.exe");
420 // Checking if cl.exe exists is a small optimization over calling
421 // can_execute, which really only checks for existence but will also do
422 // extra checks for cl.exe.exe. These add up when walking a long path.
423 if (llvm::sys::fs::exists(FilePath.c_str()) &&
424 !llvm::sys::fs::equivalent(FilePath.c_str(), clangProgramPath)) {
425 // If we found it on the PATH, use it exactly as is with no
433 std::string installDir;
434 // With no VCINSTALLDIR and nothing on the PATH, if we can't find it in the
435 // registry then we have no choice but to fail.
436 if (!getVisualStudioInstallDir(installDir))
439 // Regardless of what binary we're ultimately trying to find, we make sure
440 // that this is a Visual Studio directory by checking for cl.exe. We use
441 // cl.exe instead of other binaries like link.exe because programs such as
442 // GnuWin32 also have a utility called link.exe, so cl.exe is the least
445 llvm::sys::path::append(BinDir, "VC", "bin");
446 SmallString<128> ClPath(BinDir);
447 llvm::sys::path::append(ClPath, "cl.exe");
449 if (!llvm::sys::fs::can_execute(ClPath.c_str()))
457 case llvm::Triple::x86:
459 case llvm::Triple::x86_64:
460 llvm::sys::path::append(BinDir, "amd64");
462 case llvm::Triple::arm:
463 llvm::sys::path::append(BinDir, "arm");
466 // Whatever this is, Visual Studio doesn't have a toolchain for it.
473 VersionTuple MSVCToolChain::getMSVCVersionFromExe() const {
474 VersionTuple Version;
477 if (!getVisualStudioBinariesFolder("", BinPath))
479 SmallString<128> ClExe(BinPath);
480 llvm::sys::path::append(ClExe, "cl.exe");
482 std::wstring ClExeWide;
483 if (!llvm::ConvertUTF8toWide(ClExe.c_str(), ClExeWide))
486 const DWORD VersionSize = ::GetFileVersionInfoSizeW(ClExeWide.c_str(),
488 if (VersionSize == 0)
491 SmallVector<uint8_t, 4 * 1024> VersionBlock(VersionSize);
492 if (!::GetFileVersionInfoW(ClExeWide.c_str(), 0, VersionSize,
493 VersionBlock.data()))
496 VS_FIXEDFILEINFO *FileInfo = nullptr;
497 UINT FileInfoSize = 0;
498 if (!::VerQueryValueW(VersionBlock.data(), L"\\",
499 reinterpret_cast<LPVOID *>(&FileInfo), &FileInfoSize) ||
500 FileInfoSize < sizeof(*FileInfo))
503 const unsigned Major = (FileInfo->dwFileVersionMS >> 16) & 0xFFFF;
504 const unsigned Minor = (FileInfo->dwFileVersionMS ) & 0xFFFF;
505 const unsigned Micro = (FileInfo->dwFileVersionLS >> 16) & 0xFFFF;
507 Version = VersionTuple(Major, Minor, Micro);
512 // Get Visual Studio installation directory.
513 bool MSVCToolChain::getVisualStudioInstallDir(std::string &path) const {
514 // First check the environment variables that vsvars32.bat sets.
515 const char *vcinstalldir = getenv("VCINSTALLDIR");
518 path = path.substr(0, path.find("\\VC"));
522 std::string vsIDEInstallDir;
523 std::string vsExpressIDEInstallDir;
524 // Then try the windows registry.
526 getSystemRegistryString("SOFTWARE\\Microsoft\\VisualStudio\\$VERSION",
527 "InstallDir", vsIDEInstallDir, nullptr);
528 if (hasVCDir && !vsIDEInstallDir.empty()) {
529 path = vsIDEInstallDir.substr(0, vsIDEInstallDir.find("\\Common7\\IDE"));
533 bool hasVCExpressDir =
534 getSystemRegistryString("SOFTWARE\\Microsoft\\VCExpress\\$VERSION",
535 "InstallDir", vsExpressIDEInstallDir, nullptr);
536 if (hasVCExpressDir && !vsExpressIDEInstallDir.empty()) {
537 path = vsExpressIDEInstallDir.substr(
538 0, vsIDEInstallDir.find("\\Common7\\IDE"));
542 // Try the environment.
543 const char *vs120comntools = getenv("VS120COMNTOOLS");
544 const char *vs100comntools = getenv("VS100COMNTOOLS");
545 const char *vs90comntools = getenv("VS90COMNTOOLS");
546 const char *vs80comntools = getenv("VS80COMNTOOLS");
548 const char *vscomntools = nullptr;
550 // Find any version we can
552 vscomntools = vs120comntools;
553 else if (vs100comntools)
554 vscomntools = vs100comntools;
555 else if (vs90comntools)
556 vscomntools = vs90comntools;
557 else if (vs80comntools)
558 vscomntools = vs80comntools;
560 if (vscomntools && *vscomntools) {
561 const char *p = strstr(vscomntools, "\\Common7\\Tools");
562 path = p ? std::string(vscomntools, p) : vscomntools;
568 void MSVCToolChain::AddSystemIncludeWithSubfolder(
569 const ArgList &DriverArgs, ArgStringList &CC1Args,
570 const std::string &folder, const Twine &subfolder1, const Twine &subfolder2,
571 const Twine &subfolder3) const {
572 llvm::SmallString<128> path(folder);
573 llvm::sys::path::append(path, subfolder1, subfolder2, subfolder3);
574 addSystemInclude(DriverArgs, CC1Args, path);
577 void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
578 ArgStringList &CC1Args) const {
579 if (DriverArgs.hasArg(options::OPT_nostdinc))
582 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
583 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, getDriver().ResourceDir,
587 // Add %INCLUDE%-like directories from the -imsvc flag.
588 for (const auto &Path : DriverArgs.getAllArgValues(options::OPT__SLASH_imsvc))
589 addSystemInclude(DriverArgs, CC1Args, Path);
591 if (DriverArgs.hasArg(options::OPT_nostdlibinc))
594 // Honor %INCLUDE%. It should know essential search paths with vcvarsall.bat.
595 if (const char *cl_include_dir = getenv("INCLUDE")) {
596 SmallVector<StringRef, 8> Dirs;
597 StringRef(cl_include_dir)
598 .split(Dirs, ";", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
599 for (StringRef Dir : Dirs)
600 addSystemInclude(DriverArgs, CC1Args, Dir);
607 // When built with access to the proper Windows APIs, try to actually find
608 // the correct include paths first.
609 if (getVisualStudioInstallDir(VSDir)) {
610 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, VSDir, "VC\\include");
612 if (useUniversalCRT(VSDir)) {
613 std::string UniversalCRTSdkPath;
614 std::string UCRTVersion;
615 if (getUniversalCRTSdkDir(UniversalCRTSdkPath, UCRTVersion)) {
616 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, UniversalCRTSdkPath,
617 "Include", UCRTVersion, "ucrt");
621 std::string WindowsSDKDir;
623 std::string windowsSDKIncludeVersion;
624 std::string windowsSDKLibVersion;
625 if (getWindowsSDKDir(WindowsSDKDir, major, windowsSDKIncludeVersion,
626 windowsSDKLibVersion)) {
628 // Note: windowsSDKIncludeVersion is empty for SDKs prior to v10.
629 // Anyway, llvm::sys::path::append is able to manage it.
630 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
631 "include", windowsSDKIncludeVersion,
633 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
634 "include", windowsSDKIncludeVersion,
636 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
637 "include", windowsSDKIncludeVersion,
640 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
644 addSystemInclude(DriverArgs, CC1Args, VSDir);
649 // As a fallback, select default install paths.
650 // FIXME: Don't guess drives and paths like this on Windows.
651 const StringRef Paths[] = {
652 "C:/Program Files/Microsoft Visual Studio 10.0/VC/include",
653 "C:/Program Files/Microsoft Visual Studio 9.0/VC/include",
654 "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include",
655 "C:/Program Files/Microsoft Visual Studio 8/VC/include",
656 "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include"
658 addSystemIncludes(DriverArgs, CC1Args, Paths);
661 void MSVCToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
662 ArgStringList &CC1Args) const {
663 // FIXME: There should probably be logic here to find libc++ on Windows.
667 MSVCToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
668 types::ID InputType) const {
669 std::string TripleStr =
670 ToolChain::ComputeEffectiveClangTriple(Args, InputType);
671 llvm::Triple Triple(TripleStr);
673 tools::visualstudio::getMSVCVersion(/*D=*/nullptr, *this, Triple, Args,
674 /*IsWindowsMSVC=*/true);
678 MSVT = VersionTuple(MSVT.getMajor(), MSVT.getMinor().getValueOr(0),
679 MSVT.getSubminor().getValueOr(0));
681 if (Triple.getEnvironment() == llvm::Triple::MSVC) {
682 StringRef ObjFmt = Triple.getEnvironmentName().split('-').second;
684 Triple.setEnvironmentName((Twine("msvc") + MSVT.getAsString()).str());
686 Triple.setEnvironmentName(
687 (Twine("msvc") + MSVT.getAsString() + Twine('-') + ObjFmt).str());
689 return Triple.getTriple();
692 SanitizerMask MSVCToolChain::getSupportedSanitizers() const {
693 SanitizerMask Res = ToolChain::getSupportedSanitizers();
694 Res |= SanitizerKind::Address;
698 static void TranslateOptArg(Arg *A, llvm::opt::DerivedArgList &DAL,
699 bool SupportsForcingFramePointer,
700 const char *ExpandChar, const OptTable &Opts) {
701 assert(A->getOption().matches(options::OPT__SLASH_O));
703 StringRef OptStr = A->getValue();
704 for (size_t I = 0, E = OptStr.size(); I != E; ++I) {
705 const char &OptChar = *(OptStr.data() + I);
713 if (&OptChar == ExpandChar) {
714 if (OptChar == 'd') {
715 DAL.AddFlagArg(A, Opts.getOption(options::OPT_O0));
717 if (OptChar == '1') {
718 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
719 } else if (OptChar == '2' || OptChar == 'x') {
720 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin));
721 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
723 if (SupportsForcingFramePointer &&
724 !DAL.hasArgNoClaim(options::OPT_fno_omit_frame_pointer))
726 Opts.getOption(options::OPT_fomit_frame_pointer));
727 if (OptChar == '1' || OptChar == '2')
729 Opts.getOption(options::OPT_ffunction_sections));
734 if (I + 1 != E && isdigit(OptStr[I + 1])) {
735 switch (OptStr[I + 1]) {
737 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_inline));
740 DAL.AddFlagArg(A, Opts.getOption(options::OPT_finline_hint_functions));
743 DAL.AddFlagArg(A, Opts.getOption(options::OPT_finline_functions));
752 if (I + 1 != E && OptStr[I + 1] == '-') {
754 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_builtin));
756 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin));
760 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
763 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
766 bool OmitFramePointer = true;
767 if (I + 1 != E && OptStr[I + 1] == '-') {
768 OmitFramePointer = false;
771 if (SupportsForcingFramePointer) {
772 if (OmitFramePointer)
774 Opts.getOption(options::OPT_fomit_frame_pointer));
777 A, Opts.getOption(options::OPT_fno_omit_frame_pointer));
779 // Don't warn about /Oy- in 64-bit builds (where
780 // SupportsForcingFramePointer is false). The flag having no effect
781 // there is a compiler-internal optimization, and people shouldn't have
782 // to special-case their build files for 64-bit clang-cl.
791 static void TranslateDArg(Arg *A, llvm::opt::DerivedArgList &DAL,
792 const OptTable &Opts) {
793 assert(A->getOption().matches(options::OPT_D));
795 StringRef Val = A->getValue();
796 size_t Hash = Val.find('#');
797 if (Hash == StringRef::npos || Hash > Val.find('=')) {
802 std::string NewVal = Val;
804 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_D), NewVal);
807 llvm::opt::DerivedArgList *
808 MSVCToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
809 const char *BoundArch) const {
810 DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
811 const OptTable &Opts = getDriver().getOpts();
813 // /Oy and /Oy- only has an effect under X86-32.
814 bool SupportsForcingFramePointer = getArch() == llvm::Triple::x86;
816 // The -O[12xd] flag actually expands to several flags. We must desugar the
817 // flags so that options embedded can be negated. For example, the '-O2' flag
818 // enables '-Oy'. Expanding '-O2' into its constituent flags allows us to
819 // correctly handle '-O2 -Oy-' where the trailing '-Oy-' disables a single
822 // Note that this expansion logic only applies to the *last* of '[12xd]'.
824 // First step is to search for the character we'd like to expand.
825 const char *ExpandChar = nullptr;
826 for (Arg *A : Args) {
827 if (!A->getOption().matches(options::OPT__SLASH_O))
829 StringRef OptStr = A->getValue();
830 for (size_t I = 0, E = OptStr.size(); I != E; ++I) {
831 char OptChar = OptStr[I];
832 char PrevChar = I > 0 ? OptStr[I - 1] : '0';
833 if (PrevChar == 'b') {
834 // OptChar does not expand; it's an argument to the previous char.
837 if (OptChar == '1' || OptChar == '2' || OptChar == 'x' || OptChar == 'd')
838 ExpandChar = OptStr.data() + I;
842 for (Arg *A : Args) {
843 if (A->getOption().matches(options::OPT__SLASH_O)) {
844 // The -O flag actually takes an amalgam of other options. For example,
845 // '/Ogyb2' is equivalent to '/Og' '/Oy' '/Ob2'.
846 TranslateOptArg(A, *DAL, SupportsForcingFramePointer, ExpandChar, Opts);
847 } else if (A->getOption().matches(options::OPT_D)) {
848 // Translate -Dfoo#bar into -Dfoo=bar.
849 TranslateDArg(A, *DAL, Opts);