Bug Summary

File:build/source/clang/lib/Driver/ToolChains/MinGW.cpp
Warning:line 191, column 5
Value stored to 'OutputFile' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name MinGW.cpp -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 -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/source/build-llvm/tools/clang/stage2-bins -resource-dir /usr/lib/llvm-17/lib/clang/17 -D CLANG_REPOSITORY_STRING="++20230510111145+7df43bdb42ae-1~exp1~20230510111303.1288" -D _DEBUG -D _GLIBCXX_ASSERTIONS -D _GNU_SOURCE -D _LIBCPP_ENABLE_ASSERTIONS -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I tools/clang/lib/Driver -I /build/source/clang/lib/Driver -I /build/source/clang/include -I tools/clang/include -I include -I /build/source/llvm/include -D _FORTIFY_SOURCE=2 -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-17/lib/clang/17/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 -fmacro-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fmacro-prefix-map=/build/source/= -fcoverage-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fcoverage-prefix-map=/build/source/= -source-date-epoch 1683717183 -O2 -Wno-unused-command-line-argument -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 -Wno-misleading-indentation -std=c++17 -fdeprecated-macro -fdebug-compilation-dir=/build/source/build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/source/= -ferror-limit 19 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -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-2023-05-10-133810-16478-1 -x c++ /build/source/clang/lib/Driver/ToolChains/MinGW.cpp
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 "CommonArgs.h"
11#include "clang/Config/config.h"
12#include "clang/Driver/Compilation.h"
13#include "clang/Driver/Driver.h"
14#include "clang/Driver/DriverDiagnostic.h"
15#include "clang/Driver/InputInfo.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
24using namespace clang::diag;
25using namespace clang::driver;
26using namespace clang;
27using namespace llvm::opt;
28
29/// MinGW Tools
30void 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, ResponseFileSupport::None(),
54 Exec, CmdArgs, Inputs, Output));
55
56 if (Args.hasArg(options::OPT_gsplit_dwarf))
57 SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output,
58 SplitDebugName(JA, Args, Inputs[0], Output));
59}
60
61void tools::MinGW::Linker::AddLibGCC(const ArgList &Args,
62 ArgStringList &CmdArgs) const {
63 if (Args.hasArg(options::OPT_mthreads))
64 CmdArgs.push_back("-lmingwthrd");
65 CmdArgs.push_back("-lmingw32");
66
67 // Make use of compiler-rt if --rtlib option is used
68 ToolChain::RuntimeLibType RLT = getToolChain().GetRuntimeLibType(Args);
69 if (RLT == ToolChain::RLT_Libgcc) {
70 bool Static = Args.hasArg(options::OPT_static_libgcc) ||
71 Args.hasArg(options::OPT_static);
72 bool Shared = Args.hasArg(options::OPT_shared);
73 bool CXX = getToolChain().getDriver().CCCIsCXX();
74
75 if (Static || (!CXX && !Shared)) {
76 CmdArgs.push_back("-lgcc");
77 CmdArgs.push_back("-lgcc_eh");
78 } else {
79 CmdArgs.push_back("-lgcc_s");
80 CmdArgs.push_back("-lgcc");
81 }
82 } else {
83 AddRunTimeLibs(getToolChain(), getToolChain().getDriver(), CmdArgs, Args);
84 }
85
86 CmdArgs.push_back("-lmoldname");
87 CmdArgs.push_back("-lmingwex");
88 for (auto Lib : Args.getAllArgValues(options::OPT_l))
89 if (StringRef(Lib).startswith("msvcr") ||
90 StringRef(Lib).startswith("ucrt") ||
91 StringRef(Lib).startswith("crtdll"))
92 return;
93 CmdArgs.push_back("-lmsvcrt");
94}
95
96void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
97 const InputInfo &Output,
98 const InputInfoList &Inputs,
99 const ArgList &Args,
100 const char *LinkingOutput) const {
101 const ToolChain &TC = getToolChain();
102 const Driver &D = TC.getDriver();
103 const SanitizerArgs &Sanitize = TC.getSanitizerArgs(Args);
104
105 ArgStringList CmdArgs;
106
107 // Silence warning for "clang -g foo.o -o foo"
108 Args.ClaimAllArgs(options::OPT_g_Group);
109 // and "clang -emit-llvm foo.o -o foo"
110 Args.ClaimAllArgs(options::OPT_emit_llvm);
111 // and for "clang -w foo.o -o foo". Other warning options are already
112 // handled somewhere else.
113 Args.ClaimAllArgs(options::OPT_w);
114
115 if (!D.SysRoot.empty())
116 CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
117
118 if (Args.hasArg(options::OPT_s))
119 CmdArgs.push_back("-s");
120
121 CmdArgs.push_back("-m");
122 switch (TC.getArch()) {
123 case llvm::Triple::x86:
124 CmdArgs.push_back("i386pe");
125 break;
126 case llvm::Triple::x86_64:
127 CmdArgs.push_back("i386pep");
128 break;
129 case llvm::Triple::arm:
130 case llvm::Triple::thumb:
131 // FIXME: this is incorrect for WinCE
132 CmdArgs.push_back("thumb2pe");
133 break;
134 case llvm::Triple::aarch64:
135 CmdArgs.push_back("arm64pe");
136 break;
137 default:
138 D.Diag(diag::err_target_unknown_triple) << TC.getEffectiveTriple().str();
139 }
140
141 Arg *SubsysArg =
142 Args.getLastArg(options::OPT_mwindows, options::OPT_mconsole);
143 if (SubsysArg && SubsysArg->getOption().matches(options::OPT_mwindows)) {
144 CmdArgs.push_back("--subsystem");
145 CmdArgs.push_back("windows");
146 } else if (SubsysArg &&
147 SubsysArg->getOption().matches(options::OPT_mconsole)) {
148 CmdArgs.push_back("--subsystem");
149 CmdArgs.push_back("console");
150 }
151
152 if (Args.hasArg(options::OPT_mdll))
153 CmdArgs.push_back("--dll");
154 else if (Args.hasArg(options::OPT_shared))
155 CmdArgs.push_back("--shared");
156 if (Args.hasArg(options::OPT_static))
157 CmdArgs.push_back("-Bstatic");
158 else
159 CmdArgs.push_back("-Bdynamic");
160 if (Args.hasArg(options::OPT_mdll) || Args.hasArg(options::OPT_shared)) {
161 CmdArgs.push_back("-e");
162 if (TC.getArch() == llvm::Triple::x86)
163 CmdArgs.push_back("_DllMainCRTStartup@12");
164 else
165 CmdArgs.push_back("DllMainCRTStartup");
166 CmdArgs.push_back("--enable-auto-image-base");
167 }
168
169 if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
170 CmdArgs.push_back("--no-demangle");
171
172 if (Arg *A = Args.getLastArg(options::OPT_mguard_EQ)) {
173 StringRef GuardArgs = A->getValue();
174 if (GuardArgs == "none")
175 CmdArgs.push_back("--no-guard-cf");
176 else if (GuardArgs == "cf" || GuardArgs == "cf-nochecks")
177 CmdArgs.push_back("--guard-cf");
178 else
179 D.Diag(diag::err_drv_unsupported_option_argument)
180 << A->getSpelling() << GuardArgs;
181 }
182
183 CmdArgs.push_back("-o");
184 const char *OutputFile = Output.getFilename();
185 // GCC implicitly adds an .exe extension if it is given an output file name
186 // that lacks an extension.
187 // GCC used to do this only when the compiler itself runs on windows, but
188 // since GCC 8 it does the same when cross compiling as well.
189 if (!llvm::sys::path::has_extension(OutputFile)) {
190 CmdArgs.push_back(Args.MakeArgString(Twine(OutputFile) + ".exe"));
191 OutputFile = CmdArgs.back();
Value stored to 'OutputFile' is never read
192 } else
193 CmdArgs.push_back(OutputFile);
194
195 Args.AddAllArgs(CmdArgs, options::OPT_e);
196 // FIXME: add -N, -n flags
197 Args.AddLastArg(CmdArgs, options::OPT_r);
198 Args.AddLastArg(CmdArgs, options::OPT_s);
199 Args.AddLastArg(CmdArgs, options::OPT_t);
200 Args.AddAllArgs(CmdArgs, options::OPT_u_Group);
201 Args.AddLastArg(CmdArgs, options::OPT_Z_Flag);
202
203 // Add asan_dynamic as the first import lib before other libs. This allows
204 // asan to be initialized as early as possible to increase its instrumentation
205 // coverage to include other user DLLs which has not been built with asan.
206 if (Sanitize.needsAsanRt() && !Args.hasArg(options::OPT_nostdlib) &&
207 !Args.hasArg(options::OPT_nodefaultlibs)) {
208 // MinGW always links against a shared MSVCRT.
209 CmdArgs.push_back(
210 TC.getCompilerRTArgString(Args, "asan_dynamic", ToolChain::FT_Shared));
211 }
212
213 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
214 if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_mdll)) {
215 CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("dllcrt2.o")));
216 } else {
217 if (Args.hasArg(options::OPT_municode))
218 CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt2u.o")));
219 else
220 CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt2.o")));
221 }
222 if (Args.hasArg(options::OPT_pg))
223 CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("gcrt2.o")));
224 CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtbegin.o")));
225 }
226
227 Args.AddAllArgs(CmdArgs, options::OPT_L);
228 TC.AddFilePathLibArgs(Args, CmdArgs);
229
230 // Add the compiler-rt library directories if they exist to help
231 // the linker find the various sanitizer, builtin, and profiling runtimes.
232 for (const auto &LibPath : TC.getLibraryPaths()) {
233 if (TC.getVFS().exists(LibPath))
234 CmdArgs.push_back(Args.MakeArgString("-L" + LibPath));
235 }
236 auto CRTPath = TC.getCompilerRTPath();
237 if (TC.getVFS().exists(CRTPath))
238 CmdArgs.push_back(Args.MakeArgString("-L" + CRTPath));
239
240 AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
241
242 if (C.getDriver().IsFlangMode()) {
243 addFortranRuntimeLibraryPath(TC, Args, CmdArgs);
244 addFortranRuntimeLibs(TC, CmdArgs);
245 }
246
247 // TODO: Add profile stuff here
248
249 if (TC.ShouldLinkCXXStdlib(Args)) {
250 bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
251 !Args.hasArg(options::OPT_static);
252 if (OnlyLibstdcxxStatic)
253 CmdArgs.push_back("-Bstatic");
254 TC.AddCXXStdlibLibArgs(Args, CmdArgs);
255 if (OnlyLibstdcxxStatic)
256 CmdArgs.push_back("-Bdynamic");
257 }
258
259 bool HasWindowsApp = false;
260 for (auto Lib : Args.getAllArgValues(options::OPT_l)) {
261 if (Lib == "windowsapp") {
262 HasWindowsApp = true;
263 break;
264 }
265 }
266
267 if (!Args.hasArg(options::OPT_nostdlib)) {
268 if (!Args.hasArg(options::OPT_nodefaultlibs)) {
269 if (Args.hasArg(options::OPT_static))
270 CmdArgs.push_back("--start-group");
271
272 if (Args.hasArg(options::OPT_fstack_protector) ||
273 Args.hasArg(options::OPT_fstack_protector_strong) ||
274 Args.hasArg(options::OPT_fstack_protector_all)) {
275 CmdArgs.push_back("-lssp_nonshared");
276 CmdArgs.push_back("-lssp");
277 }
278
279 if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
280 options::OPT_fno_openmp, false)) {
281 switch (TC.getDriver().getOpenMPRuntime(Args)) {
282 case Driver::OMPRT_OMP:
283 CmdArgs.push_back("-lomp");
284 break;
285 case Driver::OMPRT_IOMP5:
286 CmdArgs.push_back("-liomp5md");
287 break;
288 case Driver::OMPRT_GOMP:
289 CmdArgs.push_back("-lgomp");
290 break;
291 case Driver::OMPRT_Unknown:
292 // Already diagnosed.
293 break;
294 }
295 }
296
297 AddLibGCC(Args, CmdArgs);
298
299 if (Args.hasArg(options::OPT_pg))
300 CmdArgs.push_back("-lgmon");
301
302 if (Args.hasArg(options::OPT_pthread))
303 CmdArgs.push_back("-lpthread");
304
305 if (Sanitize.needsAsanRt()) {
306 // MinGW always links against a shared MSVCRT.
307 CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dynamic",
308 ToolChain::FT_Shared));
309 CmdArgs.push_back(
310 TC.getCompilerRTArgString(Args, "asan_dynamic_runtime_thunk"));
311 CmdArgs.push_back("--require-defined");
312 CmdArgs.push_back(TC.getArch() == llvm::Triple::x86
313 ? "___asan_seh_interceptor"
314 : "__asan_seh_interceptor");
315 // Make sure the linker consider all object files from the dynamic
316 // runtime thunk.
317 CmdArgs.push_back("--whole-archive");
318 CmdArgs.push_back(
319 TC.getCompilerRTArgString(Args, "asan_dynamic_runtime_thunk"));
320 CmdArgs.push_back("--no-whole-archive");
321 }
322
323 TC.addProfileRTLibs(Args, CmdArgs);
324
325 if (!HasWindowsApp) {
326 // Add system libraries. If linking to libwindowsapp.a, that import
327 // library replaces all these and we shouldn't accidentally try to
328 // link to the normal desktop mode dlls.
329 if (Args.hasArg(options::OPT_mwindows)) {
330 CmdArgs.push_back("-lgdi32");
331 CmdArgs.push_back("-lcomdlg32");
332 }
333 CmdArgs.push_back("-ladvapi32");
334 CmdArgs.push_back("-lshell32");
335 CmdArgs.push_back("-luser32");
336 CmdArgs.push_back("-lkernel32");
337 }
338
339 if (Args.hasArg(options::OPT_static)) {
340 CmdArgs.push_back("--end-group");
341 } else {
342 AddLibGCC(Args, CmdArgs);
343 if (!HasWindowsApp)
344 CmdArgs.push_back("-lkernel32");
345 }
346 }
347
348 if (!Args.hasArg(options::OPT_nostartfiles)) {
349 // Add crtfastmath.o if available and fast math is enabled.
350 TC.addFastMathRuntimeIfAvailable(Args, CmdArgs);
351
352 CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtend.o")));
353 }
354 }
355 const char *Exec = Args.MakeArgString(TC.GetLinkerPath());
356 C.addCommand(std::make_unique<Command>(JA, *this,
357 ResponseFileSupport::AtFileUTF8(),
358 Exec, CmdArgs, Inputs, Output));
359}
360
361static bool isCrossCompiling(const llvm::Triple &T, bool RequireArchMatch) {
362 llvm::Triple HostTriple(llvm::Triple::normalize(LLVM_HOST_TRIPLE"x86_64-pc-linux-gnu"));
363 if (HostTriple.getOS() != llvm::Triple::Win32)
364 return true;
365 if (RequireArchMatch && HostTriple.getArch() != T.getArch())
366 return true;
367 return false;
368}
369
370// Simplified from Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple.
371static bool findGccVersion(StringRef LibDir, std::string &GccLibDir,
372 std::string &Ver,
373 toolchains::Generic_GCC::GCCVersion &Version) {
374 Version = toolchains::Generic_GCC::GCCVersion::Parse("0.0.0");
375 std::error_code EC;
376 for (llvm::sys::fs::directory_iterator LI(LibDir, EC), LE; !EC && LI != LE;
377 LI = LI.increment(EC)) {
378 StringRef VersionText = llvm::sys::path::filename(LI->path());
379 auto CandidateVersion =
380 toolchains::Generic_GCC::GCCVersion::Parse(VersionText);
381 if (CandidateVersion.Major == -1)
382 continue;
383 if (CandidateVersion <= Version)
384 continue;
385 Version = CandidateVersion;
386 Ver = std::string(VersionText);
387 GccLibDir = LI->path();
388 }
389 return Ver.size();
390}
391
392static llvm::Triple getLiteralTriple(const Driver &D, const llvm::Triple &T) {
393 llvm::Triple LiteralTriple(D.getTargetTriple());
394 // The arch portion of the triple may be overridden by -m32/-m64.
395 LiteralTriple.setArchName(T.getArchName());
396 return LiteralTriple;
397}
398
399void toolchains::MinGW::findGccLibDir(const llvm::Triple &LiteralTriple) {
400 llvm::SmallVector<llvm::SmallString<32>, 5> SubdirNames;
401 SubdirNames.emplace_back(LiteralTriple.str());
402 SubdirNames.emplace_back(getTriple().str());
403 SubdirNames.emplace_back(getTriple().getArchName());
404 SubdirNames.back() += "-w64-mingw32";
405 SubdirNames.emplace_back(getTriple().getArchName());
406 SubdirNames.back() += "-w64-mingw32ucrt";
407 SubdirNames.emplace_back("mingw32");
408 if (SubdirName.empty()) {
409 SubdirName = getTriple().getArchName();
410 SubdirName += "-w64-mingw32";
411 }
412 // lib: Arch Linux, Ubuntu, Windows
413 // lib64: openSUSE Linux
414 for (StringRef CandidateLib : {"lib", "lib64"}) {
415 for (StringRef CandidateSysroot : SubdirNames) {
416 llvm::SmallString<1024> LibDir(Base);
417 llvm::sys::path::append(LibDir, CandidateLib, "gcc", CandidateSysroot);
418 if (findGccVersion(LibDir, GccLibDir, Ver, GccVer)) {
419 SubdirName = std::string(CandidateSysroot);
420 return;
421 }
422 }
423 }
424}
425
426static llvm::ErrorOr<std::string> findGcc(const llvm::Triple &LiteralTriple,
427 const llvm::Triple &T) {
428 llvm::SmallVector<llvm::SmallString<32>, 5> Gccs;
429 Gccs.emplace_back(LiteralTriple.str());
430 Gccs.back() += "-gcc";
431 Gccs.emplace_back(T.str());
432 Gccs.back() += "-gcc";
433 Gccs.emplace_back(T.getArchName());
434 Gccs.back() += "-w64-mingw32-gcc";
435 Gccs.emplace_back(T.getArchName());
436 Gccs.back() += "-w64-mingw32ucrt-gcc";
437 Gccs.emplace_back("mingw32-gcc");
438 // Please do not add "gcc" here
439 for (StringRef CandidateGcc : Gccs)
440 if (llvm::ErrorOr<std::string> GPPName = llvm::sys::findProgramByName(CandidateGcc))
441 return GPPName;
442 return make_error_code(std::errc::no_such_file_or_directory);
443}
444
445static llvm::ErrorOr<std::string>
446findClangRelativeSysroot(const Driver &D, const llvm::Triple &LiteralTriple,
447 const llvm::Triple &T, std::string &SubdirName) {
448 llvm::SmallVector<llvm::SmallString<32>, 4> Subdirs;
449 Subdirs.emplace_back(LiteralTriple.str());
450 Subdirs.emplace_back(T.str());
451 Subdirs.emplace_back(T.getArchName());
452 Subdirs.back() += "-w64-mingw32";
453 Subdirs.emplace_back(T.getArchName());
454 Subdirs.back() += "-w64-mingw32ucrt";
455 StringRef ClangRoot = llvm::sys::path::parent_path(D.getInstalledDir());
456 StringRef Sep = llvm::sys::path::get_separator();
457 for (StringRef CandidateSubdir : Subdirs) {
458 if (llvm::sys::fs::is_directory(ClangRoot + Sep + CandidateSubdir)) {
459 SubdirName = std::string(CandidateSubdir);
460 return (ClangRoot + Sep + CandidateSubdir).str();
461 }
462 }
463 return make_error_code(std::errc::no_such_file_or_directory);
464}
465
466toolchains::MinGW::MinGW(const Driver &D, const llvm::Triple &Triple,
467 const ArgList &Args)
468 : ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args),
469 RocmInstallation(D, Triple, Args) {
470 getProgramPaths().push_back(getDriver().getInstalledDir());
471
472 // The sequence for detecting a sysroot here should be kept in sync with
473 // the testTriple function below.
474 llvm::Triple LiteralTriple = getLiteralTriple(D, getTriple());
475 if (getDriver().SysRoot.size())
476 Base = getDriver().SysRoot;
477 // Look for <clang-bin>/../<triplet>; if found, use <clang-bin>/.. as the
478 // base as it could still be a base for a gcc setup with libgcc.
479 else if (llvm::ErrorOr<std::string> TargetSubdir = findClangRelativeSysroot(
480 getDriver(), LiteralTriple, getTriple(), SubdirName))
481 Base = std::string(llvm::sys::path::parent_path(TargetSubdir.get()));
482 else if (llvm::ErrorOr<std::string> GPPName =
483 findGcc(LiteralTriple, getTriple()))
484 Base = std::string(llvm::sys::path::parent_path(
485 llvm::sys::path::parent_path(GPPName.get())));
486 else
487 Base = std::string(
488 llvm::sys::path::parent_path(getDriver().getInstalledDir()));
489
490 Base += llvm::sys::path::get_separator();
491 findGccLibDir(LiteralTriple);
492 TripleDirName = SubdirName;
493 // GccLibDir must precede Base/lib so that the
494 // correct crtbegin.o ,cetend.o would be found.
495 getFilePaths().push_back(GccLibDir);
496
497 // openSUSE/Fedora
498 std::string CandidateSubdir = SubdirName + "/sys-root/mingw";
499 if (getDriver().getVFS().exists(Base + CandidateSubdir))
500 SubdirName = CandidateSubdir;
501
502 getFilePaths().push_back(
503 (Base + SubdirName + llvm::sys::path::get_separator() + "lib").str());
504
505 // Gentoo
506 getFilePaths().push_back(
507 (Base + SubdirName + llvm::sys::path::get_separator() + "mingw/lib").str());
508
509 // Only include <base>/lib if we're not cross compiling (not even for
510 // windows->windows to a different arch), or if the sysroot has been set
511 // (where we presume the user has pointed it at an arch specific
512 // subdirectory).
513 if (!::isCrossCompiling(getTriple(), /*RequireArchMatch=*/true) ||
514 getDriver().SysRoot.size())
515 getFilePaths().push_back(Base + "lib");
516
517 NativeLLVMSupport =
518 Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER"ld")
519 .equals_insensitive("lld");
520}
521
522bool toolchains::MinGW::IsIntegratedAssemblerDefault() const { return true; }
523
524Tool *toolchains::MinGW::getTool(Action::ActionClass AC) const {
525 switch (AC) {
526 case Action::PreprocessJobClass:
527 if (!Preprocessor)
528 Preprocessor.reset(new tools::gcc::Preprocessor(*this));
529 return Preprocessor.get();
530 case Action::CompileJobClass:
531 if (!Compiler)
532 Compiler.reset(new tools::gcc::Compiler(*this));
533 return Compiler.get();
534 default:
535 return ToolChain::getTool(AC);
536 }
537}
538
539Tool *toolchains::MinGW::buildAssembler() const {
540 return new tools::MinGW::Assembler(*this);
541}
542
543Tool *toolchains::MinGW::buildLinker() const {
544 return new tools::MinGW::Linker(*this);
545}
546
547bool toolchains::MinGW::HasNativeLLVMSupport() const {
548 return NativeLLVMSupport;
549}
550
551ToolChain::UnwindTableLevel
552toolchains::MinGW::getDefaultUnwindTableLevel(const ArgList &Args) const {
553 Arg *ExceptionArg = Args.getLastArg(options::OPT_fsjlj_exceptions,
554 options::OPT_fseh_exceptions,
555 options::OPT_fdwarf_exceptions);
556 if (ExceptionArg &&
557 ExceptionArg->getOption().matches(options::OPT_fseh_exceptions))
558 return UnwindTableLevel::Asynchronous;
559
560 if (getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::arm ||
561 getArch() == llvm::Triple::thumb || getArch() == llvm::Triple::aarch64)
562 return UnwindTableLevel::Asynchronous;
563 return UnwindTableLevel::None;
564}
565
566bool toolchains::MinGW::isPICDefault() const {
567 return getArch() == llvm::Triple::x86_64 ||
568 getArch() == llvm::Triple::aarch64;
569}
570
571bool toolchains::MinGW::isPIEDefault(const llvm::opt::ArgList &Args) const {
572 return false;
573}
574
575bool toolchains::MinGW::isPICDefaultForced() const { return true; }
576
577llvm::ExceptionHandling
578toolchains::MinGW::GetExceptionModel(const ArgList &Args) const {
579 if (getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::aarch64 ||
580 getArch() == llvm::Triple::arm || getArch() == llvm::Triple::thumb)
581 return llvm::ExceptionHandling::WinEH;
582 return llvm::ExceptionHandling::DwarfCFI;
583}
584
585SanitizerMask toolchains::MinGW::getSupportedSanitizers() const {
586 SanitizerMask Res = ToolChain::getSupportedSanitizers();
587 Res |= SanitizerKind::Address;
588 Res |= SanitizerKind::PointerCompare;
589 Res |= SanitizerKind::PointerSubtract;
590 Res |= SanitizerKind::Vptr;
591 return Res;
592}
593
594void toolchains::MinGW::AddCudaIncludeArgs(const ArgList &DriverArgs,
595 ArgStringList &CC1Args) const {
596 CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args);
597}
598
599void toolchains::MinGW::AddHIPIncludeArgs(const ArgList &DriverArgs,
600 ArgStringList &CC1Args) const {
601 RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args);
602}
603
604void toolchains::MinGW::printVerboseInfo(raw_ostream &OS) const {
605 CudaInstallation.print(OS);
606 RocmInstallation.print(OS);
607}
608
609// Include directories for various hosts:
610
611// Windows, mingw.org
612// c:\mingw\lib\gcc\mingw32\4.8.1\include\c++
613// c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\mingw32
614// c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\backward
615// c:\mingw\include
616// c:\mingw\mingw32\include
617
618// Windows, mingw-w64 mingw-builds
619// c:\mingw32\i686-w64-mingw32\include
620// c:\mingw32\i686-w64-mingw32\include\c++
621// c:\mingw32\i686-w64-mingw32\include\c++\i686-w64-mingw32
622// c:\mingw32\i686-w64-mingw32\include\c++\backward
623
624// Windows, mingw-w64 msys2
625// c:\msys64\mingw32\include
626// c:\msys64\mingw32\i686-w64-mingw32\include
627// c:\msys64\mingw32\include\c++\4.9.2
628// c:\msys64\mingw32\include\c++\4.9.2\i686-w64-mingw32
629// c:\msys64\mingw32\include\c++\4.9.2\backward
630
631// openSUSE
632// /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++
633// /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++/x86_64-w64-mingw32
634// /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++/backward
635// /usr/x86_64-w64-mingw32/sys-root/mingw/include
636
637// Arch Linux
638// /usr/i686-w64-mingw32/include/c++/5.1.0
639// /usr/i686-w64-mingw32/include/c++/5.1.0/i686-w64-mingw32
640// /usr/i686-w64-mingw32/include/c++/5.1.0/backward
641// /usr/i686-w64-mingw32/include
642
643// Ubuntu
644// /usr/include/c++/4.8
645// /usr/include/c++/4.8/x86_64-w64-mingw32
646// /usr/include/c++/4.8/backward
647// /usr/x86_64-w64-mingw32/include
648
649// Fedora
650// /usr/x86_64-w64-mingw32ucrt/sys-root/mingw/include/c++/x86_64-w64-mingw32ucrt
651// /usr/x86_64-w64-mingw32ucrt/sys-root/mingw/include/c++/backward
652// /usr/x86_64-w64-mingw32ucrt/sys-root/mingw/include
653// /usr/lib/gcc/x86_64-w64-mingw32ucrt/12.2.1/include-fixed
654
655void toolchains::MinGW::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
656 ArgStringList &CC1Args) const {
657 if (DriverArgs.hasArg(options::OPT_nostdinc))
658 return;
659
660 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
661 SmallString<1024> P(getDriver().ResourceDir);
662 llvm::sys::path::append(P, "include");
663 addSystemInclude(DriverArgs, CC1Args, P.str());
664 }
665
666 if (DriverArgs.hasArg(options::OPT_nostdlibinc))
667 return;
668
669 addSystemInclude(DriverArgs, CC1Args,
670 Base + SubdirName + llvm::sys::path::get_separator() +
671 "include");
672
673 // Gentoo
674 addSystemInclude(DriverArgs, CC1Args,
675 Base + SubdirName + llvm::sys::path::get_separator() + "usr/include");
676
677 // Only include <base>/include if we're not cross compiling (but do allow it
678 // if we're on Windows and building for Windows on another architecture),
679 // or if the sysroot has been set (where we presume the user has pointed it
680 // at an arch specific subdirectory).
681 if (!::isCrossCompiling(getTriple(), /*RequireArchMatch=*/false) ||
682 getDriver().SysRoot.size())
683 addSystemInclude(DriverArgs, CC1Args, Base + "include");
684}
685
686void toolchains::MinGW::addClangTargetOptions(
687 const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
688 Action::OffloadKind DeviceOffloadKind) const {
689 if (Arg *A = DriverArgs.getLastArg(options::OPT_mguard_EQ)) {
690 StringRef GuardArgs = A->getValue();
691 if (GuardArgs == "none") {
692 // Do nothing.
693 } else if (GuardArgs == "cf") {
694 // Emit CFG instrumentation and the table of address-taken functions.
695 CC1Args.push_back("-cfguard");
696 } else if (GuardArgs == "cf-nochecks") {
697 // Emit only the table of address-taken functions.
698 CC1Args.push_back("-cfguard-no-checks");
699 } else {
700 getDriver().Diag(diag::err_drv_unsupported_option_argument)
701 << A->getSpelling() << GuardArgs;
702 }
703 }
704}
705
706void toolchains::MinGW::AddClangCXXStdlibIncludeArgs(
707 const ArgList &DriverArgs, ArgStringList &CC1Args) const {
708 if (DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdlibinc,
709 options::OPT_nostdincxx))
710 return;
711
712 StringRef Slash = llvm::sys::path::get_separator();
713
714 switch (GetCXXStdlibType(DriverArgs)) {
715 case ToolChain::CST_Libcxx: {
716 std::string TargetDir = (Base + "include" + Slash + getTripleString() +
717 Slash + "c++" + Slash + "v1")
718 .str();
719 if (getDriver().getVFS().exists(TargetDir))
720 addSystemInclude(DriverArgs, CC1Args, TargetDir);
721 addSystemInclude(DriverArgs, CC1Args,
722 Base + SubdirName + Slash + "include" + Slash + "c++" +
723 Slash + "v1");
724 addSystemInclude(DriverArgs, CC1Args,
725 Base + "include" + Slash + "c++" + Slash + "v1");
726 break;
727 }
728
729 case ToolChain::CST_Libstdcxx:
730 llvm::SmallVector<llvm::SmallString<1024>, 7> CppIncludeBases;
731 CppIncludeBases.emplace_back(Base);
732 llvm::sys::path::append(CppIncludeBases[0], SubdirName, "include", "c++");
733 CppIncludeBases.emplace_back(Base);
734 llvm::sys::path::append(CppIncludeBases[1], SubdirName, "include", "c++",
735 Ver);
736 CppIncludeBases.emplace_back(Base);
737 llvm::sys::path::append(CppIncludeBases[2], "include", "c++", Ver);
738 CppIncludeBases.emplace_back(GccLibDir);
739 llvm::sys::path::append(CppIncludeBases[3], "include", "c++");
740 CppIncludeBases.emplace_back(GccLibDir);
741 llvm::sys::path::append(CppIncludeBases[4], "include",
742 "g++-v" + GccVer.Text);
743 CppIncludeBases.emplace_back(GccLibDir);
744 llvm::sys::path::append(CppIncludeBases[5], "include",
745 "g++-v" + GccVer.MajorStr + "." + GccVer.MinorStr);
746 CppIncludeBases.emplace_back(GccLibDir);
747 llvm::sys::path::append(CppIncludeBases[6], "include",
748 "g++-v" + GccVer.MajorStr);
749 for (auto &CppIncludeBase : CppIncludeBases) {
750 addSystemInclude(DriverArgs, CC1Args, CppIncludeBase);
751 CppIncludeBase += Slash;
752 addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + TripleDirName);
753 addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + "backward");
754 }
755 break;
756 }
757}
758
759static bool testTriple(const Driver &D, const llvm::Triple &Triple,
760 const ArgList &Args) {
761 // If an explicit sysroot is set, that will be used and we shouldn't try to
762 // detect anything else.
763 std::string SubdirName;
764 if (D.SysRoot.size())
765 return true;
766 llvm::Triple LiteralTriple = getLiteralTriple(D, Triple);
767 if (llvm::ErrorOr<std::string> TargetSubdir =
768 findClangRelativeSysroot(D, LiteralTriple, Triple, SubdirName))
769 return true;
770 if (llvm::ErrorOr<std::string> GPPName = findGcc(LiteralTriple, Triple))
771 return true;
772 // If we neither found a colocated sysroot or a matching gcc executable,
773 // conclude that we can't know if this is the correct spelling of the triple.
774 return false;
775}
776
777static llvm::Triple adjustTriple(const Driver &D, const llvm::Triple &Triple,
778 const ArgList &Args) {
779 // First test if the original triple can find a sysroot with the triple
780 // name.
781 if (testTriple(D, Triple, Args))
782 return Triple;
783 llvm::SmallVector<llvm::StringRef, 3> Archs;
784 // If not, test a couple other possible arch names that might be what was
785 // intended.
786 if (Triple.getArch() == llvm::Triple::x86) {
787 Archs.emplace_back("i386");
788 Archs.emplace_back("i586");
789 Archs.emplace_back("i686");
790 } else if (Triple.getArch() == llvm::Triple::arm ||
791 Triple.getArch() == llvm::Triple::thumb) {
792 Archs.emplace_back("armv7");
793 }
794 for (auto A : Archs) {
795 llvm::Triple TestTriple(Triple);
796 TestTriple.setArchName(A);
797 if (testTriple(D, TestTriple, Args))
798 return TestTriple;
799 }
800 // If none was found, just proceed with the original value.
801 return Triple;
802}
803
804void toolchains::MinGW::fixTripleArch(const Driver &D, llvm::Triple &Triple,
805 const ArgList &Args) {
806 if (Triple.getArch() == llvm::Triple::x86 ||
807 Triple.getArch() == llvm::Triple::arm ||
808 Triple.getArch() == llvm::Triple::thumb)
809 Triple = adjustTriple(D, Triple, Args);
810}