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