clang 17.0.0git
CompilerInvocation.cpp
Go to the documentation of this file.
1//===- CompilerInvocation.cpp ---------------------------------------------===//
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
19#include "clang/Basic/LLVM.h"
26#include "clang/Basic/Version.h"
29#include "clang/Config/config.h"
30#include "clang/Driver/Driver.h"
48#include "llvm/ADT/APInt.h"
49#include "llvm/ADT/ArrayRef.h"
50#include "llvm/ADT/CachedHashString.h"
51#include "llvm/ADT/DenseSet.h"
52#include "llvm/ADT/FloatingPointMode.h"
53#include "llvm/ADT/Hashing.h"
54#include "llvm/ADT/STLExtras.h"
55#include "llvm/ADT/SmallString.h"
56#include "llvm/ADT/SmallVector.h"
57#include "llvm/ADT/StringRef.h"
58#include "llvm/ADT/StringSwitch.h"
59#include "llvm/ADT/Twine.h"
60#include "llvm/Config/llvm-config.h"
61#include "llvm/Frontend/Debug/Options.h"
62#include "llvm/IR/DebugInfoMetadata.h"
63#include "llvm/Linker/Linker.h"
64#include "llvm/MC/MCTargetOptions.h"
65#include "llvm/Option/Arg.h"
66#include "llvm/Option/ArgList.h"
67#include "llvm/Option/OptSpecifier.h"
68#include "llvm/Option/OptTable.h"
69#include "llvm/Option/Option.h"
70#include "llvm/ProfileData/InstrProfReader.h"
71#include "llvm/Remarks/HotnessThresholdParser.h"
72#include "llvm/Support/CodeGen.h"
73#include "llvm/Support/Compiler.h"
74#include "llvm/Support/Error.h"
75#include "llvm/Support/ErrorHandling.h"
76#include "llvm/Support/ErrorOr.h"
77#include "llvm/Support/FileSystem.h"
78#include "llvm/Support/HashBuilder.h"
79#include "llvm/Support/MathExtras.h"
80#include "llvm/Support/MemoryBuffer.h"
81#include "llvm/Support/Path.h"
82#include "llvm/Support/Process.h"
83#include "llvm/Support/Regex.h"
84#include "llvm/Support/VersionTuple.h"
85#include "llvm/Support/VirtualFileSystem.h"
86#include "llvm/Support/raw_ostream.h"
87#include "llvm/Target/TargetOptions.h"
88#include "llvm/TargetParser/Host.h"
89#include "llvm/TargetParser/Triple.h"
90#include <algorithm>
91#include <atomic>
92#include <cassert>
93#include <cstddef>
94#include <cstring>
95#include <ctime>
96#include <fstream>
97#include <limits>
98#include <memory>
99#include <optional>
100#include <string>
101#include <tuple>
102#include <type_traits>
103#include <utility>
104#include <vector>
105
106using namespace clang;
107using namespace driver;
108using namespace options;
109using namespace llvm::opt;
110
111//===----------------------------------------------------------------------===//
112// Helpers.
113//===----------------------------------------------------------------------===//
114
115// Parse misexpect tolerance argument value.
116// Valid option values are integers in the range [0, 100)
118 uint32_t Val;
119 if (Arg.getAsInteger(10, Val))
120 return llvm::createStringError(llvm::inconvertibleErrorCode(),
121 "Not an integer: %s", Arg.data());
122 return Val;
123}
124
125//===----------------------------------------------------------------------===//
126// Initialization.
127//===----------------------------------------------------------------------===//
128
130 : LangOpts(new LangOptions()), TargetOpts(new TargetOptions()),
131 DiagnosticOpts(new DiagnosticOptions()),
132 HeaderSearchOpts(new HeaderSearchOptions()),
133 PreprocessorOpts(new PreprocessorOptions()),
134 AnalyzerOpts(new AnalyzerOptions()) {}
135
138 : LangOpts(new LangOptions(*X.getLangOpts())),
139 TargetOpts(new TargetOptions(X.getTargetOpts())),
140 DiagnosticOpts(new DiagnosticOptions(X.getDiagnosticOpts())),
141 HeaderSearchOpts(new HeaderSearchOptions(X.getHeaderSearchOpts())),
142 PreprocessorOpts(new PreprocessorOptions(X.getPreprocessorOpts())),
143 AnalyzerOpts(new AnalyzerOptions(*X.getAnalyzerOpts())) {}
144
146 CompilerInvocationRefBase &&X) = default;
147
150 LangOpts.swap(X.LangOpts);
151 TargetOpts.swap(X.TargetOpts);
152 DiagnosticOpts.swap(X.DiagnosticOpts);
153 HeaderSearchOpts.swap(X.HeaderSearchOpts);
154 PreprocessorOpts.swap(X.PreprocessorOpts);
155 AnalyzerOpts.swap(X.AnalyzerOpts);
156 return *this;
157}
158
161
163
164//===----------------------------------------------------------------------===//
165// Normalizers
166//===----------------------------------------------------------------------===//
167
168#define SIMPLE_ENUM_VALUE_TABLE
169#include "clang/Driver/Options.inc"
170#undef SIMPLE_ENUM_VALUE_TABLE
171
172static std::optional<bool> normalizeSimpleFlag(OptSpecifier Opt,
173 unsigned TableIndex,
174 const ArgList &Args,
175 DiagnosticsEngine &Diags) {
176 if (Args.hasArg(Opt))
177 return true;
178 return std::nullopt;
179}
180
181static std::optional<bool> normalizeSimpleNegativeFlag(OptSpecifier Opt,
182 unsigned,
183 const ArgList &Args,
185 if (Args.hasArg(Opt))
186 return false;
187 return std::nullopt;
188}
189
190/// The tblgen-erated code passes in a fifth parameter of an arbitrary type, but
191/// denormalizeSimpleFlags never looks at it. Avoid bloating compile-time with
192/// unnecessary template instantiations and just ignore it with a variadic
193/// argument.
195 const char *Spelling,
197 Option::OptionClass, unsigned, /*T*/...) {
198 Args.push_back(Spelling);
199}
200
201template <typename T> static constexpr bool is_uint64_t_convertible() {
202 return !std::is_same_v<T, uint64_t> && llvm::is_integral_or_enum<T>::value;
203}
204
205template <typename T,
206 std::enable_if_t<!is_uint64_t_convertible<T>(), bool> = false>
208 return [Value](OptSpecifier Opt, unsigned, const ArgList &Args,
209 DiagnosticsEngine &) -> std::optional<T> {
210 if (Args.hasArg(Opt))
211 return Value;
212 return std::nullopt;
213 };
214}
215
216template <typename T,
217 std::enable_if_t<is_uint64_t_convertible<T>(), bool> = false>
218static auto makeFlagToValueNormalizer(T Value) {
220}
221
222static auto makeBooleanOptionNormalizer(bool Value, bool OtherValue,
223 OptSpecifier OtherOpt) {
224 return [Value, OtherValue,
225 OtherOpt](OptSpecifier Opt, unsigned, const ArgList &Args,
226 DiagnosticsEngine &) -> std::optional<bool> {
227 if (const Arg *A = Args.getLastArg(Opt, OtherOpt)) {
228 return A->getOption().matches(Opt) ? Value : OtherValue;
229 }
230 return std::nullopt;
231 };
232}
233
235 return [Value](SmallVectorImpl<const char *> &Args, const char *Spelling,
236 CompilerInvocation::StringAllocator, Option::OptionClass,
237 unsigned, bool KeyPath) {
238 if (KeyPath == Value)
239 Args.push_back(Spelling);
240 };
241}
242
244 const char *Spelling,
246 Option::OptionClass OptClass, unsigned,
247 const Twine &Value) {
248 switch (OptClass) {
249 case Option::SeparateClass:
250 case Option::JoinedOrSeparateClass:
251 case Option::JoinedAndSeparateClass:
252 Args.push_back(Spelling);
253 Args.push_back(SA(Value));
254 break;
255 case Option::JoinedClass:
256 case Option::CommaJoinedClass:
257 Args.push_back(SA(Twine(Spelling) + Value));
258 break;
259 default:
260 llvm_unreachable("Cannot denormalize an option with option class "
261 "incompatible with string denormalization.");
262 }
263}
264
265template <typename T>
266static void
269 Option::OptionClass OptClass, unsigned TableIndex, T Value) {
270 denormalizeStringImpl(Args, Spelling, SA, OptClass, TableIndex, Twine(Value));
271}
272
273static std::optional<SimpleEnumValue>
274findValueTableByName(const SimpleEnumValueTable &Table, StringRef Name) {
275 for (int I = 0, E = Table.Size; I != E; ++I)
276 if (Name == Table.Table[I].Name)
277 return Table.Table[I];
278
279 return std::nullopt;
280}
281
282static std::optional<SimpleEnumValue>
283findValueTableByValue(const SimpleEnumValueTable &Table, unsigned Value) {
284 for (int I = 0, E = Table.Size; I != E; ++I)
285 if (Value == Table.Table[I].Value)
286 return Table.Table[I];
287
288 return std::nullopt;
289}
290
291static std::optional<unsigned> normalizeSimpleEnum(OptSpecifier Opt,
292 unsigned TableIndex,
293 const ArgList &Args,
294 DiagnosticsEngine &Diags) {
295 assert(TableIndex < SimpleEnumValueTablesSize);
296 const SimpleEnumValueTable &Table = SimpleEnumValueTables[TableIndex];
297
298 auto *Arg = Args.getLastArg(Opt);
299 if (!Arg)
300 return std::nullopt;
301
302 StringRef ArgValue = Arg->getValue();
303 if (auto MaybeEnumVal = findValueTableByName(Table, ArgValue))
304 return MaybeEnumVal->Value;
305
306 Diags.Report(diag::err_drv_invalid_value)
307 << Arg->getAsString(Args) << ArgValue;
308 return std::nullopt;
309}
310
312 const char *Spelling,
314 Option::OptionClass OptClass,
315 unsigned TableIndex, unsigned Value) {
316 assert(TableIndex < SimpleEnumValueTablesSize);
317 const SimpleEnumValueTable &Table = SimpleEnumValueTables[TableIndex];
318 if (auto MaybeEnumVal = findValueTableByValue(Table, Value)) {
319 denormalizeString(Args, Spelling, SA, OptClass, TableIndex,
320 MaybeEnumVal->Name);
321 } else {
322 llvm_unreachable("The simple enum value was not correctly defined in "
323 "the tablegen option description");
324 }
325}
326
327template <typename T>
329 const char *Spelling,
331 Option::OptionClass OptClass,
332 unsigned TableIndex, T Value) {
333 return denormalizeSimpleEnumImpl(Args, Spelling, SA, OptClass, TableIndex,
334 static_cast<unsigned>(Value));
335}
336
337static std::optional<std::string> normalizeString(OptSpecifier Opt,
338 int TableIndex,
339 const ArgList &Args,
340 DiagnosticsEngine &Diags) {
341 auto *Arg = Args.getLastArg(Opt);
342 if (!Arg)
343 return std::nullopt;
344 return std::string(Arg->getValue());
345}
346
347template <typename IntTy>
348static std::optional<IntTy> normalizeStringIntegral(OptSpecifier Opt, int,
349 const ArgList &Args,
350 DiagnosticsEngine &Diags) {
351 auto *Arg = Args.getLastArg(Opt);
352 if (!Arg)
353 return std::nullopt;
354 IntTy Res;
355 if (StringRef(Arg->getValue()).getAsInteger(0, Res)) {
356 Diags.Report(diag::err_drv_invalid_int_value)
357 << Arg->getAsString(Args) << Arg->getValue();
358 return std::nullopt;
359 }
360 return Res;
361}
362
363static std::optional<std::vector<std::string>>
364normalizeStringVector(OptSpecifier Opt, int, const ArgList &Args,
366 return Args.getAllArgValues(Opt);
367}
368
370 const char *Spelling,
372 Option::OptionClass OptClass,
373 unsigned TableIndex,
374 const std::vector<std::string> &Values) {
375 switch (OptClass) {
376 case Option::CommaJoinedClass: {
377 std::string CommaJoinedValue;
378 if (!Values.empty()) {
379 CommaJoinedValue.append(Values.front());
380 for (const std::string &Value : llvm::drop_begin(Values, 1)) {
381 CommaJoinedValue.append(",");
382 CommaJoinedValue.append(Value);
383 }
384 }
385 denormalizeString(Args, Spelling, SA, Option::OptionClass::JoinedClass,
386 TableIndex, CommaJoinedValue);
387 break;
388 }
389 case Option::JoinedClass:
390 case Option::SeparateClass:
391 case Option::JoinedOrSeparateClass:
392 for (const std::string &Value : Values)
393 denormalizeString(Args, Spelling, SA, OptClass, TableIndex, Value);
394 break;
395 default:
396 llvm_unreachable("Cannot denormalize an option with option class "
397 "incompatible with string vector denormalization.");
398 }
399}
400
401static std::optional<std::string> normalizeTriple(OptSpecifier Opt,
402 int TableIndex,
403 const ArgList &Args,
404 DiagnosticsEngine &Diags) {
405 auto *Arg = Args.getLastArg(Opt);
406 if (!Arg)
407 return std::nullopt;
408 return llvm::Triple::normalize(Arg->getValue());
409}
410
411template <typename T, typename U>
412static T mergeForwardValue(T KeyPath, U Value) {
413 return static_cast<T>(Value);
414}
415
416template <typename T, typename U> static T mergeMaskValue(T KeyPath, U Value) {
417 return KeyPath | Value;
418}
419
420template <typename T> static T extractForwardValue(T KeyPath) {
421 return KeyPath;
422}
423
424template <typename T, typename U, U Value>
425static T extractMaskValue(T KeyPath) {
426 return ((KeyPath & Value) == Value) ? static_cast<T>(Value) : T();
427}
428
429#define PARSE_OPTION_WITH_MARSHALLING( \
430 ARGS, DIAGS, PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, \
431 PARAM, HELPTEXT, METAVAR, VALUES, SPELLING, SHOULD_PARSE, ALWAYS_EMIT, \
432 KEYPATH, DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, \
433 DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX) \
434 if ((FLAGS)&options::CC1Option) { \
435 KEYPATH = MERGER(KEYPATH, DEFAULT_VALUE); \
436 if (IMPLIED_CHECK) \
437 KEYPATH = MERGER(KEYPATH, IMPLIED_VALUE); \
438 if (SHOULD_PARSE) \
439 if (auto MaybeValue = NORMALIZER(OPT_##ID, TABLE_INDEX, ARGS, DIAGS)) \
440 KEYPATH = \
441 MERGER(KEYPATH, static_cast<decltype(KEYPATH)>(*MaybeValue)); \
442 }
443
444// Capture the extracted value as a lambda argument to avoid potential issues
445// with lifetime extension of the reference.
446#define GENERATE_OPTION_WITH_MARSHALLING( \
447 ARGS, STRING_ALLOCATOR, PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, \
448 ALIASARGS, FLAGS, PARAM, HELPTEXT, METAVAR, VALUES, SPELLING, \
449 SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, IMPLIED_CHECK, \
450 IMPLIED_VALUE, NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX) \
451 if ((FLAGS)&options::CC1Option) { \
452 [&](const auto &Extracted) { \
453 if (ALWAYS_EMIT || \
454 (Extracted != \
455 static_cast<decltype(KEYPATH)>((IMPLIED_CHECK) ? (IMPLIED_VALUE) \
456 : (DEFAULT_VALUE)))) \
457 DENORMALIZER(ARGS, SPELLING, STRING_ALLOCATOR, Option::KIND##Class, \
458 TABLE_INDEX, Extracted); \
459 }(EXTRACTOR(KEYPATH)); \
460 }
461
462static StringRef GetInputKindName(InputKind IK);
463
464static bool FixupInvocation(CompilerInvocation &Invocation,
465 DiagnosticsEngine &Diags, const ArgList &Args,
466 InputKind IK) {
467 unsigned NumErrorsBefore = Diags.getNumErrors();
468
469 LangOptions &LangOpts = *Invocation.getLangOpts();
470 CodeGenOptions &CodeGenOpts = Invocation.getCodeGenOpts();
471 TargetOptions &TargetOpts = Invocation.getTargetOpts();
472 FrontendOptions &FrontendOpts = Invocation.getFrontendOpts();
473 CodeGenOpts.XRayInstrumentFunctions = LangOpts.XRayInstrument;
474 CodeGenOpts.XRayAlwaysEmitCustomEvents = LangOpts.XRayAlwaysEmitCustomEvents;
475 CodeGenOpts.XRayAlwaysEmitTypedEvents = LangOpts.XRayAlwaysEmitTypedEvents;
476 CodeGenOpts.DisableFree = FrontendOpts.DisableFree;
477 FrontendOpts.GenerateGlobalModuleIndex = FrontendOpts.UseGlobalModuleIndex;
478 if (FrontendOpts.ShowStats)
479 CodeGenOpts.ClearASTBeforeBackend = false;
480 LangOpts.SanitizeCoverage = CodeGenOpts.hasSanitizeCoverage();
481 LangOpts.ForceEmitVTables = CodeGenOpts.ForceEmitVTables;
482 LangOpts.SpeculativeLoadHardening = CodeGenOpts.SpeculativeLoadHardening;
483 LangOpts.CurrentModule = LangOpts.ModuleName;
484
485 llvm::Triple T(TargetOpts.Triple);
486 llvm::Triple::ArchType Arch = T.getArch();
487
488 CodeGenOpts.CodeModel = TargetOpts.CodeModel;
489
490 if (LangOpts.getExceptionHandling() !=
492 T.isWindowsMSVCEnvironment())
493 Diags.Report(diag::err_fe_invalid_exception_model)
494 << static_cast<unsigned>(LangOpts.getExceptionHandling()) << T.str();
495
496 if (LangOpts.AppleKext && !LangOpts.CPlusPlus)
497 Diags.Report(diag::warn_c_kext);
498
499 if (LangOpts.NewAlignOverride &&
500 !llvm::isPowerOf2_32(LangOpts.NewAlignOverride)) {
501 Arg *A = Args.getLastArg(OPT_fnew_alignment_EQ);
502 Diags.Report(diag::err_fe_invalid_alignment)
503 << A->getAsString(Args) << A->getValue();
504 LangOpts.NewAlignOverride = 0;
505 }
506
507 // Prevent the user from specifying both -fsycl-is-device and -fsycl-is-host.
508 if (LangOpts.SYCLIsDevice && LangOpts.SYCLIsHost)
509 Diags.Report(diag::err_drv_argument_not_allowed_with) << "-fsycl-is-device"
510 << "-fsycl-is-host";
511
512 if (Args.hasArg(OPT_fgnu89_inline) && LangOpts.CPlusPlus)
513 Diags.Report(diag::err_drv_argument_not_allowed_with)
514 << "-fgnu89-inline" << GetInputKindName(IK);
515
516 if (Args.hasArg(OPT_hlsl_entrypoint) && !LangOpts.HLSL)
517 Diags.Report(diag::err_drv_argument_not_allowed_with)
518 << "-hlsl-entry" << GetInputKindName(IK);
519
520 if (Args.hasArg(OPT_fgpu_allow_device_init) && !LangOpts.HIP)
521 Diags.Report(diag::warn_ignored_hip_only_option)
522 << Args.getLastArg(OPT_fgpu_allow_device_init)->getAsString(Args);
523
524 if (Args.hasArg(OPT_gpu_max_threads_per_block_EQ) && !LangOpts.HIP)
525 Diags.Report(diag::warn_ignored_hip_only_option)
526 << Args.getLastArg(OPT_gpu_max_threads_per_block_EQ)->getAsString(Args);
527
528 // When these options are used, the compiler is allowed to apply
529 // optimizations that may affect the final result. For example
530 // (x+y)+z is transformed to x+(y+z) but may not give the same
531 // final result; it's not value safe.
532 // Another example can be to simplify x/x to 1.0 but x could be 0.0, INF
533 // or NaN. Final result may then differ. An error is issued when the eval
534 // method is set with one of these options.
535 if (Args.hasArg(OPT_ffp_eval_method_EQ)) {
536 if (LangOpts.ApproxFunc)
537 Diags.Report(diag::err_incompatible_fp_eval_method_options) << 0;
538 if (LangOpts.AllowFPReassoc)
539 Diags.Report(diag::err_incompatible_fp_eval_method_options) << 1;
540 if (LangOpts.AllowRecip)
541 Diags.Report(diag::err_incompatible_fp_eval_method_options) << 2;
542 }
543
544 // -cl-strict-aliasing needs to emit diagnostic in the case where CL > 1.0.
545 // This option should be deprecated for CL > 1.0 because
546 // this option was added for compatibility with OpenCL 1.0.
547 if (Args.getLastArg(OPT_cl_strict_aliasing) &&
548 (LangOpts.getOpenCLCompatibleVersion() > 100))
549 Diags.Report(diag::warn_option_invalid_ocl_version)
550 << LangOpts.getOpenCLVersionString()
551 << Args.getLastArg(OPT_cl_strict_aliasing)->getAsString(Args);
552
553 if (Arg *A = Args.getLastArg(OPT_fdefault_calling_conv_EQ)) {
554 auto DefaultCC = LangOpts.getDefaultCallingConv();
555
556 bool emitError = (DefaultCC == LangOptions::DCC_FastCall ||
557 DefaultCC == LangOptions::DCC_StdCall) &&
558 Arch != llvm::Triple::x86;
559 emitError |= (DefaultCC == LangOptions::DCC_VectorCall ||
560 DefaultCC == LangOptions::DCC_RegCall) &&
561 !T.isX86();
562 if (emitError)
563 Diags.Report(diag::err_drv_argument_not_allowed_with)
564 << A->getSpelling() << T.getTriple();
565 }
566
567 return Diags.getNumErrors() == NumErrorsBefore;
568}
569
570//===----------------------------------------------------------------------===//
571// Deserialization (from args)
572//===----------------------------------------------------------------------===//
573
574static unsigned getOptimizationLevel(ArgList &Args, InputKind IK,
575 DiagnosticsEngine &Diags) {
576 unsigned DefaultOpt = llvm::CodeGenOpt::None;
577 if ((IK.getLanguage() == Language::OpenCL ||
579 !Args.hasArg(OPT_cl_opt_disable))
580 DefaultOpt = llvm::CodeGenOpt::Default;
581
582 if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
583 if (A->getOption().matches(options::OPT_O0))
584 return llvm::CodeGenOpt::None;
585
586 if (A->getOption().matches(options::OPT_Ofast))
587 return llvm::CodeGenOpt::Aggressive;
588
589 assert(A->getOption().matches(options::OPT_O));
590
591 StringRef S(A->getValue());
592 if (S == "s" || S == "z")
593 return llvm::CodeGenOpt::Default;
594
595 if (S == "g")
596 return llvm::CodeGenOpt::Less;
597
598 return getLastArgIntValue(Args, OPT_O, DefaultOpt, Diags);
599 }
600
601 return DefaultOpt;
602}
603
604static unsigned getOptimizationLevelSize(ArgList &Args) {
605 if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
606 if (A->getOption().matches(options::OPT_O)) {
607 switch (A->getValue()[0]) {
608 default:
609 return 0;
610 case 's':
611 return 1;
612 case 'z':
613 return 2;
614 }
615 }
616 }
617 return 0;
618}
619
621 llvm::opt::OptSpecifier OptSpecifier,
623 Option Opt = getDriverOptTable().getOption(OptSpecifier);
624 denormalizeSimpleFlag(Args, SA(Opt.getPrefix() + Opt.getName()), SA,
625 Option::OptionClass::FlagClass, 0);
626}
627
629 llvm::opt::OptSpecifier OptSpecifier,
630 const Twine &Value,
632 Option Opt = getDriverOptTable().getOption(OptSpecifier);
633 denormalizeString(Args, SA(Opt.getPrefix() + Opt.getName()), SA,
634 Opt.getKind(), 0, Value);
635}
636
637// Parse command line arguments into CompilerInvocation.
638using ParseFn =
639 llvm::function_ref<bool(CompilerInvocation &, ArrayRef<const char *>,
640 DiagnosticsEngine &, const char *)>;
641
642// Generate command line arguments from CompilerInvocation.
643using GenerateFn = llvm::function_ref<void(
646
647/// May perform round-trip of command line arguments. By default, the round-trip
648/// is enabled in assert builds. This can be overwritten at run-time via the
649/// "-round-trip-args" and "-no-round-trip-args" command line flags, or via the
650/// ForceRoundTrip parameter.
651///
652/// During round-trip, the command line arguments are parsed into a dummy
653/// CompilerInvocation, which is used to generate the command line arguments
654/// again. The real CompilerInvocation is then created by parsing the generated
655/// arguments, not the original ones. This (in combination with tests covering
656/// argument behavior) ensures the generated command line is complete (doesn't
657/// drop/mangle any arguments).
658///
659/// Finally, we check the command line that was used to create the real
660/// CompilerInvocation instance. By default, we compare it to the command line
661/// the real CompilerInvocation generates. This checks whether the generator is
662/// deterministic. If \p CheckAgainstOriginalInvocation is enabled, we instead
663/// compare it to the original command line to verify the original command-line
664/// was canonical and can round-trip exactly.
665static bool RoundTrip(ParseFn Parse, GenerateFn Generate,
666 CompilerInvocation &RealInvocation,
667 CompilerInvocation &DummyInvocation,
668 ArrayRef<const char *> CommandLineArgs,
669 DiagnosticsEngine &Diags, const char *Argv0,
670 bool CheckAgainstOriginalInvocation = false,
671 bool ForceRoundTrip = false) {
672#ifndef NDEBUG
673 bool DoRoundTripDefault = true;
674#else
675 bool DoRoundTripDefault = false;
676#endif
677
678 bool DoRoundTrip = DoRoundTripDefault;
679 if (ForceRoundTrip) {
680 DoRoundTrip = true;
681 } else {
682 for (const auto *Arg : CommandLineArgs) {
683 if (Arg == StringRef("-round-trip-args"))
684 DoRoundTrip = true;
685 if (Arg == StringRef("-no-round-trip-args"))
686 DoRoundTrip = false;
687 }
688 }
689
690 // If round-trip was not requested, simply run the parser with the real
691 // invocation diagnostics.
692 if (!DoRoundTrip)
693 return Parse(RealInvocation, CommandLineArgs, Diags, Argv0);
694
695 // Serializes quoted (and potentially escaped) arguments.
696 auto SerializeArgs = [](ArrayRef<const char *> Args) {
697 std::string Buffer;
698 llvm::raw_string_ostream OS(Buffer);
699 for (const char *Arg : Args) {
700 llvm::sys::printArg(OS, Arg, /*Quote=*/true);
701 OS << ' ';
702 }
703 OS.flush();
704 return Buffer;
705 };
706
707 // Setup a dummy DiagnosticsEngine.
708 DiagnosticsEngine DummyDiags(new DiagnosticIDs(), new DiagnosticOptions());
709 DummyDiags.setClient(new TextDiagnosticBuffer());
710
711 // Run the first parse on the original arguments with the dummy invocation and
712 // diagnostics.
713 if (!Parse(DummyInvocation, CommandLineArgs, DummyDiags, Argv0) ||
714 DummyDiags.getNumWarnings() != 0) {
715 // If the first parse did not succeed, it must be user mistake (invalid
716 // command line arguments). We won't be able to generate arguments that
717 // would reproduce the same result. Let's fail again with the real
718 // invocation and diagnostics, so all side-effects of parsing are visible.
719 unsigned NumWarningsBefore = Diags.getNumWarnings();
720 auto Success = Parse(RealInvocation, CommandLineArgs, Diags, Argv0);
721 if (!Success || Diags.getNumWarnings() != NumWarningsBefore)
722 return Success;
723
724 // Parse with original options and diagnostics succeeded even though it
725 // shouldn't have. Something is off.
726 Diags.Report(diag::err_cc1_round_trip_fail_then_ok);
727 Diags.Report(diag::note_cc1_round_trip_original)
728 << SerializeArgs(CommandLineArgs);
729 return false;
730 }
731
732 // Setup string allocator.
733 llvm::BumpPtrAllocator Alloc;
734 llvm::StringSaver StringPool(Alloc);
735 auto SA = [&StringPool](const Twine &Arg) {
736 return StringPool.save(Arg).data();
737 };
738
739 // Generate arguments from the dummy invocation. If Generate is the
740 // inverse of Parse, the newly generated arguments must have the same
741 // semantics as the original.
742 SmallVector<const char *> GeneratedArgs;
743 Generate(DummyInvocation, GeneratedArgs, SA);
744
745 // Run the second parse, now on the generated arguments, and with the real
746 // invocation and diagnostics. The result is what we will end up using for the
747 // rest of compilation, so if Generate is not inverse of Parse, something down
748 // the line will break.
749 bool Success2 = Parse(RealInvocation, GeneratedArgs, Diags, Argv0);
750
751 // The first parse on original arguments succeeded, but second parse of
752 // generated arguments failed. Something must be wrong with the generator.
753 if (!Success2) {
754 Diags.Report(diag::err_cc1_round_trip_ok_then_fail);
755 Diags.Report(diag::note_cc1_round_trip_generated)
756 << 1 << SerializeArgs(GeneratedArgs);
757 return false;
758 }
759
760 SmallVector<const char *> ComparisonArgs;
761 if (CheckAgainstOriginalInvocation)
762 // Compare against original arguments.
763 ComparisonArgs.assign(CommandLineArgs.begin(), CommandLineArgs.end());
764 else
765 // Generate arguments again, this time from the options we will end up using
766 // for the rest of the compilation.
767 Generate(RealInvocation, ComparisonArgs, SA);
768
769 // Compares two lists of arguments.
770 auto Equal = [](const ArrayRef<const char *> A,
771 const ArrayRef<const char *> B) {
772 return std::equal(A.begin(), A.end(), B.begin(), B.end(),
773 [](const char *AElem, const char *BElem) {
774 return StringRef(AElem) == StringRef(BElem);
775 });
776 };
777
778 // If we generated different arguments from what we assume are two
779 // semantically equivalent CompilerInvocations, the Generate function may
780 // be non-deterministic.
781 if (!Equal(GeneratedArgs, ComparisonArgs)) {
782 Diags.Report(diag::err_cc1_round_trip_mismatch);
783 Diags.Report(diag::note_cc1_round_trip_generated)
784 << 1 << SerializeArgs(GeneratedArgs);
785 Diags.Report(diag::note_cc1_round_trip_generated)
786 << 2 << SerializeArgs(ComparisonArgs);
787 return false;
788 }
789
790 Diags.Report(diag::remark_cc1_round_trip_generated)
791 << 1 << SerializeArgs(GeneratedArgs);
792 Diags.Report(diag::remark_cc1_round_trip_generated)
793 << 2 << SerializeArgs(ComparisonArgs);
794
795 return Success2;
796}
797
799 DiagnosticsEngine &Diags,
800 const char *Argv0) {
801 CompilerInvocation DummyInvocation1, DummyInvocation2;
802 return RoundTrip(
803 [](CompilerInvocation &Invocation, ArrayRef<const char *> CommandLineArgs,
804 DiagnosticsEngine &Diags, const char *Argv0) {
805 return CreateFromArgsImpl(Invocation, CommandLineArgs, Diags, Argv0);
806 },
808 StringAllocator SA) {
809 Args.push_back("-cc1");
810 Invocation.generateCC1CommandLine(Args, SA);
811 },
812 DummyInvocation1, DummyInvocation2, Args, Diags, Argv0,
813 /*CheckAgainstOriginalInvocation=*/true, /*ForceRoundTrip=*/true);
814}
815
816static void addDiagnosticArgs(ArgList &Args, OptSpecifier Group,
817 OptSpecifier GroupWithValue,
818 std::vector<std::string> &Diagnostics) {
819 for (auto *A : Args.filtered(Group)) {
820 if (A->getOption().getKind() == Option::FlagClass) {
821 // The argument is a pure flag (such as OPT_Wall or OPT_Wdeprecated). Add
822 // its name (minus the "W" or "R" at the beginning) to the diagnostics.
823 Diagnostics.push_back(
824 std::string(A->getOption().getName().drop_front(1)));
825 } else if (A->getOption().matches(GroupWithValue)) {
826 // This is -Wfoo= or -Rfoo=, where foo is the name of the diagnostic
827 // group. Add only the group name to the diagnostics.
828 Diagnostics.push_back(
829 std::string(A->getOption().getName().drop_front(1).rtrim("=-")));
830 } else {
831 // Otherwise, add its value (for OPT_W_Joined and similar).
832 Diagnostics.push_back(A->getValue());
833 }
834 }
835}
836
837// Parse the Static Analyzer configuration. If \p Diags is set to nullptr,
838// it won't verify the input.
839static void parseAnalyzerConfigs(AnalyzerOptions &AnOpts,
840 DiagnosticsEngine *Diags);
841
842static void getAllNoBuiltinFuncValues(ArgList &Args,
843 std::vector<std::string> &Funcs) {
844 std::vector<std::string> Values = Args.getAllArgValues(OPT_fno_builtin_);
845 auto BuiltinEnd = llvm::partition(Values, Builtin::Context::isBuiltinFunc);
846 Funcs.insert(Funcs.end(), Values.begin(), BuiltinEnd);
847}
848
852 const AnalyzerOptions *AnalyzerOpts = &Opts;
853
854#define ANALYZER_OPTION_WITH_MARSHALLING(...) \
855 GENERATE_OPTION_WITH_MARSHALLING(Args, SA, __VA_ARGS__)
856#include "clang/Driver/Options.inc"
857#undef ANALYZER_OPTION_WITH_MARSHALLING
858
859 if (Opts.AnalysisConstraintsOpt != RangeConstraintsModel) {
860 switch (Opts.AnalysisConstraintsOpt) {
861#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) \
862 case NAME##Model: \
863 GenerateArg(Args, OPT_analyzer_constraints, CMDFLAG, SA); \
864 break;
865#include "clang/StaticAnalyzer/Core/Analyses.def"
866 default:
867 llvm_unreachable("Tried to generate unknown analysis constraint.");
868 }
869 }
870
871 if (Opts.AnalysisDiagOpt != PD_HTML) {
872 switch (Opts.AnalysisDiagOpt) {
873#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN) \
874 case PD_##NAME: \
875 GenerateArg(Args, OPT_analyzer_output, CMDFLAG, SA); \
876 break;
877#include "clang/StaticAnalyzer/Core/Analyses.def"
878 default:
879 llvm_unreachable("Tried to generate unknown analysis diagnostic client.");
880 }
881 }
882
883 if (Opts.AnalysisPurgeOpt != PurgeStmt) {
884 switch (Opts.AnalysisPurgeOpt) {
885#define ANALYSIS_PURGE(NAME, CMDFLAG, DESC) \
886 case NAME: \
887 GenerateArg(Args, OPT_analyzer_purge, CMDFLAG, SA); \
888 break;
889#include "clang/StaticAnalyzer/Core/Analyses.def"
890 default:
891 llvm_unreachable("Tried to generate unknown analysis purge mode.");
892 }
893 }
894
895 if (Opts.InliningMode != NoRedundancy) {
896 switch (Opts.InliningMode) {
897#define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC) \
898 case NAME: \
899 GenerateArg(Args, OPT_analyzer_inlining_mode, CMDFLAG, SA); \
900 break;
901#include "clang/StaticAnalyzer/Core/Analyses.def"
902 default:
903 llvm_unreachable("Tried to generate unknown analysis inlining mode.");
904 }
905 }
906
907 for (const auto &CP : Opts.CheckersAndPackages) {
908 OptSpecifier Opt =
909 CP.second ? OPT_analyzer_checker : OPT_analyzer_disable_checker;
910 GenerateArg(Args, Opt, CP.first, SA);
911 }
912
913 AnalyzerOptions ConfigOpts;
914 parseAnalyzerConfigs(ConfigOpts, nullptr);
915
916 // Sort options by key to avoid relying on StringMap iteration order.
918 for (const auto &C : Opts.Config)
919 SortedConfigOpts.emplace_back(C.getKey(), C.getValue());
920 llvm::sort(SortedConfigOpts, llvm::less_first());
921
922 for (const auto &[Key, Value] : SortedConfigOpts) {
923 // Don't generate anything that came from parseAnalyzerConfigs. It would be
924 // redundant and may not be valid on the command line.
925 auto Entry = ConfigOpts.Config.find(Key);
926 if (Entry != ConfigOpts.Config.end() && Entry->getValue() == Value)
927 continue;
928
929 GenerateArg(Args, OPT_analyzer_config, Key + "=" + Value, SA);
930 }
931
932 // Nothing to generate for FullCompilerInvocation.
933}
934
935static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
936 DiagnosticsEngine &Diags) {
937 unsigned NumErrorsBefore = Diags.getNumErrors();
938
939 AnalyzerOptions *AnalyzerOpts = &Opts;
940
941#define ANALYZER_OPTION_WITH_MARSHALLING(...) \
942 PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
943#include "clang/Driver/Options.inc"
944#undef ANALYZER_OPTION_WITH_MARSHALLING
945
946 if (Arg *A = Args.getLastArg(OPT_analyzer_constraints)) {
947 StringRef Name = A->getValue();
948 AnalysisConstraints Value = llvm::StringSwitch<AnalysisConstraints>(Name)
949#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) \
950 .Case(CMDFLAG, NAME##Model)
951#include "clang/StaticAnalyzer/Core/Analyses.def"
952 .Default(NumConstraints);
953 if (Value == NumConstraints) {
954 Diags.Report(diag::err_drv_invalid_value)
955 << A->getAsString(Args) << Name;
956 } else {
957#ifndef LLVM_WITH_Z3
958 if (Value == AnalysisConstraints::Z3ConstraintsModel) {
959 Diags.Report(diag::err_analyzer_not_built_with_z3);
960 }
961#endif // LLVM_WITH_Z3
963 }
964 }
965
966 if (Arg *A = Args.getLastArg(OPT_analyzer_output)) {
967 StringRef Name = A->getValue();
968 AnalysisDiagClients Value = llvm::StringSwitch<AnalysisDiagClients>(Name)
969#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN) \
970 .Case(CMDFLAG, PD_##NAME)
971#include "clang/StaticAnalyzer/Core/Analyses.def"
974 Diags.Report(diag::err_drv_invalid_value)
975 << A->getAsString(Args) << Name;
976 } else {
977 Opts.AnalysisDiagOpt = Value;
978 }
979 }
980
981 if (Arg *A = Args.getLastArg(OPT_analyzer_purge)) {
982 StringRef Name = A->getValue();
983 AnalysisPurgeMode Value = llvm::StringSwitch<AnalysisPurgeMode>(Name)
984#define ANALYSIS_PURGE(NAME, CMDFLAG, DESC) \
985 .Case(CMDFLAG, NAME)
986#include "clang/StaticAnalyzer/Core/Analyses.def"
987 .Default(NumPurgeModes);
988 if (Value == NumPurgeModes) {
989 Diags.Report(diag::err_drv_invalid_value)
990 << A->getAsString(Args) << Name;
991 } else {
992 Opts.AnalysisPurgeOpt = Value;
993 }
994 }
995
996 if (Arg *A = Args.getLastArg(OPT_analyzer_inlining_mode)) {
997 StringRef Name = A->getValue();
998 AnalysisInliningMode Value = llvm::StringSwitch<AnalysisInliningMode>(Name)
999#define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC) \
1000 .Case(CMDFLAG, NAME)
1001#include "clang/StaticAnalyzer/Core/Analyses.def"
1002 .Default(NumInliningModes);
1003 if (Value == NumInliningModes) {
1004 Diags.Report(diag::err_drv_invalid_value)
1005 << A->getAsString(Args) << Name;
1006 } else {
1007 Opts.InliningMode = Value;
1008 }
1009 }
1010
1011 Opts.CheckersAndPackages.clear();
1012 for (const Arg *A :
1013 Args.filtered(OPT_analyzer_checker, OPT_analyzer_disable_checker)) {
1014 A->claim();
1015 bool IsEnabled = A->getOption().getID() == OPT_analyzer_checker;
1016 // We can have a list of comma separated checker names, e.g:
1017 // '-analyzer-checker=cocoa,unix'
1018 StringRef CheckerAndPackageList = A->getValue();
1019 SmallVector<StringRef, 16> CheckersAndPackages;
1020 CheckerAndPackageList.split(CheckersAndPackages, ",");
1021 for (const StringRef &CheckerOrPackage : CheckersAndPackages)
1022 Opts.CheckersAndPackages.emplace_back(std::string(CheckerOrPackage),
1023 IsEnabled);
1024 }
1025
1026 // Go through the analyzer configuration options.
1027 for (const auto *A : Args.filtered(OPT_analyzer_config)) {
1028
1029 // We can have a list of comma separated config names, e.g:
1030 // '-analyzer-config key1=val1,key2=val2'
1031 StringRef configList = A->getValue();
1032 SmallVector<StringRef, 4> configVals;
1033 configList.split(configVals, ",");
1034 for (const auto &configVal : configVals) {
1035 StringRef key, val;
1036 std::tie(key, val) = configVal.split("=");
1037 if (val.empty()) {
1038 Diags.Report(SourceLocation(),
1039 diag::err_analyzer_config_no_value) << configVal;
1040 break;
1041 }
1042 if (val.contains('=')) {
1043 Diags.Report(SourceLocation(),
1044 diag::err_analyzer_config_multiple_values)
1045 << configVal;
1046 break;
1047 }
1048
1049 // TODO: Check checker options too, possibly in CheckerRegistry.
1050 // Leave unknown non-checker configs unclaimed.
1051 if (!key.contains(":") && Opts.isUnknownAnalyzerConfig(key)) {
1053 Diags.Report(diag::err_analyzer_config_unknown) << key;
1054 continue;
1055 }
1056
1057 A->claim();
1058 Opts.Config[key] = std::string(val);
1059
1060 // FIXME: Remove this hunk after clang-17 released.
1061 constexpr auto SingleFAM =
1062 "consider-single-element-arrays-as-flexible-array-members";
1063 if (key == SingleFAM) {
1064 Diags.Report(diag::warn_analyzer_deprecated_option_with_alternative)
1065 << SingleFAM << "clang-17"
1066 << "-fstrict-flex-arrays=<N>";
1067 }
1068 }
1069 }
1070
1072 parseAnalyzerConfigs(Opts, &Diags);
1073 else
1074 parseAnalyzerConfigs(Opts, nullptr);
1075
1076 llvm::raw_string_ostream os(Opts.FullCompilerInvocation);
1077 for (unsigned i = 0; i < Args.getNumInputArgStrings(); ++i) {
1078 if (i != 0)
1079 os << " ";
1080 os << Args.getArgString(i);
1081 }
1082 os.flush();
1083
1084 return Diags.getNumErrors() == NumErrorsBefore;
1085}
1086
1088 StringRef OptionName, StringRef DefaultVal) {
1089 return Config.insert({OptionName, std::string(DefaultVal)}).first->second;
1090}
1091
1093 DiagnosticsEngine *Diags,
1094 StringRef &OptionField, StringRef Name,
1095 StringRef DefaultVal) {
1096 // String options may be known to invalid (e.g. if the expected string is a
1097 // file name, but the file does not exist), those will have to be checked in
1098 // parseConfigs.
1099 OptionField = getStringOption(Config, Name, DefaultVal);
1100}
1101
1103 DiagnosticsEngine *Diags,
1104 bool &OptionField, StringRef Name, bool DefaultVal) {
1105 auto PossiblyInvalidVal =
1106 llvm::StringSwitch<std::optional<bool>>(
1107 getStringOption(Config, Name, (DefaultVal ? "true" : "false")))
1108 .Case("true", true)
1109 .Case("false", false)
1110 .Default(std::nullopt);
1111
1112 if (!PossiblyInvalidVal) {
1113 if (Diags)
1114 Diags->Report(diag::err_analyzer_config_invalid_input)
1115 << Name << "a boolean";
1116 else
1117 OptionField = DefaultVal;
1118 } else
1119 OptionField = *PossiblyInvalidVal;
1120}
1121
1123 DiagnosticsEngine *Diags,
1124 unsigned &OptionField, StringRef Name,
1125 unsigned DefaultVal) {
1126
1127 OptionField = DefaultVal;
1128 bool HasFailed = getStringOption(Config, Name, std::to_string(DefaultVal))
1129 .getAsInteger(0, OptionField);
1130 if (Diags && HasFailed)
1131 Diags->Report(diag::err_analyzer_config_invalid_input)
1132 << Name << "an unsigned";
1133}
1134
1136 DiagnosticsEngine *Diags) {
1137 // TODO: There's no need to store the entire configtable, it'd be plenty
1138 // enough to store checker options.
1139
1140#define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL) \
1141 initOption(AnOpts.Config, Diags, AnOpts.NAME, CMDFLAG, DEFAULT_VAL);
1142#define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(...)
1143#include "clang/StaticAnalyzer/Core/AnalyzerOptions.def"
1144
1145 assert(AnOpts.UserMode == "shallow" || AnOpts.UserMode == "deep");
1146 const bool InShallowMode = AnOpts.UserMode == "shallow";
1147
1148#define ANALYZER_OPTION(...)
1149#define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC, \
1150 SHALLOW_VAL, DEEP_VAL) \
1151 initOption(AnOpts.Config, Diags, AnOpts.NAME, CMDFLAG, \
1152 InShallowMode ? SHALLOW_VAL : DEEP_VAL);
1153#include "clang/StaticAnalyzer/Core/AnalyzerOptions.def"
1154
1155 // At this point, AnalyzerOptions is configured. Let's validate some options.
1156
1157 // FIXME: Here we try to validate the silenced checkers or packages are valid.
1158 // The current approach only validates the registered checkers which does not
1159 // contain the runtime enabled checkers and optimally we would validate both.
1160 if (!AnOpts.RawSilencedCheckersAndPackages.empty()) {
1161 std::vector<StringRef> Checkers =
1162 AnOpts.getRegisteredCheckers(/*IncludeExperimental=*/true);
1163 std::vector<StringRef> Packages =
1164 AnOpts.getRegisteredPackages(/*IncludeExperimental=*/true);
1165
1166 SmallVector<StringRef, 16> CheckersAndPackages;
1167 AnOpts.RawSilencedCheckersAndPackages.split(CheckersAndPackages, ";");
1168
1169 for (const StringRef &CheckerOrPackage : CheckersAndPackages) {
1170 if (Diags) {
1171 bool IsChecker = CheckerOrPackage.contains('.');
1172 bool IsValidName = IsChecker
1173 ? llvm::is_contained(Checkers, CheckerOrPackage)
1174 : llvm::is_contained(Packages, CheckerOrPackage);
1175
1176 if (!IsValidName)
1177 Diags->Report(diag::err_unknown_analyzer_checker_or_package)
1178 << CheckerOrPackage;
1179 }
1180
1181 AnOpts.SilencedCheckersAndPackages.emplace_back(CheckerOrPackage);
1182 }
1183 }
1184
1185 if (!Diags)
1186 return;
1187
1188 if (AnOpts.ShouldTrackConditionsDebug && !AnOpts.ShouldTrackConditions)
1189 Diags->Report(diag::err_analyzer_config_invalid_input)
1190 << "track-conditions-debug" << "'track-conditions' to also be enabled";
1191
1192 if (!AnOpts.CTUDir.empty() && !llvm::sys::fs::is_directory(AnOpts.CTUDir))
1193 Diags->Report(diag::err_analyzer_config_invalid_input) << "ctu-dir"
1194 << "a filename";
1195
1196 if (!AnOpts.ModelPath.empty() &&
1197 !llvm::sys::fs::is_directory(AnOpts.ModelPath))
1198 Diags->Report(diag::err_analyzer_config_invalid_input) << "model-path"
1199 << "a filename";
1200}
1201
1202/// Generate a remark argument. This is an inverse of `ParseOptimizationRemark`.
1203static void
1206 OptSpecifier OptEQ, StringRef Name,
1208 if (Remark.hasValidPattern()) {
1209 GenerateArg(Args, OptEQ, Remark.Pattern, SA);
1210 } else if (Remark.Kind == CodeGenOptions::RK_Enabled) {
1211 GenerateArg(Args, OPT_R_Joined, Name, SA);
1212 } else if (Remark.Kind == CodeGenOptions::RK_Disabled) {
1213 GenerateArg(Args, OPT_R_Joined, StringRef("no-") + Name, SA);
1214 }
1215}
1216
1217/// Parse a remark command line argument. It may be missing, disabled/enabled by
1218/// '-R[no-]group' or specified with a regular expression by '-Rgroup=regexp'.
1219/// On top of that, it can be disabled/enabled globally by '-R[no-]everything'.
1222 OptSpecifier OptEQ, StringRef Name) {
1224
1225 auto InitializeResultPattern = [&Diags, &Args, &Result](const Arg *A,
1226 StringRef Pattern) {
1227 Result.Pattern = Pattern.str();
1228
1229 std::string RegexError;
1230 Result.Regex = std::make_shared<llvm::Regex>(Result.Pattern);
1231 if (!Result.Regex->isValid(RegexError)) {
1232 Diags.Report(diag::err_drv_optimization_remark_pattern)
1233 << RegexError << A->getAsString(Args);
1234 return false;
1235 }
1236
1237 return true;
1238 };
1239
1240 for (Arg *A : Args) {
1241 if (A->getOption().matches(OPT_R_Joined)) {
1242 StringRef Value = A->getValue();
1243
1244 if (Value == Name)
1246 else if (Value == "everything")
1248 else if (Value.split('-') == std::make_pair(StringRef("no"), Name))
1250 else if (Value == "no-everything")
1252 else
1253 continue;
1254
1255 if (Result.Kind == CodeGenOptions::RK_Disabled ||
1257 Result.Pattern = "";
1258 Result.Regex = nullptr;
1259 } else {
1260 InitializeResultPattern(A, ".*");
1261 }
1262 } else if (A->getOption().matches(OptEQ)) {
1264 if (!InitializeResultPattern(A, A->getValue()))
1266 }
1267 }
1268
1269 return Result;
1270}
1271
1272static bool parseDiagnosticLevelMask(StringRef FlagName,
1273 const std::vector<std::string> &Levels,
1274 DiagnosticsEngine &Diags,
1276 bool Success = true;
1277 for (const auto &Level : Levels) {
1278 DiagnosticLevelMask const PM =
1279 llvm::StringSwitch<DiagnosticLevelMask>(Level)
1280 .Case("note", DiagnosticLevelMask::Note)
1281 .Case("remark", DiagnosticLevelMask::Remark)
1282 .Case("warning", DiagnosticLevelMask::Warning)
1283 .Case("error", DiagnosticLevelMask::Error)
1284 .Default(DiagnosticLevelMask::None);
1285 if (PM == DiagnosticLevelMask::None) {
1286 Success = false;
1287 Diags.Report(diag::err_drv_invalid_value) << FlagName << Level;
1288 }
1289 M = M | PM;
1290 }
1291 return Success;
1292}
1293
1294static void parseSanitizerKinds(StringRef FlagName,
1295 const std::vector<std::string> &Sanitizers,
1296 DiagnosticsEngine &Diags, SanitizerSet &S) {
1297 for (const auto &Sanitizer : Sanitizers) {
1298 SanitizerMask K = parseSanitizerValue(Sanitizer, /*AllowGroups=*/false);
1299 if (K == SanitizerMask())
1300 Diags.Report(diag::err_drv_invalid_value) << FlagName << Sanitizer;
1301 else
1302 S.set(K, true);
1303 }
1304}
1305
1308 serializeSanitizerSet(S, Values);
1309 return Values;
1310}
1311
1312static void parseXRayInstrumentationBundle(StringRef FlagName, StringRef Bundle,
1313 ArgList &Args, DiagnosticsEngine &D,
1314 XRayInstrSet &S) {
1316 llvm::SplitString(Bundle, BundleParts, ",");
1317 for (const auto &B : BundleParts) {
1318 auto Mask = parseXRayInstrValue(B);
1319 if (Mask == XRayInstrKind::None)
1320 if (B != "none")
1321 D.Report(diag::err_drv_invalid_value) << FlagName << Bundle;
1322 else
1323 S.Mask = Mask;
1324 else if (Mask == XRayInstrKind::All)
1325 S.Mask = Mask;
1326 else
1327 S.set(Mask, true);
1328 }
1329}
1330
1333 serializeXRayInstrValue(S, BundleParts);
1334 std::string Buffer;
1335 llvm::raw_string_ostream OS(Buffer);
1336 llvm::interleave(BundleParts, OS, [&OS](StringRef Part) { OS << Part; }, ",");
1337 return Buffer;
1338}
1339
1340// Set the profile kind using fprofile-instrument-use-path.
1342 const Twine &ProfileName,
1343 llvm::vfs::FileSystem &FS,
1344 DiagnosticsEngine &Diags) {
1345 auto ReaderOrErr = llvm::IndexedInstrProfReader::create(ProfileName, FS);
1346 if (auto E = ReaderOrErr.takeError()) {
1347 unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
1348 "Error in reading profile %0: %1");
1349 llvm::handleAllErrors(std::move(E), [&](const llvm::ErrorInfoBase &EI) {
1350 Diags.Report(DiagID) << ProfileName.str() << EI.message();
1351 });
1352 return;
1353 }
1354 std::unique_ptr<llvm::IndexedInstrProfReader> PGOReader =
1355 std::move(ReaderOrErr.get());
1356 // Currently memprof profiles are only added at the IR level. Mark the profile
1357 // type as IR in that case as well and the subsequent matching needs to detect
1358 // which is available (might be one or both).
1359 if (PGOReader->isIRLevelProfile() || PGOReader->hasMemoryProfile()) {
1360 if (PGOReader->hasCSIRLevelProfile())
1361 Opts.setProfileUse(CodeGenOptions::ProfileCSIRInstr);
1362 else
1363 Opts.setProfileUse(CodeGenOptions::ProfileIRInstr);
1364 } else
1365 Opts.setProfileUse(CodeGenOptions::ProfileClangInstr);
1366}
1367
1368void CompilerInvocation::GenerateCodeGenArgs(
1370 StringAllocator SA, const llvm::Triple &T, const std::string &OutputFile,
1371 const LangOptions *LangOpts) {
1372 const CodeGenOptions &CodeGenOpts = Opts;
1373
1374 if (Opts.OptimizationLevel == 0)
1375 GenerateArg(Args, OPT_O0, SA);
1376 else
1377 GenerateArg(Args, OPT_O, Twine(Opts.OptimizationLevel), SA);
1378
1379#define CODEGEN_OPTION_WITH_MARSHALLING(...) \
1380 GENERATE_OPTION_WITH_MARSHALLING(Args, SA, __VA_ARGS__)
1381#include "clang/Driver/Options.inc"
1382#undef CODEGEN_OPTION_WITH_MARSHALLING
1383
1384 if (Opts.OptimizationLevel > 0) {
1385 if (Opts.Inlining == CodeGenOptions::NormalInlining)
1386 GenerateArg(Args, OPT_finline_functions, SA);
1387 else if (Opts.Inlining == CodeGenOptions::OnlyHintInlining)
1388 GenerateArg(Args, OPT_finline_hint_functions, SA);
1389 else if (Opts.Inlining == CodeGenOptions::OnlyAlwaysInlining)
1390 GenerateArg(Args, OPT_fno_inline, SA);
1391 }
1392
1393 if (Opts.DirectAccessExternalData && LangOpts->PICLevel != 0)
1394 GenerateArg(Args, OPT_fdirect_access_external_data, SA);
1395 else if (!Opts.DirectAccessExternalData && LangOpts->PICLevel == 0)
1396 GenerateArg(Args, OPT_fno_direct_access_external_data, SA);
1397
1398 std::optional<StringRef> DebugInfoVal;
1399 switch (Opts.DebugInfo) {
1400 case llvm::codegenoptions::DebugLineTablesOnly:
1401 DebugInfoVal = "line-tables-only";
1402 break;
1403 case llvm::codegenoptions::DebugDirectivesOnly:
1404 DebugInfoVal = "line-directives-only";
1405 break;
1406 case llvm::codegenoptions::DebugInfoConstructor:
1407 DebugInfoVal = "constructor";
1408 break;
1409 case llvm::codegenoptions::LimitedDebugInfo:
1410 DebugInfoVal = "limited";
1411 break;
1412 case llvm::codegenoptions::FullDebugInfo:
1413 DebugInfoVal = "standalone";
1414 break;
1415 case llvm::codegenoptions::UnusedTypeInfo:
1416 DebugInfoVal = "unused-types";
1417 break;
1418 case llvm::codegenoptions::NoDebugInfo: // default value
1419 DebugInfoVal = std::nullopt;
1420 break;
1421 case llvm::codegenoptions::LocTrackingOnly: // implied value
1422 DebugInfoVal = std::nullopt;
1423 break;
1424 }
1425 if (DebugInfoVal)
1426 GenerateArg(Args, OPT_debug_info_kind_EQ, *DebugInfoVal, SA);
1427
1428 for (const auto &Prefix : Opts.DebugPrefixMap)
1429 GenerateArg(Args, OPT_fdebug_prefix_map_EQ,
1430 Prefix.first + "=" + Prefix.second, SA);
1431
1432 for (const auto &Prefix : Opts.CoveragePrefixMap)
1433 GenerateArg(Args, OPT_fcoverage_prefix_map_EQ,
1434 Prefix.first + "=" + Prefix.second, SA);
1435
1436 if (Opts.NewStructPathTBAA)
1437 GenerateArg(Args, OPT_new_struct_path_tbaa, SA);
1438
1439 if (Opts.OptimizeSize == 1)
1440 GenerateArg(Args, OPT_O, "s", SA);
1441 else if (Opts.OptimizeSize == 2)
1442 GenerateArg(Args, OPT_O, "z", SA);
1443
1444 // SimplifyLibCalls is set only in the absence of -fno-builtin and
1445 // -ffreestanding. We'll consider that when generating them.
1446
1447 // NoBuiltinFuncs are generated by LangOptions.
1448
1449 if (Opts.UnrollLoops && Opts.OptimizationLevel <= 1)
1450 GenerateArg(Args, OPT_funroll_loops, SA);
1451 else if (!Opts.UnrollLoops && Opts.OptimizationLevel > 1)
1452 GenerateArg(Args, OPT_fno_unroll_loops, SA);
1453
1454 if (!Opts.BinutilsVersion.empty())
1455 GenerateArg(Args, OPT_fbinutils_version_EQ, Opts.BinutilsVersion, SA);
1456
1457 if (Opts.DebugNameTable ==
1458 static_cast<unsigned>(llvm::DICompileUnit::DebugNameTableKind::GNU))
1459 GenerateArg(Args, OPT_ggnu_pubnames, SA);
1460 else if (Opts.DebugNameTable ==
1461 static_cast<unsigned>(
1462 llvm::DICompileUnit::DebugNameTableKind::Default))
1463 GenerateArg(Args, OPT_gpubnames, SA);
1464
1465 auto TNK = Opts.getDebugSimpleTemplateNames();
1466 if (TNK != llvm::codegenoptions::DebugTemplateNamesKind::Full) {
1467 if (TNK == llvm::codegenoptions::DebugTemplateNamesKind::Simple)
1468 GenerateArg(Args, OPT_gsimple_template_names_EQ, "simple", SA);
1469 else if (TNK == llvm::codegenoptions::DebugTemplateNamesKind::Mangled)
1470 GenerateArg(Args, OPT_gsimple_template_names_EQ, "mangled", SA);
1471 }
1472 // ProfileInstrumentUsePath is marshalled automatically, no need to generate
1473 // it or PGOUseInstrumentor.
1474
1475 if (Opts.TimePasses) {
1476 if (Opts.TimePassesPerRun)
1477 GenerateArg(Args, OPT_ftime_report_EQ, "per-pass-run", SA);
1478 else
1479 GenerateArg(Args, OPT_ftime_report, SA);
1480 }
1481
1482 if (Opts.PrepareForLTO && !Opts.PrepareForThinLTO)
1483 GenerateArg(Args, OPT_flto_EQ, "full", SA);
1484
1485 if (Opts.PrepareForThinLTO)
1486 GenerateArg(Args, OPT_flto_EQ, "thin", SA);
1487
1488 if (!Opts.ThinLTOIndexFile.empty())
1489 GenerateArg(Args, OPT_fthinlto_index_EQ, Opts.ThinLTOIndexFile, SA);
1490
1491 if (Opts.SaveTempsFilePrefix == OutputFile)
1492 GenerateArg(Args, OPT_save_temps_EQ, "obj", SA);
1493
1494 StringRef MemProfileBasename("memprof.profraw");
1495 if (!Opts.MemoryProfileOutput.empty()) {
1496 if (Opts.MemoryProfileOutput == MemProfileBasename) {
1497 GenerateArg(Args, OPT_fmemory_profile, SA);
1498 } else {
1499 size_t ArgLength =
1500 Opts.MemoryProfileOutput.size() - MemProfileBasename.size();
1501 GenerateArg(Args, OPT_fmemory_profile_EQ,
1502 Opts.MemoryProfileOutput.substr(0, ArgLength), SA);
1503 }
1504 }
1505
1506 if (memcmp(Opts.CoverageVersion, "408*", 4) != 0)
1507 GenerateArg(Args, OPT_coverage_version_EQ,
1508 StringRef(Opts.CoverageVersion, 4), SA);
1509
1510 // TODO: Check if we need to generate arguments stored in CmdArgs. (Namely
1511 // '-fembed_bitcode', which does not map to any CompilerInvocation field and
1512 // won't be generated.)
1513
1515 std::string InstrBundle =
1517 if (!InstrBundle.empty())
1518 GenerateArg(Args, OPT_fxray_instrumentation_bundle, InstrBundle, SA);
1519 }
1520
1521 if (Opts.CFProtectionReturn && Opts.CFProtectionBranch)
1522 GenerateArg(Args, OPT_fcf_protection_EQ, "full", SA);
1523 else if (Opts.CFProtectionReturn)
1524 GenerateArg(Args, OPT_fcf_protection_EQ, "return", SA);
1525 else if (Opts.CFProtectionBranch)
1526 GenerateArg(Args, OPT_fcf_protection_EQ, "branch", SA);
1527
1528 if (Opts.FunctionReturnThunks)
1529 GenerateArg(Args, OPT_mfunction_return_EQ, "thunk-extern", SA);
1530
1531 for (const auto &F : Opts.LinkBitcodeFiles) {
1532 bool Builtint = F.LinkFlags == llvm::Linker::Flags::LinkOnlyNeeded &&
1533 F.PropagateAttrs && F.Internalize;
1534 GenerateArg(Args,
1535 Builtint ? OPT_mlink_builtin_bitcode : OPT_mlink_bitcode_file,
1536 F.Filename, SA);
1537 }
1538
1540 Args, Opts.EmulatedTLS ? OPT_femulated_tls : OPT_fno_emulated_tls, SA);
1541
1542 if (Opts.FPDenormalMode != llvm::DenormalMode::getIEEE())
1543 GenerateArg(Args, OPT_fdenormal_fp_math_EQ, Opts.FPDenormalMode.str(), SA);
1544
1545 if ((Opts.FPDenormalMode != Opts.FP32DenormalMode) ||
1546 (Opts.FP32DenormalMode != llvm::DenormalMode::getIEEE()))
1547 GenerateArg(Args, OPT_fdenormal_fp_math_f32_EQ, Opts.FP32DenormalMode.str(),
1548 SA);
1549
1550 if (Opts.StructReturnConvention == CodeGenOptions::SRCK_OnStack) {
1551 OptSpecifier Opt =
1552 T.isPPC32() ? OPT_maix_struct_return : OPT_fpcc_struct_return;
1553 GenerateArg(Args, Opt, SA);
1554 } else if (Opts.StructReturnConvention == CodeGenOptions::SRCK_InRegs) {
1555 OptSpecifier Opt =
1556 T.isPPC32() ? OPT_msvr4_struct_return : OPT_freg_struct_return;
1557 GenerateArg(Args, Opt, SA);
1558 }
1559
1560 if (Opts.EnableAIXExtendedAltivecABI)
1561 GenerateArg(Args, OPT_mabi_EQ_vec_extabi, SA);
1562
1563 if (!Opts.OptRecordPasses.empty())
1564 GenerateArg(Args, OPT_opt_record_passes, Opts.OptRecordPasses, SA);
1565
1566 if (!Opts.OptRecordFormat.empty())
1567 GenerateArg(Args, OPT_opt_record_format, Opts.OptRecordFormat, SA);
1568
1569 GenerateOptimizationRemark(Args, SA, OPT_Rpass_EQ, "pass",
1570 Opts.OptimizationRemark);
1571
1572 GenerateOptimizationRemark(Args, SA, OPT_Rpass_missed_EQ, "pass-missed",
1574
1575 GenerateOptimizationRemark(Args, SA, OPT_Rpass_analysis_EQ, "pass-analysis",
1577
1578 GenerateArg(Args, OPT_fdiagnostics_hotness_threshold_EQ,
1580 ? Twine(*Opts.DiagnosticsHotnessThreshold)
1581 : "auto",
1582 SA);
1583
1584 GenerateArg(Args, OPT_fdiagnostics_misexpect_tolerance_EQ,
1585 Twine(*Opts.DiagnosticsMisExpectTolerance), SA);
1586
1587 for (StringRef Sanitizer : serializeSanitizerKinds(Opts.SanitizeRecover))
1588 GenerateArg(Args, OPT_fsanitize_recover_EQ, Sanitizer, SA);
1589
1590 for (StringRef Sanitizer : serializeSanitizerKinds(Opts.SanitizeTrap))
1591 GenerateArg(Args, OPT_fsanitize_trap_EQ, Sanitizer, SA);
1592
1593 if (!Opts.EmitVersionIdentMetadata)
1594 GenerateArg(Args, OPT_Qn, SA);
1595
1596 switch (Opts.FiniteLoops) {
1598 break;
1600 GenerateArg(Args, OPT_ffinite_loops, SA);
1601 break;
1603 GenerateArg(Args, OPT_fno_finite_loops, SA);
1604 break;
1605 }
1606}
1607
1608bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
1609 InputKind IK,
1610 DiagnosticsEngine &Diags,
1611 const llvm::Triple &T,
1612 const std::string &OutputFile,
1613 const LangOptions &LangOptsRef) {
1614 unsigned NumErrorsBefore = Diags.getNumErrors();
1615
1616 unsigned OptimizationLevel = getOptimizationLevel(Args, IK, Diags);
1617 // TODO: This could be done in Driver
1618 unsigned MaxOptLevel = 3;
1619 if (OptimizationLevel > MaxOptLevel) {
1620 // If the optimization level is not supported, fall back on the default
1621 // optimization
1622 Diags.Report(diag::warn_drv_optimization_value)
1623 << Args.getLastArg(OPT_O)->getAsString(Args) << "-O" << MaxOptLevel;
1624 OptimizationLevel = MaxOptLevel;
1625 }
1626 Opts.OptimizationLevel = OptimizationLevel;
1627
1628 // The key paths of codegen options defined in Options.td start with
1629 // "CodeGenOpts.". Let's provide the expected variable name and type.
1631 // Some codegen options depend on language options. Let's provide the expected
1632 // variable name and type.
1633 const LangOptions *LangOpts = &LangOptsRef;
1634
1635#define CODEGEN_OPTION_WITH_MARSHALLING(...) \
1636 PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
1637#include "clang/Driver/Options.inc"
1638#undef CODEGEN_OPTION_WITH_MARSHALLING
1639
1640 // At O0 we want to fully disable inlining outside of cases marked with
1641 // 'alwaysinline' that are required for correctness.
1642 if (Opts.OptimizationLevel == 0) {
1643 Opts.setInlining(CodeGenOptions::OnlyAlwaysInlining);
1644 } else if (const Arg *A = Args.getLastArg(options::OPT_finline_functions,
1645 options::OPT_finline_hint_functions,
1646 options::OPT_fno_inline_functions,
1647 options::OPT_fno_inline)) {
1648 // Explicit inlining flags can disable some or all inlining even at
1649 // optimization levels above zero.
1650 if (A->getOption().matches(options::OPT_finline_functions))
1651 Opts.setInlining(CodeGenOptions::NormalInlining);
1652 else if (A->getOption().matches(options::OPT_finline_hint_functions))
1653 Opts.setInlining(CodeGenOptions::OnlyHintInlining);
1654 else
1655 Opts.setInlining(CodeGenOptions::OnlyAlwaysInlining);
1656 } else {
1657 Opts.setInlining(CodeGenOptions::NormalInlining);
1658 }
1659
1660 // PIC defaults to -fno-direct-access-external-data while non-PIC defaults to
1661 // -fdirect-access-external-data.
1662 Opts.DirectAccessExternalData =
1663 Args.hasArg(OPT_fdirect_access_external_data) ||
1664 (!Args.hasArg(OPT_fno_direct_access_external_data) &&
1665 LangOpts->PICLevel == 0);
1666
1667 if (Arg *A = Args.getLastArg(OPT_debug_info_kind_EQ)) {
1668 unsigned Val =
1669 llvm::StringSwitch<unsigned>(A->getValue())
1670 .Case("line-tables-only", llvm::codegenoptions::DebugLineTablesOnly)
1671 .Case("line-directives-only",
1672 llvm::codegenoptions::DebugDirectivesOnly)
1673 .Case("constructor", llvm::codegenoptions::DebugInfoConstructor)
1674 .Case("limited", llvm::codegenoptions::LimitedDebugInfo)
1675 .Case("standalone", llvm::codegenoptions::FullDebugInfo)
1676 .Case("unused-types", llvm::codegenoptions::UnusedTypeInfo)
1677 .Default(~0U);
1678 if (Val == ~0U)
1679 Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args)
1680 << A->getValue();
1681 else
1682 Opts.setDebugInfo(static_cast<llvm::codegenoptions::DebugInfoKind>(Val));
1683 }
1684
1685 // If -fuse-ctor-homing is set and limited debug info is already on, then use
1686 // constructor homing, and vice versa for -fno-use-ctor-homing.
1687 if (const Arg *A =
1688 Args.getLastArg(OPT_fuse_ctor_homing, OPT_fno_use_ctor_homing)) {
1689 if (A->getOption().matches(OPT_fuse_ctor_homing) &&
1690 Opts.getDebugInfo() == llvm::codegenoptions::LimitedDebugInfo)
1691 Opts.setDebugInfo(llvm::codegenoptions::DebugInfoConstructor);
1692 if (A->getOption().matches(OPT_fno_use_ctor_homing) &&
1693 Opts.getDebugInfo() == llvm::codegenoptions::DebugInfoConstructor)
1694 Opts.setDebugInfo(llvm::codegenoptions::LimitedDebugInfo);
1695 }
1696
1697 for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ)) {
1698 auto Split = StringRef(Arg).split('=');
1699 Opts.DebugPrefixMap.insert(
1700 {std::string(Split.first), std::string(Split.second)});
1701 }
1702
1703 for (const auto &Arg : Args.getAllArgValues(OPT_fcoverage_prefix_map_EQ)) {
1704 auto Split = StringRef(Arg).split('=');
1705 Opts.CoveragePrefixMap.insert(
1706 {std::string(Split.first), std::string(Split.second)});
1707 }
1708
1709 const llvm::Triple::ArchType DebugEntryValueArchs[] = {
1710 llvm::Triple::x86, llvm::Triple::x86_64, llvm::Triple::aarch64,
1711 llvm::Triple::arm, llvm::Triple::armeb, llvm::Triple::mips,
1712 llvm::Triple::mipsel, llvm::Triple::mips64, llvm::Triple::mips64el};
1713
1714 if (Opts.OptimizationLevel > 0 && Opts.hasReducedDebugInfo() &&
1715 llvm::is_contained(DebugEntryValueArchs, T.getArch()))
1716 Opts.EmitCallSiteInfo = true;
1717
1718 if (!Opts.EnableDIPreservationVerify && Opts.DIBugsReportFilePath.size()) {
1719 Diags.Report(diag::warn_ignoring_verify_debuginfo_preserve_export)
1720 << Opts.DIBugsReportFilePath;
1721 Opts.DIBugsReportFilePath = "";
1722 }
1723
1724 Opts.NewStructPathTBAA = !Args.hasArg(OPT_no_struct_path_tbaa) &&
1725 Args.hasArg(OPT_new_struct_path_tbaa);
1726 Opts.OptimizeSize = getOptimizationLevelSize(Args);
1727 Opts.SimplifyLibCalls = !LangOpts->NoBuiltin;
1728 if (Opts.SimplifyLibCalls)
1729 Opts.NoBuiltinFuncs = LangOpts->NoBuiltinFuncs;
1730 Opts.UnrollLoops =
1731 Args.hasFlag(OPT_funroll_loops, OPT_fno_unroll_loops,
1732 (Opts.OptimizationLevel > 1));
1733 Opts.BinutilsVersion =
1734 std::string(Args.getLastArgValue(OPT_fbinutils_version_EQ));
1735
1736 Opts.DebugNameTable = static_cast<unsigned>(
1737 Args.hasArg(OPT_ggnu_pubnames)
1738 ? llvm::DICompileUnit::DebugNameTableKind::GNU
1739 : Args.hasArg(OPT_gpubnames)
1740 ? llvm::DICompileUnit::DebugNameTableKind::Default
1741 : llvm::DICompileUnit::DebugNameTableKind::None);
1742 if (const Arg *A = Args.getLastArg(OPT_gsimple_template_names_EQ)) {
1743 StringRef Value = A->getValue();
1744 if (Value != "simple" && Value != "mangled")
1745 Diags.Report(diag::err_drv_unsupported_option_argument)
1746 << A->getSpelling() << A->getValue();
1747 Opts.setDebugSimpleTemplateNames(
1748 StringRef(A->getValue()) == "simple"
1749 ? llvm::codegenoptions::DebugTemplateNamesKind::Simple
1750 : llvm::codegenoptions::DebugTemplateNamesKind::Mangled);
1751 }
1752
1753 if (const Arg *A = Args.getLastArg(OPT_ftime_report, OPT_ftime_report_EQ)) {
1754 Opts.TimePasses = true;
1755
1756 // -ftime-report= is only for new pass manager.
1757 if (A->getOption().getID() == OPT_ftime_report_EQ) {
1758 StringRef Val = A->getValue();
1759 if (Val == "per-pass")
1760 Opts.TimePassesPerRun = false;
1761 else if (Val == "per-pass-run")
1762 Opts.TimePassesPerRun = true;
1763 else
1764 Diags.Report(diag::err_drv_invalid_value)
1765 << A->getAsString(Args) << A->getValue();
1766 }
1767 }
1768
1769 Opts.PrepareForLTO = false;
1770 Opts.PrepareForThinLTO = false;
1771 if (Arg *A = Args.getLastArg(OPT_flto_EQ)) {
1772 Opts.PrepareForLTO = true;
1773 StringRef S = A->getValue();
1774 if (S == "thin")
1775 Opts.PrepareForThinLTO = true;
1776 else if (S != "full")
1777 Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << S;
1778 }
1779 if (Arg *A = Args.getLastArg(OPT_fthinlto_index_EQ)) {
1780 if (IK.getLanguage() != Language::LLVM_IR)
1781 Diags.Report(diag::err_drv_argument_only_allowed_with)
1782 << A->getAsString(Args) << "-x ir";
1783 Opts.ThinLTOIndexFile =
1784 std::string(Args.getLastArgValue(OPT_fthinlto_index_EQ));
1785 }
1786 if (Arg *A = Args.getLastArg(OPT_save_temps_EQ))
1787 Opts.SaveTempsFilePrefix =
1788 llvm::StringSwitch<std::string>(A->getValue())
1789 .Case("obj", OutputFile)
1790 .Default(llvm::sys::path::filename(OutputFile).str());
1791
1792 // The memory profile runtime appends the pid to make this name more unique.
1793 const char *MemProfileBasename = "memprof.profraw";
1794 if (Args.hasArg(OPT_fmemory_profile_EQ)) {
1795 SmallString<128> Path(
1796 std::string(Args.getLastArgValue(OPT_fmemory_profile_EQ)));
1797 llvm::sys::path::append(Path, MemProfileBasename);
1798 Opts.MemoryProfileOutput = std::string(Path);
1799 } else if (Args.hasArg(OPT_fmemory_profile))
1800 Opts.MemoryProfileOutput = MemProfileBasename;
1801
1802 memcpy(Opts.CoverageVersion, "408*", 4);
1803 if (Opts.EmitGcovArcs || Opts.EmitGcovNotes) {
1804 if (Args.hasArg(OPT_coverage_version_EQ)) {
1805 StringRef CoverageVersion = Args.getLastArgValue(OPT_coverage_version_EQ);
1806 if (CoverageVersion.size() != 4) {
1807 Diags.Report(diag::err_drv_invalid_value)
1808 << Args.getLastArg(OPT_coverage_version_EQ)->getAsString(Args)
1809 << CoverageVersion;
1810 } else {
1811 memcpy(Opts.CoverageVersion, CoverageVersion.data(), 4);
1812 }
1813 }
1814 }
1815 // FIXME: For backend options that are not yet recorded as function
1816 // attributes in the IR, keep track of them so we can embed them in a
1817 // separate data section and use them when building the bitcode.
1818 for (const auto &A : Args) {
1819 // Do not encode output and input.
1820 if (A->getOption().getID() == options::OPT_o ||
1821 A->getOption().getID() == options::OPT_INPUT ||
1822 A->getOption().getID() == options::OPT_x ||
1823 A->getOption().getID() == options::OPT_fembed_bitcode ||
1824 A->getOption().matches(options::OPT_W_Group))
1825 continue;
1826 ArgStringList ASL;
1827 A->render(Args, ASL);
1828 for (const auto &arg : ASL) {
1829 StringRef ArgStr(arg);
1830 Opts.CmdArgs.insert(Opts.CmdArgs.end(), ArgStr.begin(), ArgStr.end());
1831 // using \00 to separate each commandline options.
1832 Opts.CmdArgs.push_back('\0');
1833 }
1834 }
1835
1836 auto XRayInstrBundles =
1837 Args.getAllArgValues(OPT_fxray_instrumentation_bundle);
1838 if (XRayInstrBundles.empty())
1840 else
1841 for (const auto &A : XRayInstrBundles)
1842 parseXRayInstrumentationBundle("-fxray-instrumentation-bundle=", A, Args,
1843 Diags, Opts.XRayInstrumentationBundle);
1844
1845 if (const Arg *A = Args.getLastArg(OPT_fcf_protection_EQ)) {
1846 StringRef Name = A->getValue();
1847 if (Name == "full") {
1848 Opts.CFProtectionReturn = 1;
1849 Opts.CFProtectionBranch = 1;
1850 } else if (Name == "return")
1851 Opts.CFProtectionReturn = 1;
1852 else if (Name == "branch")
1853 Opts.CFProtectionBranch = 1;
1854 else if (Name != "none")
1855 Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name;
1856 }
1857
1858 if (const Arg *A = Args.getLastArg(OPT_mfunction_return_EQ)) {
1859 auto Val = llvm::StringSwitch<llvm::FunctionReturnThunksKind>(A->getValue())
1860 .Case("keep", llvm::FunctionReturnThunksKind::Keep)
1861 .Case("thunk-extern", llvm::FunctionReturnThunksKind::Extern)
1862 .Default(llvm::FunctionReturnThunksKind::Invalid);
1863 // SystemZ might want to add support for "expolines."
1864 if (!T.isX86())
1865 Diags.Report(diag::err_drv_argument_not_allowed_with)
1866 << A->getSpelling() << T.getTriple();
1867 else if (Val == llvm::FunctionReturnThunksKind::Invalid)
1868 Diags.Report(diag::err_drv_invalid_value)
1869 << A->getAsString(Args) << A->getValue();
1870 else if (Val == llvm::FunctionReturnThunksKind::Extern &&
1871 Args.getLastArgValue(OPT_mcmodel_EQ).equals("large"))
1872 Diags.Report(diag::err_drv_argument_not_allowed_with)
1873 << A->getAsString(Args)
1874 << Args.getLastArg(OPT_mcmodel_EQ)->getAsString(Args);
1875 else
1876 Opts.FunctionReturnThunks = static_cast<unsigned>(Val);
1877 }
1878
1879 for (auto *A :
1880 Args.filtered(OPT_mlink_bitcode_file, OPT_mlink_builtin_bitcode)) {
1882 F.Filename = A->getValue();
1883 if (A->getOption().matches(OPT_mlink_builtin_bitcode)) {
1884 F.LinkFlags = llvm::Linker::Flags::LinkOnlyNeeded;
1885 // When linking CUDA bitcode, propagate function attributes so that
1886 // e.g. libdevice gets fast-math attrs if we're building with fast-math.
1887 F.PropagateAttrs = true;
1888 F.Internalize = true;
1889 }
1890 Opts.LinkBitcodeFiles.push_back(F);
1891 }
1892
1893 if (!Args.getLastArg(OPT_femulated_tls) &&
1894 !Args.getLastArg(OPT_fno_emulated_tls)) {
1895 Opts.EmulatedTLS = T.hasDefaultEmulatedTLS();
1896 }
1897
1898 if (Arg *A = Args.getLastArg(OPT_ftlsmodel_EQ)) {
1899 if (T.isOSAIX()) {
1900 StringRef Name = A->getValue();
1901 if (Name != "global-dynamic")
1902 Diags.Report(diag::err_aix_unsupported_tls_model) << Name;
1903 }
1904 }
1905
1906 if (Arg *A = Args.getLastArg(OPT_fdenormal_fp_math_EQ)) {
1907 StringRef Val = A->getValue();
1908 Opts.FPDenormalMode = llvm::parseDenormalFPAttribute(Val);
1909 Opts.FP32DenormalMode = Opts.FPDenormalMode;
1910 if (!Opts.FPDenormalMode.isValid())
1911 Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;
1912 }
1913
1914 if (Arg *A = Args.getLastArg(OPT_fdenormal_fp_math_f32_EQ)) {
1915 StringRef Val = A->getValue();
1916 Opts.FP32DenormalMode = llvm::parseDenormalFPAttribute(Val);
1917 if (!Opts.FP32DenormalMode.isValid())
1918 Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;
1919 }
1920
1921 // X86_32 has -fppc-struct-return and -freg-struct-return.
1922 // PPC32 has -maix-struct-return and -msvr4-struct-return.
1923 if (Arg *A =
1924 Args.getLastArg(OPT_fpcc_struct_return, OPT_freg_struct_return,
1925 OPT_maix_struct_return, OPT_msvr4_struct_return)) {
1926 // TODO: We might want to consider enabling these options on AIX in the
1927 // future.
1928 if (T.isOSAIX())
1929 Diags.Report(diag::err_drv_unsupported_opt_for_target)
1930 << A->getSpelling() << T.str();
1931
1932 const Option &O = A->getOption();
1933 if (O.matches(OPT_fpcc_struct_return) ||
1934 O.matches(OPT_maix_struct_return)) {
1935 Opts.setStructReturnConvention(CodeGenOptions::SRCK_OnStack);
1936 } else {
1937 assert(O.matches(OPT_freg_struct_return) ||
1938 O.matches(OPT_msvr4_struct_return));
1939 Opts.setStructReturnConvention(CodeGenOptions::SRCK_InRegs);
1940 }
1941 }
1942
1943 if (Arg *A =
1944 Args.getLastArg(OPT_mabi_EQ_vec_default, OPT_mabi_EQ_vec_extabi)) {
1945 if (!T.isOSAIX())
1946 Diags.Report(diag::err_drv_unsupported_opt_for_target)
1947 << A->getSpelling() << T.str();
1948
1949 const Option &O = A->getOption();
1950 Opts.EnableAIXExtendedAltivecABI = O.matches(OPT_mabi_EQ_vec_extabi);
1951 }
1952
1953 if (Arg *A = Args.getLastArg(OPT_mabi_EQ_quadword_atomics)) {
1954 if (!T.isOSAIX() || T.isPPC32())
1955 Diags.Report(diag::err_drv_unsupported_opt_for_target)
1956 << A->getSpelling() << T.str();
1957 }
1958
1959 bool NeedLocTracking = false;
1960
1961 if (!Opts.OptRecordFile.empty())
1962 NeedLocTracking = true;
1963
1964 if (Arg *A = Args.getLastArg(OPT_opt_record_passes)) {
1965 Opts.OptRecordPasses = A->getValue();
1966 NeedLocTracking = true;
1967 }
1968
1969 if (Arg *A = Args.getLastArg(OPT_opt_record_format)) {
1970 Opts.OptRecordFormat = A->getValue();
1971 NeedLocTracking = true;
1972 }
1973
1974 Opts.OptimizationRemark =
1975 ParseOptimizationRemark(Diags, Args, OPT_Rpass_EQ, "pass");
1976
1978 ParseOptimizationRemark(Diags, Args, OPT_Rpass_missed_EQ, "pass-missed");
1979
1981 Diags, Args, OPT_Rpass_analysis_EQ, "pass-analysis");
1982
1983 NeedLocTracking |= Opts.OptimizationRemark.hasValidPattern() ||
1986
1987 bool UsingSampleProfile = !Opts.SampleProfileFile.empty();
1988 bool UsingProfile =
1989 UsingSampleProfile || !Opts.ProfileInstrumentUsePath.empty();
1990
1991 if (Opts.DiagnosticsWithHotness && !UsingProfile &&
1992 // An IR file will contain PGO as metadata
1994 Diags.Report(diag::warn_drv_diagnostics_hotness_requires_pgo)
1995 << "-fdiagnostics-show-hotness";
1996
1997 // Parse remarks hotness threshold. Valid value is either integer or 'auto'.
1998 if (auto *arg =
1999 Args.getLastArg(options::OPT_fdiagnostics_hotness_threshold_EQ)) {
2000 auto ResultOrErr =
2001 llvm::remarks::parseHotnessThresholdOption(arg->getValue());
2002
2003 if (!ResultOrErr) {
2004 Diags.Report(diag::err_drv_invalid_diagnotics_hotness_threshold)
2005 << "-fdiagnostics-hotness-threshold=";
2006 } else {
2007 Opts.DiagnosticsHotnessThreshold = *ResultOrErr;
2008 if ((!Opts.DiagnosticsHotnessThreshold ||
2009 *Opts.DiagnosticsHotnessThreshold > 0) &&
2010 !UsingProfile)
2011 Diags.Report(diag::warn_drv_diagnostics_hotness_requires_pgo)
2012 << "-fdiagnostics-hotness-threshold=";
2013 }
2014 }
2015
2016 if (auto *arg =
2017 Args.getLastArg(options::OPT_fdiagnostics_misexpect_tolerance_EQ)) {
2018 auto ResultOrErr = parseToleranceOption(arg->getValue());
2019
2020 if (!ResultOrErr) {
2021 Diags.Report(diag::err_drv_invalid_diagnotics_misexpect_tolerance)
2022 << "-fdiagnostics-misexpect-tolerance=";
2023 } else {
2024 Opts.DiagnosticsMisExpectTolerance = *ResultOrErr;
2025 if ((!Opts.DiagnosticsMisExpectTolerance ||
2026 *Opts.DiagnosticsMisExpectTolerance > 0) &&
2027 !UsingProfile)
2028 Diags.Report(diag::warn_drv_diagnostics_misexpect_requires_pgo)
2029 << "-fdiagnostics-misexpect-tolerance=";
2030 }
2031 }
2032
2033 // If the user requested to use a sample profile for PGO, then the
2034 // backend will need to track source location information so the profile
2035 // can be incorporated into the IR.
2036 if (UsingSampleProfile)
2037 NeedLocTracking = true;
2038
2039 if (!Opts.StackUsageOutput.empty())
2040 NeedLocTracking = true;
2041
2042 // If the user requested a flag that requires source locations available in
2043 // the backend, make sure that the backend tracks source location information.
2044 if (NeedLocTracking &&
2045 Opts.getDebugInfo() == llvm::codegenoptions::NoDebugInfo)
2046 Opts.setDebugInfo(llvm::codegenoptions::LocTrackingOnly);
2047
2048 // Parse -fsanitize-recover= arguments.
2049 // FIXME: Report unrecoverable sanitizers incorrectly specified here.
2050 parseSanitizerKinds("-fsanitize-recover=",
2051 Args.getAllArgValues(OPT_fsanitize_recover_EQ), Diags,
2052 Opts.SanitizeRecover);
2053 parseSanitizerKinds("-fsanitize-trap=",
2054 Args.getAllArgValues(OPT_fsanitize_trap_EQ), Diags,
2055 Opts.SanitizeTrap);
2056
2057 Opts.EmitVersionIdentMetadata = Args.hasFlag(OPT_Qy, OPT_Qn, true);
2058
2059 if (Args.hasArg(options::OPT_ffinite_loops))
2060 Opts.FiniteLoops = CodeGenOptions::FiniteLoopsKind::Always;
2061 else if (Args.hasArg(options::OPT_fno_finite_loops))
2062 Opts.FiniteLoops = CodeGenOptions::FiniteLoopsKind::Never;
2063
2064 Opts.EmitIEEENaNCompliantInsts = Args.hasFlag(
2065 options::OPT_mamdgpu_ieee, options::OPT_mno_amdgpu_ieee, true);
2066 if (!Opts.EmitIEEENaNCompliantInsts && !LangOptsRef.NoHonorNaNs)
2067 Diags.Report(diag::err_drv_amdgpu_ieee_without_no_honor_nans);
2068
2069 return Diags.getNumErrors() == NumErrorsBefore;
2070}
2071
2072static void
2076 const DependencyOutputOptions &DependencyOutputOpts = Opts;
2077#define DEPENDENCY_OUTPUT_OPTION_WITH_MARSHALLING(...) \
2078 GENERATE_OPTION_WITH_MARSHALLING(Args, SA, __VA_ARGS__)
2079#include "clang/Driver/Options.inc"
2080#undef DEPENDENCY_OUTPUT_OPTION_WITH_MARSHALLING
2081
2083 GenerateArg(Args, OPT_show_includes, SA);
2084
2085 for (const auto &Dep : Opts.ExtraDeps) {
2086 switch (Dep.second) {
2088 // Sanitizer ignorelist arguments are generated from LanguageOptions.
2089 continue;
2090 case EDK_ModuleFile:
2091 // Module file arguments are generated from FrontendOptions and
2092 // HeaderSearchOptions.
2093 continue;
2094 case EDK_ProfileList:
2095 // Profile list arguments are generated from LanguageOptions via the
2096 // marshalling infrastructure.
2097 continue;
2098 case EDK_DepFileEntry:
2099 GenerateArg(Args, OPT_fdepfile_entry, Dep.first, SA);
2100 break;
2101 }
2102 }
2103}
2104
2106 ArgList &Args, DiagnosticsEngine &Diags,
2108 bool ShowLineMarkers) {
2109 unsigned NumErrorsBefore = Diags.getNumErrors();
2110
2111 DependencyOutputOptions &DependencyOutputOpts = Opts;
2112#define DEPENDENCY_OUTPUT_OPTION_WITH_MARSHALLING(...) \
2113 PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
2114#include "clang/Driver/Options.inc"
2115#undef DEPENDENCY_OUTPUT_OPTION_WITH_MARSHALLING
2116
2117 if (Args.hasArg(OPT_show_includes)) {
2118 // Writing both /showIncludes and preprocessor output to stdout
2119 // would produce interleaved output, so use stderr for /showIncludes.
2120 // This behaves the same as cl.exe, when /E, /EP or /P are passed.
2121 if (Action == frontend::PrintPreprocessedInput || !ShowLineMarkers)
2123 else
2125 } else {
2127 }
2128
2129 // Add sanitizer ignorelists as extra dependencies.
2130 // They won't be discovered by the regular preprocessor, so
2131 // we let make / ninja to know about this implicit dependency.
2132 if (!Args.hasArg(OPT_fno_sanitize_ignorelist)) {
2133 for (const auto *A : Args.filtered(OPT_fsanitize_ignorelist_EQ)) {
2134 StringRef Val = A->getValue();
2135 if (!Val.contains('='))
2136 Opts.ExtraDeps.emplace_back(std::string(Val), EDK_SanitizeIgnorelist);
2137 }
2138 if (Opts.IncludeSystemHeaders) {
2139 for (const auto *A : Args.filtered(OPT_fsanitize_system_ignorelist_EQ)) {
2140 StringRef Val = A->getValue();
2141 if (!Val.contains('='))
2142 Opts.ExtraDeps.emplace_back(std::string(Val), EDK_SanitizeIgnorelist);
2143 }
2144 }
2145 }
2146
2147 // -fprofile-list= dependencies.
2148 for (const auto &Filename : Args.getAllArgValues(OPT_fprofile_list_EQ))
2149 Opts.ExtraDeps.emplace_back(Filename, EDK_ProfileList);
2150
2151 // Propagate the extra dependencies.
2152 for (const auto *A : Args.filtered(OPT_fdepfile_entry))
2153 Opts.ExtraDeps.emplace_back(A->getValue(), EDK_DepFileEntry);
2154
2155 // Only the -fmodule-file=<file> form.
2156 for (const auto *A : Args.filtered(OPT_fmodule_file)) {
2157 StringRef Val = A->getValue();
2158 if (!Val.contains('='))
2159 Opts.ExtraDeps.emplace_back(std::string(Val), EDK_ModuleFile);
2160 }
2161
2162 // Check for invalid combinations of header-include-format
2163 // and header-include-filtering.
2164 if ((Opts.HeaderIncludeFormat == HIFMT_Textual &&
2168 Diags.Report(diag::err_drv_print_header_env_var_combination_cc1)
2169 << Args.getLastArg(OPT_header_include_format_EQ)->getValue()
2170 << Args.getLastArg(OPT_header_include_filtering_EQ)->getValue();
2171
2172 return Diags.getNumErrors() == NumErrorsBefore;
2173}
2174
2175static bool parseShowColorsArgs(const ArgList &Args, bool DefaultColor) {
2176 // Color diagnostics default to auto ("on" if terminal supports) in the driver
2177 // but default to off in cc1, needing an explicit OPT_fdiagnostics_color.
2178 // Support both clang's -f[no-]color-diagnostics and gcc's
2179 // -f[no-]diagnostics-colors[=never|always|auto].
2180 enum {
2181 Colors_On,
2182 Colors_Off,
2183 Colors_Auto
2184 } ShowColors = DefaultColor ? Colors_Auto : Colors_Off;
2185 for (auto *A : Args) {
2186 const Option &O = A->getOption();
2187 if (O.matches(options::OPT_fcolor_diagnostics)) {
2188 ShowColors = Colors_On;
2189 } else if (O.matches(options::OPT_fno_color_diagnostics)) {
2190 ShowColors = Colors_Off;
2191 } else if (O.matches(options::OPT_fdiagnostics_color_EQ)) {
2192 StringRef Value(A->getValue());
2193 if (Value == "always")
2194 ShowColors = Colors_On;
2195 else if (Value == "never")
2196 ShowColors = Colors_Off;
2197 else if (Value == "auto")
2198 ShowColors = Colors_Auto;
2199 }
2200 }
2201 return ShowColors == Colors_On ||
2202 (ShowColors == Colors_Auto &&
2203 llvm::sys::Process::StandardErrHasColors());
2204}
2205
2206static bool checkVerifyPrefixes(const std::vector<std::string> &VerifyPrefixes,
2207 DiagnosticsEngine &Diags) {
2208 bool Success = true;
2209 for (const auto &Prefix : VerifyPrefixes) {
2210 // Every prefix must start with a letter and contain only alphanumeric
2211 // characters, hyphens, and underscores.
2212 auto BadChar = llvm::find_if(Prefix, [](char C) {
2213 return !isAlphanumeric(C) && C != '-' && C != '_';
2214 });
2215 if (BadChar != Prefix.end() || !isLetter(Prefix[0])) {
2216 Success = false;
2217 Diags.Report(diag::err_drv_invalid_value) << "-verify=" << Prefix;
2218 Diags.Report(diag::note_drv_verify_prefix_spelling);
2219 }
2220 }
2221 return Success;
2222}
2223
2227 const FileSystemOptions &FileSystemOpts = Opts;
2228
2229#define FILE_SYSTEM_OPTION_WITH_MARSHALLING(...) \
2230 GENERATE_OPTION_WITH_MARSHALLING(Args, SA, __VA_ARGS__)
2231#include "clang/Driver/Options.inc"
2232#undef FILE_SYSTEM_OPTION_WITH_MARSHALLING
2233}
2234
2235static bool ParseFileSystemArgs(FileSystemOptions &Opts, const ArgList &Args,
2236 DiagnosticsEngine &Diags) {
2237 unsigned NumErrorsBefore = Diags.getNumErrors();
2238
2239 FileSystemOptions &FileSystemOpts = Opts;
2240
2241#define FILE_SYSTEM_OPTION_WITH_MARSHALLING(...) \
2242 PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
2243#include "clang/Driver/Options.inc"
2244#undef FILE_SYSTEM_OPTION_WITH_MARSHALLING
2245
2246 return Diags.getNumErrors() == NumErrorsBefore;
2247}
2248
2252 const MigratorOptions &MigratorOpts = Opts;
2253#define MIGRATOR_OPTION_WITH_MARSHALLING(...) \
2254 GENERATE_OPTION_WITH_MARSHALLING(Args, SA, __VA_ARGS__)
2255#include "clang/Driver/Options.inc"
2256#undef MIGRATOR_OPTION_WITH_MARSHALLING
2257}
2258
2259static bool ParseMigratorArgs(MigratorOptions &Opts, const ArgList &Args,
2260 DiagnosticsEngine &Diags) {
2261 unsigned NumErrorsBefore = Diags.getNumErrors();
2262
2263 MigratorOptions &MigratorOpts = Opts;
2264
2265#define MIGRATOR_OPTION_WITH_MARSHALLING(...) \
2266 PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
2267#include "clang/Driver/Options.inc"
2268#undef MIGRATOR_OPTION_WITH_MARSHALLING
2269
2270 return Diags.getNumErrors() == NumErrorsBefore;
2271}
2272
2273void CompilerInvocation::GenerateDiagnosticArgs(
2275 StringAllocator SA, bool DefaultDiagColor) {
2276 const DiagnosticOptions *DiagnosticOpts = &Opts;
2277#define DIAG_OPTION_WITH_MARSHALLING(...) \
2278 GENERATE_OPTION_WITH_MARSHALLING(Args, SA, __VA_ARGS__)
2279#include "clang/Driver/Options.inc"
2280#undef DIAG_OPTION_WITH_MARSHALLING
2281
2282 if (!Opts.DiagnosticSerializationFile.empty())
2283 GenerateArg(Args, OPT_diagnostic_serialized_file,
2285
2286 if (Opts.ShowColors)
2287 GenerateArg(Args, OPT_fcolor_diagnostics, SA);
2288
2289 if (Opts.VerifyDiagnostics &&
2290 llvm::is_contained(Opts.VerifyPrefixes, "expected"))
2291 GenerateArg(Args, OPT_verify, SA);
2292
2293 for (const auto &Prefix : Opts.VerifyPrefixes)
2294 if (Prefix != "expected")
2295 GenerateArg(Args, OPT_verify_EQ, Prefix, SA);
2296
2297 DiagnosticLevelMask VIU = Opts.getVerifyIgnoreUnexpected();
2298 if (VIU == DiagnosticLevelMask::None) {
2299 // This is the default, don't generate anything.
2300 } else if (VIU == DiagnosticLevelMask::All) {
2301 GenerateArg(Args, OPT_verify_ignore_unexpected, SA);
2302 } else {
2303 if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Note) != 0)
2304 GenerateArg(Args, OPT_verify_ignore_unexpected_EQ, "note", SA);
2305 if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Remark) != 0)
2306 GenerateArg(Args, OPT_verify_ignore_unexpected_EQ, "remark", SA);
2307 if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Warning) != 0)
2308 GenerateArg(Args, OPT_verify_ignore_unexpected_EQ, "warning", SA);
2309 if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Error) != 0)
2310 GenerateArg(Args, OPT_verify_ignore_unexpected_EQ, "error", SA);
2311 }
2312
2313 for (const auto &Warning : Opts.Warnings) {
2314 // This option is automatically generated from UndefPrefixes.
2315 if (Warning == "undef-prefix")
2316 continue;
2317 Args.push_back(SA(StringRef("-W") + Warning));
2318 }
2319
2320 for (const auto &Remark : Opts.Remarks) {
2321 // These arguments are generated from OptimizationRemark fields of
2322 // CodeGenOptions.
2323 StringRef IgnoredRemarks[] = {"pass", "no-pass",
2324 "pass-analysis", "no-pass-analysis",
2325 "pass-missed", "no-pass-missed"};
2326 if (llvm::is_contained(IgnoredRemarks, Remark))
2327 continue;
2328
2329 Args.push_back(SA(StringRef("-R") + Remark));
2330 }
2331}
2332
2333std::unique_ptr<DiagnosticOptions>
2335 auto DiagOpts = std::make_unique<DiagnosticOptions>();
2336 unsigned MissingArgIndex, MissingArgCount;
2337 InputArgList Args = getDriverOptTable().ParseArgs(
2338 Argv.slice(1), MissingArgIndex, MissingArgCount);
2339 // We ignore MissingArgCount and the return value of ParseDiagnosticArgs.
2340 // Any errors that would be diagnosed here will also be diagnosed later,
2341 // when the DiagnosticsEngine actually exists.
2342 (void)ParseDiagnosticArgs(*DiagOpts, Args);
2343 return DiagOpts;
2344}
2345
2346bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
2347 DiagnosticsEngine *Diags,
2348 bool DefaultDiagColor) {
2349 std::optional<DiagnosticsEngine> IgnoringDiags;
2350 if (!Diags) {
2351 IgnoringDiags.emplace(new DiagnosticIDs(), new DiagnosticOptions(),
2352 new IgnoringDiagConsumer());
2353 Diags = &*IgnoringDiags;
2354 }
2355
2356 unsigned NumErrorsBefore = Diags->getNumErrors();
2357
2358 // The key paths of diagnostic options defined in Options.td start with
2359 // "DiagnosticOpts->". Let's provide the expected variable name and type.
2360 DiagnosticOptions *DiagnosticOpts = &Opts;
2361
2362#define DIAG_OPTION_WITH_MARSHALLING(...) \
2363 PARSE_OPTION_WITH_MARSHALLING(Args, *Diags, __VA_ARGS__)
2364#include "clang/Driver/Options.inc"
2365#undef DIAG_OPTION_WITH_MARSHALLING
2366
2367 llvm::sys::Process::UseANSIEscapeCodes(Opts.UseANSIEscapeCodes);
2368
2369 if (Arg *A =
2370 Args.getLastArg(OPT_diagnostic_serialized_file, OPT__serialize_diags))
2371 Opts.DiagnosticSerializationFile = A->getValue();
2372 Opts.ShowColors = parseShowColorsArgs(Args, DefaultDiagColor);
2373
2374 Opts.VerifyDiagnostics = Args.hasArg(OPT_verify) || Args.hasArg(OPT_verify_EQ);
2375 Opts.VerifyPrefixes = Args.getAllArgValues(OPT_verify_EQ);
2376 if (Args.hasArg(OPT_verify))
2377 Opts.VerifyPrefixes.push_back("expected");
2378 // Keep VerifyPrefixes in its original order for the sake of diagnostics, and
2379 // then sort it to prepare for fast lookup using std::binary_search.
2380 if (!checkVerifyPrefixes(Opts.VerifyPrefixes, *Diags))
2381 Opts.VerifyDiagnostics = false;
2382 else
2383 llvm::sort(Opts.VerifyPrefixes);
2386 "-verify-ignore-unexpected=",
2387 Args.getAllArgValues(OPT_verify_ignore_unexpected_EQ), *Diags, DiagMask);
2388 if (Args.hasArg(OPT_verify_ignore_unexpected))
2389 DiagMask = DiagnosticLevelMask::All;
2390 Opts.setVerifyIgnoreUnexpected(DiagMask);
2391 if (Opts.TabStop == 0 || Opts.TabStop > DiagnosticOptions::MaxTabStop) {
2392 Opts.TabStop = DiagnosticOptions::DefaultTabStop;
2393 Diags->Report(diag::warn_ignoring_ftabstop_value)
2394 << Opts.TabStop << DiagnosticOptions::DefaultTabStop;
2395 }
2396
2397 addDiagnosticArgs(Args, OPT_W_Group, OPT_W_value_Group, Opts.Warnings);
2398 addDiagnosticArgs(Args, OPT_R_Group, OPT_R_value_Group, Opts.Remarks);
2399
2400 return Diags->getNumErrors() == NumErrorsBefore;
2401}
2402
2403/// Parse the argument to the -ftest-module-file-extension
2404/// command-line argument.
2405///
2406/// \returns true on error, false on success.
2407static bool parseTestModuleFileExtensionArg(StringRef Arg,
2408 std::string &BlockName,
2409 unsigned &MajorVersion,
2410 unsigned &MinorVersion,
2411 bool &Hashed,
2412 std::string &UserInfo) {
2414 Arg.split(Args, ':', 5);
2415 if (Args.size() < 5)
2416 return true;
2417
2418 BlockName = std::string(Args[0]);
2419 if (Args[1].getAsInteger(10, MajorVersion)) return true;
2420 if (Args[2].getAsInteger(10, MinorVersion)) return true;
2421 if (Args[3].getAsInteger(2, Hashed)) return true;
2422 if (Args.size() > 4)
2423 UserInfo = std::string(Args[4]);
2424 return false;
2425}
2426
2427/// Return a table that associates command line option specifiers with the
2428/// frontend action. Note: The pair {frontend::PluginAction, OPT_plugin} is
2429/// intentionally missing, as this case is handled separately from other
2430/// frontend options.
2431static const auto &getFrontendActionTable() {
2432 static const std::pair<frontend::ActionKind, unsigned> Table[] = {
2433 {frontend::ASTDeclList, OPT_ast_list},
2434
2435 {frontend::ASTDump, OPT_ast_dump_all_EQ},
2436 {frontend::ASTDump, OPT_ast_dump_all},
2437 {frontend::ASTDump, OPT_ast_dump_EQ},
2438 {frontend::ASTDump, OPT_ast_dump},
2439 {frontend::ASTDump, OPT_ast_dump_lookups},
2440 {frontend::ASTDump, OPT_ast_dump_decl_types},
2441
2442 {frontend::ASTPrint, OPT_ast_print},
2443 {frontend::ASTView, OPT_ast_view},
2444 {frontend::DumpCompilerOptions, OPT_compiler_options_dump},
2445 {frontend::DumpRawTokens, OPT_dump_raw_tokens},
2446 {frontend::DumpTokens, OPT_dump_tokens},
2447 {frontend::EmitAssembly, OPT_S},
2448 {frontend::EmitBC, OPT_emit_llvm_bc},
2449 {frontend::EmitHTML, OPT_emit_html},
2450 {frontend::EmitLLVM, OPT_emit_llvm},
2451 {frontend::EmitLLVMOnly, OPT_emit_llvm_only},
2452 {frontend::EmitCodeGenOnly, OPT_emit_codegen_only},
2453 {frontend::EmitObj, OPT_emit_obj},
2454 {frontend::ExtractAPI, OPT_extract_api},
2455
2456 {frontend::FixIt, OPT_fixit_EQ},
2457 {frontend::FixIt, OPT_fixit},
2458
2459 {frontend::GenerateModule, OPT_emit_module},
2460 {frontend::GenerateModuleInterface, OPT_emit_module_interface},
2461 {frontend::GenerateHeaderUnit, OPT_emit_header_unit},
2462 {frontend::GeneratePCH, OPT_emit_pch},
2463 {frontend::GenerateInterfaceStubs, OPT_emit_interface_stubs},
2464 {frontend::InitOnly, OPT_init_only},
2465 {frontend::ParseSyntaxOnly, OPT_fsyntax_only},
2466 {frontend::ModuleFileInfo, OPT_module_file_info},
2467 {frontend::VerifyPCH, OPT_verify_pch},
2468 {frontend::PrintPreamble, OPT_print_preamble},
2470 {frontend::TemplightDump, OPT_templight_dump},
2471 {frontend::RewriteMacros, OPT_rewrite_macros},
2472 {frontend::RewriteObjC, OPT_rewrite_objc},
2473 {frontend::RewriteTest, OPT_rewrite_test},
2474 {frontend::RunAnalysis, OPT_analyze},
2475 {frontend::MigrateSource, OPT_migrate},
2476 {frontend::RunPreprocessorOnly, OPT_Eonly},
2478 OPT_print_dependency_directives_minimized_source},
2479 };
2480
2481 return Table;
2482}
2483
2484/// Maps command line option to frontend action.
2485static std::optional<frontend::ActionKind>
2486getFrontendAction(OptSpecifier &Opt) {
2487 for (const auto &ActionOpt : getFrontendActionTable())
2488 if (ActionOpt.second == Opt.getID())
2489 return ActionOpt.first;
2490
2491 return std::nullopt;
2492}
2493
2494/// Maps frontend action to command line option.
2495static std::optional<OptSpecifier>
2497 for (const auto &ActionOpt : getFrontendActionTable())
2498 if (ActionOpt.first == ProgramAction)
2499 return OptSpecifier(ActionOpt.second);
2500
2501 return std::nullopt;
2502}
2503
2507 bool IsHeader) {
2508 const FrontendOptions &FrontendOpts = Opts;
2509#define FRONTEND_OPTION_WITH_MARSHALLING(...) \
2510 GENERATE_OPTION_WITH_MARSHALLING(Args, SA, __VA_ARGS__)
2511#include "clang/Driver/Options.inc"
2512#undef FRONTEND_OPTION_WITH_MARSHALLING
2513
2514 std::optional<OptSpecifier> ProgramActionOpt =
2516
2517 // Generating a simple flag covers most frontend actions.
2518 std::function<void()> GenerateProgramAction = [&]() {
2519 GenerateArg(Args, *ProgramActionOpt, SA);
2520 };
2521
2522 if (!ProgramActionOpt) {
2523 // PluginAction is the only program action handled separately.
2524 assert(Opts.ProgramAction == frontend::PluginAction &&
2525 "Frontend action without option.");
2526 GenerateProgramAction = [&]() {
2527 GenerateArg(Args, OPT_plugin, Opts.ActionName, SA);
2528 };
2529 }
2530
2531 // FIXME: Simplify the complex 'AST dump' command line.
2532 if (Opts.ProgramAction == frontend::ASTDump) {
2533 GenerateProgramAction = [&]() {
2534 // ASTDumpLookups, ASTDumpDeclTypes and ASTDumpFilter are generated via
2535 // marshalling infrastructure.
2536
2537 if (Opts.ASTDumpFormat != ADOF_Default) {
2538 StringRef Format;
2539 switch (Opts.ASTDumpFormat) {
2540 case ADOF_Default:
2541 llvm_unreachable("Default AST dump format.");
2542 case ADOF_JSON:
2543 Format = "json";
2544 break;
2545 }
2546
2547 if (Opts.ASTDumpAll)
2548 GenerateArg(Args, OPT_ast_dump_all_EQ, Format, SA);
2549 if (Opts.ASTDumpDecls)
2550 GenerateArg(Args, OPT_ast_dump_EQ, Format, SA);
2551 } else {
2552 if (Opts.ASTDumpAll)
2553 GenerateArg(Args, OPT_ast_dump_all, SA);
2554 if (Opts.ASTDumpDecls)
2555 GenerateArg(Args, OPT_ast_dump, SA);
2556 }
2557 };
2558 }
2559
2560 if (Opts.ProgramAction == frontend::FixIt && !Opts.FixItSuffix.empty()) {
2561 GenerateProgramAction = [&]() {
2562 GenerateArg(Args, OPT_fixit_EQ, Opts.FixItSuffix, SA);
2563 };
2564 }
2565
2566 GenerateProgramAction();
2567
2568 for (const auto &PluginArgs : Opts.PluginArgs) {
2569 Option Opt = getDriverOptTable().getOption(OPT_plugin_arg);
2570 const char *Spelling =
2571 SA(Opt.getPrefix() + Opt.getName() + PluginArgs.first);
2572 for (const auto &PluginArg : PluginArgs.second)
2573 denormalizeString(Args, Spelling, SA, Opt.getKind(), 0, PluginArg);
2574 }
2575
2576 for (const auto &Ext : Opts.ModuleFileExtensions)
2577 if (auto *TestExt = dyn_cast_or_null<TestModuleFileExtension>(Ext.get()))
2578 GenerateArg(Args, OPT_ftest_module_file_extension_EQ, TestExt->str(), SA);
2579
2580 if (!Opts.CodeCompletionAt.FileName.empty())
2581 GenerateArg(Args, OPT_code_completion_at, Opts.CodeCompletionAt.ToString(),
2582 SA);
2583
2584 for (const auto &Plugin : Opts.Plugins)
2585 GenerateArg(Args, OPT_load, Plugin, SA);
2586
2587 // ASTDumpDecls and ASTDumpAll already handled with ProgramAction.
2588
2589 for (const auto &ModuleFile : Opts.ModuleFiles)
2590 GenerateArg(Args, OPT_fmodule_file, ModuleFile, SA);
2591
2592 if (Opts.AuxTargetCPU)
2593 GenerateArg(Args, OPT_aux_target_cpu, *Opts.AuxTargetCPU, SA);
2594
2595 if (Opts.AuxTargetFeatures)
2596 for (const auto &Feature : *Opts.AuxTargetFeatures)
2597 GenerateArg(Args, OPT_aux_target_feature, Feature, SA);
2598
2599 {
2600 StringRef Preprocessed = Opts.DashX.isPreprocessed() ? "-cpp-output" : "";
2601 StringRef ModuleMap =
2602 Opts.DashX.getFormat() == InputKind::ModuleMap ? "-module-map" : "";
2603 StringRef HeaderUnit = "";
2604 switch (Opts.DashX.getHeaderUnitKind()) {
2606 break;
2608 HeaderUnit = "-user";
2609 break;
2611 HeaderUnit = "-system";
2612 break;
2614 HeaderUnit = "-header-unit";
2615 break;
2616 }
2617 StringRef Header = IsHeader ? "-header" : "";
2618
2619 StringRef Lang;
2620 switch (Opts.DashX.getLanguage()) {
2621 case Language::C:
2622 Lang = "c";
2623 break;
2624 case Language::OpenCL:
2625 Lang = "cl";
2626 break;
2628 Lang = "clcpp";
2629 break;
2630 case Language::CUDA:
2631 Lang = "cuda";
2632 break;
2633 case Language::HIP:
2634 Lang = "hip";
2635 break;
2636 case Language::CXX:
2637 Lang = "c++";
2638 break;
2639 case Language::ObjC:
2640 Lang = "objective-c";
2641 break;
2642 case Language::ObjCXX:
2643 Lang = "objective-c++";
2644 break;
2646 Lang = "renderscript";
2647 break;
2648 case Language::Asm:
2649 Lang = "assembler-with-cpp";
2650 break;
2651 case Language::Unknown:
2652 assert(Opts.DashX.getFormat() == InputKind::Precompiled &&
2653 "Generating -x argument for unknown language (not precompiled).");
2654 Lang = "ast";
2655 break;
2656 case Language::LLVM_IR:
2657 Lang = "ir";
2658 break;
2659 case Language::HLSL:
2660 Lang = "hlsl";
2661 break;
2662 }
2663
2664 GenerateArg(Args, OPT_x,
2665 Lang + HeaderUnit + Header + ModuleMap + Preprocessed, SA);
2666 }
2667
2668 // OPT_INPUT has a unique class, generate it directly.
2669 for (const auto &Input : Opts.Inputs)
2670 Args.push_back(SA(Input.getFile()));
2671}
2672
2673static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
2674 DiagnosticsEngine &Diags, bool &IsHeaderFile) {
2675 unsigned NumErrorsBefore = Diags.getNumErrors();
2676
2677 FrontendOptions &FrontendOpts = Opts;
2678
2679#define FRONTEND_OPTION_WITH_MARSHALLING(...) \
2680 PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
2681#include "clang/Driver/Options.inc"
2682#undef FRONTEND_OPTION_WITH_MARSHALLING
2683
2685 if (const Arg *A = Args.getLastArg(OPT_Action_Group)) {
2686 OptSpecifier Opt = OptSpecifier(A->getOption().getID());
2687 std::optional<frontend::ActionKind> ProgramAction = getFrontendAction(Opt);
2688 assert(ProgramAction && "Option specifier not in Action_Group.");
2689
2690 if (ProgramAction == frontend::ASTDump &&
2691 (Opt == OPT_ast_dump_all_EQ || Opt == OPT_ast_dump_EQ)) {
2692 unsigned Val = llvm::StringSwitch<unsigned>(A->getValue())
2693 .CaseLower("default", ADOF_Default)
2694 .CaseLower("json", ADOF_JSON)
2695 .Default(std::numeric_limits<unsigned>::max());
2696
2697 if (Val != std::numeric_limits<unsigned>::max())
2698 Opts.ASTDumpFormat = static_cast<ASTDumpOutputFormat>(Val);
2699 else {
2700 Diags.Report(diag::err_drv_invalid_value)
2701 << A->getAsString(Args) << A->getValue();
2703 }
2704 }
2705
2706 if (ProgramAction == frontend::FixIt && Opt == OPT_fixit_EQ)
2707 Opts.FixItSuffix = A->getValue();
2708
2709 if (ProgramAction == frontend::GenerateInterfaceStubs) {
2710 StringRef ArgStr =
2711 Args.hasArg(OPT_interface_stub_version_EQ)
2712 ? Args.getLastArgValue(OPT_interface_stub_version_EQ)
2713 : "ifs-v1";
2714 if (ArgStr == "experimental-yaml-elf-v1" ||
2715 ArgStr == "experimental-ifs-v1" || ArgStr == "experimental-ifs-v2" ||
2716 ArgStr == "experimental-tapi-elf-v1") {
2717 std::string ErrorMessage =
2718 "Invalid interface stub format: " + ArgStr.str() +
2719 " is deprecated.";
2720 Diags.Report(diag::err_drv_invalid_value)
2721 << "Must specify a valid interface stub format type, ie: "
2722 "-interface-stub-version=ifs-v1"
2723 << ErrorMessage;
2724 ProgramAction = frontend::ParseSyntaxOnly;
2725 } else if (!ArgStr.startswith("ifs-")) {
2726 std::string ErrorMessage =
2727 "Invalid interface stub format: " + ArgStr.str() + ".";
2728 Diags.Report(diag::err_drv_invalid_value)
2729 << "Must specify a valid interface stub format type, ie: "
2730 "-interface-stub-version=ifs-v1"
2731 << ErrorMessage;
2732 ProgramAction = frontend::ParseSyntaxOnly;
2733 }
2734 }
2735
2736 Opts.ProgramAction = *ProgramAction;
2737 }
2738
2739 if (const Arg* A = Args.getLastArg(OPT_plugin)) {
2740 Opts.Plugins.emplace_back(A->getValue(0));
2742 Opts.ActionName = A->getValue();
2743 }
2744 for (const auto *AA : Args.filtered(OPT_plugin_arg))
2745 Opts.PluginArgs[AA->getValue(0)].emplace_back(AA->getValue(1));
2746
2747 for (const std::string &Arg :
2748 Args.getAllArgValues(OPT_ftest_module_file_extension_EQ)) {
2749 std::string BlockName;
2750 unsigned MajorVersion;
2751 unsigned MinorVersion;
2752 bool Hashed;
2753 std::string UserInfo;
2754 if (parseTestModuleFileExtensionArg(Arg, BlockName, MajorVersion,
2755 MinorVersion, Hashed, UserInfo)) {
2756 Diags.Report(diag::err_test_module_file_extension_format) << Arg;
2757
2758 continue;
2759 }
2760
2761 // Add the testing module file extension.
2762 Opts.ModuleFileExtensions.push_back(
2763 std::make_shared<TestModuleFileExtension>(
2764 BlockName, MajorVersion, MinorVersion, Hashed, UserInfo));
2765 }
2766
2767 if (const Arg *A = Args.getLastArg(OPT_code_completion_at)) {
2768 Opts.CodeCompletionAt =
2769 ParsedSourceLocation::FromString(A->getValue());
2770 if (Opts.CodeCompletionAt.FileName.empty())
2771 Diags.Report(diag::err_drv_invalid_value)
2772 << A->getAsString(Args) << A->getValue();
2773 }
2774
2775 Opts.Plugins = Args.getAllArgValues(OPT_load);
2776 Opts.ASTDumpDecls = Args.hasArg(OPT_ast_dump, OPT_ast_dump_EQ);
2777 Opts.ASTDumpAll = Args.hasArg(OPT_ast_dump_all, OPT_ast_dump_all_EQ);
2778 // Only the -fmodule-file=<file> form.
2779 for (const auto *A : Args.filtered(OPT_fmodule_file)) {
2780 StringRef Val = A->getValue();
2781 if (!Val.contains('='))
2782 Opts.ModuleFiles.push_back(std::string(Val));
2783 }
2784
2786 Diags.Report(diag::err_drv_argument_only_allowed_with) << "-fsystem-module"
2787 << "-emit-module";
2788
2789 if (Args.hasArg(OPT_aux_target_cpu))
2790 Opts.AuxTargetCPU = std::string(Args.getLastArgValue(OPT_aux_target_cpu));
2791 if (Args.hasArg(OPT_aux_target_feature))
2792 Opts.AuxTargetFeatures = Args.getAllArgValues(OPT_aux_target_feature);
2793
2796 Diags.Report(diag::err_drv_argument_not_allowed_with)
2797 << "ARC migration" << "ObjC migration";
2798 }
2799
2801 if (const Arg *A = Args.getLastArg(OPT_x)) {
2802 StringRef XValue = A->getValue();
2803
2804 // Parse suffixes:
2805 // '<lang>(-[{header-unit,user,system}-]header|[-module-map][-cpp-output])'.
2806 // FIXME: Supporting '<lang>-header-cpp-output' would be useful.
2807 bool Preprocessed = XValue.consume_back("-cpp-output");
2808 bool ModuleMap = XValue.consume_back("-module-map");
2809 // Detect and consume the header indicator.
2810 bool IsHeader =
2811 XValue != "precompiled-header" && XValue.consume_back("-header");
2812
2813 // If we have c++-{user,system}-header, that indicates a header unit input
2814 // likewise, if the user put -fmodule-header together with a header with an
2815 // absolute path (header-unit-header).
2817 if (IsHeader || Preprocessed) {
2818 if (XValue.consume_back("-header-unit"))
2820 else if (XValue.consume_back("-system"))
2822 else if (XValue.consume_back("-user"))
2824 }
2825
2826 // The value set by this processing is an un-preprocessed source which is
2827 // not intended to be a module map or header unit.
2828 IsHeaderFile = IsHeader && !Preprocessed && !ModuleMap &&
2830
2831 // Principal languages.
2832 DashX = llvm::StringSwitch<InputKind>(XValue)
2833 .Case("c", Language::C)
2834 .Case("cl", Language::OpenCL)
2835 .Case("clcpp", Language::OpenCLCXX)
2836 .Case("cuda", Language::CUDA)
2837 .Case("hip", Language::HIP)
2838 .Case("c++", Language::CXX)
2839 .Case("objective-c", Language::ObjC)
2840 .Case("objective-c++", Language::ObjCXX)
2841 .Case("renderscript", Language::RenderScript)
2842 .Case("hlsl", Language::HLSL)
2843 .Default(Language::Unknown);
2844
2845 // "objc[++]-cpp-output" is an acceptable synonym for
2846 // "objective-c[++]-cpp-output".
2847 if (DashX.isUnknown() && Preprocessed && !IsHeaderFile && !ModuleMap &&
2849 DashX = llvm::StringSwitch<InputKind>(XValue)
2850 .Case("objc", Language::ObjC)
2851 .Case("objc++", Language::ObjCXX)
2852 .Default(Language::Unknown);
2853
2854 // Some special cases cannot be combined with suffixes.
2855 if (DashX.isUnknown() && !Preprocessed && !IsHeaderFile && !ModuleMap &&
2857 DashX = llvm::StringSwitch<InputKind>(XValue)
2858 .Case("cpp-output", InputKind(Language::C).getPreprocessed())
2859 .Case("assembler-with-cpp", Language::Asm)
2860 .Cases("ast", "pcm", "precompiled-header",
2862 .Case("ir", Language::LLVM_IR)
2863 .Default(Language::Unknown);
2864
2865 if (DashX.isUnknown())
2866 Diags.Report(diag::err_drv_invalid_value)
2867 << A->getAsString(Args) << A->getValue();
2868
2869 if (Preprocessed)
2870 DashX = DashX.getPreprocessed();
2871 // A regular header is considered mutually exclusive with a header unit.
2872 if (HUK != InputKind::HeaderUnit_None) {
2873 DashX = DashX.withHeaderUnit(HUK);
2874 IsHeaderFile = true;
2875 } else if (IsHeaderFile)
2876 DashX = DashX.getHeader();
2877 if (ModuleMap)
2878 DashX = DashX.withFormat(InputKind::ModuleMap);
2879 }
2880
2881 // '-' is the default input if none is given.
2882 std::vector<std::string> Inputs = Args.getAllArgValues(OPT_INPUT);
2883 Opts.Inputs.clear();
2884 if (Inputs.empty())
2885 Inputs.push_back("-");
2886
2888 Inputs.size() > 1)
2889 Diags.Report(diag::err_drv_header_unit_extra_inputs) << Inputs[1];
2890
2891 for (unsigned i = 0, e = Inputs.size(); i != e; ++i) {
2892 InputKind IK = DashX;
2893 if (IK.isUnknown()) {
2895 StringRef(Inputs[i]).rsplit('.').second);
2896 // FIXME: Warn on this?
2897 if (IK.isUnknown())
2898 IK = Language::C;
2899 // FIXME: Remove this hack.
2900 if (i == 0)
2901 DashX = IK;
2902 }
2903
2904 bool IsSystem = false;
2905
2906 // The -emit-module action implicitly takes a module map.
2908 IK.getFormat() == InputKind::Source) {
2910 IsSystem = Opts.IsSystemModule;
2911 }
2912
2913 Opts.Inputs.emplace_back(std::move(Inputs[i]), IK, IsSystem);
2914 }
2915
2916 Opts.DashX = DashX;
2917
2918 return Diags.getNumErrors() == NumErrorsBefore;
2919}
2920
2921std::string CompilerInvocation::GetResourcesPath(const char *Argv0,
2922 void *MainAddr) {
2923 std::string ClangExecutable =
2924 llvm::sys::fs::getMainExecutable(Argv0, MainAddr);
2925 return Driver::GetResourcesPath(ClangExecutable, CLANG_RESOURCE_DIR);
2926}
2927
2931 const HeaderSearchOptions *HeaderSearchOpts = &Opts;
2932#define HEADER_SEARCH_OPTION_WITH_MARSHALLING(...) \
2933 GENERATE_OPTION_WITH_MARSHALLING(Args, SA, __VA_ARGS__)
2934#include "clang/Driver/Options.inc"
2935#undef HEADER_SEARCH_OPTION_WITH_MARSHALLING
2936
2937 if (Opts.UseLibcxx)
2938 GenerateArg(Args, OPT_stdlib_EQ, "libc++", SA);
2939
2940 if (!Opts.ModuleCachePath.empty())
2941 GenerateArg(Args, OPT_fmodules_cache_path, Opts.ModuleCachePath, SA);
2942
2943 for (const auto &File : Opts.PrebuiltModuleFiles)
2944 GenerateArg(Args, OPT_fmodule_file, File.first + "=" + File.second, SA);
2945
2946 for (const auto &Path : Opts.PrebuiltModulePaths)
2947 GenerateArg(Args, OPT_fprebuilt_module_path, Path, SA);
2948
2949 for (const auto &Macro : Opts.ModulesIgnoreMacros)
2950 GenerateArg(Args, OPT_fmodules_ignore_macro, Macro.val(), SA);
2951
2952 auto Matches = [](const HeaderSearchOptions::Entry &Entry,
2954 std::optional<bool> IsFramework,
2955 std::optional<bool> IgnoreSysRoot) {
2956 return llvm::is_contained(Groups, Entry.Group) &&
2957 (!IsFramework || (Entry.IsFramework == *IsFramework)) &&
2958 (!IgnoreSysRoot || (Entry.IgnoreSysRoot == *IgnoreSysRoot));
2959 };
2960
2961 auto It = Opts.UserEntries.begin();
2962 auto End = Opts.UserEntries.end();
2963
2964 // Add -I..., -F..., and -index-header-map options in order.
2965 for (; It < End && Matches(*It, {frontend::IndexHeaderMap, frontend::Angled},
2966 std::nullopt, true);
2967 ++It) {
2968 OptSpecifier Opt = [It, Matches]() {
2969 if (Matches(*It, frontend::IndexHeaderMap, true, true))
2970 return OPT_F;
2971 if (Matches(*It, frontend::IndexHeaderMap, false, true))
2972 return OPT_I;
2973 if (Matches(*It, frontend::Angled, true, true))
2974 return OPT_F;
2975 if (Matches(*It, frontend::Angled, false, true))
2976 return OPT_I;
2977 llvm_unreachable("Unexpected HeaderSearchOptions::Entry.");
2978 }();
2979
2980 if (It->Group == frontend::IndexHeaderMap)
2981 GenerateArg(Args, OPT_index_header_map, SA);
2982 GenerateArg(Args, Opt, It->Path, SA);
2983 };
2984
2985 // Note: some paths that came from "[-iprefix=xx] -iwithprefixbefore=yy" may
2986 // have already been generated as "-I[xx]yy". If that's the case, their
2987 // position on command line was such that this has no semantic impact on
2988 // include paths.
2989 for (; It < End &&
2990 Matches(*It, {frontend::After, frontend::Angled}, false, true);
2991 ++It) {
2992 OptSpecifier Opt =
2993 It->Group == frontend::After ? OPT_iwithprefix : OPT_iwithprefixbefore;
2994 GenerateArg(Args, Opt, It->Path, SA);
2995 }
2996
2997 // Note: Some paths that came from "-idirafter=xxyy" may have already been
2998 // generated as "-iwithprefix=xxyy". If that's the case, their position on
2999 // command line was such that this has no semantic impact on include paths.
3000 for (; It < End && Matches(*It, {frontend::After}, false, true); ++It)
3001 GenerateArg(Args, OPT_idirafter, It->Path, SA);
3002 for (; It < End && Matches(*It, {frontend::Quoted}, false, true); ++It)
3003 GenerateArg(Args, OPT_iquote, It->Path, SA);
3004 for (; It < End && Matches(*It, {frontend::System}, false, std::nullopt);
3005 ++It)
3006 GenerateArg(Args, It->IgnoreSysRoot ? OPT_isystem : OPT_iwithsysroot,
3007 It->Path, SA);
3008 for (; It < End && Matches(*It, {frontend::System}, true, true); ++It)
3009 GenerateArg(Args, OPT_iframework, It->Path, SA);
3010 for (; It < End && Matches(*It, {frontend::System}, true, false); ++It)
3011 GenerateArg(Args, OPT_iframeworkwithsysroot, It->Path, SA);
3012
3013 // Add the paths for the various language specific isystem flags.
3014 for (; It < End && Matches(*It, {frontend::CSystem}, false, true); ++It)
3015 GenerateArg(Args, OPT_c_isystem, It->Path, SA);
3016 for (; It < End && Matches(*It, {frontend::CXXSystem}, false, true); ++It)
3017 GenerateArg(Args, OPT_cxx_isystem, It->Path, SA);
3018 for (; It < End && Matches(*It, {frontend::ObjCSystem}, false, true); ++It)
3019 GenerateArg(Args, OPT_objc_isystem, It->Path, SA);
3020 for (; It < End && Matches(*It, {frontend::ObjCXXSystem}, false, true); ++It)
3021 GenerateArg(Args, OPT_objcxx_isystem, It->Path, SA);
3022
3023 // Add the internal paths from a driver that detects standard include paths.
3024 // Note: Some paths that came from "-internal-isystem" arguments may have
3025 // already been generated as "-isystem". If that's the case, their position on
3026 // command line was such that this has no semantic impact on include paths.
3027 for (; It < End &&
3028 Matches(*It, {frontend::System, frontend::ExternCSystem}, false, true);
3029 ++It) {
3030 OptSpecifier Opt = It->Group == frontend::System
3031 ? OPT_internal_isystem
3032 : OPT_internal_externc_isystem;
3033 GenerateArg(Args, Opt, It->Path, SA);
3034 }
3035
3036 assert(It == End && "Unhandled HeaderSearchOption::Entry.");
3037
3038 // Add the path prefixes which are implicitly treated as being system headers.
3039 for (const auto &P : Opts.SystemHeaderPrefixes) {
3040 OptSpecifier Opt = P.IsSystemHeader ? OPT_system_header_prefix
3041 : OPT_no_system_header_prefix;
3042 GenerateArg(Args, Opt, P.Prefix, SA);
3043 }
3044
3045 for (const std::string &F : Opts.VFSOverlayFiles)
3046 GenerateArg(Args, OPT_ivfsoverlay, F, SA);
3047}
3048
3049static bool ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args,
3050 DiagnosticsEngine &Diags,
3051 const std::string &WorkingDir) {
3052 unsigned NumErrorsBefore = Diags.getNumErrors();
3053
3054 HeaderSearchOptions *HeaderSearchOpts = &Opts;
3055
3056#define HEADER_SEARCH_OPTION_WITH_MARSHALLING(...) \
3057 PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
3058#include "clang/Driver/Options.inc"
3059#undef HEADER_SEARCH_OPTION_WITH_MARSHALLING
3060
3061 if (const Arg *A = Args.getLastArg(OPT_stdlib_EQ))
3062 Opts.UseLibcxx = (strcmp(A->getValue(), "libc++") == 0);
3063
3064 // Canonicalize -fmodules-cache-path before storing it.
3065 SmallString<128> P(Args.getLastArgValue(OPT_fmodules_cache_path));
3066 if (!(P.empty() || llvm::sys::path::is_absolute(P))) {
3067 if (WorkingDir.empty())
3068 llvm::sys::fs::make_absolute(P);
3069 else
3070 llvm::sys::fs::make_absolute(WorkingDir, P);
3071 }
3072 llvm::sys::path::remove_dots(P);
3073 Opts.ModuleCachePath = std::string(P.str());
3074
3075 // Only the -fmodule-file=<name>=<file> form.
3076 for (const auto *A : Args.filtered(OPT_fmodule_file)) {
3077 StringRef Val = A->getValue();
3078 if (Val.contains('=')) {
3079 auto Split = Val.split('=');
3080 Opts.PrebuiltModuleFiles.insert(
3081 {std::string(Split.first), std::string(Split.second)});
3082 }
3083 }
3084 for (const auto *A : Args.filtered(OPT_fprebuilt_module_path))
3085 Opts.AddPrebuiltModulePath(A->getValue());
3086
3087 for (const auto *A : Args.filtered(OPT_fmodules_ignore_macro)) {
3088 StringRef MacroDef = A->getValue();
3089 Opts.ModulesIgnoreMacros.insert(
3090 llvm::CachedHashString(MacroDef.split('=').first));
3091 }
3092
3093 // Add -I..., -F..., and -index-header-map options in order.
3094 bool IsIndexHeaderMap = false;
3095 bool IsSysrootSpecified =
3096 Args.hasArg(OPT__sysroot_EQ) || Args.hasArg(OPT_isysroot);
3097 for (const auto *A : Args.filtered(OPT_I, OPT_F, OPT_index_header_map)) {
3098 if (A->getOption().matches(OPT_index_header_map)) {
3099 // -index-header-map applies to the next -I or -F.
3100 IsIndexHeaderMap = true;
3101 continue;
3102 }
3103
3105 IsIndexHeaderMap ? frontend::IndexHeaderMap : frontend::Angled;
3106
3107 bool IsFramework = A->getOption().matches(OPT_F);
3108 std::string Path = A->getValue();
3109
3110 if (IsSysrootSpecified && !IsFramework && A->getValue()[0] == '=') {
3111 SmallString<32> Buffer;
3112 llvm::sys::path::append(Buffer, Opts.Sysroot,
3113 llvm::StringRef(A->getValue()).substr(1));
3114 Path = std::string(Buffer.str());
3115 }
3116
3117 Opts.AddPath(Path, Group, IsFramework,
3118 /*IgnoreSysroot*/ true);
3119 IsIndexHeaderMap = false;
3120 }
3121
3122 // Add -iprefix/-iwithprefix/-iwithprefixbefore options.
3123 StringRef Prefix = ""; // FIXME: This isn't the correct default prefix.
3124 for (const auto *A :
3125 Args.filtered(OPT_iprefix, OPT_iwithprefix, OPT_iwithprefixbefore)) {
3126 if (A->getOption().matches(OPT_iprefix))
3127 Prefix = A->getValue();
3128 else if (A->getOption().matches(OPT_iwithprefix))
3129 Opts.AddPath(Prefix.str() + A->getValue(), frontend::After, false, true);
3130 else
3131 Opts.AddPath(Prefix.str() + A->getValue(), frontend::Angled, false, true);
3132 }
3133
3134 for (const auto *A : Args.filtered(OPT_idirafter))
3135 Opts.AddPath(A->getValue(), frontend::After, false, true);
3136 for (const auto *A : Args.filtered(OPT_iquote))
3137 Opts.AddPath(A->getValue(), frontend::Quoted, false, true);
3138 for (const auto *A : Args.filtered(OPT_isystem, OPT_iwithsysroot))
3139 Opts.AddPath(A->getValue(), frontend::System, false,
3140 !A->getOption().matches(OPT_iwithsysroot));
3141 for (const auto *A : Args.filtered(OPT_iframework))
3142 Opts.AddPath(A->getValue(), frontend::System, true, true);
3143 for (const auto *A : Args.filtered(OPT_iframeworkwithsysroot))
3144 Opts.AddPath(A->getValue(), frontend::System, /*IsFramework=*/true,
3145 /*IgnoreSysRoot=*/false);
3146
3147 // Add the paths for the various language specific isystem flags.
3148 for (const auto *A : Args.filtered(OPT_c_isystem))
3149 Opts.AddPath(A->getValue(), frontend::CSystem, false, true);
3150 for (const auto *A : Args.filtered(OPT_cxx_isystem))
3151 Opts.AddPath(A->getValue(), frontend::CXXSystem, false, true);
3152 for (const auto *A : Args.filtered(OPT_objc_isystem))
3153 Opts.AddPath(A->getValue(), frontend::ObjCSystem, false,true);
3154 for (const auto *A : Args.filtered(OPT_objcxx_isystem))
3155 Opts.AddPath(A->getValue(), frontend::ObjCXXSystem, false, true);
3156
3157 // Add the internal paths from a driver that detects standard include paths.
3158 for (const auto *A :
3159 Args.filtered(OPT_internal_isystem, OPT_internal_externc_isystem)) {
3161 if (A->getOption().matches(OPT_internal_externc_isystem))
3163 Opts.AddPath(A->getValue(), Group, false, true);
3164 }
3165
3166 // Add the path prefixes which are implicitly treated as being system headers.
3167 for (const auto *A :
3168 Args.filtered(OPT_system_header_prefix, OPT_no_system_header_prefix))
3170 A->getValue(), A->getOption().matches(OPT_system_header_prefix));
3171
3172 for (const auto *A : Args.filtered(OPT_ivfsoverlay, OPT_vfsoverlay))
3173 Opts.AddVFSOverlayFile(A->getValue());
3174
3175 return Diags.getNumErrors() == NumErrorsBefore;
3176}
3177
3178/// Check if input file kind and language standard are compatible.
3180 const LangStandard &S) {
3181 switch (IK.getLanguage()) {
3182 case Language::Unknown:
3183 case Language::LLVM_IR:
3184 llvm_unreachable("should not parse language flags for this input");
3185
3186 case Language::C:
3187 case Language::ObjC:
3189 return S.getLanguage() == Language::C;
3190
3191 case Language::OpenCL:
3192 return S.getLanguage() == Language::OpenCL ||
3193 S.getLanguage() == Language::OpenCLCXX;
3194
3196 return S.getLanguage() == Language::OpenCLCXX;
3197
3198 case Language::CXX:
3199 case Language::ObjCXX:
3200 return S.getLanguage() == Language::CXX;
3201
3202 case Language::CUDA:
3203 // FIXME: What -std= values should be permitted for CUDA compilations?
3204 return S.getLanguage() == Language::CUDA ||
3205 S.getLanguage() == Language::CXX;
3206
3207 case Language::HIP:
3208 return S.getLanguage() == Language::CXX || S.getLanguage() == Language::HIP;
3209
3210 case Language::Asm:
3211 // Accept (and ignore) all -std= values.
3212 // FIXME: The -std= value is not ignored; it affects the tokenization
3213 // and preprocessing rules if we're preprocessing this asm input.
3214 return true;
3215
3216 case Language::HLSL:
3217 return S.getLanguage() == Language::HLSL;
3218 }
3219
3220 llvm_unreachable("unexpected input language");
3221}
3222
3223/// Get language name for given input kind.
3224static StringRef GetInputKindName(InputKind IK) {
3225 switch (IK.getLanguage()) {
3226 case Language::C:
3227 return "C";
3228 case Language::ObjC:
3229 return "Objective-C";
3230 case Language::CXX:
3231 return "C++";
3232 case Language::ObjCXX:
3233 return "Objective-C++";
3234 case Language::OpenCL:
3235 return "OpenCL";
3237 return "C++ for OpenCL";
3238 case Language::CUDA:
3239 return "CUDA";
3241 return "RenderScript";
3242 case Language::HIP:
3243 return "HIP";
3244
3245 case Language::Asm:
3246 return "Asm";
3247 case Language::LLVM_IR:
3248 return "LLVM IR";
3249
3250 case Language::HLSL:
3251 return "HLSL";
3252
3253 case Language::Unknown:
3254 break;
3255 }
3256 llvm_unreachable("unknown input language");
3257}
3258
3259void CompilerInvocation::GenerateLangArgs(const LangOptions &Opts,
3261 StringAllocator SA,
3262 const llvm::Triple &T, InputKind IK) {
3263 if (IK.getFormat() == InputKind::Precompiled ||
3265 if (Opts.ObjCAutoRefCount)
3266 GenerateArg(Args, OPT_fobjc_arc, SA);
3267 if (Opts.PICLevel != 0)
3268 GenerateArg(Args, OPT_pic_level, Twine(Opts.PICLevel), SA);
3269 if (Opts.PIE)
3270 GenerateArg(Args, OPT_pic_is_pie, SA);
3271 for (StringRef Sanitizer : serializeSanitizerKinds(Opts.Sanitize))
3272 GenerateArg(Args, OPT_fsanitize_EQ, Sanitizer, SA);
3273
3274 return;
3275 }
3276
3277 OptSpecifier StdOpt;
3278 switch (Opts.LangStd) {
3279 case LangStandard::lang_opencl10:
3280 case LangStandard::lang_opencl11:
3281 case LangStandard::lang_opencl12:
3282 case LangStandard::lang_opencl20:
3283 case LangStandard::lang_opencl30:
3284 case LangStandard::lang_openclcpp10:
3285 case LangStandard::lang_openclcpp2021:
3286 StdOpt = OPT_cl_std_EQ;
3287 break;
3288 default:
3289 StdOpt = OPT_std_EQ;
3290 break;
3291 }
3292
3294 GenerateArg(Args, StdOpt, LangStandard.getName(), SA);
3295
3296 if (Opts.IncludeDefaultHeader)
3297 GenerateArg(Args, OPT_finclude_default_header, SA);
3298 if (Opts.DeclareOpenCLBuiltins)
3299 GenerateArg(Args, OPT_fdeclare_opencl_builtins, SA);
3300
3301 const LangOptions *LangOpts = &Opts;
3302
3303#define LANG_OPTION_WITH_MARSHALLING(...) \
3304 GENERATE_OPTION_WITH_MARSHALLING(Args, SA, __VA_ARGS__)
3305#include "clang/Driver/Options.inc"
3306#undef LANG_OPTION_WITH_MARSHALLING
3307
3308 // The '-fcf-protection=' option is generated by CodeGenOpts generator.
3309
3310 if (Opts.ObjC) {
3311 GenerateArg(Args, OPT_fobjc_runtime_EQ, Opts.ObjCRuntime.getAsString(), SA);
3312
3313 if (Opts.GC == LangOptions::GCOnly)
3314 GenerateArg(Args, OPT_fobjc_gc_only, SA);
3315 else if (Opts.GC == LangOptions::HybridGC)
3316 GenerateArg(Args, OPT_fobjc_gc, SA);
3317 else if (Opts.ObjCAutoRefCount == 1)
3318 GenerateArg(Args, OPT_fobjc_arc, SA);
3319
3320 if (Opts.ObjCWeakRuntime)
3321 GenerateArg(Args, OPT_fobjc_runtime_has_weak, SA);
3322
3323 if (Opts.ObjCWeak)
3324 GenerateArg(Args, OPT_fobjc_weak, SA);
3325
3326 if (Opts.ObjCSubscriptingLegacyRuntime)
3327 GenerateArg(Args, OPT_fobjc_subscripting_legacy_runtime, SA);
3328 }
3329
3330 if (Opts.GNUCVersion != 0) {
3331 unsigned Major = Opts.GNUCVersion / 100 / 100;
3332 unsigned Minor = (Opts.GNUCVersion / 100) % 100;
3333 unsigned Patch = Opts.GNUCVersion % 100;
3334 GenerateArg(Args, OPT_fgnuc_version_EQ,
3335 Twine(Major) + "." + Twine(Minor) + "." + Twine(Patch), SA);
3336 }
3337
3338 if (Opts.IgnoreXCOFFVisibility)
3339 GenerateArg(Args, OPT_mignore_xcoff_visibility, SA);
3340
3341 if (Opts.SignedOverflowBehavior == LangOptions::SOB_Trapping) {
3342 GenerateArg(Args, OPT_ftrapv, SA);
3343 GenerateArg(Args, OPT_ftrapv_handler, Opts.OverflowHandler, SA);
3344 } else if (Opts.SignedOverflowBehavior == LangOptions::SOB_Defined) {
3345 GenerateArg(Args, OPT_fwrapv, SA);
3346 }
3347
3348 if (Opts.MSCompatibilityVersion != 0) {
3349 unsigned Major = Opts.MSCompatibilityVersion / 10000000;
3350 unsigned Minor = (Opts.MSCompatibilityVersion / 100000) % 100;
3351 unsigned Subminor = Opts.MSCompatibilityVersion % 100000;
3352 GenerateArg(Args, OPT_fms_compatibility_version,
3353 Twine(Major) + "." + Twine(Minor) + "." + Twine(Subminor), SA);
3354 }
3355
3356 if ((!Opts.GNUMode && !Opts.MSVCCompat && !Opts.CPlusPlus17) || T.isOSzOS()) {
3357 if (!Opts.Trigraphs)
3358 GenerateArg(Args, OPT_fno_trigraphs, SA);
3359 } else {
3360 if (Opts.Trigraphs)
3361 GenerateArg(Args, OPT_ftrigraphs, SA);
3362 }
3363
3364 if (Opts.Blocks && !(Opts.OpenCL && Opts.OpenCLVersion == 200))
3365 GenerateArg(Args, OPT_fblocks, SA);
3366
3367 if (Opts.ConvergentFunctions &&
3368 !(Opts.OpenCL || (Opts.CUDA && Opts.CUDAIsDevice) || Opts.SYCLIsDevice))
3369 GenerateArg(Args, OPT_fconvergent_functions, SA);
3370
3371 if (Opts.NoBuiltin && !Opts.Freestanding)
3372 GenerateArg(Args, OPT_fno_builtin, SA);
3373
3374 if (!Opts.NoBuiltin)
3375 for (const auto &Func : Opts.NoBuiltinFuncs)
3376 GenerateArg(Args, OPT_fno_builtin_, Func, SA);
3377
3378 if (Opts.LongDoubleSize == 128)
3379 GenerateArg(Args, OPT_mlong_double_128, SA);
3380 else if (Opts.LongDoubleSize == 64)
3381 GenerateArg(Args, OPT_mlong_double_64, SA);
3382 else if (Opts.LongDoubleSize == 80)
3383 GenerateArg(Args, OPT_mlong_double_80, SA);
3384
3385 // Not generating '-mrtd', it's just an alias for '-fdefault-calling-conv='.
3386
3387 // OpenMP was requested via '-fopenmp', not implied by '-fopenmp-simd' or
3388 // '-fopenmp-targets='.
3389 if (Opts.OpenMP && !Opts.OpenMPSimd) {
3390 GenerateArg(Args, OPT_fopenmp, SA);
3391
3392 if (Opts.OpenMP != 50)
3393 GenerateArg(Args, OPT_fopenmp_version_EQ, Twine(Opts.OpenMP), SA);
3394
3395 if (!Opts.OpenMPUseTLS)
3396 GenerateArg(Args, OPT_fnoopenmp_use_tls, SA);
3397
3398 if (Opts.OpenMPIsDevice)
3399 GenerateArg(Args, OPT_fopenmp_is_device, SA);
3400
3401 if (Opts.OpenMPIRBuilder)
3402 GenerateArg(Args, OPT_fopenmp_enable_irbuilder, SA);
3403 }
3404
3405 if (Opts.OpenMPSimd) {
3406 GenerateArg(Args, OPT_fopenmp_simd, SA);
3407
3408 if (Opts.OpenMP != 50)
3409 GenerateArg(Args, OPT_fopenmp_version_EQ, Twine(Opts.OpenMP), SA);
3410 }
3411
3412 if (Opts.OpenMPThreadSubscription)
3413 GenerateArg(Args, OPT_fopenmp_assume_threads_oversubscription, SA);
3414
3415 if (Opts.OpenMPTeamSubscription)
3416 GenerateArg(Args, OPT_fopenmp_assume_teams_oversubscription, SA);
3417
3418 if (Opts.OpenMPTargetDebug != 0)
3419 GenerateArg(Args, OPT_fopenmp_target_debug_EQ,
3420 Twine(Opts.OpenMPTargetDebug), SA);
3421
3422 if (Opts.OpenMPCUDANumSMs != 0)
3423 GenerateArg(Args, OPT_fopenmp_cuda_number_of_sm_EQ,
3424 Twine(Opts.OpenMPCUDANumSMs), SA);
3425
3426 if (Opts.OpenMPCUDABlocksPerSM != 0)
3427 GenerateArg(Args, OPT_fopenmp_cuda_blocks_per_sm_EQ,
3428 Twine(Opts.OpenMPCUDABlocksPerSM), SA);
3429
3430 if (Opts.OpenMPCUDAReductionBufNum != 1024)
3431 GenerateArg(Args, OPT_fopenmp_cuda_teams_reduction_recs_num_EQ,
3432 Twine(Opts.OpenMPCUDAReductionBufNum), SA);
3433
3434 if (!Opts.OMPTargetTriples.empty()) {
3435 std::string Targets;
3436 llvm::raw_string_ostream OS(Targets);
3437 llvm::interleave(
3438 Opts.OMPTargetTriples, OS,
3439 [&OS](const llvm::Triple &T) { OS << T.str(); }, ",");
3440 GenerateArg(Args, OPT_fopenmp_targets_EQ, OS.str(), SA);
3441 }
3442
3443 if (!Opts.OMPHostIRFile.empty())
3444 GenerateArg(Args, OPT_fopenmp_host_ir_file_path, Opts.OMPHostIRFile, SA);
3445
3446 if (Opts.OpenMPCUDAMode)
3447 GenerateArg(Args, OPT_fopenmp_cuda_mode, SA);
3448
3449 // The arguments used to set Optimize, OptimizeSize and NoInlineDefine are
3450 // generated from CodeGenOptions.
3451
3452 if (Opts.DefaultFPContractMode == LangOptions::FPM_Fast)
3453 GenerateArg(Args, OPT_ffp_contract, "fast", SA);
3454 else if (Opts.DefaultFPContractMode == LangOptions::FPM_On)
3455 GenerateArg(Args, OPT_ffp_contract, "on", SA);
3456 else if (Opts.DefaultFPContractMode == LangOptions::FPM_Off)
3457 GenerateArg(Args, OPT_ffp_contract, "off", SA);
3458 else if (Opts.DefaultFPContractMode == LangOptions::FPM_FastHonorPragmas)
3459 GenerateArg(Args, OPT_ffp_contract, "fast-honor-pragmas", SA);
3460
3461 for (StringRef Sanitizer : serializeSanitizerKinds(Opts.Sanitize))
3462 GenerateArg(Args, OPT_fsanitize_EQ, Sanitizer, SA);
3463
3464 // Conflating '-fsanitize-system-ignorelist' and '-fsanitize-ignorelist'.
3465 for (const std::string &F : Opts.NoSanitizeFiles)
3466 GenerateArg(Args, OPT_fsanitize_ignorelist_EQ, F, SA);
3467
3468 if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver3_8)
3469 GenerateArg(Args, OPT_fclang_abi_compat_EQ, "3.8", SA);
3470 else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver4)
3471 GenerateArg(Args, OPT_fclang_abi_compat_EQ, "4.0", SA);
3472 else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver6)
3473 GenerateArg(Args, OPT_fclang_abi_compat_EQ, "6.0", SA);
3474 else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver7)
3475 GenerateArg(Args, OPT_fclang_abi_compat_EQ, "7.0", SA);
3476 else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver9)
3477 GenerateArg(Args, OPT_fclang_abi_compat_EQ, "9.0", SA);
3478 else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver11)
3479 GenerateArg(Args, OPT_fclang_abi_compat_EQ, "11.0", SA);
3480 else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver12)
3481 GenerateArg(Args, OPT_fclang_abi_compat_EQ, "12.0", SA);
3482 else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver14)
3483 GenerateArg(Args, OPT_fclang_abi_compat_EQ, "14.0", SA);
3484 else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver15)
3485 GenerateArg(Args, OPT_fclang_abi_compat_EQ, "15.0", SA);
3486
3487 if (Opts.getSignReturnAddressScope() ==
3489 GenerateArg(Args, OPT_msign_return_address_EQ, "all", SA);
3490 else if (Opts.getSignReturnAddressScope() ==
3492 GenerateArg(Args, OPT_msign_return_address_EQ, "non-leaf", SA);
3493
3494 if (Opts.getSignReturnAddressKey() ==
3496 GenerateArg(Args, OPT_msign_return_address_key_EQ, "b_key", SA);
3497
3498 if (Opts.CXXABI)
3499 GenerateArg(Args, OPT_fcxx_abi_EQ, TargetCXXABI::getSpelling(*Opts.CXXABI),
3500 SA);
3501
3502 if (Opts.RelativeCXXABIVTables)
3503 GenerateArg(Args, OPT_fexperimental_relative_cxx_abi_vtables, SA);
3504 else
3505 GenerateArg(Args, OPT_fno_experimental_relative_cxx_abi_vtables, SA);
3506
3507 if (Opts.UseTargetPathSeparator)
3508 GenerateArg(Args, OPT_ffile_reproducible, SA);
3509 else
3510 GenerateArg(Args, OPT_fno_file_reproducible, SA);
3511
3512 for (const auto &MP : Opts.MacroPrefixMap)
3513 GenerateArg(Args, OPT_fmacro_prefix_map_EQ, MP.first + "=" + MP.second, SA);
3514
3515 if (!Opts.RandstructSeed.empty())
3516 GenerateArg(Args, OPT_frandomize_layout_seed_EQ, Opts.RandstructSeed, SA);
3517}
3518
3519bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
3520 InputKind IK, const llvm::Triple &T,
3521 std::vector<std::string> &Includes,
3522 DiagnosticsEngine &Diags) {
3523 unsigned NumErrorsBefore = Diags.getNumErrors();
3524
3525 if (IK.getFormat() == InputKind::Precompiled ||
3527 // ObjCAAutoRefCount and Sanitize LangOpts are used to setup the
3528 // PassManager in BackendUtil.cpp. They need to be initialized no matter
3529 // what the input type is.
3530 if (Args.hasArg(OPT_fobjc_arc))
3531 Opts.ObjCAutoRefCount = 1;
3532 // PICLevel and PIELevel are needed during code generation and this should
3533 // be set regardless of the input type.
3534 Opts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags);
3535 Opts.PIE = Args.hasArg(OPT_pic_is_pie);
3536 parseSanitizerKinds("-fsanitize=", Args.getAllArgValues(OPT_fsanitize_EQ),
3537 Diags, Opts.Sanitize);
3538
3539 return Diags.getNumErrors() == NumErrorsBefore;
3540 }
3541
3542 // Other LangOpts are only initialized when the input is not AST or LLVM IR.
3543 // FIXME: Should we really be parsing this for an Language::Asm input?
3544
3545 // FIXME: Cleanup per-file based stuff.
3547 if (const Arg *A = Args.getLastArg(OPT_std_EQ)) {
3548 LangStd = LangStandard::getLangKind(A->getValue());
3549 if (LangStd == LangStandard::lang_unspecified) {
3550 Diags.Report(diag::err_drv_invalid_value)
3551 << A->getAsString(Args) << A->getValue();
3552 // Report supported standards with short description.
3553 for (unsigned KindValue = 0;
3554 KindValue != LangStandard::lang_unspecified;
3555 ++KindValue) {
3557 static_cast<LangStandard::Kind>(KindValue));
3559 auto Diag = Diags.Report(diag::note_drv_use_standard);
3560 Diag << Std.getName() << Std.getDescription();
3561 unsigned NumAliases = 0;
3562#define LANGSTANDARD(id, name, lang, desc, features)
3563#define LANGSTANDARD_ALIAS(id, alias) \
3564 if (KindValue == LangStandard::lang_##id) ++NumAliases;
3565#define LANGSTANDARD_ALIAS_DEPR(id, alias)
3566#include "clang/Basic/LangStandards.def"
3567 Diag << NumAliases;
3568#define LANGSTANDARD(id, name, lang, desc, features)
3569#define LANGSTANDARD_ALIAS(id, alias) \
3570 if (KindValue == LangStandard::lang_##id) Diag << alias;
3571#define LANGSTANDARD_ALIAS_DEPR(id, alias)
3572#include "clang/Basic/LangStandards.def"
3573 }
3574 }
3575 } else {
3576 // Valid standard, check to make sure language and standard are
3577 // compatible.
3580 Diags.Report(diag::err_drv_argument_not_allowed_with)
3581 << A->getAsString(Args) << GetInputKindName(IK);
3582 }
3583 }
3584 }
3585
3586 // -cl-std only applies for OpenCL language standards.
3587 // Override the -std option in this case.
3588 if (const Arg *A = Args.getLastArg(OPT_cl_std_EQ)) {
3589 LangStandard::Kind OpenCLLangStd
3590 = llvm::StringSwitch<LangStandard::Kind>(A->getValue())
3591 .Cases("cl", "CL", LangStandard::lang_opencl10)
3592 .Cases("cl1.0", "CL1.0", LangStandard::lang_opencl10)
3593 .Cases("cl1.1", "CL1.1", LangStandard::lang_opencl11)
3594 .Cases("cl1.2", "CL1.2", LangStandard::lang_opencl12)
3595 .Cases("cl2.0", "CL2.0", LangStandard::lang_opencl20)
3596 .Cases("cl3.0", "CL3.0", LangStandard::lang_opencl30)
3597 .Cases("clc++", "CLC++", LangStandard::lang_openclcpp10)
3598 .Cases("clc++1.0", "CLC++1.0", LangStandard::lang_openclcpp10)
3599 .Cases("clc++2021", "CLC++2021", LangStandard::lang_openclcpp2021)
3601
3602 if (OpenCLLangStd == LangStandard::lang_unspecified) {
3603 Diags.Report(diag::err_drv_invalid_value)
3604 << A->getAsString(Args) << A->getValue();
3605 }
3606 else
3607 LangStd = OpenCLLangStd;
3608 }
3609
3610 // These need to be parsed now. They are used to set OpenCL defaults.
3611 Opts.IncludeDefaultHeader = Args.hasArg(OPT_finclude_default_header);
3612 Opts.DeclareOpenCLBuiltins = Args.hasArg(OPT_fdeclare_opencl_builtins);
3613
3614 LangOptions::setLangDefaults(Opts, IK.getLanguage(), T, Includes, LangStd);
3615
3616 // The key paths of codegen options defined in Options.td start with
3617 // "LangOpts->". Let's provide the expected variable name and type.
3618 LangOptions *LangOpts = &Opts;
3619
3620#define LANG_OPTION_WITH_MARSHALLING(...) \
3621 PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
3622#include "clang/Driver/Options.inc"
3623#undef LANG_OPTION_WITH_MARSHALLING
3624
3625 if (const Arg *A = Args.getLastArg(OPT_fcf_protection_EQ)) {
3626 StringRef Name = A->getValue();
3627 if (Name == "full" || Name == "branch") {
3628 Opts.CFProtectionBranch = 1;
3629 }
3630 }
3631
3632 if ((Args.hasArg(OPT_fsycl_is_device) || Args.hasArg(OPT_fsycl_is_host)) &&
3633 !Args.hasArg(OPT_sycl_std_EQ)) {
3634 // If the user supplied -fsycl-is-device or -fsycl-is-host, but failed to
3635 // provide -sycl-std=, we want to default it to whatever the default SYCL
3636 // version is. I could not find a way to express this with the options
3637 // tablegen because we still want this value to be SYCL_None when the user
3638 // is not in device or host mode.
3639 Opts.setSYCLVersion(LangOptions::SYCL_Default);
3640 }
3641
3642 if (Opts.ObjC) {
3643 if (Arg *arg = Args.getLastArg(OPT_fobjc_runtime_EQ)) {
3644 StringRef value = arg->getValue();
3645 if (Opts.ObjCRuntime.tryParse(value))
3646 Diags.Report(diag::err_drv_unknown_objc_runtime) << value;
3647 }
3648
3649 if (Args.hasArg(OPT_fobjc_gc_only))
3650 Opts.setGC(LangOptions::GCOnly);
3651 else if (Args.hasArg(OPT_fobjc_gc))
3652 Opts.setGC(LangOptions::HybridGC);
3653 else if (Args.hasArg(OPT_fobjc_arc)) {
3654 Opts.ObjCAutoRefCount = 1;
3655 if (!Opts.ObjCRuntime.allowsARC())
3656 Diags.Report(diag::err_arc_unsupported_on_runtime);
3657 }
3658
3659 // ObjCWeakRuntime tracks whether the runtime supports __weak, not
3660 // whether the feature is actually enabled. This is predominantly
3661 // determined by -fobjc-runtime, but we allow it to be overridden
3662 // from the command line for testing purposes.
3663 if (Args.hasArg(OPT_fobjc_runtime_has_weak))
3664 Opts.ObjCWeakRuntime = 1;
3665 else
3666 Opts.ObjCWeakRuntime = Opts.ObjCRuntime.allowsWeak();
3667
3668 // ObjCWeak determines whether __weak is actually enabled.
3669 // Note that we allow -fno-objc-weak to disable this even in ARC mode.
3670 if (auto weakArg = Args.getLastArg(OPT_fobjc_weak, OPT_fno_objc_weak)) {
3671 if (!weakArg->getOption().matches(OPT_fobjc_weak)) {
3672 assert(!Opts.ObjCWeak);
3673 } else if (Opts.getGC() != LangOptions::NonGC) {
3674 Diags.Report(diag::err_objc_weak_with_gc);
3675 } else if (!Opts.ObjCWeakRuntime) {
3676 Diags.Report(diag::err_objc_weak_unsupported);
3677 } else {
3678 Opts.ObjCWeak = 1;
3679 }
3680 } else if (Opts.ObjCAutoRefCount) {
3681 Opts.ObjCWeak = Opts.ObjCWeakRuntime;
3682 }
3683
3684 if (Args.hasArg(OPT_fobjc_subscripting_legacy_runtime))
3685 Opts.ObjCSubscriptingLegacyRuntime =
3687 }
3688
3689 if (Arg *A = Args.getLastArg(options::OPT_fgnuc_version_EQ)) {
3690 // Check that the version has 1 to 3 components and the minor and patch
3691 // versions fit in two decimal digits.
3692 VersionTuple GNUCVer;
3693 bool Invalid = GNUCVer.tryParse(A->getValue());
3694 unsigned Major = GNUCVer.getMajor();
3695 unsigned Minor = GNUCVer.getMinor().value_or(0);
3696 unsigned Patch = GNUCVer.getSubminor().value_or(0);
3697 if (Invalid || GNUCVer.getBuild() || Minor >= 100 || Patch >= 100) {
3698 Diags.Report(diag::err_drv_invalid_value)
3699 << A->getAsString(Args) << A->getValue();
3700 }
3701 Opts.GNUCVersion = Major * 100 * 100 + Minor * 100 + Patch;
3702 }
3703
3704 if (T.isOSAIX() && (Args.hasArg(OPT_mignore_xcoff_visibility)))
3705 Opts.IgnoreXCOFFVisibility = 1;
3706
3707 if (Args.hasArg(OPT_ftrapv)) {
3708 Opts.setSignedOverflowBehavior(LangOptions::SOB_Trapping);
3709 // Set the handler, if one is specified.
3710 Opts.OverflowHandler =
3711 std::string(Args.getLastArgValue(OPT_ftrapv_handler));
3712 }
3713 else if (Args.hasArg(OPT_fwrapv))
3714 Opts.setSignedOverflowBehavior(LangOptions::SOB_Defined);
3715
3716 Opts.MSCompatibilityVersion = 0;
3717 if (const Arg *A = Args.getLastArg(OPT_fms_compatibility_version)) {
3718 VersionTuple VT;
3719 if (VT.tryParse(A->getValue()))
3720 Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args)
3721 << A->getValue();
3722 Opts.MSCompatibilityVersion = VT.getMajor() * 10000000 +
3723 VT.getMinor().value_or(0) * 100000 +
3724 VT.getSubminor().value_or(0);
3725 }
3726
3727 // Mimicking gcc's behavior, trigraphs are only enabled if -trigraphs
3728 // is specified, or -std is set to a conforming mode.
3729 // Trigraphs are disabled by default in c++1z onwards.
3730 // For z/OS, trigraphs are enabled by default (without regard to the above).
3731 Opts.Trigraphs =
3732 (!Opts.GNUMode && !Opts.MSVCCompat && !Opts.CPlusPlus17) || T.isOSzOS();
3733 Opts.Trigraphs =
3734 Args.hasFlag(OPT_ftrigraphs, OPT_fno_trigraphs, Opts.Trigraphs);
3735
3736 Opts.Blocks = Args.hasArg(OPT_fblocks) || (Opts.OpenCL
3737 && Opts.OpenCLVersion == 200);
3738
3739 Opts.ConvergentFunctions = Opts.OpenCL || (Opts.CUDA && Opts.CUDAIsDevice) ||
3740 Opts.SYCLIsDevice ||
3741 Args.hasArg(OPT_fconvergent_functions);
3742
3743 Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding;
3744 if (!Opts.NoBuiltin)
3746 if (Arg *A = Args.getLastArg(options::OPT_LongDouble_Group)) {
3747 if (A->getOption().matches(options::OPT_mlong_double_64))
3748 Opts.LongDoubleSize = 64;
3749 else if (A->getOption().matches(options::OPT_mlong_double_80))
3750 Opts.LongDoubleSize = 80;
3751 else if (A->getOption().matches(options::OPT_mlong_double_128))
3752 Opts.LongDoubleSize = 128;
3753 else
3754 Opts.LongDoubleSize = 0;
3755 }
3756 if (Opts.FastRelaxedMath || Opts.CLUnsafeMath)
3757 Opts.setDefaultFPContractMode(LangOptions::FPM_Fast);
3758
3759 llvm::sort(Opts.ModuleFeatures);
3760
3761 // -mrtd option
3762 if (Arg *A = Args.getLastArg(OPT_mrtd)) {
3763 if (Opts.getDefaultCallingConv() != LangOptions::DCC_None)
3764 Diags.Report(diag::err_drv_argument_not_allowed_with)
3765 << A->getSpelling() << "-fdefault-calling-conv";
3766 else {
3767 if (T.getArch() != llvm::Triple::x86)
3768 Diags.Report(diag::err_drv_argument_not_allowed_with)
3769 << A->getSpelling() << T.getTriple();
3770 else
3771 Opts.setDefaultCallingConv(LangOptions::DCC_StdCall);
3772 }
3773 }
3774
3775 // Check if -fopenmp is specified and set default version to 5.0.
3776 Opts.OpenMP = Args.hasArg(OPT_fopenmp) ? 50 : 0;
3777 // Check if -fopenmp-simd is specified.
3778 bool IsSimdSpecified =
3779 Args.hasFlag(options::OPT_fopenmp_simd, options::OPT_fno_openmp_simd,
3780 /*Default=*/false);
3781 Opts.OpenMPSimd = !Opts.OpenMP && IsSimdSpecified;
3782 Opts.OpenMPUseTLS =
3783 Opts.OpenMP && !Args.hasArg(options::OPT_fnoopenmp_use_tls);
3784 Opts.OpenMPIsDevice =
3785 Opts.OpenMP && Args.hasArg(options::OPT_fopenmp_is_device);
3786 Opts.OpenMPIRBuilder =
3787 Opts.OpenMP && Args.hasArg(options::OPT_fopenmp_enable_irbuilder);
3788 bool IsTargetSpecified =
3789 Opts.OpenMPIsDevice || Args.hasArg(options::OPT_fopenmp_targets_EQ);
3790
3791 Opts.ConvergentFunctions = Opts.ConvergentFunctions || Opts.OpenMPIsDevice;
3792
3793 if (Opts.OpenMP || Opts.OpenMPSimd) {
3794 if (int Version = getLastArgIntValue(
3795 Args, OPT_fopenmp_version_EQ,
3796 (IsSimdSpecified || IsTargetSpecified) ? 50 : Opts.OpenMP, Diags))
3797 Opts.OpenMP = Version;
3798 // Provide diagnostic when a given target is not expected to be an OpenMP
3799 // device or host.
3800 if (!Opts.OpenMPIsDevice) {
3801 switch (T.getArch()) {
3802 default:
3803 break;
3804 // Add unsupported host targets here:
3805 case llvm::Triple::nvptx:
3806 case llvm::Triple::nvptx64:
3807 Diags.Report(diag::err_drv_omp_host_target_not_supported) << T.str();
3808 break;
3809 }
3810 }
3811 }
3812
3813 // Set the flag to prevent the implementation from emitting device exception
3814 // handling code for those requiring so.
3815 if ((Opts.OpenMPIsDevice && (T.isNVPTX() || T.isAMDGCN())) ||
3816 Opts.OpenCLCPlusPlus) {
3817
3818 Opts.Exceptions = 0;
3819 Opts.CXXExceptions = 0;
3820 }
3821 if (Opts.OpenMPIsDevice && T.isNVPTX()) {
3822 Opts.OpenMPCUDANumSMs =
3823 getLastArgIntValue(Args, options::OPT_fopenmp_cuda_number_of_sm_EQ,
3824 Opts.OpenMPCUDANumSMs, Diags);
3825 Opts.OpenMPCUDABlocksPerSM =
3826 getLastArgIntValue(Args, options::OPT_fopenmp_cuda_blocks_per_sm_EQ,
3827 Opts.OpenMPCUDABlocksPerSM, Diags);
3828 Opts.OpenMPCUDAReductionBufNum = getLastArgIntValue(
3829 Args, options::OPT_fopenmp_cuda_teams_reduction_recs_num_EQ,
3830 Opts.OpenMPCUDAReductionBufNum, Diags);
3831 }
3832
3833 // Set the value of the debugging flag used in the new offloading device RTL.
3834 // Set either by a specific value or to a default if not specified.
3835 if (Opts.OpenMPIsDevice && (Args.hasArg(OPT_fopenmp_target_debug) ||
3836 Args.hasArg(OPT_fopenmp_target_debug_EQ))) {
3837 Opts.OpenMPTargetDebug = getLastArgIntValue(
3838 Args, OPT_fopenmp_target_debug_EQ, Opts.OpenMPTargetDebug, Diags);
3839 if (!Opts.OpenMPTargetDebug && Args.hasArg(OPT_fopenmp_target_debug))
3840 Opts.OpenMPTargetDebug = 1;
3841 }
3842
3843 if (Opts.OpenMPIsDevice) {
3844 if (Args.hasArg(OPT_fopenmp_assume_teams_oversubscription))
3845 Opts.OpenMPTeamSubscription = true;
3846 if (Args.hasArg(OPT_fopenmp_assume_threads_oversubscription))
3847 Opts.OpenMPThreadSubscription = true;
3848 }
3849
3850 // Get the OpenMP target triples if any.
3851 if (Arg *A = Args.getLastArg(options::OPT_fopenmp_targets_EQ)) {
3852 enum ArchPtrSize { Arch16Bit, Arch32Bit, Arch64Bit };
3853 auto getArchPtrSize = [](const llvm::Triple &T) {
3854 if (T.isArch16Bit())
3855 return Arch16Bit;
3856 if (T.isArch32Bit())
3857 return Arch32Bit;
3858 assert(T.isArch64Bit() && "Expected 64-bit architecture");
3859 return Arch64Bit;
3860 };
3861
3862 for (unsigned i = 0; i < A->getNumValues(); ++i) {
3863 llvm::Triple TT(A->getValue(i));
3864
3865 if (TT.getArch() == llvm::Triple::UnknownArch ||
3866 !(TT.getArch() == llvm::Triple::aarch64 || TT.isPPC() ||
3867 TT.getArch() == llvm::Triple::nvptx ||
3868 TT.getArch() == llvm::Triple::nvptx64 ||
3869 TT.getArch() == llvm::Triple::amdgcn ||
3870 TT.getArch() == llvm::Triple::x86 ||
3871 TT.getArch() == llvm::Triple::x86_64))
3872 Diags.Report(diag::err_drv_invalid_omp_target) << A->getValue(i);
3873 else if (getArchPtrSize(T) != getArchPtrSize(TT))
3874 Diags.Report(diag::err_drv_incompatible_omp_arch)
3875 << A->getValue(i) << T.str();
3876 else
3877 Opts.OMPTargetTriples.push_back(TT);
3878 }
3879 }
3880
3881 // Get OpenMP host file path if any and report if a non existent file is
3882 // found
3883 if (Arg *A = Args.getLastArg(options::OPT_fopenmp_host_ir_file_path)) {
3884 Opts.OMPHostIRFile = A->getValue();
3885 if (!llvm::sys::fs::exists(Opts.OMPHostIRFile))
3886 Diags.Report(diag::err_drv_omp_host_ir_file_not_found)
3887 << Opts.OMPHostIRFile;
3888 }
3889
3890 // Set CUDA mode for OpenMP target NVPTX/AMDGCN if specified in options
3891 Opts.OpenMPCUDAMode = Opts.OpenMPIsDevice && (T.isNVPTX() || T.isAMDGCN()) &&
3892 Args.hasArg(options::OPT_fopenmp_cuda_mode);
3893
3894 // FIXME: Eliminate this dependency.
3895 unsigned Opt = getOptimizationLevel(Args, IK, Diags),
3896 OptSize = getOptimizationLevelSize(Args);
3897 Opts.Optimize = Opt != 0;
3898 Opts.OptimizeSize = OptSize != 0;
3899
3900 // This is the __NO_INLINE__ define, which just depends on things like the
3901 // optimization level and -fno-inline, not actually whether the backend has
3902 // inlining enabled.
3903 Opts.NoInlineDefine = !Opts.Optimize;
3904 if (Arg *InlineArg = Args.getLastArg(
3905 options::OPT_finline_functions, options::OPT_finline_hint_functions,
3906 options::OPT_fno_inline_functions, options::OPT_fno_inline))
3907 if (InlineArg->getOption().matches(options::OPT_fno_inline))
3908 Opts.NoInlineDefine = true;
3909
3910 if (Arg *A = Args.getLastArg(OPT_ffp_contract)) {
3911 StringRef Val = A->getValue();
3912 if (Val == "fast")
3913 Opts.setDefaultFPContractMode(LangOptions::FPM_Fast);
3914 else if (Val == "on")
3915 Opts.setDefaultFPContractMode(LangOptions::FPM_On);
3916 else if (Val == "off")
3917 Opts.setDefaultFPContractMode(LangOptions::FPM_Off);
3918 else if (Val == "fast-honor-pragmas")
3919 Opts.setDefaultFPContractMode(LangOptions::FPM_FastHonorPragmas);
3920 else
3921 Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;
3922 }
3923
3924 // Parse -fsanitize= arguments.
3925 parseSanitizerKinds("-fsanitize=", Args.getAllArgValues(OPT_fsanitize_EQ),
3926 Diags, Opts.Sanitize);
3927 Opts.NoSanitizeFiles = Args.getAllArgValues(OPT_fsanitize_ignorelist_EQ);
3928 std::vector<std::string> systemIgnorelists =
3929 Args.getAllArgValues(OPT_fsanitize_system_ignorelist_EQ);
3930 Opts.NoSanitizeFiles.insert(Opts.NoSanitizeFiles.end(),
3931 systemIgnorelists.begin(),
3932 systemIgnorelists.end());
3933
3934 if (Arg *A = Args.getLastArg(OPT_fclang_abi_compat_EQ)) {
3935 Opts.setClangABICompat(LangOptions::ClangABI::Latest);
3936
3937 StringRef Ver = A->getValue();
3938 std::pair<StringRef, StringRef> VerParts = Ver.split('.');
3939 unsigned Major, Minor = 0;
3940
3941 // Check the version number is valid: either 3.x (0 <= x <= 9) or
3942 // y or y.0 (4 <= y <= current version).
3943 if (!VerParts.first.startswith("0") &&
3944 !VerParts.first.getAsInteger(10, Major) &&
3945 3 <= Major && Major <= CLANG_VERSION_MAJOR &&
3946 (Major == 3 ? VerParts.second.size() == 1 &&
3947 !VerParts.second.getAsInteger(10, Minor)
3948 : VerParts.first.size() == Ver.size() ||
3949 VerParts.second == "0")) {
3950 // Got a valid version number.
3951 if (Major == 3 && Minor <= 8)
3952 Opts.setClangABICompat(LangOptions::ClangABI::Ver3_8);
3953 else if (Major <= 4)
3954 Opts.setClangABICompat(LangOptions::ClangABI::Ver4);
3955 else if (Major <= 6)
3956 Opts.setClangABICompat(LangOptions::ClangABI::Ver6);
3957 else if (Major <= 7)
3958 Opts.setClangABICompat(LangOptions::ClangABI::Ver7);
3959 else if (Major <= 9)
3960 Opts.setClangABICompat(LangOptions::ClangABI::Ver9);
3961 else if (Major <= 11)
3962 Opts.setClangABICompat(LangOptions::ClangABI::Ver11);
3963 else if (Major <= 12)
3964 Opts.setClangABICompat(LangOptions::ClangABI::Ver12);
3965 else if (Major <= 14)
3966 Opts.setClangABICompat(LangOptions::ClangABI::Ver14);
3967 else if (Major <= 15)
3968 Opts.setClangABICompat(LangOptions::ClangABI::Ver15);
3969 } else if (Ver != "latest") {
3970 Diags.Report(diag::err_drv_invalid_value)
3971 << A->getAsString(Args) << A->getValue();
3972 }
3973 }
3974
3975 if (Arg *A = Args.getLastArg(OPT_msign_return_address_EQ)) {
3976 StringRef SignScope = A->getValue();
3977
3978 if (SignScope.equals_insensitive("none"))
3979 Opts.setSignReturnAddressScope(
3981 else if (SignScope.equals_insensitive("all"))
3982 Opts.setSignReturnAddressScope(
3984 else if (SignScope.equals_insensitive("non-leaf"))
3985 Opts.setSignReturnAddressScope(
3987 else
3988 Diags.Report(diag::err_drv_invalid_value)
3989 << A->getAsString(Args) << SignScope;
3990
3991 if (Arg *A = Args.getLastArg(OPT_msign_return_address_key_EQ)) {
3992 StringRef SignKey = A->getValue();
3993 if (!SignScope.empty() && !SignKey.empty()) {
3994 if (SignKey.equals_insensitive("a_key"))
3995 Opts.setSignReturnAddressKey(
3997 else if (SignKey.equals_insensitive("b_key"))
3998 Opts.setSignReturnAddressKey(
4000 else
4001 Diags.Report(diag::err_drv_invalid_value)
4002 << A->getAsString(Args) << SignKey;
4003 }
4004 }
4005 }
4006
4007 // The value can be empty, which indicates the system default should be used.
4008 StringRef CXXABI = Args.getLastArgValue(OPT_fcxx_abi_EQ);
4009 if (!CXXABI.empty()) {
4011 Diags.Report(diag::err_invalid_cxx_abi) << CXXABI;
4012 } else {
4014 if (!TargetCXXABI::isSupportedCXXABI(T, Kind))
4015 Diags.Report(diag::err_unsupported_cxx_abi) << CXXABI << T.str();
4016 else
4017 Opts.CXXABI = Kind;
4018 }
4019 }
4020
4021 Opts.RelativeCXXABIVTables =
4022 Args.hasFlag(options::OPT_fexperimental_relative_cxx_abi_vtables,
4023 options::OPT_fno_experimental_relative_cxx_abi_vtables,
4025
4026 for (const auto &A : Args.getAllArgValues(OPT_fmacro_prefix_map_EQ)) {
4027 auto Split = StringRef(A).split('=');
4028 Opts.MacroPrefixMap.insert(
4029 {std::string(Split.first), std::string(Split.second)});
4030 }
4031
4033 !Args.getLastArg(OPT_fno_file_reproducible) &&
4034 (Args.getLastArg(OPT_ffile_compilation_dir_EQ) ||
4035 Args.getLastArg(OPT_fmacro_prefix_map_EQ) ||
4036 Args.getLastArg(OPT_ffile_reproducible));
4037
4038 // Error if -mvscale-min is unbounded.
4039 if (Arg *A = Args.getLastArg(options::OPT_mvscale_min_EQ)) {
4040 unsigned VScaleMin;
4041 if (StringRef(A->getValue()).getAsInteger(10, VScaleMin) || VScaleMin == 0)
4042 Diags.Report(diag::err_cc1_unbounded_vscale_min);
4043 }
4044
4045 if (const Arg *A = Args.getLastArg(OPT_frandomize_layout_seed_file_EQ)) {
4046 std::ifstream SeedFile(A->getValue(0));
4047
4048 if (!SeedFile.is_open())
4049 Diags.Report(diag::err_drv_cannot_open_randomize_layout_seed_file)
4050 << A->getValue(0);
4051
4052 std::getline(SeedFile, Opts.RandstructSeed);
4053 }
4054
4055 if (const Arg *A = Args.getLastArg(OPT_frandomize_layout_seed_EQ))
4056 Opts.RandstructSeed = A->getValue(0);
4057
4058 // Validate options for HLSL
4059 if (Opts.HLSL) {
4060 bool SupportedTarget = T.getArch() == llvm::Triple::dxil &&
4061 T.getOS() == llvm::Triple::ShaderModel;
4062 if (!SupportedTarget)
4063 Diags.Report(diag::err_drv_hlsl_unsupported_target) << T.str();
4064 }
4065
4066 return Diags.getNumErrors() == NumErrorsBefore;
4067}
4068
4070 switch (Action) {
4072 case frontend::ASTDump:
4073 case frontend::ASTPrint:
4074 case frontend::ASTView:
4076 case frontend::EmitBC:
4077 case frontend::EmitHTML:
4078 case frontend::EmitLLVM:
4081 case frontend::EmitObj:
4083 case frontend::FixIt:
4098 return false;
4099
4103 case frontend::InitOnly:
4109 return true;
4110 }
4111 llvm_unreachable("invalid frontend action");
4112}
4113
4117 const LangOptions &LangOpts,
4118 const FrontendOptions &FrontendOpts,
4119 const CodeGenOptions &CodeGenOpts) {
4120 PreprocessorOptions *PreprocessorOpts = &Opts;
4121
4122#define PREPROCESSOR_OPTION_WITH_MARSHALLING(...) \
4123 GENERATE_OPTION_WITH_MARSHALLING(Args, SA, __VA_ARGS__)
4124#include "clang/Driver/Options.inc"
4125#undef PREPROCESSOR_OPTION_WITH_MARSHALLING
4126
4127 if (Opts.PCHWithHdrStop && !Opts.PCHWithHdrStopCreate)
4128 GenerateArg(Args, OPT_pch_through_hdrstop_use, SA);
4129
4130 for (const auto &D : Opts.DeserializedPCHDeclsToErrorOn)
4131 GenerateArg(Args, OPT_error_on_deserialized_pch_decl, D, SA);
4132
4133 if (Opts.PrecompiledPreambleBytes != std::make_pair(0u, false))
4134 GenerateArg(Args, OPT_preamble_bytes_EQ,
4135 Twine(Opts.PrecompiledPreambleBytes.first) + "," +
4136 (Opts.PrecompiledPreambleBytes.second ? "1" : "0"),
4137 SA);
4138
4139 for (const auto &M : Opts.Macros) {
4140 // Don't generate __CET__ macro definitions. They are implied by the
4141 // -fcf-protection option that is generated elsewhere.
4142 if (M.first == "__CET__=1" && !M.second &&
4143 !CodeGenOpts.CFProtectionReturn && CodeGenOpts.CFProtectionBranch)
4144 continue;
4145 if (M.first == "__CET__=2" && !M.second && CodeGenOpts.CFProtectionReturn &&
4146 !CodeGenOpts.CFProtectionBranch)
4147 continue;
4148 if (M.first == "__CET__=3" && !M.second && CodeGenOpts.CFProtectionReturn &&
4149 CodeGenOpts.CFProtectionBranch)
4150 continue;
4151
4152 GenerateArg(Args, M.second ? OPT_U : OPT_D, M.first, SA);
4153 }
4154
4155 for (const auto &I : Opts.Includes) {
4156 // Don't generate OpenCL includes. They are implied by other flags that are
4157 // generated elsewhere.
4158 if (LangOpts.OpenCL && LangOpts.IncludeDefaultHeader &&
4159 ((LangOpts.DeclareOpenCLBuiltins && I == "opencl-c-base.h") ||
4160 I == "opencl-c.h"))
4161 continue;
4162 // Don't generate HLSL includes. They are implied by other flags that are
4163 // generated elsewhere.
4164 if (LangOpts.HLSL && I == "hlsl.h")
4165 continue;
4166
4167 GenerateArg(Args, OPT_include, I, SA);
4168 }
4169
4170 for (const auto &CI : Opts.ChainedIncludes)
4171 GenerateArg(Args, OPT_chain_include, CI, SA);
4172
4173 for (const auto &RF : Opts.RemappedFiles)
4174 GenerateArg(Args, OPT_remap_file, RF.first + ";" + RF.second, SA);
4175
4176 if (Opts.SourceDateEpoch)
4177 GenerateArg(Args, OPT_source_date_epoch, Twine(*Opts.SourceDateEpoch), SA);
4178
4179 // Don't handle LexEditorPlaceholders. It is implied by the action that is
4180 // generated elsewhere.
4181}
4182
4183static bool ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
4184 DiagnosticsEngine &Diags,
4186 const FrontendOptions &FrontendOpts) {
4187 unsigned NumErrorsBefore = Diags.getNumErrors();
4188
4189 PreprocessorOptions *PreprocessorOpts = &Opts;
4190
4191#define PREPROCESSOR_OPTION_WITH_MARSHALLING(...) \
4192 PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
4193#include "clang/Driver/Options.inc"
4194#undef PREPROCESSOR_OPTION_WITH_MARSHALLING
4195
4196 Opts.PCHWithHdrStop = Args.hasArg(OPT_pch_through_hdrstop_create) ||
4197 Args.hasArg(OPT_pch_through_hdrstop_use);
4198
4199 for (const auto *A : Args.filtered(OPT_error_on_deserialized_pch_decl))
4200 Opts.DeserializedPCHDeclsToErrorOn.insert(A->getValue());
4201
4202 if (const Arg *A = Args.getLastArg(OPT_preamble_bytes_EQ)) {
4203 StringRef Value(A->getValue());
4204 size_t Comma = Value.find(',');
4205 unsigned Bytes = 0;
4206 unsigned EndOfLine = 0;
4207
4208 if (Comma == StringRef::npos ||
4209 Value.substr(0, Comma).getAsInteger(10, Bytes) ||
4210 Value.substr(Comma + 1).getAsInteger(10, EndOfLine))
4211 Diags.Report(diag::err_drv_preamble_format);
4212 else {
4213 Opts.PrecompiledPreambleBytes.first = Bytes;
4214 Opts.PrecompiledPreambleBytes.second = (EndOfLine != 0);
4215 }
4216 }
4217
4218 // Add the __CET__ macro if a CFProtection option is set.
4219 if (const Arg *A = Args.getLastArg(OPT_fcf_protection_EQ)) {
4220 StringRef Name = A->getValue();
4221 if (Name == "branch")
4222 Opts.addMacroDef("__CET__=1");
4223 else if (Name == "return")
4224 Opts.addMacroDef("__CET__=2");
4225 else if (Name == "full")
4226 Opts.addMacroDef("__CET__=3");
4227 }
4228
4229 // Add macros from the command line.
4230 for (const auto *A : Args.filtered(OPT_D, OPT_U)) {
4231 if (A->getOption().matches(OPT_D))
4232 Opts.addMacroDef(A->getValue());
4233 else
4234 Opts.addMacroUndef(A->getValue());
4235 }
4236
4237 // Add the ordered list of -includes.
4238 for (const auto *A : Args.filtered(OPT_include))
4239 Opts.Includes.emplace_back(A->getValue());
4240
4241 for (const auto *A : Args.filtered(OPT_chain_include))
4242 Opts.ChainedIncludes.emplace_back(A->getValue());
4243
4244 for (const auto *A : Args.filtered(OPT_remap_file)) {
4245 std::pair<StringRef, StringRef> Split = StringRef(A->getValue()).split(';');
4246
4247 if (Split.second.empty()) {
4248 Diags.Report(diag::err_drv_invalid_remap_file) << A->getAsString(Args);
4249 continue;
4250 }
4251
4252 Opts.addRemappedFile(Split.first, Split.second);
4253 }
4254
4255 if (const Arg *A = Args.getLastArg(OPT_source_date_epoch)) {
4256 StringRef Epoch = A->getValue();
4257 // SOURCE_DATE_EPOCH, if specified, must be a non-negative decimal integer.
4258 // On time64 systems, pick 253402300799 (the UNIX timestamp of
4259 // 9999-12-31T23:59:59Z) as the upper bound.
4260 const uint64_t MaxTimestamp =
4261 std::min<uint64_t>(std::numeric_limits<time_t>::max(), 253402300799);
4262 uint64_t V;
4263 if (Epoch.getAsInteger(10, V) || V > MaxTimestamp) {
4264 Diags.Report(diag::err_fe_invalid_source_date_epoch)
4265 << Epoch << MaxTimestamp;
4266 } else {
4267 Opts.SourceDateEpoch = V;
4268 }
4269 }
4270
4271 // Always avoid lexing editor placeholders when we're just running the
4272 // preprocessor as we never want to emit the
4273 // "editor placeholder in source file" error in PP only mode.
4275 Opts.LexEditorPlaceholders = false;
4276
4277 return Diags.getNumErrors() == NumErrorsBefore;
4278}
4279
4283 const PreprocessorOutputOptions &PreprocessorOutputOpts = Opts;
4284
4285#define PREPROCESSOR_OUTPUT_OPTION_WITH_MARSHALLING(...) \
4286 GENERATE_OPTION_WITH_MARSHALLING(Args, SA, __VA_ARGS__)
4287#include "clang/Driver/Options.inc"
4288#undef PREPROCESSOR_OUTPUT_OPTION_WITH_MARSHALLING
4289
4290 bool Generate_dM = isStrictlyPreprocessorAction(Action) && !Opts.ShowCPP;
4291 if (Generate_dM)
4292 GenerateArg(Args, OPT_dM, SA);
4293 if (!Generate_dM && Opts.ShowMacros)
4294 GenerateArg(Args, OPT_dD, SA);
4295 if (Opts.DirectivesOnly)
4296 GenerateArg(Args, OPT_fdirectives_only, SA);
4297}
4298
4300 ArgList &Args, DiagnosticsEngine &Diags,
4302 unsigned NumErrorsBefore = Diags.getNumErrors();
4303
4304 PreprocessorOutputOptions &PreprocessorOutputOpts = Opts;
4305
4306#define PREPROCESSOR_OUTPUT_OPTION_WITH_MARSHALLING(...) \
4307 PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
4308#include "clang/Driver/Options.inc"
4309#undef PREPROCESSOR_OUTPUT_OPTION_WITH_MARSHALLING
4310
4311 Opts.ShowCPP = isStrictlyPreprocessorAction(Action) && !Args.hasArg(OPT_dM);
4312 Opts.ShowMacros = Args.hasArg(OPT_dM) || Args.hasArg(OPT_dD);
4313 Opts.DirectivesOnly = Args.hasArg(OPT_fdirectives_only);
4314
4315 return Diags.getNumErrors() == NumErrorsBefore;
4316}
4317
4318static void GenerateTargetArgs(const TargetOptions &Opts,
4321 const TargetOptions *TargetOpts = &Opts;
4322#define TARGET_OPTION_WITH_MARSHALLING(...) \
4323 GENERATE_OPTION_WITH_MARSHALLING(Args, SA, __VA_ARGS__)
4324#include "clang/Driver/Options.inc"
4325#undef TARGET_OPTION_WITH_MARSHALLING
4326
4327 if (!Opts.SDKVersion.empty())
4328 GenerateArg(Args, OPT_target_sdk_version_EQ, Opts.SDKVersion.getAsString(),
4329 SA);
4330 if (!Opts.DarwinTargetVariantSDKVersion.empty())
4331 GenerateArg(Args, OPT_darwin_target_variant_sdk_version_EQ,
4332 Opts.DarwinTargetVariantSDKVersion.getAsString(), SA);
4333}
4334
4335static bool ParseTargetArgs(TargetOptions &Opts, ArgList &Args,
4336 DiagnosticsEngine &Diags) {
4337 unsigned NumErrorsBefore = Diags.getNumErrors();
4338
4339 TargetOptions *TargetOpts = &Opts;
4340
4341#define TARGET_OPTION_WITH_MARSHALLING(...) \
4342 PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
4343#include "clang/Driver/Options.inc"
4344#undef TARGET_OPTION_WITH_MARSHALLING
4345
4346 if (Arg *A = Args.getLastArg(options::OPT_target_sdk_version_EQ)) {
4347 llvm::VersionTuple Version;
4348 if (Version.tryParse(A->getValue()))
4349 Diags.Report(diag::err_drv_invalid_value)
4350 << A->getAsString(Args) << A->getValue();
4351 else
4352 Opts.SDKVersion = Version;
4353 }
4354 if (Arg *A =
4355 Args.getLastArg(options::OPT_darwin_target_variant_sdk_version_EQ)) {
4356 llvm::VersionTuple Version;
4357 if (Version.tryParse(A->getValue()))
4358 Diags.Report(diag::err_drv_invalid_value)
4359 << A->getAsString(Args) << A->getValue();
4360 else
4361 Opts.DarwinTargetVariantSDKVersion = Version;
4362 }
4363
4364 return Diags.getNumErrors() == NumErrorsBefore;
4365}
4366
4367bool CompilerInvocation::CreateFromArgsImpl(
4368 CompilerInvocation &Res, ArrayRef<const char *> CommandLineArgs,
4369 DiagnosticsEngine &Diags, const char *Argv0) {
4370 unsigned NumErrorsBefore = Diags.getNumErrors();
4371
4372 // Parse the arguments.
4373 const OptTable &Opts = getDriverOptTable();
4374 const unsigned IncludedFlagsBitmask = options::CC1Option;
4375 unsigned MissingArgIndex, MissingArgCount;
4376 InputArgList Args = Opts.ParseArgs(CommandLineArgs, MissingArgIndex,
4377 MissingArgCount, IncludedFlagsBitmask);
4379
4380 // Check for missing argument error.
4381 if (MissingArgCount)
4382 Diags.Report(diag::err_drv_missing_argument)
4383 << Args.getArgString(MissingArgIndex) << MissingArgCount;
4384
4385 // Issue errors on unknown arguments.
4386 for (const auto *A : Args.filtered(OPT_UNKNOWN)) {
4387 auto ArgString = A->getAsString(Args);
4388 std::string Nearest;
4389 if (Opts.findNearest(ArgString, Nearest, IncludedFlagsBitmask) > 1)
4390 Diags.Report(diag::err_drv_unknown_argument) << ArgString;
4391 else
4392 Diags.Report(diag::err_drv_unknown_argument_with_suggestion)
4393 << ArgString << Nearest;
4394 }
4395
4396 ParseFileSystemArgs(Res.getFileSystemOpts(), Args, Diags);
4397 ParseMigratorArgs(Res.getMigratorOpts(), Args, Diags);
4398 ParseAnalyzerArgs(*Res.getAnalyzerOpts(), Args, Diags);
4399 ParseDiagnosticArgs(Res.getDiagnosticOpts(), Args, &Diags,
4400 /*DefaultDiagColor=*/false);
4401 ParseFrontendArgs(Res.getFrontendOpts(), Args, Diags, LangOpts.IsHeaderFile);
4402 // FIXME: We shouldn't have to pass the DashX option around here
4403 InputKind DashX = Res.getFrontendOpts().DashX;
4404 ParseTargetArgs(Res.getTargetOpts(), Args, Diags);
4405 llvm::Triple T(Res.getTargetOpts().Triple);
4406 ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), Args, Diags,
4408
4409 ParseLangArgs(LangOpts, Args, DashX, T, Res.getPreprocessorOpts().Includes,
4410 Diags);
4412 LangOpts.ObjCExceptions = 1;
4413
4414 for (auto Warning : Res.getDiagnosticOpts().Warnings) {
4415 if (Warning == "misexpect" &&
4416 !Diags.isIgnored(diag::warn_profile_data_misexpect, SourceLocation())) {
4417 Res.getCodeGenOpts().MisExpect = true;
4418 }
4419 }
4420
4421 if (LangOpts.CUDA) {
4422 // During CUDA device-side compilation, the aux triple is the
4423 // triple used for host compilation.
4424 if (LangOpts.CUDAIsDevice)
4426 }
4427
4428 // Set the triple of the host for OpenMP device compile.
4429 if (LangOpts.OpenMPIsDevice)
4431
4432 ParseCodeGenArgs(Res.getCodeGenOpts(), Args, DashX, Diags, T,
4434
4435 // FIXME: Override value name discarding when asan or msan is used because the
4436 // backend passes depend on the name of the alloca in order to print out
4437 // names.
4438 Res.getCodeGenOpts().DiscardValueNames &=
4439 !LangOpts.Sanitize.has(SanitizerKind::Address) &&
4440 !LangOpts.Sanitize.has(SanitizerKind::KernelAddress) &&
4441 !LangOpts.Sanitize.has(SanitizerKind::Memory) &&
4442 !LangOpts.Sanitize.has(SanitizerKind::KernelMemory);
4443
4444 ParsePreprocessorArgs(Res.getPreprocessorOpts(), Args, Diags,
4446 Res.getFrontendOpts());
4449
4453 if (!Res.getDependencyOutputOpts().OutputFile.empty() &&
4454 Res.getDependencyOutputOpts().Targets.empty())
4455 Diags.Report(diag::err_fe_dependency_file_requires_MT);
4456
4457 // If sanitizer is enabled, disable OPT_ffine_grained_bitfield_accesses.
4458 if (Res.getCodeGenOpts().FineGrainedBitfieldAccesses &&
4459 !Res.getLangOpts()->Sanitize.empty()) {
4460 Res.getCodeGenOpts().FineGrainedBitfieldAccesses = false;
4461 Diags.Report(diag::warn_drv_fine_grained_bitfield_accesses_ignored);
4462 }
4463
4464 // Store the command-line for using in the CodeView backend.
4465 if (Res.getCodeGenOpts().CodeViewCommandLine) {
4466 Res.getCodeGenOpts().Argv0 = Argv0;
4467 append_range(Res.getCodeGenOpts().CommandLineArgs, CommandLineArgs);
4468 }
4469
4470 // Set PGOOptions. Need to create a temporary VFS to read the profile
4471 // to determine the PGO type.
4472 if (!Res.getCodeGenOpts().ProfileInstrumentUsePath.empty()) {
4473 auto FS =
4475 Diags, llvm::vfs::getRealFileSystem());
4478 Diags);
4479 }
4480
4481 FixupInvocation(Res, Diags, Args, DashX);
4482
4483 return Diags.getNumErrors() == NumErrorsBefore;
4484}
4485
4487 ArrayRef<const char *> CommandLineArgs,
4488 DiagnosticsEngine &Diags,
4489 const char *Argv0) {
4490 CompilerInvocation DummyInvocation;
4491
4492 return RoundTrip(
4493 [](CompilerInvocation &Invocation, ArrayRef<const char *> CommandLineArgs,
4494 DiagnosticsEngine &Diags, const char *Argv0) {
4495 return CreateFromArgsImpl(Invocation, CommandLineArgs, Diags, Argv0);
4496 },
4498 StringAllocator SA) {
4499 Args.push_back("-cc1");
4500 Invocation.generateCC1CommandLine(Args, SA);
4501 },
4502 Invocation, DummyInvocation, CommandLineArgs, Diags, Argv0);
4503}
4504
4506 // FIXME: Consider using SHA1 instead of MD5.
4507 llvm::HashBuilder<llvm::MD5, llvm::support::endianness::native> HBuilder;
4508
4509 // Note: For QoI reasons, the things we use as a hash here should all be
4510 // dumped via the -module-info flag.
4511
4512 // Start the signature with the compiler version.
4513 HBuilder.add(getClangFullRepositoryVersion());
4514
4515 // Also include the serialization version, in case LLVM_APPEND_VC_REV is off
4516 // and getClangFullRepositoryVersion() doesn't include git revision.
4518
4519 // Extend the signature with the language options
4520#define LANGOPT(Name, Bits, Default, Description) HBuilder.add(LangOpts->Name);
4521#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
4522 HBuilder.add(static_cast<unsigned>(LangOpts->get##Name()));
4523#define BENIGN_LANGOPT(Name, Bits, Default, Description)
4524#define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description)
4525#include "clang/Basic/LangOptions.def"
4526
4527 HBuilder.addRange(LangOpts->ModuleFeatures);
4528
4529 HBuilder.add(LangOpts->ObjCRuntime);
4530 HBuilder.addRange(LangOpts->CommentOpts.BlockCommandNames);
4531
4532 // Extend the signature with the target options.
4533 HBuilder.add(TargetOpts->Triple, TargetOpts->CPU, TargetOpts->TuneCPU,
4534 TargetOpts->ABI);
4535 HBuilder.addRange(TargetOpts->FeaturesAsWritten);
4536
4537 // Extend the signature with preprocessor options.
4538 const PreprocessorOptions &ppOpts = getPreprocessorOpts();
4539 HBuilder.add(ppOpts.UsePredefines, ppOpts.DetailedRecord);
4540
4541 const HeaderSearchOptions &hsOpts = getHeaderSearchOpts();
4542 for (const auto &Macro : getPreprocessorOpts().Macros) {
4543 // If we're supposed to ignore this macro for the purposes of modules,
4544 // don't put it into the hash.
4545 if (!hsOpts.ModulesIgnoreMacros.empty()) {
4546 // Check whether we're ignoring this macro.
4547 StringRef MacroDef = Macro.first;
4548 if (hsOpts.ModulesIgnoreMacros.count(
4549 llvm::CachedHashString(MacroDef.split('=').first)))
4550 continue;
4551 }
4552
4553 HBuilder.add(Macro);
4554 }
4555
4556 // Extend the signature with the sysroot and other header search options.
4557 HBuilder.add(hsOpts.Sysroot, hsOpts.ModuleFormat, hsOpts.UseDebugInfo,
4559 hsOpts.UseStandardCXXIncludes, hsOpts.UseLibcxx,
4561 HBuilder.add(hsOpts.ResourceDir);
4562
4563 if (hsOpts.ModulesStrictContextHash) {
4564 HBuilder.addRange(hsOpts.SystemHeaderPrefixes);
4565 HBuilder.addRange(hsOpts.UserEntries);
4566
4567 const DiagnosticOptions &diagOpts = getDiagnosticOpts();
4568#define DIAGOPT(Name, Bits, Default) HBuilder.add(diagOpts.Name);
4569#define ENUM_DIAGOPT(Name, Type, Bits, Default) \
4570 HBuilder.add(diagOpts.get##Name());
4571#include "clang/Basic/DiagnosticOptions.def"
4572#undef DIAGOPT
4573#undef ENUM_DIAGOPT
4574 }
4575
4576 // Extend the signature with the user build path.
4577 HBuilder.add(hsOpts.ModuleUserBuildPath);
4578
4579 // Extend the signature with the module file extensions.
4580 for (const auto &ext : getFrontendOpts().ModuleFileExtensions)
4581 ext->hashExtension(HBuilder);
4582
4583 // When compiling with -gmodules, also hash -fdebug-prefix-map as it
4584 // affects the debug info in the PCM.
4585 if (getCodeGenOpts().DebugTypeExtRefs)
4586 HBuilder.addRange(getCodeGenOpts().DebugPrefixMap);
4587
4588 // Extend the signature with the enabled sanitizers, if at least one is
4589 // enabled. Sanitizers which cannot affect AST generation aren't hashed.
4590 SanitizerSet SanHash = LangOpts->Sanitize;
4592 if (!SanHash.empty())
4593 HBuilder.add(SanHash.Mask);
4594
4595 llvm::MD5::MD5Result Result;
4596 HBuilder.getHasher().final(Result);
4597 uint64_t Hash = Result.high() ^ Result.low();
4598 return toString(llvm::APInt(64, Hash), 36, /*Signed=*/false);
4599}
4600
4603 llvm::Triple T(TargetOpts->Triple);
4604
4608 GenerateDiagnosticArgs(*DiagnosticOpts, Args, SA, false);
4609 GenerateFrontendArgs(FrontendOpts, Args, SA, LangOpts->IsHeaderFile);
4610 GenerateTargetArgs(*TargetOpts, Args, SA);
4612 GenerateLangArgs(*LangOpts, Args, SA, T, FrontendOpts.DashX);
4613 GenerateCodeGenArgs(CodeGenOpts, Args, SA, T, FrontendOpts.OutputFile,
4614 &*LangOpts);
4616 CodeGenOpts);
4620}
4621
4622std::vector<std::string> CompilerInvocation::getCC1CommandLine() const {
4623 // Set up string allocator.
4624 llvm::BumpPtrAllocator Alloc;
4625 llvm::StringSaver Strings(Alloc);
4626 auto SA = [&Strings](const Twine &Arg) { return Strings.save(Arg).data(); };
4627
4628 // Synthesize full command line from the CompilerInvocation, including "-cc1".
4629 SmallVector<const char *, 32> Args{"-cc1"};
4630 generateCC1CommandLine(Args, SA);
4631
4632 // Convert arguments to the return type.
4633 return std::vector<std::string>{Args.begin(), Args.end()};
4634}
4635
4639}
4640
4642 getLangOpts()->ImplicitModules = false;
4647 // The specific values we canonicalize to for pruning don't affect behaviour,
4648 /// so use the default values so they may be dropped from the command-line.
4649 getHeaderSearchOpts().ModuleCachePruneInterval = 7 * 24 * 60 * 60;
4650 getHeaderSearchOpts().ModuleCachePruneAfter = 31 * 24 * 60 * 60;
4651}
4652
4655 DiagnosticsEngine &Diags) {
4656 return createVFSFromCompilerInvocation(CI, Diags,
4657 llvm::vfs::getRealFileSystem());
4658}
4659
4662 const CompilerInvocation &CI, DiagnosticsEngine &Diags,
4665 Diags, std::move(BaseFS));
4666}
4667
4669 ArrayRef<std::string> VFSOverlayFiles, DiagnosticsEngine &Diags,
4671 if (VFSOverlayFiles.empty())
4672 return BaseFS;
4673
4675 // earlier vfs files are on the bottom
4676 for (const auto &File : VFSOverlayFiles) {
4677 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buffer =
4678 Result->getBufferForFile(File);
4679 if (!Buffer) {
4680 Diags.Report(diag::err_missing_vfs_overlay_file) << File;
4681 continue;
4682 }
4683
4684 IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS = llvm::vfs::getVFSFromYAML(
4685 std::move(Buffer.get()), /*DiagHandler*/ nullptr, File,
4686 /*DiagContext*/ nullptr, Result);
4687 if (!FS) {
4688 Diags.Report(diag::err_invalid_vfs_overlay) << File;
4689 continue;
4690 }
4691
4692 Result = FS;
4693 }
4694 return Result;
4695}
#define V(N, I)
Definition: ASTContext.h:3217
StringRef P
Defines the Diagnostic-related interfaces.
Defines enum values for all the target-independent builtin functions.
Defines the clang::CommentOptions interface.
static CompilationDatabasePluginRegistry::Add< FixedCompilationDatabasePlugin > X("fixed-compilation-database", "Reads plain-text flags file")
static void getAllNoBuiltinFuncValues(ArgList &Args, std::vector< std::string > &Funcs)
static T extractMaskValue(T KeyPath)
static void GenerateFileSystemArgs(const FileSystemOptions &Opts, SmallVectorImpl< const char * > &Args, CompilerInvocation::StringAllocator SA)
static std::optional< IntTy > normalizeStringIntegral(OptSpecifier Opt, int, const ArgList &Args, DiagnosticsEngine &Diags)
static T mergeMaskValue(T KeyPath, U Value)
static std::optional< std::string > normalizeString(OptSpecifier Opt, int TableIndex, const ArgList &Args, DiagnosticsEngine &Diags)
static auto makeBooleanOptionNormalizer(bool Value, bool OtherValue, OptSpecifier OtherOpt)
static SmallVector< StringRef, 4 > serializeSanitizerKinds(SanitizerSet S)
static void parseXRayInstrumentationBundle(StringRef FlagName, StringRef Bundle, ArgList &Args, DiagnosticsEngine &D, XRayInstrSet &S)
static unsigned getOptimizationLevelSize(ArgList &Args)
static std::optional< SimpleEnumValue > findValueTableByValue(const SimpleEnumValueTable &Table, unsigned Value)
static void GenerateFrontendArgs(const FrontendOptions &Opts, SmallVectorImpl< const char * > &Args, CompilerInvocation::StringAllocator SA, bool IsHeader)
static void GeneratePreprocessorArgs(PreprocessorOptions &Opts, SmallVectorImpl< const char * > &Args, CompilerInvocation::StringAllocator SA, const LangOptions &LangOpts, const FrontendOptions &FrontendOpts, const CodeGenOptions &CodeGenOpts)
static bool ParseTargetArgs(TargetOptions &Opts, ArgList &Args, DiagnosticsEngine &Diags)
static auto makeFlagToValueNormalizer(T Value)
static CodeGenOptions::OptRemark ParseOptimizationRemark(DiagnosticsEngine &Diags, ArgList &Args, OptSpecifier OptEQ, StringRef Name)
Parse a remark command line argument.
static bool ParseFileSystemArgs(FileSystemOptions &Opts, const ArgList &Args, DiagnosticsEngine &Diags)
static constexpr bool is_uint64_t_convertible()
static std::optional< SimpleEnumValue > findValueTableByName(const SimpleEnumValueTable &Table, StringRef Name)
static std::optional< OptSpecifier > getProgramActionOpt(frontend::ActionKind ProgramAction)
Maps frontend action to command line option.
static bool parseDiagnosticLevelMask(StringRef FlagName, const std::vector< std::string > &Levels, DiagnosticsEngine &Diags, DiagnosticLevelMask &M)
static std::optional< bool > normalizeSimpleFlag(OptSpecifier Opt, unsigned TableIndex, const ArgList &Args, DiagnosticsEngine &Diags)
static void addDiagnosticArgs(ArgList &Args, OptSpecifier Group, OptSpecifier GroupWithValue, std::vector< std::string > &Diagnostics)
static void GenerateOptimizationRemark(SmallVectorImpl< const char * > &Args, CompilerInvocation::StringAllocator SA, OptSpecifier OptEQ, StringRef Name, const CodeGenOptions::OptRemark &Remark)
Generate a remark argument. This is an inverse of ParseOptimizationRemark.
static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, DiagnosticsEngine &Diags)
static void parseAnalyzerConfigs(AnalyzerOptions &AnOpts, DiagnosticsEngine *Diags)
static bool ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args, DiagnosticsEngine &Diags, frontend::ActionKind Action, const FrontendOptions &FrontendOpts)
static std::optional< unsigned > normalizeSimpleEnum(OptSpecifier Opt, unsigned TableIndex, const ArgList &Args, DiagnosticsEngine &Diags)
static StringRef GetInputKindName(InputKind IK)
Get language name for given input kind.
static void denormalizeSimpleEnumImpl(SmallVectorImpl< const char * > &Args, const char *Spelling, CompilerInvocation::StringAllocator SA, Option::OptionClass OptClass, unsigned TableIndex, unsigned Value)
static void initOption(AnalyzerOptions::ConfigTable &Config, DiagnosticsEngine *Diags, StringRef &OptionField, StringRef Name, StringRef DefaultVal)
static void denormalizeString(SmallVectorImpl< const char * > &Args, const char *Spelling, CompilerInvocation::StringAllocator SA, Option::OptionClass OptClass, unsigned TableIndex, T Value)
static std::optional< std::string > normalizeTriple(OptSpecifier Opt, int TableIndex, const ArgList &Args, DiagnosticsEngine &Diags)
llvm::function_ref< bool(CompilerInvocation &, ArrayRef< const char * >, DiagnosticsEngine &, const char *)> ParseFn
llvm::function_ref< void(CompilerInvocation &, SmallVectorImpl< const char * > &, CompilerInvocation::StringAllocator)> GenerateFn
static void GeneratePreprocessorOutputArgs(const PreprocessorOutputOptions &Opts, SmallVectorImpl< const char * > &Args, CompilerInvocation::StringAllocator SA, frontend::ActionKind Action)
static const auto & getFrontendActionTable()
Return a table that associates command line option specifiers with the frontend action.
static std::optional< frontend::ActionKind > getFrontendAction(OptSpecifier &Opt)
Maps command line option to frontend action.
static bool checkVerifyPrefixes(const std::vector< std::string > &VerifyPrefixes, DiagnosticsEngine &Diags)
static std::optional< bool > normalizeSimpleNegativeFlag(OptSpecifier Opt, unsigned, const ArgList &Args, DiagnosticsEngine &)
static bool IsInputCompatibleWithStandard(InputKind IK, const LangStandard &S)
Check if input file kind and language standard are compatible.
static void setPGOUseInstrumentor(CodeGenOptions &Opts, const Twine &ProfileName, llvm::vfs::FileSystem &FS, DiagnosticsEngine &Diags)
static void denormalizeSimpleFlag(SmallVectorImpl< const char * > &Args, const char *Spelling, CompilerInvocation::StringAllocator, Option::OptionClass, unsigned,...)
The tblgen-erated code passes in a fifth parameter of an arbitrary type, but denormalizeSimpleFlags n...
static bool ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args, DiagnosticsEngine &Diags, const std::string &WorkingDir)
static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, DiagnosticsEngine &Diags, bool &IsHeaderFile)
static auto makeBooleanOptionDenormalizer(bool Value)
static bool isStrictlyPreprocessorAction(frontend::ActionKind Action)
static std::string serializeXRayInstrumentationBundle(const XRayInstrSet &S)
static bool ParseMigratorArgs(MigratorOptions &Opts, const ArgList &Args, DiagnosticsEngine &Diags)
static bool parseShowColorsArgs(const ArgList &Args, bool DefaultColor)
static T mergeForwardValue(T KeyPath, U Value)
static void GenerateHeaderSearchArgs(HeaderSearchOptions &Opts, SmallVectorImpl< const char * > &Args, CompilerInvocation::StringAllocator SA)
static void GenerateArg(SmallVectorImpl< const char * > &Args, llvm::opt::OptSpecifier OptSpecifier, CompilerInvocation::StringAllocator SA)
static bool ParseDependencyOutputArgs(DependencyOutputOptions &Opts, ArgList &Args, DiagnosticsEngine &Diags, frontend::ActionKind Action, bool ShowLineMarkers)
static Expected< std::optional< uint32_t > > parseToleranceOption(StringRef Arg)
static std::optional< std::vector< std::string > > normalizeStringVector(OptSpecifier Opt, int, const ArgList &Args, DiagnosticsEngine &)
static bool ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts, ArgList &Args, DiagnosticsEngine &Diags, frontend::ActionKind Action)
static void GenerateMigratorArgs(const MigratorOptions &Opts, SmallVectorImpl< const char * > &Args, CompilerInvocation::StringAllocator SA)
static bool RoundTrip(ParseFn Parse, GenerateFn Generate, CompilerInvocation &RealInvocation, CompilerInvocation &DummyInvocation, ArrayRef< const char * > CommandLineArgs, DiagnosticsEngine &Diags, const char *Argv0, bool CheckAgainstOriginalInvocation=false, bool ForceRoundTrip=false)
May perform round-trip of command line arguments.
static T extractForwardValue(T KeyPath)
static void GenerateDependencyOutputArgs(const DependencyOutputOptions &Opts, SmallVectorImpl< const char * > &Args, CompilerInvocation::StringAllocator SA)
static void denormalizeStringImpl(SmallVectorImpl< const char * > &Args, const char *Spelling, CompilerInvocation::StringAllocator SA, Option::OptionClass OptClass, unsigned, const Twine &Value)
static unsigned getOptimizationLevel(ArgList &Args, InputKind IK, DiagnosticsEngine &Diags)
static void GenerateAnalyzerArgs(AnalyzerOptions &Opts, SmallVectorImpl< const char * > &Args, CompilerInvocation::StringAllocator SA)
static void GenerateTargetArgs(const TargetOptions &Opts, SmallVectorImpl< const char * > &Args, CompilerInvocation::StringAllocator SA)
static void denormalizeSimpleEnum(SmallVectorImpl< const char * > &Args, const char *Spelling, CompilerInvocation::StringAllocator SA, Option::OptionClass OptClass, unsigned TableIndex, T Value)
static bool parseTestModuleFileExtensionArg(StringRef Arg, std::string &BlockName, unsigned &MajorVersion, unsigned &MinorVersion, bool &Hashed, std::string &UserInfo)
Parse the argument to the -ftest-module-file-extension command-line argument.
static StringRef getStringOption(AnalyzerOptions::ConfigTable &Config, StringRef OptionName, StringRef DefaultVal)
static bool FixupInvocation(CompilerInvocation &Invocation, DiagnosticsEngine &Diags, const ArgList &Args, InputKind IK)
static void parseSanitizerKinds(StringRef FlagName, const std::vector< std::string > &Sanitizers, DiagnosticsEngine &Diags, SanitizerSet &S)
static void denormalizeStringVector(SmallVectorImpl< const char * > &Args, const char *Spelling, CompilerInvocation::StringAllocator SA, Option::OptionClass OptClass, unsigned TableIndex, const std::vector< std::string > &Values)
Defines the clang::FileSystemOptions interface.
StringRef Filename
Definition: Format.cpp:2776
LangStandard::Kind Std
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
Defines the clang::LangOptions interface.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
bool ShowColors
Definition: Logger.cpp:29
llvm::raw_ostream & OS
Definition: Logger.cpp:24
Defines types useful for describing an Objective-C runtime.
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
Defines the clang::SanitizerKind enum.
Defines the clang::SourceLocation class and associated facilities.
Defines the clang::TargetOptions class.
Defines version macros and version-related utility functions for Clang.
Defines the clang::Visibility enumeration and various utility functions.
Defines the clang::XRayInstrKind enum.
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
Stores options for the analyzer from the command line.
static std::vector< StringRef > getRegisteredPackages(bool IncludeExperimental=false)
Retrieves the list of packages generated from Checkers.td.
std::vector< std::pair< std::string, bool > > CheckersAndPackages
Pairs of checker/package name and enable/disable.
std::vector< std::string > SilencedCheckersAndPackages
Vector of checker/package names which will not emit warnings.
AnalysisDiagClients AnalysisDiagOpt
AnalysisConstraints AnalysisConstraintsOpt
ConfigTable Config
A key-value table of use-specified configuration values.
bool isUnknownAnalyzerConfig(StringRef Name) const
unsigned ShouldEmitErrorsOnInvalidConfigValue
AnalysisPurgeMode AnalysisPurgeOpt
static std::vector< StringRef > getRegisteredCheckers(bool IncludeExperimental=false)
Retrieves the list of checkers generated from Checkers.td.
llvm::StringMap< std::string > ConfigTable
std::string FullCompilerInvocation
Store full compiler invocation for reproducible instructions in the generated report.
AnalysisInliningMode InliningMode
The mode of function selection used during inlining.
static bool isBuiltinFunc(llvm::StringRef Name)
Returns true if this is a libc/libm function without the '__builtin_' prefix.
Definition: Builtins.cpp:63
Implements C++ ABI-specific semantic analysis functions.
Definition: CXXABI.h:29
CodeGenOptions - Track various options which control how the code is optimized and passed to the back...
std::string OptRecordFile
The name of the file to which the backend should save YAML optimization records.
std::string BinutilsVersion
std::vector< BitcodeFileToLink > LinkBitcodeFiles
The files specified here are linked in to the module before optimizations.
std::optional< uint64_t > DiagnosticsHotnessThreshold
The minimum hotness value a diagnostic needs in order to be included in optimization diagnostics.
char CoverageVersion[4]
The version string to put into coverage files.
llvm::DenormalMode FPDenormalMode
The floating-point denormal mode to use.
std::string ProfileInstrumentUsePath
Name of the profile file to use as input for -fprofile-instr-use.
std::string SampleProfileFile
Name of the profile file to use with -fprofile-sample-use.
std::string MemoryProfileOutput
Name of the profile file to use as output for with -fmemory-profile.
std::string CodeModel
The code model to use (-mcmodel).
std::map< std::string, std::string > DebugPrefixMap
std::optional< uint32_t > DiagnosticsMisExpectTolerance
The maximum percentage profiling weights can deviate from the expected values in order to be included...
std::string StackUsageOutput
Name of the stack usage file (i.e., .su file) if user passes -fstack-usage.
std::string OptRecordPasses
The regex that filters the passes that should be saved to the optimization records.
std::string SaveTempsFilePrefix
Prefix to use for -save-temps output.
XRayInstrSet XRayInstrumentationBundle
Set of XRay instrumentation kinds to emit.
bool hasSanitizeCoverage() const
llvm::DenormalMode FP32DenormalMode
The floating-point denormal mode to use, for float.
SanitizerSet SanitizeTrap
Set of sanitizer checks that trap rather than diagnose.
SanitizerSet SanitizeRecover
Set of sanitizer checks that are non-fatal (i.e.
bool hasReducedDebugInfo() const
Check if type and variable info should be emitted.
OptRemark OptimizationRemark
Selected optimizations for which we should enable optimization remarks.
std::string ThinLTOIndexFile
Name of the function summary index file to use for ThinLTO function importing.
const char * Argv0
Executable and command-line used to create a given CompilerInvocation.
std::vector< std::string > NoBuiltinFuncs
A list of all -fno-builtin-* function names (e.g., memset).
std::vector< uint8_t > CmdArgs
List of backend command-line options for -fembed-bitcode.
OptRemark OptimizationRemarkAnalysis
Selected optimizations for which we should enable optimization analyses.
std::vector< std::string > CommandLineArgs
std::string OptRecordFormat
The format used for serializing remarks (default: YAML)
std::map< std::string, std::string > CoveragePrefixMap
std::string DIBugsReportFilePath
The file to use for dumping bug report by Debugify for original debug info.
OptRemark OptimizationRemarkMissed
Selected optimizations for which we should enable missed optimization remarks.
The base class of CompilerInvocation with reference semantics.
PreprocessorOptions & getPreprocessorOpts()
AnalyzerOptionsRef AnalyzerOpts
Options controlling the static analyzer.
CompilerInvocationRefBase & operator=(CompilerInvocationRefBase X)
DiagnosticOptions & getDiagnosticOpts() const
IntrusiveRefCntPtr< DiagnosticOptions > DiagnosticOpts
Options controlling the diagnostic engine.
AnalyzerOptionsRef getAnalyzerOpts() const
std::shared_ptr< PreprocessorOptions > PreprocessorOpts
Options controlling the preprocessor (aside from #include handling).
std::shared_ptr< LangOptions > LangOpts
Options controlling the language variant.
HeaderSearchOptions & getHeaderSearchOpts()
std::shared_ptr< TargetOptions > TargetOpts
Options controlling the target.
std::shared_ptr< HeaderSearchOptions > HeaderSearchOpts
Options controlling the #include directive.
FileSystemOptions FileSystemOpts
Options controlling file system operations.
DependencyOutputOptions & getDependencyOutputOpts()
CodeGenOptions CodeGenOpts
Options controlling IRgen and the backend.
PreprocessorOutputOptions PreprocessorOutputOpts
Options controlling preprocessed output.
PreprocessorOutputOptions & getPreprocessorOutputOpts()
FrontendOptions FrontendOpts
Options controlling the frontend itself.
DependencyOutputOptions DependencyOutputOpts
Options controlling dependency output.
Helper class for holding the data necessary to invoke the compiler.
void clearImplicitModuleBuildOptions()
Disable implicit modules and canonicalize options that are only used by implicit modules.
static std::string GetResourcesPath(const char *Argv0, void *MainAddr)
Get the directory where the compiler headers reside, relative to the compiler binary (found by the pa...
static bool CreateFromArgs(CompilerInvocation &Res, ArrayRef< const char * > CommandLineArgs, DiagnosticsEngine &Diags, const char *Argv0=nullptr)
Create a compiler invocation from a list of input options.
static bool checkCC1RoundTrip(ArrayRef< const char * > Args, DiagnosticsEngine &Diags, const char *Argv0=nullptr)
Check that Args can be parsed and re-serialized without change, emiting diagnostics for any differenc...
void resetNonModularOptions()
Reset all of the options that are not considered when building a module.
void generateCC1CommandLine(llvm::SmallVectorImpl< const char * > &Args, StringAllocator SA) const
Generate cc1-compatible command line arguments from this instance.
std::string getModuleHash() const
Retrieve a module hash string that is suitable for uniquely identifying the conditions under which th...
std::vector< std::string > getCC1CommandLine() const
Generate cc1-compatible command line arguments from this instance, wrapping the result as a std::vect...
llvm::function_ref< const char *(const llvm::Twine &)> StringAllocator
DependencyOutputOptions - Options for controlling the compiler dependency file generation.
ShowIncludesDestination ShowIncludesDest
Destination of cl.exe style /showIncludes info.
HeaderIncludeFormatKind HeaderIncludeFormat
The format of header information.
std::string OutputFile
The file to write dependency output to.
HeaderIncludeFilteringKind HeaderIncludeFiltering
Determine whether header information should be filtered.
std::vector< std::string > Targets
A list of names to use as the targets in the dependency file; this list must contain at least one ent...
std::vector< std::pair< std::string, ExtraDepKind > > ExtraDeps
A list of extra dependencies (filename and kind) to be used for every target.
unsigned IncludeSystemHeaders
Include system header dependencies.
Used for handling and querying diagnostic IDs.
Options for controlling the compiler diagnostics engine.