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