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