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