clang 23.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
20#include "clang/Basic/LLVM.h"
27#include "clang/Basic/Version.h"
29#include "clang/Config/config.h"
43#include "llvm/ADT/APInt.h"
44#include "llvm/ADT/ArrayRef.h"
45#include "llvm/ADT/CachedHashString.h"
46#include "llvm/ADT/FloatingPointMode.h"
47#include "llvm/ADT/STLExtras.h"
48#include "llvm/ADT/SmallVector.h"
49#include "llvm/ADT/StringRef.h"
50#include "llvm/ADT/StringSwitch.h"
51#include "llvm/ADT/Twine.h"
52#include "llvm/Config/llvm-config.h"
53#include "llvm/Frontend/Debug/Options.h"
54#include "llvm/IR/DebugInfoMetadata.h"
55#include "llvm/Linker/Linker.h"
56#include "llvm/MC/MCTargetOptions.h"
57#include "llvm/Option/Arg.h"
58#include "llvm/Option/ArgList.h"
59#include "llvm/Option/OptSpecifier.h"
60#include "llvm/Option/OptTable.h"
61#include "llvm/Option/Option.h"
62#include "llvm/ProfileData/InstrProfReader.h"
63#include "llvm/Remarks/HotnessThresholdParser.h"
64#include "llvm/Support/CodeGen.h"
65#include "llvm/Support/Compiler.h"
66#include "llvm/Support/Error.h"
67#include "llvm/Support/ErrorHandling.h"
68#include "llvm/Support/ErrorOr.h"
69#include "llvm/Support/FileSystem.h"
70#include "llvm/Support/HashBuilder.h"
71#include "llvm/Support/MathExtras.h"
72#include "llvm/Support/MemoryBuffer.h"
73#include "llvm/Support/Path.h"
74#include "llvm/Support/Process.h"
75#include "llvm/Support/Regex.h"
76#include "llvm/Support/VersionTuple.h"
77#include "llvm/Support/VirtualFileSystem.h"
78#include "llvm/Support/raw_ostream.h"
79#include "llvm/Target/TargetOptions.h"
80#include "llvm/TargetParser/Host.h"
81#include "llvm/TargetParser/Triple.h"
82#include <algorithm>
83#include <cassert>
84#include <cstddef>
85#include <cstring>
86#include <ctime>
87#include <fstream>
88#include <limits>
89#include <memory>
90#include <optional>
91#include <string>
92#include <tuple>
93#include <type_traits>
94#include <utility>
95#include <vector>
96
97using namespace clang;
98using namespace options;
99using namespace llvm::opt;
100
101//===----------------------------------------------------------------------===//
102// Helpers.
103//===----------------------------------------------------------------------===//
104
105// Parse misexpect tolerance argument value.
106// Valid option values are integers in the range [0, 100)
108 uint32_t Val;
109 if (Arg.getAsInteger(10, Val))
110 return llvm::createStringError(llvm::inconvertibleErrorCode(),
111 "Not an integer: %s", Arg.data());
112 return Val;
113}
114
115//===----------------------------------------------------------------------===//
116// Initialization.
117//===----------------------------------------------------------------------===//
118
119template <class T> std::shared_ptr<T> make_shared_copy(const T &X) {
120 return std::make_shared<T>(X);
121}
122
124 : LangOpts(std::make_shared<LangOptions>()),
125 TargetOpts(std::make_shared<TargetOptions>()),
126 DiagnosticOpts(std::make_shared<DiagnosticOptions>()),
127 HSOpts(std::make_shared<HeaderSearchOptions>()),
128 PPOpts(std::make_shared<PreprocessorOptions>()),
129 AnalyzerOpts(std::make_shared<AnalyzerOptions>()),
130 MigratorOpts(std::make_shared<MigratorOptions>()),
131 APINotesOpts(std::make_shared<APINotesOptions>()),
132 CodeGenOpts(std::make_shared<CodeGenOptions>()),
133 FSOpts(std::make_shared<FileSystemOptions>()),
134 FrontendOpts(std::make_shared<FrontendOptions>()),
137
140 if (this != &X) {
141 LangOpts = make_shared_copy(X.getLangOpts());
142 TargetOpts = make_shared_copy(X.getTargetOpts());
143 DiagnosticOpts = make_shared_copy(X.getDiagnosticOpts());
144 HSOpts = make_shared_copy(X.getHeaderSearchOpts());
145 PPOpts = make_shared_copy(X.getPreprocessorOpts());
146 AnalyzerOpts = make_shared_copy(X.getAnalyzerOpts());
147 MigratorOpts = make_shared_copy(X.getMigratorOpts());
148 APINotesOpts = make_shared_copy(X.getAPINotesOpts());
149 CodeGenOpts = make_shared_copy(X.getCodeGenOpts());
150 FSOpts = make_shared_copy(X.getFileSystemOpts());
151 FrontendOpts = make_shared_copy(X.getFrontendOpts());
152 DependencyOutputOpts = make_shared_copy(X.getDependencyOutputOpts());
153 PreprocessorOutputOpts = make_shared_copy(X.getPreprocessorOutputOpts());
154 }
155 return *this;
156}
157
160 if (this != &X) {
161 LangOpts = X.LangOpts;
162 TargetOpts = X.TargetOpts;
163 DiagnosticOpts = X.DiagnosticOpts;
164 HSOpts = X.HSOpts;
165 PPOpts = X.PPOpts;
166 AnalyzerOpts = X.AnalyzerOpts;
167 MigratorOpts = X.MigratorOpts;
168 APINotesOpts = X.APINotesOpts;
169 CodeGenOpts = X.CodeGenOpts;
170 FSOpts = X.FSOpts;
171 FrontendOpts = X.FrontendOpts;
172 DependencyOutputOpts = X.DependencyOutputOpts;
173 PreprocessorOutputOpts = X.PreprocessorOutputOpts;
174 }
175 return *this;
176}
177
182
188
189template <typename T>
190T &ensureOwned(std::shared_ptr<T> &Storage) {
191 if (Storage.use_count() > 1)
192 Storage = std::make_shared<T>(*Storage);
193 return *Storage;
194}
195
199
203
207
211
215
219
223
227
231
235
239
243
248
249//===----------------------------------------------------------------------===//
250// Normalizers
251//===----------------------------------------------------------------------===//
252
254
255#define OPTTABLE_STR_TABLE_CODE
256#include "clang/Options/Options.inc"
257#undef OPTTABLE_STR_TABLE_CODE
258
259static llvm::StringRef lookupStrInTable(unsigned Offset) {
260 return OptionStrTable[Offset];
261}
262
263#define SIMPLE_ENUM_VALUE_TABLE
264#include "clang/Options/Options.inc"
265#undef SIMPLE_ENUM_VALUE_TABLE
266
267static std::optional<bool> normalizeSimpleFlag(OptSpecifier Opt,
268 unsigned TableIndex,
269 const ArgList &Args,
270 DiagnosticsEngine &Diags) {
271 if (Args.hasArg(Opt))
272 return true;
273 return std::nullopt;
274}
275
276static std::optional<bool> normalizeSimpleNegativeFlag(OptSpecifier Opt,
277 unsigned,
278 const ArgList &Args,
280 if (Args.hasArg(Opt))
281 return false;
282 return std::nullopt;
283}
284
285/// The tblgen-erated code passes in a fifth parameter of an arbitrary type, but
286/// denormalizeSimpleFlags never looks at it. Avoid bloating compile-time with
287/// unnecessary template instantiations and just ignore it with a variadic
288/// argument.
290 unsigned SpellingOffset, Option::OptionClass,
291 unsigned, /*T*/...) {
292 Consumer(lookupStrInTable(SpellingOffset));
293}
295 const Twine &Spelling, Option::OptionClass,
296 unsigned, /*T*/...) {
297 Consumer(Spelling);
298}
299
300template <typename T> static constexpr bool is_uint64_t_convertible() {
301 return !std::is_same_v<T, uint64_t> && llvm::is_integral_or_enum<T>::value;
302}
303
304template <typename T,
305 std::enable_if_t<!is_uint64_t_convertible<T>(), bool> = false>
307 return [Value](OptSpecifier Opt, unsigned, const ArgList &Args,
308 DiagnosticsEngine &) -> std::optional<T> {
309 if (Args.hasArg(Opt))
310 return Value;
311 return std::nullopt;
312 };
313}
314
315template <typename T,
316 std::enable_if_t<is_uint64_t_convertible<T>(), bool> = false>
318 return makeFlagToValueNormalizer(uint64_t(Value));
319}
320
321static auto makeBooleanOptionNormalizer(bool Value, bool OtherValue,
322 OptSpecifier OtherOpt) {
323 return [Value, OtherValue,
324 OtherOpt](OptSpecifier Opt, unsigned, const ArgList &Args,
325 DiagnosticsEngine &) -> std::optional<bool> {
326 if (const Arg *A = Args.getLastArg(Opt, OtherOpt)) {
327 return A->getOption().matches(Opt) ? Value : OtherValue;
328 }
329 return std::nullopt;
330 };
331}
332
334 return [Value](ArgumentConsumer Consumer, unsigned SpellingOffset,
335 Option::OptionClass, unsigned, bool KeyPath) {
336 if (KeyPath == Value)
337 Consumer(lookupStrInTable(SpellingOffset));
338 };
339}
340
342 const Twine &Spelling,
343 Option::OptionClass OptClass, unsigned,
344 const Twine &Value) {
345 switch (OptClass) {
346 case Option::SeparateClass:
347 case Option::JoinedOrSeparateClass:
348 case Option::JoinedAndSeparateClass:
349 Consumer(Spelling);
350 Consumer(Value);
351 break;
352 case Option::JoinedClass:
353 case Option::CommaJoinedClass:
354 Consumer(Spelling + Value);
355 break;
356 default:
357 llvm_unreachable("Cannot denormalize an option with option class "
358 "incompatible with string denormalization.");
359 }
360}
361
362template <typename T>
363static void
364denormalizeString(ArgumentConsumer Consumer, unsigned SpellingOffset,
365 Option::OptionClass OptClass, unsigned TableIndex, T Value) {
366 denormalizeStringImpl(Consumer, lookupStrInTable(SpellingOffset), OptClass,
367 TableIndex, Twine(Value));
368}
369
370template <typename T>
371static void denormalizeString(ArgumentConsumer Consumer, const Twine &Spelling,
372 Option::OptionClass OptClass, unsigned TableIndex,
373 T Value) {
374 denormalizeStringImpl(Consumer, Spelling, OptClass, TableIndex, Twine(Value));
375}
376
377static std::optional<SimpleEnumValue>
378findValueTableByName(const SimpleEnumValueTable &Table, StringRef Name) {
379 for (int I = 0, E = Table.Size; I != E; ++I)
380 if (Name == Table.Table[I].Name)
381 return Table.Table[I];
382
383 return std::nullopt;
384}
385
386static std::optional<SimpleEnumValue>
387findValueTableByValue(const SimpleEnumValueTable &Table, unsigned Value) {
388 for (int I = 0, E = Table.Size; I != E; ++I)
389 if (Value == Table.Table[I].Value)
390 return Table.Table[I];
391
392 return std::nullopt;
393}
394
395static std::optional<unsigned> normalizeSimpleEnum(OptSpecifier Opt,
396 unsigned TableIndex,
397 const ArgList &Args,
398 DiagnosticsEngine &Diags) {
399 assert(TableIndex < SimpleEnumValueTablesSize);
400 const SimpleEnumValueTable &Table = SimpleEnumValueTables[TableIndex];
401
402 auto *Arg = Args.getLastArg(Opt);
403 if (!Arg)
404 return std::nullopt;
405
406 StringRef ArgValue = Arg->getValue();
407 if (auto MaybeEnumVal = findValueTableByName(Table, ArgValue))
408 return MaybeEnumVal->Value;
409
410 Diags.Report(diag::err_drv_invalid_value)
411 << Arg->getAsString(Args) << ArgValue;
412 return std::nullopt;
413}
414
416 unsigned SpellingOffset,
417 Option::OptionClass OptClass,
418 unsigned TableIndex, unsigned Value) {
419 assert(TableIndex < SimpleEnumValueTablesSize);
420 const SimpleEnumValueTable &Table = SimpleEnumValueTables[TableIndex];
421 if (auto MaybeEnumVal = findValueTableByValue(Table, Value)) {
422 denormalizeString(Consumer, lookupStrInTable(SpellingOffset), OptClass,
423 TableIndex, MaybeEnumVal->Name);
424 } else {
425 llvm_unreachable("The simple enum value was not correctly defined in "
426 "the tablegen option description");
427 }
428}
429
430template <typename T>
432 unsigned SpellingOffset,
433 Option::OptionClass OptClass,
434 unsigned TableIndex, T Value) {
435 return denormalizeSimpleEnumImpl(Consumer, SpellingOffset, OptClass,
436 TableIndex, static_cast<unsigned>(Value));
437}
438
439static std::optional<std::string> normalizeString(OptSpecifier Opt,
440 int TableIndex,
441 const ArgList &Args,
442 DiagnosticsEngine &Diags) {
443 auto *Arg = Args.getLastArg(Opt);
444 if (!Arg)
445 return std::nullopt;
446 return std::string(Arg->getValue());
447}
448
449template <typename IntTy>
450static std::optional<IntTy> normalizeStringIntegral(OptSpecifier Opt, int,
451 const ArgList &Args,
452 DiagnosticsEngine &Diags) {
453 auto *Arg = Args.getLastArg(Opt);
454 if (!Arg)
455 return std::nullopt;
456 IntTy Res;
457 if (StringRef(Arg->getValue()).getAsInteger(0, Res)) {
458 Diags.Report(diag::err_drv_invalid_int_value)
459 << Arg->getAsString(Args) << Arg->getValue();
460 return std::nullopt;
461 }
462 return Res;
463}
464
465static std::optional<std::vector<std::string>>
466normalizeStringVector(OptSpecifier Opt, int, const ArgList &Args,
468 return Args.getAllArgValues(Opt);
469}
470
472 unsigned SpellingOffset,
473 Option::OptionClass OptClass,
474 unsigned TableIndex,
475 const std::vector<std::string> &Values) {
476 switch (OptClass) {
477 case Option::CommaJoinedClass: {
478 std::string CommaJoinedValue;
479 if (!Values.empty()) {
480 CommaJoinedValue.append(Values.front());
481 for (const std::string &Value : llvm::drop_begin(Values, 1)) {
482 CommaJoinedValue.append(",");
483 CommaJoinedValue.append(Value);
484 }
485 }
486 denormalizeString(Consumer, SpellingOffset,
487 Option::OptionClass::JoinedClass, TableIndex,
488 CommaJoinedValue);
489 break;
490 }
491 case Option::JoinedClass:
492 case Option::SeparateClass:
493 case Option::JoinedOrSeparateClass:
494 for (const std::string &Value : Values)
495 denormalizeString(Consumer, SpellingOffset, OptClass, TableIndex, Value);
496 break;
497 default:
498 llvm_unreachable("Cannot denormalize an option with option class "
499 "incompatible with string vector denormalization.");
500 }
501}
502
503static std::optional<std::string> normalizeTriple(OptSpecifier Opt,
504 int TableIndex,
505 const ArgList &Args,
506 DiagnosticsEngine &Diags) {
507 auto *Arg = Args.getLastArg(Opt);
508 if (!Arg)
509 return std::nullopt;
510 return llvm::Triple::normalize(Arg->getValue());
511}
512
513template <typename T, typename U>
514static T mergeForwardValue(T KeyPath, U Value) {
515 return static_cast<T>(Value);
516}
517
518template <typename T, typename U> static T mergeMaskValue(T KeyPath, U Value) {
519 return KeyPath | Value;
520}
521
522template <typename T> static T extractForwardValue(T KeyPath) {
523 return KeyPath;
524}
525
526template <typename T, typename U, U Value>
527static T extractMaskValue(T KeyPath) {
528 return ((KeyPath & Value) == Value) ? static_cast<T>(Value) : T();
529}
530
531#define PARSE_OPTION_WITH_MARSHALLING( \
532 ARGS, DIAGS, PREFIX_TYPE, SPELLING_OFFSET, ID, KIND, GROUP, ALIAS, \
533 ALIASARGS, FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, \
534 METAVAR, VALUES, SUBCOMMANDIDS_OFFSET, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, \
535 DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, \
536 MERGER, EXTRACTOR, TABLE_INDEX) \
537 if ((VISIBILITY) & options::CC1Option) { \
538 KEYPATH = MERGER(KEYPATH, DEFAULT_VALUE); \
539 if (IMPLIED_CHECK) \
540 KEYPATH = MERGER(KEYPATH, IMPLIED_VALUE); \
541 if (SHOULD_PARSE) \
542 if (auto MaybeValue = NORMALIZER(OPT_##ID, TABLE_INDEX, ARGS, DIAGS)) \
543 KEYPATH = \
544 MERGER(KEYPATH, static_cast<decltype(KEYPATH)>(*MaybeValue)); \
545 }
546
547// Capture the extracted value as a lambda argument to avoid potential issues
548// with lifetime extension of the reference.
549#define GENERATE_OPTION_WITH_MARSHALLING( \
550 CONSUMER, PREFIX_TYPE, SPELLING_OFFSET, ID, KIND, GROUP, ALIAS, ALIASARGS, \
551 FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, VALUES, \
552 SUBCOMMANDIDS_OFFSET, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, \
553 IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, \
554 TABLE_INDEX) \
555 if ((VISIBILITY) & options::CC1Option) { \
556 [&](const auto &Extracted) { \
557 if (ALWAYS_EMIT || \
558 (Extracted != \
559 static_cast<decltype(KEYPATH)>((IMPLIED_CHECK) ? (IMPLIED_VALUE) \
560 : (DEFAULT_VALUE)))) \
561 DENORMALIZER(CONSUMER, SPELLING_OFFSET, Option::KIND##Class, \
562 TABLE_INDEX, Extracted); \
563 }(EXTRACTOR(KEYPATH)); \
564 }
565
566static StringRef GetInputKindName(InputKind IK);
567
568static bool FixupInvocation(CompilerInvocation &Invocation,
569 DiagnosticsEngine &Diags, const ArgList &Args,
570 InputKind IK) {
571 unsigned NumErrorsBefore = Diags.getNumErrors();
572
573 LangOptions &LangOpts = Invocation.getLangOpts();
574 CodeGenOptions &CodeGenOpts = Invocation.getCodeGenOpts();
575 TargetOptions &TargetOpts = Invocation.getTargetOpts();
576 FrontendOptions &FrontendOpts = Invocation.getFrontendOpts();
577 CodeGenOpts.XRayInstrumentFunctions = LangOpts.XRayInstrument;
578 CodeGenOpts.XRayAlwaysEmitCustomEvents = LangOpts.XRayAlwaysEmitCustomEvents;
579 CodeGenOpts.XRayAlwaysEmitTypedEvents = LangOpts.XRayAlwaysEmitTypedEvents;
580 CodeGenOpts.DisableFree = FrontendOpts.DisableFree;
581 FrontendOpts.GenerateGlobalModuleIndex = FrontendOpts.UseGlobalModuleIndex;
582 if (FrontendOpts.ShowStats)
583 CodeGenOpts.ClearASTBeforeBackend = false;
584 LangOpts.SanitizeCoverage = CodeGenOpts.hasSanitizeCoverage();
585 LangOpts.ForceEmitVTables = CodeGenOpts.ForceEmitVTables;
586 LangOpts.SpeculativeLoadHardening = CodeGenOpts.SpeculativeLoadHardening;
587 LangOpts.CurrentModule = LangOpts.ModuleName;
588
589 llvm::Triple T(TargetOpts.Triple);
590 llvm::Triple::ArchType Arch = T.getArch();
591
592 CodeGenOpts.CodeModel = TargetOpts.CodeModel;
593 CodeGenOpts.LargeDataThreshold = TargetOpts.LargeDataThreshold;
594
595 if (CodeGenOpts.getExceptionHandling() !=
597 T.isWindowsMSVCEnvironment())
598 Diags.Report(diag::err_fe_invalid_exception_model)
599 << static_cast<unsigned>(CodeGenOpts.getExceptionHandling()) << T.str();
600
601 if (LangOpts.AppleKext && !LangOpts.CPlusPlus)
602 Diags.Report(diag::warn_c_kext);
603
604 if (LangOpts.NewAlignOverride &&
605 !llvm::isPowerOf2_32(LangOpts.NewAlignOverride)) {
606 Arg *A = Args.getLastArg(OPT_fnew_alignment_EQ);
607 Diags.Report(diag::err_fe_invalid_alignment)
608 << A->getAsString(Args) << A->getValue();
609 LangOpts.NewAlignOverride = 0;
610 }
611
612 // The -f[no-]raw-string-literals option is only valid in C and in C++
613 // standards before C++11.
614 if (LangOpts.CPlusPlus11) {
615 if (Args.hasArg(OPT_fraw_string_literals, OPT_fno_raw_string_literals)) {
616 Args.claimAllArgs(OPT_fraw_string_literals, OPT_fno_raw_string_literals);
617 Diags.Report(diag::warn_drv_fraw_string_literals_in_cxx11)
618 << bool(LangOpts.RawStringLiterals);
619 }
620
621 // Do not allow disabling raw string literals in C++11 or later.
622 LangOpts.RawStringLiterals = true;
623 }
624
625 if (Args.hasArg(OPT_freflection) && !LangOpts.CPlusPlus26) {
626 Diags.Report(diag::err_drv_reflection_requires_cxx26)
627 << Args.getLastArg(options::OPT_freflection)->getAsString(Args);
628 }
629
630 LangOpts.NamedLoops =
631 Args.hasFlag(OPT_fnamed_loops, OPT_fno_named_loops, LangOpts.C2y);
632
633 // Prevent the user from specifying both -fsycl-is-device and -fsycl-is-host.
634 if (LangOpts.SYCLIsDevice && LangOpts.SYCLIsHost)
635 Diags.Report(diag::err_drv_argument_not_allowed_with) << "-fsycl-is-device"
636 << "-fsycl-is-host";
637
638 if (Args.hasArg(OPT_fgnu89_inline) && LangOpts.CPlusPlus)
639 Diags.Report(diag::err_drv_argument_not_allowed_with)
640 << "-fgnu89-inline" << GetInputKindName(IK);
641
642 if (Args.hasArg(OPT_hlsl_entrypoint) && !LangOpts.HLSL)
643 Diags.Report(diag::err_drv_argument_not_allowed_with)
644 << "-hlsl-entry" << GetInputKindName(IK);
645
646 if (Args.hasArg(OPT_fdx_rootsignature_version) && !LangOpts.HLSL)
647 Diags.Report(diag::err_drv_argument_not_allowed_with)
648 << "-fdx-rootsignature-version" << GetInputKindName(IK);
649
650 if (Args.hasArg(OPT_fdx_rootsignature_define) && !LangOpts.HLSL)
651 Diags.Report(diag::err_drv_argument_not_allowed_with)
652 << "-fdx-rootsignature-define" << GetInputKindName(IK);
653
654 if (Args.hasArg(OPT_fgpu_allow_device_init) && !LangOpts.HIP)
655 Diags.Report(diag::warn_ignored_hip_only_option)
656 << Args.getLastArg(OPT_fgpu_allow_device_init)->getAsString(Args);
657
658 if (Args.hasArg(OPT_gpu_max_threads_per_block_EQ) && !LangOpts.HIP)
659 Diags.Report(diag::warn_ignored_hip_only_option)
660 << Args.getLastArg(OPT_gpu_max_threads_per_block_EQ)->getAsString(Args);
661
662 // HLSL invocations should always have -Wconversion, -Wvector-conversion, and
663 // -Wmatrix-conversion by default.
664 if (LangOpts.HLSL) {
665 auto &Warnings = Invocation.getDiagnosticOpts().Warnings;
666 if (!llvm::is_contained(Warnings, "conversion"))
667 Warnings.insert(Warnings.begin(), "conversion");
668 if (!llvm::is_contained(Warnings, "vector-conversion"))
669 Warnings.insert(Warnings.begin(), "vector-conversion");
670 if (!llvm::is_contained(Warnings, "matrix-conversion"))
671 Warnings.insert(Warnings.begin(), "matrix-conversion");
672 }
673
674 // When these options are used, the compiler is allowed to apply
675 // optimizations that may affect the final result. For example
676 // (x+y)+z is transformed to x+(y+z) but may not give the same
677 // final result; it's not value safe.
678 // Another example can be to simplify x/x to 1.0 but x could be 0.0, INF
679 // or NaN. Final result may then differ. An error is issued when the eval
680 // method is set with one of these options.
681 if (Args.hasArg(OPT_ffp_eval_method_EQ)) {
682 if (LangOpts.ApproxFunc)
683 Diags.Report(diag::err_incompatible_fp_eval_method_options) << 0;
684 if (LangOpts.AllowFPReassoc)
685 Diags.Report(diag::err_incompatible_fp_eval_method_options) << 1;
686 if (LangOpts.AllowRecip)
687 Diags.Report(diag::err_incompatible_fp_eval_method_options) << 2;
688 }
689
690 // -cl-strict-aliasing needs to emit diagnostic in the case where CL > 1.0.
691 // This option should be deprecated for CL > 1.0 because
692 // this option was added for compatibility with OpenCL 1.0.
693 if (Args.getLastArg(OPT_cl_strict_aliasing) &&
694 (LangOpts.getOpenCLCompatibleVersion() > 100))
695 Diags.Report(diag::warn_option_invalid_ocl_version)
696 << LangOpts.getOpenCLVersionString()
697 << Args.getLastArg(OPT_cl_strict_aliasing)->getAsString(Args);
698
699 if (Arg *A = Args.getLastArg(OPT_fdefault_calling_conv_EQ)) {
700 auto DefaultCC = LangOpts.getDefaultCallingConv();
701
702 bool emitError = (DefaultCC == LangOptions::DCC_FastCall ||
703 DefaultCC == LangOptions::DCC_StdCall) &&
704 Arch != llvm::Triple::x86;
705 emitError |= (DefaultCC == LangOptions::DCC_VectorCall ||
706 DefaultCC == LangOptions::DCC_RegCall) &&
707 !T.isX86();
708 emitError |= DefaultCC == LangOptions::DCC_RtdCall && Arch != llvm::Triple::m68k;
709 if (emitError)
710 Diags.Report(diag::err_drv_argument_not_allowed_with)
711 << A->getSpelling() << T.getTriple();
712 }
713
714 return Diags.getNumErrors() == NumErrorsBefore;
715}
716
717//===----------------------------------------------------------------------===//
718// Deserialization (from args)
719//===----------------------------------------------------------------------===//
720
721static void GenerateArg(ArgumentConsumer Consumer,
722 llvm::opt::OptSpecifier OptSpecifier) {
723 Option Opt = getDriverOptTable().getOption(OptSpecifier);
724 denormalizeSimpleFlag(Consumer, Opt.getPrefixedName(),
725 Option::OptionClass::FlagClass, 0);
726}
727
728static void GenerateArg(ArgumentConsumer Consumer,
729 llvm::opt::OptSpecifier OptSpecifier,
730 const Twine &Value) {
731 Option Opt = getDriverOptTable().getOption(OptSpecifier);
732 denormalizeString(Consumer, Opt.getPrefixedName(), Opt.getKind(), 0, Value);
733}
734
735// Parse command line arguments into CompilerInvocation.
736using ParseFn =
737 llvm::function_ref<bool(CompilerInvocation &, ArrayRef<const char *>,
738 DiagnosticsEngine &, const char *)>;
739
740// Generate command line arguments from CompilerInvocation.
741using GenerateFn = llvm::function_ref<void(
744
745/// May perform round-trip of command line arguments. By default, the round-trip
746/// is enabled in assert builds. This can be overwritten at run-time via the
747/// "-round-trip-args" and "-no-round-trip-args" command line flags, or via the
748/// ForceRoundTrip parameter.
749///
750/// During round-trip, the command line arguments are parsed into a dummy
751/// CompilerInvocation, which is used to generate the command line arguments
752/// again. The real CompilerInvocation is then created by parsing the generated
753/// arguments, not the original ones. This (in combination with tests covering
754/// argument behavior) ensures the generated command line is complete (doesn't
755/// drop/mangle any arguments).
756///
757/// Finally, we check the command line that was used to create the real
758/// CompilerInvocation instance. By default, we compare it to the command line
759/// the real CompilerInvocation generates. This checks whether the generator is
760/// deterministic. If \p CheckAgainstOriginalInvocation is enabled, we instead
761/// compare it to the original command line to verify the original command-line
762/// was canonical and can round-trip exactly.
763static bool RoundTrip(ParseFn Parse, GenerateFn Generate,
764 CompilerInvocation &RealInvocation,
765 CompilerInvocation &DummyInvocation,
766 ArrayRef<const char *> CommandLineArgs,
767 DiagnosticsEngine &Diags, const char *Argv0,
768 bool CheckAgainstOriginalInvocation = false,
769 bool ForceRoundTrip = false) {
770#ifndef NDEBUG
771 bool DoRoundTripDefault = true;
772#else
773 bool DoRoundTripDefault = false;
774#endif
775
776 bool DoRoundTrip = DoRoundTripDefault;
777 if (ForceRoundTrip) {
778 DoRoundTrip = true;
779 } else {
780 for (const auto *Arg : CommandLineArgs) {
781 if (Arg == StringRef("-round-trip-args"))
782 DoRoundTrip = true;
783 if (Arg == StringRef("-no-round-trip-args"))
784 DoRoundTrip = false;
785 }
786 }
787
788 // If round-trip was not requested, simply run the parser with the real
789 // invocation diagnostics.
790 if (!DoRoundTrip)
791 return Parse(RealInvocation, CommandLineArgs, Diags, Argv0);
792
793 // Serializes quoted (and potentially escaped) arguments.
794 auto SerializeArgs = [](ArrayRef<const char *> Args) {
795 std::string Buffer;
796 llvm::raw_string_ostream OS(Buffer);
797 for (const char *Arg : Args) {
798 llvm::sys::printArg(OS, Arg, /*Quote=*/true);
799 OS << ' ';
800 }
801 return Buffer;
802 };
803
804 // Setup a dummy DiagnosticsEngine.
805 DiagnosticOptions DummyDiagOpts;
806 DiagnosticsEngine DummyDiags(DiagnosticIDs::create(), DummyDiagOpts);
807 DummyDiags.setClient(new TextDiagnosticBuffer());
808
809 // Run the first parse on the original arguments with the dummy invocation and
810 // diagnostics.
811 if (!Parse(DummyInvocation, CommandLineArgs, DummyDiags, Argv0) ||
812 DummyDiags.getNumWarnings() != 0) {
813 // If the first parse did not succeed, it must be user mistake (invalid
814 // command line arguments). We won't be able to generate arguments that
815 // would reproduce the same result. Let's fail again with the real
816 // invocation and diagnostics, so all side-effects of parsing are visible.
817 unsigned NumWarningsBefore = Diags.getNumWarnings();
818 auto Success = Parse(RealInvocation, CommandLineArgs, Diags, Argv0);
819 if (!Success || Diags.getNumWarnings() != NumWarningsBefore)
820 return Success;
821
822 // Parse with original options and diagnostics succeeded even though it
823 // shouldn't have. Something is off.
824 Diags.Report(diag::err_cc1_round_trip_fail_then_ok);
825 Diags.Report(diag::note_cc1_round_trip_original)
826 << SerializeArgs(CommandLineArgs);
827 return false;
828 }
829
830 // Setup string allocator.
831 llvm::BumpPtrAllocator Alloc;
832 llvm::StringSaver StringPool(Alloc);
833 auto SA = [&StringPool](const Twine &Arg) {
834 return StringPool.save(Arg).data();
835 };
836
837 // Generate arguments from the dummy invocation. If Generate is the
838 // inverse of Parse, the newly generated arguments must have the same
839 // semantics as the original.
840 SmallVector<const char *> GeneratedArgs;
841 Generate(DummyInvocation, GeneratedArgs, SA);
842
843 // Run the second parse, now on the generated arguments, and with the real
844 // invocation and diagnostics. The result is what we will end up using for the
845 // rest of compilation, so if Generate is not inverse of Parse, something down
846 // the line will break.
847 bool Success2 = Parse(RealInvocation, GeneratedArgs, Diags, Argv0);
848
849 // The first parse on original arguments succeeded, but second parse of
850 // generated arguments failed. Something must be wrong with the generator.
851 if (!Success2) {
852 Diags.Report(diag::err_cc1_round_trip_ok_then_fail);
853 Diags.Report(diag::note_cc1_round_trip_generated)
854 << 1 << SerializeArgs(GeneratedArgs);
855 return false;
856 }
857
858 SmallVector<const char *> ComparisonArgs;
859 if (CheckAgainstOriginalInvocation)
860 // Compare against original arguments.
861 ComparisonArgs.assign(CommandLineArgs.begin(), CommandLineArgs.end());
862 else
863 // Generate arguments again, this time from the options we will end up using
864 // for the rest of the compilation.
865 Generate(RealInvocation, ComparisonArgs, SA);
866
867 // Compares two lists of arguments.
868 auto Equal = [](const ArrayRef<const char *> A,
869 const ArrayRef<const char *> B) {
870 return llvm::equal(A, B, [](const char *AElem, const char *BElem) {
871 return StringRef(AElem) == StringRef(BElem);
872 });
873 };
874
875 // If we generated different arguments from what we assume are two
876 // semantically equivalent CompilerInvocations, the Generate function may
877 // be non-deterministic.
878 if (!Equal(GeneratedArgs, ComparisonArgs)) {
879 Diags.Report(diag::err_cc1_round_trip_mismatch);
880 Diags.Report(diag::note_cc1_round_trip_generated)
881 << 1 << SerializeArgs(GeneratedArgs);
882 Diags.Report(diag::note_cc1_round_trip_generated)
883 << 2 << SerializeArgs(ComparisonArgs);
884 return false;
885 }
886
887 Diags.Report(diag::remark_cc1_round_trip_generated)
888 << 1 << SerializeArgs(GeneratedArgs);
889 Diags.Report(diag::remark_cc1_round_trip_generated)
890 << 2 << SerializeArgs(ComparisonArgs);
891
892 return Success2;
893}
894
896 DiagnosticsEngine &Diags,
897 const char *Argv0) {
898 CompilerInvocation DummyInvocation1, DummyInvocation2;
899 return RoundTrip(
900 [](CompilerInvocation &Invocation, ArrayRef<const char *> CommandLineArgs,
901 DiagnosticsEngine &Diags, const char *Argv0) {
902 return CreateFromArgsImpl(Invocation, CommandLineArgs, Diags, Argv0);
903 },
905 StringAllocator SA) {
906 Args.push_back("-cc1");
907 Invocation.generateCC1CommandLine(Args, SA);
908 },
909 DummyInvocation1, DummyInvocation2, Args, Diags, Argv0,
910 /*CheckAgainstOriginalInvocation=*/true, /*ForceRoundTrip=*/true);
911}
912
913static void addDiagnosticArgs(ArgList &Args, OptSpecifier Group,
914 OptSpecifier GroupWithValue,
915 std::vector<std::string> &Diagnostics) {
916 for (auto *A : Args.filtered(Group)) {
917 if (A->getOption().getKind() == Option::FlagClass) {
918 // The argument is a pure flag (such as OPT_Wall or OPT_Wdeprecated). Add
919 // its name (minus the "W" or "R" at the beginning) to the diagnostics.
920 Diagnostics.push_back(
921 std::string(A->getOption().getName().drop_front(1)));
922 } else if (A->getOption().matches(GroupWithValue)) {
923 // This is -Wfoo= or -Rfoo=, where foo is the name of the diagnostic
924 // group. Add only the group name to the diagnostics.
925 Diagnostics.push_back(
926 std::string(A->getOption().getName().drop_front(1).rtrim("=-")));
927 } else {
928 // Otherwise, add its value (for OPT_W_Joined and similar).
929 Diagnostics.push_back(A->getValue());
930 }
931 }
932}
933
934// Parse the Static Analyzer configuration. If \p Diags is set to nullptr,
935// it won't verify the input.
936static void parseAnalyzerConfigs(AnalyzerOptions &AnOpts,
937 DiagnosticsEngine *Diags);
938
939static void getAllNoBuiltinFuncValues(ArgList &Args,
940 std::vector<std::string> &Funcs) {
941 std::vector<std::string> Values = Args.getAllArgValues(OPT_fno_builtin_);
942 auto BuiltinEnd = llvm::partition(Values, Builtin::Context::isBuiltinFunc);
943 Funcs.insert(Funcs.end(), Values.begin(), BuiltinEnd);
944}
945
946static void GenerateAnalyzerArgs(const AnalyzerOptions &Opts,
947 ArgumentConsumer Consumer) {
948 const AnalyzerOptions *AnalyzerOpts = &Opts;
949
950#define ANALYZER_OPTION_WITH_MARSHALLING(...) \
951 GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
952#include "clang/Options/Options.inc"
953#undef ANALYZER_OPTION_WITH_MARSHALLING
954
955 if (Opts.AnalysisConstraintsOpt != RangeConstraintsModel) {
956 switch (Opts.AnalysisConstraintsOpt) {
957#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) \
958 case NAME##Model: \
959 GenerateArg(Consumer, OPT_analyzer_constraints, CMDFLAG); \
960 break;
961#include "clang/StaticAnalyzer/Core/Analyses.def"
962 default:
963 llvm_unreachable("Tried to generate unknown analysis constraint.");
964 }
965 }
966
967 if (Opts.AnalysisDiagOpt != PD_HTML) {
968 switch (Opts.AnalysisDiagOpt) {
969#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN) \
970 case PD_##NAME: \
971 GenerateArg(Consumer, OPT_analyzer_output, CMDFLAG); \
972 break;
973#include "clang/StaticAnalyzer/Core/Analyses.def"
974 default:
975 llvm_unreachable("Tried to generate unknown analysis diagnostic client.");
976 }
977 }
978
979 if (Opts.AnalysisPurgeOpt != PurgeStmt) {
980 switch (Opts.AnalysisPurgeOpt) {
981#define ANALYSIS_PURGE(NAME, CMDFLAG, DESC) \
982 case NAME: \
983 GenerateArg(Consumer, OPT_analyzer_purge, CMDFLAG); \
984 break;
985#include "clang/StaticAnalyzer/Core/Analyses.def"
986 default:
987 llvm_unreachable("Tried to generate unknown analysis purge mode.");
988 }
989 }
990
991 if (Opts.InliningMode != NoRedundancy) {
992 switch (Opts.InliningMode) {
993#define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC) \
994 case NAME: \
995 GenerateArg(Consumer, OPT_analyzer_inlining_mode, CMDFLAG); \
996 break;
997#include "clang/StaticAnalyzer/Core/Analyses.def"
998 default:
999 llvm_unreachable("Tried to generate unknown analysis inlining mode.");
1000 }
1001 }
1002
1003 for (const auto &CP : Opts.CheckersAndPackages) {
1004 OptSpecifier Opt =
1005 CP.second ? OPT_analyzer_checker : OPT_analyzer_disable_checker;
1006 GenerateArg(Consumer, Opt, CP.first);
1007 }
1008
1009 AnalyzerOptions ConfigOpts;
1010 parseAnalyzerConfigs(ConfigOpts, nullptr);
1011
1012 // Sort options by key to avoid relying on StringMap iteration order.
1014 for (const auto &C : Opts.Config)
1015 SortedConfigOpts.emplace_back(C.getKey(), C.getValue());
1016 llvm::sort(SortedConfigOpts, llvm::less_first());
1017
1018 for (const auto &[Key, Value] : SortedConfigOpts) {
1019 // Don't generate anything that came from parseAnalyzerConfigs. It would be
1020 // redundant and may not be valid on the command line.
1021 auto Entry = ConfigOpts.Config.find(Key);
1022 if (Entry != ConfigOpts.Config.end() && Entry->getValue() == Value)
1023 continue;
1024
1025 GenerateArg(Consumer, OPT_analyzer_config, Key + "=" + Value);
1026 }
1027
1028 // Nothing to generate for FullCompilerInvocation.
1029}
1030
1031static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
1032 DiagnosticsEngine &Diags) {
1033 unsigned NumErrorsBefore = Diags.getNumErrors();
1034
1035 AnalyzerOptions *AnalyzerOpts = &Opts;
1036
1037#define ANALYZER_OPTION_WITH_MARSHALLING(...) \
1038 PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
1039#include "clang/Options/Options.inc"
1040#undef ANALYZER_OPTION_WITH_MARSHALLING
1041
1042 if (Arg *A = Args.getLastArg(OPT_analyzer_constraints)) {
1043 StringRef Name = A->getValue();
1044 AnalysisConstraints Value = llvm::StringSwitch<AnalysisConstraints>(Name)
1045#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) \
1046 .Case(CMDFLAG, NAME##Model)
1047#include "clang/StaticAnalyzer/Core/Analyses.def"
1048 .Default(NumConstraints);
1049 if (Value == NumConstraints) {
1050 Diags.Report(diag::err_drv_invalid_value)
1051 << A->getAsString(Args) << Name;
1052 } else {
1053#ifndef LLVM_WITH_Z3
1054 if (Value == AnalysisConstraints::Z3ConstraintsModel) {
1055 Diags.Report(diag::err_analyzer_not_built_with_z3);
1056 }
1057#endif // LLVM_WITH_Z3
1059 }
1060 }
1061
1062 if (Arg *A = Args.getLastArg(OPT_analyzer_output)) {
1063 StringRef Name = A->getValue();
1064 AnalysisDiagClients Value = llvm::StringSwitch<AnalysisDiagClients>(Name)
1065#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN) \
1066 .Case(CMDFLAG, PD_##NAME)
1067#include "clang/StaticAnalyzer/Core/Analyses.def"
1068 .Default(NUM_ANALYSIS_DIAG_CLIENTS);
1070 Diags.Report(diag::err_drv_invalid_value)
1071 << A->getAsString(Args) << Name;
1072 } else {
1073 Opts.AnalysisDiagOpt = Value;
1074 }
1075 }
1076
1077 if (Arg *A = Args.getLastArg(OPT_analyzer_purge)) {
1078 StringRef Name = A->getValue();
1079 AnalysisPurgeMode Value = llvm::StringSwitch<AnalysisPurgeMode>(Name)
1080#define ANALYSIS_PURGE(NAME, CMDFLAG, DESC) \
1081 .Case(CMDFLAG, NAME)
1082#include "clang/StaticAnalyzer/Core/Analyses.def"
1083 .Default(NumPurgeModes);
1084 if (Value == NumPurgeModes) {
1085 Diags.Report(diag::err_drv_invalid_value)
1086 << A->getAsString(Args) << Name;
1087 } else {
1088 Opts.AnalysisPurgeOpt = Value;
1089 }
1090 }
1091
1092 if (Arg *A = Args.getLastArg(OPT_analyzer_inlining_mode)) {
1093 StringRef Name = A->getValue();
1094 AnalysisInliningMode Value = llvm::StringSwitch<AnalysisInliningMode>(Name)
1095#define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC) \
1096 .Case(CMDFLAG, NAME)
1097#include "clang/StaticAnalyzer/Core/Analyses.def"
1098 .Default(NumInliningModes);
1099 if (Value == NumInliningModes) {
1100 Diags.Report(diag::err_drv_invalid_value)
1101 << A->getAsString(Args) << Name;
1102 } else {
1103 Opts.InliningMode = Value;
1104 }
1105 }
1106
1107 Opts.CheckersAndPackages.clear();
1108 for (const Arg *A :
1109 Args.filtered(OPT_analyzer_checker, OPT_analyzer_disable_checker)) {
1110 A->claim();
1111 bool IsEnabled = A->getOption().getID() == OPT_analyzer_checker;
1112 // We can have a list of comma separated checker names, e.g:
1113 // '-analyzer-checker=cocoa,unix'
1114 StringRef CheckerAndPackageList = A->getValue();
1115 SmallVector<StringRef, 16> CheckersAndPackages;
1116 CheckerAndPackageList.split(CheckersAndPackages, ",");
1117 for (const StringRef &CheckerOrPackage : CheckersAndPackages)
1118 Opts.CheckersAndPackages.emplace_back(std::string(CheckerOrPackage),
1119 IsEnabled);
1120 }
1121
1122 // Go through the analyzer configuration options.
1123 for (const auto *A : Args.filtered(OPT_analyzer_config)) {
1124
1125 // We can have a list of comma separated config names, e.g:
1126 // '-analyzer-config key1=val1,key2=val2'
1127 StringRef configList = A->getValue();
1128 SmallVector<StringRef, 4> configVals;
1129 configList.split(configVals, ",");
1130 for (const auto &configVal : configVals) {
1131 StringRef key, val;
1132 std::tie(key, val) = configVal.split("=");
1133 if (val.empty()) {
1134 Diags.Report(SourceLocation(),
1135 diag::err_analyzer_config_no_value) << configVal;
1136 break;
1137 }
1138 if (val.contains('=')) {
1139 Diags.Report(SourceLocation(),
1140 diag::err_analyzer_config_multiple_values)
1141 << configVal;
1142 break;
1143 }
1144
1145 // TODO: Check checker options too, possibly in CheckerRegistry.
1146 // Leave unknown non-checker configs unclaimed.
1147 if (!key.contains(":") && Opts.isUnknownAnalyzerConfig(key)) {
1149 Diags.Report(diag::err_analyzer_config_unknown) << key;
1150 continue;
1151 }
1152
1153 A->claim();
1154 Opts.Config[key] = std::string(val);
1155 }
1156 }
1157
1159 parseAnalyzerConfigs(Opts, &Diags);
1160 else
1161 parseAnalyzerConfigs(Opts, nullptr);
1162
1163 llvm::raw_string_ostream os(Opts.FullCompilerInvocation);
1164 for (unsigned i = 0; i < Args.getNumInputArgStrings(); ++i) {
1165 if (i != 0)
1166 os << " ";
1167 os << Args.getArgString(i);
1168 }
1169
1170 return Diags.getNumErrors() == NumErrorsBefore;
1171}
1172
1174 StringRef OptionName, StringRef DefaultVal) {
1175 return Config.insert({OptionName, std::string(DefaultVal)}).first->second;
1176}
1177
1179 DiagnosticsEngine *Diags,
1180 StringRef &OptionField, StringRef Name,
1181 StringRef DefaultVal) {
1182 // String options may be known to invalid (e.g. if the expected string is a
1183 // file name, but the file does not exist), those will have to be checked in
1184 // parseConfigs.
1185 OptionField = getStringOption(Config, Name, DefaultVal);
1186}
1187
1189 DiagnosticsEngine *Diags,
1190 bool &OptionField, StringRef Name, bool DefaultVal) {
1191 auto PossiblyInvalidVal =
1192 llvm::StringSwitch<std::optional<bool>>(
1193 getStringOption(Config, Name, (DefaultVal ? "true" : "false")))
1194 .Case("true", true)
1195 .Case("false", false)
1196 .Default(std::nullopt);
1197
1198 if (!PossiblyInvalidVal) {
1199 if (Diags)
1200 Diags->Report(diag::err_analyzer_config_invalid_input)
1201 << Name << "a boolean";
1202 else
1203 OptionField = DefaultVal;
1204 } else
1205 OptionField = *PossiblyInvalidVal;
1206}
1207
1209 DiagnosticsEngine *Diags,
1210 unsigned &OptionField, StringRef Name,
1211 unsigned DefaultVal) {
1212
1213 OptionField = DefaultVal;
1214 bool HasFailed = getStringOption(Config, Name, std::to_string(DefaultVal))
1215 .getAsInteger(0, OptionField);
1216 if (Diags && HasFailed)
1217 Diags->Report(diag::err_analyzer_config_invalid_input)
1218 << Name << "an unsigned";
1219}
1220
1222 DiagnosticsEngine *Diags,
1223 PositiveAnalyzerOption &OptionField, StringRef Name,
1224 unsigned DefaultVal) {
1225 auto Parsed = PositiveAnalyzerOption::create(
1226 getStringOption(Config, Name, std::to_string(DefaultVal)));
1227 if (Parsed.has_value()) {
1228 OptionField = Parsed.value();
1229 return;
1230 }
1231 if (Diags && !Parsed.has_value())
1232 Diags->Report(diag::err_analyzer_config_invalid_input)
1233 << Name << "a positive";
1234
1235 OptionField = DefaultVal;
1236}
1237
1239 DiagnosticsEngine *Diags) {
1240 // TODO: There's no need to store the entire configtable, it'd be plenty
1241 // enough to store checker options.
1242
1243#define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL) \
1244 initOption(AnOpts.Config, Diags, AnOpts.NAME, CMDFLAG, DEFAULT_VAL);
1245#define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(...)
1246#include "clang/StaticAnalyzer/Core/AnalyzerOptions.def"
1247
1248 assert(AnOpts.UserMode == "shallow" || AnOpts.UserMode == "deep");
1249 const bool InShallowMode = AnOpts.UserMode == "shallow";
1250
1251#define ANALYZER_OPTION(...)
1252#define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC, \
1253 SHALLOW_VAL, DEEP_VAL) \
1254 initOption(AnOpts.Config, Diags, AnOpts.NAME, CMDFLAG, \
1255 InShallowMode ? SHALLOW_VAL : DEEP_VAL);
1256#include "clang/StaticAnalyzer/Core/AnalyzerOptions.def"
1257
1258 // At this point, AnalyzerOptions is configured. Let's validate some options.
1259
1260 // FIXME: Here we try to validate the silenced checkers or packages are valid.
1261 // The current approach only validates the registered checkers which does not
1262 // contain the runtime enabled checkers and optimally we would validate both.
1263 if (!AnOpts.RawSilencedCheckersAndPackages.empty()) {
1264 std::vector<StringRef> Checkers =
1265 AnOpts.getRegisteredCheckers(/*IncludeExperimental=*/true);
1266 std::vector<StringRef> Packages =
1267 AnOpts.getRegisteredPackages(/*IncludeExperimental=*/true);
1268
1269 SmallVector<StringRef, 16> CheckersAndPackages;
1270 AnOpts.RawSilencedCheckersAndPackages.split(CheckersAndPackages, ";");
1271
1272 for (const StringRef &CheckerOrPackage : CheckersAndPackages) {
1273 if (Diags) {
1274 bool IsChecker = CheckerOrPackage.contains('.');
1275 bool IsValidName = IsChecker
1276 ? llvm::is_contained(Checkers, CheckerOrPackage)
1277 : llvm::is_contained(Packages, CheckerOrPackage);
1278
1279 if (!IsValidName)
1280 Diags->Report(diag::err_unknown_analyzer_checker_or_package)
1281 << CheckerOrPackage;
1282 }
1283
1284 AnOpts.SilencedCheckersAndPackages.emplace_back(CheckerOrPackage);
1285 }
1286 }
1287
1288 if (!Diags)
1289 return;
1290
1291 if (AnOpts.ShouldTrackConditionsDebug && !AnOpts.ShouldTrackConditions)
1292 Diags->Report(diag::err_analyzer_config_invalid_input)
1293 << "track-conditions-debug" << "'track-conditions' to also be enabled";
1294}
1295
1296/// Generate a remark argument. This is an inverse of `ParseOptimizationRemark`.
1297static void
1299 StringRef Name,
1301 if (Remark.hasValidPattern()) {
1302 GenerateArg(Consumer, OptEQ, Remark.Pattern);
1303 } else if (Remark.Kind == CodeGenOptions::RK_Enabled) {
1304 GenerateArg(Consumer, OPT_R_Joined, Name);
1305 } else if (Remark.Kind == CodeGenOptions::RK_Disabled) {
1306 GenerateArg(Consumer, OPT_R_Joined, StringRef("no-") + Name);
1307 }
1308}
1309
1310/// Parse a remark command line argument. It may be missing, disabled/enabled by
1311/// '-R[no-]group' or specified with a regular expression by '-Rgroup=regexp'.
1312/// On top of that, it can be disabled/enabled globally by '-R[no-]everything'.
1315 OptSpecifier OptEQ, StringRef Name) {
1317
1318 auto InitializeResultPattern = [&Diags, &Args, &Result](const Arg *A,
1319 StringRef Pattern) {
1320 Result.Pattern = Pattern.str();
1321
1322 std::string RegexError;
1323 Result.Regex = std::make_shared<llvm::Regex>(Result.Pattern);
1324 if (!Result.Regex->isValid(RegexError)) {
1325 Diags.Report(diag::err_drv_optimization_remark_pattern)
1326 << RegexError << A->getAsString(Args);
1327 return false;
1328 }
1329
1330 return true;
1331 };
1332
1333 for (Arg *A : Args) {
1334 if (A->getOption().matches(OPT_R_Joined)) {
1335 StringRef Value = A->getValue();
1336
1337 if (Value == Name)
1339 else if (Value == "everything")
1341 else if (Value.split('-') == std::make_pair(StringRef("no"), Name))
1342 Result.Kind = CodeGenOptions::RK_Disabled;
1343 else if (Value == "no-everything")
1345 else
1346 continue;
1347
1348 if (Result.Kind == CodeGenOptions::RK_Disabled ||
1350 Result.Pattern = "";
1351 Result.Regex = nullptr;
1352 } else {
1353 InitializeResultPattern(A, ".*");
1354 }
1355 } else if (A->getOption().matches(OptEQ)) {
1356 Result.Kind = CodeGenOptions::RK_WithPattern;
1357 if (!InitializeResultPattern(A, A->getValue()))
1359 }
1360 }
1361
1362 return Result;
1363}
1364
1365static bool parseDiagnosticLevelMask(StringRef FlagName,
1366 const std::vector<std::string> &Levels,
1367 DiagnosticsEngine &Diags,
1369 bool Success = true;
1370 for (const auto &Level : Levels) {
1371 DiagnosticLevelMask const PM =
1372 llvm::StringSwitch<DiagnosticLevelMask>(Level)
1373 .Case("note", DiagnosticLevelMask::Note)
1374 .Case("remark", DiagnosticLevelMask::Remark)
1375 .Case("warning", DiagnosticLevelMask::Warning)
1376 .Case("error", DiagnosticLevelMask::Error)
1377 .Default(DiagnosticLevelMask::None);
1378 if (PM == DiagnosticLevelMask::None) {
1379 Success = false;
1380 Diags.Report(diag::err_drv_invalid_value) << FlagName << Level;
1381 }
1382 M = M | PM;
1383 }
1384 return Success;
1385}
1386
1387static void parseSanitizerKinds(StringRef FlagName,
1388 const std::vector<std::string> &Sanitizers,
1389 DiagnosticsEngine &Diags, SanitizerSet &S) {
1390 for (const auto &Sanitizer : Sanitizers) {
1391 SanitizerMask K = parseSanitizerValue(Sanitizer, /*AllowGroups=*/false);
1392 if (K == SanitizerMask())
1393 Diags.Report(diag::err_drv_invalid_value) << FlagName << Sanitizer;
1394 else
1395 S.set(K, true);
1396 }
1397}
1398
1404
1407 const std::vector<std::string> &Sanitizers,
1408 DiagnosticsEngine &Diags) {
1409 SanitizerMaskCutoffs Cutoffs;
1410 for (const auto &Sanitizer : Sanitizers) {
1411 if (!parseSanitizerWeightedValue(Sanitizer, /*AllowGroups=*/false, Cutoffs))
1412 Diags.Report(diag::err_drv_invalid_value) << FlagName << Sanitizer;
1413 }
1414 return Cutoffs;
1415}
1416
1417static void parseXRayInstrumentationBundle(StringRef FlagName, StringRef Bundle,
1418 ArgList &Args, DiagnosticsEngine &D,
1419 XRayInstrSet &S) {
1421 llvm::SplitString(Bundle, BundleParts, ",");
1422 for (const auto &B : BundleParts) {
1423 auto Mask = parseXRayInstrValue(B);
1424 if (Mask == XRayInstrKind::None)
1425 if (B != "none")
1426 D.Report(diag::err_drv_invalid_value) << FlagName << Bundle;
1427 else
1428 S.Mask = Mask;
1429 else if (Mask == XRayInstrKind::All)
1430 S.Mask = Mask;
1431 else
1432 S.set(Mask, true);
1433 }
1434}
1435
1438 serializeXRayInstrValue(S, BundleParts);
1439 std::string Buffer;
1440 llvm::raw_string_ostream OS(Buffer);
1441 llvm::interleave(BundleParts, OS, [&OS](StringRef Part) { OS << Part; }, ",");
1442 return Buffer;
1443}
1444
1447 const llvm::Triple &Triple) {
1448 assert(Triple.getArch() == llvm::Triple::aarch64);
1449 if (LangOpts.PointerAuthCalls) {
1450 using Key = PointerAuthSchema::ARM8_3Key;
1451 using Discrimination = PointerAuthSchema::Discrimination;
1452 // If you change anything here, be sure to update <ptrauth.h>.
1454 Key::ASIA, false,
1455 LangOpts.PointerAuthFunctionTypeDiscrimination ? Discrimination::Type
1456 : Discrimination::None);
1457
1459 Key::ASDA, LangOpts.PointerAuthVTPtrAddressDiscrimination,
1460 LangOpts.PointerAuthVTPtrTypeDiscrimination ? Discrimination::Type
1461 : Discrimination::None);
1462
1463 if (LangOpts.PointerAuthTypeInfoVTPtrDiscrimination)
1465 PointerAuthSchema(Key::ASDA, true, Discrimination::Constant,
1467 else
1469 PointerAuthSchema(Key::ASDA, false, Discrimination::None);
1470
1472 PointerAuthSchema(Key::ASDA, false, Discrimination::None);
1474 PointerAuthSchema(Key::ASIA, true, Discrimination::Decl);
1476 PointerAuthSchema(Key::ASIA, false, Discrimination::Type);
1477
1478 if (LangOpts.PointerAuthInitFini) {
1480 Key::ASIA, LangOpts.PointerAuthInitFiniAddressDiscrimination,
1481 Discrimination::Constant, InitFiniPointerConstantDiscriminator);
1482 }
1483
1485 PointerAuthSchema(Key::ASIA, true, Discrimination::None);
1487 PointerAuthSchema(Key::ASIA, true, Discrimination::None);
1489 PointerAuthSchema(Key::ASIA, true, Discrimination::None);
1490 if (LangOpts.PointerAuthBlockDescriptorPointers)
1492 PointerAuthSchema(Key::ASDA, true, Discrimination::Constant,
1494
1496 PointerAuthSchema(Key::ASIA, true, Discrimination::None);
1498 PointerAuthSchema(Key::ASDA, true, Discrimination::Constant,
1500 if (LangOpts.PointerAuthObjcIsa) {
1501 Opts.ObjCIsaPointers =
1502 PointerAuthSchema(Key::ASDA, true, Discrimination::Constant,
1504 Opts.ObjCSuperPointers =
1505 PointerAuthSchema(Key::ASDA, true, Discrimination::Constant,
1507 }
1508
1509 if (LangOpts.PointerAuthObjcClassROPointers)
1510 Opts.ObjCClassROPointers =
1511 PointerAuthSchema(Key::ASDA, true, Discrimination::Constant,
1513 }
1514 Opts.ReturnAddresses = LangOpts.PointerAuthReturns;
1515 Opts.AuthTraps = LangOpts.PointerAuthAuthTraps;
1516 Opts.IndirectGotos = LangOpts.PointerAuthIndirectGotos;
1517 Opts.AArch64JumpTableHardening = LangOpts.AArch64JumpTableHardening;
1518}
1519
1521 const LangOptions &LangOpts,
1522 const llvm::Triple &Triple,
1523 DiagnosticsEngine &Diags) {
1524 if (!LangOpts.PointerAuthCalls && !LangOpts.PointerAuthReturns &&
1525 !LangOpts.PointerAuthAuthTraps && !LangOpts.PointerAuthIndirectGotos &&
1526 !LangOpts.AArch64JumpTableHardening)
1527 return;
1528
1530}
1531
1532void CompilerInvocationBase::GenerateCodeGenArgs(const CodeGenOptions &Opts,
1533 ArgumentConsumer Consumer,
1534 const llvm::Triple &T,
1535 const std::string &OutputFile,
1536 const LangOptions *LangOpts) {
1537 const CodeGenOptions &CodeGenOpts = Opts;
1538
1539 if (Opts.OptimizationLevel == 0)
1540 GenerateArg(Consumer, OPT_O0);
1541 else
1542 GenerateArg(Consumer, OPT_O, Twine(Opts.OptimizationLevel));
1543
1544#define CODEGEN_OPTION_WITH_MARSHALLING(...) \
1545 GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
1546#include "clang/Options/Options.inc"
1547#undef CODEGEN_OPTION_WITH_MARSHALLING
1548
1549 if (Opts.OptimizationLevel > 0) {
1550 if (Opts.Inlining == CodeGenOptions::NormalInlining)
1551 GenerateArg(Consumer, OPT_finline_functions);
1552 else if (Opts.Inlining == CodeGenOptions::OnlyHintInlining)
1553 GenerateArg(Consumer, OPT_finline_hint_functions);
1554 else if (Opts.Inlining == CodeGenOptions::OnlyAlwaysInlining)
1555 GenerateArg(Consumer, OPT_fno_inline);
1556 }
1557
1558 if (Opts.DirectAccessExternalData && LangOpts->PICLevel != 0)
1559 GenerateArg(Consumer, OPT_fdirect_access_external_data);
1560 else if (!Opts.DirectAccessExternalData && LangOpts->PICLevel == 0)
1561 GenerateArg(Consumer, OPT_fno_direct_access_external_data);
1562
1563 std::optional<StringRef> DebugInfoVal;
1564 switch (Opts.DebugInfo) {
1565 case llvm::codegenoptions::DebugLineTablesOnly:
1566 DebugInfoVal = "line-tables-only";
1567 break;
1568 case llvm::codegenoptions::DebugDirectivesOnly:
1569 DebugInfoVal = "line-directives-only";
1570 break;
1571 case llvm::codegenoptions::DebugInfoConstructor:
1572 DebugInfoVal = "constructor";
1573 break;
1574 case llvm::codegenoptions::LimitedDebugInfo:
1575 DebugInfoVal = "limited";
1576 break;
1577 case llvm::codegenoptions::FullDebugInfo:
1578 DebugInfoVal = "standalone";
1579 break;
1580 case llvm::codegenoptions::UnusedTypeInfo:
1581 DebugInfoVal = "unused-types";
1582 break;
1583 case llvm::codegenoptions::NoDebugInfo: // default value
1584 DebugInfoVal = std::nullopt;
1585 break;
1586 case llvm::codegenoptions::LocTrackingOnly: // implied value
1587 DebugInfoVal = std::nullopt;
1588 break;
1589 }
1590 if (DebugInfoVal)
1591 GenerateArg(Consumer, OPT_debug_info_kind_EQ, *DebugInfoVal);
1592
1593 for (const auto &Prefix : Opts.DebugPrefixMap)
1594 GenerateArg(Consumer, OPT_fdebug_prefix_map_EQ,
1595 Prefix.first + "=" + Prefix.second);
1596
1597 for (const auto &Prefix : Opts.CoveragePrefixMap)
1598 GenerateArg(Consumer, OPT_fcoverage_prefix_map_EQ,
1599 Prefix.first + "=" + Prefix.second);
1600
1601 if (Opts.NewStructPathTBAA)
1602 GenerateArg(Consumer, OPT_new_struct_path_tbaa);
1603
1604 if (Opts.OptimizeSize == 1)
1605 GenerateArg(Consumer, OPT_O, "s");
1606 else if (Opts.OptimizeSize == 2)
1607 GenerateArg(Consumer, OPT_O, "z");
1608
1609 // SimplifyLibCalls is set only in the absence of -fno-builtin and
1610 // -ffreestanding. We'll consider that when generating them.
1611
1612 // NoBuiltinFuncs are generated by LangOptions.
1613
1614 if (Opts.UnrollLoops && Opts.OptimizationLevel <= 1)
1615 GenerateArg(Consumer, OPT_funroll_loops);
1616 else if (!Opts.UnrollLoops && Opts.OptimizationLevel > 1)
1617 GenerateArg(Consumer, OPT_fno_unroll_loops);
1618
1619 if (Opts.InterchangeLoops)
1620 GenerateArg(Consumer, OPT_floop_interchange);
1621 else
1622 GenerateArg(Consumer, OPT_fno_loop_interchange);
1623
1624 if (Opts.FuseLoops)
1625 GenerateArg(Consumer, OPT_fexperimental_loop_fusion);
1626
1627 if (!Opts.BinutilsVersion.empty())
1628 GenerateArg(Consumer, OPT_fbinutils_version_EQ, Opts.BinutilsVersion);
1629
1630 if (Opts.DebugNameTable ==
1631 static_cast<unsigned>(llvm::DICompileUnit::DebugNameTableKind::GNU))
1632 GenerateArg(Consumer, OPT_ggnu_pubnames);
1633 else if (Opts.DebugNameTable ==
1634 static_cast<unsigned>(
1635 llvm::DICompileUnit::DebugNameTableKind::Default))
1636 GenerateArg(Consumer, OPT_gpubnames);
1637
1638 if (Opts.DebugTemplateAlias)
1639 GenerateArg(Consumer, OPT_gtemplate_alias);
1640
1641 auto TNK = Opts.getDebugSimpleTemplateNames();
1642 if (TNK != llvm::codegenoptions::DebugTemplateNamesKind::Full) {
1643 if (TNK == llvm::codegenoptions::DebugTemplateNamesKind::Simple)
1644 GenerateArg(Consumer, OPT_gsimple_template_names_EQ, "simple");
1645 else if (TNK == llvm::codegenoptions::DebugTemplateNamesKind::Mangled)
1646 GenerateArg(Consumer, OPT_gsimple_template_names_EQ, "mangled");
1647 }
1648 // ProfileInstrumentUsePath is marshalled automatically, no need to generate
1649 // it or PGOUseInstrumentor.
1650
1651 if (Opts.TimePasses) {
1652 if (Opts.TimePassesPerRun)
1653 GenerateArg(Consumer, OPT_ftime_report_EQ, "per-pass-run");
1654 else
1655 GenerateArg(Consumer, OPT_ftime_report);
1656
1657 if (Opts.TimePassesJson)
1658 GenerateArg(Consumer, OPT_ftime_report_json);
1659 }
1660
1661 if (Opts.PrepareForLTO && !Opts.PrepareForThinLTO)
1662 GenerateArg(Consumer, OPT_flto_EQ, "full");
1663
1664 if (Opts.PrepareForThinLTO)
1665 GenerateArg(Consumer, OPT_flto_EQ, "thin");
1666
1667 if (!Opts.ThinLTOIndexFile.empty())
1668 GenerateArg(Consumer, OPT_fthinlto_index_EQ, Opts.ThinLTOIndexFile);
1669
1670 if (Opts.SaveTempsFilePrefix == OutputFile)
1671 GenerateArg(Consumer, OPT_save_temps_EQ, "obj");
1672
1673 StringRef MemProfileBasename("memprof.profraw");
1674 if (!Opts.MemoryProfileOutput.empty()) {
1675 if (Opts.MemoryProfileOutput == MemProfileBasename) {
1676 GenerateArg(Consumer, OPT_fmemory_profile);
1677 } else {
1678 size_t ArgLength =
1679 Opts.MemoryProfileOutput.size() - MemProfileBasename.size();
1680 GenerateArg(Consumer, OPT_fmemory_profile_EQ,
1681 Opts.MemoryProfileOutput.substr(0, ArgLength));
1682 }
1683 }
1684
1685 if (memcmp(Opts.CoverageVersion, "0000", 4))
1686 GenerateArg(Consumer, OPT_coverage_version_EQ,
1687 StringRef(Opts.CoverageVersion, 4));
1688
1689 // TODO: Check if we need to generate arguments stored in CmdArgs. (Namely
1690 // '-fembed_bitcode', which does not map to any CompilerInvocation field and
1691 // won't be generated.)
1692
1694 std::string InstrBundle =
1696 if (!InstrBundle.empty())
1697 GenerateArg(Consumer, OPT_fxray_instrumentation_bundle, InstrBundle);
1698 }
1699
1700 if (Opts.CFProtectionReturn && Opts.CFProtectionBranch)
1701 GenerateArg(Consumer, OPT_fcf_protection_EQ, "full");
1702 else if (Opts.CFProtectionReturn)
1703 GenerateArg(Consumer, OPT_fcf_protection_EQ, "return");
1704 else if (Opts.CFProtectionBranch)
1705 GenerateArg(Consumer, OPT_fcf_protection_EQ, "branch");
1706
1707 if (Opts.CFProtectionBranch) {
1708 switch (Opts.getCFBranchLabelScheme()) {
1710 break;
1711#define CF_BRANCH_LABEL_SCHEME(Kind, FlagVal) \
1712 case CFBranchLabelSchemeKind::Kind: \
1713 GenerateArg(Consumer, OPT_mcf_branch_label_scheme_EQ, #FlagVal); \
1714 break;
1715#include "clang/Basic/CFProtectionOptions.def"
1716 }
1717 }
1718
1719 if (Opts.FunctionReturnThunks)
1720 GenerateArg(Consumer, OPT_mfunction_return_EQ, "thunk-extern");
1721
1722 for (const auto &F : Opts.LinkBitcodeFiles) {
1723 bool Builtint = F.LinkFlags == llvm::Linker::Flags::LinkOnlyNeeded &&
1724 F.PropagateAttrs && F.Internalize;
1725 GenerateArg(Consumer,
1726 Builtint ? OPT_mlink_builtin_bitcode : OPT_mlink_bitcode_file,
1727 F.Filename);
1728 }
1729
1730 if (Opts.EmulatedTLS)
1731 GenerateArg(Consumer, OPT_femulated_tls);
1732
1733 if (Opts.FPDenormalMode != llvm::DenormalMode::getIEEE())
1734 GenerateArg(Consumer, OPT_fdenormal_fp_math_EQ, Opts.FPDenormalMode.str());
1735
1736 if ((Opts.FPDenormalMode != Opts.FP32DenormalMode) ||
1737 (Opts.FP32DenormalMode != llvm::DenormalMode::getIEEE()))
1738 GenerateArg(Consumer, OPT_fdenormal_fp_math_f32_EQ,
1739 Opts.FP32DenormalMode.str());
1740
1741 if (Opts.StructReturnConvention == CodeGenOptions::SRCK_OnStack) {
1742 OptSpecifier Opt =
1743 T.isPPC32() ? OPT_maix_struct_return : OPT_fpcc_struct_return;
1744 GenerateArg(Consumer, Opt);
1745 } else if (Opts.StructReturnConvention == CodeGenOptions::SRCK_InRegs) {
1746 OptSpecifier Opt =
1747 T.isPPC32() ? OPT_msvr4_struct_return : OPT_freg_struct_return;
1748 GenerateArg(Consumer, Opt);
1749 }
1750
1751 if (Opts.EnableAIXExtendedAltivecABI)
1752 GenerateArg(Consumer, OPT_mabi_EQ_vec_extabi);
1753
1754 if (Opts.XCOFFReadOnlyPointers)
1755 GenerateArg(Consumer, OPT_mxcoff_roptr);
1756
1757 if (!Opts.OptRecordPasses.empty())
1758 GenerateArg(Consumer, OPT_opt_record_passes, Opts.OptRecordPasses);
1759
1760 if (!Opts.OptRecordFormat.empty())
1761 GenerateArg(Consumer, OPT_opt_record_format, Opts.OptRecordFormat);
1762
1763 GenerateOptimizationRemark(Consumer, OPT_Rpass_EQ, "pass",
1764 Opts.OptimizationRemark);
1765
1766 GenerateOptimizationRemark(Consumer, OPT_Rpass_missed_EQ, "pass-missed",
1768
1769 GenerateOptimizationRemark(Consumer, OPT_Rpass_analysis_EQ, "pass-analysis",
1771
1772 GenerateArg(Consumer, OPT_fdiagnostics_hotness_threshold_EQ,
1774 ? Twine(*Opts.DiagnosticsHotnessThreshold)
1775 : "auto");
1776
1777 GenerateArg(Consumer, OPT_fdiagnostics_misexpect_tolerance_EQ,
1778 Twine(*Opts.DiagnosticsMisExpectTolerance));
1779
1780 for (StringRef Sanitizer : serializeSanitizerKinds(Opts.SanitizeRecover))
1781 GenerateArg(Consumer, OPT_fsanitize_recover_EQ, Sanitizer);
1782
1783 for (StringRef Sanitizer : serializeSanitizerKinds(Opts.SanitizeTrap))
1784 GenerateArg(Consumer, OPT_fsanitize_trap_EQ, Sanitizer);
1785
1786 for (StringRef Sanitizer :
1788 GenerateArg(Consumer, OPT_fsanitize_merge_handlers_EQ, Sanitizer);
1789
1790 SmallVector<std::string, 4> Values;
1792 for (std::string Sanitizer : Values)
1793 GenerateArg(Consumer, OPT_fsanitize_skip_hot_cutoff_EQ, Sanitizer);
1794
1796 GenerateArg(Consumer, OPT_fallow_runtime_check_skip_hot_cutoff_EQ,
1797 std::to_string(*Opts.AllowRuntimeCheckSkipHotCutoff));
1798 }
1799
1800 for (StringRef Sanitizer :
1802 GenerateArg(Consumer, OPT_fsanitize_annotate_debug_info_EQ, Sanitizer);
1803
1804 if (!Opts.EmitVersionIdentMetadata)
1805 GenerateArg(Consumer, OPT_Qn);
1806
1807 switch (Opts.FiniteLoops) {
1809 break;
1811 GenerateArg(Consumer, OPT_ffinite_loops);
1812 break;
1814 GenerateArg(Consumer, OPT_fno_finite_loops);
1815 break;
1816 }
1817
1818 if (Opts.StaticClosure)
1819 GenerateArg(Consumer, OPT_static_libclosure);
1820}
1821
1822bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
1823 InputKind IK,
1824 DiagnosticsEngine &Diags,
1825 const llvm::Triple &T,
1826 const std::string &OutputFile,
1827 const LangOptions &LangOptsRef) {
1828 unsigned NumErrorsBefore = Diags.getNumErrors();
1829
1830 Opts.OptimizationLevel = getOptimizationLevel(Args, IK, Diags);
1831
1832 // The key paths of codegen options defined in Options.td start with
1833 // "CodeGenOpts.". Let's provide the expected variable name and type.
1834 CodeGenOptions &CodeGenOpts = Opts;
1835 // Some codegen options depend on language options. Let's provide the expected
1836 // variable name and type.
1837 const LangOptions *LangOpts = &LangOptsRef;
1838
1839#define CODEGEN_OPTION_WITH_MARSHALLING(...) \
1840 PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
1841#include "clang/Options/Options.inc"
1842#undef CODEGEN_OPTION_WITH_MARSHALLING
1843
1844 // At O0 we want to fully disable inlining outside of cases marked with
1845 // 'alwaysinline' that are required for correctness.
1846 if (Opts.OptimizationLevel == 0) {
1847 Opts.setInlining(CodeGenOptions::OnlyAlwaysInlining);
1848 } else if (const Arg *A = Args.getLastArg(options::OPT_finline_functions,
1849 options::OPT_finline_hint_functions,
1850 options::OPT_fno_inline_functions,
1851 options::OPT_fno_inline)) {
1852 // Explicit inlining flags can disable some or all inlining even at
1853 // optimization levels above zero.
1854 if (A->getOption().matches(options::OPT_finline_functions))
1855 Opts.setInlining(CodeGenOptions::NormalInlining);
1856 else if (A->getOption().matches(options::OPT_finline_hint_functions))
1857 Opts.setInlining(CodeGenOptions::OnlyHintInlining);
1858 else
1859 Opts.setInlining(CodeGenOptions::OnlyAlwaysInlining);
1860 } else {
1861 Opts.setInlining(CodeGenOptions::NormalInlining);
1862 }
1863
1864 // PIC defaults to -fno-direct-access-external-data while non-PIC defaults to
1865 // -fdirect-access-external-data.
1866 Opts.DirectAccessExternalData =
1867 Args.hasArg(OPT_fdirect_access_external_data) ||
1868 (!Args.hasArg(OPT_fno_direct_access_external_data) &&
1869 LangOpts->PICLevel == 0);
1870
1871 if (Arg *A = Args.getLastArg(OPT_debug_info_kind_EQ)) {
1872 unsigned Val =
1873 llvm::StringSwitch<unsigned>(A->getValue())
1874 .Case("line-tables-only", llvm::codegenoptions::DebugLineTablesOnly)
1875 .Case("line-directives-only",
1876 llvm::codegenoptions::DebugDirectivesOnly)
1877 .Case("constructor", llvm::codegenoptions::DebugInfoConstructor)
1878 .Case("limited", llvm::codegenoptions::LimitedDebugInfo)
1879 .Case("standalone", llvm::codegenoptions::FullDebugInfo)
1880 .Case("unused-types", llvm::codegenoptions::UnusedTypeInfo)
1881 .Default(~0U);
1882 if (Val == ~0U)
1883 Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args)
1884 << A->getValue();
1885 else
1886 Opts.setDebugInfo(static_cast<llvm::codegenoptions::DebugInfoKind>(Val));
1887 }
1888
1889 // If -fuse-ctor-homing is set and limited debug info is already on, then use
1890 // constructor homing, and vice versa for -fno-use-ctor-homing.
1891 if (const Arg *A =
1892 Args.getLastArg(OPT_fuse_ctor_homing, OPT_fno_use_ctor_homing)) {
1893 if (A->getOption().matches(OPT_fuse_ctor_homing) &&
1894 Opts.getDebugInfo() == llvm::codegenoptions::LimitedDebugInfo)
1895 Opts.setDebugInfo(llvm::codegenoptions::DebugInfoConstructor);
1896 if (A->getOption().matches(OPT_fno_use_ctor_homing) &&
1897 Opts.getDebugInfo() == llvm::codegenoptions::DebugInfoConstructor)
1898 Opts.setDebugInfo(llvm::codegenoptions::LimitedDebugInfo);
1899 }
1900
1901 for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ)) {
1902 auto Split = StringRef(Arg).split('=');
1903 Opts.DebugPrefixMap.emplace_back(Split.first, Split.second);
1904 }
1905
1906 for (const auto &Arg : Args.getAllArgValues(OPT_fcoverage_prefix_map_EQ)) {
1907 auto Split = StringRef(Arg).split('=');
1908 Opts.CoveragePrefixMap.emplace_back(Split.first, Split.second);
1909 }
1910
1911 const llvm::Triple::ArchType DebugEntryValueArchs[] = {
1912 llvm::Triple::x86, llvm::Triple::x86_64, llvm::Triple::aarch64,
1913 llvm::Triple::arm, llvm::Triple::armeb, llvm::Triple::mips,
1914 llvm::Triple::mipsel, llvm::Triple::mips64, llvm::Triple::mips64el,
1915 llvm::Triple::riscv32, llvm::Triple::riscv64};
1916
1917 if (Opts.OptimizationLevel > 0 && Opts.hasReducedDebugInfo() &&
1918 llvm::is_contained(DebugEntryValueArchs, T.getArch()))
1919 Opts.EmitCallSiteInfo = true;
1920
1921 if (!Opts.EnableDIPreservationVerify && Opts.DIBugsReportFilePath.size()) {
1922 Diags.Report(diag::warn_ignoring_verify_debuginfo_preserve_export)
1923 << Opts.DIBugsReportFilePath;
1924 Opts.DIBugsReportFilePath = "";
1925 }
1926
1927 Opts.NewStructPathTBAA = !Args.hasArg(OPT_no_struct_path_tbaa) &&
1928 Args.hasArg(OPT_new_struct_path_tbaa);
1929 Opts.OptimizeSize = getOptimizationLevelSize(Args);
1930 Opts.SimplifyLibCalls = !LangOpts->NoBuiltin;
1931 if (Opts.SimplifyLibCalls)
1932 Opts.NoBuiltinFuncs = LangOpts->NoBuiltinFuncs;
1933 Opts.UnrollLoops =
1934 Args.hasFlag(OPT_funroll_loops, OPT_fno_unroll_loops,
1935 (Opts.OptimizationLevel > 1));
1936 Opts.InterchangeLoops =
1937 Args.hasFlag(OPT_floop_interchange, OPT_fno_loop_interchange, false);
1938 Opts.FuseLoops = Args.hasFlag(OPT_fexperimental_loop_fusion,
1939 OPT_fno_experimental_loop_fusion, false);
1940 Opts.BinutilsVersion =
1941 std::string(Args.getLastArgValue(OPT_fbinutils_version_EQ));
1942
1943 Opts.DebugTemplateAlias = Args.hasArg(OPT_gtemplate_alias);
1944
1945 Opts.DebugNameTable = static_cast<unsigned>(
1946 Args.hasArg(OPT_ggnu_pubnames)
1947 ? llvm::DICompileUnit::DebugNameTableKind::GNU
1948 : Args.hasArg(OPT_gpubnames)
1949 ? llvm::DICompileUnit::DebugNameTableKind::Default
1950 : llvm::DICompileUnit::DebugNameTableKind::None);
1951 if (const Arg *A = Args.getLastArg(OPT_gsimple_template_names_EQ)) {
1952 StringRef Value = A->getValue();
1953 if (Value != "simple" && Value != "mangled")
1954 Diags.Report(diag::err_drv_unsupported_option_argument)
1955 << A->getSpelling() << A->getValue();
1956 Opts.setDebugSimpleTemplateNames(
1957 StringRef(A->getValue()) == "simple"
1958 ? llvm::codegenoptions::DebugTemplateNamesKind::Simple
1959 : llvm::codegenoptions::DebugTemplateNamesKind::Mangled);
1960 }
1961
1962 if (Args.hasArg(OPT_ftime_report, OPT_ftime_report_EQ, OPT_ftime_report_json,
1963 OPT_stats_file_timers)) {
1964 Opts.TimePasses = true;
1965
1966 // -ftime-report= is only for new pass manager.
1967 if (const Arg *EQ = Args.getLastArg(OPT_ftime_report_EQ)) {
1968 StringRef Val = EQ->getValue();
1969 if (Val == "per-pass")
1970 Opts.TimePassesPerRun = false;
1971 else if (Val == "per-pass-run")
1972 Opts.TimePassesPerRun = true;
1973 else
1974 Diags.Report(diag::err_drv_invalid_value)
1975 << EQ->getAsString(Args) << EQ->getValue();
1976 }
1977
1978 if (Args.getLastArg(OPT_ftime_report_json))
1979 Opts.TimePassesJson = true;
1980 }
1981
1982 Opts.PrepareForLTO = false;
1983 Opts.PrepareForThinLTO = false;
1984 if (Arg *A = Args.getLastArg(OPT_flto_EQ)) {
1985 Opts.PrepareForLTO = true;
1986 StringRef S = A->getValue();
1987 if (S == "thin")
1988 Opts.PrepareForThinLTO = true;
1989 else if (S != "full")
1990 Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << S;
1991 if (Args.hasArg(OPT_funified_lto))
1992 Opts.PrepareForThinLTO = true;
1993 }
1994 if (Arg *A = Args.getLastArg(OPT_fthinlto_index_EQ)) {
1995 if (IK.getLanguage() != Language::LLVM_IR)
1996 Diags.Report(diag::err_drv_argument_only_allowed_with)
1997 << A->getAsString(Args) << "-x ir";
1998 Opts.ThinLTOIndexFile =
1999 std::string(Args.getLastArgValue(OPT_fthinlto_index_EQ));
2000 }
2001 if (Arg *A = Args.getLastArg(OPT_save_temps_EQ))
2002 Opts.SaveTempsFilePrefix =
2003 llvm::StringSwitch<std::string>(A->getValue())
2004 .Case("obj", OutputFile)
2005 .Default(llvm::sys::path::filename(OutputFile).str());
2006
2007 // The memory profile runtime appends the pid to make this name more unique.
2008 const char *MemProfileBasename = "memprof.profraw";
2009 if (Args.hasArg(OPT_fmemory_profile_EQ)) {
2010 SmallString<128> Path(Args.getLastArgValue(OPT_fmemory_profile_EQ));
2011 llvm::sys::path::append(Path, MemProfileBasename);
2012 Opts.MemoryProfileOutput = std::string(Path);
2013 } else if (Args.hasArg(OPT_fmemory_profile))
2014 Opts.MemoryProfileOutput = MemProfileBasename;
2015
2016 if (Opts.CoverageNotesFile.size() || Opts.CoverageDataFile.size()) {
2017 if (Args.hasArg(OPT_coverage_version_EQ)) {
2018 StringRef CoverageVersion = Args.getLastArgValue(OPT_coverage_version_EQ);
2019 if (CoverageVersion.size() != 4) {
2020 Diags.Report(diag::err_drv_invalid_value)
2021 << Args.getLastArg(OPT_coverage_version_EQ)->getAsString(Args)
2022 << CoverageVersion;
2023 } else {
2024 memcpy(Opts.CoverageVersion, CoverageVersion.data(), 4);
2025 }
2026 }
2027 }
2028 // FIXME: For backend options that are not yet recorded as function
2029 // attributes in the IR, keep track of them so we can embed them in a
2030 // separate data section and use them when building the bitcode.
2031 for (const auto &A : Args) {
2032 // Do not encode output and input.
2033 if (A->getOption().getID() == options::OPT_o ||
2034 A->getOption().getID() == options::OPT_INPUT ||
2035 A->getOption().getID() == options::OPT_x ||
2036 A->getOption().getID() == options::OPT_fembed_bitcode ||
2037 A->getOption().matches(options::OPT_W_Group))
2038 continue;
2039 ArgStringList ASL;
2040 A->render(Args, ASL);
2041 for (const auto &arg : ASL) {
2042 StringRef ArgStr(arg);
2043 llvm::append_range(Opts.CmdArgs, ArgStr);
2044 // using \00 to separate each commandline options.
2045 Opts.CmdArgs.push_back('\0');
2046 }
2047 }
2048
2049 auto XRayInstrBundles =
2050 Args.getAllArgValues(OPT_fxray_instrumentation_bundle);
2051 if (XRayInstrBundles.empty())
2053 else
2054 for (const auto &A : XRayInstrBundles)
2055 parseXRayInstrumentationBundle("-fxray-instrumentation-bundle=", A, Args,
2056 Diags, Opts.XRayInstrumentationBundle);
2057
2058 if (const Arg *A = Args.getLastArg(OPT_fcf_protection_EQ)) {
2059 StringRef Name = A->getValue();
2060 if (Name == "full") {
2061 Opts.CFProtectionReturn = 1;
2062 Opts.CFProtectionBranch = 1;
2063 } else if (Name == "return")
2064 Opts.CFProtectionReturn = 1;
2065 else if (Name == "branch")
2066 Opts.CFProtectionBranch = 1;
2067 else if (Name != "none")
2068 Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name;
2069 }
2070
2071 if (Opts.CFProtectionBranch && T.isRISCV()) {
2072 if (const Arg *A = Args.getLastArg(OPT_mcf_branch_label_scheme_EQ)) {
2073 const auto Scheme =
2074 llvm::StringSwitch<CFBranchLabelSchemeKind>(A->getValue())
2075#define CF_BRANCH_LABEL_SCHEME(Kind, FlagVal) \
2076 .Case(#FlagVal, CFBranchLabelSchemeKind::Kind)
2077#include "clang/Basic/CFProtectionOptions.def"
2080 Opts.setCFBranchLabelScheme(Scheme);
2081 else
2082 Diags.Report(diag::err_drv_invalid_value)
2083 << A->getAsString(Args) << A->getValue();
2084 }
2085 }
2086
2087 if (const Arg *A = Args.getLastArg(OPT_mfunction_return_EQ)) {
2088 auto Val = llvm::StringSwitch<llvm::FunctionReturnThunksKind>(A->getValue())
2089 .Case("keep", llvm::FunctionReturnThunksKind::Keep)
2090 .Case("thunk-extern", llvm::FunctionReturnThunksKind::Extern)
2091 .Default(llvm::FunctionReturnThunksKind::Invalid);
2092 // SystemZ might want to add support for "expolines."
2093 if (!T.isX86())
2094 Diags.Report(diag::err_drv_argument_not_allowed_with)
2095 << A->getSpelling() << T.getTriple();
2096 else if (Val == llvm::FunctionReturnThunksKind::Invalid)
2097 Diags.Report(diag::err_drv_invalid_value)
2098 << A->getAsString(Args) << A->getValue();
2099 else if (Val == llvm::FunctionReturnThunksKind::Extern &&
2100 Args.getLastArgValue(OPT_mcmodel_EQ) == "large")
2101 Diags.Report(diag::err_drv_argument_not_allowed_with)
2102 << A->getAsString(Args)
2103 << Args.getLastArg(OPT_mcmodel_EQ)->getAsString(Args);
2104 else
2105 Opts.FunctionReturnThunks = static_cast<unsigned>(Val);
2106 }
2107
2108 for (auto *A :
2109 Args.filtered(OPT_mlink_bitcode_file, OPT_mlink_builtin_bitcode)) {
2110 CodeGenOptions::BitcodeFileToLink F;
2111 F.Filename = A->getValue();
2112 if (A->getOption().matches(OPT_mlink_builtin_bitcode)) {
2113 F.LinkFlags = llvm::Linker::Flags::LinkOnlyNeeded;
2114 // When linking CUDA bitcode, propagate function attributes so that
2115 // e.g. libdevice gets fast-math attrs if we're building with fast-math.
2116 F.PropagateAttrs = true;
2117 F.Internalize = true;
2118 }
2119 Opts.LinkBitcodeFiles.push_back(F);
2120 }
2121
2122 if (Arg *A = Args.getLastArg(OPT_fdenormal_fp_math_EQ)) {
2123 StringRef Val = A->getValue();
2124 Opts.FPDenormalMode = llvm::parseDenormalFPAttribute(Val);
2125 Opts.FP32DenormalMode = Opts.FPDenormalMode;
2126 if (!Opts.FPDenormalMode.isValid())
2127 Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;
2128 }
2129
2130 if (Arg *A = Args.getLastArg(OPT_fdenormal_fp_math_f32_EQ)) {
2131 StringRef Val = A->getValue();
2132 Opts.FP32DenormalMode = llvm::parseDenormalFPAttribute(Val);
2133 if (!Opts.FP32DenormalMode.isValid())
2134 Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;
2135 }
2136
2137 // X86_32 has -fppc-struct-return and -freg-struct-return.
2138 // PPC32 has -maix-struct-return and -msvr4-struct-return.
2139 if (Arg *A =
2140 Args.getLastArg(OPT_fpcc_struct_return, OPT_freg_struct_return,
2141 OPT_maix_struct_return, OPT_msvr4_struct_return)) {
2142 // TODO: We might want to consider enabling these options on AIX in the
2143 // future.
2144 if (T.isOSAIX())
2145 Diags.Report(diag::err_drv_unsupported_opt_for_target)
2146 << A->getSpelling() << T.str();
2147
2148 const Option &O = A->getOption();
2149 if (O.matches(OPT_fpcc_struct_return) ||
2150 O.matches(OPT_maix_struct_return)) {
2151 Opts.setStructReturnConvention(CodeGenOptions::SRCK_OnStack);
2152 } else {
2153 assert(O.matches(OPT_freg_struct_return) ||
2154 O.matches(OPT_msvr4_struct_return));
2155 Opts.setStructReturnConvention(CodeGenOptions::SRCK_InRegs);
2156 }
2157 }
2158
2159 if (Arg *A = Args.getLastArg(OPT_mxcoff_roptr)) {
2160 if (!T.isOSAIX())
2161 Diags.Report(diag::err_drv_unsupported_opt_for_target)
2162 << A->getSpelling() << T.str();
2163
2164 // Since the storage mapping class is specified per csect,
2165 // without using data sections, it is less effective to use read-only
2166 // pointers. Using read-only pointers may cause other RO variables in the
2167 // same csect to become RW when the linker acts upon `-bforceimprw`;
2168 // therefore, we require that separate data sections
2169 // are used when `-mxcoff-roptr` is in effect. We respect the setting of
2170 // data-sections since we have not found reasons to do otherwise that
2171 // overcome the user surprise of not respecting the setting.
2172 if (!Args.hasFlag(OPT_fdata_sections, OPT_fno_data_sections, false))
2173 Diags.Report(diag::err_roptr_requires_data_sections);
2174
2175 Opts.XCOFFReadOnlyPointers = true;
2176 }
2177
2178 if (Arg *A = Args.getLastArg(OPT_mabi_EQ_quadword_atomics)) {
2179 if (!T.isOSAIX() || T.isPPC32())
2180 Diags.Report(diag::err_drv_unsupported_opt_for_target)
2181 << A->getSpelling() << T.str();
2182 }
2183
2184 bool NeedLocTracking = false;
2185
2186 if (!Opts.OptRecordFile.empty())
2187 NeedLocTracking = true;
2188
2189 if (Arg *A = Args.getLastArg(OPT_opt_record_passes)) {
2190 Opts.OptRecordPasses = A->getValue();
2191 NeedLocTracking = true;
2192 }
2193
2194 if (Arg *A = Args.getLastArg(OPT_opt_record_format)) {
2195 Opts.OptRecordFormat = A->getValue();
2196 NeedLocTracking = true;
2197 }
2198
2199 Opts.OptimizationRemark =
2200 ParseOptimizationRemark(Diags, Args, OPT_Rpass_EQ, "pass");
2201
2203 ParseOptimizationRemark(Diags, Args, OPT_Rpass_missed_EQ, "pass-missed");
2204
2206 Diags, Args, OPT_Rpass_analysis_EQ, "pass-analysis");
2207
2208 NeedLocTracking |= Opts.OptimizationRemark.hasValidPattern() ||
2211
2212 bool UsingSampleProfile = !Opts.SampleProfileFile.empty();
2213 bool UsingProfile =
2214 UsingSampleProfile || !Opts.ProfileInstrumentUsePath.empty();
2215
2216 if (Opts.DiagnosticsWithHotness && !UsingProfile &&
2217 // An IR file will contain PGO as metadata
2219 Diags.Report(diag::warn_drv_diagnostics_hotness_requires_pgo)
2220 << "-fdiagnostics-show-hotness";
2221
2222 // Parse remarks hotness threshold. Valid value is either integer or 'auto'.
2223 if (auto *arg =
2224 Args.getLastArg(options::OPT_fdiagnostics_hotness_threshold_EQ)) {
2225 auto ResultOrErr =
2226 llvm::remarks::parseHotnessThresholdOption(arg->getValue());
2227
2228 if (!ResultOrErr) {
2229 Diags.Report(diag::err_drv_invalid_diagnotics_hotness_threshold)
2230 << "-fdiagnostics-hotness-threshold=";
2231 } else {
2232 Opts.DiagnosticsHotnessThreshold = *ResultOrErr;
2233 if ((!Opts.DiagnosticsHotnessThreshold ||
2234 *Opts.DiagnosticsHotnessThreshold > 0) &&
2235 !UsingProfile)
2236 Diags.Report(diag::warn_drv_diagnostics_hotness_requires_pgo)
2237 << "-fdiagnostics-hotness-threshold=";
2238 }
2239 }
2240
2241 if (auto *arg =
2242 Args.getLastArg(options::OPT_fdiagnostics_misexpect_tolerance_EQ)) {
2243 auto ResultOrErr = parseToleranceOption(arg->getValue());
2244
2245 if (!ResultOrErr) {
2246 Diags.Report(diag::err_drv_invalid_diagnotics_misexpect_tolerance)
2247 << "-fdiagnostics-misexpect-tolerance=";
2248 } else {
2249 Opts.DiagnosticsMisExpectTolerance = *ResultOrErr;
2250 if ((!Opts.DiagnosticsMisExpectTolerance ||
2251 *Opts.DiagnosticsMisExpectTolerance > 0) &&
2252 !UsingProfile)
2253 Diags.Report(diag::warn_drv_diagnostics_misexpect_requires_pgo)
2254 << "-fdiagnostics-misexpect-tolerance=";
2255 }
2256 }
2257
2258 // If the user requested to use a sample profile for PGO, then the
2259 // backend will need to track source location information so the profile
2260 // can be incorporated into the IR.
2261 if (UsingSampleProfile)
2262 NeedLocTracking = true;
2263
2264 if (!Opts.StackUsageFile.empty())
2265 NeedLocTracking = true;
2266
2267 // If the user requested a flag that requires source locations available in
2268 // the backend, make sure that the backend tracks source location information.
2269 if (NeedLocTracking &&
2270 Opts.getDebugInfo() == llvm::codegenoptions::NoDebugInfo)
2271 Opts.setDebugInfo(llvm::codegenoptions::LocTrackingOnly);
2272
2273 // Parse -fsanitize-recover= arguments.
2274 // FIXME: Report unrecoverable sanitizers incorrectly specified here.
2275 parseSanitizerKinds("-fsanitize-recover=",
2276 Args.getAllArgValues(OPT_fsanitize_recover_EQ), Diags,
2277 Opts.SanitizeRecover);
2278 parseSanitizerKinds("-fsanitize-trap=",
2279 Args.getAllArgValues(OPT_fsanitize_trap_EQ), Diags,
2280 Opts.SanitizeTrap);
2281 parseSanitizerKinds("-fsanitize-merge=",
2282 Args.getAllArgValues(OPT_fsanitize_merge_handlers_EQ),
2283 Diags, Opts.SanitizeMergeHandlers);
2284
2285 // Parse -fsanitize-skip-hot-cutoff= arguments.
2287 "-fsanitize-skip-hot-cutoff=",
2288 Args.getAllArgValues(OPT_fsanitize_skip_hot_cutoff_EQ), Diags);
2289
2291 "-fsanitize-annotate-debug-info=",
2292 Args.getAllArgValues(OPT_fsanitize_annotate_debug_info_EQ), Diags,
2294
2295 if (StringRef V =
2296 Args.getLastArgValue(OPT_fallow_runtime_check_skip_hot_cutoff_EQ);
2297 !V.empty()) {
2298 double A;
2299 if (V.getAsDouble(A) || A < 0.0 || A > 1.0) {
2300 Diags.Report(diag::err_drv_invalid_value)
2301 << "-fallow-runtime-check-skip-hot-cutoff=" << V;
2302 } else {
2304 }
2305 }
2306
2307 Opts.EmitVersionIdentMetadata = Args.hasFlag(OPT_Qy, OPT_Qn, true);
2308
2309 if (!LangOpts->CUDAIsDevice)
2311
2312 if (Args.hasArg(options::OPT_ffinite_loops))
2313 Opts.FiniteLoops = CodeGenOptions::FiniteLoopsKind::Always;
2314 else if (Args.hasArg(options::OPT_fno_finite_loops))
2315 Opts.FiniteLoops = CodeGenOptions::FiniteLoopsKind::Never;
2316
2317 Opts.EmitIEEENaNCompliantInsts = Args.hasFlag(
2318 options::OPT_mamdgpu_ieee, options::OPT_mno_amdgpu_ieee, true);
2319 if (!Opts.EmitIEEENaNCompliantInsts && !LangOptsRef.NoHonorNaNs)
2320 Diags.Report(diag::err_drv_amdgpu_ieee_without_no_honor_nans);
2321
2322 Opts.StaticClosure = Args.hasArg(options::OPT_static_libclosure);
2323
2324 return Diags.getNumErrors() == NumErrorsBefore;
2325}
2326
2328 ArgumentConsumer Consumer) {
2329 const DependencyOutputOptions &DependencyOutputOpts = Opts;
2330#define DEPENDENCY_OUTPUT_OPTION_WITH_MARSHALLING(...) \
2331 GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
2332#include "clang/Options/Options.inc"
2333#undef DEPENDENCY_OUTPUT_OPTION_WITH_MARSHALLING
2334
2336 GenerateArg(Consumer, OPT_show_includes);
2337
2338 for (const auto &Dep : Opts.ExtraDeps) {
2339 switch (Dep.second) {
2341 // Sanitizer ignorelist arguments are generated from LanguageOptions.
2342 continue;
2343 case EDK_ModuleFile:
2344 // Module file arguments are generated from FrontendOptions and
2345 // HeaderSearchOptions.
2346 continue;
2347 case EDK_ProfileList:
2348 // Profile list arguments are generated from LanguageOptions via the
2349 // marshalling infrastructure.
2350 continue;
2351 case EDK_DepFileEntry:
2352 GenerateArg(Consumer, OPT_fdepfile_entry, Dep.first);
2353 break;
2354 }
2355 }
2356}
2357
2359 ArgList &Args, DiagnosticsEngine &Diags,
2360 frontend::ActionKind Action,
2361 bool ShowLineMarkers) {
2362 unsigned NumErrorsBefore = Diags.getNumErrors();
2363
2364 DependencyOutputOptions &DependencyOutputOpts = Opts;
2365#define DEPENDENCY_OUTPUT_OPTION_WITH_MARSHALLING(...) \
2366 PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
2367#include "clang/Options/Options.inc"
2368#undef DEPENDENCY_OUTPUT_OPTION_WITH_MARSHALLING
2369
2370 if (Args.hasArg(OPT_show_includes)) {
2371 // Writing both /showIncludes and preprocessor output to stdout
2372 // would produce interleaved output, so use stderr for /showIncludes.
2373 // This behaves the same as cl.exe, when /E, /EP or /P are passed.
2374 if (Action == frontend::PrintPreprocessedInput || !ShowLineMarkers)
2376 else
2378 } else {
2380 }
2381
2382 // Add sanitizer ignorelists as extra dependencies.
2383 // They won't be discovered by the regular preprocessor, so
2384 // we let make / ninja to know about this implicit dependency.
2385 if (!Args.hasArg(OPT_fno_sanitize_ignorelist)) {
2386 for (const auto *A : Args.filtered(OPT_fsanitize_ignorelist_EQ)) {
2387 StringRef Val = A->getValue();
2388 if (!Val.contains('='))
2389 Opts.ExtraDeps.emplace_back(std::string(Val), EDK_SanitizeIgnorelist);
2390 }
2391 if (Opts.IncludeSystemHeaders) {
2392 for (const auto *A : Args.filtered(OPT_fsanitize_system_ignorelist_EQ)) {
2393 StringRef Val = A->getValue();
2394 if (!Val.contains('='))
2395 Opts.ExtraDeps.emplace_back(std::string(Val), EDK_SanitizeIgnorelist);
2396 }
2397 }
2398 }
2399
2400 // -fprofile-list= dependencies.
2401 for (const auto &Filename : Args.getAllArgValues(OPT_fprofile_list_EQ))
2402 Opts.ExtraDeps.emplace_back(Filename, EDK_ProfileList);
2403
2404 // Propagate the extra dependencies.
2405 for (const auto *A : Args.filtered(OPT_fdepfile_entry))
2406 Opts.ExtraDeps.emplace_back(A->getValue(), EDK_DepFileEntry);
2407
2408 // Only the -fmodule-file=<file> form.
2409 for (const auto *A : Args.filtered(OPT_fmodule_file)) {
2410 StringRef Val = A->getValue();
2411 if (!Val.contains('='))
2412 Opts.ExtraDeps.emplace_back(std::string(Val), EDK_ModuleFile);
2413 }
2414
2415 // Check for invalid combinations of header-include-format
2416 // and header-include-filtering.
2417 if (Opts.HeaderIncludeFormat == HIFMT_Textual &&
2419 if (Args.hasArg(OPT_header_include_format_EQ))
2420 Diags.Report(diag::err_drv_print_header_cc1_invalid_combination)
2423 else
2424 Diags.Report(diag::err_drv_print_header_cc1_invalid_filtering)
2426 } else if (Opts.HeaderIncludeFormat == HIFMT_JSON &&
2428 if (Args.hasArg(OPT_header_include_filtering_EQ))
2429 Diags.Report(diag::err_drv_print_header_cc1_invalid_combination)
2432 else
2433 Diags.Report(diag::err_drv_print_header_cc1_invalid_format)
2435 }
2436
2437 return Diags.getNumErrors() == NumErrorsBefore;
2438}
2439
2440static bool parseShowColorsArgs(const ArgList &Args, bool DefaultColor) {
2441 // Color diagnostics default to auto ("on" if terminal supports) in the driver
2442 // but default to off in cc1, needing an explicit OPT_fdiagnostics_color.
2443 // Support both clang's -f[no-]color-diagnostics and gcc's
2444 // -f[no-]diagnostics-colors[=never|always|auto].
2445 enum {
2446 Colors_On,
2447 Colors_Off,
2448 Colors_Auto
2449 } ShowColors = DefaultColor ? Colors_Auto : Colors_Off;
2450 for (auto *A : Args) {
2451 const Option &O = A->getOption();
2452 if (O.matches(options::OPT_fcolor_diagnostics)) {
2453 ShowColors = Colors_On;
2454 } else if (O.matches(options::OPT_fno_color_diagnostics)) {
2455 ShowColors = Colors_Off;
2456 } else if (O.matches(options::OPT_fdiagnostics_color_EQ)) {
2457 StringRef Value(A->getValue());
2458 if (Value == "always")
2459 ShowColors = Colors_On;
2460 else if (Value == "never")
2461 ShowColors = Colors_Off;
2462 else if (Value == "auto")
2463 ShowColors = Colors_Auto;
2464 }
2465 }
2466 return ShowColors == Colors_On ||
2467 (ShowColors == Colors_Auto &&
2468 llvm::sys::Process::StandardErrHasColors());
2469}
2470
2471static bool checkVerifyPrefixes(const std::vector<std::string> &VerifyPrefixes,
2472 DiagnosticsEngine &Diags) {
2473 bool Success = true;
2474 for (const auto &Prefix : VerifyPrefixes) {
2475 // Every prefix must start with a letter and contain only alphanumeric
2476 // characters, hyphens, and underscores.
2477 auto BadChar = llvm::find_if(Prefix, [](char C) {
2478 return !isAlphanumeric(C) && C != '-' && C != '_';
2479 });
2480 if (BadChar != Prefix.end() || !isLetter(Prefix[0])) {
2481 Success = false;
2482 Diags.Report(diag::err_drv_invalid_value) << "-verify=" << Prefix;
2483 Diags.Report(diag::note_drv_verify_prefix_spelling);
2484 }
2485 }
2486 return Success;
2487}
2488
2490 ArgumentConsumer Consumer) {
2491 const FileSystemOptions &FileSystemOpts = Opts;
2492
2493#define FILE_SYSTEM_OPTION_WITH_MARSHALLING(...) \
2494 GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
2495#include "clang/Options/Options.inc"
2496#undef FILE_SYSTEM_OPTION_WITH_MARSHALLING
2497}
2498
2499static bool ParseFileSystemArgs(FileSystemOptions &Opts, const ArgList &Args,
2500 DiagnosticsEngine &Diags) {
2501 unsigned NumErrorsBefore = Diags.getNumErrors();
2502
2503 FileSystemOptions &FileSystemOpts = Opts;
2504
2505#define FILE_SYSTEM_OPTION_WITH_MARSHALLING(...) \
2506 PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
2507#include "clang/Options/Options.inc"
2508#undef FILE_SYSTEM_OPTION_WITH_MARSHALLING
2509
2510 return Diags.getNumErrors() == NumErrorsBefore;
2511}
2512
2514 ArgumentConsumer Consumer) {
2515 const MigratorOptions &MigratorOpts = Opts;
2516#define MIGRATOR_OPTION_WITH_MARSHALLING(...) \
2517 GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
2518#include "clang/Options/Options.inc"
2519#undef MIGRATOR_OPTION_WITH_MARSHALLING
2520}
2521
2522static bool ParseMigratorArgs(MigratorOptions &Opts, const ArgList &Args,
2523 DiagnosticsEngine &Diags) {
2524 unsigned NumErrorsBefore = Diags.getNumErrors();
2525
2526 MigratorOptions &MigratorOpts = Opts;
2527
2528#define MIGRATOR_OPTION_WITH_MARSHALLING(...) \
2529 PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
2530#include "clang/Options/Options.inc"
2531#undef MIGRATOR_OPTION_WITH_MARSHALLING
2532
2533 return Diags.getNumErrors() == NumErrorsBefore;
2534}
2535
2536void CompilerInvocationBase::GenerateDiagnosticArgs(
2537 const DiagnosticOptions &Opts, ArgumentConsumer Consumer,
2538 bool DefaultDiagColor) {
2539 const DiagnosticOptions *DiagnosticOpts = &Opts;
2540#define DIAG_OPTION_WITH_MARSHALLING(...) \
2541 GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
2542#include "clang/Options/Options.inc"
2543#undef DIAG_OPTION_WITH_MARSHALLING
2544
2545 if (!Opts.DiagnosticSerializationFile.empty())
2546 GenerateArg(Consumer, OPT_diagnostic_serialized_file,
2548
2549 if (Opts.ShowColors)
2550 GenerateArg(Consumer, OPT_fcolor_diagnostics);
2551
2552 if (Opts.VerifyDiagnostics &&
2553 llvm::is_contained(Opts.VerifyPrefixes, "expected"))
2554 GenerateArg(Consumer, OPT_verify);
2555
2556 for (const auto &Prefix : Opts.VerifyPrefixes)
2557 if (Prefix != "expected")
2558 GenerateArg(Consumer, OPT_verify_EQ, Prefix);
2559
2560 if (Opts.VerifyDirectives) {
2561 GenerateArg(Consumer, OPT_verify_directives);
2562 }
2563
2564 DiagnosticLevelMask VIU = Opts.getVerifyIgnoreUnexpected();
2565 if (VIU == DiagnosticLevelMask::None) {
2566 // This is the default, don't generate anything.
2567 } else if (VIU == DiagnosticLevelMask::All) {
2568 GenerateArg(Consumer, OPT_verify_ignore_unexpected);
2569 } else {
2570 if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Note) != 0)
2571 GenerateArg(Consumer, OPT_verify_ignore_unexpected_EQ, "note");
2572 if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Remark) != 0)
2573 GenerateArg(Consumer, OPT_verify_ignore_unexpected_EQ, "remark");
2574 if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Warning) != 0)
2575 GenerateArg(Consumer, OPT_verify_ignore_unexpected_EQ, "warning");
2576 if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Error) != 0)
2577 GenerateArg(Consumer, OPT_verify_ignore_unexpected_EQ, "error");
2578 }
2579
2580 for (const auto &Warning : Opts.Warnings) {
2581 // This option is automatically generated from UndefPrefixes.
2582 if (Warning == "undef-prefix")
2583 continue;
2584 // This option is automatically generated from CheckConstexprFunctionBodies.
2585 if (Warning == "invalid-constexpr" || Warning == "no-invalid-constexpr")
2586 continue;
2587 Consumer(StringRef("-W") + Warning);
2588 }
2589
2590 for (const auto &Remark : Opts.Remarks) {
2591 // These arguments are generated from OptimizationRemark fields of
2592 // CodeGenOptions.
2593 StringRef IgnoredRemarks[] = {"pass", "no-pass",
2594 "pass-analysis", "no-pass-analysis",
2595 "pass-missed", "no-pass-missed"};
2596 if (llvm::is_contained(IgnoredRemarks, Remark))
2597 continue;
2598
2599 Consumer(StringRef("-R") + Remark);
2600 }
2601
2602 if (!Opts.DiagnosticSuppressionMappingsFile.empty()) {
2603 GenerateArg(Consumer, OPT_warning_suppression_mappings_EQ,
2605 }
2606}
2607
2608std::unique_ptr<DiagnosticOptions>
2610 auto DiagOpts = std::make_unique<DiagnosticOptions>();
2611 unsigned MissingArgIndex, MissingArgCount;
2612 InputArgList Args = getDriverOptTable().ParseArgs(
2613 Argv.slice(1), MissingArgIndex, MissingArgCount);
2614
2615 bool ShowColors = true;
2616 if (std::optional<std::string> NoColor =
2617 llvm::sys::Process::GetEnv("NO_COLOR");
2618 NoColor && !NoColor->empty()) {
2619 // If the user set the NO_COLOR environment variable, we'll honor that
2620 // unless the command line overrides it.
2621 ShowColors = false;
2622 }
2623
2624 // We ignore MissingArgCount and the return value of ParseDiagnosticArgs.
2625 // Any errors that would be diagnosed here will also be diagnosed later,
2626 // when the DiagnosticsEngine actually exists.
2627 (void)ParseDiagnosticArgs(*DiagOpts, Args, /*Diags=*/nullptr, ShowColors);
2628 return DiagOpts;
2629}
2630
2631bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
2632 DiagnosticsEngine *Diags,
2633 bool DefaultDiagColor) {
2634 std::optional<DiagnosticOptions> IgnoringDiagOpts;
2635 std::optional<DiagnosticsEngine> IgnoringDiags;
2636 if (!Diags) {
2637 IgnoringDiagOpts.emplace();
2638 IgnoringDiags.emplace(DiagnosticIDs::create(), *IgnoringDiagOpts,
2639 new IgnoringDiagConsumer());
2640 Diags = &*IgnoringDiags;
2641 }
2642
2643 unsigned NumErrorsBefore = Diags->getNumErrors();
2644
2645 // The key paths of diagnostic options defined in Options.td start with
2646 // "DiagnosticOpts->". Let's provide the expected variable name and type.
2647 DiagnosticOptions *DiagnosticOpts = &Opts;
2648
2649#define DIAG_OPTION_WITH_MARSHALLING(...) \
2650 PARSE_OPTION_WITH_MARSHALLING(Args, *Diags, __VA_ARGS__)
2651#include "clang/Options/Options.inc"
2652#undef DIAG_OPTION_WITH_MARSHALLING
2653
2654 llvm::sys::Process::UseANSIEscapeCodes(Opts.UseANSIEscapeCodes);
2655
2656 if (Arg *A =
2657 Args.getLastArg(OPT_diagnostic_serialized_file, OPT__serialize_diags))
2658 Opts.DiagnosticSerializationFile = A->getValue();
2659 Opts.ShowColors = parseShowColorsArgs(Args, DefaultDiagColor);
2660
2661 Opts.VerifyDiagnostics = Args.hasArg(OPT_verify) || Args.hasArg(OPT_verify_EQ);
2662 Opts.VerifyDirectives = Args.hasArg(OPT_verify_directives);
2663 Opts.VerifyPrefixes = Args.getAllArgValues(OPT_verify_EQ);
2664 if (Args.hasArg(OPT_verify))
2665 Opts.VerifyPrefixes.push_back("expected");
2666 // Keep VerifyPrefixes in its original order for the sake of diagnostics, and
2667 // then sort it to prepare for fast lookup using std::binary_search.
2668 if (!checkVerifyPrefixes(Opts.VerifyPrefixes, *Diags))
2669 Opts.VerifyDiagnostics = false;
2670 else
2671 llvm::sort(Opts.VerifyPrefixes);
2674 "-verify-ignore-unexpected=",
2675 Args.getAllArgValues(OPT_verify_ignore_unexpected_EQ), *Diags, DiagMask);
2676 if (Args.hasArg(OPT_verify_ignore_unexpected))
2677 DiagMask = DiagnosticLevelMask::All;
2678 Opts.setVerifyIgnoreUnexpected(DiagMask);
2679 if (Opts.TabStop == 0 || Opts.TabStop > DiagnosticOptions::MaxTabStop) {
2680 Diags->Report(diag::warn_ignoring_ftabstop_value)
2681 << Opts.TabStop << DiagnosticOptions::DefaultTabStop;
2682 Opts.TabStop = DiagnosticOptions::DefaultTabStop;
2683 }
2684
2685 if (const Arg *A = Args.getLastArg(OPT_warning_suppression_mappings_EQ))
2686 Opts.DiagnosticSuppressionMappingsFile = A->getValue();
2687
2688 addDiagnosticArgs(Args, OPT_W_Group, OPT_W_value_Group, Opts.Warnings);
2689 addDiagnosticArgs(Args, OPT_R_Group, OPT_R_value_Group, Opts.Remarks);
2690
2691 return Diags->getNumErrors() == NumErrorsBefore;
2692}
2693
2694unsigned clang::getOptimizationLevel(const ArgList &Args, InputKind IK,
2695 DiagnosticsEngine &Diags) {
2696 unsigned DefaultOpt = 0;
2697 if ((IK.getLanguage() == Language::OpenCL ||
2699 !Args.hasArg(OPT_cl_opt_disable))
2700 DefaultOpt = 2;
2701
2702 if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
2703 if (A->getOption().matches(options::OPT_O0))
2704 return 0;
2705
2706 if (A->getOption().matches(options::OPT_Ofast))
2707 return 3;
2708
2709 assert(A->getOption().matches(options::OPT_O));
2710
2711 StringRef S(A->getValue());
2712 if (S == "s" || S == "z")
2713 return 2;
2714
2715 if (S == "g")
2716 return 1;
2717
2718 DefaultOpt = getLastArgIntValue(Args, OPT_O, DefaultOpt, Diags);
2719 }
2720
2721 unsigned MaxOptLevel = 3;
2722 if (DefaultOpt > MaxOptLevel) {
2723 // If the optimization level is not supported, fall back on the default
2724 // optimization
2725 Diags.Report(diag::warn_drv_optimization_value)
2726 << Args.getLastArg(OPT_O)->getAsString(Args) << "-O" << MaxOptLevel;
2727 DefaultOpt = MaxOptLevel;
2728 }
2729
2730 return DefaultOpt;
2731}
2732
2733unsigned clang::getOptimizationLevelSize(const ArgList &Args) {
2734 if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
2735 if (A->getOption().matches(options::OPT_O)) {
2736 switch (A->getValue()[0]) {
2737 default:
2738 return 0;
2739 case 's':
2740 return 1;
2741 case 'z':
2742 return 2;
2743 }
2744 }
2745 }
2746 return 0;
2747}
2748
2749/// Parse the argument to the -ftest-module-file-extension
2750/// command-line argument.
2751///
2752/// \returns true on error, false on success.
2753static bool parseTestModuleFileExtensionArg(StringRef Arg,
2754 std::string &BlockName,
2755 unsigned &MajorVersion,
2756 unsigned &MinorVersion,
2757 bool &Hashed,
2758 std::string &UserInfo) {
2760 Arg.split(Args, ':', 5);
2761 if (Args.size() < 5)
2762 return true;
2763
2764 BlockName = std::string(Args[0]);
2765 if (Args[1].getAsInteger(10, MajorVersion)) return true;
2766 if (Args[2].getAsInteger(10, MinorVersion)) return true;
2767 if (Args[3].getAsInteger(2, Hashed)) return true;
2768 if (Args.size() > 4)
2769 UserInfo = std::string(Args[4]);
2770 return false;
2771}
2772
2773/// Return a table that associates command line option specifiers with the
2774/// frontend action. Note: The pair {frontend::PluginAction, OPT_plugin} is
2775/// intentionally missing, as this case is handled separately from other
2776/// frontend options.
2777static const auto &getFrontendActionTable() {
2778 static const std::pair<frontend::ActionKind, unsigned> Table[] = {
2779 {frontend::ASTDeclList, OPT_ast_list},
2780
2781 {frontend::ASTDump, OPT_ast_dump_all_EQ},
2782 {frontend::ASTDump, OPT_ast_dump_all},
2783 {frontend::ASTDump, OPT_ast_dump_EQ},
2784 {frontend::ASTDump, OPT_ast_dump},
2785 {frontend::ASTDump, OPT_ast_dump_lookups},
2786 {frontend::ASTDump, OPT_ast_dump_decl_types},
2787
2788 {frontend::ASTPrint, OPT_ast_print},
2789 {frontend::ASTView, OPT_ast_view},
2790 {frontend::DumpCompilerOptions, OPT_compiler_options_dump},
2791 {frontend::DumpRawTokens, OPT_dump_raw_tokens},
2792 {frontend::DumpTokens, OPT_dump_tokens},
2793 {frontend::EmitAssembly, OPT_S},
2794 {frontend::EmitBC, OPT_emit_llvm_bc},
2795 {frontend::EmitCIR, OPT_emit_cir},
2796 {frontend::EmitHTML, OPT_emit_html},
2797 {frontend::EmitLLVM, OPT_emit_llvm},
2798 {frontend::EmitLLVMOnly, OPT_emit_llvm_only},
2799 {frontend::EmitCodeGenOnly, OPT_emit_codegen_only},
2800 {frontend::EmitObj, OPT_emit_obj},
2801 {frontend::ExtractAPI, OPT_extract_api},
2802
2803 {frontend::FixIt, OPT_fixit_EQ},
2804 {frontend::FixIt, OPT_fixit},
2805
2806 {frontend::GenerateModule, OPT_emit_module},
2807 {frontend::GenerateModuleInterface, OPT_emit_module_interface},
2809 OPT_emit_reduced_module_interface},
2810 {frontend::GenerateHeaderUnit, OPT_emit_header_unit},
2811 {frontend::GeneratePCH, OPT_emit_pch},
2812 {frontend::GenerateInterfaceStubs, OPT_emit_interface_stubs},
2813 {frontend::InitOnly, OPT_init_only},
2814 {frontend::ParseSyntaxOnly, OPT_fsyntax_only},
2815 {frontend::ModuleFileInfo, OPT_module_file_info},
2816 {frontend::VerifyPCH, OPT_verify_pch},
2817 {frontend::PrintPreamble, OPT_print_preamble},
2819 {frontend::TemplightDump, OPT_templight_dump},
2820 {frontend::RewriteMacros, OPT_rewrite_macros},
2821 {frontend::RewriteObjC, OPT_rewrite_objc},
2822 {frontend::RewriteTest, OPT_rewrite_test},
2823 {frontend::RunAnalysis, OPT_analyze},
2824 {frontend::RunPreprocessorOnly, OPT_Eonly},
2826 OPT_print_dependency_directives_minimized_source},
2827 };
2828
2829 return Table;
2830}
2831
2832/// Maps command line option to frontend action.
2833static std::optional<frontend::ActionKind>
2834getFrontendAction(OptSpecifier &Opt) {
2835 for (const auto &ActionOpt : getFrontendActionTable())
2836 if (ActionOpt.second == Opt.getID())
2837 return ActionOpt.first;
2838
2839 return std::nullopt;
2840}
2841
2842/// Maps frontend action to command line option.
2843static std::optional<OptSpecifier>
2845 for (const auto &ActionOpt : getFrontendActionTable())
2846 if (ActionOpt.first == ProgramAction)
2847 return OptSpecifier(ActionOpt.second);
2848
2849 return std::nullopt;
2850}
2851
2853 ArgumentConsumer Consumer, bool IsHeader) {
2854 const FrontendOptions &FrontendOpts = Opts;
2855#define FRONTEND_OPTION_WITH_MARSHALLING(...) \
2856 GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
2857#include "clang/Options/Options.inc"
2858#undef FRONTEND_OPTION_WITH_MARSHALLING
2859
2860 std::optional<OptSpecifier> ProgramActionOpt =
2862
2863 // Generating a simple flag covers most frontend actions.
2864 std::function<void()> GenerateProgramAction = [&]() {
2865 GenerateArg(Consumer, *ProgramActionOpt);
2866 };
2867
2868 if (!ProgramActionOpt) {
2869 // PluginAction is the only program action handled separately.
2870 assert(Opts.ProgramAction == frontend::PluginAction &&
2871 "Frontend action without option.");
2872 GenerateProgramAction = [&]() {
2873 GenerateArg(Consumer, OPT_plugin, Opts.ActionName);
2874 };
2875 }
2876
2877 // FIXME: Simplify the complex 'AST dump' command line.
2878 if (Opts.ProgramAction == frontend::ASTDump) {
2879 GenerateProgramAction = [&]() {
2880 // ASTDumpLookups, ASTDumpDeclTypes and ASTDumpFilter are generated via
2881 // marshalling infrastructure.
2882
2883 if (Opts.ASTDumpFormat != ADOF_Default) {
2884 StringRef Format;
2885 switch (Opts.ASTDumpFormat) {
2886 case ADOF_Default:
2887 llvm_unreachable("Default AST dump format.");
2888 case ADOF_JSON:
2889 Format = "json";
2890 break;
2891 }
2892
2893 if (Opts.ASTDumpAll)
2894 GenerateArg(Consumer, OPT_ast_dump_all_EQ, Format);
2895 if (Opts.ASTDumpDecls)
2896 GenerateArg(Consumer, OPT_ast_dump_EQ, Format);
2897 } else {
2898 if (Opts.ASTDumpAll)
2899 GenerateArg(Consumer, OPT_ast_dump_all);
2900 if (Opts.ASTDumpDecls)
2901 GenerateArg(Consumer, OPT_ast_dump);
2902 }
2903 };
2904 }
2905
2906 if (Opts.ProgramAction == frontend::FixIt && !Opts.FixItSuffix.empty()) {
2907 GenerateProgramAction = [&]() {
2908 GenerateArg(Consumer, OPT_fixit_EQ, Opts.FixItSuffix);
2909 };
2910 }
2911
2912 GenerateProgramAction();
2913
2914 for (const auto &PluginArgs : Opts.PluginArgs) {
2915 Option Opt = getDriverOptTable().getOption(OPT_plugin_arg);
2916 for (const auto &PluginArg : PluginArgs.second)
2917 denormalizeString(Consumer,
2918 Opt.getPrefix() + Opt.getName() + PluginArgs.first,
2919 Opt.getKind(), 0, PluginArg);
2920 }
2921
2922 for (const auto &Ext : Opts.ModuleFileExtensions)
2923 if (auto *TestExt = dyn_cast_or_null<TestModuleFileExtension>(Ext.get()))
2924 GenerateArg(Consumer, OPT_ftest_module_file_extension_EQ, TestExt->str());
2925
2926 if (!Opts.CodeCompletionAt.FileName.empty())
2927 GenerateArg(Consumer, OPT_code_completion_at,
2928 Opts.CodeCompletionAt.ToString());
2929
2930 for (const auto &Plugin : Opts.Plugins)
2931 GenerateArg(Consumer, OPT_load, Plugin);
2932
2933 // ASTDumpDecls and ASTDumpAll already handled with ProgramAction.
2934
2935 for (const auto &ModuleFile : Opts.ModuleFiles)
2936 GenerateArg(Consumer, OPT_fmodule_file, ModuleFile);
2937
2938 if (Opts.AuxTargetCPU)
2939 GenerateArg(Consumer, OPT_aux_target_cpu, *Opts.AuxTargetCPU);
2940
2941 if (Opts.AuxTargetFeatures)
2942 for (const auto &Feature : *Opts.AuxTargetFeatures)
2943 GenerateArg(Consumer, OPT_aux_target_feature, Feature);
2944
2945 {
2946 StringRef Preprocessed = Opts.DashX.isPreprocessed() ? "-cpp-output" : "";
2947 StringRef ModuleMap =
2948 Opts.DashX.getFormat() == InputKind::ModuleMap ? "-module-map" : "";
2949 StringRef HeaderUnit = "";
2950 switch (Opts.DashX.getHeaderUnitKind()) {
2952 break;
2954 HeaderUnit = "-user";
2955 break;
2957 HeaderUnit = "-system";
2958 break;
2960 HeaderUnit = "-header-unit";
2961 break;
2962 }
2963 StringRef Header = IsHeader ? "-header" : "";
2964
2965 StringRef Lang;
2966 switch (Opts.DashX.getLanguage()) {
2967 case Language::C:
2968 Lang = "c";
2969 break;
2970 case Language::OpenCL:
2971 Lang = "cl";
2972 break;
2974 Lang = "clcpp";
2975 break;
2976 case Language::CUDA:
2977 Lang = "cuda";
2978 break;
2979 case Language::HIP:
2980 Lang = "hip";
2981 break;
2982 case Language::CXX:
2983 Lang = "c++";
2984 break;
2985 case Language::ObjC:
2986 Lang = "objective-c";
2987 break;
2988 case Language::ObjCXX:
2989 Lang = "objective-c++";
2990 break;
2991 case Language::Asm:
2992 Lang = "assembler-with-cpp";
2993 break;
2994 case Language::Unknown:
2995 assert(Opts.DashX.getFormat() == InputKind::Precompiled &&
2996 "Generating -x argument for unknown language (not precompiled).");
2997 Lang = "ast";
2998 break;
2999 case Language::LLVM_IR:
3000 Lang = "ir";
3001 break;
3002 case Language::HLSL:
3003 Lang = "hlsl";
3004 break;
3005 case Language::CIR:
3006 Lang = "cir";
3007 break;
3008 }
3009
3010 GenerateArg(Consumer, OPT_x,
3011 Lang + HeaderUnit + Header + ModuleMap + Preprocessed);
3012 }
3013
3014 // OPT_INPUT has a unique class, generate it directly.
3015 for (const auto &Input : Opts.Inputs)
3016 Consumer(Input.getFile());
3017}
3018
3019static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
3020 DiagnosticsEngine &Diags, bool &IsHeaderFile) {
3021 unsigned NumErrorsBefore = Diags.getNumErrors();
3022
3023 FrontendOptions &FrontendOpts = Opts;
3024
3025#define FRONTEND_OPTION_WITH_MARSHALLING(...) \
3026 PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
3027#include "clang/Options/Options.inc"
3028#undef FRONTEND_OPTION_WITH_MARSHALLING
3029
3031 if (const Arg *A = Args.getLastArg(OPT_Action_Group)) {
3032 OptSpecifier Opt = OptSpecifier(A->getOption().getID());
3033 std::optional<frontend::ActionKind> ProgramAction = getFrontendAction(Opt);
3034 assert(ProgramAction && "Option specifier not in Action_Group.");
3035
3036 if (ProgramAction == frontend::ASTDump &&
3037 (Opt == OPT_ast_dump_all_EQ || Opt == OPT_ast_dump_EQ)) {
3038 unsigned Val = llvm::StringSwitch<unsigned>(A->getValue())
3039 .CaseLower("default", ADOF_Default)
3040 .CaseLower("json", ADOF_JSON)
3041 .Default(std::numeric_limits<unsigned>::max());
3042
3043 if (Val != std::numeric_limits<unsigned>::max())
3044 Opts.ASTDumpFormat = static_cast<ASTDumpOutputFormat>(Val);
3045 else {
3046 Diags.Report(diag::err_drv_invalid_value)
3047 << A->getAsString(Args) << A->getValue();
3049 }
3050 }
3051
3052 if (ProgramAction == frontend::FixIt && Opt == OPT_fixit_EQ)
3053 Opts.FixItSuffix = A->getValue();
3054
3055 if (ProgramAction == frontend::GenerateInterfaceStubs) {
3056 StringRef ArgStr =
3057 Args.hasArg(OPT_interface_stub_version_EQ)
3058 ? Args.getLastArgValue(OPT_interface_stub_version_EQ)
3059 : "ifs-v1";
3060 if (ArgStr == "experimental-yaml-elf-v1" ||
3061 ArgStr == "experimental-ifs-v1" || ArgStr == "experimental-ifs-v2" ||
3062 ArgStr == "experimental-tapi-elf-v1") {
3063 std::string ErrorMessage =
3064 "Invalid interface stub format: " + ArgStr.str() +
3065 " is deprecated.";
3066 Diags.Report(diag::err_drv_invalid_value)
3067 << "Must specify a valid interface stub format type, ie: "
3068 "-interface-stub-version=ifs-v1"
3069 << ErrorMessage;
3070 ProgramAction = frontend::ParseSyntaxOnly;
3071 } else if (!ArgStr.starts_with("ifs-")) {
3072 std::string ErrorMessage =
3073 "Invalid interface stub format: " + ArgStr.str() + ".";
3074 Diags.Report(diag::err_drv_invalid_value)
3075 << "Must specify a valid interface stub format type, ie: "
3076 "-interface-stub-version=ifs-v1"
3077 << ErrorMessage;
3078 ProgramAction = frontend::ParseSyntaxOnly;
3079 }
3080 }
3081
3082 Opts.ProgramAction = *ProgramAction;
3083
3084 // Catch common mistakes when multiple actions are specified for cc1 (e.g.
3085 // -S -emit-llvm means -emit-llvm while -emit-llvm -S means -S). However, to
3086 // support driver `-c -Xclang ACTION` (-cc1 -emit-llvm file -main-file-name
3087 // X ACTION), we suppress the error when the two actions are separated by
3088 // -main-file-name.
3089 //
3090 // As an exception, accept composable -ast-dump*.
3091 if (!A->getSpelling().starts_with("-ast-dump")) {
3092 const Arg *SavedAction = nullptr;
3093 for (const Arg *AA :
3094 Args.filtered(OPT_Action_Group, OPT_main_file_name)) {
3095 if (AA->getOption().matches(OPT_main_file_name)) {
3096 SavedAction = nullptr;
3097 } else if (!SavedAction) {
3098 SavedAction = AA;
3099 } else {
3100 if (!A->getOption().matches(OPT_ast_dump_EQ))
3101 Diags.Report(diag::err_fe_invalid_multiple_actions)
3102 << SavedAction->getSpelling() << A->getSpelling();
3103 break;
3104 }
3105 }
3106 }
3107 }
3108
3109 if (const Arg* A = Args.getLastArg(OPT_plugin)) {
3110 Opts.Plugins.emplace_back(A->getValue(0));
3112 Opts.ActionName = A->getValue();
3113 }
3114 for (const auto *AA : Args.filtered(OPT_plugin_arg))
3115 Opts.PluginArgs[AA->getValue(0)].emplace_back(AA->getValue(1));
3116
3117 for (const std::string &Arg :
3118 Args.getAllArgValues(OPT_ftest_module_file_extension_EQ)) {
3119 std::string BlockName;
3120 unsigned MajorVersion;
3121 unsigned MinorVersion;
3122 bool Hashed;
3123 std::string UserInfo;
3124 if (parseTestModuleFileExtensionArg(Arg, BlockName, MajorVersion,
3125 MinorVersion, Hashed, UserInfo)) {
3126 Diags.Report(diag::err_test_module_file_extension_format) << Arg;
3127
3128 continue;
3129 }
3130
3131 // Add the testing module file extension.
3132 Opts.ModuleFileExtensions.push_back(
3133 std::make_shared<TestModuleFileExtension>(
3134 BlockName, MajorVersion, MinorVersion, Hashed, UserInfo));
3135 }
3136
3137 if (const Arg *A = Args.getLastArg(OPT_code_completion_at)) {
3138 Opts.CodeCompletionAt =
3139 ParsedSourceLocation::FromString(A->getValue());
3140 if (Opts.CodeCompletionAt.FileName.empty()) {
3141 Diags.Report(diag::err_drv_invalid_value)
3142 << A->getAsString(Args) << A->getValue();
3143 Diags.Report(diag::note_command_line_code_loc_requirement);
3144 }
3145 }
3146
3147 Opts.Plugins = Args.getAllArgValues(OPT_load);
3148 Opts.ASTDumpDecls = Args.hasArg(OPT_ast_dump, OPT_ast_dump_EQ);
3149 Opts.ASTDumpAll = Args.hasArg(OPT_ast_dump_all, OPT_ast_dump_all_EQ);
3150 // Only the -fmodule-file=<file> form.
3151 for (const auto *A : Args.filtered(OPT_fmodule_file)) {
3152 StringRef Val = A->getValue();
3153 if (!Val.contains('='))
3154 Opts.ModuleFiles.push_back(std::string(Val));
3155 }
3156
3158 Diags.Report(diag::err_drv_argument_only_allowed_with) << "-fsystem-module"
3159 << "-emit-module";
3160 if (Args.hasArg(OPT_fclangir) || Args.hasArg(OPT_emit_cir))
3161 Opts.UseClangIRPipeline = true;
3162
3163#if CLANG_ENABLE_CIR
3164 if (Args.hasArg(OPT_clangir_disable_passes))
3165 Opts.ClangIRDisablePasses = true;
3166
3167 if (Args.hasArg(OPT_clangir_disable_verifier))
3168 Opts.ClangIRDisableCIRVerifier = true;
3169#endif // CLANG_ENABLE_CIR
3170
3171 if (Args.hasArg(OPT_aux_target_cpu))
3172 Opts.AuxTargetCPU = std::string(Args.getLastArgValue(OPT_aux_target_cpu));
3173 if (Args.hasArg(OPT_aux_target_feature))
3174 Opts.AuxTargetFeatures = Args.getAllArgValues(OPT_aux_target_feature);
3175
3177 if (const Arg *A = Args.getLastArg(OPT_x)) {
3178 StringRef XValue = A->getValue();
3179
3180 // Parse suffixes:
3181 // '<lang>(-[{header-unit,user,system}-]header|[-module-map][-cpp-output])'.
3182 // FIXME: Supporting '<lang>-header-cpp-output' would be useful.
3183 bool Preprocessed = XValue.consume_back("-cpp-output");
3184 bool ModuleMap = XValue.consume_back("-module-map");
3185 // Detect and consume the header indicator.
3186 bool IsHeader =
3187 XValue != "precompiled-header" && XValue.consume_back("-header");
3188
3189 // If we have c++-{user,system}-header, that indicates a header unit input
3190 // likewise, if the user put -fmodule-header together with a header with an
3191 // absolute path (header-unit-header).
3193 if (IsHeader || Preprocessed) {
3194 if (XValue.consume_back("-header-unit"))
3196 else if (XValue.consume_back("-system"))
3198 else if (XValue.consume_back("-user"))
3200 }
3201
3202 // The value set by this processing is an un-preprocessed source which is
3203 // not intended to be a module map or header unit.
3204 IsHeaderFile = IsHeader && !Preprocessed && !ModuleMap &&
3206
3207 // Principal languages.
3208 DashX = llvm::StringSwitch<InputKind>(XValue)
3209 .Case("c", Language::C)
3210 .Case("cl", Language::OpenCL)
3211 .Case("clcpp", Language::OpenCLCXX)
3212 .Case("cuda", Language::CUDA)
3213 .Case("hip", Language::HIP)
3214 .Case("c++", Language::CXX)
3215 .Case("objective-c", Language::ObjC)
3216 .Case("objective-c++", Language::ObjCXX)
3217 .Case("hlsl", Language::HLSL)
3218 .Default(Language::Unknown);
3219
3220 // "objc[++]-cpp-output" is an acceptable synonym for
3221 // "objective-c[++]-cpp-output".
3222 if (DashX.isUnknown() && Preprocessed && !IsHeaderFile && !ModuleMap &&
3224 DashX = llvm::StringSwitch<InputKind>(XValue)
3225 .Case("objc", Language::ObjC)
3226 .Case("objc++", Language::ObjCXX)
3227 .Default(Language::Unknown);
3228
3229 // Some special cases cannot be combined with suffixes.
3230 if (DashX.isUnknown() && !Preprocessed && !IsHeaderFile && !ModuleMap &&
3232 DashX = llvm::StringSwitch<InputKind>(XValue)
3233 .Case("cpp-output", InputKind(Language::C).getPreprocessed())
3234 .Case("assembler-with-cpp", Language::Asm)
3235 .Cases({"ast", "pcm", "precompiled-header"},
3237 .Case("ir", Language::LLVM_IR)
3238 .Case("cir", Language::CIR)
3239 .Default(Language::Unknown);
3240
3241 if (DashX.isUnknown())
3242 Diags.Report(diag::err_drv_invalid_value)
3243 << A->getAsString(Args) << A->getValue();
3244
3245 if (Preprocessed)
3246 DashX = DashX.getPreprocessed();
3247 // A regular header is considered mutually exclusive with a header unit.
3248 if (HUK != InputKind::HeaderUnit_None) {
3249 DashX = DashX.withHeaderUnit(HUK);
3250 IsHeaderFile = true;
3251 } else if (IsHeaderFile)
3252 DashX = DashX.getHeader();
3253 if (ModuleMap)
3254 DashX = DashX.withFormat(InputKind::ModuleMap);
3255 }
3256
3257 // '-' is the default input if none is given.
3258 std::vector<std::string> Inputs = Args.getAllArgValues(OPT_INPUT);
3259 Opts.Inputs.clear();
3260 if (Inputs.empty())
3261 Inputs.push_back("-");
3262
3264 Inputs.size() > 1)
3265 Diags.Report(diag::err_drv_header_unit_extra_inputs) << Inputs[1];
3266
3267 for (unsigned i = 0, e = Inputs.size(); i != e; ++i) {
3268 InputKind IK = DashX;
3269 if (IK.isUnknown()) {
3271 StringRef(Inputs[i]).rsplit('.').second);
3272 // FIXME: Warn on this?
3273 if (IK.isUnknown())
3274 IK = Language::C;
3275 // FIXME: Remove this hack.
3276 if (i == 0)
3277 DashX = IK;
3278 }
3279
3280 bool IsSystem = false;
3281
3282 // The -emit-module action implicitly takes a module map.
3284 IK.getFormat() == InputKind::Source) {
3286 IsSystem = Opts.IsSystemModule;
3287 }
3288
3289 Opts.Inputs.emplace_back(std::move(Inputs[i]), IK, IsSystem);
3290 }
3291
3292 Opts.DashX = DashX;
3293
3294 // CIR is a source-level frontend pipeline. When the input is already LLVM IR
3295 // (e.g. during the backend phase of OpenMP offloading), the standard LLVM
3296 // backend should be used instead.
3297 if (Opts.UseClangIRPipeline && DashX.getLanguage() == Language::LLVM_IR)
3298 Opts.UseClangIRPipeline = false;
3299
3300 return Diags.getNumErrors() == NumErrorsBefore;
3301}
3302
3304 ArgumentConsumer Consumer) {
3305 const HeaderSearchOptions *HeaderSearchOpts = &Opts;
3306#define HEADER_SEARCH_OPTION_WITH_MARSHALLING(...) \
3307 GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
3308#include "clang/Options/Options.inc"
3309#undef HEADER_SEARCH_OPTION_WITH_MARSHALLING
3310
3311 if (Opts.UseLibcxx)
3312 GenerateArg(Consumer, OPT_stdlib_EQ, "libc++");
3313
3314 for (const auto &File : Opts.PrebuiltModuleFiles)
3315 GenerateArg(Consumer, OPT_fmodule_file, File.first + "=" + File.second);
3316
3317 for (const auto &Path : Opts.PrebuiltModulePaths)
3318 GenerateArg(Consumer, OPT_fprebuilt_module_path, Path);
3319
3320 for (const auto &Macro : Opts.ModulesIgnoreMacros)
3321 GenerateArg(Consumer, OPT_fmodules_ignore_macro, Macro.val());
3322
3323 auto Matches = [](const HeaderSearchOptions::Entry &Entry,
3325 std::optional<bool> IsFramework,
3326 std::optional<bool> IgnoreSysRoot) {
3327 return llvm::is_contained(Groups, Entry.Group) &&
3328 (!IsFramework || (Entry.IsFramework == *IsFramework)) &&
3329 (!IgnoreSysRoot || (Entry.IgnoreSysRoot == *IgnoreSysRoot));
3330 };
3331
3332 auto It = Opts.UserEntries.begin();
3333 auto End = Opts.UserEntries.end();
3334
3335 // Add -I... and -F... options in order.
3336 for (; It < End && Matches(*It, {frontend::Angled}, std::nullopt, true);
3337 ++It) {
3338 OptSpecifier Opt = [It, Matches]() {
3339 if (Matches(*It, frontend::Angled, true, true))
3340 return OPT_F;
3341 if (Matches(*It, frontend::Angled, false, true))
3342 return OPT_I;
3343 llvm_unreachable("Unexpected HeaderSearchOptions::Entry.");
3344 }();
3345
3346 GenerateArg(Consumer, Opt, It->Path);
3347 }
3348
3349 // Note: some paths that came from "[-iprefix=xx] -iwithprefixbefore=yy" may
3350 // have already been generated as "-I[xx]yy". If that's the case, their
3351 // position on command line was such that this has no semantic impact on
3352 // include paths.
3353 for (; It < End &&
3354 Matches(*It, {frontend::After, frontend::Angled}, false, true);
3355 ++It) {
3356 OptSpecifier Opt =
3357 It->Group == frontend::After ? OPT_iwithprefix : OPT_iwithprefixbefore;
3358 GenerateArg(Consumer, Opt, It->Path);
3359 }
3360
3361 // Note: Some paths that came from "-idirafter=xxyy" may have already been
3362 // generated as "-iwithprefix=xxyy". If that's the case, their position on
3363 // command line was such that this has no semantic impact on include paths.
3364 for (; It < End && Matches(*It, {frontend::After}, false, true); ++It)
3365 GenerateArg(Consumer, OPT_idirafter, It->Path);
3366 for (; It < End && Matches(*It, {frontend::Quoted}, false, true); ++It)
3367 GenerateArg(Consumer, OPT_iquote, It->Path);
3368 for (; It < End && Matches(*It, {frontend::System}, false, std::nullopt);
3369 ++It)
3370 GenerateArg(Consumer, It->IgnoreSysRoot ? OPT_isystem : OPT_iwithsysroot,
3371 It->Path);
3372 for (; It < End && Matches(*It, {frontend::System}, true, true); ++It)
3373 GenerateArg(Consumer, OPT_iframework, It->Path);
3374 for (; It < End && Matches(*It, {frontend::System}, true, false); ++It)
3375 GenerateArg(Consumer, OPT_iframeworkwithsysroot, It->Path);
3376
3377 // Add the paths for the various language specific isystem flags.
3378 for (; It < End && Matches(*It, {frontend::CSystem}, false, true); ++It)
3379 GenerateArg(Consumer, OPT_c_isystem, It->Path);
3380 for (; It < End && Matches(*It, {frontend::CXXSystem}, false, true); ++It)
3381 GenerateArg(Consumer, OPT_cxx_isystem, It->Path);
3382 for (; It < End && Matches(*It, {frontend::ObjCSystem}, false, true); ++It)
3383 GenerateArg(Consumer, OPT_objc_isystem, It->Path);
3384 for (; It < End && Matches(*It, {frontend::ObjCXXSystem}, false, true); ++It)
3385 GenerateArg(Consumer, OPT_objcxx_isystem, It->Path);
3386
3387 // Add the internal paths from a driver that detects standard include paths.
3388 // Note: Some paths that came from "-internal-isystem" arguments may have
3389 // already been generated as "-isystem". If that's the case, their position on
3390 // command line was such that this has no semantic impact on include paths.
3391 for (; It < End &&
3392 Matches(*It, {frontend::System, frontend::ExternCSystem}, false, true);
3393 ++It) {
3394 OptSpecifier Opt = It->Group == frontend::System
3395 ? OPT_internal_isystem
3396 : OPT_internal_externc_isystem;
3397 GenerateArg(Consumer, Opt, It->Path);
3398 }
3399 for (; It < End && Matches(*It, {frontend::System}, true, true); ++It)
3400 GenerateArg(Consumer, OPT_internal_iframework, It->Path);
3401
3402 assert(It == End && "Unhandled HeaderSearchOption::Entry.");
3403
3404 // Add the path prefixes which are implicitly treated as being system headers.
3405 for (const auto &P : Opts.SystemHeaderPrefixes) {
3406 OptSpecifier Opt = P.IsSystemHeader ? OPT_system_header_prefix
3407 : OPT_no_system_header_prefix;
3408 GenerateArg(Consumer, Opt, P.Prefix);
3409 }
3410
3411 for (const std::string &F : Opts.VFSOverlayFiles)
3412 GenerateArg(Consumer, OPT_ivfsoverlay, F);
3413}
3414
3415static bool ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args,
3416 DiagnosticsEngine &Diags) {
3417 unsigned NumErrorsBefore = Diags.getNumErrors();
3418
3419 HeaderSearchOptions *HeaderSearchOpts = &Opts;
3420
3421#define HEADER_SEARCH_OPTION_WITH_MARSHALLING(...) \
3422 PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
3423#include "clang/Options/Options.inc"
3424#undef HEADER_SEARCH_OPTION_WITH_MARSHALLING
3425
3426 if (const Arg *A = Args.getLastArg(OPT_stdlib_EQ))
3427 Opts.UseLibcxx = (strcmp(A->getValue(), "libc++") == 0);
3428
3429 // Only the -fmodule-file=<name>=<file> form.
3430 for (const auto *A : Args.filtered(OPT_fmodule_file)) {
3431 StringRef Val = A->getValue();
3432 if (Val.contains('=')) {
3433 auto Split = Val.split('=');
3434 Opts.PrebuiltModuleFiles.insert_or_assign(
3435 std::string(Split.first), std::string(Split.second));
3436 }
3437 }
3438 for (const auto *A : Args.filtered(OPT_fprebuilt_module_path))
3439 Opts.AddPrebuiltModulePath(A->getValue());
3440
3441 for (const auto *A : Args.filtered(OPT_fmodules_ignore_macro)) {
3442 StringRef MacroDef = A->getValue();
3443 Opts.ModulesIgnoreMacros.insert(
3444 llvm::CachedHashString(MacroDef.split('=').first));
3445 }
3446
3447 // Add -I... and -F... options in order.
3448 bool IsSysrootSpecified =
3449 Args.hasArg(OPT__sysroot_EQ) || Args.hasArg(OPT_isysroot);
3450
3451 // Expand a leading `=` to the sysroot if one was passed (and it's not a
3452 // framework flag).
3453 auto PrefixHeaderPath = [IsSysrootSpecified,
3454 &Opts](const llvm::opt::Arg *A,
3455 bool IsFramework = false) -> std::string {
3456 assert(A->getNumValues() && "Unexpected empty search path flag!");
3457 if (IsSysrootSpecified && !IsFramework && A->getValue()[0] == '=') {
3458 SmallString<32> Buffer;
3459 llvm::sys::path::append(Buffer, Opts.Sysroot,
3460 llvm::StringRef(A->getValue()).substr(1));
3461 return std::string(Buffer);
3462 }
3463 return A->getValue();
3464 };
3465
3466 for (const auto *A : Args.filtered(OPT_I, OPT_F)) {
3467 bool IsFramework = A->getOption().matches(OPT_F);
3468 Opts.AddPath(PrefixHeaderPath(A, IsFramework), frontend::Angled,
3469 IsFramework, /*IgnoreSysroot=*/true);
3470 }
3471
3472 // Add -iprefix/-iwithprefix/-iwithprefixbefore options.
3473 StringRef Prefix = ""; // FIXME: This isn't the correct default prefix.
3474 for (const auto *A :
3475 Args.filtered(OPT_iprefix, OPT_iwithprefix, OPT_iwithprefixbefore)) {
3476 if (A->getOption().matches(OPT_iprefix))
3477 Prefix = A->getValue();
3478 else if (A->getOption().matches(OPT_iwithprefix))
3479 Opts.AddPath(Prefix.str() + A->getValue(), frontend::After, false, true);
3480 else
3481 Opts.AddPath(Prefix.str() + A->getValue(), frontend::Angled, false, true);
3482 }
3483
3484 for (const auto *A : Args.filtered(OPT_idirafter))
3485 Opts.AddPath(PrefixHeaderPath(A), frontend::After, false, true);
3486 for (const auto *A : Args.filtered(OPT_iquote))
3487 Opts.AddPath(PrefixHeaderPath(A), frontend::Quoted, false, true);
3488
3489 for (const auto *A : Args.filtered(OPT_isystem, OPT_iwithsysroot)) {
3490 if (A->getOption().matches(OPT_iwithsysroot)) {
3491 Opts.AddPath(A->getValue(), frontend::System, false,
3492 /*IgnoreSysRoot=*/false);
3493 continue;
3494 }
3495 Opts.AddPath(PrefixHeaderPath(A), frontend::System, false, true);
3496 }
3497 for (const auto *A : Args.filtered(OPT_iframework))
3498 Opts.AddPath(A->getValue(), frontend::System, true, true);
3499 for (const auto *A : Args.filtered(OPT_iframeworkwithsysroot))
3500 Opts.AddPath(A->getValue(), frontend::System, /*IsFramework=*/true,
3501 /*IgnoreSysRoot=*/false);
3502
3503 // Add the paths for the various language specific isystem flags.
3504 for (const auto *A : Args.filtered(OPT_c_isystem))
3505 Opts.AddPath(A->getValue(), frontend::CSystem, false, true);
3506 for (const auto *A : Args.filtered(OPT_cxx_isystem))
3507 Opts.AddPath(A->getValue(), frontend::CXXSystem, false, true);
3508 for (const auto *A : Args.filtered(OPT_objc_isystem))
3509 Opts.AddPath(A->getValue(), frontend::ObjCSystem, false,true);
3510 for (const auto *A : Args.filtered(OPT_objcxx_isystem))
3511 Opts.AddPath(A->getValue(), frontend::ObjCXXSystem, false, true);
3512
3513 // Add the internal paths from a driver that detects standard include paths.
3514 for (const auto *A :
3515 Args.filtered(OPT_internal_isystem, OPT_internal_externc_isystem)) {
3517 if (A->getOption().matches(OPT_internal_externc_isystem))
3519 Opts.AddPath(A->getValue(), Group, false, true);
3520 }
3521 for (const auto *A : Args.filtered(OPT_internal_iframework))
3522 Opts.AddPath(A->getValue(), frontend::System, true, true);
3523
3524 // Add the path prefixes which are implicitly treated as being system headers.
3525 for (const auto *A :
3526 Args.filtered(OPT_system_header_prefix, OPT_no_system_header_prefix))
3528 A->getValue(), A->getOption().matches(OPT_system_header_prefix));
3529
3530 for (const auto *A : Args.filtered(OPT_ivfsoverlay, OPT_vfsoverlay))
3531 Opts.AddVFSOverlayFile(A->getValue());
3532
3533 return Diags.getNumErrors() == NumErrorsBefore;
3534}
3535
3537 ArgumentConsumer Consumer) {
3538 if (!Opts.SwiftVersion.empty())
3539 GenerateArg(Consumer, OPT_fapinotes_swift_version,
3540 Opts.SwiftVersion.getAsString());
3541
3542 for (const auto &Path : Opts.ModuleSearchPaths)
3543 GenerateArg(Consumer, OPT_iapinotes_modules, Path);
3544}
3545
3546static void ParseAPINotesArgs(APINotesOptions &Opts, ArgList &Args,
3547 DiagnosticsEngine &diags) {
3548 if (const Arg *A = Args.getLastArg(OPT_fapinotes_swift_version)) {
3549 if (Opts.SwiftVersion.tryParse(A->getValue()))
3550 diags.Report(diag::err_drv_invalid_value)
3551 << A->getAsString(Args) << A->getValue();
3552 }
3553 for (const Arg *A : Args.filtered(OPT_iapinotes_modules))
3554 Opts.ModuleSearchPaths.push_back(A->getValue());
3555}
3556
3557static void GeneratePointerAuthArgs(const LangOptions &Opts,
3558 ArgumentConsumer Consumer) {
3559 if (Opts.PointerAuthIntrinsics)
3560 GenerateArg(Consumer, OPT_fptrauth_intrinsics);
3561 if (Opts.PointerAuthCalls)
3562 GenerateArg(Consumer, OPT_fptrauth_calls);
3563 if (Opts.PointerAuthReturns)
3564 GenerateArg(Consumer, OPT_fptrauth_returns);
3565 if (Opts.PointerAuthIndirectGotos)
3566 GenerateArg(Consumer, OPT_fptrauth_indirect_gotos);
3567 if (Opts.PointerAuthAuthTraps)
3568 GenerateArg(Consumer, OPT_fptrauth_auth_traps);
3569 if (Opts.PointerAuthVTPtrAddressDiscrimination)
3570 GenerateArg(Consumer, OPT_fptrauth_vtable_pointer_address_discrimination);
3571 if (Opts.PointerAuthVTPtrTypeDiscrimination)
3572 GenerateArg(Consumer, OPT_fptrauth_vtable_pointer_type_discrimination);
3573 if (Opts.PointerAuthTypeInfoVTPtrDiscrimination)
3574 GenerateArg(Consumer, OPT_fptrauth_type_info_vtable_pointer_discrimination);
3575 if (Opts.PointerAuthFunctionTypeDiscrimination)
3576 GenerateArg(Consumer, OPT_fptrauth_function_pointer_type_discrimination);
3577 if (Opts.PointerAuthInitFini)
3578 GenerateArg(Consumer, OPT_fptrauth_init_fini);
3579 if (Opts.PointerAuthInitFiniAddressDiscrimination)
3580 GenerateArg(Consumer, OPT_fptrauth_init_fini_address_discrimination);
3581 if (Opts.PointerAuthELFGOT)
3582 GenerateArg(Consumer, OPT_fptrauth_elf_got);
3583 if (Opts.AArch64JumpTableHardening)
3584 GenerateArg(Consumer, OPT_faarch64_jump_table_hardening);
3585 if (Opts.PointerAuthObjcIsa)
3586 GenerateArg(Consumer, OPT_fptrauth_objc_isa);
3587 if (Opts.PointerAuthObjcInterfaceSel)
3588 GenerateArg(Consumer, OPT_fptrauth_objc_interface_sel);
3589 if (Opts.PointerAuthObjcClassROPointers)
3590 GenerateArg(Consumer, OPT_fptrauth_objc_class_ro);
3591 if (Opts.PointerAuthBlockDescriptorPointers)
3592 GenerateArg(Consumer, OPT_fptrauth_block_descriptor_pointers);
3593}
3594
3595static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args,
3596 DiagnosticsEngine &Diags) {
3597 Opts.PointerAuthIntrinsics = Args.hasArg(OPT_fptrauth_intrinsics);
3598 Opts.PointerAuthCalls = Args.hasArg(OPT_fptrauth_calls);
3599 Opts.PointerAuthReturns = Args.hasArg(OPT_fptrauth_returns);
3600 Opts.PointerAuthIndirectGotos = Args.hasArg(OPT_fptrauth_indirect_gotos);
3601 Opts.PointerAuthAuthTraps = Args.hasArg(OPT_fptrauth_auth_traps);
3602 Opts.PointerAuthVTPtrAddressDiscrimination =
3603 Args.hasArg(OPT_fptrauth_vtable_pointer_address_discrimination);
3604 Opts.PointerAuthVTPtrTypeDiscrimination =
3605 Args.hasArg(OPT_fptrauth_vtable_pointer_type_discrimination);
3606 Opts.PointerAuthTypeInfoVTPtrDiscrimination =
3607 Args.hasArg(OPT_fptrauth_type_info_vtable_pointer_discrimination);
3608 Opts.PointerAuthFunctionTypeDiscrimination =
3609 Args.hasArg(OPT_fptrauth_function_pointer_type_discrimination);
3610 Opts.PointerAuthInitFini = Args.hasArg(OPT_fptrauth_init_fini);
3611 Opts.PointerAuthInitFiniAddressDiscrimination =
3612 Args.hasArg(OPT_fptrauth_init_fini_address_discrimination);
3613 Opts.PointerAuthELFGOT = Args.hasArg(OPT_fptrauth_elf_got);
3614 Opts.AArch64JumpTableHardening =
3615 Args.hasArg(OPT_faarch64_jump_table_hardening);
3616 Opts.PointerAuthBlockDescriptorPointers =
3617 Args.hasArg(OPT_fptrauth_block_descriptor_pointers);
3618 Opts.PointerAuthObjcIsa = Args.hasArg(OPT_fptrauth_objc_isa);
3619 Opts.PointerAuthObjcClassROPointers = Args.hasArg(OPT_fptrauth_objc_class_ro);
3620 Opts.PointerAuthObjcInterfaceSel =
3621 Args.hasArg(OPT_fptrauth_objc_interface_sel);
3622
3623 if (Opts.PointerAuthObjcInterfaceSel)
3624 Opts.PointerAuthObjcInterfaceSelKey =
3625 static_cast<unsigned>(PointerAuthSchema::ARM8_3Key::ASDB);
3626}
3627
3628/// Check if input file kind and language standard are compatible.
3630 const LangStandard &S) {
3631 switch (IK.getLanguage()) {
3632 case Language::Unknown:
3633 case Language::LLVM_IR:
3634 case Language::CIR:
3635 llvm_unreachable("should not parse language flags for this input");
3636
3637 case Language::C:
3638 case Language::ObjC:
3639 return S.getLanguage() == Language::C;
3640
3641 case Language::OpenCL:
3642 return S.getLanguage() == Language::OpenCL ||
3644
3646 return S.getLanguage() == Language::OpenCLCXX;
3647
3648 case Language::CXX:
3649 case Language::ObjCXX:
3650 return S.getLanguage() == Language::CXX;
3651
3652 case Language::CUDA:
3653 // FIXME: What -std= values should be permitted for CUDA compilations?
3654 return S.getLanguage() == Language::CUDA ||
3656
3657 case Language::HIP:
3658 return S.getLanguage() == Language::CXX || S.getLanguage() == Language::HIP;
3659
3660 case Language::Asm:
3661 // Accept (and ignore) all -std= values.
3662 // FIXME: The -std= value is not ignored; it affects the tokenization
3663 // and preprocessing rules if we're preprocessing this asm input.
3664 return true;
3665
3666 case Language::HLSL:
3667 return S.getLanguage() == Language::HLSL;
3668 }
3669
3670 llvm_unreachable("unexpected input language");
3671}
3672
3673/// Get language name for given input kind.
3674static StringRef GetInputKindName(InputKind IK) {
3675 switch (IK.getLanguage()) {
3676 case Language::C:
3677 return "C";
3678 case Language::ObjC:
3679 return "Objective-C";
3680 case Language::CXX:
3681 return "C++";
3682 case Language::ObjCXX:
3683 return "Objective-C++";
3684 case Language::OpenCL:
3685 return "OpenCL";
3687 return "C++ for OpenCL";
3688 case Language::CUDA:
3689 return "CUDA";
3690 case Language::HIP:
3691 return "HIP";
3692
3693 case Language::Asm:
3694 return "Asm";
3695 case Language::LLVM_IR:
3696 return "LLVM IR";
3697 case Language::CIR:
3698 return "Clang IR";
3699
3700 case Language::HLSL:
3701 return "HLSL";
3702
3703 case Language::Unknown:
3704 break;
3705 }
3706 llvm_unreachable("unknown input language");
3707}
3708
3709void CompilerInvocationBase::GenerateLangArgs(const LangOptions &Opts,
3710 ArgumentConsumer Consumer,
3711 const llvm::Triple &T,
3712 InputKind IK) {
3713 if (IK.getFormat() == InputKind::Precompiled ||
3715 IK.getLanguage() == Language::CIR) {
3716 if (Opts.ObjCAutoRefCount)
3717 GenerateArg(Consumer, OPT_fobjc_arc);
3718 if (Opts.PICLevel != 0)
3719 GenerateArg(Consumer, OPT_pic_level, Twine(Opts.PICLevel));
3720 if (Opts.PIE)
3721 GenerateArg(Consumer, OPT_pic_is_pie);
3722 for (StringRef Sanitizer : serializeSanitizerKinds(Opts.Sanitize))
3723 GenerateArg(Consumer, OPT_fsanitize_EQ, Sanitizer);
3724 for (StringRef Sanitizer :
3726 GenerateArg(Consumer, OPT_fsanitize_ignore_for_ubsan_feature_EQ,
3727 Sanitizer);
3728
3729 return;
3730 }
3731
3732 OptSpecifier StdOpt;
3733 switch (Opts.LangStd) {
3734 case LangStandard::lang_opencl10:
3735 case LangStandard::lang_opencl11:
3736 case LangStandard::lang_opencl12:
3737 case LangStandard::lang_opencl20:
3738 case LangStandard::lang_opencl30:
3739 case LangStandard::lang_openclcpp10:
3740 case LangStandard::lang_openclcpp2021:
3741 StdOpt = OPT_cl_std_EQ;
3742 break;
3743 default:
3744 StdOpt = OPT_std_EQ;
3745 break;
3746 }
3747
3748 auto LangStandard = LangStandard::getLangStandardForKind(Opts.LangStd);
3749 GenerateArg(Consumer, StdOpt, LangStandard.getName());
3750
3751 if (Opts.IncludeDefaultHeader)
3752 GenerateArg(Consumer, OPT_finclude_default_header);
3753 if (Opts.DeclareOpenCLBuiltins)
3754 GenerateArg(Consumer, OPT_fdeclare_opencl_builtins);
3755
3756 const LangOptions *LangOpts = &Opts;
3757
3758#define LANG_OPTION_WITH_MARSHALLING(...) \
3759 GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
3760#include "clang/Options/Options.inc"
3761#undef LANG_OPTION_WITH_MARSHALLING
3762
3763 // The '-fcf-protection=' option is generated by CodeGenOpts generator.
3764
3765 if (Opts.ObjC) {
3766 GenerateArg(Consumer, OPT_fobjc_runtime_EQ, Opts.ObjCRuntime.getAsString());
3767
3768 if (Opts.GC == LangOptions::GCOnly)
3769 GenerateArg(Consumer, OPT_fobjc_gc_only);
3770 else if (Opts.GC == LangOptions::HybridGC)
3771 GenerateArg(Consumer, OPT_fobjc_gc);
3772 else if (Opts.ObjCAutoRefCount == 1)
3773 GenerateArg(Consumer, OPT_fobjc_arc);
3774
3775 if (Opts.ObjCWeakRuntime)
3776 GenerateArg(Consumer, OPT_fobjc_runtime_has_weak);
3777
3778 if (Opts.ObjCWeak)
3779 GenerateArg(Consumer, OPT_fobjc_weak);
3780
3781 if (Opts.ObjCSubscriptingLegacyRuntime)
3782 GenerateArg(Consumer, OPT_fobjc_subscripting_legacy_runtime);
3783 }
3784
3785 if (Opts.GNUCVersion != 0) {
3786 unsigned Major = Opts.GNUCVersion / 100 / 100;
3787 unsigned Minor = (Opts.GNUCVersion / 100) % 100;
3788 unsigned Patch = Opts.GNUCVersion % 100;
3789 GenerateArg(Consumer, OPT_fgnuc_version_EQ,
3790 Twine(Major) + "." + Twine(Minor) + "." + Twine(Patch));
3791 }
3792
3793 if (Opts.IgnoreXCOFFVisibility)
3794 GenerateArg(Consumer, OPT_mignore_xcoff_visibility);
3795
3796 if (Opts.SignedOverflowBehavior == LangOptions::SOB_Trapping) {
3797 GenerateArg(Consumer, OPT_ftrapv);
3798 GenerateArg(Consumer, OPT_ftrapv_handler, Opts.OverflowHandler);
3799 } else if (Opts.SignedOverflowBehavior == LangOptions::SOB_Defined) {
3800 GenerateArg(Consumer, OPT_fwrapv);
3801 }
3802 if (Opts.PointerOverflowDefined)
3803 GenerateArg(Consumer, OPT_fwrapv_pointer);
3804
3805 if (Opts.MSCompatibilityVersion != 0) {
3806 unsigned Major = Opts.MSCompatibilityVersion / 10000000;
3807 unsigned Minor = (Opts.MSCompatibilityVersion / 100000) % 100;
3808 unsigned Subminor = Opts.MSCompatibilityVersion % 100000;
3809 GenerateArg(Consumer, OPT_fms_compatibility_version,
3810 Twine(Major) + "." + Twine(Minor) + "." + Twine(Subminor));
3811 }
3812
3813 if ((!Opts.GNUMode && !Opts.MSVCCompat && !Opts.CPlusPlus17 && !Opts.C23) ||
3814 T.isOSzOS()) {
3815 if (!Opts.Trigraphs)
3816 GenerateArg(Consumer, OPT_fno_trigraphs);
3817 } else {
3818 if (Opts.Trigraphs)
3819 GenerateArg(Consumer, OPT_ftrigraphs);
3820 }
3821
3822 if (T.isOSzOS() && !Opts.ZOSExt)
3823 GenerateArg(Consumer, OPT_fno_zos_extensions);
3824 else if (Opts.ZOSExt)
3825 GenerateArg(Consumer, OPT_fzos_extensions);
3826
3827 if (Opts.Blocks && !(Opts.OpenCL && Opts.OpenCLVersion == 200))
3828 GenerateArg(Consumer, OPT_fblocks);
3829
3830 if (Opts.ConvergentFunctions)
3831 GenerateArg(Consumer, OPT_fconvergent_functions);
3832 else
3833 GenerateArg(Consumer, OPT_fno_convergent_functions);
3834
3835 if (Opts.NoBuiltin && !Opts.Freestanding)
3836 GenerateArg(Consumer, OPT_fno_builtin);
3837
3838 if (!Opts.NoBuiltin)
3839 for (const auto &Func : Opts.NoBuiltinFuncs)
3840 GenerateArg(Consumer, OPT_fno_builtin_, Func);
3841
3842 if (Opts.LongDoubleSize == 128)
3843 GenerateArg(Consumer, OPT_mlong_double_128);
3844 else if (Opts.LongDoubleSize == 64)
3845 GenerateArg(Consumer, OPT_mlong_double_64);
3846 else if (Opts.LongDoubleSize == 80)
3847 GenerateArg(Consumer, OPT_mlong_double_80);
3848
3849 // Not generating '-mrtd', it's just an alias for '-fdefault-calling-conv='.
3850
3851 // OpenMP was requested via '-fopenmp', not implied by '-fopenmp-simd' or
3852 // '-fopenmp-targets='.
3853 if (Opts.OpenMP && !Opts.OpenMPSimd) {
3854 GenerateArg(Consumer, OPT_fopenmp);
3855
3856 if (Opts.OpenMP != 51)
3857 GenerateArg(Consumer, OPT_fopenmp_version_EQ, Twine(Opts.OpenMP));
3858
3859 if (!Opts.OpenMPUseTLS)
3860 GenerateArg(Consumer, OPT_fnoopenmp_use_tls);
3861
3862 if (Opts.OpenMPIsTargetDevice)
3863 GenerateArg(Consumer, OPT_fopenmp_is_target_device);
3864
3865 if (Opts.OpenMPIRBuilder)
3866 GenerateArg(Consumer, OPT_fopenmp_enable_irbuilder);
3867 }
3868
3869 if (Opts.OpenMPSimd) {
3870 GenerateArg(Consumer, OPT_fopenmp_simd);
3871
3872 if (Opts.OpenMP != 51)
3873 GenerateArg(Consumer, OPT_fopenmp_version_EQ, Twine(Opts.OpenMP));
3874 }
3875
3876 if (Opts.OpenMPThreadSubscription)
3877 GenerateArg(Consumer, OPT_fopenmp_assume_threads_oversubscription);
3878
3879 if (Opts.OpenMPTeamSubscription)
3880 GenerateArg(Consumer, OPT_fopenmp_assume_teams_oversubscription);
3881
3882 if (Opts.OpenMPTargetDebug != 0)
3883 GenerateArg(Consumer, OPT_fopenmp_target_debug_EQ,
3884 Twine(Opts.OpenMPTargetDebug));
3885
3886 if (Opts.OpenMPCUDANumSMs != 0)
3887 GenerateArg(Consumer, OPT_fopenmp_cuda_number_of_sm_EQ,
3888 Twine(Opts.OpenMPCUDANumSMs));
3889
3890 if (Opts.OpenMPCUDABlocksPerSM != 0)
3891 GenerateArg(Consumer, OPT_fopenmp_cuda_blocks_per_sm_EQ,
3892 Twine(Opts.OpenMPCUDABlocksPerSM));
3893
3894 if (Opts.OpenMPCUDAReductionBufNum != 1024)
3895 GenerateArg(Consumer, OPT_fopenmp_cuda_teams_reduction_recs_num_EQ,
3896 Twine(Opts.OpenMPCUDAReductionBufNum));
3897
3898 if (!Opts.OMPTargetTriples.empty()) {
3899 std::string Targets;
3900 llvm::raw_string_ostream OS(Targets);
3901 llvm::interleave(
3902 Opts.OMPTargetTriples, OS,
3903 [&OS](const llvm::Triple &T) { OS << T.str(); }, ",");
3904 GenerateArg(Consumer, OPT_offload_targets_EQ, Targets);
3905 }
3906
3907 if (Opts.OpenMPCUDAMode)
3908 GenerateArg(Consumer, OPT_fopenmp_cuda_mode);
3909
3910 if (Opts.OpenACC)
3911 GenerateArg(Consumer, OPT_fopenacc);
3912
3913 // The arguments used to set Optimize, OptimizeSize and NoInlineDefine are
3914 // generated from CodeGenOptions.
3915
3916 if (Opts.DefaultFPContractMode == LangOptions::FPM_Fast)
3917 GenerateArg(Consumer, OPT_ffp_contract, "fast");
3918 else if (Opts.DefaultFPContractMode == LangOptions::FPM_On)
3919 GenerateArg(Consumer, OPT_ffp_contract, "on");
3920 else if (Opts.DefaultFPContractMode == LangOptions::FPM_Off)
3921 GenerateArg(Consumer, OPT_ffp_contract, "off");
3922 else if (Opts.DefaultFPContractMode == LangOptions::FPM_FastHonorPragmas)
3923 GenerateArg(Consumer, OPT_ffp_contract, "fast-honor-pragmas");
3924
3925 for (StringRef Sanitizer : serializeSanitizerKinds(Opts.Sanitize))
3926 GenerateArg(Consumer, OPT_fsanitize_EQ, Sanitizer);
3927 for (StringRef Sanitizer :
3929 GenerateArg(Consumer, OPT_fsanitize_ignore_for_ubsan_feature_EQ, Sanitizer);
3930
3931 // Conflating '-fsanitize-system-ignorelist' and '-fsanitize-ignorelist'.
3932 for (const std::string &F : Opts.NoSanitizeFiles)
3933 GenerateArg(Consumer, OPT_fsanitize_ignorelist_EQ, F);
3934
3935 switch (Opts.getClangABICompat()) {
3936#define ABI_VER_MAJOR_MINOR(Major, Minor) \
3937 case LangOptions::ClangABI::Ver##Major##_##Minor: \
3938 GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, #Major "." #Minor); \
3939 break;
3940#define ABI_VER_MAJOR(Major) \
3941 case LangOptions::ClangABI::Ver##Major: \
3942 GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, #Major ".0"); \
3943 break;
3944#define ABI_VER_LATEST(Latest) \
3945 case LangOptions::ClangABI::Latest: \
3946 break;
3947#include "clang/Basic/ABIVersions.def"
3948 }
3949
3950 if (Opts.getSignReturnAddressScope() ==
3952 GenerateArg(Consumer, OPT_msign_return_address_EQ, "all");
3953 else if (Opts.getSignReturnAddressScope() ==
3955 GenerateArg(Consumer, OPT_msign_return_address_EQ, "non-leaf");
3956
3957 if (Opts.getSignReturnAddressKey() ==
3959 GenerateArg(Consumer, OPT_msign_return_address_key_EQ, "b_key");
3960
3961 if (Opts.CXXABI)
3962 GenerateArg(Consumer, OPT_fcxx_abi_EQ,
3964
3965 if (Opts.RelativeCXXABIVTables)
3966 GenerateArg(Consumer, OPT_fexperimental_relative_cxx_abi_vtables);
3967 else
3968 GenerateArg(Consumer, OPT_fno_experimental_relative_cxx_abi_vtables);
3969
3970 if (Opts.UseTargetPathSeparator)
3971 GenerateArg(Consumer, OPT_ffile_reproducible);
3972 else
3973 GenerateArg(Consumer, OPT_fno_file_reproducible);
3974
3975 for (const auto &MP : Opts.MacroPrefixMap)
3976 GenerateArg(Consumer, OPT_fmacro_prefix_map_EQ, MP.first + "=" + MP.second);
3977
3978 if (!Opts.RandstructSeed.empty())
3979 GenerateArg(Consumer, OPT_frandomize_layout_seed_EQ, Opts.RandstructSeed);
3980
3981 if (Opts.AllocTokenMax)
3982 GenerateArg(Consumer, OPT_falloc_token_max_EQ,
3983 std::to_string(*Opts.AllocTokenMax));
3984
3985 if (Opts.AllocTokenMode) {
3986 StringRef S = llvm::getAllocTokenModeAsString(*Opts.AllocTokenMode);
3987 GenerateArg(Consumer, OPT_falloc_token_mode_EQ, S);
3988 }
3989 // Generate args for matrix types.
3990 if (Opts.MatrixTypes) {
3991 if (Opts.getDefaultMatrixMemoryLayout() ==
3993 GenerateArg(Consumer, OPT_fmatrix_memory_layout_EQ, "column-major");
3994 if (Opts.getDefaultMatrixMemoryLayout() ==
3996 GenerateArg(Consumer, OPT_fmatrix_memory_layout_EQ, "row-major");
3997 }
3998}
3999
4000bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
4001 InputKind IK, const llvm::Triple &T,
4002 std::vector<std::string> &Includes,
4003 DiagnosticsEngine &Diags) {
4004 unsigned NumErrorsBefore = Diags.getNumErrors();
4005
4006 if (IK.getFormat() == InputKind::Precompiled ||
4008 IK.getLanguage() == Language::CIR) {
4009 // ObjCAAutoRefCount and Sanitize LangOpts are used to setup the
4010 // PassManager in BackendUtil.cpp. They need to be initialized no matter
4011 // what the input type is.
4012 if (Args.hasArg(OPT_fobjc_arc))
4013 Opts.ObjCAutoRefCount = 1;
4014 // PICLevel and PIELevel are needed during code generation and this should
4015 // be set regardless of the input type.
4016 Opts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags);
4017 Opts.PIE = Args.hasArg(OPT_pic_is_pie);
4018 parseSanitizerKinds("-fsanitize=", Args.getAllArgValues(OPT_fsanitize_EQ),
4019 Diags, Opts.Sanitize);
4021 "-fsanitize-ignore-for-ubsan-feature=",
4022 Args.getAllArgValues(OPT_fsanitize_ignore_for_ubsan_feature_EQ), Diags,
4024
4025 return Diags.getNumErrors() == NumErrorsBefore;
4026 }
4027
4028 // Other LangOpts are only initialized when the input is not AST or LLVM IR.
4029 // FIXME: Should we really be parsing this for an Language::Asm input?
4030
4031 // FIXME: Cleanup per-file based stuff.
4033 if (const Arg *A = Args.getLastArg(OPT_std_EQ)) {
4034 LangStd = LangStandard::getLangKind(A->getValue());
4035 if (LangStd == LangStandard::lang_unspecified) {
4036 Diags.Report(diag::err_drv_invalid_value)
4037 << A->getAsString(Args) << A->getValue();
4038 // Report supported standards with short description.
4039 for (unsigned KindValue = 0;
4040 KindValue != LangStandard::lang_unspecified;
4041 ++KindValue) {
4042 const LangStandard &Std = LangStandard::getLangStandardForKind(
4043 static_cast<LangStandard::Kind>(KindValue));
4044 if (IsInputCompatibleWithStandard(IK, Std)) {
4045 auto Diag = Diags.Report(diag::note_drv_use_standard);
4046 Diag << Std.getName() << Std.getDescription();
4047 unsigned NumAliases = 0;
4048#define LANGSTANDARD(id, name, lang, desc, features, version)
4049#define LANGSTANDARD_ALIAS(id, alias) \
4050 if (KindValue == LangStandard::lang_##id) ++NumAliases;
4051#define LANGSTANDARD_ALIAS_DEPR(id, alias)
4052#include "clang/Basic/LangStandards.def"
4053 Diag << NumAliases;
4054#define LANGSTANDARD(id, name, lang, desc, features, version)
4055#define LANGSTANDARD_ALIAS(id, alias) \
4056 if (KindValue == LangStandard::lang_##id) Diag << alias;
4057#define LANGSTANDARD_ALIAS_DEPR(id, alias)
4058#include "clang/Basic/LangStandards.def"
4059 }
4060 }
4061 } else {
4062 // Valid standard, check to make sure language and standard are
4063 // compatible.
4064 const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd);
4065 if (!IsInputCompatibleWithStandard(IK, Std)) {
4066 Diags.Report(diag::err_drv_argument_not_allowed_with)
4067 << A->getAsString(Args) << GetInputKindName(IK);
4068 }
4069 }
4070 }
4071
4072 // -cl-std only applies for OpenCL language standards.
4073 // Override the -std option in this case.
4074 if (const Arg *A = Args.getLastArg(OPT_cl_std_EQ)) {
4075 LangStandard::Kind OpenCLLangStd =
4076 llvm::StringSwitch<LangStandard::Kind>(A->getValue())
4077 .Cases({"cl", "CL"}, LangStandard::lang_opencl10)
4078 .Cases({"cl1.0", "CL1.0"}, LangStandard::lang_opencl10)
4079 .Cases({"cl1.1", "CL1.1"}, LangStandard::lang_opencl11)
4080 .Cases({"cl1.2", "CL1.2"}, LangStandard::lang_opencl12)
4081 .Cases({"cl2.0", "CL2.0"}, LangStandard::lang_opencl20)
4082 .Cases({"cl3.0", "CL3.0"}, LangStandard::lang_opencl30)
4083 .Cases({"clc++", "CLC++"}, LangStandard::lang_openclcpp10)
4084 .Cases({"clc++1.0", "CLC++1.0"}, LangStandard::lang_openclcpp10)
4085 .Cases({"clc++2021", "CLC++2021"}, LangStandard::lang_openclcpp2021)
4087
4088 if (OpenCLLangStd == LangStandard::lang_unspecified) {
4089 Diags.Report(diag::err_drv_invalid_value)
4090 << A->getAsString(Args) << A->getValue();
4091 }
4092 else
4093 LangStd = OpenCLLangStd;
4094 }
4095
4096 // These need to be parsed now. They are used to set OpenCL defaults.
4097 Opts.IncludeDefaultHeader = Args.hasArg(OPT_finclude_default_header);
4098 Opts.DeclareOpenCLBuiltins = Args.hasArg(OPT_fdeclare_opencl_builtins);
4099
4100 LangOptions::setLangDefaults(Opts, IK.getLanguage(), T, Includes, LangStd);
4101
4102 // The key paths of codegen options defined in Options.td start with
4103 // "LangOpts->". Let's provide the expected variable name and type.
4104 LangOptions *LangOpts = &Opts;
4105
4106#define LANG_OPTION_WITH_MARSHALLING(...) \
4107 PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
4108#include "clang/Options/Options.inc"
4109#undef LANG_OPTION_WITH_MARSHALLING
4110
4111 if (const Arg *A = Args.getLastArg(OPT_fcf_protection_EQ)) {
4112 StringRef Name = A->getValue();
4113 if (Name == "full") {
4114 Opts.CFProtectionBranch = 1;
4115 Opts.CFProtectionReturn = 1;
4116 } else if (Name == "branch") {
4117 Opts.CFProtectionBranch = 1;
4118 } else if (Name == "return") {
4119 Opts.CFProtectionReturn = 1;
4120 }
4121 }
4122
4123 if (Opts.CFProtectionBranch) {
4124 if (const Arg *A = Args.getLastArg(OPT_mcf_branch_label_scheme_EQ)) {
4125 const auto Scheme =
4126 llvm::StringSwitch<CFBranchLabelSchemeKind>(A->getValue())
4127#define CF_BRANCH_LABEL_SCHEME(Kind, FlagVal) \
4128 .Case(#FlagVal, CFBranchLabelSchemeKind::Kind)
4129#include "clang/Basic/CFProtectionOptions.def"
4131 Opts.setCFBranchLabelScheme(Scheme);
4132 }
4133 }
4134
4135 if ((Args.hasArg(OPT_fsycl_is_device) || Args.hasArg(OPT_fsycl_is_host)) &&
4136 !Args.hasArg(OPT_sycl_std_EQ)) {
4137 // If the user supplied -fsycl-is-device or -fsycl-is-host, but failed to
4138 // provide -sycl-std=, we want to default it to whatever the default SYCL
4139 // version is. I could not find a way to express this with the options
4140 // tablegen because we still want this value to be SYCL_None when the user
4141 // is not in device or host mode.
4142 Opts.setSYCLVersion(LangOptions::SYCL_Default);
4143 }
4144
4145 if (Opts.ObjC) {
4146 if (Arg *arg = Args.getLastArg(OPT_fobjc_runtime_EQ)) {
4147 StringRef value = arg->getValue();
4148 if (Opts.ObjCRuntime.tryParse(value))
4149 Diags.Report(diag::err_drv_unknown_objc_runtime) << value;
4150 }
4151
4152 if (Args.hasArg(OPT_fobjc_gc_only))
4153 Opts.setGC(LangOptions::GCOnly);
4154 else if (Args.hasArg(OPT_fobjc_gc))
4155 Opts.setGC(LangOptions::HybridGC);
4156 else if (Args.hasArg(OPT_fobjc_arc)) {
4157 Opts.ObjCAutoRefCount = 1;
4158 if (!Opts.ObjCRuntime.allowsARC())
4159 Diags.Report(diag::err_arc_unsupported_on_runtime);
4160 }
4161
4162 // ObjCWeakRuntime tracks whether the runtime supports __weak, not
4163 // whether the feature is actually enabled. This is predominantly
4164 // determined by -fobjc-runtime, but we allow it to be overridden
4165 // from the command line for testing purposes.
4166 if (Args.hasArg(OPT_fobjc_runtime_has_weak))
4167 Opts.ObjCWeakRuntime = 1;
4168 else
4169 Opts.ObjCWeakRuntime = Opts.ObjCRuntime.allowsWeak();
4170
4171 // ObjCWeak determines whether __weak is actually enabled.
4172 // Note that we allow -fno-objc-weak to disable this even in ARC mode.
4173 if (auto weakArg = Args.getLastArg(OPT_fobjc_weak, OPT_fno_objc_weak)) {
4174 if (!weakArg->getOption().matches(OPT_fobjc_weak)) {
4175 assert(!Opts.ObjCWeak);
4176 } else if (Opts.getGC() != LangOptions::NonGC) {
4177 Diags.Report(diag::err_objc_weak_with_gc);
4178 } else if (!Opts.ObjCWeakRuntime) {
4179 Diags.Report(diag::err_objc_weak_unsupported);
4180 } else {
4181 Opts.ObjCWeak = 1;
4182 }
4183 } else if (Opts.ObjCAutoRefCount) {
4184 Opts.ObjCWeak = Opts.ObjCWeakRuntime;
4185 }
4186
4187 if (Args.hasArg(OPT_fobjc_subscripting_legacy_runtime))
4188 Opts.ObjCSubscriptingLegacyRuntime =
4190 }
4191
4192 if (Arg *A = Args.getLastArg(options::OPT_fgnuc_version_EQ)) {
4193 // Check that the version has 1 to 3 components and the minor and patch
4194 // versions fit in two decimal digits.
4195 VersionTuple GNUCVer;
4196 bool Invalid = GNUCVer.tryParse(A->getValue());
4197 unsigned Major = GNUCVer.getMajor();
4198 unsigned Minor = GNUCVer.getMinor().value_or(0);
4199 unsigned Patch = GNUCVer.getSubminor().value_or(0);
4200 if (Invalid || GNUCVer.getBuild() || Minor >= 100 || Patch >= 100) {
4201 Diags.Report(diag::err_drv_invalid_value)
4202 << A->getAsString(Args) << A->getValue();
4203 }
4204 Opts.GNUCVersion = Major * 100 * 100 + Minor * 100 + Patch;
4205 }
4206
4207 if (T.isOSAIX() && (Args.hasArg(OPT_mignore_xcoff_visibility)))
4208 Opts.IgnoreXCOFFVisibility = 1;
4209
4210 if (Args.hasArg(OPT_ftrapv)) {
4211 Opts.setSignedOverflowBehavior(LangOptions::SOB_Trapping);
4212 // Set the handler, if one is specified.
4213 Opts.OverflowHandler =
4214 std::string(Args.getLastArgValue(OPT_ftrapv_handler));
4215 }
4216 else if (Args.hasArg(OPT_fwrapv))
4217 Opts.setSignedOverflowBehavior(LangOptions::SOB_Defined);
4218 if (Args.hasArg(OPT_fwrapv_pointer))
4219 Opts.PointerOverflowDefined = true;
4220
4221 Opts.MSCompatibilityVersion = 0;
4222 if (const Arg *A = Args.getLastArg(OPT_fms_compatibility_version)) {
4223 VersionTuple VT;
4224 if (VT.tryParse(A->getValue()))
4225 Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args)
4226 << A->getValue();
4227 Opts.MSCompatibilityVersion = VT.getMajor() * 10000000 +
4228 VT.getMinor().value_or(0) * 100000 +
4229 VT.getSubminor().value_or(0);
4230 }
4231
4232 // Mimicking gcc's behavior, trigraphs are only enabled if -trigraphs
4233 // is specified, or -std is set to a conforming mode.
4234 // Trigraphs are disabled by default in C++17 and C23 onwards.
4235 // For z/OS, trigraphs are enabled by default (without regard to the above).
4236 Opts.Trigraphs =
4237 (!Opts.GNUMode && !Opts.MSVCCompat && !Opts.CPlusPlus17 && !Opts.C23) ||
4238 T.isOSzOS();
4239 Opts.Trigraphs =
4240 Args.hasFlag(OPT_ftrigraphs, OPT_fno_trigraphs, Opts.Trigraphs);
4241
4242 Opts.ZOSExt =
4243 Args.hasFlag(OPT_fzos_extensions, OPT_fno_zos_extensions, T.isOSzOS());
4244
4245 Opts.Blocks = Args.hasArg(OPT_fblocks) || (Opts.OpenCL
4246 && Opts.OpenCLVersion == 200);
4247
4248 bool HasConvergentOperations = Opts.isTargetDevice() || Opts.OpenCL ||
4249 Opts.HLSL || T.isAMDGPU() || T.isNVPTX();
4250 Opts.ConvergentFunctions =
4251 Args.hasFlag(OPT_fconvergent_functions, OPT_fno_convergent_functions,
4252 HasConvergentOperations);
4253
4254 Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding;
4255 if (!Opts.NoBuiltin)
4257 if (Arg *A = Args.getLastArg(options::OPT_LongDouble_Group)) {
4258 if (A->getOption().matches(options::OPT_mlong_double_64))
4259 Opts.LongDoubleSize = 64;
4260 else if (A->getOption().matches(options::OPT_mlong_double_80))
4261 Opts.LongDoubleSize = 80;
4262 else if (A->getOption().matches(options::OPT_mlong_double_128))
4263 Opts.LongDoubleSize = 128;
4264 else
4265 Opts.LongDoubleSize = 0;
4266 }
4267 if (Opts.FastRelaxedMath || Opts.CLUnsafeMath)
4268 Opts.setDefaultFPContractMode(LangOptions::FPM_Fast);
4269
4270 llvm::sort(Opts.ModuleFeatures);
4271
4272 // -mrtd option
4273 if (Arg *A = Args.getLastArg(OPT_mrtd)) {
4274 if (Opts.getDefaultCallingConv() != LangOptions::DCC_None)
4275 Diags.Report(diag::err_drv_argument_not_allowed_with)
4276 << A->getSpelling() << "-fdefault-calling-conv";
4277 else {
4278 switch (T.getArch()) {
4279 case llvm::Triple::x86:
4280 Opts.setDefaultCallingConv(LangOptions::DCC_StdCall);
4281 break;
4282 case llvm::Triple::m68k:
4283 Opts.setDefaultCallingConv(LangOptions::DCC_RtdCall);
4284 break;
4285 default:
4286 Diags.Report(diag::err_drv_argument_not_allowed_with)
4287 << A->getSpelling() << T.getTriple();
4288 }
4289 }
4290 }
4291
4292 // Check if -fopenmp is specified and set default version to 5.1.
4293 Opts.OpenMP = Args.hasArg(OPT_fopenmp) ? 51 : 0;
4294 // Check if -fopenmp-simd is specified.
4295 bool IsSimdSpecified =
4296 Args.hasFlag(options::OPT_fopenmp_simd, options::OPT_fno_openmp_simd,
4297 /*Default=*/false);
4298 Opts.OpenMPSimd = !Opts.OpenMP && IsSimdSpecified;
4299 Opts.OpenMPUseTLS =
4300 Opts.OpenMP && !Args.hasArg(options::OPT_fnoopenmp_use_tls);
4301 Opts.OpenMPIsTargetDevice =
4302 Opts.OpenMP && Args.hasArg(options::OPT_fopenmp_is_target_device);
4303 Opts.OpenMPIRBuilder =
4304 Opts.OpenMP && Args.hasArg(options::OPT_fopenmp_enable_irbuilder);
4305 bool IsTargetSpecified =
4306 Opts.OpenMPIsTargetDevice || Args.hasArg(options::OPT_offload_targets_EQ);
4307
4308 if (Opts.OpenMP || Opts.OpenMPSimd) {
4309 if (int Version = getLastArgIntValue(
4310 Args, OPT_fopenmp_version_EQ,
4311 (IsSimdSpecified || IsTargetSpecified) ? 51 : Opts.OpenMP, Diags))
4312 Opts.OpenMP = Version;
4313 // Provide diagnostic when a given target is not expected to be an OpenMP
4314 // device or host.
4315 if (!Opts.OpenMPIsTargetDevice) {
4316 switch (T.getArch()) {
4317 default:
4318 break;
4319 // Add unsupported host targets here:
4320 case llvm::Triple::nvptx:
4321 case llvm::Triple::nvptx64:
4322 Diags.Report(diag::err_drv_omp_host_target_not_supported) << T.str();
4323 break;
4324 }
4325 }
4326 }
4327
4328 // Set the flag to prevent the implementation from emitting device exception
4329 // handling code for those requiring so.
4330 if ((Opts.OpenMPIsTargetDevice && T.isGPU()) || Opts.OpenCLCPlusPlus) {
4331
4332 Opts.Exceptions = 0;
4333 Opts.CXXExceptions = 0;
4334 }
4335 if (Opts.OpenMPIsTargetDevice && T.isNVPTX()) {
4336 Opts.OpenMPCUDANumSMs =
4337 getLastArgIntValue(Args, options::OPT_fopenmp_cuda_number_of_sm_EQ,
4338 Opts.OpenMPCUDANumSMs, Diags);
4339 Opts.OpenMPCUDABlocksPerSM =
4340 getLastArgIntValue(Args, options::OPT_fopenmp_cuda_blocks_per_sm_EQ,
4341 Opts.OpenMPCUDABlocksPerSM, Diags);
4342 Opts.OpenMPCUDAReductionBufNum = getLastArgIntValue(
4343 Args, options::OPT_fopenmp_cuda_teams_reduction_recs_num_EQ,
4344 Opts.OpenMPCUDAReductionBufNum, Diags);
4345 }
4346
4347 // Set the value of the debugging flag used in the new offloading device RTL.
4348 // Set either by a specific value or to a default if not specified.
4349 if (Opts.OpenMPIsTargetDevice && (Args.hasArg(OPT_fopenmp_target_debug) ||
4350 Args.hasArg(OPT_fopenmp_target_debug_EQ))) {
4351 Opts.OpenMPTargetDebug = getLastArgIntValue(
4352 Args, OPT_fopenmp_target_debug_EQ, Opts.OpenMPTargetDebug, Diags);
4353 if (!Opts.OpenMPTargetDebug && Args.hasArg(OPT_fopenmp_target_debug))
4354 Opts.OpenMPTargetDebug = 1;
4355 }
4356
4357 if (Opts.OpenMPIsTargetDevice) {
4358 if (Args.hasArg(OPT_fopenmp_assume_teams_oversubscription))
4359 Opts.OpenMPTeamSubscription = true;
4360 if (Args.hasArg(OPT_fopenmp_assume_threads_oversubscription))
4361 Opts.OpenMPThreadSubscription = true;
4362 }
4363
4364 // Get the OpenMP target triples if any.
4365 if (Arg *A = Args.getLastArg(options::OPT_offload_targets_EQ)) {
4366 enum ArchPtrSize { Arch16Bit, Arch32Bit, Arch64Bit };
4367 auto getArchPtrSize = [](const llvm::Triple &T) {
4368 if (T.isArch16Bit())
4369 return Arch16Bit;
4370 if (T.isArch32Bit())
4371 return Arch32Bit;
4372 assert(T.isArch64Bit() && "Expected 64-bit architecture");
4373 return Arch64Bit;
4374 };
4375
4376 for (unsigned i = 0; i < A->getNumValues(); ++i) {
4377 llvm::Triple TT(A->getValue(i));
4378
4379 if (TT.getArch() == llvm::Triple::UnknownArch ||
4380 !(TT.getArch() == llvm::Triple::aarch64 || TT.isPPC() ||
4381 TT.getArch() == llvm::Triple::spirv64 ||
4382 TT.getArch() == llvm::Triple::systemz ||
4383 TT.getArch() == llvm::Triple::loongarch64 ||
4384 TT.getArch() == llvm::Triple::nvptx ||
4385 TT.getArch() == llvm::Triple::nvptx64 || TT.isAMDGCN() ||
4386 TT.getArch() == llvm::Triple::x86 ||
4387 TT.getArch() == llvm::Triple::x86_64))
4388 Diags.Report(diag::err_drv_invalid_omp_target) << A->getValue(i);
4389 else if (getArchPtrSize(T) != getArchPtrSize(TT))
4390 Diags.Report(diag::err_drv_incompatible_omp_arch)
4391 << A->getValue(i) << T.str();
4392 else
4393 Opts.OMPTargetTriples.push_back(TT);
4394 }
4395 }
4396
4397 // Set CUDA mode for OpenMP target NVPTX/AMDGCN if specified in options
4398 Opts.OpenMPCUDAMode = Opts.OpenMPIsTargetDevice &&
4399 (T.isNVPTX() || T.isAMDGCN()) &&
4400 Args.hasArg(options::OPT_fopenmp_cuda_mode);
4401
4402 // OpenACC Configuration.
4403 if (Args.hasArg(options::OPT_fopenacc))
4404 Opts.OpenACC = true;
4405
4406 if (Arg *A = Args.getLastArg(OPT_ffp_contract)) {
4407 StringRef Val = A->getValue();
4408 if (Val == "fast")
4409 Opts.setDefaultFPContractMode(LangOptions::FPM_Fast);
4410 else if (Val == "on")
4411 Opts.setDefaultFPContractMode(LangOptions::FPM_On);
4412 else if (Val == "off")
4413 Opts.setDefaultFPContractMode(LangOptions::FPM_Off);
4414 else if (Val == "fast-honor-pragmas")
4415 Opts.setDefaultFPContractMode(LangOptions::FPM_FastHonorPragmas);
4416 else
4417 Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;
4418 }
4419
4420 if (auto *A =
4421 Args.getLastArg(OPT_fsanitize_undefined_ignore_overflow_pattern_EQ)) {
4422 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
4424 llvm::StringSwitch<unsigned>(A->getValue(i))
4425 .Case("none", LangOptionsBase::None)
4426 .Case("all", LangOptionsBase::All)
4427 .Case("add-unsigned-overflow-test",
4429 .Case("add-signed-overflow-test",
4431 .Case("negated-unsigned-const", LangOptionsBase::NegUnsignedConst)
4432 .Case("unsigned-post-decr-while",
4434 .Default(0);
4435 }
4436 }
4437
4438 // Parse -fsanitize= arguments.
4439 parseSanitizerKinds("-fsanitize=", Args.getAllArgValues(OPT_fsanitize_EQ),
4440 Diags, Opts.Sanitize);
4442 "-fsanitize-ignore-for-ubsan-feature=",
4443 Args.getAllArgValues(OPT_fsanitize_ignore_for_ubsan_feature_EQ), Diags,
4445 Opts.NoSanitizeFiles = Args.getAllArgValues(OPT_fsanitize_ignorelist_EQ);
4446 std::vector<std::string> systemIgnorelists =
4447 Args.getAllArgValues(OPT_fsanitize_system_ignorelist_EQ);
4448 Opts.NoSanitizeFiles.insert(Opts.NoSanitizeFiles.end(),
4449 systemIgnorelists.begin(),
4450 systemIgnorelists.end());
4451
4452 if (Arg *A = Args.getLastArg(OPT_fclang_abi_compat_EQ)) {
4453 Opts.setClangABICompat(LangOptions::ClangABI::Latest);
4454
4455 StringRef Ver = A->getValue();
4456 std::pair<StringRef, StringRef> VerParts = Ver.split('.');
4457 int Major, Minor = 0;
4458
4459 // Check the version number is valid: either 3.x (0 <= x <= 9) or
4460 // y or y.0 (4 <= y <= current version).
4461 if (!VerParts.first.starts_with("0") &&
4462 !VerParts.first.getAsInteger(10, Major) && 3 <= Major &&
4463 Major <= MAX_CLANG_ABI_COMPAT_VERSION &&
4464 (Major == 3
4465 ? VerParts.second.size() == 1 &&
4466 !VerParts.second.getAsInteger(10, Minor)
4467 : VerParts.first.size() == Ver.size() || VerParts.second == "0")) {
4468 // Got a valid version number.
4469#define ABI_VER_MAJOR_MINOR(Major_, Minor_) \
4470 if (std::tuple(Major, Minor) <= std::tuple(Major_, Minor_)) \
4471 Opts.setClangABICompat(LangOptions::ClangABI::Ver##Major_##_##Minor_); \
4472 else
4473#define ABI_VER_MAJOR(Major_) \
4474 if (Major <= Major_) \
4475 Opts.setClangABICompat(LangOptions::ClangABI::Ver##Major_); \
4476 else
4477#define ABI_VER_LATEST(Latest) \
4478 { /* Equivalent to latest version - do nothing */ \
4479 }
4480#include "clang/Basic/ABIVersions.def"
4481 } else if (Ver != "latest") {
4482 Diags.Report(diag::err_drv_invalid_value)
4483 << A->getAsString(Args) << A->getValue();
4484 }
4485 }
4486
4487 if (Arg *A = Args.getLastArg(OPT_msign_return_address_EQ)) {
4488 StringRef SignScope = A->getValue();
4489
4490 if (SignScope.equals_insensitive("none"))
4491 Opts.setSignReturnAddressScope(
4493 else if (SignScope.equals_insensitive("all"))
4494 Opts.setSignReturnAddressScope(
4496 else if (SignScope.equals_insensitive("non-leaf"))
4497 Opts.setSignReturnAddressScope(
4499 else
4500 Diags.Report(diag::err_drv_invalid_value)
4501 << A->getAsString(Args) << SignScope;
4502
4503 if (Arg *A = Args.getLastArg(OPT_msign_return_address_key_EQ)) {
4504 StringRef SignKey = A->getValue();
4505 if (!SignScope.empty() && !SignKey.empty()) {
4506 if (SignKey == "a_key")
4507 Opts.setSignReturnAddressKey(
4509 else if (SignKey == "b_key")
4510 Opts.setSignReturnAddressKey(
4512 else
4513 Diags.Report(diag::err_drv_invalid_value)
4514 << A->getAsString(Args) << SignKey;
4515 }
4516 }
4517 }
4518
4519 // The value can be empty, which indicates the system default should be used.
4520 StringRef CXXABI = Args.getLastArgValue(OPT_fcxx_abi_EQ);
4521 if (!CXXABI.empty()) {
4523 Diags.Report(diag::err_invalid_cxx_abi) << CXXABI;
4524 } else {
4526 if (!TargetCXXABI::isSupportedCXXABI(T, Kind))
4527 Diags.Report(diag::err_unsupported_cxx_abi) << CXXABI << T.str();
4528 else
4529 Opts.CXXABI = Kind;
4530 }
4531 }
4532
4533 Opts.RelativeCXXABIVTables =
4534 Args.hasFlag(options::OPT_fexperimental_relative_cxx_abi_vtables,
4535 options::OPT_fno_experimental_relative_cxx_abi_vtables,
4537
4538 // RTTI is on by default.
4539 bool HasRTTI = !Args.hasArg(options::OPT_fno_rtti);
4540 Opts.OmitVTableRTTI =
4541 Args.hasFlag(options::OPT_fexperimental_omit_vtable_rtti,
4542 options::OPT_fno_experimental_omit_vtable_rtti, false);
4543 if (Opts.OmitVTableRTTI && HasRTTI)
4544 Diags.Report(diag::err_drv_using_omit_rtti_component_without_no_rtti);
4545
4546 for (const auto &A : Args.getAllArgValues(OPT_fmacro_prefix_map_EQ)) {
4547 auto Split = StringRef(A).split('=');
4548 Opts.MacroPrefixMap.insert(
4549 {std::string(Split.first), std::string(Split.second)});
4550 }
4551
4553 !Args.getLastArg(OPT_fno_file_reproducible) &&
4554 (Args.getLastArg(OPT_ffile_compilation_dir_EQ) ||
4555 Args.getLastArg(OPT_fmacro_prefix_map_EQ) ||
4556 Args.getLastArg(OPT_ffile_reproducible));
4557
4558 // Error if -mvscale-min is unbounded.
4559 if (Arg *A = Args.getLastArg(options::OPT_mvscale_min_EQ)) {
4560 unsigned VScaleMin;
4561 if (StringRef(A->getValue()).getAsInteger(10, VScaleMin) || VScaleMin == 0)
4562 Diags.Report(diag::err_cc1_unbounded_vscale_min);
4563 }
4564 if (Arg *A = Args.getLastArg(options::OPT_mvscale_streaming_min_EQ)) {
4565 unsigned VScaleMin;
4566 if (StringRef(A->getValue()).getAsInteger(10, VScaleMin) || VScaleMin == 0)
4567 Diags.Report(diag::err_cc1_unbounded_vscale_min);
4568 }
4569
4570 if (const Arg *A = Args.getLastArg(OPT_frandomize_layout_seed_file_EQ)) {
4571 std::ifstream SeedFile(A->getValue(0));
4572
4573 if (!SeedFile.is_open())
4574 Diags.Report(diag::err_drv_cannot_open_randomize_layout_seed_file)
4575 << A->getValue(0);
4576
4577 std::getline(SeedFile, Opts.RandstructSeed);
4578 }
4579
4580 if (const Arg *A = Args.getLastArg(OPT_frandomize_layout_seed_EQ))
4581 Opts.RandstructSeed = A->getValue(0);
4582
4583 if (const auto *Arg = Args.getLastArg(options::OPT_falloc_token_max_EQ)) {
4584 StringRef S = Arg->getValue();
4585 uint64_t Value = 0;
4586 if (S.getAsInteger(0, Value))
4587 Diags.Report(diag::err_drv_invalid_value) << Arg->getAsString(Args) << S;
4588 else
4589 Opts.AllocTokenMax = Value;
4590 }
4591
4592 if (const auto *Arg = Args.getLastArg(options::OPT_falloc_token_mode_EQ)) {
4593 StringRef S = Arg->getValue();
4594 if (auto Mode = getAllocTokenModeFromString(S))
4595 Opts.AllocTokenMode = Mode;
4596 else
4597 Diags.Report(diag::err_drv_invalid_value) << Arg->getAsString(Args) << S;
4598 }
4599
4600 // Enable options for matrix types.
4601 if (Opts.MatrixTypes) {
4602 if (const Arg *A = Args.getLastArg(OPT_fmatrix_memory_layout_EQ)) {
4603 StringRef ClangValue = A->getValue();
4604 if (ClangValue == "row-major")
4605 Opts.setDefaultMatrixMemoryLayout(
4607 else
4608 Opts.setDefaultMatrixMemoryLayout(
4610
4611 for (Arg *A : Args.filtered(options::OPT_mllvm)) {
4612 StringRef OptValue = A->getValue();
4613 if (OptValue.consume_front("-matrix-default-layout=") &&
4614 ClangValue != OptValue)
4615 Diags.Report(diag::err_conflicting_matrix_layout_flags)
4616 << ClangValue << OptValue;
4617 }
4618 }
4619 }
4620
4621 // Validate options for HLSL
4622 if (Opts.HLSL) {
4623 // TODO: Revisit restricting SPIR-V to logical once we've figured out how to
4624 // handle PhysicalStorageBuffer64 memory model
4625 if (T.isDXIL() || T.isSPIRVLogical()) {
4626 enum { ShaderModel, VulkanEnv, ShaderStage };
4627 enum { OS, Environment };
4628
4629 int ExpectedOS = T.isSPIRVLogical() ? VulkanEnv : ShaderModel;
4630
4631 if (T.getOSName().empty()) {
4632 Diags.Report(diag::err_drv_hlsl_bad_shader_required_in_target)
4633 << ExpectedOS << OS << T.str();
4634 } else if (T.getEnvironmentName().empty()) {
4635 Diags.Report(diag::err_drv_hlsl_bad_shader_required_in_target)
4636 << ShaderStage << Environment << T.str();
4637 } else if (!T.isShaderStageEnvironment()) {
4638 Diags.Report(diag::err_drv_hlsl_bad_shader_unsupported)
4639 << ShaderStage << T.getEnvironmentName() << T.str();
4640 }
4641
4642 if (T.isDXIL()) {
4643 if (!T.isShaderModelOS() || T.getOSVersion() == VersionTuple(0)) {
4644 Diags.Report(diag::err_drv_hlsl_bad_shader_unsupported)
4645 << ShaderModel << T.getOSName() << T.str();
4646 }
4647 // Validate that if fnative-half-type is given, that
4648 // the language standard is at least hlsl2018, and that
4649 // the target shader model is at least 6.2.
4650 if (Args.getLastArg(OPT_fnative_half_type) ||
4651 Args.getLastArg(OPT_fnative_int16_type)) {
4652 const LangStandard &Std =
4654 if (!(Opts.LangStd >= LangStandard::lang_hlsl2018 &&
4655 T.getOSVersion() >= VersionTuple(6, 2)))
4656 Diags.Report(diag::err_drv_hlsl_16bit_types_unsupported)
4657 << "-enable-16bit-types" << true << Std.getName()
4658 << T.getOSVersion().getAsString();
4659 }
4660 } else if (T.isSPIRVLogical()) {
4661 if (!T.isVulkanOS() || T.getVulkanVersion() == VersionTuple(0)) {
4662 Diags.Report(diag::err_drv_hlsl_bad_shader_unsupported)
4663 << VulkanEnv << T.getOSName() << T.str();
4664 }
4665 if (Args.getLastArg(OPT_fnative_half_type) ||
4666 Args.getLastArg(OPT_fnative_int16_type)) {
4667 const char *Str = Args.getLastArg(OPT_fnative_half_type)
4668 ? "-fnative-half-type"
4669 : "-fnative-int16-type";
4670 const LangStandard &Std =
4672 if (!(Opts.LangStd >= LangStandard::lang_hlsl2018))
4673 Diags.Report(diag::err_drv_hlsl_16bit_types_unsupported)
4674 << Str << false << Std.getName();
4675 }
4676 } else {
4677 llvm_unreachable("expected DXIL or SPIR-V target");
4678 }
4679 } else
4680 Diags.Report(diag::err_drv_hlsl_unsupported_target) << T.str();
4681
4682 if (Opts.LangStd < LangStandard::lang_hlsl202x) {
4683 const LangStandard &Requested =
4685 const LangStandard &Recommended =
4686 LangStandard::getLangStandardForKind(LangStandard::lang_hlsl202x);
4687 Diags.Report(diag::warn_hlsl_langstd_minimal)
4688 << Requested.getName() << Recommended.getName();
4689 }
4690 }
4691
4692 return Diags.getNumErrors() == NumErrorsBefore;
4693}
4694
4696 switch (Action) {
4698 case frontend::ASTDump:
4699 case frontend::ASTPrint:
4700 case frontend::ASTView:
4702 case frontend::EmitBC:
4703 case frontend::EmitCIR:
4704 case frontend::EmitHTML:
4705 case frontend::EmitLLVM:
4708 case frontend::EmitObj:
4710 case frontend::FixIt:
4725 return false;
4726
4730 case frontend::InitOnly:
4736 return true;
4737 }
4738 llvm_unreachable("invalid frontend action");
4739}
4740
4742 switch (Action) {
4744 case frontend::EmitBC:
4745 case frontend::EmitCIR:
4746 case frontend::EmitHTML:
4747 case frontend::EmitLLVM:
4750 case frontend::EmitObj:
4757 return true;
4759 case frontend::ASTDump:
4760 case frontend::ASTPrint:
4761 case frontend::ASTView:
4763 case frontend::FixIt:
4775 case frontend::InitOnly:
4781 return false;
4782 }
4783 llvm_unreachable("invalid frontend action");
4784}
4785
4787 ArgumentConsumer Consumer,
4788 const LangOptions &LangOpts,
4789 const FrontendOptions &FrontendOpts,
4790 const CodeGenOptions &CodeGenOpts) {
4791 const PreprocessorOptions *PreprocessorOpts = &Opts;
4792
4793#define PREPROCESSOR_OPTION_WITH_MARSHALLING(...) \
4794 GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
4795#include "clang/Options/Options.inc"
4796#undef PREPROCESSOR_OPTION_WITH_MARSHALLING
4797
4798 if (Opts.PCHWithHdrStop && !Opts.PCHWithHdrStopCreate)
4799 GenerateArg(Consumer, OPT_pch_through_hdrstop_use);
4800
4801 for (const auto &D : Opts.DeserializedPCHDeclsToErrorOn)
4802 GenerateArg(Consumer, OPT_error_on_deserialized_pch_decl, D);
4803
4804 if (Opts.PrecompiledPreambleBytes != std::make_pair(0u, false))
4805 GenerateArg(Consumer, OPT_preamble_bytes_EQ,
4806 Twine(Opts.PrecompiledPreambleBytes.first) + "," +
4807 (Opts.PrecompiledPreambleBytes.second ? "1" : "0"));
4808
4809 for (const auto &M : Opts.Macros) {
4810 // Don't generate __CET__ macro definitions. They are implied by the
4811 // -fcf-protection option that is generated elsewhere.
4812 if (M.first == "__CET__=1" && !M.second &&
4813 !CodeGenOpts.CFProtectionReturn && CodeGenOpts.CFProtectionBranch)
4814 continue;
4815 if (M.first == "__CET__=2" && !M.second && CodeGenOpts.CFProtectionReturn &&
4816 !CodeGenOpts.CFProtectionBranch)
4817 continue;
4818 if (M.first == "__CET__=3" && !M.second && CodeGenOpts.CFProtectionReturn &&
4819 CodeGenOpts.CFProtectionBranch)
4820 continue;
4821
4822 GenerateArg(Consumer, M.second ? OPT_U : OPT_D, M.first);
4823 }
4824
4825 for (const auto &I : Opts.Includes) {
4826 // Don't generate OpenCL includes. They are implied by other flags that are
4827 // generated elsewhere.
4828 if (LangOpts.OpenCL && LangOpts.IncludeDefaultHeader &&
4829 ((LangOpts.DeclareOpenCLBuiltins && I == "opencl-c-base.h") ||
4830 I == "opencl-c.h"))
4831 continue;
4832 // Don't generate HLSL includes. They are implied by other flags that are
4833 // generated elsewhere.
4834 if (LangOpts.HLSL && I == "hlsl.h")
4835 continue;
4836
4837 GenerateArg(Consumer, OPT_include, I);
4838 }
4839
4840 for (const auto &CI : Opts.ChainedIncludes)
4841 GenerateArg(Consumer, OPT_chain_include, CI);
4842
4843 for (const auto &RF : Opts.RemappedFiles)
4844 GenerateArg(Consumer, OPT_remap_file, RF.first + ";" + RF.second);
4845
4846 if (Opts.SourceDateEpoch)
4847 GenerateArg(Consumer, OPT_source_date_epoch, Twine(*Opts.SourceDateEpoch));
4848
4849 if (Opts.DefineTargetOSMacros)
4850 GenerateArg(Consumer, OPT_fdefine_target_os_macros);
4851
4852 for (const auto &EmbedEntry : Opts.EmbedEntries)
4853 GenerateArg(Consumer, OPT_embed_dir_EQ, EmbedEntry);
4854
4855 // Don't handle LexEditorPlaceholders. It is implied by the action that is
4856 // generated elsewhere.
4857}
4858
4859static bool ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
4860 DiagnosticsEngine &Diags,
4861 frontend::ActionKind Action,
4862 const FrontendOptions &FrontendOpts) {
4863 unsigned NumErrorsBefore = Diags.getNumErrors();
4864
4865 PreprocessorOptions *PreprocessorOpts = &Opts;
4866
4867#define PREPROCESSOR_OPTION_WITH_MARSHALLING(...) \
4868 PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
4869#include "clang/Options/Options.inc"
4870#undef PREPROCESSOR_OPTION_WITH_MARSHALLING
4871
4872 Opts.PCHWithHdrStop = Args.hasArg(OPT_pch_through_hdrstop_create) ||
4873 Args.hasArg(OPT_pch_through_hdrstop_use);
4874
4875 for (const auto *A : Args.filtered(OPT_error_on_deserialized_pch_decl))
4876 Opts.DeserializedPCHDeclsToErrorOn.insert(A->getValue());
4877
4878 if (const Arg *A = Args.getLastArg(OPT_preamble_bytes_EQ)) {
4879 StringRef Value(A->getValue());
4880 size_t Comma = Value.find(',');
4881 unsigned Bytes = 0;
4882 unsigned EndOfLine = 0;
4883
4884 if (Comma == StringRef::npos ||
4885 Value.substr(0, Comma).getAsInteger(10, Bytes) ||
4886 Value.substr(Comma + 1).getAsInteger(10, EndOfLine))
4887 Diags.Report(diag::err_drv_preamble_format);
4888 else {
4889 Opts.PrecompiledPreambleBytes.first = Bytes;
4890 Opts.PrecompiledPreambleBytes.second = (EndOfLine != 0);
4891 }
4892 }
4893
4894 // Add macros from the command line.
4895 for (const auto *A : Args.filtered(OPT_D, OPT_U)) {
4896 if (A->getOption().matches(OPT_D))
4897 Opts.addMacroDef(A->getValue());
4898 else
4899 Opts.addMacroUndef(A->getValue());
4900 }
4901
4902 // Add the ordered list of -includes.
4903 for (const auto *A : Args.filtered(OPT_include))
4904 Opts.Includes.emplace_back(A->getValue());
4905
4906 for (const auto *A : Args.filtered(OPT_chain_include))
4907 Opts.ChainedIncludes.emplace_back(A->getValue());
4908
4909 for (const auto *A : Args.filtered(OPT_remap_file)) {
4910 std::pair<StringRef, StringRef> Split = StringRef(A->getValue()).split(';');
4911
4912 if (Split.second.empty()) {
4913 Diags.Report(diag::err_drv_invalid_remap_file) << A->getAsString(Args);
4914 continue;
4915 }
4916
4917 Opts.addRemappedFile(Split.first, Split.second);
4918 }
4919
4920 if (const Arg *A = Args.getLastArg(OPT_source_date_epoch)) {
4921 StringRef Epoch = A->getValue();
4922 // SOURCE_DATE_EPOCH, if specified, must be a non-negative decimal integer.
4923 // On time64 systems, pick 253402300799 (the UNIX timestamp of
4924 // 9999-12-31T23:59:59Z) as the upper bound.
4925 const uint64_t MaxTimestamp =
4926 std::min<uint64_t>(std::numeric_limits<time_t>::max(), 253402300799);
4927 uint64_t V;
4928 if (Epoch.getAsInteger(10, V) || V > MaxTimestamp) {
4929 Diags.Report(diag::err_fe_invalid_source_date_epoch)
4930 << Epoch << MaxTimestamp;
4931 } else {
4932 Opts.SourceDateEpoch = V;
4933 }
4934 }
4935
4936 for (const auto *A : Args.filtered(OPT_embed_dir_EQ)) {
4937 StringRef Val = A->getValue();
4938 Opts.EmbedEntries.push_back(std::string(Val));
4939 }
4940
4941 // Always avoid lexing editor placeholders when we're just running the
4942 // preprocessor as we never want to emit the
4943 // "editor placeholder in source file" error in PP only mode.
4944 if (isStrictlyPreprocessorAction(Action))
4945 Opts.LexEditorPlaceholders = false;
4946
4948 Args.hasFlag(OPT_fdefine_target_os_macros,
4949 OPT_fno_define_target_os_macros, Opts.DefineTargetOSMacros);
4950
4951 return Diags.getNumErrors() == NumErrorsBefore;
4952}
4953
4954static void
4956 ArgumentConsumer Consumer,
4957 frontend::ActionKind Action) {
4958 const PreprocessorOutputOptions &PreprocessorOutputOpts = Opts;
4959
4960#define PREPROCESSOR_OUTPUT_OPTION_WITH_MARSHALLING(...) \
4961 GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
4962#include "clang/Options/Options.inc"
4963#undef PREPROCESSOR_OUTPUT_OPTION_WITH_MARSHALLING
4964
4965 bool Generate_dM = isStrictlyPreprocessorAction(Action) && !Opts.ShowCPP;
4966 if (Generate_dM)
4967 GenerateArg(Consumer, OPT_dM);
4968 if (!Generate_dM && Opts.ShowMacros)
4969 GenerateArg(Consumer, OPT_dD);
4970 if (Opts.DirectivesOnly)
4971 GenerateArg(Consumer, OPT_fdirectives_only);
4972}
4973
4975 ArgList &Args, DiagnosticsEngine &Diags,
4976 frontend::ActionKind Action) {
4977 unsigned NumErrorsBefore = Diags.getNumErrors();
4978
4979 PreprocessorOutputOptions &PreprocessorOutputOpts = Opts;
4980
4981#define PREPROCESSOR_OUTPUT_OPTION_WITH_MARSHALLING(...) \
4982 PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
4983#include "clang/Options/Options.inc"
4984#undef PREPROCESSOR_OUTPUT_OPTION_WITH_MARSHALLING
4985
4986 Opts.ShowCPP = isStrictlyPreprocessorAction(Action) && !Args.hasArg(OPT_dM);
4987 Opts.ShowMacros = Args.hasArg(OPT_dM) || Args.hasArg(OPT_dD);
4988 Opts.DirectivesOnly = Args.hasArg(OPT_fdirectives_only);
4989
4990 return Diags.getNumErrors() == NumErrorsBefore;
4991}
4992
4993static void GenerateTargetArgs(const TargetOptions &Opts,
4994 ArgumentConsumer Consumer) {
4995 const TargetOptions *TargetOpts = &Opts;
4996#define TARGET_OPTION_WITH_MARSHALLING(...) \
4997 GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
4998#include "clang/Options/Options.inc"
4999#undef TARGET_OPTION_WITH_MARSHALLING
5000
5001 if (!Opts.SDKVersion.empty())
5002 GenerateArg(Consumer, OPT_target_sdk_version_EQ,
5003 Opts.SDKVersion.getAsString());
5004 if (!Opts.DarwinTargetVariantSDKVersion.empty())
5005 GenerateArg(Consumer, OPT_darwin_target_variant_sdk_version_EQ,
5006 Opts.DarwinTargetVariantSDKVersion.getAsString());
5007}
5008
5009static bool ParseTargetArgs(TargetOptions &Opts, ArgList &Args,
5010 DiagnosticsEngine &Diags) {
5011 unsigned NumErrorsBefore = Diags.getNumErrors();
5012
5013 TargetOptions *TargetOpts = &Opts;
5014
5015#define TARGET_OPTION_WITH_MARSHALLING(...) \
5016 PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
5017#include "clang/Options/Options.inc"
5018#undef TARGET_OPTION_WITH_MARSHALLING
5019
5020 if (Arg *A = Args.getLastArg(options::OPT_target_sdk_version_EQ)) {
5021 llvm::VersionTuple Version;
5022 if (Version.tryParse(A->getValue()))
5023 Diags.Report(diag::err_drv_invalid_value)
5024 << A->getAsString(Args) << A->getValue();
5025 else
5026 Opts.SDKVersion = Version;
5027 }
5028 if (Arg *A =
5029 Args.getLastArg(options::OPT_darwin_target_variant_sdk_version_EQ)) {
5030 llvm::VersionTuple Version;
5031 if (Version.tryParse(A->getValue()))
5032 Diags.Report(diag::err_drv_invalid_value)
5033 << A->getAsString(Args) << A->getValue();
5034 else
5035 Opts.DarwinTargetVariantSDKVersion = Version;
5036 }
5037
5038 return Diags.getNumErrors() == NumErrorsBefore;
5039}
5040
5041bool CompilerInvocation::CreateFromArgsImpl(
5042 CompilerInvocation &Res, ArrayRef<const char *> CommandLineArgs,
5043 DiagnosticsEngine &Diags, const char *Argv0) {
5044 unsigned NumErrorsBefore = Diags.getNumErrors();
5045
5046 // Parse the arguments.
5047 const OptTable &Opts = getDriverOptTable();
5048 llvm::opt::Visibility VisibilityMask(options::CC1Option);
5049 unsigned MissingArgIndex, MissingArgCount;
5050 InputArgList Args = Opts.ParseArgs(CommandLineArgs, MissingArgIndex,
5051 MissingArgCount, VisibilityMask);
5052 LangOptions &LangOpts = Res.getLangOpts();
5053
5054 // Check for missing argument error.
5055 if (MissingArgCount)
5056 Diags.Report(diag::err_drv_missing_argument)
5057 << Args.getArgString(MissingArgIndex) << MissingArgCount;
5058
5059 // Issue errors on unknown arguments.
5060 for (const auto *A : Args.filtered(OPT_UNKNOWN)) {
5061 auto ArgString = A->getAsString(Args);
5062 std::string Nearest;
5063 if (Opts.findNearest(ArgString, Nearest, VisibilityMask) > 1)
5064 Diags.Report(diag::err_drv_unknown_argument) << ArgString;
5065 else
5066 Diags.Report(diag::err_drv_unknown_argument_with_suggestion)
5067 << ArgString << Nearest;
5068 }
5069
5070 ParseFileSystemArgs(Res.getFileSystemOpts(), Args, Diags);
5071 ParseMigratorArgs(Res.getMigratorOpts(), Args, Diags);
5072 ParseAnalyzerArgs(Res.getAnalyzerOpts(), Args, Diags);
5073 ParseDiagnosticArgs(Res.getDiagnosticOpts(), Args, &Diags,
5074 /*DefaultDiagColor=*/false);
5075 ParseFrontendArgs(Res.getFrontendOpts(), Args, Diags, LangOpts.IsHeaderFile);
5076 // FIXME: We shouldn't have to pass the DashX option around here
5077 InputKind DashX = Res.getFrontendOpts().DashX;
5078 ParseTargetArgs(Res.getTargetOpts(), Args, Diags);
5079 llvm::Triple T(Res.getTargetOpts().Triple);
5080 ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), Args, Diags);
5081 if (Res.getFrontendOpts().GenReducedBMI ||
5088 }
5089 ParseAPINotesArgs(Res.getAPINotesOpts(), Args, Diags);
5090
5091 ParsePointerAuthArgs(LangOpts, Args, Diags);
5092
5093 ParseLangArgs(LangOpts, Args, DashX, T, Res.getPreprocessorOpts().Includes,
5094 Diags);
5096 LangOpts.ObjCExceptions = 1;
5097
5098 for (auto Warning : Res.getDiagnosticOpts().Warnings) {
5099 if (Warning == "misexpect" &&
5100 !Diags.isIgnored(diag::warn_profile_data_misexpect, SourceLocation())) {
5101 Res.getCodeGenOpts().MisExpect = true;
5102 }
5103 }
5104
5105 if (LangOpts.CUDA) {
5106 // During CUDA device-side compilation, the aux triple is the
5107 // triple used for host compilation.
5108 if (LangOpts.CUDAIsDevice)
5110 }
5111
5112 if (LangOpts.OpenACC && !Res.getFrontendOpts().UseClangIRPipeline &&
5114 Diags.Report(diag::warn_drv_openacc_without_cir);
5115
5116 // Set the triple of the host for OpenMP device compile.
5117 if (LangOpts.OpenMPIsTargetDevice)
5119
5120 ParseCodeGenArgs(Res.getCodeGenOpts(), Args, DashX, Diags, T,
5122
5123 // FIXME: Override value name discarding when asan or msan is used because the
5124 // backend passes depend on the name of the alloca in order to print out
5125 // names.
5126 Res.getCodeGenOpts().DiscardValueNames &=
5127 !LangOpts.Sanitize.has(SanitizerKind::Address) &&
5128 !LangOpts.Sanitize.has(SanitizerKind::KernelAddress) &&
5129 !LangOpts.Sanitize.has(SanitizerKind::Memory) &&
5130 !LangOpts.Sanitize.has(SanitizerKind::KernelMemory);
5131
5132 ParsePreprocessorArgs(Res.getPreprocessorOpts(), Args, Diags,
5134 Res.getFrontendOpts());
5137
5141 if (!Res.getDependencyOutputOpts().OutputFile.empty() &&
5142 Res.getDependencyOutputOpts().Targets.empty())
5143 Diags.Report(diag::err_fe_dependency_file_requires_MT);
5144
5145 // If sanitizer is enabled, disable OPT_ffine_grained_bitfield_accesses.
5146 if (Res.getCodeGenOpts().FineGrainedBitfieldAccesses &&
5147 !Res.getLangOpts().Sanitize.empty()) {
5148 Res.getCodeGenOpts().FineGrainedBitfieldAccesses = false;
5149 Diags.Report(diag::warn_drv_fine_grained_bitfield_accesses_ignored);
5150 }
5151
5152 // Store the command-line for using in the CodeView backend.
5153 if (Res.getCodeGenOpts().CodeViewCommandLine) {
5154 Res.getCodeGenOpts().Argv0 = Argv0;
5155 append_range(Res.getCodeGenOpts().CommandLineArgs, CommandLineArgs);
5156 }
5157
5158 if (!Res.getCodeGenOpts().ProfileInstrumentUsePath.empty() &&
5159 Res.getCodeGenOpts().getProfileUse() ==
5160 llvm::driver::ProfileInstrKind::ProfileNone)
5161 Diags.Report(diag::err_drv_profile_instrument_use_path_with_no_kind);
5162
5163 FixupInvocation(Res, Diags, Args, DashX);
5164
5165 return Diags.getNumErrors() == NumErrorsBefore;
5166}
5167
5169 ArrayRef<const char *> CommandLineArgs,
5170 DiagnosticsEngine &Diags,
5171 const char *Argv0) {
5172 CompilerInvocation DummyInvocation;
5173
5174 return RoundTrip(
5175 [](CompilerInvocation &Invocation, ArrayRef<const char *> CommandLineArgs,
5176 DiagnosticsEngine &Diags, const char *Argv0) {
5177 return CreateFromArgsImpl(Invocation, CommandLineArgs, Diags, Argv0);
5178 },
5180 StringAllocator SA) {
5181 Args.push_back("-cc1");
5182 Invocation.generateCC1CommandLine(Args, SA);
5183 },
5184 Invocation, DummyInvocation, CommandLineArgs, Diags, Argv0);
5185}
5186
5188 // FIXME: Consider using SHA1 instead of MD5.
5189 llvm::HashBuilder<llvm::MD5, llvm::endianness::native> HBuilder;
5190
5191 // Note: For QoI reasons, the things we use as a hash here should all be
5192 // dumped via the -module-info flag.
5193
5194 // Start the signature with the compiler version.
5195 HBuilder.add(getClangFullRepositoryVersion());
5196
5197 // Also include the serialization version, in case LLVM_APPEND_VC_REV is off
5198 // and getClangFullRepositoryVersion() doesn't include git revision.
5200
5201 // Extend the signature with the language options
5202 // FIXME: Replace with C++20 `using enum LangOptions::CompatibilityKind`.
5204#define LANGOPT(Name, Bits, Default, Compatibility, Description) \
5205 if constexpr (CK::Compatibility != CK::Benign) \
5206 HBuilder.add(LangOpts->Name);
5207#define ENUM_LANGOPT(Name, Type, Bits, Default, Compatibility, Description) \
5208 if constexpr (CK::Compatibility != CK::Benign) \
5209 HBuilder.add(static_cast<unsigned>(LangOpts->get##Name()));
5210#include "clang/Basic/LangOptions.def"
5211
5212 HBuilder.addRange(getLangOpts().ModuleFeatures);
5213
5214 HBuilder.add(getLangOpts().ObjCRuntime);
5215 HBuilder.addRange(getLangOpts().CommentOpts.BlockCommandNames);
5216
5217 // Extend the signature with the target options.
5218 HBuilder.add(getTargetOpts().Triple, getTargetOpts().CPU,
5219 getTargetOpts().TuneCPU, getTargetOpts().ABI);
5220 HBuilder.addRange(getTargetOpts().FeaturesAsWritten);
5221
5222 // Extend the signature with preprocessor options.
5223 const PreprocessorOptions &ppOpts = getPreprocessorOpts();
5224 HBuilder.add(ppOpts.UsePredefines, ppOpts.DetailedRecord);
5225
5226 const HeaderSearchOptions &hsOpts = getHeaderSearchOpts();
5227 for (const auto &Macro : getPreprocessorOpts().Macros) {
5228 // If we're supposed to ignore this macro for the purposes of modules,
5229 // don't put it into the hash.
5230 if (!hsOpts.ModulesIgnoreMacros.empty()) {
5231 // Check whether we're ignoring this macro.
5232 StringRef MacroDef = Macro.first;
5233 if (hsOpts.ModulesIgnoreMacros.count(
5234 llvm::CachedHashString(MacroDef.split('=').first)))
5235 continue;
5236 }
5237
5238 HBuilder.add(Macro);
5239 }
5240
5241 // Extend the signature with the sysroot and other header search options.
5242 HBuilder.add(hsOpts.Sysroot, hsOpts.ModuleFormat, hsOpts.UseDebugInfo,
5244 hsOpts.UseStandardCXXIncludes, hsOpts.UseLibcxx,
5246 HBuilder.add(hsOpts.ResourceDir);
5247
5248 if (hsOpts.ModulesStrictContextHash) {
5249 HBuilder.addRange(hsOpts.SystemHeaderPrefixes);
5250 HBuilder.addRange(hsOpts.UserEntries);
5251 HBuilder.addRange(hsOpts.VFSOverlayFiles);
5252
5253 const DiagnosticOptions &diagOpts = getDiagnosticOpts();
5254#define DIAGOPT(Name, Bits, Default) HBuilder.add(diagOpts.Name);
5255#define ENUM_DIAGOPT(Name, Type, Bits, Default) \
5256 HBuilder.add(diagOpts.get##Name());
5257#include "clang/Basic/DiagnosticOptions.def"
5258#undef DIAGOPT
5259#undef ENUM_DIAGOPT
5260 }
5261
5262 // Extend the signature with the user build path.
5263 HBuilder.add(hsOpts.ModuleUserBuildPath);
5264
5265 // Extend the signature with the module file extensions.
5266 for (const auto &ext : getFrontendOpts().ModuleFileExtensions)
5267 ext->hashExtension(HBuilder);
5268
5269 // Extend the signature with the Swift version for API notes.
5271 if (!APINotesOpts.SwiftVersion.empty()) {
5272 HBuilder.add(APINotesOpts.SwiftVersion.getMajor());
5273 if (auto Minor = APINotesOpts.SwiftVersion.getMinor())
5274 HBuilder.add(*Minor);
5275 if (auto Subminor = APINotesOpts.SwiftVersion.getSubminor())
5276 HBuilder.add(*Subminor);
5277 if (auto Build = APINotesOpts.SwiftVersion.getBuild())
5278 HBuilder.add(*Build);
5279 }
5280
5281 // Extend the signature with affecting codegen options.
5282 {
5284#define CODEGENOPT(Name, Bits, Default, Compatibility) \
5285 if constexpr (CK::Compatibility != CK::Benign) \
5286 HBuilder.add(CodeGenOpts->Name);
5287#define ENUM_CODEGENOPT(Name, Type, Bits, Default, Compatibility) \
5288 if constexpr (CK::Compatibility != CK::Benign) \
5289 HBuilder.add(static_cast<unsigned>(CodeGenOpts->get##Name()));
5290#define DEBUGOPT(Name, Bits, Default, Compatibility)
5291#define VALUE_DEBUGOPT(Name, Bits, Default, Compatibility)
5292#define ENUM_DEBUGOPT(Name, Type, Bits, Default, Compatibility)
5293#include "clang/Basic/CodeGenOptions.def"
5294 }
5295
5296 // When compiling with -gmodules, also hash -fdebug-prefix-map as it
5297 // affects the debug info in the PCM.
5298 if (getCodeGenOpts().DebugTypeExtRefs)
5299 HBuilder.addRange(getCodeGenOpts().DebugPrefixMap);
5300
5301 // Extend the signature with the affecting debug options.
5302 if (getHeaderSearchOpts().ModuleFormat == "obj") {
5303 // FIXME: Replace with C++20 `using enum CodeGenOptions::CompatibilityKind`.
5305#define DEBUGOPT(Name, Bits, Default, Compatibility) \
5306 if constexpr (CK::Compatibility != CK::Benign) \
5307 HBuilder.add(CodeGenOpts->Name);
5308#define VALUE_DEBUGOPT(Name, Bits, Default, Compatibility) \
5309 if constexpr (CK::Compatibility != CK::Benign) \
5310 HBuilder.add(CodeGenOpts->Name);
5311#define ENUM_DEBUGOPT(Name, Type, Bits, Default, Compatibility) \
5312 if constexpr (CK::Compatibility != CK::Benign) \
5313 HBuilder.add(static_cast<unsigned>(CodeGenOpts->get##Name()));
5314#include "clang/Basic/DebugOptions.def"
5315 }
5316
5317 // Extend the signature with the enabled sanitizers, if at least one is
5318 // enabled. Sanitizers which cannot affect AST generation aren't hashed.
5319 SanitizerSet SanHash = getLangOpts().Sanitize;
5321 if (!SanHash.empty())
5322 HBuilder.add(SanHash.Mask);
5323
5324 llvm::MD5::MD5Result Result;
5325 HBuilder.getHasher().final(Result);
5326 uint64_t Hash = Result.high() ^ Result.low();
5327 return toString(llvm::APInt(64, Hash), 36, /*Signed=*/false);
5328}
5329
5331 llvm::function_ref<bool(std::string &)> Predicate) {
5332#define RETURN_IF(PATH) \
5333 do { \
5334 if (Predicate(PATH)) \
5335 return; \
5336 } while (0)
5337
5338#define RETURN_IF_MANY(PATHS) \
5339 do { \
5340 if (llvm::any_of(PATHS, Predicate)) \
5341 return; \
5342 } while (0)
5343
5344 auto &HeaderSearchOpts = *this->HSOpts;
5345 // Header search paths.
5346 RETURN_IF(HeaderSearchOpts.Sysroot);
5347 for (auto &Entry : HeaderSearchOpts.UserEntries)
5348 if (Entry.IgnoreSysRoot)
5349 RETURN_IF(Entry.Path);
5350 RETURN_IF(HeaderSearchOpts.ResourceDir);
5351 RETURN_IF(HeaderSearchOpts.ModuleCachePath);
5352 RETURN_IF(HeaderSearchOpts.ModuleUserBuildPath);
5353 for (auto &[Name, File] : HeaderSearchOpts.PrebuiltModuleFiles)
5354 RETURN_IF(File);
5355 RETURN_IF_MANY(HeaderSearchOpts.PrebuiltModulePaths);
5356 RETURN_IF_MANY(HeaderSearchOpts.VFSOverlayFiles);
5357
5358 // Preprocessor options.
5359 auto &PPOpts = *this->PPOpts;
5360 RETURN_IF_MANY(PPOpts.MacroIncludes);
5361 RETURN_IF_MANY(PPOpts.Includes);
5362 RETURN_IF(PPOpts.ImplicitPCHInclude);
5363
5364 // Frontend options.
5365 auto &FrontendOpts = *this->FrontendOpts;
5366 for (auto &Input : FrontendOpts.Inputs) {
5367 if (Input.isBuffer())
5368 continue;
5369
5370 RETURN_IF(Input.File);
5371 }
5372 // TODO: Also report output files such as FrontendOpts.OutputFile;
5373 RETURN_IF(FrontendOpts.CodeCompletionAt.FileName);
5374 RETURN_IF_MANY(FrontendOpts.ModuleMapFiles);
5375 RETURN_IF_MANY(FrontendOpts.ModuleFiles);
5376 RETURN_IF_MANY(FrontendOpts.ModulesEmbedFiles);
5377 RETURN_IF_MANY(FrontendOpts.ASTMergeFiles);
5378 RETURN_IF(FrontendOpts.OverrideRecordLayoutsFile);
5379 RETURN_IF(FrontendOpts.StatsFile);
5380
5381 // Filesystem options.
5382 auto &FileSystemOpts = *this->FSOpts;
5383 RETURN_IF(FileSystemOpts.WorkingDir);
5384
5385 // Codegen options.
5386 auto &CodeGenOpts = *this->CodeGenOpts;
5387 RETURN_IF(CodeGenOpts.DebugCompilationDir);
5388 RETURN_IF(CodeGenOpts.CoverageCompilationDir);
5389
5390 // Sanitizer options.
5391 RETURN_IF_MANY(LangOpts->NoSanitizeFiles);
5392
5393 // Coverage mappings.
5394 RETURN_IF(CodeGenOpts.ProfileInstrumentUsePath);
5395 RETURN_IF(CodeGenOpts.SampleProfileFile);
5396 RETURN_IF(CodeGenOpts.ProfileRemappingFile);
5397
5398 // Dependency output options.
5399 for (auto &ExtraDep : DependencyOutputOpts->ExtraDeps)
5400 RETURN_IF(ExtraDep.first);
5401}
5402
5404 llvm::function_ref<bool(StringRef)> Callback) const {
5405 // The const_cast here is OK, because visitPathsImpl() itself doesn't modify
5406 // the invocation, and our callback takes immutable StringRefs.
5407 return const_cast<CompilerInvocationBase *>(this)->visitPathsImpl(
5408 [&Callback](std::string &Path) { return Callback(StringRef(Path)); });
5409}
5410
5412 ArgumentConsumer Consumer) const {
5413 llvm::Triple T(getTargetOpts().Triple);
5414
5418 GenerateDiagnosticArgs(getDiagnosticOpts(), Consumer,
5419 /*DefaultDiagColor=*/false);
5420 GenerateFrontendArgs(getFrontendOpts(), Consumer, getLangOpts().IsHeaderFile);
5421 GenerateTargetArgs(getTargetOpts(), Consumer);
5425 GenerateLangArgs(getLangOpts(), Consumer, T, getFrontendOpts().DashX);
5426 GenerateCodeGenArgs(getCodeGenOpts(), Consumer, T,
5427 getFrontendOpts().OutputFile, &getLangOpts());
5431 getFrontendOpts().ProgramAction);
5433}
5434
5435std::vector<std::string> CompilerInvocationBase::getCC1CommandLine() const {
5436 std::vector<std::string> Args{"-cc1"};
5438 [&Args](const Twine &Arg) { Args.push_back(Arg.str()); });
5439 return Args;
5440}
5441
5447
5449 getLangOpts().ImplicitModules = false;
5454 // The specific values we canonicalize to for pruning don't affect behaviour,
5455 /// so use the default values so they may be dropped from the command-line.
5456 getHeaderSearchOpts().ModuleCachePruneInterval = 7 * 24 * 60 * 60;
5457 getHeaderSearchOpts().ModuleCachePruneAfter = 31 * 24 * 60 * 60;
5458}
5459
5462 DiagnosticsEngine &Diags) {
5463 return createVFSFromCompilerInvocation(CI, Diags,
5464 llvm::vfs::getRealFileSystem());
5465}
5466
5474
5476 ArrayRef<std::string> VFSOverlayFiles, DiagnosticsEngine &Diags,
5478 if (VFSOverlayFiles.empty())
5479 return BaseFS;
5480
5482 // earlier vfs files are on the bottom
5483 for (const auto &File : VFSOverlayFiles) {
5484 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buffer =
5485 Result->getBufferForFile(File);
5486 if (!Buffer) {
5487 Diags.Report(diag::err_missing_vfs_overlay_file) << File;
5488 continue;
5489 }
5490
5491 IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS = llvm::vfs::getVFSFromYAML(
5492 std::move(Buffer.get()), /*DiagHandler*/ nullptr, File,
5493 /*DiagContext*/ nullptr, Result);
5494 if (!FS) {
5495 Diags.Report(diag::err_invalid_vfs_overlay) << File;
5496 continue;
5497 }
5498
5499 Result = FS;
5500 }
5501 return Result;
5502}
#define V(N, I)
Defines the Diagnostic-related interfaces.
Defines enum values for all the target-independent builtin functions.
Defines the clang::CommentOptions interface.
static void getAllNoBuiltinFuncValues(ArgList &Args, std::vector< std::string > &Funcs)
static T extractMaskValue(T KeyPath)
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 void parsePointerAuthOptions(PointerAuthOptions &Opts, const LangOptions &LangOpts, const llvm::Triple &Triple, DiagnosticsEngine &Diags)
static void denormalizeString(ArgumentConsumer Consumer, unsigned SpellingOffset, Option::OptionClass OptClass, unsigned TableIndex, T Value)
static SmallVector< StringRef, 4 > serializeSanitizerKinds(SanitizerSet S)
static void parseXRayInstrumentationBundle(StringRef FlagName, StringRef Bundle, ArgList &Args, DiagnosticsEngine &D, XRayInstrSet &S)
static void GenerateFrontendArgs(const FrontendOptions &Opts, ArgumentConsumer Consumer, bool IsHeader)
static std::optional< SimpleEnumValue > findValueTableByValue(const SimpleEnumValueTable &Table, unsigned Value)
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 void GeneratePointerAuthArgs(const LangOptions &Opts, ArgumentConsumer Consumer)
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)
CompilerInvocation::ArgumentConsumer ArgumentConsumer
static void denormalizeSimpleEnumImpl(ArgumentConsumer Consumer, unsigned SpellingOffset, Option::OptionClass OptClass, unsigned TableIndex, unsigned Value)
static void GenerateArg(ArgumentConsumer Consumer, llvm::opt::OptSpecifier OptSpecifier)
static void addDiagnosticArgs(ArgList &Args, OptSpecifier Group, OptSpecifier GroupWithValue, std::vector< std::string > &Diagnostics)
static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, DiagnosticsEngine &Diags)
static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args, DiagnosticsEngine &Diags)
static void parseAnalyzerConfigs(AnalyzerOptions &AnOpts, DiagnosticsEngine *Diags)
static void denormalizeSimpleFlag(ArgumentConsumer Consumer, unsigned SpellingOffset, Option::OptionClass, unsigned,...)
The tblgen-erated code passes in a fifth parameter of an arbitrary type, but denormalizeSimpleFlags n...
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 initOption(AnalyzerOptions::ConfigTable &Config, DiagnosticsEngine *Diags, StringRef &OptionField, StringRef Name, StringRef DefaultVal)
#define RETURN_IF(PATH)
static std::optional< std::string > normalizeTriple(OptSpecifier Opt, int TableIndex, const ArgList &Args, DiagnosticsEngine &Diags)
T & ensureOwned(std::shared_ptr< T > &Storage)
static void GenerateMigratorArgs(const MigratorOptions &Opts, ArgumentConsumer Consumer)
static const auto & getFrontendActionTable()
Return a table that associates command line option specifiers with the frontend action.
static void GenerateTargetArgs(const TargetOptions &Opts, ArgumentConsumer Consumer)
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 SanitizerMaskCutoffs parseSanitizerWeightedKinds(StringRef FlagName, const std::vector< std::string > &Sanitizers, DiagnosticsEngine &Diags)
static void GenerateAPINotesArgs(const APINotesOptions &Opts, ArgumentConsumer Consumer)
static bool isCodeGenAction(frontend::ActionKind Action)
static std::optional< bool > normalizeSimpleNegativeFlag(OptSpecifier Opt, unsigned, const ArgList &Args, DiagnosticsEngine &)
static void GenerateFileSystemArgs(const FileSystemOptions &Opts, ArgumentConsumer Consumer)
static bool IsInputCompatibleWithStandard(InputKind IK, const LangStandard &S)
Check if input file kind and language standard are compatible.
static void denormalizeStringImpl(ArgumentConsumer Consumer, const Twine &Spelling, Option::OptionClass OptClass, unsigned, const Twine &Value)
static llvm::StringRef lookupStrInTable(unsigned Offset)
static void GeneratePreprocessorArgs(const PreprocessorOptions &Opts, ArgumentConsumer Consumer, const LangOptions &LangOpts, const FrontendOptions &FrontendOpts, const CodeGenOptions &CodeGenOpts)
static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, DiagnosticsEngine &Diags, bool &IsHeaderFile)
static auto makeBooleanOptionDenormalizer(bool Value)
static void GeneratePreprocessorOutputArgs(const PreprocessorOutputOptions &Opts, ArgumentConsumer Consumer, frontend::ActionKind Action)
static bool isStrictlyPreprocessorAction(frontend::ActionKind Action)
#define RETURN_IF_MANY(PATHS)
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 ParseAPINotesArgs(APINotesOptions &Opts, ArgList &Args, DiagnosticsEngine &diags)
static void denormalizeStringVector(ArgumentConsumer Consumer, unsigned SpellingOffset, Option::OptionClass OptClass, unsigned TableIndex, const std::vector< std::string > &Values)
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 void GenerateAnalyzerArgs(const AnalyzerOptions &Opts, ArgumentConsumer Consumer)
static void GenerateOptimizationRemark(ArgumentConsumer Consumer, OptSpecifier OptEQ, StringRef Name, const CodeGenOptions::OptRemark &Remark)
Generate a remark argument. This is an inverse of ParseOptimizationRemark.
static bool ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts, ArgList &Args, DiagnosticsEngine &Diags, frontend::ActionKind Action)
llvm::function_ref< void( CompilerInvocation &, SmallVectorImpl< const char * > &, CompilerInvocation::StringAllocator)> GenerateFn
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 denormalizeSimpleEnum(ArgumentConsumer Consumer, unsigned SpellingOffset, Option::OptionClass OptClass, unsigned TableIndex, T Value)
std::shared_ptr< T > make_shared_copy(const T &X)
llvm::function_ref< bool(CompilerInvocation &, ArrayRef< const char * >, DiagnosticsEngine &, const char *)> ParseFn
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 bool ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args, DiagnosticsEngine &Diags)
static void GenerateDependencyOutputArgs(const DependencyOutputOptions &Opts, ArgumentConsumer Consumer)
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 GenerateHeaderSearchArgs(const HeaderSearchOptions &Opts, ArgumentConsumer Consumer)
Defines the clang::FileSystemOptions interface.
#define X(type, name)
Definition Value.h:97
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.
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.
#define CXXABI(Name, Str)
Defines the clang::TargetOptions class.
Defines version macros and version-related utility functions for Clang.
Defines the clang::XRayInstrKind enum.
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
Tracks various options which control how API notes are found and handled.
llvm::VersionTuple SwiftVersion
The Swift version which should be used for API notes.
std::vector< std::string > ModuleSearchPaths
The set of search paths where we API notes can be found for particular modules.
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.
unsigned ShouldEmitErrorsOnInvalidConfigValue
AnalysisPurgeMode AnalysisPurgeOpt
bool isUnknownAnalyzerConfig(llvm::StringRef Name)
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:123
CompatibilityKind
For ASTs produced with different option value, signifies their level of compatibility.
CodeGenOptions - Track various options which control how the code is optimized and passed to the back...
llvm::SmallVector< std::pair< std::string, std::string >, 0 > CoveragePrefixMap
Prefix replacement map for source-based code coverage to remap source file paths in coverage mapping.
SanitizerSet SanitizeMergeHandlers
Set of sanitizer checks that can merge handlers (smaller code size at the expense of debuggability).
std::string StackUsageFile
Name of the stack usage file (i.e., .su file) if user passes -fstack-usage.
llvm::SmallVector< std::pair< std::string, std::string >, 0 > DebugPrefixMap
std::string OptRecordFile
The name of the file to which the backend should save YAML optimization records.
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 CoverageNotesFile
The filename with path we use for coverage notes files.
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.
uint64_t LargeDataThreshold
The code model-specific large data threshold to use (-mlarge-data-threshold).
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::string CoverageDataFile
The filename with path we use for coverage data files.
std::optional< uint32_t > DiagnosticsMisExpectTolerance
The maximum percentage profiling weights can deviate from the expected values in order to be included...
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
SanitizerSet SanitizeAnnotateDebugInfo
Set of sanitizer checks, for which the instrumentation will be annotated with extra debug info.
PointerAuthOptions PointerAuth
Configuration for pointer-signing.
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.
SanitizerMaskCutoffs SanitizeSkipHotCutoffs
Set of thresholds in a range [0.0, 1.0]: the top hottest code responsible for the given fraction of P...
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::optional< double > AllowRuntimeCheckSkipHotCutoff
std::vector< std::string > CommandLineArgs
void resetNonModularOptions(StringRef ModuleFormat)
Reset all of the options that are not considered when building a module.
std::string OptRecordFormat
The format used for serializing remarks (default: YAML)
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.
std::shared_ptr< DiagnosticOptions > DiagnosticOpts
Options controlling the diagnostic engine.
std::shared_ptr< AnalyzerOptions > AnalyzerOpts
Options controlling the static analyzer.
std::shared_ptr< MigratorOptions > MigratorOpts
std::shared_ptr< PreprocessorOutputOptions > PreprocessorOutputOpts
Options controlling preprocessed output.
std::shared_ptr< APINotesOptions > APINotesOpts
Options controlling API notes.
std::shared_ptr< TargetOptions > TargetOpts
Options controlling the target.
const FrontendOptions & getFrontendOpts() const
const CodeGenOptions & getCodeGenOpts() const
void visitPathsImpl(llvm::function_ref< bool(std::string &)> Predicate)
Visits paths stored in the invocation.
llvm::function_ref< const char *(const Twine &)> StringAllocator
Command line generation.
const FileSystemOptions & getFileSystemOpts() const
std::shared_ptr< PreprocessorOptions > PPOpts
Options controlling the preprocessor (aside from #include handling).
const PreprocessorOutputOptions & getPreprocessorOutputOpts() const
void visitPaths(llvm::function_ref< bool(StringRef)> Callback) const
Visitation.
std::vector< std::string > getCC1CommandLine() const
Generate cc1-compatible command line arguments from this instance, wrapping the result as a std::vect...
std::shared_ptr< FileSystemOptions > FSOpts
Options controlling file system operations.
const AnalyzerOptions & getAnalyzerOpts() const
const MigratorOptions & getMigratorOpts() const
void generateCC1CommandLine(llvm::SmallVectorImpl< const char * > &Args, StringAllocator SA) const
Generate cc1-compatible command line arguments from this instance.
CompilerInvocationBase & deep_copy_assign(const CompilerInvocationBase &X)
const DependencyOutputOptions & getDependencyOutputOpts() const
CompilerInvocationBase & shallow_copy_assign(const CompilerInvocationBase &X)
const TargetOptions & getTargetOpts() const
std::shared_ptr< CodeGenOptions > CodeGenOpts
Options controlling IRgen and the backend.
std::shared_ptr< LangOptions > LangOpts
Options controlling the language variant.
const APINotesOptions & getAPINotesOpts() const
const HeaderSearchOptions & getHeaderSearchOpts() const
std::shared_ptr< HeaderSearchOptions > HSOpts
Options controlling the #include directive.
const PreprocessorOptions & getPreprocessorOpts() const
const DiagnosticOptions & getDiagnosticOpts() const
const LangOptions & getLangOpts() const
Const getters.
std::shared_ptr< FrontendOptions > FrontendOpts
Options controlling the frontend itself.
llvm::function_ref< void(const Twine &)> ArgumentConsumer
std::shared_ptr< DependencyOutputOptions > DependencyOutputOpts
Options controlling dependency output.
Helper class for holding the data necessary to invoke the compiler.
PreprocessorOptions & getPreprocessorOpts()
void clearImplicitModuleBuildOptions()
Disable implicit modules and canonicalize options that are only used by implicit modules.
MigratorOptions & getMigratorOpts()
AnalyzerOptions & getAnalyzerOpts()
APINotesOptions & getAPINotesOpts()
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.
LangOptions & getLangOpts()
Mutable getters.
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...
DependencyOutputOptions & getDependencyOutputOpts()
void resetNonModularOptions()
Reset all of the options that are not considered when building a module.
FrontendOptions & getFrontendOpts()
FileSystemOptions & getFileSystemOpts()
CompilerInvocation & operator=(const CompilerInvocation &X)
static void setDefaultPointerAuthOptions(PointerAuthOptions &Opts, const LangOptions &LangOpts, const llvm::Triple &Triple)
Populate Opts with the default set of pointer authentication-related options given LangOpts and Tripl...
CodeGenOptions & getCodeGenOpts()
std::string computeContextHash() const
Compute the context hash - a string that uniquely identifies compiler settings.
HeaderSearchOptions & getHeaderSearchOpts()
DiagnosticOptions & getDiagnosticOpts()
PreprocessorOutputOptions & getPreprocessorOutputOpts()
Same as CompilerInvocation, but with copy-on-write optimization.
LangOptions & getMutLangOpts()
Mutable getters.
HeaderSearchOptions & getMutHeaderSearchOpts()
PreprocessorOptions & getMutPreprocessorOpts()
PreprocessorOutputOptions & getMutPreprocessorOutputOpts()
FileSystemOptions & getMutFileSystemOpts()
DiagnosticOptions & getMutDiagnosticOpts()
DependencyOutputOptions & getMutDependencyOutputOpts()
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.
static llvm::IntrusiveRefCntPtr< DiagnosticIDs > create()
Options for controlling the compiler diagnostics engine.
std::string DiagnosticSuppressionMappingsFile
Path for the file that defines diagnostic suppression mappings.
std::vector< std::string > Remarks
The list of -R... options used to alter the diagnostic mappings, with the prefixes removed.
std::vector< std::string > Warnings
The list of -W... options used to alter the diagnostic mappings, with the prefixes removed.
std::vector< std::string > VerifyPrefixes
The prefixes for comment directives sought by -verify ("expected" by default).
std::string DiagnosticSerializationFile
The file to serialize diagnostics to (non-appending).
Concrete class used by the front-end to report problems and issues.
Definition Diagnostic.h:233
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
void setClient(DiagnosticConsumer *client, bool ShouldOwnClient=true)
Set the diagnostic client associated with this diagnostic object.
unsigned getNumErrors() const
Definition Diagnostic.h:895
bool isIgnored(unsigned DiagID, SourceLocation Loc) const
Determine whether the diagnostic is known to be ignored.
Definition Diagnostic.h:960
unsigned getNumWarnings() const
Definition Diagnostic.h:896
Keeps track of options that affect how file operations are performed.
FrontendOptions - Options for controlling the behavior of the frontend.
InputKind DashX
The input kind, either specified via -x argument or deduced from the input file name.
std::vector< std::string > ModuleFiles
The list of additional prebuilt module files to load before processing the input.
unsigned ClangIRDisablePasses
Disable Clang IR specific (CIR) passes.
std::map< std::string, std::vector< std::string > > PluginArgs
Args to pass to the plugins.
unsigned ClangIRDisableCIRVerifier
Disable Clang IR (CIR) verifier.
unsigned IsSystemModule
When using -emit-module, treat the modulemap as a system module.
unsigned UseClangIRPipeline
Use Clang IR pipeline to emit code.
ASTDumpOutputFormat ASTDumpFormat
Specifies the output format of the AST.
std::optional< std::string > AuxTargetCPU
Auxiliary target CPU for CUDA/HIP compilation.
std::string OutputFile
The output file, if any.
unsigned ShowStats
Show frontend performance metrics and statistics.
unsigned GenReducedBMI
Whether to generate reduced BMI for C++20 named modules.
std::string ActionName
The name of the action to run when using a plugin action.
std::vector< std::shared_ptr< ModuleFileExtension > > ModuleFileExtensions
The list of module file extensions.
ParsedSourceLocation CodeCompletionAt
If given, enable code completion at the provided location.
std::string FixItSuffix
If given, the new suffix for fix-it rewritten files.
static InputKind getInputKindForExtension(StringRef Extension)
getInputKindForExtension - Return the appropriate input kind for a file extension.
std::vector< std::string > Plugins
The list of plugins to load.
unsigned ASTDumpAll
Whether we deserialize all decls when forming AST dumps.
unsigned GenerateGlobalModuleIndex
Whether we can generate the global module index if needed.
unsigned DisableFree
Disable memory freeing on exit.
SmallVector< FrontendInputFile, 0 > Inputs
The input files and their types.
frontend::ActionKind ProgramAction
The frontend action to perform.
std::optional< std::vector< std::string > > AuxTargetFeatures
Auxiliary target features for CUDA/HIP compilation.
std::string AuxTriple
Auxiliary triple for CUDA/HIP compilation.
unsigned UseGlobalModuleIndex
Whether we can use the global module index if available.
unsigned ASTDumpDecls
Whether we include declaration dumps in AST dumps.
HeaderSearchOptions - Helper class for storing options related to the initialization of the HeaderSea...
unsigned ModulesStrictContextHash
Whether we should include all things that could impact the module in the hash.
void AddPath(StringRef Path, frontend::IncludeDirGroup Group, bool IsFramework, bool IgnoreSysRoot)
AddPath - Add the Path path to the specified Group list.
unsigned ModuleCachePruneInterval
The interval (in seconds) between pruning operations.
std::map< std::string, std::string, std::less<> > PrebuiltModuleFiles
The mapping of module names to prebuilt module files.
uint64_t BuildSessionTimestamp
The time in seconds when the build session started.
std::vector< std::string > PrebuiltModulePaths
The directories used to load prebuilt module files.
unsigned ModulesSkipHeaderSearchPaths
Whether to entirely skip writing header search paths.
unsigned ImplicitModuleMaps
Implicit module maps.
void AddSystemHeaderPrefix(StringRef Prefix, bool IsSystemHeader)
AddSystemHeaderPrefix - Override whether #include directives naming a path starting with Prefix shoul...
std::vector< SystemHeaderPrefix > SystemHeaderPrefixes
User-specified system header prefixes.
std::string ModuleFormat
The module/pch container format.
std::string Sysroot
If non-empty, the directory to use as a "virtual system root" for include paths.
unsigned ModulesSkipDiagnosticOptions
Whether to entirely skip writing diagnostic options.
llvm::SmallSetVector< llvm::CachedHashString, 16 > ModulesIgnoreMacros
The set of macro names that should be ignored for the purposes of computing the module hash.
std::string ModuleCachePath
The directory used for the module cache.
std::string ModuleUserBuildPath
The directory used for a user build.
std::vector< std::string > VFSOverlayFiles
The set of user-provided virtual filesystem overlay files.
unsigned UseLibcxx
Use libc++ instead of the default libstdc++.
unsigned UseBuiltinIncludes
Include the compiler builtin includes.
unsigned UseStandardCXXIncludes
Include the system standard C++ library include search directories.
unsigned UseDebugInfo
Whether the module includes debug information (-gmodules).
std::vector< Entry > UserEntries
User specified include entries.
std::string ResourceDir
The directory which holds the compiler resource files (builtin includes, etc.).
void AddPrebuiltModulePath(StringRef Name)
unsigned UseStandardSystemIncludes
Include the system standard include search directories.
void AddVFSOverlayFile(StringRef Name)
unsigned ModulesValidateOncePerBuildSession
If true, skip verifying input files used by modules if the module was already verified during this bu...
unsigned ModuleCachePruneAfter
The time (in seconds) after which an unused module file will be considered unused and will,...
A diagnostic client that ignores all diagnostics.
The kind of a file that we've been handed as an input.
bool isPreprocessed() const
InputKind withHeaderUnit(HeaderUnitKind HU) const
bool isUnknown() const
Is the input kind fully-unknown?
InputKind getPreprocessed() const
Format getFormat() const
HeaderUnitKind getHeaderUnitKind() const
InputKind getHeader() const
InputKind withFormat(Format F) const
Language getLanguage() const
@ NonLeaf
Sign the return address of functions that spill LR.
@ All
Sign the return address of all functions,.
@ BKey
Return address signing uses APIB key.
@ AKey
Return address signing uses APIA key.
@ None
Don't exclude any overflow patterns from sanitizers.
@ AddUnsignedOverflowTest
if (a + b < a)
@ All
Exclude all overflow patterns (below)
@ AddSignedOverflowTest
if (a + b < a)
@ PostDecrInWhile
while (count–)
CompatibilityKind
For ASTs produced with different option value, signifies their level of compatibility.
Definition LangOptions.h:83
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
SanitizerSet UBSanFeatureIgnoredSanitize
Set of (UBSan) sanitizers that when enabled do not cause __has_feature(undefined_behavior_sanitizer) ...
void resetNonModularOptions()
Reset all of the options that are not considered when building a module.
std::optional< TargetCXXABI::Kind > CXXABI
C++ ABI to compile with, if specified by the frontend through -fc++-abi=.
std::vector< std::string > NoBuiltinFuncs
A list of all -fno-builtin-* function names (e.g., memset).
std::string ModuleName
The module currently being compiled as specified by -fmodule-name.
clang::ObjCRuntime ObjCRuntime
std::string getOpenCLVersionString() const
Return the OpenCL C or C++ for OpenCL language name and version as a string.
unsigned OverflowPatternExclusionMask
Which overflow patterns should be excluded from sanitizer instrumentation.
SanitizerSet Sanitize
Set of enabled sanitizers.
std::optional< llvm::AllocTokenMode > AllocTokenMode
The allocation token mode.
bool UseTargetPathSeparator
Indicates whether to use target's platform-specific file separator when FILE macro is used and when c...
static void setLangDefaults(LangOptions &Opts, Language Lang, const llvm::Triple &T, std::vector< std::string > &Includes, LangStandard::Kind LangStd=LangStandard::lang_unspecified)
Set language defaults for the given input language and language standard in the given LangOptions obj...
std::string OverflowHandler
The name of the handler function to be called when -ftrapv is specified.
std::string RandstructSeed
The seed used by the randomize structure layout feature.
std::map< std::string, std::string, std::greater< std::string > > MacroPrefixMap
A prefix map for FILE, BASE_FILE and __builtin_FILE().
bool isTargetDevice() const
True when compiling for an offloading target device.
std::optional< uint64_t > AllocTokenMax
Maximum number of allocation tokens (0 = target SIZE_MAX), nullopt if none set (use target SIZE_MAX).
LangStandard::Kind LangStd
The used language standard.
unsigned getOpenCLCompatibleVersion() const
Return the OpenCL version that kernel language is compatible with.
bool SanitizeCoverage
Is at least one coverage instrumentation type enabled.
std::vector< llvm::Triple > OMPTargetTriples
Triples of the OpenMP targets that the host code codegen should take into account in order to generat...
std::vector< std::string > NoSanitizeFiles
Paths to files specifying which objects (files, functions, variables) should not be instrumented.
std::string CurrentModule
The name of the current module, of which the main source file is a part.
std::vector< std::string > ModuleFeatures
The names of any features to enable in module 'requires' decls in addition to the hard-coded list in ...
The basic abstraction for the target Objective-C runtime.
Definition ObjCRuntime.h:28
bool allowsWeak() const
Does this runtime allow the use of __weak?
Kind getKind() const
Definition ObjCRuntime.h:77
bool tryParse(StringRef input)
Try to parse an Objective-C runtime specification from the given string.
std::string getAsString() const
bool allowsARC() const
Does this runtime allow ARC at all?
@ FragileMacOSX
'macosx-fragile' is the Apple-provided NeXT-derived runtime on Mac OS X platforms that use the fragil...
Definition ObjCRuntime.h:40
Discrimination
Forms of extra discrimination.
ARM8_3Key
Hardware pointer-signing keys in ARM8.3.
static constexpr std::optional< PositiveAnalyzerOption > create(unsigned Val)
PreprocessorOptions - This class is used for passing the various options used in preprocessor initial...
std::vector< std::pair< std::string, std::string > > RemappedFiles
The set of file remappings, which take existing files on the system (the first part of each pair) and...
bool PCHWithHdrStopCreate
When true, we are creating a PCH or creating the PCH object while expecting a pragma hdrstop to separ...
std::vector< std::string > Includes
std::pair< unsigned, bool > PrecompiledPreambleBytes
If non-zero, the implicit PCH include is actually a precompiled preamble that covers this number of b...
bool LexEditorPlaceholders
When enabled, the preprocessor will construct editor placeholder tokens.
void resetNonModularOptions()
Reset any options that are not considered when building a module.
void addMacroUndef(StringRef Name)
std::set< std::string > DeserializedPCHDeclsToErrorOn
This is a set of names for decls that we do not want to be deserialized, and we emit an error if they...
std::vector< std::string > EmbedEntries
User specified embed entries.
void addMacroDef(StringRef Name)
bool DefineTargetOSMacros
Indicates whether to predefine target OS macros.
bool DetailedRecord
Whether we should maintain a detailed record of all macro definitions and expansions.
std::vector< std::string > ChainedIncludes
Headers that will be converted to chained PCHs in memory.
bool PCHWithHdrStop
When true, we are creating or using a PCH where a pragma hdrstop is expected to indicate the beginnin...
std::optional< uint64_t > SourceDateEpoch
If set, the UNIX timestamp specified by SOURCE_DATE_EPOCH.
bool UsePredefines
Initialize the preprocessor with the compiler and target specific predefines.
void addRemappedFile(StringRef From, StringRef To)
std::vector< std::pair< std::string, bool > > Macros
PreprocessorOutputOptions - Options for controlling the C preprocessor output (e.g....
unsigned ShowMacros
Print macro definitions.
unsigned ShowCPP
Print normal preprocessed output.
unsigned ShowLineMarkers
Show #line markers.
unsigned DirectivesOnly
Process directives but do not expand macros.
Encodes a location in the source.
static bool isSupportedCXXABI(const llvm::Triple &T, Kind Kind)
static const auto & getSpelling(Kind ABIKind)
static bool usesRelativeVTables(const llvm::Triple &T)
static bool isABI(StringRef Name)
Kind getKind() const
Options for controlling the target.
std::string Triple
The name of the target triple to compile for.
llvm::VersionTuple SDKVersion
The version of the SDK which was used during the compilation.
llvm::VersionTuple DarwinTargetVariantSDKVersion
The version of the darwin target variant SDK which was used during the compilation.
std::string HostTriple
When compiling for the device side, contains the triple used to compile for the host.
Value()=default
constexpr XRayInstrMask None
Definition XRayInstr.h:38
constexpr XRayInstrMask All
Definition XRayInstr.h:43
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
IncludeDirGroup
IncludeDirGroup - Identifies the group an include Entry belongs to, representing its relative positiv...
@ CXXSystem
Like System, but only used for C++.
@ Angled
Paths for '#include <>' added by '-I'.
@ CSystem
Like System, but only used for C.
@ System
Like Angled, but marks system directories.
@ Quoted
'#include ""' paths, added by 'gcc -iquote'.
@ ExternCSystem
Like System, but headers are implicitly wrapped in extern "C".
@ ObjCSystem
Like System, but only used for ObjC.
@ ObjCXXSystem
Like System, but only used for ObjC++.
@ After
Like System, but searched after the system directories.
@ GenerateHeaderUnit
Generate a C++20 header unit module from a header file.
@ VerifyPCH
Load and verify that a PCH file is usable.
@ PrintPreprocessedInput
-E mode.
@ RewriteTest
Rewriter playground.
@ ParseSyntaxOnly
Parse and perform semantic analysis.
@ TemplightDump
Dump template instantiations.
@ EmitBC
Emit a .bc file.
@ GenerateModuleInterface
Generate pre-compiled module from a standard C++ module interface unit.
@ EmitLLVM
Emit a .ll file.
@ PrintPreamble
Print the "preamble" of the input file.
@ InitOnly
Only execute frontend initialization.
@ ASTView
Parse ASTs and view them in Graphviz.
@ PluginAction
Run a plugin action,.
@ EmitObj
Emit a .o file.
@ DumpRawTokens
Dump out raw tokens.
@ PrintDependencyDirectivesSourceMinimizerOutput
Print the output of the dependency directives source minimizer.
@ RewriteObjC
ObjC->C Rewriter.
@ RunPreprocessorOnly
Just lex, no output.
@ ModuleFileInfo
Dump information about a module file.
@ EmitCIR
Emit a .cir file.
@ DumpCompilerOptions
Dump the compiler configuration.
@ RunAnalysis
Run one or more source code analyses.
@ ASTPrint
Parse ASTs and print them.
@ GenerateReducedModuleInterface
Generate reduced module interface for a standard C++ module interface unit.
@ GenerateInterfaceStubs
Generate Interface Stub Files.
@ ASTDump
Parse ASTs and dump them.
@ DumpTokens
Dump out preprocessed tokens.
@ FixIt
Parse and apply any fixits to the source.
@ EmitAssembly
Emit a .s file.
@ EmitCodeGenOnly
Generate machine code, but don't emit anything.
@ RewriteMacros
Expand macros but not #includes.
@ EmitHTML
Translate input source into HTML.
@ GeneratePCH
Generate pre-compiled header.
@ EmitLLVMOnly
Generate LLVM IR, but do not emit anything.
@ GenerateModule
Generate pre-compiled module from a module map.
@ ASTDeclList
Parse ASTs and list Decl nodes.
bool EQ(InterpState &S, CodePtr OpPC)
Definition Interp.h:1392
const unsigned VERSION_MINOR
AST file minor version number supported by this version of Clang.
Definition ASTBitCodes.h:57
const unsigned VERSION_MAJOR
AST file major version number supported by this version of Clang.
Definition ASTBitCodes.h:47
The JSON file list parser is used to communicate input to InstallAPI.
ASTDumpOutputFormat
Used to specify the format for printing AST dump information.
bool ParseDiagnosticArgs(DiagnosticOptions &Opts, llvm::opt::ArgList &Args, DiagnosticsEngine *Diags=nullptr, bool DefaultDiagColor=true)
Fill out Opts based on the options given in Args.
SanitizerMask getPPTransparentSanitizers()
Return the sanitizers which do not affect preprocessing.
Definition Sanitizers.h:230
IntrusiveRefCntPtr< llvm::vfs::FileSystem > createVFSFromOverlayFiles(ArrayRef< std::string > VFSOverlayFiles, DiagnosticsEngine &Diags, IntrusiveRefCntPtr< llvm::vfs::FileSystem > BaseFS)
DiagnosticLevelMask
A bitmask representing the diagnostic levels used by VerifyDiagnosticConsumer.
const char * headerIncludeFormatKindToString(HeaderIncludeFormatKind K)
std::unique_ptr< DiagnosticOptions > CreateAndPopulateDiagOpts(ArrayRef< const char * > Argv)
constexpr uint16_t BlockDescriptorConstantDiscriminator
Constant discriminator to be used with block descriptor pointers.
constexpr uint16_t IsaPointerConstantDiscriminator
Constant discriminator to be used with objective-c isa pointers.
const char * headerIncludeFilteringKindToString(HeaderIncludeFilteringKind K)
std::vector< std::string > Macros
A list of macros of the form <definition>=<expansion> .
Definition Format.h:3949
AnalysisConstraints
AnalysisConstraints - Set of available constraint models.
@ Success
Annotation was successful.
Definition Parser.h:65
@ Parse
Parse the block; this code is always used.
Definition Parser.h:137
constexpr uint16_t SuperPointerConstantDiscriminator
Constant discriminator to be used with objective-c superclass pointers.
void serializeSanitizerSet(SanitizerSet Set, SmallVectorImpl< StringRef > &Values)
Serialize a SanitizerSet into values for -fsanitize= or -fno-sanitize=.
LLVM_READONLY bool isLetter(unsigned char c)
Return true if this character is an ASCII letter: [a-zA-Z].
Definition CharInfo.h:132
LLVM_READONLY bool isAlphanumeric(unsigned char c)
Return true if this character is an ASCII letter or digit: [a-zA-Z0-9].
Definition CharInfo.h:138
constexpr uint16_t MethodListPointerConstantDiscriminator
Constant discriminator to be used with method list pointers.
constexpr uint16_t ClassROConstantDiscriminator
Constant discriminator to be used with objective-c class_ro_t pointers.
constexpr uint16_t InitFiniPointerConstantDiscriminator
Constant discriminator to be used with function pointers in .init_array and .fini_array.
@ C
Languages that the frontend can parse and compile.
@ CIR
LLVM IR & CIR: we accept these so that we can run the optimizer on them, and compile them to assembly...
@ Asm
Assembly: we accept this only so that we can preprocess it.
bool parseSanitizerWeightedValue(StringRef Value, bool AllowGroups, SanitizerMaskCutoffs &Cutoffs)
Parse a single weighted value (e.g., 'undefined=0.05') from a -fsanitize= or -fno-sanitize= value lis...
@ Result
The result type of a method or function.
Definition TypeBase.h:905
unsigned getOptimizationLevel(const llvm::opt::ArgList &Args, InputKind IK, DiagnosticsEngine &Diags)
XRayInstrMask parseXRayInstrValue(StringRef Value)
Parses a command line argument into a mask.
Definition XRayInstr.cpp:19
IntrusiveRefCntPtr< llvm::vfs::FileSystem > createVFSFromCompilerInvocation(const CompilerInvocation &CI, DiagnosticsEngine &Diags)
void serializeXRayInstrValue(XRayInstrSet Set, SmallVectorImpl< StringRef > &Values)
Serializes a set into a list of command line arguments.
Definition XRayInstr.cpp:34
unsigned getOptimizationLevelSize(const llvm::opt::ArgList &Args)
AnalysisPurgeMode
AnalysisPurgeModes - Set of available strategies for dead symbol removal.
void serializeSanitizerMaskCutoffs(const SanitizerMaskCutoffs &Cutoffs, SmallVectorImpl< std::string > &Values)
Serialize a SanitizerMaskCutoffs into command line arguments.
ShaderStage
Shader programs run in specific pipeline stages.
Definition LangOptions.h:44
constexpr uint16_t StdTypeInfoVTablePointerConstantDiscrimination
Constant discriminator for std::type_info vtable pointers: 0xB1EA/45546 The value is ptrauth_string_d...
SanitizerMask parseSanitizerValue(StringRef Value, bool AllowGroups)
Parse a single value from a -fsanitize= or -fno-sanitize= value list.
const llvm::opt::OptTable & getDriverOptTable()
AnalysisDiagClients
AnalysisDiagClients - Set of available diagnostic clients for rendering analysis results.
@ NUM_ANALYSIS_DIAG_CLIENTS
std::string getClangFullRepositoryVersion()
Retrieves the full repository version that is an amalgamation of the information in getClangRepositor...
Definition Version.cpp:68
int getLastArgIntValue(const llvm::opt::ArgList &Args, llvm::opt::OptSpecifier Id, int Default, DiagnosticsEngine *Diags=nullptr, unsigned Base=0)
Return the value of the last argument as an integer, or a default.
AnalysisInliningMode
AnalysisInlineFunctionSelection - Set of inlining function selection heuristics.
@ NumInliningModes
@ HIFMT_Textual
unsigned long uint64_t
int const char * function
Definition c++config.h:31
__DEVICE__ _Tp arg(const std::complex< _Tp > &__c)
Optimization remark with an optional regular expression pattern.
bool hasValidPattern() const
Returns true iff the optimization remark holds a valid regular expression.
Dummy tag type whose instance can be passed into the constructor to prevent creation of the reference...
unsigned IgnoreSysRoot
IgnoreSysRoot - This is false if an absolute path should be treated relative to the sysroot,...
LangStandard - Information about the properties of a particular language standard.
clang::Language getLanguage() const
Get the language that this standard describes.
const char * getDescription() const
getDescription - Get the description of this standard.
static const LangStandard & getLangStandardForKind(Kind K)
const char * getName() const
getName - Get the name of this standard.
static Kind getLangKind(StringRef Name)
static ParsedSourceLocation FromString(StringRef Str)
Construct a parsed source location from a string; the Filename is empty on error.
std::string ToString() const
Serialize ParsedSourceLocation back to a string.
PointerAuthSchema BlockDescriptorPointers
The ABI for pointers to block descriptors.
PointerAuthSchema BlockHelperFunctionPointers
The ABI for block object copy/destroy function pointers.
PointerAuthSchema CXXVTablePointers
The ABI for C++ virtual table pointers (the pointer to the table itself) as installed in an actual cl...
PointerAuthSchema InitFiniPointers
The ABI for function addresses in .init_array and .fini_array.
PointerAuthSchema BlockInvocationFunctionPointers
The ABI for block invocation function pointers.
PointerAuthSchema BlockByrefHelperFunctionPointers
The ABI for __block variable copy/destroy function pointers.
PointerAuthSchema CXXVTTVTablePointers
The ABI for C++ virtual table pointers as installed in a VTT.
bool ReturnAddresses
Should return addresses be authenticated?
PointerAuthSchema CXXTypeInfoVTablePointer
TypeInfo has external ABI requirements and is emitted without actually having parsed the libcxx defin...
bool AArch64JumpTableHardening
Use hardened lowering for jump-table dispatch?
PointerAuthSchema ObjCMethodListPointer
The ABI for a reference to an Objective-C method list in _class_ro_t.
PointerAuthSchema FunctionPointers
The ABI for C function pointers.
PointerAuthSchema ObjCSuperPointers
The ABI for Objective-C superclass pointers.
bool AuthTraps
Do authentication failures cause a trap?
PointerAuthSchema CXXMemberFunctionPointers
The ABI for C++ member function pointers.
PointerAuthSchema CXXVirtualVariadicFunctionPointers
The ABI for variadic C++ virtual function pointers.
PointerAuthSchema ObjCMethodListFunctionPointers
The ABI for Objective-C method lists.
PointerAuthSchema ObjCClassROPointers
The ABI for Objective-C class_ro_t pointers.
PointerAuthSchema CXXVirtualFunctionPointers
The ABI for most C++ virtual function pointers, i.e. v-table entries.
PointerAuthSchema ObjCIsaPointers
The ABI for Objective-C isa pointers.
bool IndirectGotos
Do indirect goto label addresses need to be authenticated?
void clear(SanitizerMask K=SanitizerKind::All)
Disable the sanitizers specified in K.
Definition Sanitizers.h:195
void set(SanitizerMask K, bool Value)
Enable or disable a certain (single) sanitizer.
Definition Sanitizers.h:187
bool empty() const
Returns true if no sanitizers are enabled.
Definition Sanitizers.h:198
SanitizerMask Mask
Bitmask of enabled sanitizers.
Definition Sanitizers.h:201
XRayInstrMask Mask
Definition XRayInstr.h:65
void set(XRayInstrMask K, bool Value)
Definition XRayInstr.h:55