clang 24.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
263static llvm::StringRef lookupStrInTable(unsigned Offset) {
264 return getDriverOptTable().getStrTable()[Offset];
265}
266
267#define SIMPLE_ENUM_VALUE_TABLE
268#include "clang/Options/Options.inc"
269#undef SIMPLE_ENUM_VALUE_TABLE
270
271static std::optional<bool> normalizeSimpleFlag(OptSpecifier Opt,
272 unsigned TableIndex,
273 const ArgList &Args,
274 DiagnosticsEngine &Diags) {
275 if (Args.hasArg(Opt))
276 return true;
277 return std::nullopt;
278}
279
280static std::optional<bool> normalizeSimpleNegativeFlag(OptSpecifier Opt,
281 unsigned,
282 const ArgList &Args,
284 if (Args.hasArg(Opt))
285 return false;
286 return std::nullopt;
287}
288
289/// The tblgen-erated code passes in a fifth parameter of an arbitrary type, but
290/// denormalizeSimpleFlags never looks at it. Avoid bloating compile-time with
291/// unnecessary template instantiations and just ignore it with a variadic
292/// argument.
294 unsigned SpellingOffset, Option::OptionClass,
295 unsigned, /*T*/...) {
296 Consumer(lookupStrInTable(SpellingOffset));
297}
299 const Twine &Spelling, Option::OptionClass,
300 unsigned, /*T*/...) {
301 Consumer(Spelling);
302}
303
304template <typename T> static constexpr bool is_uint64_t_convertible() {
305 return !std::is_same_v<T, uint64_t> && llvm::is_integral_or_enum<T>::value;
306}
307
308template <typename T,
309 std::enable_if_t<!is_uint64_t_convertible<T>(), bool> = false>
311 return [Value](OptSpecifier Opt, unsigned, const ArgList &Args,
312 DiagnosticsEngine &) -> std::optional<T> {
313 if (Args.hasArg(Opt))
314 return Value;
315 return std::nullopt;
316 };
317}
318
319template <typename T,
320 std::enable_if_t<is_uint64_t_convertible<T>(), bool> = false>
322 return makeFlagToValueNormalizer(uint64_t(Value));
323}
324
325static auto makeBooleanOptionNormalizer(bool Value, bool OtherValue,
326 OptSpecifier OtherOpt) {
327 return [Value, OtherValue,
328 OtherOpt](OptSpecifier Opt, unsigned, const ArgList &Args,
329 DiagnosticsEngine &) -> std::optional<bool> {
330 if (const Arg *A = Args.getLastArg(Opt, OtherOpt)) {
331 return A->getOption().matches(Opt) ? Value : OtherValue;
332 }
333 return std::nullopt;
334 };
335}
336
338 return [Value](ArgumentConsumer Consumer, unsigned SpellingOffset,
339 Option::OptionClass, unsigned, bool KeyPath) {
340 if (KeyPath == Value)
341 Consumer(lookupStrInTable(SpellingOffset));
342 };
343}
344
346 const Twine &Spelling,
347 Option::OptionClass OptClass, unsigned,
348 const Twine &Value) {
349 switch (OptClass) {
350 case Option::SeparateClass:
351 case Option::JoinedOrSeparateClass:
352 case Option::JoinedAndSeparateClass:
353 Consumer(Spelling);
354 Consumer(Value);
355 break;
356 case Option::JoinedClass:
357 case Option::CommaJoinedClass:
358 Consumer(Spelling + Value);
359 break;
360 default:
361 llvm_unreachable("Cannot denormalize an option with option class "
362 "incompatible with string denormalization.");
363 }
364}
365
366template <typename T>
367static void
368denormalizeString(ArgumentConsumer Consumer, unsigned SpellingOffset,
369 Option::OptionClass OptClass, unsigned TableIndex, T Value) {
370 denormalizeStringImpl(Consumer, lookupStrInTable(SpellingOffset), OptClass,
371 TableIndex, Twine(Value));
372}
373
374template <typename T>
375static void denormalizeString(ArgumentConsumer Consumer, const Twine &Spelling,
376 Option::OptionClass OptClass, unsigned TableIndex,
377 T Value) {
378 denormalizeStringImpl(Consumer, Spelling, OptClass, TableIndex, Twine(Value));
379}
380
381static std::optional<SimpleEnumValue>
382findValueTableByName(const SimpleEnumValueTable &Table, StringRef Name) {
383 for (int I = 0, E = Table.Size; I != E; ++I)
384 if (Name == Table.Table[I].Name)
385 return Table.Table[I];
386
387 return std::nullopt;
388}
389
390static std::optional<SimpleEnumValue>
391findValueTableByValue(const SimpleEnumValueTable &Table, unsigned Value) {
392 for (int I = 0, E = Table.Size; I != E; ++I)
393 if (Value == Table.Table[I].Value)
394 return Table.Table[I];
395
396 return std::nullopt;
397}
398
399static std::optional<unsigned> normalizeSimpleEnum(OptSpecifier Opt,
400 unsigned TableIndex,
401 const ArgList &Args,
402 DiagnosticsEngine &Diags) {
403 assert(TableIndex < SimpleEnumValueTablesSize);
404 const SimpleEnumValueTable &Table = SimpleEnumValueTables[TableIndex];
405
406 auto *Arg = Args.getLastArg(Opt);
407 if (!Arg)
408 return std::nullopt;
409
410 StringRef ArgValue = Arg->getValue();
411 if (auto MaybeEnumVal = findValueTableByName(Table, ArgValue))
412 return MaybeEnumVal->Value;
413
414 Diags.Report(diag::err_drv_invalid_value)
415 << Arg->getAsString(Args) << ArgValue;
416 return std::nullopt;
417}
418
420 unsigned SpellingOffset,
421 Option::OptionClass OptClass,
422 unsigned TableIndex, unsigned Value) {
423 assert(TableIndex < SimpleEnumValueTablesSize);
424 const SimpleEnumValueTable &Table = SimpleEnumValueTables[TableIndex];
425 if (auto MaybeEnumVal = findValueTableByValue(Table, Value)) {
426 denormalizeString(Consumer, lookupStrInTable(SpellingOffset), OptClass,
427 TableIndex, MaybeEnumVal->Name);
428 } else {
429 llvm_unreachable("The simple enum value was not correctly defined in "
430 "the tablegen option description");
431 }
432}
433
434template <typename T>
436 unsigned SpellingOffset,
437 Option::OptionClass OptClass,
438 unsigned TableIndex, T Value) {
439 return denormalizeSimpleEnumImpl(Consumer, SpellingOffset, OptClass,
440 TableIndex, static_cast<unsigned>(Value));
441}
442
443static std::optional<std::string> normalizeString(OptSpecifier Opt,
444 int TableIndex,
445 const ArgList &Args,
446 DiagnosticsEngine &Diags) {
447 auto *Arg = Args.getLastArg(Opt);
448 if (!Arg)
449 return std::nullopt;
450 return std::string(Arg->getValue());
451}
452
453template <typename IntTy>
454static std::optional<IntTy> normalizeStringIntegral(OptSpecifier Opt, int,
455 const ArgList &Args,
456 DiagnosticsEngine &Diags) {
457 auto *Arg = Args.getLastArg(Opt);
458 if (!Arg)
459 return std::nullopt;
460 IntTy Res;
461 if (StringRef(Arg->getValue()).getAsInteger(0, Res)) {
462 Diags.Report(diag::err_drv_invalid_int_value)
463 << Arg->getAsString(Args) << Arg->getValue();
464 return std::nullopt;
465 }
466 return Res;
467}
468
469static std::optional<std::vector<std::string>>
470normalizeStringVector(OptSpecifier Opt, int, const ArgList &Args,
472 return Args.getAllArgValues(Opt);
473}
474
476 unsigned SpellingOffset,
477 Option::OptionClass OptClass,
478 unsigned TableIndex,
479 const std::vector<std::string> &Values) {
480 switch (OptClass) {
481 case Option::CommaJoinedClass: {
482 std::string CommaJoinedValue;
483 if (!Values.empty()) {
484 CommaJoinedValue.append(Values.front());
485 for (const std::string &Value : llvm::drop_begin(Values, 1)) {
486 CommaJoinedValue.append(",");
487 CommaJoinedValue.append(Value);
488 }
489 }
490 denormalizeString(Consumer, SpellingOffset,
491 Option::OptionClass::JoinedClass, TableIndex,
492 CommaJoinedValue);
493 break;
494 }
495 case Option::JoinedClass:
496 case Option::SeparateClass:
497 case Option::JoinedOrSeparateClass:
498 for (const std::string &Value : Values)
499 denormalizeString(Consumer, SpellingOffset, OptClass, TableIndex, Value);
500 break;
501 default:
502 llvm_unreachable("Cannot denormalize an option with option class "
503 "incompatible with string vector denormalization.");
504 }
505}
506
507static std::optional<std::string> normalizeTriple(OptSpecifier Opt,
508 int TableIndex,
509 const ArgList &Args,
510 DiagnosticsEngine &Diags) {
511 auto *Arg = Args.getLastArg(Opt);
512 if (!Arg)
513 return std::nullopt;
514 return llvm::Triple::normalize(Arg->getValue());
515}
516
517#define PARSE_OPTION_WITH_MARSHALLING( \
518 ARGS, DIAGS, PREFIX_TYPE, SPELLING_OFFSET, ID, KIND, GROUP, ALIAS, \
519 ALIASARGS, FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, \
520 METAVAR, VALUES, SUBCOMMANDIDS_OFFSET, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, \
521 DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, \
522 TABLE_INDEX) \
523 if ((VISIBILITY) & options::CC1Option) { \
524 KEYPATH = static_cast<decltype(KEYPATH)>(DEFAULT_VALUE); \
525 if (IMPLIED_CHECK) \
526 KEYPATH = static_cast<decltype(KEYPATH)>(IMPLIED_VALUE); \
527 if (SHOULD_PARSE) \
528 if (auto MaybeValue = NORMALIZER(OPT_##ID, TABLE_INDEX, ARGS, DIAGS)) \
529 KEYPATH = static_cast<decltype(KEYPATH)>(*MaybeValue); \
530 }
531
532#define GENERATE_OPTION_WITH_MARSHALLING( \
533 CONSUMER, PREFIX_TYPE, SPELLING_OFFSET, ID, KIND, GROUP, ALIAS, ALIASARGS, \
534 FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, VALUES, \
535 SUBCOMMANDIDS_OFFSET, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, \
536 IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, TABLE_INDEX) \
537 if ((VISIBILITY) & options::CC1Option) { \
538 if (ALWAYS_EMIT || (KEYPATH != static_cast<decltype(KEYPATH)>( \
539 ((IMPLIED_CHECK) ? (IMPLIED_VALUE) \
540 : (DEFAULT_VALUE))))) \
541 DENORMALIZER(CONSUMER, SPELLING_OFFSET, Option::KIND##Class, \
542 TABLE_INDEX, KEYPATH); \
543 }
544
545static StringRef GetInputKindName(InputKind IK);
546
547static bool FixupInvocation(CompilerInvocation &Invocation,
548 DiagnosticsEngine &Diags, const ArgList &Args,
549 InputKind IK) {
550 unsigned NumErrorsBefore = Diags.getNumErrors();
551
552 LangOptions &LangOpts = Invocation.getLangOpts();
553 CodeGenOptions &CodeGenOpts = Invocation.getCodeGenOpts();
554 TargetOptions &TargetOpts = Invocation.getTargetOpts();
555 FrontendOptions &FrontendOpts = Invocation.getFrontendOpts();
556 CodeGenOpts.XRayInstrumentFunctions = LangOpts.XRayInstrument;
557 CodeGenOpts.XRayAlwaysEmitCustomEvents = LangOpts.XRayAlwaysEmitCustomEvents;
558 CodeGenOpts.XRayAlwaysEmitTypedEvents = LangOpts.XRayAlwaysEmitTypedEvents;
559 CodeGenOpts.DisableFree = FrontendOpts.DisableFree;
560 FrontendOpts.GenerateGlobalModuleIndex = FrontendOpts.UseGlobalModuleIndex;
561 if (FrontendOpts.ShowStats)
562 CodeGenOpts.ClearASTBeforeBackend = false;
563 LangOpts.SanitizeCoverage = CodeGenOpts.hasSanitizeCoverage();
564 LangOpts.ForceEmitVTables = CodeGenOpts.ForceEmitVTables;
565 LangOpts.SpeculativeLoadHardening = CodeGenOpts.SpeculativeLoadHardening;
566 LangOpts.CurrentModule = LangOpts.ModuleName;
567
568 llvm::Triple T(TargetOpts.Triple);
569 llvm::Triple::ArchType Arch = T.getArch();
570
571 CodeGenOpts.CodeModel = TargetOpts.CodeModel;
572 CodeGenOpts.LargeDataThreshold = TargetOpts.LargeDataThreshold;
573
574 if (CodeGenOpts.getExceptionHandling() !=
576 T.isWindowsMSVCEnvironment())
577 Diags.Report(diag::err_fe_invalid_exception_model)
578 << static_cast<unsigned>(CodeGenOpts.getExceptionHandling()) << T.str();
579
580 if (LangOpts.AppleKext && !LangOpts.CPlusPlus)
581 Diags.Report(diag::warn_c_kext);
582
583 if (LangOpts.NewAlignOverride &&
584 !llvm::isPowerOf2_32(LangOpts.NewAlignOverride)) {
585 Arg *A = Args.getLastArg(OPT_fnew_alignment_EQ);
586 Diags.Report(diag::err_fe_invalid_alignment)
587 << A->getAsString(Args) << A->getValue();
588 LangOpts.NewAlignOverride = 0;
589 }
590
591 // The -f[no-]raw-string-literals option is only valid in C and in C++
592 // standards before C++11.
593 if (LangOpts.CPlusPlus11) {
594 if (Args.hasArg(OPT_fraw_string_literals, OPT_fno_raw_string_literals)) {
595 Args.claimAllArgs(OPT_fraw_string_literals, OPT_fno_raw_string_literals);
596 Diags.Report(diag::warn_drv_fraw_string_literals_in_cxx11)
597 << bool(LangOpts.RawStringLiterals);
598 }
599
600 // Do not allow disabling raw string literals in C++11 or later.
601 LangOpts.RawStringLiterals = true;
602 }
603
604 if (Args.hasArg(OPT_freflection) && !LangOpts.CPlusPlus26) {
605 Diags.Report(diag::err_drv_reflection_requires_cxx26)
606 << Args.getLastArg(options::OPT_freflection)->getAsString(Args);
607 }
608
609 LangOpts.NamedLoops =
610 Args.hasFlag(OPT_fnamed_loops, OPT_fno_named_loops, LangOpts.C2y);
611
612 // Prevent the user from specifying both -fsycl-is-device and -fsycl-is-host.
613 if (LangOpts.SYCLIsDevice && LangOpts.SYCLIsHost)
614 Diags.Report(diag::err_drv_argument_not_allowed_with) << "-fsycl-is-device"
615 << "-fsycl-is-host";
616
617 // SYCL requires C++; reject C inputs on both device and host.
618 if ((LangOpts.SYCLIsDevice || LangOpts.SYCLIsHost) && !LangOpts.CPlusPlus)
619 Diags.Report(diag::err_drv_argument_not_allowed_with)
620 << GetInputKindName(IK) << "-fsycl";
621
622 if (Args.hasArg(OPT_fgnu89_inline) && LangOpts.CPlusPlus)
623 Diags.Report(diag::err_drv_argument_not_allowed_with)
624 << "-fgnu89-inline" << GetInputKindName(IK);
625
626 if (Args.hasArg(OPT_hlsl_entrypoint) && !LangOpts.HLSL)
627 Diags.Report(diag::err_drv_argument_not_allowed_with)
628 << "-hlsl-entry" << GetInputKindName(IK);
629
630 if (Args.hasArg(OPT_fdx_rootsignature_version) && !LangOpts.HLSL)
631 Diags.Report(diag::err_drv_argument_not_allowed_with)
632 << "-fdx-rootsignature-version" << GetInputKindName(IK);
633
634 if (Args.hasArg(OPT_fdx_rootsignature_define) && !LangOpts.HLSL)
635 Diags.Report(diag::err_drv_argument_not_allowed_with)
636 << "-fdx-rootsignature-define" << GetInputKindName(IK);
637
638 if (Args.hasArg(OPT_fdx_semantic_signature_packing_mode_EQ) && !LangOpts.HLSL)
639 Diags.Report(diag::err_drv_argument_not_allowed_with)
640 << "-fdx-semantic-signature-packing-mode" << 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
1483 if (LangOpts.PointerAuthVTTVTPtrDiscrimination)
1485 Key::ASDA, LangOpts.PointerAuthVTPtrAddressDiscrimination,
1486 LangOpts.PointerAuthVTPtrTypeDiscrimination ? Discrimination::Type
1487 : Discrimination::None);
1488 else
1490 PointerAuthSchema(Key::ASDA, false, Discrimination::None);
1491
1493 PointerAuthSchema(Key::ASIA, true, Discrimination::Decl);
1495 PointerAuthSchema(Key::ASIA, false, Discrimination::Type);
1496
1498 PointerAuthSchema(Key::ASIA, true, Discrimination::None);
1500 PointerAuthSchema(Key::ASIA, true, Discrimination::None);
1502 PointerAuthSchema(Key::ASIA, true, Discrimination::None);
1503 if (LangOpts.PointerAuthBlockDescriptorPointers)
1505 PointerAuthSchema(Key::ASDA, true, Discrimination::Constant,
1507
1509 PointerAuthSchema(Key::ASIA, true, Discrimination::None);
1511 PointerAuthSchema(Key::ASDA, true, Discrimination::Constant,
1513 if (LangOpts.PointerAuthObjcIsa) {
1514 Opts.ObjCIsaPointers =
1515 PointerAuthSchema(Key::ASDA, true, Discrimination::Constant,
1517 Opts.ObjCSuperPointers =
1518 PointerAuthSchema(Key::ASDA, true, Discrimination::Constant,
1520 }
1521
1522 if (LangOpts.PointerAuthObjcClassROPointers)
1523 Opts.ObjCClassROPointers =
1524 PointerAuthSchema(Key::ASDA, true, Discrimination::Constant,
1526 }
1527 Opts.ReturnAddresses = LangOpts.PointerAuthReturns;
1528 Opts.AuthTraps = LangOpts.PointerAuthAuthTraps;
1529 Opts.IndirectGotos = LangOpts.PointerAuthIndirectGotos;
1530 Opts.AArch64JumpTableHardening = LangOpts.AArch64JumpTableHardening;
1531}
1532
1534 const LangOptions &LangOpts,
1535 const llvm::Triple &Triple,
1536 DiagnosticsEngine &Diags) {
1537 if (!LangOpts.PointerAuthCalls && !LangOpts.PointerAuthReturns &&
1538 !LangOpts.PointerAuthAuthTraps && !LangOpts.PointerAuthIndirectGotos &&
1539 !LangOpts.AArch64JumpTableHardening)
1540 return;
1541
1543}
1544
1545void CompilerInvocationBase::GenerateCodeGenArgs(const CodeGenOptions &Opts,
1546 ArgumentConsumer Consumer,
1547 const llvm::Triple &T,
1548 const std::string &OutputFile,
1549 const LangOptions *LangOpts) {
1550 const CodeGenOptions &CodeGenOpts = Opts;
1551
1552 if (Opts.OptimizationLevel == 0)
1553 GenerateArg(Consumer, OPT_O0);
1554 else
1555 GenerateArg(Consumer, OPT_O, Twine(Opts.OptimizationLevel));
1556
1557#define CODEGEN_OPTION_WITH_MARSHALLING(...) \
1558 GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
1559#include "clang/Options/Options.inc"
1560#undef CODEGEN_OPTION_WITH_MARSHALLING
1561
1562 if (Opts.OptimizationLevel > 0) {
1563 if (Opts.Inlining == CodeGenOptions::NormalInlining)
1564 GenerateArg(Consumer, OPT_finline_functions);
1565 else if (Opts.Inlining == CodeGenOptions::OnlyHintInlining)
1566 GenerateArg(Consumer, OPT_finline_hint_functions);
1567 else if (Opts.Inlining == CodeGenOptions::OnlyAlwaysInlining)
1568 GenerateArg(Consumer, OPT_fno_inline);
1569 }
1570
1571 if (Opts.DirectAccessExternalData && LangOpts->PICLevel != 0)
1572 GenerateArg(Consumer, OPT_fdirect_access_external_data);
1573 else if (!Opts.DirectAccessExternalData && LangOpts->PICLevel == 0)
1574 GenerateArg(Consumer, OPT_fno_direct_access_external_data);
1575
1576 std::optional<StringRef> DebugInfoVal;
1577 switch (Opts.DebugInfo) {
1578 case llvm::codegenoptions::DebugLineTablesOnly:
1579 DebugInfoVal = "line-tables-only";
1580 break;
1581 case llvm::codegenoptions::DebugDirectivesOnly:
1582 DebugInfoVal = "line-directives-only";
1583 break;
1584 case llvm::codegenoptions::DebugInfoConstructor:
1585 DebugInfoVal = "constructor";
1586 break;
1587 case llvm::codegenoptions::LimitedDebugInfo:
1588 DebugInfoVal = "limited";
1589 break;
1590 case llvm::codegenoptions::FullDebugInfo:
1591 DebugInfoVal = "standalone";
1592 break;
1593 case llvm::codegenoptions::UnusedTypeInfo:
1594 DebugInfoVal = "unused-types";
1595 break;
1596 case llvm::codegenoptions::NoDebugInfo: // default value
1597 DebugInfoVal = std::nullopt;
1598 break;
1599 case llvm::codegenoptions::LocTrackingOnly: // implied value
1600 DebugInfoVal = std::nullopt;
1601 break;
1602 }
1603 if (DebugInfoVal)
1604 GenerateArg(Consumer, OPT_debug_info_kind_EQ, *DebugInfoVal);
1605
1606 for (const auto &Prefix : Opts.DebugPrefixMap)
1607 GenerateArg(Consumer, OPT_fdebug_prefix_map_EQ,
1608 Prefix.first + "=" + Prefix.second);
1609
1610 for (const auto &Prefix : Opts.CoveragePrefixMap)
1611 GenerateArg(Consumer, OPT_fcoverage_prefix_map_EQ,
1612 Prefix.first + "=" + Prefix.second);
1613
1614 if (Opts.NewStructPathTBAA)
1615 GenerateArg(Consumer, OPT_new_struct_path_tbaa);
1616
1617 if (Opts.OptimizeSize == 1)
1618 GenerateArg(Consumer, OPT_O, "s");
1619 else if (Opts.OptimizeSize == 2)
1620 GenerateArg(Consumer, OPT_O, "z");
1621
1622 // SimplifyLibCalls is set only in the absence of -fno-builtin and
1623 // -ffreestanding. We'll consider that when generating them.
1624
1625 // NoBuiltinFuncs are generated by LangOptions.
1626
1627 if (Opts.UnrollLoops && Opts.OptimizationLevel <= 1)
1628 GenerateArg(Consumer, OPT_funroll_loops);
1629 else if (!Opts.UnrollLoops && Opts.OptimizationLevel > 1)
1630 GenerateArg(Consumer, OPT_fno_unroll_loops);
1631
1632 if (Opts.InterchangeLoops)
1633 GenerateArg(Consumer, OPT_floop_interchange);
1634 else
1635 GenerateArg(Consumer, OPT_fno_loop_interchange);
1636
1637 if (Opts.FuseLoops)
1638 GenerateArg(Consumer, OPT_fexperimental_loop_fusion);
1639
1640 if (!Opts.BinutilsVersion.empty())
1641 GenerateArg(Consumer, OPT_fbinutils_version_EQ, Opts.BinutilsVersion);
1642
1643 if (Opts.DebugNameTable ==
1644 static_cast<unsigned>(llvm::DICompileUnit::DebugNameTableKind::GNU))
1645 GenerateArg(Consumer, OPT_ggnu_pubnames);
1646 else if (Opts.DebugNameTable ==
1647 static_cast<unsigned>(
1648 llvm::DICompileUnit::DebugNameTableKind::Default))
1649 GenerateArg(Consumer, OPT_gpubnames);
1650
1651 if (Opts.DebugTemplateAlias)
1652 GenerateArg(Consumer, OPT_gtemplate_alias);
1653
1654 auto TNK = Opts.getDebugSimpleTemplateNames();
1655 if (TNK != llvm::codegenoptions::DebugTemplateNamesKind::Full) {
1656 if (TNK == llvm::codegenoptions::DebugTemplateNamesKind::Simple)
1657 GenerateArg(Consumer, OPT_gsimple_template_names_EQ, "simple");
1658 else if (TNK == llvm::codegenoptions::DebugTemplateNamesKind::Mangled)
1659 GenerateArg(Consumer, OPT_gsimple_template_names_EQ, "mangled");
1660 }
1661 // ProfileInstrumentUsePath is marshalled automatically, no need to generate
1662 // it or PGOUseInstrumentor.
1663
1664 if (Opts.TimePasses) {
1665 if (Opts.TimePassesPerRun)
1666 GenerateArg(Consumer, OPT_ftime_report_EQ, "per-pass-run");
1667 else
1668 GenerateArg(Consumer, OPT_ftime_report);
1669
1670 if (Opts.TimePassesJson)
1671 GenerateArg(Consumer, OPT_ftime_report_json);
1672 }
1673
1674 if (Opts.PrepareForLTO && !Opts.PrepareForThinLTO)
1675 GenerateArg(Consumer, OPT_flto_EQ, "full");
1676
1677 if (Opts.PrepareForThinLTO)
1678 GenerateArg(Consumer, OPT_flto_EQ, "thin");
1679
1680 if (!Opts.ThinLTOIndexFile.empty())
1681 GenerateArg(Consumer, OPT_fthinlto_index_EQ, Opts.ThinLTOIndexFile);
1682
1683 if (Opts.SaveTempsFilePrefix == OutputFile)
1684 GenerateArg(Consumer, OPT_save_temps_EQ, "obj");
1685
1686 if (!Opts.SaveDynDbgTempsFilePrefix.empty())
1687 GenerateArg(Consumer, OPT_save_dynamic_debugging_temps);
1688
1689 StringRef MemProfileBasename("memprof.profraw");
1690 if (!Opts.MemoryProfileOutput.empty()) {
1691 if (Opts.MemoryProfileOutput == MemProfileBasename) {
1692 GenerateArg(Consumer, OPT_fmemory_profile);
1693 } else {
1694 size_t ArgLength =
1695 Opts.MemoryProfileOutput.size() - MemProfileBasename.size();
1696 GenerateArg(Consumer, OPT_fmemory_profile_EQ,
1697 Opts.MemoryProfileOutput.substr(0, ArgLength));
1698 }
1699 }
1700
1701 if (memcmp(Opts.CoverageVersion, "0000", 4))
1702 GenerateArg(Consumer, OPT_coverage_version_EQ,
1703 StringRef(Opts.CoverageVersion, 4));
1704
1705 // TODO: Check if we need to generate arguments stored in CmdArgs. (Namely
1706 // '-fembed_bitcode', which does not map to any CompilerInvocation field and
1707 // won't be generated.)
1708
1710 std::string InstrBundle =
1712 if (!InstrBundle.empty())
1713 GenerateArg(Consumer, OPT_fxray_instrumentation_bundle, InstrBundle);
1714 }
1715
1716 if (Opts.CFProtectionReturn && Opts.CFProtectionBranch)
1717 GenerateArg(Consumer, OPT_fcf_protection_EQ, "full");
1718 else if (Opts.CFProtectionReturn)
1719 GenerateArg(Consumer, OPT_fcf_protection_EQ, "return");
1720 else if (Opts.CFProtectionBranch)
1721 GenerateArg(Consumer, OPT_fcf_protection_EQ, "branch");
1722
1723 if (Opts.CFProtectionBranch) {
1724 switch (Opts.getCFBranchLabelScheme()) {
1726 break;
1727#define CF_BRANCH_LABEL_SCHEME(Kind, FlagVal) \
1728 case CFBranchLabelSchemeKind::Kind: \
1729 GenerateArg(Consumer, OPT_mcf_branch_label_scheme_EQ, #FlagVal); \
1730 break;
1731#include "clang/Basic/CFProtectionOptions.def"
1732 }
1733 }
1734
1735 if (Opts.FunctionReturnThunks)
1736 GenerateArg(Consumer, OPT_mfunction_return_EQ, "thunk-extern");
1737
1738 for (const auto &F : Opts.LinkBitcodeFiles) {
1739 bool Builtint = F.LinkFlags == llvm::Linker::Flags::LinkOnlyNeeded &&
1740 F.PropagateAttrs && F.Internalize;
1741 GenerateArg(Consumer,
1742 Builtint ? OPT_mlink_builtin_bitcode : OPT_mlink_bitcode_file,
1743 F.Filename);
1744 }
1745
1746 if (Opts.EmulatedTLS)
1747 GenerateArg(Consumer, OPT_femulated_tls);
1748
1749 if (Opts.FPDenormalMode != llvm::DenormalMode::getIEEE())
1750 GenerateArg(Consumer, OPT_fdenormal_fp_math_EQ, Opts.FPDenormalMode.str());
1751
1752 if ((Opts.FPDenormalMode != Opts.FP32DenormalMode) ||
1753 (Opts.FP32DenormalMode != llvm::DenormalMode::getIEEE()))
1754 GenerateArg(Consumer, OPT_fdenormal_fp_math_f32_EQ,
1755 Opts.FP32DenormalMode.str());
1756
1757 if (Opts.StructReturnConvention == CodeGenOptions::SRCK_OnStack) {
1758 OptSpecifier Opt =
1759 T.isPPC32() ? OPT_maix_struct_return : OPT_fpcc_struct_return;
1760 GenerateArg(Consumer, Opt);
1761 } else if (Opts.StructReturnConvention == CodeGenOptions::SRCK_InRegs) {
1762 OptSpecifier Opt =
1763 T.isPPC32() ? OPT_msvr4_struct_return : OPT_freg_struct_return;
1764 GenerateArg(Consumer, Opt);
1765 }
1766
1767 if (Opts.XCOFFReadOnlyPointers)
1768 GenerateArg(Consumer, OPT_mxcoff_roptr);
1769
1770 if (!Opts.OptRecordPasses.empty())
1771 GenerateArg(Consumer, OPT_opt_record_passes, Opts.OptRecordPasses);
1772
1773 if (!Opts.OptRecordFormat.empty())
1774 GenerateArg(Consumer, OPT_opt_record_format, Opts.OptRecordFormat);
1775
1776 GenerateOptimizationRemark(Consumer, OPT_Rpass_EQ, "pass",
1777 Opts.OptimizationRemark);
1778
1779 GenerateOptimizationRemark(Consumer, OPT_Rpass_missed_EQ, "pass-missed",
1781
1782 GenerateOptimizationRemark(Consumer, OPT_Rpass_analysis_EQ, "pass-analysis",
1784
1785 GenerateArg(Consumer, OPT_fdiagnostics_hotness_threshold_EQ,
1787 ? Twine(*Opts.DiagnosticsHotnessThreshold)
1788 : "auto");
1789
1790 GenerateArg(Consumer, OPT_fdiagnostics_misexpect_tolerance_EQ,
1791 Twine(*Opts.DiagnosticsMisExpectTolerance));
1792
1793 for (StringRef Sanitizer : serializeSanitizerKinds(Opts.SanitizeRecover))
1794 GenerateArg(Consumer, OPT_fsanitize_recover_EQ, Sanitizer);
1795
1796 for (StringRef Sanitizer : serializeSanitizerKinds(Opts.SanitizeTrap))
1797 GenerateArg(Consumer, OPT_fsanitize_trap_EQ, Sanitizer);
1798
1799 for (StringRef Sanitizer :
1801 GenerateArg(Consumer, OPT_fsanitize_merge_handlers_EQ, Sanitizer);
1802
1803 SmallVector<std::string, 4> Values;
1805 for (std::string Sanitizer : Values)
1806 GenerateArg(Consumer, OPT_fsanitize_skip_hot_cutoff_EQ, Sanitizer);
1807
1809 GenerateArg(Consumer, OPT_fallow_runtime_check_skip_hot_cutoff_EQ,
1810 std::to_string(*Opts.AllowRuntimeCheckSkipHotCutoff));
1811 }
1812
1813 for (StringRef Sanitizer :
1815 GenerateArg(Consumer, OPT_fsanitize_annotate_debug_info_EQ, Sanitizer);
1816
1817 if (!Opts.EmitVersionIdentMetadata)
1818 GenerateArg(Consumer, OPT_Qn);
1819
1820 switch (Opts.FiniteLoops) {
1822 break;
1824 GenerateArg(Consumer, OPT_ffinite_loops);
1825 break;
1827 GenerateArg(Consumer, OPT_fno_finite_loops);
1828 break;
1829 }
1830
1831 if (Opts.StaticClosure)
1832 GenerateArg(Consumer, OPT_static_libclosure);
1833}
1834
1835bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
1836 InputKind IK,
1837 DiagnosticsEngine &Diags,
1838 const llvm::Triple &T,
1839 const std::string &OutputFile,
1840 const LangOptions &LangOptsRef) {
1841 unsigned NumErrorsBefore = Diags.getNumErrors();
1842
1843 Opts.OptimizationLevel = getOptimizationLevel(Args, IK, Diags);
1844
1845 // The key paths of codegen options defined in Options.td start with
1846 // "CodeGenOpts.". Let's provide the expected variable name and type.
1847 CodeGenOptions &CodeGenOpts = Opts;
1848 // Some codegen options depend on language options. Let's provide the expected
1849 // variable name and type.
1850 const LangOptions *LangOpts = &LangOptsRef;
1851
1852#define CODEGEN_OPTION_WITH_MARSHALLING(...) \
1853 PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
1854#include "clang/Options/Options.inc"
1855#undef CODEGEN_OPTION_WITH_MARSHALLING
1856
1857 // At O0 we want to fully disable inlining outside of cases marked with
1858 // 'alwaysinline' that are required for correctness.
1859 if (Opts.OptimizationLevel == 0) {
1860 Opts.setInlining(CodeGenOptions::OnlyAlwaysInlining);
1861 } else if (const Arg *A = Args.getLastArg(options::OPT_finline_functions,
1862 options::OPT_finline_hint_functions,
1863 options::OPT_fno_inline_functions,
1864 options::OPT_fno_inline)) {
1865 // Explicit inlining flags can disable some or all inlining even at
1866 // optimization levels above zero.
1867 if (A->getOption().matches(options::OPT_finline_functions))
1868 Opts.setInlining(CodeGenOptions::NormalInlining);
1869 else if (A->getOption().matches(options::OPT_finline_hint_functions))
1870 Opts.setInlining(CodeGenOptions::OnlyHintInlining);
1871 else
1872 Opts.setInlining(CodeGenOptions::OnlyAlwaysInlining);
1873 } else {
1874 Opts.setInlining(CodeGenOptions::NormalInlining);
1875 }
1876
1877 // PIC defaults to -fno-direct-access-external-data while non-PIC defaults to
1878 // -fdirect-access-external-data.
1879 Opts.DirectAccessExternalData =
1880 Args.hasArg(OPT_fdirect_access_external_data) ||
1881 (!Args.hasArg(OPT_fno_direct_access_external_data) &&
1882 LangOpts->PICLevel == 0);
1883
1884 if (Arg *A = Args.getLastArg(OPT_debug_info_kind_EQ)) {
1885 unsigned Val =
1886 llvm::StringSwitch<unsigned>(A->getValue())
1887 .Case("line-tables-only", llvm::codegenoptions::DebugLineTablesOnly)
1888 .Case("line-directives-only",
1889 llvm::codegenoptions::DebugDirectivesOnly)
1890 .Case("constructor", llvm::codegenoptions::DebugInfoConstructor)
1891 .Case("limited", llvm::codegenoptions::LimitedDebugInfo)
1892 .Case("standalone", llvm::codegenoptions::FullDebugInfo)
1893 .Case("unused-types", llvm::codegenoptions::UnusedTypeInfo)
1894 .Default(~0U);
1895 if (Val == ~0U)
1896 Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args)
1897 << A->getValue();
1898 else
1899 Opts.setDebugInfo(static_cast<llvm::codegenoptions::DebugInfoKind>(Val));
1900 }
1901
1902 // If -fuse-ctor-homing is set and limited debug info is already on, then use
1903 // constructor homing, and vice versa for -fno-use-ctor-homing.
1904 if (const Arg *A =
1905 Args.getLastArg(OPT_fuse_ctor_homing, OPT_fno_use_ctor_homing)) {
1906 if (A->getOption().matches(OPT_fuse_ctor_homing) &&
1907 Opts.getDebugInfo() == llvm::codegenoptions::LimitedDebugInfo)
1908 Opts.setDebugInfo(llvm::codegenoptions::DebugInfoConstructor);
1909 if (A->getOption().matches(OPT_fno_use_ctor_homing) &&
1910 Opts.getDebugInfo() == llvm::codegenoptions::DebugInfoConstructor)
1911 Opts.setDebugInfo(llvm::codegenoptions::LimitedDebugInfo);
1912 }
1913
1914 for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ)) {
1915 auto Split = StringRef(Arg).split('=');
1916 Opts.DebugPrefixMap.emplace_back(Split.first, Split.second);
1917 }
1918
1919 for (const auto &Arg : Args.getAllArgValues(OPT_fcoverage_prefix_map_EQ)) {
1920 auto Split = StringRef(Arg).split('=');
1921 Opts.CoveragePrefixMap.emplace_back(Split.first, Split.second);
1922 }
1923
1924 if (Opts.OptimizationLevel > 0 && Opts.hasReducedDebugInfo() &&
1925 T.supportsDebugEntryValues())
1926 Opts.EmitCallSiteInfo = true;
1927
1928 if (!Opts.EnableDIPreservationVerify && Opts.DIBugsReportFilePath.size()) {
1929 Diags.Report(diag::warn_ignoring_verify_debuginfo_preserve_export)
1930 << Opts.DIBugsReportFilePath;
1931 Opts.DIBugsReportFilePath = "";
1932 }
1933
1934 Opts.NewStructPathTBAA = !Args.hasArg(OPT_no_struct_path_tbaa) &&
1935 Args.hasArg(OPT_new_struct_path_tbaa);
1936 Opts.OptimizeSize = getOptimizationLevelSize(Args);
1937 Opts.SimplifyLibCalls = !LangOpts->NoBuiltin;
1938 if (Opts.SimplifyLibCalls)
1939 Opts.NoBuiltinFuncs = LangOpts->NoBuiltinFuncs;
1940 Opts.UnrollLoops =
1941 Args.hasFlag(OPT_funroll_loops, OPT_fno_unroll_loops,
1942 (Opts.OptimizationLevel > 1));
1943 // Match the LLVM pipeline default (PipelineTuningOptions::LoopInterchange),
1944 // which enables the pass whenever the optimization pipeline runs.
1945 Opts.InterchangeLoops =
1946 Args.hasFlag(OPT_floop_interchange, OPT_fno_loop_interchange, true);
1947 Opts.FuseLoops = Args.hasFlag(OPT_fexperimental_loop_fusion,
1948 OPT_fno_experimental_loop_fusion, false);
1949 Opts.BinutilsVersion =
1950 std::string(Args.getLastArgValue(OPT_fbinutils_version_EQ));
1951
1952 Opts.DebugTemplateAlias = Args.hasArg(OPT_gtemplate_alias);
1953
1954 Opts.DebugNameTable = static_cast<unsigned>(
1955 Args.hasArg(OPT_ggnu_pubnames)
1956 ? llvm::DICompileUnit::DebugNameTableKind::GNU
1957 : Args.hasArg(OPT_gpubnames)
1958 ? llvm::DICompileUnit::DebugNameTableKind::Default
1959 : llvm::DICompileUnit::DebugNameTableKind::None);
1960 if (const Arg *A = Args.getLastArg(OPT_gsimple_template_names_EQ)) {
1961 StringRef Value = A->getValue();
1962 if (Value != "simple" && Value != "mangled")
1963 Diags.Report(diag::err_drv_unsupported_option_argument)
1964 << A->getSpelling() << A->getValue();
1965 Opts.setDebugSimpleTemplateNames(
1966 StringRef(A->getValue()) == "simple"
1967 ? llvm::codegenoptions::DebugTemplateNamesKind::Simple
1968 : llvm::codegenoptions::DebugTemplateNamesKind::Mangled);
1969 }
1970
1971 if (Args.hasArg(OPT_ftime_report, OPT_ftime_report_EQ, OPT_ftime_report_json,
1972 OPT_stats_file_timers)) {
1973 Opts.TimePasses = true;
1974
1975 // -ftime-report= is only for new pass manager.
1976 if (const Arg *EQ = Args.getLastArg(OPT_ftime_report_EQ)) {
1977 StringRef Val = EQ->getValue();
1978 if (Val == "per-pass")
1979 Opts.TimePassesPerRun = false;
1980 else if (Val == "per-pass-run")
1981 Opts.TimePassesPerRun = true;
1982 else
1983 Diags.Report(diag::err_drv_invalid_value)
1984 << EQ->getAsString(Args) << EQ->getValue();
1985 }
1986
1987 if (Args.getLastArg(OPT_ftime_report_json))
1988 Opts.TimePassesJson = true;
1989 }
1990
1991 Opts.PrepareForLTO = false;
1992 Opts.PrepareForThinLTO = false;
1993 if (Arg *A = Args.getLastArg(OPT_flto_EQ)) {
1994 Opts.PrepareForLTO = true;
1995 StringRef S = A->getValue();
1996 if (S == "thin")
1997 Opts.PrepareForThinLTO = true;
1998 else if (S != "full")
1999 Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << S;
2000 if (Args.hasArg(OPT_funified_lto))
2001 Opts.PrepareForThinLTO = true;
2002 }
2003 if (Arg *A = Args.getLastArg(OPT_fthinlto_index_EQ)) {
2004 if (IK.getLanguage() != Language::LLVM_IR)
2005 Diags.Report(diag::err_drv_argument_only_allowed_with)
2006 << A->getAsString(Args) << "-x ir";
2007 Opts.ThinLTOIndexFile =
2008 std::string(Args.getLastArgValue(OPT_fthinlto_index_EQ));
2009 }
2010 if (Arg *A = Args.getLastArg(OPT_save_temps_EQ))
2011 Opts.SaveTempsFilePrefix =
2012 llvm::StringSwitch<std::string>(A->getValue())
2013 .Case("obj", OutputFile)
2014 .Default(llvm::sys::path::filename(OutputFile).str());
2015
2016 if (Args.getLastArg(OPT_save_dynamic_debugging_temps))
2017 Opts.SaveDynDbgTempsFilePrefix = OutputFile;
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 A->getOption().matches(options::OPT_O4))
2734 return 3;
2735
2736 assert(A->getOption().matches(options::OPT_O));
2737
2738 StringRef S(A->getValue());
2739 if (S == "s" || S == "z")
2740 return 2;
2741
2742 if (S == "g")
2743 return 1;
2744
2745 DefaultOpt = getLastArgIntValue(Args, OPT_O, DefaultOpt, Diags);
2746 }
2747
2748 unsigned MaxOptLevel = 3;
2749 if (DefaultOpt > MaxOptLevel) {
2750 // If the optimization level is not supported, fall back on the default
2751 // optimization
2752 Diags.Report(diag::warn_drv_optimization_value)
2753 << Args.getLastArg(OPT_O)->getAsString(Args) << "-O" << MaxOptLevel;
2754 DefaultOpt = MaxOptLevel;
2755 }
2756
2757 return DefaultOpt;
2758}
2759
2760unsigned clang::getOptimizationLevelSize(const ArgList &Args) {
2761 if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
2762 if (A->getOption().matches(options::OPT_O)) {
2763 switch (A->getValue()[0]) {
2764 default:
2765 return 0;
2766 case 's':
2767 return 1;
2768 case 'z':
2769 return 2;
2770 }
2771 }
2772 }
2773 return 0;
2774}
2775
2776/// Parse the argument to the -ftest-module-file-extension
2777/// command-line argument.
2778///
2779/// \returns true on error, false on success.
2780static bool parseTestModuleFileExtensionArg(StringRef Arg,
2781 std::string &BlockName,
2782 unsigned &MajorVersion,
2783 unsigned &MinorVersion,
2784 bool &Hashed,
2785 std::string &UserInfo) {
2787 Arg.split(Args, ':', 5);
2788 if (Args.size() < 5)
2789 return true;
2790
2791 BlockName = std::string(Args[0]);
2792 if (Args[1].getAsInteger(10, MajorVersion)) return true;
2793 if (Args[2].getAsInteger(10, MinorVersion)) return true;
2794 if (Args[3].getAsInteger(2, Hashed)) return true;
2795 if (Args.size() > 4)
2796 UserInfo = std::string(Args[4]);
2797 return false;
2798}
2799
2800/// Return a table that associates command line option specifiers with the
2801/// frontend action. Note: The pair {frontend::PluginAction, OPT_plugin} is
2802/// intentionally missing, as this case is handled separately from other
2803/// frontend options.
2804static const auto &getFrontendActionTable() {
2805 static const std::pair<frontend::ActionKind, unsigned> Table[] = {
2806 {frontend::ASTDeclList, OPT_ast_list},
2807
2808 {frontend::ASTDump, OPT_ast_dump_all_EQ},
2809 {frontend::ASTDump, OPT_ast_dump_all},
2810 {frontend::ASTDump, OPT_ast_dump_EQ},
2811 {frontend::ASTDump, OPT_ast_dump},
2812 {frontend::ASTDump, OPT_ast_dump_lookups},
2813 {frontend::ASTDump, OPT_ast_dump_decl_types},
2814
2815 {frontend::ASTPrint, OPT_ast_print},
2816 {frontend::ASTView, OPT_ast_view},
2817 {frontend::DumpCompilerOptions, OPT_compiler_options_dump},
2818 {frontend::DumpRawTokens, OPT_dump_raw_tokens},
2819 {frontend::DumpTokens, OPT_dump_tokens},
2820 {frontend::EmitAssembly, OPT_S},
2821 {frontend::EmitBC, OPT_emit_llvm_bc},
2822 {frontend::EmitCIR, OPT_emit_cir},
2823 {frontend::EmitCIRBC, OPT_emit_cir_bc},
2824 {frontend::EmitHTML, OPT_emit_html},
2825 {frontend::EmitLLVM, OPT_emit_llvm},
2826 {frontend::EmitLLVMOnly, OPT_emit_llvm_only},
2827 {frontend::EmitCodeGenOnly, OPT_emit_codegen_only},
2828 {frontend::EmitObj, OPT_emit_obj},
2829 {frontend::ExtractAPI, OPT_extract_api},
2830
2831 {frontend::FixIt, OPT_fixit_EQ},
2832 {frontend::FixIt, OPT_fixit},
2833
2834 {frontend::GenerateModule, OPT_emit_module},
2835 {frontend::GenerateModuleInterface, OPT_emit_module_interface},
2837 OPT_emit_reduced_module_interface},
2838 {frontend::GenerateHeaderUnit, OPT_emit_header_unit},
2839 {frontend::GeneratePCH, OPT_emit_pch},
2840 {frontend::GenerateInterfaceStubs, OPT_emit_interface_stubs},
2841 {frontend::InitOnly, OPT_init_only},
2842 {frontend::ParseSyntaxOnly, OPT_fsyntax_only},
2843 {frontend::ModuleFileInfo, OPT_module_file_info},
2844 {frontend::VerifyPCH, OPT_verify_pch},
2845 {frontend::PrintPreamble, OPT_print_preamble},
2847 {frontend::RewriteMacros, OPT_rewrite_macros},
2848 {frontend::RewriteObjC, OPT_rewrite_objc},
2849 {frontend::RewriteTest, OPT_rewrite_test},
2850 {frontend::RunAnalysis, OPT_analyze},
2851 {frontend::RunPreprocessorOnly, OPT_Eonly},
2853 OPT_print_dependency_directives_minimized_source},
2854 };
2855
2856 return Table;
2857}
2858
2859/// Maps command line option to frontend action.
2860static std::optional<frontend::ActionKind>
2861getFrontendAction(OptSpecifier &Opt) {
2862 for (const auto &ActionOpt : getFrontendActionTable())
2863 if (ActionOpt.second == Opt.getID())
2864 return ActionOpt.first;
2865
2866 return std::nullopt;
2867}
2868
2869/// Maps frontend action to command line option.
2870static std::optional<OptSpecifier>
2872 for (const auto &ActionOpt : getFrontendActionTable())
2873 if (ActionOpt.first == ProgramAction)
2874 return OptSpecifier(ActionOpt.second);
2875
2876 return std::nullopt;
2877}
2878
2880 ArgumentConsumer Consumer, bool IsHeader) {
2881 const FrontendOptions &FrontendOpts = Opts;
2882#define FRONTEND_OPTION_WITH_MARSHALLING(...) \
2883 GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
2884#include "clang/Options/Options.inc"
2885#undef FRONTEND_OPTION_WITH_MARSHALLING
2886
2887 std::optional<OptSpecifier> ProgramActionOpt =
2889
2890 // Generating a simple flag covers most frontend actions.
2891 std::function<void()> GenerateProgramAction = [&]() {
2892 GenerateArg(Consumer, *ProgramActionOpt);
2893 };
2894
2895 if (!ProgramActionOpt) {
2896 // PluginAction is the only program action handled separately.
2897 assert(Opts.ProgramAction == frontend::PluginAction &&
2898 "Frontend action without option.");
2899 GenerateProgramAction = [&]() {
2900 GenerateArg(Consumer, OPT_plugin, Opts.ActionName);
2901 };
2902 }
2903
2904 // FIXME: Simplify the complex 'AST dump' command line.
2905 if (Opts.ProgramAction == frontend::ASTDump) {
2906 GenerateProgramAction = [&]() {
2907 // ASTDumpLookups, ASTDumpDeclTypes and ASTDumpFilter are generated via
2908 // marshalling infrastructure.
2909
2910 if (Opts.ASTDumpFormat != ADOF_Default) {
2911 StringRef Format;
2912 switch (Opts.ASTDumpFormat) {
2913 case ADOF_Default:
2914 llvm_unreachable("Default AST dump format.");
2915 case ADOF_JSON:
2916 Format = "json";
2917 break;
2918 }
2919
2920 if (Opts.ASTDumpAll)
2921 GenerateArg(Consumer, OPT_ast_dump_all_EQ, Format);
2922 if (Opts.ASTDumpDecls)
2923 GenerateArg(Consumer, OPT_ast_dump_EQ, Format);
2924 } else {
2925 if (Opts.ASTDumpAll)
2926 GenerateArg(Consumer, OPT_ast_dump_all);
2927 if (Opts.ASTDumpDecls)
2928 GenerateArg(Consumer, OPT_ast_dump);
2929 }
2930 };
2931 }
2932
2933 if (Opts.ProgramAction == frontend::FixIt && !Opts.FixItSuffix.empty()) {
2934 GenerateProgramAction = [&]() {
2935 GenerateArg(Consumer, OPT_fixit_EQ, Opts.FixItSuffix);
2936 };
2937 }
2938
2939 GenerateProgramAction();
2940
2941 for (const auto &PluginArgs : Opts.PluginArgs) {
2942 Option Opt = getDriverOptTable().getOption(OPT_plugin_arg);
2943 for (const auto &PluginArg : PluginArgs.second)
2944 denormalizeString(Consumer,
2945 Opt.getPrefix() + Opt.getName() + PluginArgs.first,
2946 Opt.getKind(), 0, PluginArg);
2947 }
2948
2949 for (const auto &Ext : Opts.ModuleFileExtensions)
2950 if (auto *TestExt = dyn_cast_or_null<TestModuleFileExtension>(Ext.get()))
2951 GenerateArg(Consumer, OPT_ftest_module_file_extension_EQ, TestExt->str());
2952
2953 if (!Opts.CodeCompletionAt.FileName.empty())
2954 GenerateArg(Consumer, OPT_code_completion_at,
2955 Opts.CodeCompletionAt.ToString());
2956
2957 for (const auto &Plugin : Opts.Plugins)
2958 GenerateArg(Consumer, OPT_load, Plugin);
2959
2960 // ASTDumpDecls and ASTDumpAll already handled with ProgramAction.
2961
2962 for (const auto &ModuleFile : Opts.ModuleFiles)
2963 GenerateArg(Consumer, OPT_fmodule_file, ModuleFile);
2964
2965 if (Opts.AuxTargetCPU)
2966 GenerateArg(Consumer, OPT_aux_target_cpu, *Opts.AuxTargetCPU);
2967
2968 if (Opts.AuxTargetFeatures)
2969 for (const auto &Feature : *Opts.AuxTargetFeatures)
2970 GenerateArg(Consumer, OPT_aux_target_feature, Feature);
2971
2972 {
2973 StringRef Preprocessed = Opts.DashX.isPreprocessed() ? "-cpp-output" : "";
2974 StringRef ModuleMap =
2975 Opts.DashX.getFormat() == InputKind::ModuleMap ? "-module-map" : "";
2976 StringRef HeaderUnit = "";
2977 switch (Opts.DashX.getHeaderUnitKind()) {
2979 break;
2981 HeaderUnit = "-user";
2982 break;
2984 HeaderUnit = "-system";
2985 break;
2987 HeaderUnit = "-header-unit";
2988 break;
2989 }
2990 StringRef Header = IsHeader ? "-header" : "";
2991
2992 StringRef Lang;
2993 switch (Opts.DashX.getLanguage()) {
2994 case Language::C:
2995 Lang = "c";
2996 break;
2997 case Language::OpenCL:
2998 Lang = "cl";
2999 break;
3001 Lang = "clcpp";
3002 break;
3003 case Language::CUDA:
3004 Lang = "cuda";
3005 break;
3006 case Language::HIP:
3007 Lang = "hip";
3008 break;
3009 case Language::CXX:
3010 Lang = "c++";
3011 break;
3012 case Language::ObjC:
3013 Lang = "objective-c";
3014 break;
3015 case Language::ObjCXX:
3016 Lang = "objective-c++";
3017 break;
3018 case Language::Asm:
3019 Lang = "assembler-with-cpp";
3020 break;
3021 case Language::Unknown:
3022 assert(Opts.DashX.getFormat() == InputKind::Precompiled &&
3023 "Generating -x argument for unknown language (not precompiled).");
3024 Lang = "ast";
3025 break;
3026 case Language::LLVM_IR:
3027 Lang = "ir";
3028 break;
3029 case Language::HLSL:
3030 Lang = "hlsl";
3031 break;
3032 case Language::CIR:
3033 Lang = "cir";
3034 break;
3035 }
3036
3037 GenerateArg(Consumer, OPT_x,
3038 Lang + HeaderUnit + Header + ModuleMap + Preprocessed);
3039 }
3040
3041 // OPT_INPUT has a unique class, generate it directly.
3042 for (const auto &Input : Opts.Inputs)
3043 Consumer(Input.getFile());
3044}
3045
3046static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
3047 DiagnosticsEngine &Diags, bool &IsHeaderFile) {
3048 unsigned NumErrorsBefore = Diags.getNumErrors();
3049
3050 FrontendOptions &FrontendOpts = Opts;
3051
3052#define FRONTEND_OPTION_WITH_MARSHALLING(...) \
3053 PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
3054#include "clang/Options/Options.inc"
3055#undef FRONTEND_OPTION_WITH_MARSHALLING
3056
3058 if (const Arg *A = Args.getLastArg(OPT_Action_Group)) {
3059 OptSpecifier Opt = OptSpecifier(A->getOption().getID());
3060 std::optional<frontend::ActionKind> ProgramAction = getFrontendAction(Opt);
3061 assert(ProgramAction && "Option specifier not in Action_Group.");
3062
3063 if (ProgramAction == frontend::ASTDump &&
3064 (Opt == OPT_ast_dump_all_EQ || Opt == OPT_ast_dump_EQ)) {
3065 unsigned Val = llvm::StringSwitch<unsigned>(A->getValue())
3066 .CaseLower("default", ADOF_Default)
3067 .CaseLower("json", ADOF_JSON)
3068 .Default(std::numeric_limits<unsigned>::max());
3069
3070 if (Val != std::numeric_limits<unsigned>::max())
3071 Opts.ASTDumpFormat = static_cast<ASTDumpOutputFormat>(Val);
3072 else {
3073 Diags.Report(diag::err_drv_invalid_value)
3074 << A->getAsString(Args) << A->getValue();
3076 }
3077 }
3078
3079 if (ProgramAction == frontend::FixIt && Opt == OPT_fixit_EQ)
3080 Opts.FixItSuffix = A->getValue();
3081
3082 if (ProgramAction == frontend::GenerateInterfaceStubs) {
3083 StringRef ArgStr =
3084 Args.hasArg(OPT_interface_stub_version_EQ)
3085 ? Args.getLastArgValue(OPT_interface_stub_version_EQ)
3086 : "ifs-v1";
3087 if (ArgStr == "experimental-yaml-elf-v1" ||
3088 ArgStr == "experimental-ifs-v1" || ArgStr == "experimental-ifs-v2" ||
3089 ArgStr == "experimental-tapi-elf-v1") {
3090 std::string ErrorMessage =
3091 "Invalid interface stub format: " + ArgStr.str() +
3092 " is deprecated.";
3093 Diags.Report(diag::err_drv_invalid_value)
3094 << "Must specify a valid interface stub format type, ie: "
3095 "-interface-stub-version=ifs-v1"
3096 << ErrorMessage;
3097 ProgramAction = frontend::ParseSyntaxOnly;
3098 } else if (!ArgStr.starts_with("ifs-")) {
3099 std::string ErrorMessage =
3100 "Invalid interface stub format: " + ArgStr.str() + ".";
3101 Diags.Report(diag::err_drv_invalid_value)
3102 << "Must specify a valid interface stub format type, ie: "
3103 "-interface-stub-version=ifs-v1"
3104 << ErrorMessage;
3105 ProgramAction = frontend::ParseSyntaxOnly;
3106 }
3107 }
3108
3109 Opts.ProgramAction = *ProgramAction;
3110
3111 // Catch common mistakes when multiple actions are specified for cc1 (e.g.
3112 // -S -emit-llvm means -emit-llvm while -emit-llvm -S means -S). However, to
3113 // support driver `-c -Xclang ACTION` (-cc1 -emit-llvm file -main-file-name
3114 // X ACTION), we suppress the error when the two actions are separated by
3115 // -main-file-name.
3116 //
3117 // As an exception, accept composable -ast-dump*.
3118 if (!A->getSpelling().starts_with("-ast-dump")) {
3119 const Arg *SavedAction = nullptr;
3120 for (const Arg *AA :
3121 Args.filtered(OPT_Action_Group, OPT_main_file_name)) {
3122 if (AA->getOption().matches(OPT_main_file_name)) {
3123 SavedAction = nullptr;
3124 } else if (!SavedAction) {
3125 SavedAction = AA;
3126 } else {
3127 if (!A->getOption().matches(OPT_ast_dump_EQ))
3128 Diags.Report(diag::err_fe_invalid_multiple_actions)
3129 << SavedAction->getSpelling() << A->getSpelling();
3130 break;
3131 }
3132 }
3133 }
3134 }
3135
3136 if (const Arg* A = Args.getLastArg(OPT_plugin)) {
3137 Opts.Plugins.emplace_back(A->getValue(0));
3139 Opts.ActionName = A->getValue();
3140 }
3141 for (const auto *AA : Args.filtered(OPT_plugin_arg))
3142 Opts.PluginArgs[AA->getValue(0)].emplace_back(AA->getValue(1));
3143
3144 for (const std::string &Arg :
3145 Args.getAllArgValues(OPT_ftest_module_file_extension_EQ)) {
3146 std::string BlockName;
3147 unsigned MajorVersion;
3148 unsigned MinorVersion;
3149 bool Hashed;
3150 std::string UserInfo;
3151 if (parseTestModuleFileExtensionArg(Arg, BlockName, MajorVersion,
3152 MinorVersion, Hashed, UserInfo)) {
3153 Diags.Report(diag::err_test_module_file_extension_format) << Arg;
3154
3155 continue;
3156 }
3157
3158 // Add the testing module file extension.
3159 Opts.ModuleFileExtensions.push_back(
3160 std::make_shared<TestModuleFileExtension>(
3161 BlockName, MajorVersion, MinorVersion, Hashed, UserInfo));
3162 }
3163
3164 if (const Arg *A = Args.getLastArg(OPT_code_completion_at)) {
3165 Opts.CodeCompletionAt =
3166 ParsedSourceLocation::FromString(A->getValue());
3167 if (Opts.CodeCompletionAt.FileName.empty()) {
3168 Diags.Report(diag::err_drv_invalid_value)
3169 << A->getAsString(Args) << A->getValue();
3170 Diags.Report(diag::note_command_line_code_loc_requirement);
3171 }
3172 }
3173
3174 Opts.Plugins = Args.getAllArgValues(OPT_load);
3175 Opts.ASTDumpDecls = Args.hasArg(OPT_ast_dump, OPT_ast_dump_EQ);
3176 Opts.ASTDumpAll = Args.hasArg(OPT_ast_dump_all, OPT_ast_dump_all_EQ);
3177 // Only the -fmodule-file=<file> form.
3178 for (const auto *A : Args.filtered(OPT_fmodule_file)) {
3179 StringRef Val = A->getValue();
3180 if (!Val.contains('='))
3181 Opts.ModuleFiles.push_back(std::string(Val));
3182 }
3183
3185 Diags.Report(diag::err_drv_argument_only_allowed_with) << "-fsystem-module"
3186 << "-emit-module";
3187 if (Args.hasArg(OPT_emit_cir, OPT_emit_cir_bc))
3188 Opts.UseClangIRPipeline = true;
3189
3190#if CLANG_ENABLE_CIR
3191 if (Args.hasArg(OPT_clangir_disable_passes))
3192 Opts.ClangIRDisablePasses = true;
3193
3194 if (Args.hasArg(OPT_clangir_disable_verifier))
3195 Opts.ClangIRDisableCIRVerifier = true;
3196
3197 if (Args.hasArg(OPT_clangir_lib_opt) || Args.hasArg(OPT_clangir_lib_opt_EQ))
3198 Opts.ClangIRLibOptEnabled = true;
3199#endif // CLANG_ENABLE_CIR
3200
3201 if (Args.hasArg(OPT_aux_target_cpu))
3202 Opts.AuxTargetCPU = std::string(Args.getLastArgValue(OPT_aux_target_cpu));
3203 if (Args.hasArg(OPT_aux_target_feature))
3204 Opts.AuxTargetFeatures = Args.getAllArgValues(OPT_aux_target_feature);
3205
3207 if (const Arg *A = Args.getLastArg(OPT_x)) {
3208 StringRef XValue = A->getValue();
3209
3210 // Parse suffixes:
3211 // '<lang>(-[{header-unit,user,system}-]header|[-module-map][-cpp-output])'.
3212 // FIXME: Supporting '<lang>-header-cpp-output' would be useful.
3213 bool Preprocessed = XValue.consume_back("-cpp-output");
3214 bool ModuleMap = XValue.consume_back("-module-map");
3215 // Detect and consume the header indicator.
3216 bool IsHeader =
3217 XValue != "precompiled-header" && XValue.consume_back("-header");
3218
3219 // If we have c++-{user,system}-header, that indicates a header unit input
3220 // likewise, if the user put -fmodule-header together with a header with an
3221 // absolute path (header-unit-header).
3223 if (IsHeader || Preprocessed) {
3224 if (XValue.consume_back("-header-unit"))
3226 else if (XValue.consume_back("-system"))
3228 else if (XValue.consume_back("-user"))
3230 }
3231
3232 // The value set by this processing is an un-preprocessed source which is
3233 // not intended to be a module map or header unit.
3234 IsHeaderFile = IsHeader && !Preprocessed && !ModuleMap &&
3236
3237 // Principal languages.
3238 DashX = llvm::StringSwitch<InputKind>(XValue)
3239 .Case("c", Language::C)
3240 .Case("cl", Language::OpenCL)
3241 .Case("clcpp", Language::OpenCLCXX)
3242 .Case("cuda", Language::CUDA)
3243 .Case("hip", Language::HIP)
3244 .Case("c++", Language::CXX)
3245 .Case("objective-c", Language::ObjC)
3246 .Case("objective-c++", Language::ObjCXX)
3247 .Case("hlsl", Language::HLSL)
3248 .Default(Language::Unknown);
3249
3250 // "objc[++]-cpp-output" is an acceptable synonym for
3251 // "objective-c[++]-cpp-output".
3252 if (DashX.isUnknown() && Preprocessed && !IsHeaderFile && !ModuleMap &&
3254 DashX = llvm::StringSwitch<InputKind>(XValue)
3255 .Case("objc", Language::ObjC)
3256 .Case("objc++", Language::ObjCXX)
3257 .Default(Language::Unknown);
3258
3259 // Some special cases cannot be combined with suffixes.
3260 if (DashX.isUnknown() && !Preprocessed && !IsHeaderFile && !ModuleMap &&
3262 DashX = llvm::StringSwitch<InputKind>(XValue)
3263 .Case("cpp-output", InputKind(Language::C).getPreprocessed())
3264 .Case("assembler-with-cpp", Language::Asm)
3265 .Cases({"ast", "pcm", "precompiled-header"},
3267 .Case("ir", Language::LLVM_IR)
3268 .Case("cir", Language::CIR)
3269 .Default(Language::Unknown);
3270
3271 if (DashX.isUnknown())
3272 Diags.Report(diag::err_drv_invalid_value)
3273 << A->getAsString(Args) << A->getValue();
3274
3275 if (Preprocessed)
3276 DashX = DashX.getPreprocessed();
3277 // A regular header is considered mutually exclusive with a header unit.
3278 if (HUK != InputKind::HeaderUnit_None) {
3279 DashX = DashX.withHeaderUnit(HUK);
3280 IsHeaderFile = true;
3281 } else if (IsHeaderFile)
3282 DashX = DashX.getHeader();
3283 if (ModuleMap)
3284 DashX = DashX.withFormat(InputKind::ModuleMap);
3285 }
3286
3287 // '-' is the default input if none is given.
3288 std::vector<std::string> Inputs = Args.getAllArgValues(OPT_INPUT);
3289 Opts.Inputs.clear();
3290 if (Inputs.empty())
3291 Inputs.push_back("-");
3292
3294 Inputs.size() > 1)
3295 Diags.Report(diag::err_drv_header_unit_extra_inputs) << Inputs[1];
3296
3297 for (unsigned i = 0, e = Inputs.size(); i != e; ++i) {
3298 InputKind IK = DashX;
3299 if (IK.isUnknown()) {
3301 StringRef(Inputs[i]).rsplit('.').second);
3302 // FIXME: Warn on this?
3303 if (IK.isUnknown())
3304 IK = Language::C;
3305 // FIXME: Remove this hack.
3306 if (i == 0)
3307 DashX = IK;
3308 }
3309
3310 bool IsSystem = false;
3311
3312 // The -emit-module action implicitly takes a module map.
3314 IK.getFormat() == InputKind::Source) {
3316 IsSystem = Opts.IsSystemModule;
3317 }
3318
3319 Opts.Inputs.emplace_back(std::move(Inputs[i]), IK, IsSystem);
3320 }
3321
3322 Opts.DashX = DashX;
3323
3324 // CIR is a source-level frontend pipeline. When the input is already LLVM IR
3325 // (e.g. during the backend phase of OpenMP offloading), the standard LLVM
3326 // backend should be used instead.
3327 if (Opts.UseClangIRPipeline && DashX.getLanguage() == Language::LLVM_IR)
3328 Opts.UseClangIRPipeline = false;
3329
3330 // Conversely, ClangIR input can only be consumed by the CIR pipeline, so it
3331 // implies -fclangir, and is an error if that pipeline is not built in.
3332 if (DashX.getLanguage() == Language::CIR) {
3333#if CLANG_ENABLE_CIR
3334 Opts.UseClangIRPipeline = true;
3335#else
3336 Diags.Report(diag::err_fe_cir_not_built);
3337#endif
3338 }
3339
3340 return Diags.getNumErrors() == NumErrorsBefore;
3341}
3342
3344 ArgumentConsumer Consumer) {
3345 const HeaderSearchOptions *HeaderSearchOpts = &Opts;
3346#define HEADER_SEARCH_OPTION_WITH_MARSHALLING(...) \
3347 GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
3348#include "clang/Options/Options.inc"
3349#undef HEADER_SEARCH_OPTION_WITH_MARSHALLING
3350
3351 if (Opts.UseLibcxx)
3352 GenerateArg(Consumer, OPT_stdlib_EQ, "libc++");
3353
3354 for (const auto &File : Opts.PrebuiltModuleFiles)
3355 GenerateArg(Consumer, OPT_fmodule_file, File.first + "=" + File.second);
3356
3357 for (const auto &Path : Opts.PrebuiltModulePaths)
3358 GenerateArg(Consumer, OPT_fprebuilt_module_path, Path);
3359
3360 for (const auto &Macro : Opts.ModulesIgnoreMacros)
3361 GenerateArg(Consumer, OPT_fmodules_ignore_macro, Macro.val());
3362
3363 for (const auto &Path : Opts.ModulesIgnoreSearchPaths)
3364 GenerateArg(Consumer, OPT_fmodules_ignore_search_path, Path.val());
3365
3366 auto Matches = [](const HeaderSearchOptions::Entry &Entry,
3368 std::optional<bool> IsFramework,
3369 std::optional<bool> IgnoreSysRoot) {
3370 return llvm::is_contained(Groups, Entry.Group) &&
3371 (!IsFramework || (Entry.IsFramework == *IsFramework)) &&
3372 (!IgnoreSysRoot || (Entry.IgnoreSysRoot == *IgnoreSysRoot));
3373 };
3374
3375 auto It = Opts.UserEntries.begin();
3376 auto End = Opts.UserEntries.end();
3377
3378 // Add -I... and -F... options in order.
3379 for (; It < End && Matches(*It, {frontend::Angled}, std::nullopt, true);
3380 ++It) {
3381 OptSpecifier Opt = [It, Matches]() {
3382 if (Matches(*It, frontend::Angled, true, true))
3383 return OPT_F;
3384 if (Matches(*It, frontend::Angled, false, true))
3385 return OPT_I;
3386 llvm_unreachable("Unexpected HeaderSearchOptions::Entry.");
3387 }();
3388
3389 GenerateArg(Consumer, Opt, It->Path);
3390 }
3391
3392 // Note: some paths that came from "[-iprefix=xx] -iwithprefixbefore=yy" may
3393 // have already been generated as "-I[xx]yy". If that's the case, their
3394 // position on command line was such that this has no semantic impact on
3395 // include paths.
3396 for (; It < End &&
3397 Matches(*It, {frontend::After, frontend::Angled}, false, true);
3398 ++It) {
3399 OptSpecifier Opt =
3400 It->Group == frontend::After ? OPT_iwithprefix : OPT_iwithprefixbefore;
3401 GenerateArg(Consumer, Opt, It->Path);
3402 }
3403
3404 // Note: Some paths that came from "-idirafter=xxyy" may have already been
3405 // generated as "-iwithprefix=xxyy". If that's the case, their position on
3406 // command line was such that this has no semantic impact on include paths.
3407 for (; It < End && Matches(*It, {frontend::After}, false, true); ++It)
3408 GenerateArg(Consumer, OPT_idirafter, It->Path);
3409 for (; It < End && Matches(*It, {frontend::Quoted}, false, true); ++It)
3410 GenerateArg(Consumer, OPT_iquote, It->Path);
3411 for (; It < End && Matches(*It, {frontend::System}, false, std::nullopt);
3412 ++It)
3413 GenerateArg(Consumer, It->IgnoreSysRoot ? OPT_isystem : OPT_iwithsysroot,
3414 It->Path);
3415 for (; It < End && Matches(*It, {frontend::System}, true, true); ++It)
3416 GenerateArg(Consumer, OPT_iframework, It->Path);
3417 for (; It < End && Matches(*It, {frontend::System}, true, false); ++It)
3418 GenerateArg(Consumer, OPT_iframeworkwithsysroot, It->Path);
3419
3420 // Add the paths for the various language specific isystem flags.
3421 for (; It < End && Matches(*It, {frontend::CSystem}, false, true); ++It)
3422 GenerateArg(Consumer, OPT_c_isystem, It->Path);
3423 for (; It < End && Matches(*It, {frontend::CXXSystem}, false, true); ++It)
3424 GenerateArg(Consumer, OPT_cxx_isystem, It->Path);
3425 for (; It < End && Matches(*It, {frontend::ObjCSystem}, false, true); ++It)
3426 GenerateArg(Consumer, OPT_objc_isystem, It->Path);
3427 for (; It < End && Matches(*It, {frontend::ObjCXXSystem}, false, true); ++It)
3428 GenerateArg(Consumer, OPT_objcxx_isystem, It->Path);
3429
3430 // Add the internal paths from a driver that detects standard include paths.
3431 // Note: Some paths that came from "-internal-isystem" arguments may have
3432 // already been generated as "-isystem". If that's the case, their position on
3433 // command line was such that this has no semantic impact on include paths.
3434 for (; It < End &&
3435 Matches(*It, {frontend::System, frontend::ExternCSystem}, false, true);
3436 ++It) {
3437 OptSpecifier Opt = It->Group == frontend::System
3438 ? OPT_internal_isystem
3439 : OPT_internal_externc_isystem;
3440 GenerateArg(Consumer, Opt, It->Path);
3441 }
3442 for (; It < End && Matches(*It, {frontend::System}, true, true); ++It)
3443 GenerateArg(Consumer, OPT_internal_iframework, It->Path);
3444
3445 assert(It == End && "Unhandled HeaderSearchOption::Entry.");
3446
3447 // Add the path prefixes which are implicitly treated as being system headers.
3448 for (const auto &P : Opts.SystemHeaderPrefixes) {
3449 OptSpecifier Opt = P.IsSystemHeader ? OPT_system_header_prefix
3450 : OPT_no_system_header_prefix;
3451 GenerateArg(Consumer, Opt, P.Prefix);
3452 }
3453
3454 for (const std::string &F : Opts.VFSOverlayFiles)
3455 GenerateArg(Consumer, OPT_ivfsoverlay, F);
3456}
3457
3458static bool ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args,
3459 DiagnosticsEngine &Diags) {
3460 unsigned NumErrorsBefore = Diags.getNumErrors();
3461
3462 HeaderSearchOptions *HeaderSearchOpts = &Opts;
3463
3464#define HEADER_SEARCH_OPTION_WITH_MARSHALLING(...) \
3465 PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
3466#include "clang/Options/Options.inc"
3467#undef HEADER_SEARCH_OPTION_WITH_MARSHALLING
3468
3469 if (const Arg *A = Args.getLastArg(OPT_stdlib_EQ))
3470 Opts.UseLibcxx = (strcmp(A->getValue(), "libc++") == 0);
3471
3472 // Only the -fmodule-file=<name>=<file> form.
3473 for (const auto *A : Args.filtered(OPT_fmodule_file)) {
3474 StringRef Val = A->getValue();
3475 if (Val.contains('=')) {
3476 auto Split = Val.split('=');
3477 Opts.PrebuiltModuleFiles.insert_or_assign(
3478 std::string(Split.first), std::string(Split.second));
3479 }
3480 }
3481 for (const auto *A : Args.filtered(OPT_fprebuilt_module_path))
3482 Opts.AddPrebuiltModulePath(A->getValue());
3483
3484 for (const auto *A : Args.filtered(OPT_fmodules_ignore_macro)) {
3485 StringRef MacroDef = A->getValue();
3486 Opts.ModulesIgnoreMacros.insert(
3487 llvm::CachedHashString(MacroDef.split('=').first));
3488 }
3489
3490 for (const auto *A : Args.filtered(OPT_fmodules_ignore_search_path))
3491 Opts.ModulesIgnoreSearchPaths.insert(llvm::CachedHashString(A->getValue()));
3492
3493 // Add -I... and -F... options in order.
3494 bool IsSysrootSpecified =
3495 Args.hasArg(OPT__sysroot_EQ) || Args.hasArg(OPT_isysroot);
3496
3497 // Expand a leading `=` to the sysroot if one was passed (and it's not a
3498 // framework flag).
3499 auto PrefixHeaderPath = [IsSysrootSpecified,
3500 &Opts](const llvm::opt::Arg *A,
3501 bool IsFramework = false) -> std::string {
3502 assert(A->getNumValues() && "Unexpected empty search path flag!");
3503 if (IsSysrootSpecified && !IsFramework && A->getValue()[0] == '=') {
3504 SmallString<32> Buffer;
3505 llvm::sys::path::append(Buffer, Opts.Sysroot,
3506 llvm::StringRef(A->getValue()).substr(1));
3507 return std::string(Buffer);
3508 }
3509 return A->getValue();
3510 };
3511
3512 for (const auto *A : Args.filtered(OPT_I, OPT_F)) {
3513 bool IsFramework = A->getOption().matches(OPT_F);
3514 Opts.AddPath(PrefixHeaderPath(A, IsFramework), frontend::Angled,
3515 IsFramework, /*IgnoreSysroot=*/true);
3516 }
3517
3518 // Add -iprefix/-iwithprefix/-iwithprefixbefore options.
3519 StringRef Prefix = ""; // FIXME: This isn't the correct default prefix.
3520 for (const auto *A :
3521 Args.filtered(OPT_iprefix, OPT_iwithprefix, OPT_iwithprefixbefore)) {
3522 if (A->getOption().matches(OPT_iprefix))
3523 Prefix = A->getValue();
3524 else if (A->getOption().matches(OPT_iwithprefix))
3525 Opts.AddPath(Prefix.str() + A->getValue(), frontend::After, false, true);
3526 else
3527 Opts.AddPath(Prefix.str() + A->getValue(), frontend::Angled, false, true);
3528 }
3529
3530 for (const auto *A : Args.filtered(OPT_idirafter))
3531 Opts.AddPath(PrefixHeaderPath(A), frontend::After, false, true);
3532 for (const auto *A : Args.filtered(OPT_iquote))
3533 Opts.AddPath(PrefixHeaderPath(A), frontend::Quoted, false, true);
3534
3535 for (const auto *A : Args.filtered(OPT_isystem, OPT_iwithsysroot)) {
3536 if (A->getOption().matches(OPT_iwithsysroot)) {
3537 Opts.AddPath(A->getValue(), frontend::System, false,
3538 /*IgnoreSysRoot=*/false);
3539 continue;
3540 }
3541 Opts.AddPath(PrefixHeaderPath(A), frontend::System, false, true);
3542 }
3543 for (const auto *A : Args.filtered(OPT_iframework))
3544 Opts.AddPath(A->getValue(), frontend::System, true, true);
3545 for (const auto *A : Args.filtered(OPT_iframeworkwithsysroot))
3546 Opts.AddPath(A->getValue(), frontend::System, /*IsFramework=*/true,
3547 /*IgnoreSysRoot=*/false);
3548
3549 // Add the paths for the various language specific isystem flags.
3550 for (const auto *A : Args.filtered(OPT_c_isystem))
3551 Opts.AddPath(A->getValue(), frontend::CSystem, false, true);
3552 for (const auto *A : Args.filtered(OPT_cxx_isystem))
3553 Opts.AddPath(A->getValue(), frontend::CXXSystem, false, true);
3554 for (const auto *A : Args.filtered(OPT_objc_isystem))
3555 Opts.AddPath(A->getValue(), frontend::ObjCSystem, false,true);
3556 for (const auto *A : Args.filtered(OPT_objcxx_isystem))
3557 Opts.AddPath(A->getValue(), frontend::ObjCXXSystem, false, true);
3558
3559 // Add the internal paths from a driver that detects standard include paths.
3560 for (const auto *A :
3561 Args.filtered(OPT_internal_isystem, OPT_internal_externc_isystem)) {
3563 if (A->getOption().matches(OPT_internal_externc_isystem))
3565 Opts.AddPath(A->getValue(), Group, false, true);
3566 }
3567 for (const auto *A : Args.filtered(OPT_internal_iframework))
3568 Opts.AddPath(A->getValue(), frontend::System, true, true);
3569
3570 // Add the path prefixes which are implicitly treated as being system headers.
3571 for (const auto *A :
3572 Args.filtered(OPT_system_header_prefix, OPT_no_system_header_prefix))
3574 A->getValue(), A->getOption().matches(OPT_system_header_prefix));
3575
3576 for (const auto *A : Args.filtered(OPT_ivfsoverlay, OPT_vfsoverlay))
3577 Opts.AddVFSOverlayFile(A->getValue());
3578
3579 return Diags.getNumErrors() == NumErrorsBefore;
3580}
3581
3583 ArgumentConsumer Consumer) {
3584 if (!Opts.SwiftVersion.empty())
3585 GenerateArg(Consumer, OPT_fapinotes_swift_version,
3586 Opts.SwiftVersion.getAsString());
3587
3588 for (const auto &Path : Opts.ModuleSearchPaths)
3589 GenerateArg(Consumer, OPT_iapinotes_modules, Path);
3590}
3591
3592static void ParseAPINotesArgs(APINotesOptions &Opts, ArgList &Args,
3593 DiagnosticsEngine &diags) {
3594 if (const Arg *A = Args.getLastArg(OPT_fapinotes_swift_version)) {
3595 if (Opts.SwiftVersion.tryParse(A->getValue()))
3596 diags.Report(diag::err_drv_invalid_value)
3597 << A->getAsString(Args) << A->getValue();
3598 }
3599 for (const Arg *A : Args.filtered(OPT_iapinotes_modules))
3600 Opts.ModuleSearchPaths.push_back(A->getValue());
3601}
3602
3603static void GeneratePointerAuthArgs(const LangOptions &Opts,
3604 ArgumentConsumer Consumer) {
3605 if (Opts.PointerAuthIntrinsics)
3606 GenerateArg(Consumer, OPT_fptrauth_intrinsics);
3607 if (Opts.PointerAuthCalls)
3608 GenerateArg(Consumer, OPT_fptrauth_calls);
3609 if (Opts.PointerAuthReturns)
3610 GenerateArg(Consumer, OPT_fptrauth_returns);
3611 if (Opts.PointerAuthIndirectGotos)
3612 GenerateArg(Consumer, OPT_fptrauth_indirect_gotos);
3613 if (Opts.PointerAuthAuthTraps)
3614 GenerateArg(Consumer, OPT_fptrauth_auth_traps);
3615 if (Opts.PointerAuthVTPtrAddressDiscrimination)
3616 GenerateArg(Consumer, OPT_fptrauth_vtable_pointer_address_discrimination);
3617 if (Opts.PointerAuthVTPtrTypeDiscrimination)
3618 GenerateArg(Consumer, OPT_fptrauth_vtable_pointer_type_discrimination);
3619 if (Opts.PointerAuthVTTVTPtrDiscrimination)
3620 GenerateArg(Consumer, OPT_fptrauth_vtt_vtable_pointer_discrimination);
3621 if (Opts.PointerAuthTypeInfoVTPtrDiscrimination)
3622 GenerateArg(Consumer, OPT_fptrauth_type_info_vtable_pointer_discrimination);
3623 if (Opts.PointerAuthFunctionTypeDiscrimination)
3624 GenerateArg(Consumer, OPT_fptrauth_function_pointer_type_discrimination);
3625 if (Opts.PointerAuthInitFini)
3626 GenerateArg(Consumer, OPT_fptrauth_init_fini);
3627 if (Opts.PointerAuthInitFiniAddressDiscrimination)
3628 GenerateArg(Consumer, OPT_fptrauth_init_fini_address_discrimination);
3629 if (Opts.PointerAuthELFGOT)
3630 GenerateArg(Consumer, OPT_fptrauth_elf_got);
3631 if (Opts.AArch64JumpTableHardening)
3632 GenerateArg(Consumer, OPT_faarch64_jump_table_hardening);
3633 if (Opts.PointerAuthObjcIsa)
3634 GenerateArg(Consumer, OPT_fptrauth_objc_isa);
3635 if (Opts.PointerAuthObjcInterfaceSel)
3636 GenerateArg(Consumer, OPT_fptrauth_objc_interface_sel);
3637 if (Opts.PointerAuthObjcClassROPointers)
3638 GenerateArg(Consumer, OPT_fptrauth_objc_class_ro);
3639 if (Opts.PointerAuthBlockDescriptorPointers)
3640 GenerateArg(Consumer, OPT_fptrauth_block_descriptor_pointers);
3641}
3642
3643static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args,
3644 DiagnosticsEngine &Diags) {
3645 Opts.PointerAuthIntrinsics = Args.hasArg(OPT_fptrauth_intrinsics);
3646 Opts.PointerAuthCalls = Args.hasArg(OPT_fptrauth_calls);
3647 Opts.PointerAuthReturns = Args.hasArg(OPT_fptrauth_returns);
3648 Opts.PointerAuthIndirectGotos = Args.hasArg(OPT_fptrauth_indirect_gotos);
3649 Opts.PointerAuthAuthTraps = Args.hasArg(OPT_fptrauth_auth_traps);
3650 Opts.PointerAuthVTPtrAddressDiscrimination =
3651 Args.hasArg(OPT_fptrauth_vtable_pointer_address_discrimination);
3652 Opts.PointerAuthVTPtrTypeDiscrimination =
3653 Args.hasArg(OPT_fptrauth_vtable_pointer_type_discrimination);
3654 Opts.PointerAuthVTTVTPtrDiscrimination =
3655 Args.hasArg(OPT_fptrauth_vtt_vtable_pointer_discrimination);
3656 Opts.PointerAuthTypeInfoVTPtrDiscrimination =
3657 Args.hasArg(OPT_fptrauth_type_info_vtable_pointer_discrimination);
3658 Opts.PointerAuthFunctionTypeDiscrimination =
3659 Args.hasArg(OPT_fptrauth_function_pointer_type_discrimination);
3660 Opts.PointerAuthInitFini = Args.hasArg(OPT_fptrauth_init_fini);
3661 Opts.PointerAuthInitFiniAddressDiscrimination =
3662 Args.hasArg(OPT_fptrauth_init_fini_address_discrimination);
3663 Opts.PointerAuthELFGOT = Args.hasArg(OPT_fptrauth_elf_got);
3664 Opts.AArch64JumpTableHardening =
3665 Args.hasArg(OPT_faarch64_jump_table_hardening);
3666 Opts.PointerAuthBlockDescriptorPointers =
3667 Args.hasArg(OPT_fptrauth_block_descriptor_pointers);
3668 Opts.PointerAuthObjcIsa = Args.hasArg(OPT_fptrauth_objc_isa);
3669 Opts.PointerAuthObjcClassROPointers = Args.hasArg(OPT_fptrauth_objc_class_ro);
3670 Opts.PointerAuthObjcInterfaceSel =
3671 Args.hasArg(OPT_fptrauth_objc_interface_sel);
3672
3673 if (Opts.PointerAuthObjcInterfaceSel)
3674 Opts.PointerAuthObjcInterfaceSelKey =
3675 static_cast<unsigned>(PointerAuthSchema::ARM8_3Key::ASDB);
3676}
3677
3678/// Check if input file kind and language standard are compatible.
3680 const LangStandard &S) {
3681 switch (IK.getLanguage()) {
3682 case Language::Unknown:
3683 case Language::LLVM_IR:
3684 case Language::CIR:
3685 llvm_unreachable("should not parse language flags for this input");
3686
3687 case Language::C:
3688 case Language::ObjC:
3689 return S.getLanguage() == Language::C;
3690
3691 case Language::OpenCL:
3692 return S.getLanguage() == Language::OpenCL ||
3694
3696 return S.getLanguage() == Language::OpenCLCXX;
3697
3698 case Language::CXX:
3699 case Language::ObjCXX:
3700 return S.getLanguage() == Language::CXX;
3701
3702 case Language::CUDA:
3703 // FIXME: What -std= values should be permitted for CUDA compilations?
3704 return S.getLanguage() == Language::CUDA ||
3706
3707 case Language::HIP:
3708 return S.getLanguage() == Language::CXX || S.getLanguage() == Language::HIP;
3709
3710 case Language::Asm:
3711 // Accept (and ignore) all -std= values.
3712 // FIXME: The -std= value is not ignored; it affects the tokenization
3713 // and preprocessing rules if we're preprocessing this asm input.
3714 return true;
3715
3716 case Language::HLSL:
3717 return S.getLanguage() == Language::HLSL;
3718 }
3719
3720 llvm_unreachable("unexpected input language");
3721}
3722
3723/// Get language name for given input kind.
3724static StringRef GetInputKindName(InputKind IK) {
3725 switch (IK.getLanguage()) {
3726 case Language::C:
3727 return "C";
3728 case Language::ObjC:
3729 return "Objective-C";
3730 case Language::CXX:
3731 return "C++";
3732 case Language::ObjCXX:
3733 return "Objective-C++";
3734 case Language::OpenCL:
3735 return "OpenCL";
3737 return "C++ for OpenCL";
3738 case Language::CUDA:
3739 return "CUDA";
3740 case Language::HIP:
3741 return "HIP";
3742
3743 case Language::Asm:
3744 return "Asm";
3745 case Language::LLVM_IR:
3746 return "LLVM IR";
3747 case Language::CIR:
3748 return "Clang IR";
3749
3750 case Language::HLSL:
3751 return "HLSL";
3752
3753 case Language::Unknown:
3754 break;
3755 }
3756 llvm_unreachable("unknown input language");
3757}
3758
3759void CompilerInvocationBase::GenerateLangArgs(const LangOptions &Opts,
3760 ArgumentConsumer Consumer,
3761 const llvm::Triple &T,
3762 InputKind IK) {
3763 if (IK.getFormat() == InputKind::Precompiled ||
3765 IK.getLanguage() == Language::CIR) {
3766 if (Opts.ObjCAutoRefCount)
3767 GenerateArg(Consumer, OPT_fobjc_arc);
3768 if (Opts.PICLevel != 0)
3769 GenerateArg(Consumer, OPT_pic_level, Twine(Opts.PICLevel));
3770 if (Opts.PIE)
3771 GenerateArg(Consumer, OPT_pic_is_pie);
3772 for (StringRef Sanitizer : serializeSanitizerKinds(Opts.Sanitize))
3773 GenerateArg(Consumer, OPT_fsanitize_EQ, Sanitizer);
3774 for (StringRef Sanitizer :
3776 GenerateArg(Consumer, OPT_fsanitize_ignore_for_ubsan_feature_EQ,
3777 Sanitizer);
3778
3779 return;
3780 }
3781
3782 OptSpecifier StdOpt;
3783 switch (Opts.LangStd) {
3784 case LangStandard::lang_opencl10:
3785 case LangStandard::lang_opencl11:
3786 case LangStandard::lang_opencl12:
3787 case LangStandard::lang_opencl20:
3788 case LangStandard::lang_opencl30:
3789 case LangStandard::lang_openclcpp10:
3790 case LangStandard::lang_openclcpp2021:
3791 StdOpt = OPT_cl_std_EQ;
3792 break;
3793 default:
3794 StdOpt = OPT_std_EQ;
3795 break;
3796 }
3797
3798 auto LangStandard = LangStandard::getLangStandardForKind(Opts.LangStd);
3799 GenerateArg(Consumer, StdOpt, LangStandard.getName());
3800
3801 if (Opts.IncludeDefaultHeader)
3802 GenerateArg(Consumer, OPT_finclude_default_header);
3803 if (Opts.DeclareOpenCLBuiltins)
3804 GenerateArg(Consumer, OPT_fdeclare_opencl_builtins);
3805
3806 const LangOptions *LangOpts = &Opts;
3807
3808#define LANG_OPTION_WITH_MARSHALLING(...) \
3809 GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
3810#include "clang/Options/Options.inc"
3811#undef LANG_OPTION_WITH_MARSHALLING
3812
3813 // The '-fcf-protection=' option is generated by CodeGenOpts generator.
3814
3815 if (Opts.ObjC) {
3816 GenerateArg(Consumer, OPT_fobjc_runtime_EQ, Opts.ObjCRuntime.getAsString());
3817
3818 if (Opts.GC == LangOptions::GCOnly)
3819 GenerateArg(Consumer, OPT_fobjc_gc_only);
3820 else if (Opts.GC == LangOptions::HybridGC)
3821 GenerateArg(Consumer, OPT_fobjc_gc);
3822 else if (Opts.ObjCAutoRefCount == 1)
3823 GenerateArg(Consumer, OPT_fobjc_arc);
3824
3825 if (Opts.ObjCWeakRuntime)
3826 GenerateArg(Consumer, OPT_fobjc_runtime_has_weak);
3827
3828 if (Opts.ObjCWeak)
3829 GenerateArg(Consumer, OPT_fobjc_weak);
3830
3831 if (Opts.ObjCSubscriptingLegacyRuntime)
3832 GenerateArg(Consumer, OPT_fobjc_subscripting_legacy_runtime);
3833 }
3834
3835 if (Opts.GNUCVersion != 0) {
3836 unsigned Major = Opts.GNUCVersion / 100 / 100;
3837 unsigned Minor = (Opts.GNUCVersion / 100) % 100;
3838 unsigned Patch = Opts.GNUCVersion % 100;
3839 GenerateArg(Consumer, OPT_fgnuc_version_EQ,
3840 Twine(Major) + "." + Twine(Minor) + "." + Twine(Patch));
3841 }
3842
3843 if (Opts.IgnoreXCOFFVisibility)
3844 GenerateArg(Consumer, OPT_mignore_xcoff_visibility);
3845
3846 if (Opts.SignedOverflowBehavior == LangOptions::SOB_Trapping) {
3847 GenerateArg(Consumer, OPT_ftrapv);
3848 GenerateArg(Consumer, OPT_ftrapv_handler, Opts.OverflowHandler);
3849 } else if (Opts.SignedOverflowBehavior == LangOptions::SOB_Defined) {
3850 if (!Opts.MSVCCompat)
3851 GenerateArg(Consumer, OPT_fwrapv);
3852 } else if (Opts.MSVCCompat) {
3853 GenerateArg(Consumer, OPT_fno_wrapv);
3854 }
3855 if (Opts.PointerOverflowDefined)
3856 GenerateArg(Consumer, OPT_fwrapv_pointer);
3857
3858 if (Opts.MSCompatibilityVersion != 0) {
3859 unsigned Major = Opts.MSCompatibilityVersion / 10000000;
3860 unsigned Minor = (Opts.MSCompatibilityVersion / 100000) % 100;
3861 unsigned Subminor = Opts.MSCompatibilityVersion % 100000;
3862 GenerateArg(Consumer, OPT_fms_compatibility_version,
3863 Twine(Major) + "." + Twine(Minor) + "." + Twine(Subminor));
3864 }
3865
3866 if ((!Opts.GNUMode && !Opts.MSVCCompat && !Opts.CPlusPlus17 && !Opts.C23) ||
3867 T.isOSzOS()) {
3868 if (!Opts.Trigraphs)
3869 GenerateArg(Consumer, OPT_fno_trigraphs);
3870 } else {
3871 if (Opts.Trigraphs)
3872 GenerateArg(Consumer, OPT_ftrigraphs);
3873 }
3874
3875 if (T.isOSzOS() && !Opts.ZOSExt)
3876 GenerateArg(Consumer, OPT_fno_zos_extensions);
3877 else if (Opts.ZOSExt)
3878 GenerateArg(Consumer, OPT_fzos_extensions);
3879
3880 if (Opts.Blocks && !(Opts.OpenCL && Opts.OpenCLVersion == 200))
3881 GenerateArg(Consumer, OPT_fblocks);
3882
3883 if (Opts.ConvergentFunctions)
3884 GenerateArg(Consumer, OPT_fconvergent_functions);
3885 else
3886 GenerateArg(Consumer, OPT_fno_convergent_functions);
3887
3888 if (Opts.NoBuiltin && !Opts.Freestanding)
3889 GenerateArg(Consumer, OPT_fno_builtin);
3890
3891 if (!Opts.NoBuiltin)
3892 for (const auto &Func : Opts.NoBuiltinFuncs)
3893 GenerateArg(Consumer, OPT_fno_builtin_, Func);
3894
3895 if (Opts.LongDoubleSize == 128)
3896 GenerateArg(Consumer, OPT_mlong_double_128);
3897 else if (Opts.LongDoubleSize == 64)
3898 GenerateArg(Consumer, OPT_mlong_double_64);
3899 else if (Opts.LongDoubleSize == 80)
3900 GenerateArg(Consumer, OPT_mlong_double_80);
3901
3902 // Not generating '-mrtd', it's just an alias for '-fdefault-calling-conv='.
3903
3904 // OpenMP was requested via '-fopenmp', not implied by '-fopenmp-simd' or
3905 // '-fopenmp-targets='.
3906 if (Opts.OpenMP && !Opts.OpenMPSimd) {
3907 GenerateArg(Consumer, OPT_fopenmp);
3908
3909 if (Opts.OpenMP != 51)
3910 GenerateArg(Consumer, OPT_fopenmp_version_EQ, Twine(Opts.OpenMP));
3911
3912 if (!Opts.OpenMPUseTLS)
3913 GenerateArg(Consumer, OPT_fnoopenmp_use_tls);
3914
3915 if (Opts.OpenMPIsTargetDevice)
3916 GenerateArg(Consumer, OPT_fopenmp_is_target_device);
3917
3918 if (Opts.OpenMPIRBuilder)
3919 GenerateArg(Consumer, OPT_fopenmp_enable_irbuilder);
3920 }
3921
3922 if (Opts.OpenMPSimd) {
3923 GenerateArg(Consumer, OPT_fopenmp_simd);
3924
3925 if (Opts.OpenMP != 51)
3926 GenerateArg(Consumer, OPT_fopenmp_version_EQ, Twine(Opts.OpenMP));
3927 }
3928
3929 if (Opts.OpenMPThreadSubscription)
3930 GenerateArg(Consumer, OPT_fopenmp_assume_threads_oversubscription);
3931
3932 if (Opts.OpenMPTeamSubscription)
3933 GenerateArg(Consumer, OPT_fopenmp_assume_teams_oversubscription);
3934
3935 if (Opts.OpenMPTargetDebug != 0)
3936 GenerateArg(Consumer, OPT_fopenmp_target_debug_EQ,
3937 Twine(Opts.OpenMPTargetDebug));
3938
3939 if (Opts.OpenMPCUDANumSMs != 0)
3940 GenerateArg(Consumer, OPT_fopenmp_cuda_number_of_sm_EQ,
3941 Twine(Opts.OpenMPCUDANumSMs));
3942
3943 if (Opts.OpenMPCUDABlocksPerSM != 0)
3944 GenerateArg(Consumer, OPT_fopenmp_cuda_blocks_per_sm_EQ,
3945 Twine(Opts.OpenMPCUDABlocksPerSM));
3946
3947 if (!Opts.OMPTargetTriples.empty()) {
3948 std::string Targets;
3949 llvm::raw_string_ostream OS(Targets);
3950 llvm::interleave(
3951 Opts.OMPTargetTriples, OS,
3952 [&OS](const llvm::Triple &T) { OS << T.str(); }, ",");
3953 GenerateArg(Consumer, OPT_offload_targets_EQ, Targets);
3954 }
3955
3956 if (Opts.OpenMPCUDAMode)
3957 GenerateArg(Consumer, OPT_fopenmp_cuda_mode);
3958
3959 if (Opts.OpenACC)
3960 GenerateArg(Consumer, OPT_fopenacc);
3961
3962 // The arguments used to set Optimize, OptimizeSize and NoInlineDefine are
3963 // generated from CodeGenOptions.
3964
3965 if (Opts.DefaultFPContractMode == LangOptions::FPM_Fast)
3966 GenerateArg(Consumer, OPT_ffp_contract, "fast");
3967 else if (Opts.DefaultFPContractMode == LangOptions::FPM_On)
3968 GenerateArg(Consumer, OPT_ffp_contract, "on");
3969 else if (Opts.DefaultFPContractMode == LangOptions::FPM_Off)
3970 GenerateArg(Consumer, OPT_ffp_contract, "off");
3971 else if (Opts.DefaultFPContractMode == LangOptions::FPM_FastHonorPragmas)
3972 GenerateArg(Consumer, OPT_ffp_contract, "fast-honor-pragmas");
3973
3974 for (StringRef Sanitizer : serializeSanitizerKinds(Opts.Sanitize))
3975 GenerateArg(Consumer, OPT_fsanitize_EQ, Sanitizer);
3976 for (StringRef Sanitizer :
3978 GenerateArg(Consumer, OPT_fsanitize_ignore_for_ubsan_feature_EQ, Sanitizer);
3979
3980 // Conflating '-fsanitize-system-ignorelist' and '-fsanitize-ignorelist'.
3981 for (const std::string &F : Opts.NoSanitizeFiles)
3982 GenerateArg(Consumer, OPT_fsanitize_ignorelist_EQ, F);
3983
3984 switch (Opts.getClangABICompat()) {
3985#define ABI_VER_MAJOR_MINOR(Major, Minor) \
3986 case LangOptions::ClangABI::Ver##Major##_##Minor: \
3987 GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, #Major "." #Minor); \
3988 break;
3989#define ABI_VER_MAJOR(Major) \
3990 case LangOptions::ClangABI::Ver##Major: \
3991 GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, #Major ".0"); \
3992 break;
3993#define ABI_VER_LATEST(Latest) \
3994 case LangOptions::ClangABI::Latest: \
3995 break;
3996#include "clang/Basic/ABIVersions.def"
3997 }
3998
3999 if (Opts.getSignReturnAddressScope() ==
4001 GenerateArg(Consumer, OPT_msign_return_address_EQ, "all");
4002 else if (Opts.getSignReturnAddressScope() ==
4004 GenerateArg(Consumer, OPT_msign_return_address_EQ, "non-leaf");
4005
4006 if (Opts.getSignReturnAddressKey() ==
4008 GenerateArg(Consumer, OPT_msign_return_address_key_EQ, "b_key");
4009
4010 if (Opts.CXXABI)
4011 GenerateArg(Consumer, OPT_fcxx_abi_EQ,
4013
4014 if (Opts.RelativeCXXABIVTables)
4015 GenerateArg(Consumer, OPT_fexperimental_relative_cxx_abi_vtables);
4016 else
4017 GenerateArg(Consumer, OPT_fno_experimental_relative_cxx_abi_vtables);
4018
4019 if (Opts.UseTargetPathSeparator)
4020 GenerateArg(Consumer, OPT_ffile_reproducible);
4021 else
4022 GenerateArg(Consumer, OPT_fno_file_reproducible);
4023
4024 for (const auto &MP : Opts.MacroPrefixMap)
4025 GenerateArg(Consumer, OPT_fmacro_prefix_map_EQ, MP.first + "=" + MP.second);
4026
4027 if (!Opts.RandstructSeed.empty())
4028 GenerateArg(Consumer, OPT_frandomize_layout_seed_EQ, Opts.RandstructSeed);
4029
4030 if (Opts.AllocTokenMax)
4031 GenerateArg(Consumer, OPT_falloc_token_max_EQ,
4032 std::to_string(*Opts.AllocTokenMax));
4033
4034 if (Opts.AllocTokenMode) {
4035 StringRef S = llvm::getAllocTokenModeAsString(*Opts.AllocTokenMode);
4036 GenerateArg(Consumer, OPT_falloc_token_mode_EQ, S);
4037 }
4038 // Generate args for matrix types.
4039 if (Opts.MatrixTypes) {
4040 if (Opts.getDefaultMatrixMemoryLayout() ==
4042 GenerateArg(Consumer, OPT_fmatrix_memory_layout_EQ, "column-major");
4043 if (Opts.getDefaultMatrixMemoryLayout() ==
4045 GenerateArg(Consumer, OPT_fmatrix_memory_layout_EQ, "row-major");
4046 }
4047}
4048
4049bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
4050 InputKind IK, const llvm::Triple &T,
4051 std::vector<std::string> &Includes,
4052 DiagnosticsEngine &Diags) {
4053 unsigned NumErrorsBefore = Diags.getNumErrors();
4054
4055 if (IK.getFormat() == InputKind::Precompiled ||
4057 IK.getLanguage() == Language::CIR) {
4058 // ObjCAAutoRefCount and Sanitize LangOpts are used to setup the
4059 // PassManager in BackendUtil.cpp. They need to be initialized no matter
4060 // what the input type is.
4061 if (Args.hasArg(OPT_fobjc_arc))
4062 Opts.ObjCAutoRefCount = 1;
4063 // PICLevel and PIELevel are needed during code generation and this should
4064 // be set regardless of the input type.
4065 Opts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags);
4066 Opts.PIE = Args.hasArg(OPT_pic_is_pie);
4067 parseSanitizerKinds("-fsanitize=", Args.getAllArgValues(OPT_fsanitize_EQ),
4068 Diags, Opts.Sanitize);
4070 "-fsanitize-ignore-for-ubsan-feature=",
4071 Args.getAllArgValues(OPT_fsanitize_ignore_for_ubsan_feature_EQ), Diags,
4073
4074 return Diags.getNumErrors() == NumErrorsBefore;
4075 }
4076
4077 // Other LangOpts are only initialized when the input is not AST or LLVM IR.
4078 // FIXME: Should we really be parsing this for an Language::Asm input?
4079
4080 // FIXME: Cleanup per-file based stuff.
4082 if (const Arg *A = Args.getLastArg(OPT_std_EQ)) {
4083 LangStd = LangStandard::getLangKind(A->getValue());
4084 if (LangStd == LangStandard::lang_unspecified) {
4085 Diags.Report(diag::err_drv_invalid_value)
4086 << A->getAsString(Args) << A->getValue();
4087 // Report supported standards with short description.
4088 for (unsigned KindValue = 0;
4089 KindValue != LangStandard::lang_unspecified;
4090 ++KindValue) {
4091 const LangStandard &Std = LangStandard::getLangStandardForKind(
4092 static_cast<LangStandard::Kind>(KindValue));
4093 if (IsInputCompatibleWithStandard(IK, Std)) {
4094 auto Diag = Diags.Report(diag::note_drv_use_standard);
4095 Diag << Std.getName() << Std.getDescription();
4096 unsigned NumAliases = 0;
4097#define LANGSTANDARD(id, name, lang, desc, features, version)
4098#define LANGSTANDARD_ALIAS(id, alias) \
4099 if (KindValue == LangStandard::lang_##id) ++NumAliases;
4100#define LANGSTANDARD_ALIAS_DEPR(id, alias)
4101#include "clang/Basic/LangStandards.def"
4102 Diag << NumAliases;
4103#define LANGSTANDARD(id, name, lang, desc, features, version)
4104#define LANGSTANDARD_ALIAS(id, alias) \
4105 if (KindValue == LangStandard::lang_##id) Diag << alias;
4106#define LANGSTANDARD_ALIAS_DEPR(id, alias)
4107#include "clang/Basic/LangStandards.def"
4108 }
4109 }
4110 } else {
4111 // Valid standard, check to make sure language and standard are
4112 // compatible.
4113 const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd);
4114 if (!IsInputCompatibleWithStandard(IK, Std)) {
4115 Diags.Report(diag::err_drv_argument_not_allowed_with)
4116 << A->getAsString(Args) << GetInputKindName(IK);
4117 }
4118 }
4119 }
4120
4121 // -cl-std only applies for OpenCL language standards.
4122 // Override the -std option in this case.
4123 if (const Arg *A = Args.getLastArg(OPT_cl_std_EQ)) {
4124 LangStandard::Kind OpenCLLangStd =
4125 llvm::StringSwitch<LangStandard::Kind>(A->getValue())
4126 .Cases({"cl", "CL"}, LangStandard::lang_opencl10)
4127 .Cases({"cl1.0", "CL1.0"}, LangStandard::lang_opencl10)
4128 .Cases({"cl1.1", "CL1.1"}, LangStandard::lang_opencl11)
4129 .Cases({"cl1.2", "CL1.2"}, LangStandard::lang_opencl12)
4130 .Cases({"cl2.0", "CL2.0"}, LangStandard::lang_opencl20)
4131 .Cases({"cl3.0", "CL3.0"}, LangStandard::lang_opencl30)
4132 .Cases({"cl3.1", "CL3.1"}, LangStandard::lang_opencl31)
4133 .Cases({"clc++", "CLC++"}, LangStandard::lang_openclcpp10)
4134 .Cases({"clc++1.0", "CLC++1.0"}, LangStandard::lang_openclcpp10)
4135 .Cases({"clc++2021", "CLC++2021"}, LangStandard::lang_openclcpp2021)
4137
4138 if (OpenCLLangStd == LangStandard::lang_unspecified) {
4139 Diags.Report(diag::err_drv_invalid_value)
4140 << A->getAsString(Args) << A->getValue();
4141 }
4142 else
4143 LangStd = OpenCLLangStd;
4144 }
4145
4146 // These need to be parsed now. They are used to set OpenCL defaults.
4147 Opts.IncludeDefaultHeader = Args.hasArg(OPT_finclude_default_header);
4148 Opts.DeclareOpenCLBuiltins = Args.hasArg(OPT_fdeclare_opencl_builtins);
4149
4150 LangOptions::setLangDefaults(Opts, IK.getLanguage(), T, Includes, LangStd);
4151
4152 // The key paths of codegen options defined in Options.td start with
4153 // "LangOpts->". Let's provide the expected variable name and type.
4154 LangOptions *LangOpts = &Opts;
4155
4156#define LANG_OPTION_WITH_MARSHALLING(...) \
4157 PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
4158#include "clang/Options/Options.inc"
4159#undef LANG_OPTION_WITH_MARSHALLING
4160
4161 // "Modules semantics" (e.g. cross-translation-unit declaration merging) are
4162 // needed for both Clang (header) modules and C++20 modules, so enable them
4163 // for either.
4164 Opts.Modules = Opts.ClangModules || Opts.CPlusPlusModules;
4165
4166 if (const Arg *A = Args.getLastArg(OPT_fcf_protection_EQ)) {
4167 StringRef Name = A->getValue();
4168 if (Name == "full") {
4169 Opts.CFProtectionBranch = 1;
4170 Opts.CFProtectionReturn = 1;
4171 } else if (Name == "branch") {
4172 Opts.CFProtectionBranch = 1;
4173 } else if (Name == "return") {
4174 Opts.CFProtectionReturn = 1;
4175 }
4176 }
4177
4178 if (Opts.CFProtectionBranch) {
4179 if (const Arg *A = Args.getLastArg(OPT_mcf_branch_label_scheme_EQ)) {
4180 const auto Scheme =
4181 llvm::StringSwitch<CFBranchLabelSchemeKind>(A->getValue())
4182#define CF_BRANCH_LABEL_SCHEME(Kind, FlagVal) \
4183 .Case(#FlagVal, CFBranchLabelSchemeKind::Kind)
4184#include "clang/Basic/CFProtectionOptions.def"
4186 Opts.setCFBranchLabelScheme(Scheme);
4187 }
4188 }
4189
4190 if ((Args.hasArg(OPT_fsycl_is_device) || Args.hasArg(OPT_fsycl_is_host)) &&
4191 !Args.hasArg(OPT_sycl_std_EQ)) {
4192 // If the user supplied -fsycl-is-device or -fsycl-is-host, but failed to
4193 // provide -sycl-std=, we want to default it to whatever the default SYCL
4194 // version is. I could not find a way to express this with the options
4195 // tablegen because we still want this value to be SYCL_None when the user
4196 // is not in device or host mode.
4197 Opts.setSYCLVersion(LangOptions::SYCL_Default);
4198 }
4199
4200 if (Opts.ObjC) {
4201 if (Arg *arg = Args.getLastArg(OPT_fobjc_runtime_EQ)) {
4202 StringRef value = arg->getValue();
4203 if (Opts.ObjCRuntime.tryParse(value))
4204 Diags.Report(diag::err_drv_unknown_objc_runtime) << value;
4205 }
4206
4207 if (Args.hasArg(OPT_fobjc_gc_only))
4208 Opts.setGC(LangOptions::GCOnly);
4209 else if (Args.hasArg(OPT_fobjc_gc))
4210 Opts.setGC(LangOptions::HybridGC);
4211 else if (Args.hasArg(OPT_fobjc_arc)) {
4212 Opts.ObjCAutoRefCount = 1;
4213 if (!Opts.ObjCRuntime.allowsARC())
4214 Diags.Report(diag::err_arc_unsupported_on_runtime);
4215 }
4216
4217 // ObjCWeakRuntime tracks whether the runtime supports __weak, not
4218 // whether the feature is actually enabled. This is predominantly
4219 // determined by -fobjc-runtime, but we allow it to be overridden
4220 // from the command line for testing purposes.
4221 if (Args.hasArg(OPT_fobjc_runtime_has_weak))
4222 Opts.ObjCWeakRuntime = 1;
4223 else
4224 Opts.ObjCWeakRuntime = Opts.ObjCRuntime.allowsWeak();
4225
4226 // ObjCWeak determines whether __weak is actually enabled.
4227 // Note that we allow -fno-objc-weak to disable this even in ARC mode.
4228 if (auto weakArg = Args.getLastArg(OPT_fobjc_weak, OPT_fno_objc_weak)) {
4229 if (!weakArg->getOption().matches(OPT_fobjc_weak)) {
4230 assert(!Opts.ObjCWeak);
4231 } else if (Opts.getGC() != LangOptions::NonGC) {
4232 Diags.Report(diag::err_objc_weak_with_gc);
4233 } else if (!Opts.ObjCWeakRuntime) {
4234 Diags.Report(diag::err_objc_weak_unsupported);
4235 } else {
4236 Opts.ObjCWeak = 1;
4237 }
4238 } else if (Opts.ObjCAutoRefCount) {
4239 Opts.ObjCWeak = Opts.ObjCWeakRuntime;
4240 }
4241
4242 if (Args.hasArg(OPT_fobjc_subscripting_legacy_runtime))
4243 Opts.ObjCSubscriptingLegacyRuntime =
4245 }
4246
4247 if (Arg *A = Args.getLastArg(options::OPT_fgnuc_version_EQ)) {
4248 // Check that the version has 1 to 3 components and the minor and patch
4249 // versions fit in two decimal digits.
4250 VersionTuple GNUCVer;
4251 bool Invalid = GNUCVer.tryParse(A->getValue());
4252 unsigned Major = GNUCVer.getMajor();
4253 unsigned Minor = GNUCVer.getMinor().value_or(0);
4254 unsigned Patch = GNUCVer.getSubminor().value_or(0);
4255 if (Invalid || GNUCVer.getBuild() || Minor >= 100 || Patch >= 100) {
4256 Diags.Report(diag::err_drv_invalid_value)
4257 << A->getAsString(Args) << A->getValue();
4258 }
4259 Opts.GNUCVersion = Major * 100 * 100 + Minor * 100 + Patch;
4260 }
4261
4262 if (T.isOSAIX() && (Args.hasArg(OPT_mignore_xcoff_visibility)))
4263 Opts.IgnoreXCOFFVisibility = 1;
4264
4265 if (Args.hasArg(OPT_ftrapv)) {
4266 Opts.setSignedOverflowBehavior(LangOptions::SOB_Trapping);
4267 // Set the handler, if one is specified.
4268 Opts.OverflowHandler =
4269 std::string(Args.getLastArgValue(OPT_ftrapv_handler));
4270 } else if (Args.hasFlag(OPT_fwrapv, OPT_fno_wrapv, Opts.MSVCCompat)) {
4271 Opts.setSignedOverflowBehavior(LangOptions::SOB_Defined);
4272 }
4273 if (Args.hasArg(OPT_fwrapv_pointer))
4274 Opts.PointerOverflowDefined = true;
4275
4276 Opts.MSCompatibilityVersion = 0;
4277 if (const Arg *A = Args.getLastArg(OPT_fms_compatibility_version)) {
4278 VersionTuple VT;
4279 if (VT.tryParse(A->getValue()))
4280 Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args)
4281 << A->getValue();
4282 Opts.MSCompatibilityVersion = VT.getMajor() * 10000000 +
4283 VT.getMinor().value_or(0) * 100000 +
4284 VT.getSubminor().value_or(0);
4285 }
4286
4287 // Mimicking gcc's behavior, trigraphs are only enabled if -trigraphs
4288 // is specified, or -std is set to a conforming mode.
4289 // Trigraphs are disabled by default in C++17 and C23 onwards.
4290 // For z/OS, trigraphs are enabled by default (without regard to the above).
4291 Opts.Trigraphs =
4292 (!Opts.GNUMode && !Opts.MSVCCompat && !Opts.CPlusPlus17 && !Opts.C23) ||
4293 T.isOSzOS();
4294 Opts.Trigraphs =
4295 Args.hasFlag(OPT_ftrigraphs, OPT_fno_trigraphs, Opts.Trigraphs);
4296
4297 Opts.ZOSExt =
4298 Args.hasFlag(OPT_fzos_extensions, OPT_fno_zos_extensions, T.isOSzOS());
4299
4300 Opts.Blocks = Args.hasArg(OPT_fblocks) || (Opts.OpenCL
4301 && Opts.OpenCLVersion == 200);
4302
4303 bool HasConvergentOperations = Opts.isTargetDevice() || Opts.OpenCL ||
4304 Opts.HLSL || T.isAMDGPU() || T.isNVPTX();
4305 Opts.ConvergentFunctions =
4306 Args.hasFlag(OPT_fconvergent_functions, OPT_fno_convergent_functions,
4307 HasConvergentOperations);
4308
4309 Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding;
4310 if (!Opts.NoBuiltin)
4312 if (Arg *A = Args.getLastArg(options::OPT_LongDouble_Group)) {
4313 if (A->getOption().matches(options::OPT_mlong_double_64))
4314 Opts.LongDoubleSize = 64;
4315 else if (A->getOption().matches(options::OPT_mlong_double_80))
4316 Opts.LongDoubleSize = 80;
4317 else if (A->getOption().matches(options::OPT_mlong_double_128))
4318 Opts.LongDoubleSize = 128;
4319 else
4320 Opts.LongDoubleSize = 0;
4321 }
4322 if (Opts.FastRelaxedMath || Opts.CLUnsafeMath)
4323 Opts.setDefaultFPContractMode(LangOptions::FPM_Fast);
4324
4325 llvm::sort(Opts.ModuleFeatures);
4326
4327 // -mrtd option
4328 if (Arg *A = Args.getLastArg(OPT_mrtd)) {
4329 if (Opts.getDefaultCallingConv() != LangOptions::DCC_None)
4330 Diags.Report(diag::err_drv_argument_not_allowed_with)
4331 << A->getSpelling() << "-fdefault-calling-conv";
4332 else {
4333 switch (T.getArch()) {
4334 case llvm::Triple::x86:
4335 Opts.setDefaultCallingConv(LangOptions::DCC_StdCall);
4336 break;
4337 case llvm::Triple::m68k:
4338 Opts.setDefaultCallingConv(LangOptions::DCC_RtdCall);
4339 break;
4340 default:
4341 Diags.Report(diag::err_drv_argument_not_allowed_with)
4342 << A->getSpelling() << T.getTriple();
4343 }
4344 }
4345 }
4346
4347 // Check if -fopenmp is specified and set default version to 5.1.
4348 Opts.OpenMP = Args.hasArg(OPT_fopenmp) ? 51 : 0;
4349 // Check if -fopenmp-simd is specified.
4350 bool IsSimdSpecified =
4351 Args.hasFlag(options::OPT_fopenmp_simd, options::OPT_fno_openmp_simd,
4352 /*Default=*/false);
4353 Opts.OpenMPSimd = !Opts.OpenMP && IsSimdSpecified;
4354 Opts.OpenMPUseTLS =
4355 Opts.OpenMP && !Args.hasArg(options::OPT_fnoopenmp_use_tls);
4356 Opts.OpenMPIsTargetDevice =
4357 Opts.OpenMP && Args.hasArg(options::OPT_fopenmp_is_target_device);
4358 Opts.OpenMPIRBuilder =
4359 Opts.OpenMP && Args.hasArg(options::OPT_fopenmp_enable_irbuilder);
4360 bool IsTargetSpecified =
4361 Opts.OpenMPIsTargetDevice || Args.hasArg(options::OPT_offload_targets_EQ);
4362
4363 if (Opts.OpenMP || Opts.OpenMPSimd) {
4364 if (int Version = getLastArgIntValue(
4365 Args, OPT_fopenmp_version_EQ,
4366 (IsSimdSpecified || IsTargetSpecified) ? 51 : Opts.OpenMP, Diags))
4367 Opts.OpenMP = Version;
4368 // Provide diagnostic when a given target is not expected to be an OpenMP
4369 // device or host.
4370 if (!Opts.OpenMPIsTargetDevice) {
4371 switch (T.getArch()) {
4372 default:
4373 break;
4374 // Add unsupported host targets here:
4375 case llvm::Triple::nvptx:
4376 case llvm::Triple::nvptx64:
4377 Diags.Report(diag::err_drv_omp_host_target_not_supported) << T.str();
4378 break;
4379 }
4380 }
4381 }
4382
4383 // Set the flag to prevent the implementation from emitting device exception
4384 // handling code for those requiring so.
4385 if ((Opts.OpenMPIsTargetDevice && T.isGPU()) || Opts.OpenCLCPlusPlus) {
4386
4387 Opts.Exceptions = 0;
4388 Opts.CXXExceptions = 0;
4389 }
4390 if (Opts.OpenMPIsTargetDevice && T.isNVPTX()) {
4391 Opts.OpenMPCUDANumSMs =
4392 getLastArgIntValue(Args, options::OPT_fopenmp_cuda_number_of_sm_EQ,
4393 Opts.OpenMPCUDANumSMs, Diags);
4394 Opts.OpenMPCUDABlocksPerSM =
4395 getLastArgIntValue(Args, options::OPT_fopenmp_cuda_blocks_per_sm_EQ,
4396 Opts.OpenMPCUDABlocksPerSM, Diags);
4397 }
4398
4399 // Set the value of the debugging flag used in the new offloading device RTL.
4400 // Set either by a specific value or to a default if not specified.
4401 if (Opts.OpenMPIsTargetDevice && (Args.hasArg(OPT_fopenmp_target_debug) ||
4402 Args.hasArg(OPT_fopenmp_target_debug_EQ))) {
4403 Opts.OpenMPTargetDebug = getLastArgIntValue(
4404 Args, OPT_fopenmp_target_debug_EQ, Opts.OpenMPTargetDebug, Diags);
4405 if (!Opts.OpenMPTargetDebug && Args.hasArg(OPT_fopenmp_target_debug))
4406 Opts.OpenMPTargetDebug = 1;
4407 }
4408
4409 if (Opts.OpenMPIsTargetDevice) {
4410 if (Args.hasArg(OPT_fopenmp_assume_teams_oversubscription))
4411 Opts.OpenMPTeamSubscription = true;
4412 if (Args.hasArg(OPT_fopenmp_assume_threads_oversubscription))
4413 Opts.OpenMPThreadSubscription = true;
4414 }
4415
4416 // Get the OpenMP target triples if any.
4417 if (Arg *A = Args.getLastArg(options::OPT_offload_targets_EQ)) {
4418 enum ArchPtrSize { Arch16Bit, Arch32Bit, Arch64Bit };
4419 auto getArchPtrSize = [](const llvm::Triple &T) {
4420 if (T.isArch16Bit())
4421 return Arch16Bit;
4422 if (T.isArch32Bit())
4423 return Arch32Bit;
4424 assert(T.isArch64Bit() && "Expected 64-bit architecture");
4425 return Arch64Bit;
4426 };
4427
4428 for (unsigned i = 0; i < A->getNumValues(); ++i) {
4429 llvm::Triple TT(A->getValue(i));
4430
4431 if (TT.getArch() == llvm::Triple::UnknownArch ||
4432 !(TT.getArch() == llvm::Triple::aarch64 || TT.isPPC() ||
4433 TT.getArch() == llvm::Triple::spirv64 ||
4434 TT.getArch() == llvm::Triple::systemz ||
4435 TT.getArch() == llvm::Triple::loongarch64 ||
4436 TT.getArch() == llvm::Triple::nvptx ||
4437 TT.getArch() == llvm::Triple::nvptx64 || TT.isAMDGCN() ||
4438 TT.getArch() == llvm::Triple::x86 ||
4439 TT.getArch() == llvm::Triple::x86_64))
4440 Diags.Report(diag::err_drv_invalid_omp_target) << A->getValue(i);
4441 else if (getArchPtrSize(T) != getArchPtrSize(TT))
4442 Diags.Report(diag::err_drv_incompatible_omp_arch)
4443 << A->getValue(i) << T.str();
4444 else
4445 Opts.OMPTargetTriples.push_back(TT);
4446 }
4447 }
4448
4449 // Set CUDA mode for OpenMP target NVPTX/AMDGCN if specified in options
4450 Opts.OpenMPCUDAMode = Opts.OpenMPIsTargetDevice &&
4451 (T.isNVPTX() || T.isAMDGCN()) &&
4452 Args.hasArg(options::OPT_fopenmp_cuda_mode);
4453
4454 // OpenACC Configuration.
4455 if (Args.hasArg(options::OPT_fopenacc))
4456 Opts.OpenACC = true;
4457
4458 if (Arg *A = Args.getLastArg(OPT_ffp_contract)) {
4459 StringRef Val = A->getValue();
4460 if (Val == "fast")
4461 Opts.setDefaultFPContractMode(LangOptions::FPM_Fast);
4462 else if (Val == "on")
4463 Opts.setDefaultFPContractMode(LangOptions::FPM_On);
4464 else if (Val == "off")
4465 Opts.setDefaultFPContractMode(LangOptions::FPM_Off);
4466 else if (Val == "fast-honor-pragmas")
4467 Opts.setDefaultFPContractMode(LangOptions::FPM_FastHonorPragmas);
4468 else
4469 Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;
4470 }
4471
4472 if (auto *A =
4473 Args.getLastArg(OPT_fsanitize_undefined_ignore_overflow_pattern_EQ)) {
4474 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
4476 llvm::StringSwitch<unsigned>(A->getValue(i))
4477 .Case("none", LangOptionsBase::None)
4478 .Case("all", LangOptionsBase::All)
4479 .Case("add-unsigned-overflow-test",
4481 .Case("add-signed-overflow-test",
4483 .Case("negated-unsigned-const", LangOptionsBase::NegUnsignedConst)
4484 .Case("unsigned-post-decr-while",
4486 .Default(0);
4487 }
4488 }
4489
4490 // Parse -fsanitize= arguments.
4491 parseSanitizerKinds("-fsanitize=", Args.getAllArgValues(OPT_fsanitize_EQ),
4492 Diags, Opts.Sanitize);
4494 "-fsanitize-ignore-for-ubsan-feature=",
4495 Args.getAllArgValues(OPT_fsanitize_ignore_for_ubsan_feature_EQ), Diags,
4497 Opts.NoSanitizeFiles = Args.getAllArgValues(OPT_fsanitize_ignorelist_EQ);
4498 std::vector<std::string> systemIgnorelists =
4499 Args.getAllArgValues(OPT_fsanitize_system_ignorelist_EQ);
4500 Opts.NoSanitizeFiles.insert(Opts.NoSanitizeFiles.end(),
4501 systemIgnorelists.begin(),
4502 systemIgnorelists.end());
4503
4504 if (Arg *A = Args.getLastArg(OPT_fclang_abi_compat_EQ)) {
4505 Opts.setClangABICompat(LangOptions::ClangABI::Latest);
4506
4507 StringRef Ver = A->getValue();
4508 std::pair<StringRef, StringRef> VerParts = Ver.split('.');
4509 int Major, Minor = 0;
4510
4511 // Check the version number is valid: either 3.x (0 <= x <= 9) or
4512 // y or y.0 (4 <= y <= current version).
4513 if (!VerParts.first.starts_with("0") &&
4514 !VerParts.first.getAsInteger(10, Major) && 3 <= Major &&
4515 Major <= MAX_CLANG_ABI_COMPAT_VERSION &&
4516 (Major == 3
4517 ? VerParts.second.size() == 1 &&
4518 !VerParts.second.getAsInteger(10, Minor)
4519 : VerParts.first.size() == Ver.size() || VerParts.second == "0")) {
4520 // Got a valid version number.
4521#define ABI_VER_MAJOR_MINOR(Major_, Minor_) \
4522 if (std::tuple(Major, Minor) <= std::tuple(Major_, Minor_)) \
4523 Opts.setClangABICompat(LangOptions::ClangABI::Ver##Major_##_##Minor_); \
4524 else
4525#define ABI_VER_MAJOR(Major_) \
4526 if (Major <= Major_) \
4527 Opts.setClangABICompat(LangOptions::ClangABI::Ver##Major_); \
4528 else
4529#define ABI_VER_LATEST(Latest) \
4530 { /* Equivalent to latest version - do nothing */ \
4531 }
4532#include "clang/Basic/ABIVersions.def"
4533 } else if (Ver != "latest") {
4534 Diags.Report(diag::err_drv_invalid_value)
4535 << A->getAsString(Args) << A->getValue();
4536 }
4537 }
4538
4539 if (Arg *A = Args.getLastArg(OPT_msign_return_address_EQ)) {
4540 StringRef SignScope = A->getValue();
4541
4542 if (SignScope.equals_insensitive("none"))
4543 Opts.setSignReturnAddressScope(
4545 else if (SignScope.equals_insensitive("all"))
4546 Opts.setSignReturnAddressScope(
4548 else if (SignScope.equals_insensitive("non-leaf"))
4549 Opts.setSignReturnAddressScope(
4551 else
4552 Diags.Report(diag::err_drv_invalid_value)
4553 << A->getAsString(Args) << SignScope;
4554
4555 if (Arg *A = Args.getLastArg(OPT_msign_return_address_key_EQ)) {
4556 StringRef SignKey = A->getValue();
4557 if (!SignScope.empty() && !SignKey.empty()) {
4558 if (SignKey == "a_key")
4559 Opts.setSignReturnAddressKey(
4561 else if (SignKey == "b_key")
4562 Opts.setSignReturnAddressKey(
4564 else
4565 Diags.Report(diag::err_drv_invalid_value)
4566 << A->getAsString(Args) << SignKey;
4567 }
4568 }
4569 }
4570
4571 // The value can be empty, which indicates the system default should be used.
4572 StringRef CXXABI = Args.getLastArgValue(OPT_fcxx_abi_EQ);
4573 if (!CXXABI.empty()) {
4575 Diags.Report(diag::err_invalid_cxx_abi) << CXXABI;
4576 } else {
4579 Diags.Report(diag::err_unsupported_cxx_abi) << CXXABI << T.str();
4580 else
4581 Opts.CXXABI = Kind;
4582 }
4583 }
4584
4585 Opts.RelativeCXXABIVTables =
4586 Args.hasFlag(options::OPT_fexperimental_relative_cxx_abi_vtables,
4587 options::OPT_fno_experimental_relative_cxx_abi_vtables,
4589
4590 // RTTI is on by default.
4591 bool HasRTTI = !Args.hasArg(options::OPT_fno_rtti);
4592 Opts.OmitVTableRTTI =
4593 Args.hasFlag(options::OPT_fexperimental_omit_vtable_rtti,
4594 options::OPT_fno_experimental_omit_vtable_rtti, false);
4595 if (Opts.OmitVTableRTTI && HasRTTI)
4596 Diags.Report(diag::err_drv_using_omit_rtti_component_without_no_rtti);
4597
4598 for (const auto &A : Args.getAllArgValues(OPT_fmacro_prefix_map_EQ)) {
4599 auto Split = StringRef(A).split('=');
4600 Opts.MacroPrefixMap.insert(
4601 {std::string(Split.first), std::string(Split.second)});
4602 }
4603
4605 !Args.getLastArg(OPT_fno_file_reproducible) &&
4606 (Args.getLastArg(OPT_ffile_compilation_dir_EQ) ||
4607 Args.getLastArg(OPT_fmacro_prefix_map_EQ) ||
4608 Args.getLastArg(OPT_ffile_reproducible));
4609
4610 // Error if -mvscale-min is unbounded.
4611 if (Arg *A = Args.getLastArg(options::OPT_mvscale_min_EQ)) {
4612 unsigned VScaleMin;
4613 if (StringRef(A->getValue()).getAsInteger(10, VScaleMin) || VScaleMin == 0)
4614 Diags.Report(diag::err_cc1_unbounded_vscale_min);
4615 }
4616 if (Arg *A = Args.getLastArg(options::OPT_mvscale_streaming_min_EQ)) {
4617 unsigned VScaleMin;
4618 if (StringRef(A->getValue()).getAsInteger(10, VScaleMin) || VScaleMin == 0)
4619 Diags.Report(diag::err_cc1_unbounded_vscale_min);
4620 }
4621
4622 if (const Arg *A = Args.getLastArg(OPT_frandomize_layout_seed_file_EQ)) {
4623 std::ifstream SeedFile(A->getValue(0));
4624
4625 if (!SeedFile.is_open())
4626 Diags.Report(diag::err_drv_cannot_open_randomize_layout_seed_file)
4627 << A->getValue(0);
4628
4629 std::getline(SeedFile, Opts.RandstructSeed);
4630 }
4631
4632 if (const Arg *A = Args.getLastArg(OPT_frandomize_layout_seed_EQ))
4633 Opts.RandstructSeed = A->getValue(0);
4634
4635 if (const auto *Arg = Args.getLastArg(options::OPT_falloc_token_max_EQ)) {
4636 StringRef S = Arg->getValue();
4637 uint64_t Value = 0;
4638 if (S.getAsInteger(0, Value))
4639 Diags.Report(diag::err_drv_invalid_value) << Arg->getAsString(Args) << S;
4640 else
4641 Opts.AllocTokenMax = Value;
4642 }
4643
4644 if (const auto *Arg = Args.getLastArg(options::OPT_falloc_token_mode_EQ)) {
4645 StringRef S = Arg->getValue();
4646 if (auto Mode = getAllocTokenModeFromString(S))
4647 Opts.AllocTokenMode = Mode;
4648 else
4649 Diags.Report(diag::err_drv_invalid_value) << Arg->getAsString(Args) << S;
4650 }
4651
4652 // Enable options for matrix types.
4653 if (Opts.MatrixTypes) {
4654 if (const Arg *A = Args.getLastArg(OPT_fmatrix_memory_layout_EQ)) {
4655 StringRef ClangValue = A->getValue();
4656 if (ClangValue == "row-major")
4657 Opts.setDefaultMatrixMemoryLayout(
4659 else
4660 Opts.setDefaultMatrixMemoryLayout(
4662
4663 for (Arg *A : Args.filtered(options::OPT_mllvm)) {
4664 StringRef OptValue = A->getValue();
4665 if (OptValue.consume_front("-matrix-default-layout=") &&
4666 ClangValue != OptValue)
4667 Diags.Report(diag::err_conflicting_matrix_layout_flags)
4668 << ClangValue << OptValue;
4669 }
4670 }
4671 }
4672
4673 // Validate options for HLSL
4674 if (Opts.HLSL) {
4675 // TODO: Revisit restricting SPIR-V to logical once we've figured out how to
4676 // handle PhysicalStorageBuffer64 memory model
4677 if (T.isDXIL() || T.isSPIRVLogical()) {
4678 enum { ShaderModel, VulkanEnv, ShaderStage };
4679 enum { OS, Environment };
4680
4681 int ExpectedOS = T.isSPIRVLogical() ? VulkanEnv : ShaderModel;
4682
4683 if (T.getOSName().empty()) {
4684 Diags.Report(diag::err_drv_hlsl_bad_shader_required_in_target)
4685 << ExpectedOS << OS << T.str();
4686 } else if (T.getEnvironmentName().empty()) {
4687 Diags.Report(diag::err_drv_hlsl_bad_shader_required_in_target)
4688 << ShaderStage << Environment << T.str();
4689 } else if (!T.isShaderStageEnvironment()) {
4690 Diags.Report(diag::err_drv_hlsl_bad_shader_unsupported)
4691 << ShaderStage << T.getEnvironmentName() << T.str();
4692 }
4693
4694 if (T.isDXIL()) {
4695 if (!T.isShaderModelOS() || T.getOSVersion() == VersionTuple(0)) {
4696 Diags.Report(diag::err_drv_hlsl_bad_shader_unsupported)
4697 << ShaderModel << T.getOSName() << T.str();
4698 }
4699 // Validate that if fnative-half-type is given, that
4700 // the language standard is at least hlsl2018, and that
4701 // the target shader model is at least 6.2.
4702 if (Args.getLastArg(OPT_fnative_half_type) ||
4703 Args.getLastArg(OPT_fnative_int16_type)) {
4704 const LangStandard &Std =
4706 if (!(Opts.LangStd >= LangStandard::lang_hlsl2018 &&
4707 T.getOSVersion() >= VersionTuple(6, 2)))
4708 Diags.Report(diag::err_drv_hlsl_16bit_types_unsupported)
4709 << "-enable-16bit-types" << true << Std.getName()
4710 << T.getOSVersion().getAsString();
4711 }
4712 } else if (T.isSPIRVLogical()) {
4713 if (!T.isVulkanOS() || T.getVulkanVersion() == VersionTuple(0)) {
4714 Diags.Report(diag::err_drv_hlsl_bad_shader_unsupported)
4715 << VulkanEnv << T.getOSName() << T.str();
4716 }
4717 if (Args.getLastArg(OPT_fnative_half_type) ||
4718 Args.getLastArg(OPT_fnative_int16_type)) {
4719 const char *Str = Args.getLastArg(OPT_fnative_half_type)
4720 ? "-fnative-half-type"
4721 : "-fnative-int16-type";
4722 const LangStandard &Std =
4724 if (!(Opts.LangStd >= LangStandard::lang_hlsl2018))
4725 Diags.Report(diag::err_drv_hlsl_16bit_types_unsupported)
4726 << Str << false << Std.getName();
4727 }
4728 } else {
4729 llvm_unreachable("expected DXIL or SPIR-V target");
4730 }
4731 } else
4732 Diags.Report(diag::err_drv_hlsl_unsupported_target) << T.str();
4733
4734 if (Opts.LangStd < LangStandard::lang_hlsl202x) {
4735 const LangStandard &Requested =
4737 const LangStandard &Recommended =
4738 LangStandard::getLangStandardForKind(LangStandard::lang_hlsl202x);
4739 Diags.Report(diag::warn_hlsl_langstd_minimal)
4740 << Requested.getName() << Recommended.getName();
4741 }
4742 }
4743
4744 return Diags.getNumErrors() == NumErrorsBefore;
4745}
4746
4748 switch (Action) {
4750 case frontend::ASTDump:
4751 case frontend::ASTPrint:
4752 case frontend::ASTView:
4754 case frontend::EmitBC:
4755 case frontend::EmitCIR:
4757 case frontend::EmitHTML:
4758 case frontend::EmitLLVM:
4761 case frontend::EmitObj:
4763 case frontend::FixIt:
4777 return false;
4778
4782 case frontend::InitOnly:
4788 return true;
4789 }
4790 llvm_unreachable("invalid frontend action");
4791}
4792
4837
4839 ArgumentConsumer Consumer,
4840 const LangOptions &LangOpts,
4841 const FrontendOptions &FrontendOpts,
4842 const CodeGenOptions &CodeGenOpts) {
4843 const PreprocessorOptions *PreprocessorOpts = &Opts;
4844
4845#define PREPROCESSOR_OPTION_WITH_MARSHALLING(...) \
4846 GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
4847#include "clang/Options/Options.inc"
4848#undef PREPROCESSOR_OPTION_WITH_MARSHALLING
4849
4850 if (Opts.PCHWithHdrStop && !Opts.PCHWithHdrStopCreate)
4851 GenerateArg(Consumer, OPT_pch_through_hdrstop_use);
4852
4853 for (const auto &D : Opts.DeserializedPCHDeclsToErrorOn)
4854 GenerateArg(Consumer, OPT_error_on_deserialized_pch_decl, D);
4855
4856 if (Opts.PrecompiledPreambleBytes != std::make_pair(0u, false))
4857 GenerateArg(Consumer, OPT_preamble_bytes_EQ,
4858 Twine(Opts.PrecompiledPreambleBytes.first) + "," +
4859 (Opts.PrecompiledPreambleBytes.second ? "1" : "0"));
4860
4861 for (const auto &M : Opts.Macros) {
4862 // Don't generate __CET__ macro definitions. They are implied by the
4863 // -fcf-protection option that is generated elsewhere.
4864 if (M.first == "__CET__=1" && !M.second &&
4865 !CodeGenOpts.CFProtectionReturn && CodeGenOpts.CFProtectionBranch)
4866 continue;
4867 if (M.first == "__CET__=2" && !M.second && CodeGenOpts.CFProtectionReturn &&
4868 !CodeGenOpts.CFProtectionBranch)
4869 continue;
4870 if (M.first == "__CET__=3" && !M.second && CodeGenOpts.CFProtectionReturn &&
4871 CodeGenOpts.CFProtectionBranch)
4872 continue;
4873
4874 GenerateArg(Consumer, M.second ? OPT_U : OPT_D, M.first);
4875 }
4876
4877 for (const auto &I : Opts.Includes) {
4878 // Don't generate OpenCL includes. They are implied by other flags that are
4879 // generated elsewhere.
4880 if (LangOpts.OpenCL && LangOpts.IncludeDefaultHeader &&
4881 ((LangOpts.DeclareOpenCLBuiltins && I == "opencl-c-base.h") ||
4882 I == "opencl-c.h"))
4883 continue;
4884 // Don't generate HLSL includes. They are implied by other flags that are
4885 // generated elsewhere.
4886 if (LangOpts.HLSL && I == "hlsl.h")
4887 continue;
4888
4889 GenerateArg(Consumer, OPT_include, I);
4890 }
4891
4892 for (const auto &CI : Opts.ChainedIncludes)
4893 GenerateArg(Consumer, OPT_chain_include, CI);
4894
4895 for (const auto &RF : Opts.RemappedFiles)
4896 GenerateArg(Consumer, OPT_remap_file, RF.first + ";" + RF.second);
4897
4898 if (Opts.SourceDateEpoch)
4899 GenerateArg(Consumer, OPT_source_date_epoch, Twine(*Opts.SourceDateEpoch));
4900
4901 if (Opts.DefineTargetOSMacros)
4902 GenerateArg(Consumer, OPT_fdefine_target_os_macros);
4903
4904 for (const auto &EmbedEntry : Opts.EmbedEntries)
4905 GenerateArg(Consumer, OPT_embed_dir_EQ, EmbedEntry);
4906
4907 // Don't handle LexEditorPlaceholders. It is implied by the action that is
4908 // generated elsewhere.
4909}
4910
4911static bool ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
4912 DiagnosticsEngine &Diags,
4913 frontend::ActionKind Action,
4914 const FrontendOptions &FrontendOpts) {
4915 unsigned NumErrorsBefore = Diags.getNumErrors();
4916
4917 PreprocessorOptions *PreprocessorOpts = &Opts;
4918
4919#define PREPROCESSOR_OPTION_WITH_MARSHALLING(...) \
4920 PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
4921#include "clang/Options/Options.inc"
4922#undef PREPROCESSOR_OPTION_WITH_MARSHALLING
4923
4924 Opts.PCHWithHdrStop = Args.hasArg(OPT_pch_through_hdrstop_create) ||
4925 Args.hasArg(OPT_pch_through_hdrstop_use);
4926
4927 for (const auto *A : Args.filtered(OPT_error_on_deserialized_pch_decl))
4928 Opts.DeserializedPCHDeclsToErrorOn.insert(A->getValue());
4929
4930 if (const Arg *A = Args.getLastArg(OPT_preamble_bytes_EQ)) {
4931 StringRef Value(A->getValue());
4932 size_t Comma = Value.find(',');
4933 unsigned Bytes = 0;
4934 unsigned EndOfLine = 0;
4935
4936 if (Comma == StringRef::npos ||
4937 Value.substr(0, Comma).getAsInteger(10, Bytes) ||
4938 Value.substr(Comma + 1).getAsInteger(10, EndOfLine))
4939 Diags.Report(diag::err_drv_preamble_format);
4940 else {
4941 Opts.PrecompiledPreambleBytes.first = Bytes;
4942 Opts.PrecompiledPreambleBytes.second = (EndOfLine != 0);
4943 }
4944 }
4945
4946 // Add macros from the command line.
4947 for (const auto *A : Args.filtered(OPT_D, OPT_U)) {
4948 if (A->getOption().matches(OPT_D))
4949 Opts.addMacroDef(A->getValue());
4950 else
4951 Opts.addMacroUndef(A->getValue());
4952 }
4953
4954 // Add the ordered list of -includes.
4955 for (const auto *A : Args.filtered(OPT_include))
4956 Opts.Includes.emplace_back(A->getValue());
4957
4958 for (const auto *A : Args.filtered(OPT_chain_include))
4959 Opts.ChainedIncludes.emplace_back(A->getValue());
4960
4961 for (const auto *A : Args.filtered(OPT_remap_file)) {
4962 std::pair<StringRef, StringRef> Split = StringRef(A->getValue()).split(';');
4963
4964 if (Split.second.empty()) {
4965 Diags.Report(diag::err_drv_invalid_remap_file) << A->getAsString(Args);
4966 continue;
4967 }
4968
4969 Opts.addRemappedFile(Split.first, Split.second);
4970 }
4971
4972 if (const Arg *A = Args.getLastArg(OPT_source_date_epoch)) {
4973 StringRef Epoch = A->getValue();
4974 // SOURCE_DATE_EPOCH, if specified, must be a non-negative decimal integer.
4975 // On time64 systems, pick 253402300799 (the UNIX timestamp of
4976 // 9999-12-31T23:59:59Z) as the upper bound.
4977 const uint64_t MaxTimestamp =
4978 std::min<uint64_t>(std::numeric_limits<time_t>::max(), 253402300799);
4979 uint64_t V;
4980 if (Epoch.getAsInteger(10, V) || V > MaxTimestamp) {
4981 Diags.Report(diag::err_fe_invalid_source_date_epoch)
4982 << Epoch << MaxTimestamp;
4983 } else {
4984 Opts.SourceDateEpoch = V;
4985 }
4986 }
4987
4988 for (const auto *A : Args.filtered(OPT_embed_dir_EQ)) {
4989 StringRef Val = A->getValue();
4990 Opts.EmbedEntries.push_back(std::string(Val));
4991 }
4992
4993 // Always avoid lexing editor placeholders when we're just running the
4994 // preprocessor as we never want to emit the
4995 // "editor placeholder in source file" error in PP only mode.
4996 if (isStrictlyPreprocessorAction(Action))
4997 Opts.LexEditorPlaceholders = false;
4998
5000 Args.hasFlag(OPT_fdefine_target_os_macros,
5001 OPT_fno_define_target_os_macros, Opts.DefineTargetOSMacros);
5002
5003 return Diags.getNumErrors() == NumErrorsBefore;
5004}
5005
5006static void
5008 ArgumentConsumer Consumer,
5009 frontend::ActionKind Action) {
5010 const PreprocessorOutputOptions &PreprocessorOutputOpts = Opts;
5011
5012#define PREPROCESSOR_OUTPUT_OPTION_WITH_MARSHALLING(...) \
5013 GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
5014#include "clang/Options/Options.inc"
5015#undef PREPROCESSOR_OUTPUT_OPTION_WITH_MARSHALLING
5016
5017 bool Generate_dM = isStrictlyPreprocessorAction(Action) && !Opts.ShowCPP;
5018 if (Generate_dM)
5019 GenerateArg(Consumer, OPT_dM);
5020 if (!Generate_dM && Opts.ShowMacros)
5021 GenerateArg(Consumer, OPT_dD);
5022 if (Opts.DirectivesOnly)
5023 GenerateArg(Consumer, OPT_fdirectives_only);
5024}
5025
5027 ArgList &Args, DiagnosticsEngine &Diags,
5028 frontend::ActionKind Action) {
5029 unsigned NumErrorsBefore = Diags.getNumErrors();
5030
5031 PreprocessorOutputOptions &PreprocessorOutputOpts = Opts;
5032
5033#define PREPROCESSOR_OUTPUT_OPTION_WITH_MARSHALLING(...) \
5034 PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
5035#include "clang/Options/Options.inc"
5036#undef PREPROCESSOR_OUTPUT_OPTION_WITH_MARSHALLING
5037
5038 Opts.ShowCPP = isStrictlyPreprocessorAction(Action) && !Args.hasArg(OPT_dM);
5039 Opts.ShowMacros = Args.hasArg(OPT_dM) || Args.hasArg(OPT_dD);
5040 Opts.DirectivesOnly = Args.hasArg(OPT_fdirectives_only);
5041
5042 return Diags.getNumErrors() == NumErrorsBefore;
5043}
5044
5045static void GenerateTargetArgs(const TargetOptions &Opts,
5046 ArgumentConsumer Consumer) {
5047 const TargetOptions *TargetOpts = &Opts;
5048#define TARGET_OPTION_WITH_MARSHALLING(...) \
5049 GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
5050#include "clang/Options/Options.inc"
5051#undef TARGET_OPTION_WITH_MARSHALLING
5052
5053 if (!Opts.SDKVersion.empty())
5054 GenerateArg(Consumer, OPT_target_sdk_version_EQ,
5055 Opts.SDKVersion.getAsString());
5056 if (!Opts.DarwinTargetVariantSDKVersion.empty())
5057 GenerateArg(Consumer, OPT_darwin_target_variant_sdk_version_EQ,
5058 Opts.DarwinTargetVariantSDKVersion.getAsString());
5059
5060 // Generate AMDGPU xnack and sramecc flags.
5062 GenerateArg(Consumer, OPT_mxnack);
5064 GenerateArg(Consumer, OPT_mno_xnack);
5065
5067 GenerateArg(Consumer, OPT_msramecc);
5068 else if (Opts.AMDGPUSramEccState ==
5070 GenerateArg(Consumer, OPT_mno_sramecc);
5071}
5072
5073static bool ParseTargetArgs(TargetOptions &Opts, ArgList &Args,
5074 DiagnosticsEngine &Diags) {
5075 unsigned NumErrorsBefore = Diags.getNumErrors();
5076
5077 TargetOptions *TargetOpts = &Opts;
5078
5079#define TARGET_OPTION_WITH_MARSHALLING(...) \
5080 PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
5081#include "clang/Options/Options.inc"
5082#undef TARGET_OPTION_WITH_MARSHALLING
5083
5084 if (Arg *A = Args.getLastArg(options::OPT_target_sdk_version_EQ)) {
5085 llvm::VersionTuple Version;
5086 if (Version.tryParse(A->getValue()))
5087 Diags.Report(diag::err_drv_invalid_value)
5088 << A->getAsString(Args) << A->getValue();
5089 else
5090 Opts.SDKVersion = Version;
5091 }
5092 if (Arg *A =
5093 Args.getLastArg(options::OPT_darwin_target_variant_sdk_version_EQ)) {
5094 llvm::VersionTuple Version;
5095 if (Version.tryParse(A->getValue()))
5096 Diags.Report(diag::err_drv_invalid_value)
5097 << A->getAsString(Args) << A->getValue();
5098 else
5099 Opts.DarwinTargetVariantSDKVersion = Version;
5100 }
5101
5102 if (Arg *A = Args.getLastArg(options::OPT_mxnack, options::OPT_mno_xnack)) {
5103 bool IsEnabled = A->getOption().matches(options::OPT_mxnack);
5104 Opts.AMDGPUXnackState = IsEnabled
5107 }
5108
5109 if (Arg *A =
5110 Args.getLastArg(options::OPT_msramecc, options::OPT_mno_sramecc)) {
5111 bool IsEnabled = A->getOption().matches(options::OPT_msramecc);
5112 Opts.AMDGPUSramEccState = IsEnabled
5115 }
5116
5117 return Diags.getNumErrors() == NumErrorsBefore;
5118}
5119
5120bool CompilerInvocation::CreateFromArgsImpl(
5121 CompilerInvocation &Res, ArrayRef<const char *> CommandLineArgs,
5122 DiagnosticsEngine &Diags, const char *Argv0) {
5123 unsigned NumErrorsBefore = Diags.getNumErrors();
5124
5125 // Parse the arguments.
5126 const OptTable &Opts = getDriverOptTable();
5127 llvm::opt::Visibility VisibilityMask(options::CC1Option);
5128 unsigned MissingArgIndex, MissingArgCount;
5129 InputArgList Args = Opts.ParseArgs(CommandLineArgs, MissingArgIndex,
5130 MissingArgCount, VisibilityMask);
5131 LangOptions &LangOpts = Res.getLangOpts();
5132
5133 // Check for missing argument error.
5134 if (MissingArgCount)
5135 Diags.Report(diag::err_drv_missing_argument)
5136 << Args.getArgString(MissingArgIndex) << MissingArgCount;
5137
5138 // Issue errors on unknown arguments.
5139 for (const auto *A : Args.filtered(OPT_UNKNOWN)) {
5140 auto ArgString = A->getAsString(Args);
5141 std::string Nearest;
5142 if (Opts.findNearest(ArgString, Nearest, VisibilityMask) > 1)
5143 Diags.Report(diag::err_drv_unknown_argument) << ArgString;
5144 else
5145 Diags.Report(diag::err_drv_unknown_argument_with_suggestion)
5146 << ArgString << Nearest;
5147 }
5148
5149 ParseFileSystemArgs(Res.getFileSystemOpts(), Args, Diags);
5150 ParseMigratorArgs(Res.getMigratorOpts(), Args, Diags);
5151 ParseAnalyzerArgs(Res.getAnalyzerOpts(), Args, Diags);
5152 ParseSSAFArgs(Res.getSSAFOpts(), Args, Diags);
5153 ParseDiagnosticArgs(Res.getDiagnosticOpts(), Args, &Diags);
5154 ParseFrontendArgs(Res.getFrontendOpts(), Args, Diags, LangOpts.IsHeaderFile);
5155 // FIXME: We shouldn't have to pass the DashX option around here
5156 InputKind DashX = Res.getFrontendOpts().DashX;
5157 ParseTargetArgs(Res.getTargetOpts(), Args, Diags);
5158 llvm::Triple T(Res.getTargetOpts().Triple);
5159 ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), Args, Diags);
5160 if (Res.getFrontendOpts().GenReducedBMI ||
5167 }
5168 ParseAPINotesArgs(Res.getAPINotesOpts(), Args, Diags);
5169
5170 ParsePointerAuthArgs(LangOpts, Args, Diags);
5171
5172 ParseLangArgs(LangOpts, Args, DashX, T, Res.getPreprocessorOpts().Includes,
5173 Diags);
5175 LangOpts.ObjCExceptions = 1;
5176
5177 for (auto Warning : Res.getDiagnosticOpts().Warnings) {
5178 if (Warning == "misexpect" &&
5179 !Diags.isIgnored(diag::warn_profile_data_misexpect, SourceLocation())) {
5180 Res.getCodeGenOpts().MisExpect = true;
5181 }
5182 }
5183
5184 if (LangOpts.CUDA) {
5185 // During CUDA device-side compilation, the aux triple is the
5186 // triple used for host compilation.
5187 if (LangOpts.CUDAIsDevice)
5189 }
5190
5191 if (LangOpts.OpenACC && !Res.getFrontendOpts().UseClangIRPipeline &&
5193 Diags.Report(diag::warn_drv_openacc_without_cir);
5194
5195 // Set the triple of the host for OpenMP device compile.
5196 if (LangOpts.OpenMPIsTargetDevice)
5198
5199 // Set the default and host triples for SYCL device compilation.
5200 if (LangOpts.SYCLIsDevice) {
5201 if (!Args.hasArg(options::OPT_triple))
5202 Res.getTargetOpts().Triple = "spirv64-unknown-unknown";
5204 }
5205
5206 ParseCodeGenArgs(Res.getCodeGenOpts(), Args, DashX, Diags, T,
5208
5209 // FIXME: Override value name discarding when asan or msan is used because the
5210 // backend passes depend on the name of the alloca in order to print out
5211 // names.
5212 Res.getCodeGenOpts().DiscardValueNames &=
5213 !LangOpts.Sanitize.has(SanitizerKind::Address) &&
5214 !LangOpts.Sanitize.has(SanitizerKind::KernelAddress) &&
5215 !LangOpts.Sanitize.has(SanitizerKind::Memory) &&
5216 !LangOpts.Sanitize.has(SanitizerKind::KernelMemory);
5217
5218 ParsePreprocessorArgs(Res.getPreprocessorOpts(), Args, Diags,
5220 Res.getFrontendOpts());
5223
5227 if (!Res.getDependencyOutputOpts().OutputFile.empty() &&
5228 Res.getDependencyOutputOpts().Targets.empty())
5229 Diags.Report(diag::err_fe_dependency_file_requires_MT);
5230
5231 // If sanitizer is enabled, disable OPT_ffine_grained_bitfield_accesses.
5232 if (Res.getCodeGenOpts().FineGrainedBitfieldAccesses &&
5233 !Res.getLangOpts().Sanitize.empty()) {
5234 Res.getCodeGenOpts().FineGrainedBitfieldAccesses = false;
5235 Diags.Report(diag::warn_drv_fine_grained_bitfield_accesses_ignored);
5236 }
5237
5238 // Store the command-line for using in the CodeView backend.
5239 if (Res.getCodeGenOpts().CodeViewCommandLine) {
5240 Res.getCodeGenOpts().Argv0 = Argv0;
5241 append_range(Res.getCodeGenOpts().CommandLineArgs, CommandLineArgs);
5242 }
5243
5244 if (!Res.getCodeGenOpts().ProfileInstrumentUsePath.empty() &&
5245 Res.getCodeGenOpts().getProfileUse() ==
5246 llvm::driver::ProfileInstrKind::ProfileNone)
5247 Diags.Report(diag::err_drv_profile_instrument_use_path_with_no_kind);
5248
5249 llvm::TimeTraceCompression TimeTraceCompress =
5251 if (TimeTraceCompress == llvm::TimeTraceCompression::Infer &&
5252 !Res.getFrontendOpts().TimeTracePath.empty())
5253 TimeTraceCompress = llvm::inferTimeTraceCompressionFromPath(
5255 if (TimeTraceCompress == llvm::TimeTraceCompression::Zstd &&
5256 !llvm::compression::zstd::isAvailable())
5257 Diags.Report(diag::err_drv_time_trace_compression_unavailable) << "zstd";
5258
5259 FixupInvocation(Res, Diags, Args, DashX);
5260
5261 return Diags.getNumErrors() == NumErrorsBefore;
5262}
5263
5265 ArrayRef<const char *> CommandLineArgs,
5266 DiagnosticsEngine &Diags,
5267 const char *Argv0) {
5268 CompilerInvocation DummyInvocation;
5269
5270 return RoundTrip(
5271 [](CompilerInvocation &Invocation, ArrayRef<const char *> CommandLineArgs,
5272 DiagnosticsEngine &Diags, const char *Argv0) {
5273 return CreateFromArgsImpl(Invocation, CommandLineArgs, Diags, Argv0);
5274 },
5276 StringAllocator SA) {
5277 Args.push_back("-cc1");
5278 Invocation.generateCC1CommandLine(Args, SA);
5279 },
5280 Invocation, DummyInvocation, CommandLineArgs, Diags, Argv0);
5281}
5282
5284 // FIXME: Consider using SHA1 instead of MD5.
5285 llvm::HashBuilder<llvm::MD5, llvm::endianness::native> HBuilder;
5286
5287 // Note: For QoI reasons, the things we use as a hash here should all be
5288 // dumped via the -module-info flag.
5289
5290 // Start the signature with the compiler version.
5291 HBuilder.add(getClangFullRepositoryVersion());
5292
5293 // Also include the serialization version, in case LLVM_APPEND_VC_REV is off
5294 // and getClangFullRepositoryVersion() doesn't include git revision.
5296
5297 // Extend the signature with the language options
5298 const unsigned LanguageOptionValues[] = {
5299#define HASH_LANGOPT_Benign(Value)
5300#define HASH_LANGOPT_Compatible(Value) Value,
5301#define HASH_LANGOPT_NotCompatible(Value) Value,
5302#define LANGOPT(Name, Bits, Default, Compatibility, Description) \
5303 HASH_LANGOPT_##Compatibility(LangOpts->Name)
5304#define ENUM_LANGOPT(Name, Type, Bits, Default, Compatibility, Description) \
5305 HASH_LANGOPT_##Compatibility(static_cast<unsigned>(LangOpts->get##Name()))
5306#include "clang/Basic/LangOptions.def"
5307 };
5308#undef HASH_LANGOPT_Benign
5309#undef HASH_LANGOPT_Compatible
5310#undef HASH_LANGOPT_NotCompatible
5311 // addRangeElements preserves the HBuilder.add sequence and excludes the
5312 // LanguageOptionValues element count.
5313 HBuilder.addRangeElements(LanguageOptionValues);
5314
5315 HBuilder.addRange(getLangOpts().ModuleFeatures);
5316
5317 HBuilder.add(getLangOpts().ObjCRuntime);
5318 HBuilder.addRange(getLangOpts().CommentOpts.BlockCommandNames);
5319 HBuilder.add(getLangOpts().CommentOpts.RetainCommentsFromSystemHeaders);
5320
5321 // Extend the signature with the target options.
5322 HBuilder.add(getTargetOpts().Triple, getTargetOpts().CPU,
5323 getTargetOpts().TuneCPU, getTargetOpts().ABI);
5324 HBuilder.addRange(getTargetOpts().FeaturesAsWritten);
5325
5326 // Extend the signature with preprocessor options.
5327 const PreprocessorOptions &ppOpts = getPreprocessorOpts();
5328 HBuilder.add(ppOpts.UsePredefines, ppOpts.DetailedRecord);
5329
5330 const HeaderSearchOptions &hsOpts = getHeaderSearchOpts();
5331 for (const auto &Macro : getPreprocessorOpts().Macros) {
5332 // If we're supposed to ignore this macro for the purposes of modules,
5333 // don't put it into the hash.
5334 if (!hsOpts.ModulesIgnoreMacros.empty()) {
5335 // Check whether we're ignoring this macro.
5336 StringRef MacroDef = Macro.first;
5337 if (hsOpts.ModulesIgnoreMacros.count(
5338 llvm::CachedHashString(MacroDef.split('=').first)))
5339 continue;
5340 }
5341
5342 HBuilder.add(Macro);
5343 }
5344
5345 // Extend the signature with the sysroot and other header search options.
5346 HBuilder.add(hsOpts.Sysroot, hsOpts.ModuleFormat, hsOpts.UseDebugInfo,
5348 hsOpts.UseStandardCXXIncludes, hsOpts.UseLibcxx,
5350 HBuilder.add(hsOpts.ResourceDir);
5351
5352 if (hsOpts.ModulesStrictContextHash) {
5353 HBuilder.addRange(hsOpts.SystemHeaderPrefixes);
5354
5355 for (const auto &UserEntry : hsOpts.UserEntries) {
5356 // If we're supposed to ignore this search path for the purposes of
5357 // modules, don't put it into the hash.
5358 if (!hsOpts.ModulesIgnoreSearchPaths.empty()) {
5359 // Check whether we're ignoring this search path.
5360 StringRef Path = UserEntry.Path;
5361 if (hsOpts.ModulesIgnoreSearchPaths.count(llvm::CachedHashString(Path)))
5362 continue;
5363 }
5364
5365 HBuilder.add(UserEntry);
5366 }
5367
5368 HBuilder.addRange(getFrontendOpts().ModuleMapFiles);
5369
5370 HBuilder.addRange(hsOpts.VFSOverlayFiles);
5371
5372 const DiagnosticOptions &diagOpts = getDiagnosticOpts();
5373#define DIAGOPT(Name, Bits, Default) HBuilder.add(diagOpts.Name);
5374#define ENUM_DIAGOPT(Name, Type, Bits, Default) \
5375 HBuilder.add(diagOpts.get##Name());
5376#include "clang/Basic/DiagnosticOptions.def"
5377#undef DIAGOPT
5378#undef ENUM_DIAGOPT
5379 }
5380
5381 // Extend the signature with the user build path.
5382 HBuilder.add(hsOpts.ModuleUserBuildPath);
5383
5384 // Extend the signature with the module file extensions.
5385 for (const auto &ext : getFrontendOpts().ModuleFileExtensions)
5386 ext->hashExtension(HBuilder);
5387
5388 // Extend the signature with the Swift version for API notes.
5390 if (!APINotesOpts.SwiftVersion.empty()) {
5391 HBuilder.add(APINotesOpts.SwiftVersion.getMajor());
5392 if (auto Minor = APINotesOpts.SwiftVersion.getMinor())
5393 HBuilder.add(*Minor);
5394 if (auto Subminor = APINotesOpts.SwiftVersion.getSubminor())
5395 HBuilder.add(*Subminor);
5396 if (auto Build = APINotesOpts.SwiftVersion.getBuild())
5397 HBuilder.add(*Build);
5398 }
5399
5400 // Extend the signature with affecting codegen options.
5401 {
5403#define CODEGENOPT(Name, Bits, Default, Compatibility) \
5404 if constexpr (CK::Compatibility != CK::Benign) \
5405 HBuilder.add(CodeGenOpts->Name);
5406#define ENUM_CODEGENOPT(Name, Type, Bits, Default, Compatibility) \
5407 if constexpr (CK::Compatibility != CK::Benign) \
5408 HBuilder.add(static_cast<unsigned>(CodeGenOpts->get##Name()));
5409#define DEBUGOPT(Name, Bits, Default, Compatibility)
5410#define VALUE_DEBUGOPT(Name, Bits, Default, Compatibility)
5411#define ENUM_DEBUGOPT(Name, Type, Bits, Default, Compatibility)
5412#include "clang/Basic/CodeGenOptions.def"
5413 }
5414
5415 // When compiling with -gmodules, also hash -fdebug-prefix-map as it
5416 // affects the debug info in the PCM.
5417 if (getCodeGenOpts().DebugTypeExtRefs)
5418 HBuilder.addRange(getCodeGenOpts().DebugPrefixMap);
5419
5420 // Extend the signature with the affecting debug options.
5421 if (getHeaderSearchOpts().ModuleFormat == "obj") {
5422 // FIXME: Replace with C++20 `using enum CodeGenOptions::CompatibilityKind`.
5424#define DEBUGOPT(Name, Bits, Default, Compatibility) \
5425 if constexpr (CK::Compatibility != CK::Benign) \
5426 HBuilder.add(CodeGenOpts->Name);
5427#define VALUE_DEBUGOPT(Name, Bits, Default, Compatibility) \
5428 if constexpr (CK::Compatibility != CK::Benign) \
5429 HBuilder.add(CodeGenOpts->Name);
5430#define ENUM_DEBUGOPT(Name, Type, Bits, Default, Compatibility) \
5431 if constexpr (CK::Compatibility != CK::Benign) \
5432 HBuilder.add(static_cast<unsigned>(CodeGenOpts->get##Name()));
5433#include "clang/Basic/DebugOptions.def"
5434 }
5435
5436 // Extend the signature with the enabled sanitizers, if at least one is
5437 // enabled. Sanitizers which cannot affect AST generation aren't hashed.
5438 SanitizerSet SanHash = getLangOpts().Sanitize;
5440 if (!SanHash.empty())
5441 HBuilder.add(SanHash.Mask);
5442
5443 llvm::MD5::MD5Result Result;
5444 HBuilder.getHasher().final(Result);
5445 uint64_t Hash = Result.high() ^ Result.low();
5446 return toString(llvm::APInt(64, Hash), 36, /*Signed=*/false);
5447}
5448
5450 llvm::function_ref<VisitMutResult(StringRef, std::string &)> Cb) {
5451 std::string NewValue;
5452
5453#define RETURN_IF(OPTS, PATH) \
5454 do { \
5455 VisitMutResult Res = Cb(PATH, NewValue); \
5456 if (Res.Replace) { \
5457 (void)ensureOwned(OPTS); \
5458 PATH.clear(); \
5459 std::swap(PATH, NewValue); \
5460 } \
5461 if (Res.Terminate) \
5462 return; \
5463 } while (0)
5464
5465#define RETURN_IF_MANY(OPTS, PATHS) \
5466 do { \
5467 for (unsigned I = 0, E = PATHS.size(); I != E; ++I) \
5468 RETURN_IF(OPTS, PATHS[I]); \
5469 } while (0)
5470
5471 // Header search paths.
5472 RETURN_IF(HSOpts, HSOpts->Sysroot);
5473 for (auto &Entry : HSOpts->UserEntries)
5474 if (Entry.IgnoreSysRoot)
5475 RETURN_IF(HSOpts, Entry.Path);
5476 RETURN_IF(HSOpts, HSOpts->ResourceDir);
5477 RETURN_IF(HSOpts, HSOpts->ModuleCachePath);
5478 RETURN_IF(HSOpts, HSOpts->ModuleUserBuildPath);
5479 for (auto &[Name, File] : HSOpts->PrebuiltModuleFiles)
5481 RETURN_IF_MANY(HSOpts, HSOpts->PrebuiltModulePaths);
5482 RETURN_IF_MANY(HSOpts, HSOpts->VFSOverlayFiles);
5483
5484 // Preprocessor options.
5485 RETURN_IF_MANY(PPOpts, PPOpts->MacroIncludes);
5486 RETURN_IF_MANY(PPOpts, PPOpts->Includes);
5487 RETURN_IF(PPOpts, PPOpts->ImplicitPCHInclude);
5488
5489 // Frontend options.
5490 for (auto &Input : FrontendOpts->Inputs) {
5491 if (Input.isBuffer())
5492 continue;
5493
5494 RETURN_IF(FrontendOpts, Input.File);
5495 }
5496 // TODO: Also report output files such as FrontendOpts->OutputFile;
5497 RETURN_IF(FrontendOpts, FrontendOpts->CodeCompletionAt.FileName);
5498 RETURN_IF_MANY(FrontendOpts, FrontendOpts->ModuleMapFiles);
5500 RETURN_IF_MANY(FrontendOpts, FrontendOpts->ModulesEmbedFiles);
5501 RETURN_IF_MANY(FrontendOpts, FrontendOpts->ASTMergeFiles);
5502 RETURN_IF(FrontendOpts, FrontendOpts->OverrideRecordLayoutsFile);
5503 RETURN_IF(FrontendOpts, FrontendOpts->StatsFile);
5504
5505 // Filesystem options.
5506 RETURN_IF(FSOpts, FSOpts->WorkingDir);
5507
5508 // Codegen options.
5509 RETURN_IF(CodeGenOpts, CodeGenOpts->DebugCompilationDir);
5510 RETURN_IF(CodeGenOpts, CodeGenOpts->CoverageCompilationDir);
5511
5512 // Sanitizer options.
5513 RETURN_IF_MANY(LangOpts, LangOpts->NoSanitizeFiles);
5514
5515 // Coverage mappings.
5516 RETURN_IF(CodeGenOpts, CodeGenOpts->ProfileInstrumentUsePath);
5517 RETURN_IF(CodeGenOpts, CodeGenOpts->SampleProfileFile);
5518 RETURN_IF(CodeGenOpts, CodeGenOpts->ProfileRemappingFile);
5519
5520 // Dependency output options.
5521 for (auto &ExtraDep : DependencyOutputOpts->ExtraDeps)
5522 RETURN_IF(DependencyOutputOpts, ExtraDep.first);
5523}
5524
5526 llvm::function_ref<VisitConstResult(StringRef)> Cb) const {
5527 // The const_cast here is OK, because our callback never tries to modify.
5528 return const_cast<CowCompilerInvocation *>(this)->visitMutPaths(
5529 [&Cb](StringRef Path, std::string &) { return Cb(Path); });
5530}
5531
5533 ArgumentConsumer Consumer) const {
5534 llvm::Triple T(getTargetOpts().Triple);
5535
5539 GenerateSSAFArgs(getSSAFOpts(), Consumer);
5540 GenerateDiagnosticArgs(getDiagnosticOpts(), Consumer,
5541 /*DefaultDiagColor=*/false);
5542 GenerateFrontendArgs(getFrontendOpts(), Consumer, getLangOpts().IsHeaderFile);
5543 GenerateTargetArgs(getTargetOpts(), Consumer);
5547 GenerateLangArgs(getLangOpts(), Consumer, T, getFrontendOpts().DashX);
5548 GenerateCodeGenArgs(getCodeGenOpts(), Consumer, T,
5549 getFrontendOpts().OutputFile, &getLangOpts());
5553 getFrontendOpts().ProgramAction);
5555}
5556
5557std::vector<std::string> CompilerInvocationBase::getCC1CommandLine() const {
5558 std::vector<std::string> Args{"-cc1"};
5560 [&Args](const Twine &Arg) { Args.push_back(Arg.str()); });
5561 return Args;
5562}
5563
5569
5571 getLangOpts().ImplicitModules = false;
5577 // The specific values we canonicalize to for pruning don't affect behaviour,
5578 /// so use the default values so they may be dropped from the command-line.
5579 getHeaderSearchOpts().ModuleCachePruneInterval = 7 * 24 * 60 * 60;
5580 getHeaderSearchOpts().ModuleCachePruneAfter = 31 * 24 * 60 * 60;
5581}
5582
5585 DiagnosticsEngine &Diags) {
5586 return createVFSFromCompilerInvocation(CI, Diags,
5587 llvm::vfs::getRealFileSystem());
5588}
5589
5597
5599 ArrayRef<std::string> VFSOverlayFiles, DiagnosticsEngine &Diags,
5601 if (VFSOverlayFiles.empty())
5602 return BaseFS;
5603
5605 // earlier vfs files are on the bottom
5606 for (const auto &File : VFSOverlayFiles) {
5607 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buffer =
5608 Result->getBufferForFile(File);
5609 if (!Buffer) {
5610 Diags.Report(diag::err_missing_vfs_overlay_file) << File;
5611 continue;
5612 }
5613
5614 IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS = llvm::vfs::getVFSFromYAML(
5615 std::move(Buffer.get()), /*DiagHandler*/ nullptr, File,
5616 /*DiagContext*/ nullptr, Result);
5617 if (!FS) {
5618 Diags.Report(diag::err_invalid_vfs_overlay) << File;
5619 continue;
5620 }
5621
5622 Result = FS;
5623 }
5624 return Result;
5625}
#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:139
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.
std::string SaveDynDbgTempsFilePrefix
Prefix to use for -save-dynamic-debugging-temps output.
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:241
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:927
bool isIgnored(unsigned DiagID, SourceLocation Loc) const
Determine whether the diagnostic is known to be ignored.
Definition Diagnostic.h:992
unsigned getNumWarnings() const
Definition Diagnostic.h:928
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.
llvm::TimeTraceCompression TimeTraceCompress
Compression mode for -ftime-trace output.
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.
std::string TimeTracePath
Path which stores the output files for -ftime-trace.
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 by implicitly-built modules.
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)
llvm::SmallSetVector< llvm::CachedHashString, 16 > ModulesIgnoreSearchPaths
The set of header search paths that should be ignored by implicitly-built modules.
unsigned ModulesValidateOncePerBuildSession
If true, skip verifying input files used by modules if the module was already verified during this bu...
unsigned ModulesValidateDirectoryDependencies
Whether to treat an implicitly built module as out of date when a directory it depends on the listing...
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–)
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.
AMDGPUFeatureState AMDGPUSramEccState
AMDGPU sramecc setting from -msramecc/-mno-sramecc.
llvm::VersionTuple DarwinTargetVariantSDKVersion
The version of the darwin target variant SDK which was used during the compilation.
AMDGPUFeatureState AMDGPUXnackState
AMDGPU xnack setting from -mxnack/-mno-xnack.
std::string HostTriple
When compiling for the device side, contains the triple used to compile for the host.
@ Enabled
Feature explicitly enabled.
@ Disabled
Feature explicitly disabled.
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.
@ 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.
@ EmitCIRBC
Emit a .cirbc file (ClangIR bytecode).
@ 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:1466
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
Top level wrappers for InstallAPI frontend operations.
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)
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.
@ 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:906
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
const FunctionProtoType * T
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:45
constexpr uint16_t StdTypeInfoVTablePointerConstantDiscrimination
Constant discriminator for std::type_info vtable pointers: 0xB1EA/45546 The value is ptrauth_string_d...
SanitizerMask parseSanitizerValue(StringRef Value, bool AllowGroups)
Parse a single value from a -fsanitize= or -fno-sanitize= value list.
const llvm::opt::OptTable & getDriverOptTable()
AnalysisDiagClients
AnalysisDiagClients - Set of available diagnostic clients for rendering analysis results.
@ NUM_ANALYSIS_DIAG_CLIENTS
std::string getClangFullRepositoryVersion()
Retrieves the full repository version that is an amalgamation of the information in getClangRepositor...
Definition Version.cpp:68
int getLastArgIntValue(const llvm::opt::ArgList &Args, llvm::opt::OptSpecifier Id, int Default, DiagnosticsEngine *Diags=nullptr, unsigned Base=0)
Return the value of the last argument as an integer, or a default.
AnalysisInliningMode
AnalysisInlineFunctionSelection - Set of inlining function selection heuristics.
@ NumInliningModes
@ HIFMT_Textual
unsigned long uint64_t
int const char * function
Definition c++config.h:31
__DEVICE__ _Tp arg(const std::complex< _Tp > &__c)
Optimization remark with an optional regular expression pattern.
bool hasValidPattern() const
Returns true iff the optimization remark holds a valid regular expression.
Dummy tag type whose instance can be passed into the constructor to prevent creation of the reference...
unsigned IgnoreSysRoot
IgnoreSysRoot - This is false if an absolute path should be treated relative to the sysroot,...
LangStandard - Information about the properties of a particular language standard.
clang::Language getLanguage() const
Get the language that this standard describes.
const char * getDescription() const
getDescription - Get the description of this standard.
static const LangStandard & getLangStandardForKind(Kind K)
const char * getName() const
getName - Get the name of this standard.
static Kind getLangKind(StringRef Name)
static ParsedSourceLocation FromString(StringRef Str)
Construct a parsed source location from a string; the Filename is empty on error.
std::string ToString() const
Serialize ParsedSourceLocation back to a string.
PointerAuthSchema BlockDescriptorPointers
The ABI for pointers to block descriptors.
PointerAuthSchema BlockHelperFunctionPointers
The ABI for block object copy/destroy function pointers.
PointerAuthSchema CXXVTablePointers
The ABI for C++ virtual table pointers (the pointer to the table itself) as installed in an actual cl...
PointerAuthSchema 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