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