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