1 //===--- MinGW.cpp - MinGWToolChain Implementation ------------------------===//
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 "MinGW.h"
10 #include "InputInfo.h"
11 #include "CommonArgs.h"
12 #include "clang/Config/config.h"
13 #include "clang/Driver/Compilation.h"
14 #include "clang/Driver/Driver.h"
15 #include "clang/Driver/DriverDiagnostic.h"
16 #include "clang/Driver/Options.h"
17 #include "clang/Driver/SanitizerArgs.h"
18 #include "llvm/Option/ArgList.h"
19 #include "llvm/Support/FileSystem.h"
20 #include "llvm/Support/Path.h"
21 #include "llvm/Support/VirtualFileSystem.h"
22 #include <system_error>
23 
24 using namespace clang::diag;
25 using namespace clang::driver;
26 using namespace clang;
27 using namespace llvm::opt;
28 
29 /// MinGW Tools
30 void tools::MinGW::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
31                                            const InputInfo &Output,
32                                            const InputInfoList &Inputs,
33                                            const ArgList &Args,
34                                            const char *LinkingOutput) const {
35   claimNoWarnArgs(Args);
36   ArgStringList CmdArgs;
37 
38   if (getToolChain().getArch() == llvm::Triple::x86) {
39     CmdArgs.push_back("--32");
40   } else if (getToolChain().getArch() == llvm::Triple::x86_64) {
41     CmdArgs.push_back("--64");
42   }
43 
44   Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
45 
46   CmdArgs.push_back("-o");
47   CmdArgs.push_back(Output.getFilename());
48 
49   for (const auto &II : Inputs)
50     CmdArgs.push_back(II.getFilename());
51 
52   const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
53   C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
54 
55   if (Args.hasArg(options::OPT_gsplit_dwarf))
56     SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output,
57                    SplitDebugName(Args, Inputs[0], Output));
58 }
59 
60 void tools::MinGW::Linker::AddLibGCC(const ArgList &Args,
61                                      ArgStringList &CmdArgs) const {
62   if (Args.hasArg(options::OPT_mthreads))
63     CmdArgs.push_back("-lmingwthrd");
64   CmdArgs.push_back("-lmingw32");
65 
66   // Make use of compiler-rt if --rtlib option is used
67   ToolChain::RuntimeLibType RLT = getToolChain().GetRuntimeLibType(Args);
68   if (RLT == ToolChain::RLT_Libgcc) {
69     bool Static = Args.hasArg(options::OPT_static_libgcc) ||
70                   Args.hasArg(options::OPT_static);
71     bool Shared = Args.hasArg(options::OPT_shared);
72     bool CXX = getToolChain().getDriver().CCCIsCXX();
73 
74     if (Static || (!CXX && !Shared)) {
75       CmdArgs.push_back("-lgcc");
76       CmdArgs.push_back("-lgcc_eh");
77     } else {
78       CmdArgs.push_back("-lgcc_s");
79       CmdArgs.push_back("-lgcc");
80     }
81   } else {
82     AddRunTimeLibs(getToolChain(), getToolChain().getDriver(), CmdArgs, Args);
83   }
84 
85   CmdArgs.push_back("-lmoldname");
86   CmdArgs.push_back("-lmingwex");
87   for (auto Lib : Args.getAllArgValues(options::OPT_l))
88     if (StringRef(Lib).startswith("msvcr") || StringRef(Lib).startswith("ucrt"))
89       return;
90   CmdArgs.push_back("-lmsvcrt");
91 }
92 
93 void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
94                                         const InputInfo &Output,
95                                         const InputInfoList &Inputs,
96                                         const ArgList &Args,
97                                         const char *LinkingOutput) const {
98   const ToolChain &TC = getToolChain();
99   const Driver &D = TC.getDriver();
100   const SanitizerArgs &Sanitize = TC.getSanitizerArgs();
101 
102   ArgStringList CmdArgs;
103 
104   // Silence warning for "clang -g foo.o -o foo"
105   Args.ClaimAllArgs(options::OPT_g_Group);
106   // and "clang -emit-llvm foo.o -o foo"
107   Args.ClaimAllArgs(options::OPT_emit_llvm);
108   // and for "clang -w foo.o -o foo". Other warning options are already
109   // handled somewhere else.
110   Args.ClaimAllArgs(options::OPT_w);
111 
112   if (!D.SysRoot.empty())
113     CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
114 
115   if (Args.hasArg(options::OPT_s))
116     CmdArgs.push_back("-s");
117 
118   CmdArgs.push_back("-m");
119   switch (TC.getArch()) {
120   case llvm::Triple::x86:
121     CmdArgs.push_back("i386pe");
122     break;
123   case llvm::Triple::x86_64:
124     CmdArgs.push_back("i386pep");
125     break;
126   case llvm::Triple::arm:
127   case llvm::Triple::thumb:
128     // FIXME: this is incorrect for WinCE
129     CmdArgs.push_back("thumb2pe");
130     break;
131   case llvm::Triple::aarch64:
132     CmdArgs.push_back("arm64pe");
133     break;
134   default:
135     llvm_unreachable("Unsupported target architecture.");
136   }
137 
138   if (Args.hasArg(options::OPT_mwindows)) {
139     CmdArgs.push_back("--subsystem");
140     CmdArgs.push_back("windows");
141   } else if (Args.hasArg(options::OPT_mconsole)) {
142     CmdArgs.push_back("--subsystem");
143     CmdArgs.push_back("console");
144   }
145 
146   if (Args.hasArg(options::OPT_mdll))
147     CmdArgs.push_back("--dll");
148   else if (Args.hasArg(options::OPT_shared))
149     CmdArgs.push_back("--shared");
150   if (Args.hasArg(options::OPT_static))
151     CmdArgs.push_back("-Bstatic");
152   else
153     CmdArgs.push_back("-Bdynamic");
154   if (Args.hasArg(options::OPT_mdll) || Args.hasArg(options::OPT_shared)) {
155     CmdArgs.push_back("-e");
156     if (TC.getArch() == llvm::Triple::x86)
157       CmdArgs.push_back("_DllMainCRTStartup@12");
158     else
159       CmdArgs.push_back("DllMainCRTStartup");
160     CmdArgs.push_back("--enable-auto-image-base");
161   }
162 
163   CmdArgs.push_back("-o");
164   const char *OutputFile = Output.getFilename();
165   // GCC implicitly adds an .exe extension if it is given an output file name
166   // that lacks an extension. However, GCC only does this when actually
167   // running on windows, not when operating as a cross compiler. As some users
168   // have come to rely on this behaviour, try to replicate it.
169 #ifdef _WIN32
170   if (!llvm::sys::path::has_extension(OutputFile))
171     CmdArgs.push_back(Args.MakeArgString(Twine(OutputFile) + ".exe"));
172   else
173     CmdArgs.push_back(OutputFile);
174 #else
175   CmdArgs.push_back(OutputFile);
176 #endif
177 
178   Args.AddAllArgs(CmdArgs, options::OPT_e);
179   // FIXME: add -N, -n flags
180   Args.AddLastArg(CmdArgs, options::OPT_r);
181   Args.AddLastArg(CmdArgs, options::OPT_s);
182   Args.AddLastArg(CmdArgs, options::OPT_t);
183   Args.AddAllArgs(CmdArgs, options::OPT_u_Group);
184   Args.AddLastArg(CmdArgs, options::OPT_Z_Flag);
185 
186   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
187     if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_mdll)) {
188       CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("dllcrt2.o")));
189     } else {
190       if (Args.hasArg(options::OPT_municode))
191         CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt2u.o")));
192       else
193         CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt2.o")));
194     }
195     if (Args.hasArg(options::OPT_pg))
196       CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("gcrt2.o")));
197     CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtbegin.o")));
198   }
199 
200   Args.AddAllArgs(CmdArgs, options::OPT_L);
201   TC.AddFilePathLibArgs(Args, CmdArgs);
202 
203   // Add the compiler-rt library directories if they exist to help
204   // the linker find the various sanitizer, builtin, and profiling runtimes.
205   for (const auto &LibPath : TC.getLibraryPaths()) {
206     if (TC.getVFS().exists(LibPath))
207       CmdArgs.push_back(Args.MakeArgString("-L" + LibPath));
208   }
209   auto CRTPath = TC.getCompilerRTPath();
210   if (TC.getVFS().exists(CRTPath))
211     CmdArgs.push_back(Args.MakeArgString("-L" + CRTPath));
212 
213   AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
214 
215   // TODO: Add profile stuff here
216 
217   if (TC.ShouldLinkCXXStdlib(Args)) {
218     bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
219                                !Args.hasArg(options::OPT_static);
220     if (OnlyLibstdcxxStatic)
221       CmdArgs.push_back("-Bstatic");
222     TC.AddCXXStdlibLibArgs(Args, CmdArgs);
223     if (OnlyLibstdcxxStatic)
224       CmdArgs.push_back("-Bdynamic");
225   }
226 
227   bool HasWindowsApp = false;
228   for (auto Lib : Args.getAllArgValues(options::OPT_l)) {
229     if (Lib == "windowsapp") {
230       HasWindowsApp = true;
231       break;
232     }
233   }
234 
235   if (!Args.hasArg(options::OPT_nostdlib)) {
236     if (!Args.hasArg(options::OPT_nodefaultlibs)) {
237       if (Args.hasArg(options::OPT_static))
238         CmdArgs.push_back("--start-group");
239 
240       if (Args.hasArg(options::OPT_fstack_protector) ||
241           Args.hasArg(options::OPT_fstack_protector_strong) ||
242           Args.hasArg(options::OPT_fstack_protector_all)) {
243         CmdArgs.push_back("-lssp_nonshared");
244         CmdArgs.push_back("-lssp");
245       }
246 
247       if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
248                        options::OPT_fno_openmp, false)) {
249         switch (TC.getDriver().getOpenMPRuntime(Args)) {
250         case Driver::OMPRT_OMP:
251           CmdArgs.push_back("-lomp");
252           break;
253         case Driver::OMPRT_IOMP5:
254           CmdArgs.push_back("-liomp5md");
255           break;
256         case Driver::OMPRT_GOMP:
257           CmdArgs.push_back("-lgomp");
258           break;
259         case Driver::OMPRT_Unknown:
260           // Already diagnosed.
261           break;
262         }
263       }
264 
265       AddLibGCC(Args, CmdArgs);
266 
267       if (Args.hasArg(options::OPT_pg))
268         CmdArgs.push_back("-lgmon");
269 
270       if (Args.hasArg(options::OPT_pthread))
271         CmdArgs.push_back("-lpthread");
272 
273       if (Sanitize.needsAsanRt()) {
274         // MinGW always links against a shared MSVCRT.
275         CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dynamic",
276                                                     ToolChain::FT_Shared));
277         CmdArgs.push_back(
278             TC.getCompilerRTArgString(Args, "asan_dynamic_runtime_thunk"));
279         CmdArgs.push_back("--require-defined");
280         CmdArgs.push_back(TC.getArch() == llvm::Triple::x86
281                               ? "___asan_seh_interceptor"
282                               : "__asan_seh_interceptor");
283         // Make sure the linker consider all object files from the dynamic
284         // runtime thunk.
285         CmdArgs.push_back("--whole-archive");
286         CmdArgs.push_back(
287             TC.getCompilerRTArgString(Args, "asan_dynamic_runtime_thunk"));
288         CmdArgs.push_back("--no-whole-archive");
289       }
290 
291       TC.addProfileRTLibs(Args, CmdArgs);
292 
293       if (!HasWindowsApp) {
294         // Add system libraries. If linking to libwindowsapp.a, that import
295         // library replaces all these and we shouldn't accidentally try to
296         // link to the normal desktop mode dlls.
297         if (Args.hasArg(options::OPT_mwindows)) {
298           CmdArgs.push_back("-lgdi32");
299           CmdArgs.push_back("-lcomdlg32");
300         }
301         CmdArgs.push_back("-ladvapi32");
302         CmdArgs.push_back("-lshell32");
303         CmdArgs.push_back("-luser32");
304         CmdArgs.push_back("-lkernel32");
305       }
306 
307       if (Args.hasArg(options::OPT_static))
308         CmdArgs.push_back("--end-group");
309       else
310         AddLibGCC(Args, CmdArgs);
311     }
312 
313     if (!Args.hasArg(options::OPT_nostartfiles)) {
314       // Add crtfastmath.o if available and fast math is enabled.
315       TC.addFastMathRuntimeIfAvailable(Args, CmdArgs);
316 
317       CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtend.o")));
318     }
319   }
320   const char *Exec = Args.MakeArgString(TC.GetLinkerPath());
321   C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
322 }
323 
324 // Simplified from Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple.
325 static bool findGccVersion(StringRef LibDir, std::string &GccLibDir,
326                            std::string &Ver) {
327   auto Version = toolchains::Generic_GCC::GCCVersion::Parse("0.0.0");
328   std::error_code EC;
329   for (llvm::sys::fs::directory_iterator LI(LibDir, EC), LE; !EC && LI != LE;
330        LI = LI.increment(EC)) {
331     StringRef VersionText = llvm::sys::path::filename(LI->path());
332     auto CandidateVersion =
333         toolchains::Generic_GCC::GCCVersion::Parse(VersionText);
334     if (CandidateVersion.Major == -1)
335       continue;
336     if (CandidateVersion <= Version)
337       continue;
338     Ver = std::string(VersionText);
339     GccLibDir = LI->path();
340   }
341   return Ver.size();
342 }
343 
344 void toolchains::MinGW::findGccLibDir() {
345   llvm::SmallVector<llvm::SmallString<32>, 2> Archs;
346   Archs.emplace_back(getTriple().getArchName());
347   Archs[0] += "-w64-mingw32";
348   Archs.emplace_back("mingw32");
349   if (Arch.empty())
350     Arch = std::string(Archs[0].str());
351   // lib: Arch Linux, Ubuntu, Windows
352   // lib64: openSUSE Linux
353   for (StringRef CandidateLib : {"lib", "lib64"}) {
354     for (StringRef CandidateArch : Archs) {
355       llvm::SmallString<1024> LibDir(Base);
356       llvm::sys::path::append(LibDir, CandidateLib, "gcc", CandidateArch);
357       if (findGccVersion(LibDir, GccLibDir, Ver)) {
358         Arch = std::string(CandidateArch);
359         return;
360       }
361     }
362   }
363 }
364 
365 llvm::ErrorOr<std::string> toolchains::MinGW::findGcc() {
366   llvm::SmallVector<llvm::SmallString<32>, 2> Gccs;
367   Gccs.emplace_back(getTriple().getArchName());
368   Gccs[0] += "-w64-mingw32-gcc";
369   Gccs.emplace_back("mingw32-gcc");
370   // Please do not add "gcc" here
371   for (StringRef CandidateGcc : Gccs)
372     if (llvm::ErrorOr<std::string> GPPName = llvm::sys::findProgramByName(CandidateGcc))
373       return GPPName;
374   return make_error_code(std::errc::no_such_file_or_directory);
375 }
376 
377 llvm::ErrorOr<std::string> toolchains::MinGW::findClangRelativeSysroot() {
378   llvm::SmallVector<llvm::SmallString<32>, 2> Subdirs;
379   Subdirs.emplace_back(getTriple().str());
380   Subdirs.emplace_back(getTriple().getArchName());
381   Subdirs[1] += "-w64-mingw32";
382   StringRef ClangRoot =
383       llvm::sys::path::parent_path(getDriver().getInstalledDir());
384   StringRef Sep = llvm::sys::path::get_separator();
385   for (StringRef CandidateSubdir : Subdirs) {
386     if (llvm::sys::fs::is_directory(ClangRoot + Sep + CandidateSubdir)) {
387       Arch = std::string(CandidateSubdir);
388       return (ClangRoot + Sep + CandidateSubdir).str();
389     }
390   }
391   return make_error_code(std::errc::no_such_file_or_directory);
392 }
393 
394 toolchains::MinGW::MinGW(const Driver &D, const llvm::Triple &Triple,
395                          const ArgList &Args)
396     : ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args) {
397   getProgramPaths().push_back(getDriver().getInstalledDir());
398 
399   if (getDriver().SysRoot.size())
400     Base = getDriver().SysRoot;
401   // Look for <clang-bin>/../<triplet>; if found, use <clang-bin>/.. as the
402   // base as it could still be a base for a gcc setup with libgcc.
403   else if (llvm::ErrorOr<std::string> TargetSubdir = findClangRelativeSysroot())
404     Base = std::string(llvm::sys::path::parent_path(TargetSubdir.get()));
405   else if (llvm::ErrorOr<std::string> GPPName = findGcc())
406     Base = std::string(llvm::sys::path::parent_path(
407         llvm::sys::path::parent_path(GPPName.get())));
408   else
409     Base = std::string(
410         llvm::sys::path::parent_path(getDriver().getInstalledDir()));
411 
412   Base += llvm::sys::path::get_separator();
413   findGccLibDir();
414   // GccLibDir must precede Base/lib so that the
415   // correct crtbegin.o ,cetend.o would be found.
416   getFilePaths().push_back(GccLibDir);
417   getFilePaths().push_back(
418       (Base + Arch + llvm::sys::path::get_separator() + "lib").str());
419   getFilePaths().push_back(Base + "lib");
420   // openSUSE
421   getFilePaths().push_back(Base + Arch + "/sys-root/mingw/lib");
422 
423   NativeLLVMSupport =
424       Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER)
425           .equals_lower("lld");
426 }
427 
428 bool toolchains::MinGW::IsIntegratedAssemblerDefault() const { return true; }
429 
430 Tool *toolchains::MinGW::getTool(Action::ActionClass AC) const {
431   switch (AC) {
432   case Action::PreprocessJobClass:
433     if (!Preprocessor)
434       Preprocessor.reset(new tools::gcc::Preprocessor(*this));
435     return Preprocessor.get();
436   case Action::CompileJobClass:
437     if (!Compiler)
438       Compiler.reset(new tools::gcc::Compiler(*this));
439     return Compiler.get();
440   default:
441     return ToolChain::getTool(AC);
442   }
443 }
444 
445 Tool *toolchains::MinGW::buildAssembler() const {
446   return new tools::MinGW::Assembler(*this);
447 }
448 
449 Tool *toolchains::MinGW::buildLinker() const {
450   return new tools::MinGW::Linker(*this);
451 }
452 
453 bool toolchains::MinGW::HasNativeLLVMSupport() const {
454   return NativeLLVMSupport;
455 }
456 
457 bool toolchains::MinGW::IsUnwindTablesDefault(const ArgList &Args) const {
458   Arg *ExceptionArg = Args.getLastArg(options::OPT_fsjlj_exceptions,
459                                       options::OPT_fseh_exceptions,
460                                       options::OPT_fdwarf_exceptions);
461   if (ExceptionArg &&
462       ExceptionArg->getOption().matches(options::OPT_fseh_exceptions))
463     return true;
464   return getArch() == llvm::Triple::x86_64 ||
465          getArch() == llvm::Triple::aarch64;
466 }
467 
468 bool toolchains::MinGW::isPICDefault() const {
469   return getArch() == llvm::Triple::x86_64;
470 }
471 
472 bool toolchains::MinGW::isPIEDefault() const { return false; }
473 
474 bool toolchains::MinGW::isPICDefaultForced() const {
475   return getArch() == llvm::Triple::x86_64;
476 }
477 
478 llvm::ExceptionHandling
479 toolchains::MinGW::GetExceptionModel(const ArgList &Args) const {
480   if (getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::aarch64)
481     return llvm::ExceptionHandling::WinEH;
482   return llvm::ExceptionHandling::DwarfCFI;
483 }
484 
485 SanitizerMask toolchains::MinGW::getSupportedSanitizers() const {
486   SanitizerMask Res = ToolChain::getSupportedSanitizers();
487   Res |= SanitizerKind::Address;
488   Res |= SanitizerKind::PointerCompare;
489   Res |= SanitizerKind::PointerSubtract;
490   return Res;
491 }
492 
493 void toolchains::MinGW::AddCudaIncludeArgs(const ArgList &DriverArgs,
494                                            ArgStringList &CC1Args) const {
495   CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args);
496 }
497 
498 void toolchains::MinGW::printVerboseInfo(raw_ostream &OS) const {
499   CudaInstallation.print(OS);
500 }
501 
502 // Include directories for various hosts:
503 
504 // Windows, mingw.org
505 // c:\mingw\lib\gcc\mingw32\4.8.1\include\c++
506 // c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\mingw32
507 // c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\backward
508 // c:\mingw\include
509 // c:\mingw\mingw32\include
510 
511 // Windows, mingw-w64 mingw-builds
512 // c:\mingw32\i686-w64-mingw32\include
513 // c:\mingw32\i686-w64-mingw32\include\c++
514 // c:\mingw32\i686-w64-mingw32\include\c++\i686-w64-mingw32
515 // c:\mingw32\i686-w64-mingw32\include\c++\backward
516 
517 // Windows, mingw-w64 msys2
518 // c:\msys64\mingw32\include
519 // c:\msys64\mingw32\i686-w64-mingw32\include
520 // c:\msys64\mingw32\include\c++\4.9.2
521 // c:\msys64\mingw32\include\c++\4.9.2\i686-w64-mingw32
522 // c:\msys64\mingw32\include\c++\4.9.2\backward
523 
524 // openSUSE
525 // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++
526 // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++/x86_64-w64-mingw32
527 // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++/backward
528 // /usr/x86_64-w64-mingw32/sys-root/mingw/include
529 
530 // Arch Linux
531 // /usr/i686-w64-mingw32/include/c++/5.1.0
532 // /usr/i686-w64-mingw32/include/c++/5.1.0/i686-w64-mingw32
533 // /usr/i686-w64-mingw32/include/c++/5.1.0/backward
534 // /usr/i686-w64-mingw32/include
535 
536 // Ubuntu
537 // /usr/include/c++/4.8
538 // /usr/include/c++/4.8/x86_64-w64-mingw32
539 // /usr/include/c++/4.8/backward
540 // /usr/x86_64-w64-mingw32/include
541 
542 void toolchains::MinGW::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
543                                                   ArgStringList &CC1Args) const {
544   if (DriverArgs.hasArg(options::OPT_nostdinc))
545     return;
546 
547   if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
548     SmallString<1024> P(getDriver().ResourceDir);
549     llvm::sys::path::append(P, "include");
550     addSystemInclude(DriverArgs, CC1Args, P.str());
551   }
552 
553   if (DriverArgs.hasArg(options::OPT_nostdlibinc))
554     return;
555 
556   if (GetRuntimeLibType(DriverArgs) == ToolChain::RLT_Libgcc) {
557     // openSUSE
558     addSystemInclude(DriverArgs, CC1Args,
559                      Base + Arch + "/sys-root/mingw/include");
560   }
561 
562   addSystemInclude(DriverArgs, CC1Args,
563                    Base + Arch + llvm::sys::path::get_separator() + "include");
564   addSystemInclude(DriverArgs, CC1Args, Base + "include");
565 }
566 
567 void toolchains::MinGW::AddClangCXXStdlibIncludeArgs(
568     const ArgList &DriverArgs, ArgStringList &CC1Args) const {
569   if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
570       DriverArgs.hasArg(options::OPT_nostdincxx))
571     return;
572 
573   StringRef Slash = llvm::sys::path::get_separator();
574 
575   switch (GetCXXStdlibType(DriverArgs)) {
576   case ToolChain::CST_Libcxx:
577     addSystemInclude(DriverArgs, CC1Args, Base + Arch + Slash + "include" +
578                                               Slash + "c++" + Slash + "v1");
579     addSystemInclude(DriverArgs, CC1Args,
580                      Base + "include" + Slash + "c++" + Slash + "v1");
581     break;
582 
583   case ToolChain::CST_Libstdcxx:
584     llvm::SmallVector<llvm::SmallString<1024>, 4> CppIncludeBases;
585     CppIncludeBases.emplace_back(Base);
586     llvm::sys::path::append(CppIncludeBases[0], Arch, "include", "c++");
587     CppIncludeBases.emplace_back(Base);
588     llvm::sys::path::append(CppIncludeBases[1], Arch, "include", "c++", Ver);
589     CppIncludeBases.emplace_back(Base);
590     llvm::sys::path::append(CppIncludeBases[2], "include", "c++", Ver);
591     CppIncludeBases.emplace_back(GccLibDir);
592     llvm::sys::path::append(CppIncludeBases[3], "include", "c++");
593     for (auto &CppIncludeBase : CppIncludeBases) {
594       addSystemInclude(DriverArgs, CC1Args, CppIncludeBase);
595       CppIncludeBase += Slash;
596       addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + Arch);
597       addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + "backward");
598     }
599     break;
600   }
601 }
602