//===- CompilerInvocation.cpp ---------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "clang/Frontend/CompilerInvocation.h"
#include "TestModuleFileExtension.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/CodeGenOptions.h"
#include "clang/Basic/CommentOptions.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticDriver.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileSystemOptions.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/LangStandard.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/Sanitizers.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/Version.h"
#include "clang/Basic/XRayInstr.h"
#include "clang/Config/config.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/Options.h"
#include "clang/Frontend/CommandLineSourceLoc.h"
#include "clang/Frontend/DependencyOutputOptions.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/FrontendOptions.h"
#include "clang/Frontend/MigratorOptions.h"
#include "clang/Frontend/PreprocessorOutputOptions.h"
#include "clang/Frontend/TextDiagnosticBuffer.h"
#include "clang/Frontend/Utils.h"
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Serialization/ASTBitCodes.h"
#include "clang/Serialization/ModuleFileExtension.h"
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/CachedHashString.h"
#include "llvm/ADT/FloatingPointMode.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/Frontend/Debug/Options.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/Linker/Linker.h"
#include "llvm/MC/MCTargetOptions.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/OptSpecifier.h"
#include "llvm/Option/OptTable.h"
#include "llvm/Option/Option.h"
#include "llvm/ProfileData/InstrProfReader.h"
#include "llvm/Remarks/HotnessThresholdParser.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/HashBuilder.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/VersionTuple.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/TargetParser/Host.h"
#include "llvm/TargetParser/Triple.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstring>
#include <ctime>
#include <fstream>
#include <limits>
#include <memory>
#include <optional>
#include <string>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>

using namespace clang;
using namespace driver;
using namespace options;
using namespace llvm::opt;

//===----------------------------------------------------------------------===//
// Helpers.
//===----------------------------------------------------------------------===//

// Parse misexpect tolerance argument value.
// Valid option values are integers in the range [0, 100)
static Expected<std::optional<uint32_t>> parseToleranceOption(StringRef Arg) {
  uint32_t Val;
  if (Arg.getAsInteger(10, Val))
    return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                   "Not an integer: %s", Arg.data());
  return Val;
}

//===----------------------------------------------------------------------===//
// Initialization.
//===----------------------------------------------------------------------===//

template <class T> std::shared_ptr<T> make_shared_copy(const T &X) {
  return std::make_shared<T>(X);
}

CompilerInvocationBase::CompilerInvocationBase()
    : LangOpts(std::make_shared<LangOptions>()),
      TargetOpts(std::make_shared<TargetOptions>()),
      DiagnosticOpts(std::make_shared<DiagnosticOptions>()),
      HSOpts(std::make_shared<HeaderSearchOptions>()),
      PPOpts(std::make_shared<PreprocessorOptions>()),
      AnalyzerOpts(std::make_shared<AnalyzerOptions>()),
      MigratorOpts(std::make_shared<MigratorOptions>()),
      APINotesOpts(std::make_shared<APINotesOptions>()),
      CodeGenOpts(std::make_shared<CodeGenOptions>()),
      FSOpts(std::make_shared<FileSystemOptions>()),
      FrontendOpts(std::make_shared<FrontendOptions>()),
      DependencyOutputOpts(std::make_shared<DependencyOutputOptions>()),
      PreprocessorOutputOpts(std::make_shared<PreprocessorOutputOptions>()) {}

CompilerInvocationBase &
CompilerInvocationBase::deep_copy_assign(const CompilerInvocationBase &X) {
  if (this != &X) {
    LangOpts = make_shared_copy(X.getLangOpts());
    TargetOpts = make_shared_copy(X.getTargetOpts());
    DiagnosticOpts = make_shared_copy(X.getDiagnosticOpts());
    HSOpts = make_shared_copy(X.getHeaderSearchOpts());
    PPOpts = make_shared_copy(X.getPreprocessorOpts());
    AnalyzerOpts = make_shared_copy(X.getAnalyzerOpts());
    MigratorOpts = make_shared_copy(X.getMigratorOpts());
    APINotesOpts = make_shared_copy(X.getAPINotesOpts());
    CodeGenOpts = make_shared_copy(X.getCodeGenOpts());
    FSOpts = make_shared_copy(X.getFileSystemOpts());
    FrontendOpts = make_shared_copy(X.getFrontendOpts());
    DependencyOutputOpts = make_shared_copy(X.getDependencyOutputOpts());
    PreprocessorOutputOpts = make_shared_copy(X.getPreprocessorOutputOpts());
  }
  return *this;
}

CompilerInvocationBase &
CompilerInvocationBase::shallow_copy_assign(const CompilerInvocationBase &X) {
  if (this != &X) {
    LangOpts = X.LangOpts;
    TargetOpts = X.TargetOpts;
    DiagnosticOpts = X.DiagnosticOpts;
    HSOpts = X.HSOpts;
    PPOpts = X.PPOpts;
    AnalyzerOpts = X.AnalyzerOpts;
    MigratorOpts = X.MigratorOpts;
    APINotesOpts = X.APINotesOpts;
    CodeGenOpts = X.CodeGenOpts;
    FSOpts = X.FSOpts;
    FrontendOpts = X.FrontendOpts;
    DependencyOutputOpts = X.DependencyOutputOpts;
    PreprocessorOutputOpts = X.PreprocessorOutputOpts;
  }
  return *this;
}

CompilerInvocation::CompilerInvocation(const CowCompilerInvocation &X)
    : CompilerInvocationBase(EmptyConstructor{}) {
  CompilerInvocationBase::deep_copy_assign(X);
}

CompilerInvocation &
CompilerInvocation::operator=(const CowCompilerInvocation &X) {
  CompilerInvocationBase::deep_copy_assign(X);
  return *this;
}

template <typename T>
T &ensureOwned(std::shared_ptr<T> &Storage) {
  if (Storage.use_count() > 1)
    Storage = std::make_shared<T>(*Storage);
  return *Storage;
}

LangOptions &CowCompilerInvocation::getMutLangOpts() {
  return ensureOwned(LangOpts);
}

TargetOptions &CowCompilerInvocation::getMutTargetOpts() {
  return ensureOwned(TargetOpts);
}

DiagnosticOptions &CowCompilerInvocation::getMutDiagnosticOpts() {
  return ensureOwned(DiagnosticOpts);
}

HeaderSearchOptions &CowCompilerInvocation::getMutHeaderSearchOpts() {
  return ensureOwned(HSOpts);
}

PreprocessorOptions &CowCompilerInvocation::getMutPreprocessorOpts() {
  return ensureOwned(PPOpts);
}

AnalyzerOptions &CowCompilerInvocation::getMutAnalyzerOpts() {
  return ensureOwned(AnalyzerOpts);
}

MigratorOptions &CowCompilerInvocation::getMutMigratorOpts() {
  return ensureOwned(MigratorOpts);
}

APINotesOptions &CowCompilerInvocation::getMutAPINotesOpts() {
  return ensureOwned(APINotesOpts);
}

CodeGenOptions &CowCompilerInvocation::getMutCodeGenOpts() {
  return ensureOwned(CodeGenOpts);
}

FileSystemOptions &CowCompilerInvocation::getMutFileSystemOpts() {
  return ensureOwned(FSOpts);
}

FrontendOptions &CowCompilerInvocation::getMutFrontendOpts() {
  return ensureOwned(FrontendOpts);
}

DependencyOutputOptions &CowCompilerInvocation::getMutDependencyOutputOpts() {
  return ensureOwned(DependencyOutputOpts);
}

PreprocessorOutputOptions &
CowCompilerInvocation::getMutPreprocessorOutputOpts() {
  return ensureOwned(PreprocessorOutputOpts);
}

//===----------------------------------------------------------------------===//
// Normalizers
//===----------------------------------------------------------------------===//

using ArgumentConsumer = CompilerInvocation::ArgumentConsumer;

#define OPTTABLE_STR_TABLE_CODE
#include "clang/Driver/Options.inc"
#undef OPTTABLE_STR_TABLE_CODE

static llvm::StringRef lookupStrInTable(unsigned Offset) {
  return OptionStrTable[Offset];
}

#define SIMPLE_ENUM_VALUE_TABLE
#include "clang/Driver/Options.inc"
#undef SIMPLE_ENUM_VALUE_TABLE

static std::optional<bool> normalizeSimpleFlag(OptSpecifier Opt,
                                               unsigned TableIndex,
                                               const ArgList &Args,
                                               DiagnosticsEngine &Diags) {
  if (Args.hasArg(Opt))
    return true;
  return std::nullopt;
}

static std::optional<bool> normalizeSimpleNegativeFlag(OptSpecifier Opt,
                                                       unsigned,
                                                       const ArgList &Args,
                                                       DiagnosticsEngine &) {
  if (Args.hasArg(Opt))
    return false;
  return std::nullopt;
}

/// The tblgen-erated code passes in a fifth parameter of an arbitrary type, but
/// denormalizeSimpleFlags never looks at it. Avoid bloating compile-time with
/// unnecessary template instantiations and just ignore it with a variadic
/// argument.
static void denormalizeSimpleFlag(ArgumentConsumer Consumer,
                                  unsigned SpellingOffset, Option::OptionClass,
                                  unsigned, /*T*/...) {
  Consumer(lookupStrInTable(SpellingOffset));
}
static void denormalizeSimpleFlag(ArgumentConsumer Consumer,
                                  const Twine &Spelling, Option::OptionClass,
                                  unsigned, /*T*/...) {
  Consumer(Spelling);
}

template <typename T> static constexpr bool is_uint64_t_convertible() {
  return !std::is_same_v<T, uint64_t> && llvm::is_integral_or_enum<T>::value;
}

template <typename T,
          std::enable_if_t<!is_uint64_t_convertible<T>(), bool> = false>
static auto makeFlagToValueNormalizer(T Value) {
  return [Value](OptSpecifier Opt, unsigned, const ArgList &Args,
                 DiagnosticsEngine &) -> std::optional<T> {
    if (Args.hasArg(Opt))
      return Value;
    return std::nullopt;
  };
}

template <typename T,
          std::enable_if_t<is_uint64_t_convertible<T>(), bool> = false>
static auto makeFlagToValueNormalizer(T Value) {
  return makeFlagToValueNormalizer(uint64_t(Value));
}

static auto makeBooleanOptionNormalizer(bool Value, bool OtherValue,
                                        OptSpecifier OtherOpt) {
  return [Value, OtherValue,
          OtherOpt](OptSpecifier Opt, unsigned, const ArgList &Args,
                    DiagnosticsEngine &) -> std::optional<bool> {
    if (const Arg *A = Args.getLastArg(Opt, OtherOpt)) {
      return A->getOption().matches(Opt) ? Value : OtherValue;
    }
    return std::nullopt;
  };
}

static auto makeBooleanOptionDenormalizer(bool Value) {
  return [Value](ArgumentConsumer Consumer, unsigned SpellingOffset,
                 Option::OptionClass, unsigned, bool KeyPath) {
    if (KeyPath == Value)
      Consumer(lookupStrInTable(SpellingOffset));
  };
}

static void denormalizeStringImpl(ArgumentConsumer Consumer,
                                  const Twine &Spelling,
                                  Option::OptionClass OptClass, unsigned,
                                  const Twine &Value) {
  switch (OptClass) {
  case Option::SeparateClass:
  case Option::JoinedOrSeparateClass:
  case Option::JoinedAndSeparateClass:
    Consumer(Spelling);
    Consumer(Value);
    break;
  case Option::JoinedClass:
  case Option::CommaJoinedClass:
    Consumer(Spelling + Value);
    break;
  default:
    llvm_unreachable("Cannot denormalize an option with option class "
                     "incompatible with string denormalization.");
  }
}

template <typename T>
static void
denormalizeString(ArgumentConsumer Consumer, unsigned SpellingOffset,
                  Option::OptionClass OptClass, unsigned TableIndex, T Value) {
  denormalizeStringImpl(Consumer, lookupStrInTable(SpellingOffset), OptClass,
                        TableIndex, Twine(Value));
}

template <typename T>
static void denormalizeString(ArgumentConsumer Consumer, const Twine &Spelling,
                              Option::OptionClass OptClass, unsigned TableIndex,
                              T Value) {
  denormalizeStringImpl(Consumer, Spelling, OptClass, TableIndex, Twine(Value));
}

static std::optional<SimpleEnumValue>
findValueTableByName(const SimpleEnumValueTable &Table, StringRef Name) {
  for (int I = 0, E = Table.Size; I != E; ++I)
    if (Name == Table.Table[I].Name)
      return Table.Table[I];

  return std::nullopt;
}

static std::optional<SimpleEnumValue>
findValueTableByValue(const SimpleEnumValueTable &Table, unsigned Value) {
  for (int I = 0, E = Table.Size; I != E; ++I)
    if (Value == Table.Table[I].Value)
      return Table.Table[I];

  return std::nullopt;
}

static std::optional<unsigned> normalizeSimpleEnum(OptSpecifier Opt,
                                                   unsigned TableIndex,
                                                   const ArgList &Args,
                                                   DiagnosticsEngine &Diags) {
  assert(TableIndex < SimpleEnumValueTablesSize);
  const SimpleEnumValueTable &Table = SimpleEnumValueTables[TableIndex];

  auto *Arg = Args.getLastArg(Opt);
  if (!Arg)
    return std::nullopt;

  StringRef ArgValue = Arg->getValue();
  if (auto MaybeEnumVal = findValueTableByName(Table, ArgValue))
    return MaybeEnumVal->Value;

  Diags.Report(diag::err_drv_invalid_value)
      << Arg->getAsString(Args) << ArgValue;
  return std::nullopt;
}

static void denormalizeSimpleEnumImpl(ArgumentConsumer Consumer,
                                      unsigned SpellingOffset,
                                      Option::OptionClass OptClass,
                                      unsigned TableIndex, unsigned Value) {
  assert(TableIndex < SimpleEnumValueTablesSize);
  const SimpleEnumValueTable &Table = SimpleEnumValueTables[TableIndex];
  if (auto MaybeEnumVal = findValueTableByValue(Table, Value)) {
    denormalizeString(Consumer, lookupStrInTable(SpellingOffset), OptClass,
                      TableIndex, MaybeEnumVal->Name);
  } else {
    llvm_unreachable("The simple enum value was not correctly defined in "
                     "the tablegen option description");
  }
}

template <typename T>
static void denormalizeSimpleEnum(ArgumentConsumer Consumer,
                                  unsigned SpellingOffset,
                                  Option::OptionClass OptClass,
                                  unsigned TableIndex, T Value) {
  return denormalizeSimpleEnumImpl(Consumer, SpellingOffset, OptClass,
                                   TableIndex, static_cast<unsigned>(Value));
}

static std::optional<std::string> normalizeString(OptSpecifier Opt,
                                                  int TableIndex,
                                                  const ArgList &Args,
                                                  DiagnosticsEngine &Diags) {
  auto *Arg = Args.getLastArg(Opt);
  if (!Arg)
    return std::nullopt;
  return std::string(Arg->getValue());
}

template <typename IntTy>
static std::optional<IntTy> normalizeStringIntegral(OptSpecifier Opt, int,
                                                    const ArgList &Args,
                                                    DiagnosticsEngine &Diags) {
  auto *Arg = Args.getLastArg(Opt);
  if (!Arg)
    return std::nullopt;
  IntTy Res;
  if (StringRef(Arg->getValue()).getAsInteger(0, Res)) {
    Diags.Report(diag::err_drv_invalid_int_value)
        << Arg->getAsString(Args) << Arg->getValue();
    return std::nullopt;
  }
  return Res;
}

static std::optional<std::vector<std::string>>
normalizeStringVector(OptSpecifier Opt, int, const ArgList &Args,
                      DiagnosticsEngine &) {
  return Args.getAllArgValues(Opt);
}

static void denormalizeStringVector(ArgumentConsumer Consumer,
                                    unsigned SpellingOffset,
                                    Option::OptionClass OptClass,
                                    unsigned TableIndex,
                                    const std::vector<std::string> &Values) {
  switch (OptClass) {
  case Option::CommaJoinedClass: {
    std::string CommaJoinedValue;
    if (!Values.empty()) {
      CommaJoinedValue.append(Values.front());
      for (const std::string &Value : llvm::drop_begin(Values, 1)) {
        CommaJoinedValue.append(",");
        CommaJoinedValue.append(Value);
      }
    }
    denormalizeString(Consumer, SpellingOffset,
                      Option::OptionClass::JoinedClass, TableIndex,
                      CommaJoinedValue);
    break;
  }
  case Option::JoinedClass:
  case Option::SeparateClass:
  case Option::JoinedOrSeparateClass:
    for (const std::string &Value : Values)
      denormalizeString(Consumer, SpellingOffset, OptClass, TableIndex, Value);
    break;
  default:
    llvm_unreachable("Cannot denormalize an option with option class "
                     "incompatible with string vector denormalization.");
  }
}

static std::optional<std::string> normalizeTriple(OptSpecifier Opt,
                                                  int TableIndex,
                                                  const ArgList &Args,
                                                  DiagnosticsEngine &Diags) {
  auto *Arg = Args.getLastArg(Opt);
  if (!Arg)
    return std::nullopt;
  return llvm::Triple::normalize(Arg->getValue());
}

template <typename T, typename U>
static T mergeForwardValue(T KeyPath, U Value) {
  return static_cast<T>(Value);
}

template <typename T, typename U> static T mergeMaskValue(T KeyPath, U Value) {
  return KeyPath | Value;
}

template <typename T> static T extractForwardValue(T KeyPath) {
  return KeyPath;
}

template <typename T, typename U, U Value>
static T extractMaskValue(T KeyPath) {
  return ((KeyPath & Value) == Value) ? static_cast<T>(Value) : T();
}

#define PARSE_OPTION_WITH_MARSHALLING(                                         \
    ARGS, DIAGS, PREFIX_TYPE, SPELLING_OFFSET, ID, KIND, GROUP, ALIAS,         \
    ALIASARGS, FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS,       \
    METAVAR, VALUES, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE,        \
    IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, \
    TABLE_INDEX)                                                               \
  if ((VISIBILITY) & options::CC1Option) {                                     \
    KEYPATH = MERGER(KEYPATH, DEFAULT_VALUE);                                  \
    if (IMPLIED_CHECK)                                                         \
      KEYPATH = MERGER(KEYPATH, IMPLIED_VALUE);                                \
    if (SHOULD_PARSE)                                                          \
      if (auto MaybeValue = NORMALIZER(OPT_##ID, TABLE_INDEX, ARGS, DIAGS))    \
        KEYPATH =                                                              \
            MERGER(KEYPATH, static_cast<decltype(KEYPATH)>(*MaybeValue));      \
  }

// Capture the extracted value as a lambda argument to avoid potential issues
// with lifetime extension of the reference.
#define GENERATE_OPTION_WITH_MARSHALLING(                                      \
    CONSUMER, PREFIX_TYPE, SPELLING_OFFSET, ID, KIND, GROUP, ALIAS, ALIASARGS, \
    FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, VALUES, \
    SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, IMPLIED_CHECK,          \
    IMPLIED_VALUE, NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX)   \
  if ((VISIBILITY) & options::CC1Option) {                                     \
    [&](const auto &Extracted) {                                               \
      if (ALWAYS_EMIT ||                                                       \
          (Extracted !=                                                        \
           static_cast<decltype(KEYPATH)>((IMPLIED_CHECK) ? (IMPLIED_VALUE)    \
                                                          : (DEFAULT_VALUE)))) \
        DENORMALIZER(CONSUMER, SPELLING_OFFSET, Option::KIND##Class,           \
                     TABLE_INDEX, Extracted);                                  \
    }(EXTRACTOR(KEYPATH));                                                     \
  }

static StringRef GetInputKindName(InputKind IK);

static bool FixupInvocation(CompilerInvocation &Invocation,
                            DiagnosticsEngine &Diags, const ArgList &Args,
                            InputKind IK) {
  unsigned NumErrorsBefore = Diags.getNumErrors();

  LangOptions &LangOpts = Invocation.getLangOpts();
  CodeGenOptions &CodeGenOpts = Invocation.getCodeGenOpts();
  TargetOptions &TargetOpts = Invocation.getTargetOpts();
  FrontendOptions &FrontendOpts = Invocation.getFrontendOpts();
  CodeGenOpts.XRayInstrumentFunctions = LangOpts.XRayInstrument;
  CodeGenOpts.XRayAlwaysEmitCustomEvents = LangOpts.XRayAlwaysEmitCustomEvents;
  CodeGenOpts.XRayAlwaysEmitTypedEvents = LangOpts.XRayAlwaysEmitTypedEvents;
  CodeGenOpts.DisableFree = FrontendOpts.DisableFree;
  FrontendOpts.GenerateGlobalModuleIndex = FrontendOpts.UseGlobalModuleIndex;
  if (FrontendOpts.ShowStats)
    CodeGenOpts.ClearASTBeforeBackend = false;
  LangOpts.SanitizeCoverage = CodeGenOpts.hasSanitizeCoverage();
  LangOpts.ForceEmitVTables = CodeGenOpts.ForceEmitVTables;
  LangOpts.SpeculativeLoadHardening = CodeGenOpts.SpeculativeLoadHardening;
  LangOpts.CurrentModule = LangOpts.ModuleName;

  llvm::Triple T(TargetOpts.Triple);
  llvm::Triple::ArchType Arch = T.getArch();

  CodeGenOpts.CodeModel = TargetOpts.CodeModel;
  CodeGenOpts.LargeDataThreshold = TargetOpts.LargeDataThreshold;

  if (CodeGenOpts.getExceptionHandling() !=
          CodeGenOptions::ExceptionHandlingKind::None &&
      T.isWindowsMSVCEnvironment())
    Diags.Report(diag::err_fe_invalid_exception_model)
        << static_cast<unsigned>(CodeGenOpts.getExceptionHandling()) << T.str();

  if (LangOpts.AppleKext && !LangOpts.CPlusPlus)
    Diags.Report(diag::warn_c_kext);

  if (LangOpts.NewAlignOverride &&
      !llvm::isPowerOf2_32(LangOpts.NewAlignOverride)) {
    Arg *A = Args.getLastArg(OPT_fnew_alignment_EQ);
    Diags.Report(diag::err_fe_invalid_alignment)
        << A->getAsString(Args) << A->getValue();
    LangOpts.NewAlignOverride = 0;
  }

  // The -f[no-]raw-string-literals option is only valid in C and in C++
  // standards before C++11.
  if (LangOpts.CPlusPlus11) {
    if (Args.hasArg(OPT_fraw_string_literals, OPT_fno_raw_string_literals)) {
      Args.claimAllArgs(OPT_fraw_string_literals, OPT_fno_raw_string_literals);
      Diags.Report(diag::warn_drv_fraw_string_literals_in_cxx11)
          << bool(LangOpts.RawStringLiterals);
    }

    // Do not allow disabling raw string literals in C++11 or later.
    LangOpts.RawStringLiterals = true;
  }

  // Prevent the user from specifying both -fsycl-is-device and -fsycl-is-host.
  if (LangOpts.SYCLIsDevice && LangOpts.SYCLIsHost)
    Diags.Report(diag::err_drv_argument_not_allowed_with) << "-fsycl-is-device"
                                                          << "-fsycl-is-host";

  if (Args.hasArg(OPT_fgnu89_inline) && LangOpts.CPlusPlus)
    Diags.Report(diag::err_drv_argument_not_allowed_with)
        << "-fgnu89-inline" << GetInputKindName(IK);

  if (Args.hasArg(OPT_hlsl_entrypoint) && !LangOpts.HLSL)
    Diags.Report(diag::err_drv_argument_not_allowed_with)
        << "-hlsl-entry" << GetInputKindName(IK);

  if (Args.hasArg(OPT_fdx_rootsignature_version) && !LangOpts.HLSL)
    Diags.Report(diag::err_drv_argument_not_allowed_with)
        << "-fdx-rootsignature-version" << GetInputKindName(IK);

  if (Args.hasArg(OPT_fgpu_allow_device_init) && !LangOpts.HIP)
    Diags.Report(diag::warn_ignored_hip_only_option)
        << Args.getLastArg(OPT_fgpu_allow_device_init)->getAsString(Args);

  if (Args.hasArg(OPT_gpu_max_threads_per_block_EQ) && !LangOpts.HIP)
    Diags.Report(diag::warn_ignored_hip_only_option)
        << Args.getLastArg(OPT_gpu_max_threads_per_block_EQ)->getAsString(Args);

  // When these options are used, the compiler is allowed to apply
  // optimizations that may affect the final result. For example
  // (x+y)+z is transformed to x+(y+z) but may not give the same
  // final result; it's not value safe.
  // Another example can be to simplify x/x to 1.0 but x could be 0.0, INF
  // or NaN. Final result may then differ. An error is issued when the eval
  // method is set with one of these options.
  if (Args.hasArg(OPT_ffp_eval_method_EQ)) {
    if (LangOpts.ApproxFunc)
      Diags.Report(diag::err_incompatible_fp_eval_method_options) << 0;
    if (LangOpts.AllowFPReassoc)
      Diags.Report(diag::err_incompatible_fp_eval_method_options) << 1;
    if (LangOpts.AllowRecip)
      Diags.Report(diag::err_incompatible_fp_eval_method_options) << 2;
  }

  // -cl-strict-aliasing needs to emit diagnostic in the case where CL > 1.0.
  // This option should be deprecated for CL > 1.0 because
  // this option was added for compatibility with OpenCL 1.0.
  if (Args.getLastArg(OPT_cl_strict_aliasing) &&
      (LangOpts.getOpenCLCompatibleVersion() > 100))
    Diags.Report(diag::warn_option_invalid_ocl_version)
        << LangOpts.getOpenCLVersionString()
        << Args.getLastArg(OPT_cl_strict_aliasing)->getAsString(Args);

  if (Arg *A = Args.getLastArg(OPT_fdefault_calling_conv_EQ)) {
    auto DefaultCC = LangOpts.getDefaultCallingConv();

    bool emitError = (DefaultCC == LangOptions::DCC_FastCall ||
                      DefaultCC == LangOptions::DCC_StdCall) &&
                     Arch != llvm::Triple::x86;
    emitError |= (DefaultCC == LangOptions::DCC_VectorCall ||
                  DefaultCC == LangOptions::DCC_RegCall) &&
                 !T.isX86();
    emitError |= DefaultCC == LangOptions::DCC_RtdCall && Arch != llvm::Triple::m68k;
    if (emitError)
      Diags.Report(diag::err_drv_argument_not_allowed_with)
          << A->getSpelling() << T.getTriple();
  }

  return Diags.getNumErrors() == NumErrorsBefore;
}

//===----------------------------------------------------------------------===//
// Deserialization (from args)
//===----------------------------------------------------------------------===//

static unsigned getOptimizationLevel(ArgList &Args, InputKind IK,
                                     DiagnosticsEngine &Diags) {
  unsigned DefaultOpt = 0;
  if ((IK.getLanguage() == Language::OpenCL ||
       IK.getLanguage() == Language::OpenCLCXX) &&
      !Args.hasArg(OPT_cl_opt_disable))
    DefaultOpt = 2;

  if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
    if (A->getOption().matches(options::OPT_O0))
      return 0;

    if (A->getOption().matches(options::OPT_Ofast))
      return 3;

    assert(A->getOption().matches(options::OPT_O));

    StringRef S(A->getValue());
    if (S == "s" || S == "z")
      return 2;

    if (S == "g")
      return 1;

    return getLastArgIntValue(Args, OPT_O, DefaultOpt, Diags);
  }

  return DefaultOpt;
}

static unsigned getOptimizationLevelSize(ArgList &Args) {
  if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
    if (A->getOption().matches(options::OPT_O)) {
      switch (A->getValue()[0]) {
      default:
        return 0;
      case 's':
        return 1;
      case 'z':
        return 2;
      }
    }
  }
  return 0;
}

static void GenerateArg(ArgumentConsumer Consumer,
                        llvm::opt::OptSpecifier OptSpecifier) {
  Option Opt = getDriverOptTable().getOption(OptSpecifier);
  denormalizeSimpleFlag(Consumer, Opt.getPrefixedName(),
                        Option::OptionClass::FlagClass, 0);
}

static void GenerateArg(ArgumentConsumer Consumer,
                        llvm::opt::OptSpecifier OptSpecifier,
                        const Twine &Value) {
  Option Opt = getDriverOptTable().getOption(OptSpecifier);
  denormalizeString(Consumer, Opt.getPrefixedName(), Opt.getKind(), 0, Value);
}

// Parse command line arguments into CompilerInvocation.
using ParseFn =
    llvm::function_ref<bool(CompilerInvocation &, ArrayRef<const char *>,
                            DiagnosticsEngine &, const char *)>;

// Generate command line arguments from CompilerInvocation.
using GenerateFn = llvm::function_ref<void(
    CompilerInvocation &, SmallVectorImpl<const char *> &,
    CompilerInvocation::StringAllocator)>;

/// May perform round-trip of command line arguments. By default, the round-trip
/// is enabled in assert builds. This can be overwritten at run-time via the
/// "-round-trip-args" and "-no-round-trip-args" command line flags, or via the
/// ForceRoundTrip parameter.
///
/// During round-trip, the command line arguments are parsed into a dummy
/// CompilerInvocation, which is used to generate the command line arguments
/// again. The real CompilerInvocation is then created by parsing the generated
/// arguments, not the original ones. This (in combination with tests covering
/// argument behavior) ensures the generated command line is complete (doesn't
/// drop/mangle any arguments).
///
/// Finally, we check the command line that was used to create the real
/// CompilerInvocation instance. By default, we compare it to the command line
/// the real CompilerInvocation generates. This checks whether the generator is
/// deterministic. If \p CheckAgainstOriginalInvocation is enabled, we instead
/// compare it to the original command line to verify the original command-line
/// was canonical and can round-trip exactly.
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) {
#ifndef NDEBUG
  bool DoRoundTripDefault = true;
#else
  bool DoRoundTripDefault = false;
#endif

  bool DoRoundTrip = DoRoundTripDefault;
  if (ForceRoundTrip) {
    DoRoundTrip = true;
  } else {
    for (const auto *Arg : CommandLineArgs) {
      if (Arg == StringRef("-round-trip-args"))
        DoRoundTrip = true;
      if (Arg == StringRef("-no-round-trip-args"))
        DoRoundTrip = false;
    }
  }

  // If round-trip was not requested, simply run the parser with the real
  // invocation diagnostics.
  if (!DoRoundTrip)
    return Parse(RealInvocation, CommandLineArgs, Diags, Argv0);

  // Serializes quoted (and potentially escaped) arguments.
  auto SerializeArgs = [](ArrayRef<const char *> Args) {
    std::string Buffer;
    llvm::raw_string_ostream OS(Buffer);
    for (const char *Arg : Args) {
      llvm::sys::printArg(OS, Arg, /*Quote=*/true);
      OS << ' ';
    }
    return Buffer;
  };

  // Setup a dummy DiagnosticsEngine.
  DiagnosticOptions DummyDiagOpts;
  DiagnosticsEngine DummyDiags(new DiagnosticIDs(), DummyDiagOpts);
  DummyDiags.setClient(new TextDiagnosticBuffer());

  // Run the first parse on the original arguments with the dummy invocation and
  // diagnostics.
  if (!Parse(DummyInvocation, CommandLineArgs, DummyDiags, Argv0) ||
      DummyDiags.getNumWarnings() != 0) {
    // If the first parse did not succeed, it must be user mistake (invalid
    // command line arguments). We won't be able to generate arguments that
    // would reproduce the same result. Let's fail again with the real
    // invocation and diagnostics, so all side-effects of parsing are visible.
    unsigned NumWarningsBefore = Diags.getNumWarnings();
    auto Success = Parse(RealInvocation, CommandLineArgs, Diags, Argv0);
    if (!Success || Diags.getNumWarnings() != NumWarningsBefore)
      return Success;

    // Parse with original options and diagnostics succeeded even though it
    // shouldn't have. Something is off.
    Diags.Report(diag::err_cc1_round_trip_fail_then_ok);
    Diags.Report(diag::note_cc1_round_trip_original)
        << SerializeArgs(CommandLineArgs);
    return false;
  }

  // Setup string allocator.
  llvm::BumpPtrAllocator Alloc;
  llvm::StringSaver StringPool(Alloc);
  auto SA = [&StringPool](const Twine &Arg) {
    return StringPool.save(Arg).data();
  };

  // Generate arguments from the dummy invocation. If Generate is the
  // inverse of Parse, the newly generated arguments must have the same
  // semantics as the original.
  SmallVector<const char *> GeneratedArgs;
  Generate(DummyInvocation, GeneratedArgs, SA);

  // Run the second parse, now on the generated arguments, and with the real
  // invocation and diagnostics. The result is what we will end up using for the
  // rest of compilation, so if Generate is not inverse of Parse, something down
  // the line will break.
  bool Success2 = Parse(RealInvocation, GeneratedArgs, Diags, Argv0);

  // The first parse on original arguments succeeded, but second parse of
  // generated arguments failed. Something must be wrong with the generator.
  if (!Success2) {
    Diags.Report(diag::err_cc1_round_trip_ok_then_fail);
    Diags.Report(diag::note_cc1_round_trip_generated)
        << 1 << SerializeArgs(GeneratedArgs);
    return false;
  }

  SmallVector<const char *> ComparisonArgs;
  if (CheckAgainstOriginalInvocation)
    // Compare against original arguments.
    ComparisonArgs.assign(CommandLineArgs.begin(), CommandLineArgs.end());
  else
    // Generate arguments again, this time from the options we will end up using
    // for the rest of the compilation.
    Generate(RealInvocation, ComparisonArgs, SA);

  // Compares two lists of arguments.
  auto Equal = [](const ArrayRef<const char *> A,
                  const ArrayRef<const char *> B) {
    return std::equal(A.begin(), A.end(), B.begin(), B.end(),
                      [](const char *AElem, const char *BElem) {
                        return StringRef(AElem) == StringRef(BElem);
                      });
  };

  // If we generated different arguments from what we assume are two
  // semantically equivalent CompilerInvocations, the Generate function may
  // be non-deterministic.
  if (!Equal(GeneratedArgs, ComparisonArgs)) {
    Diags.Report(diag::err_cc1_round_trip_mismatch);
    Diags.Report(diag::note_cc1_round_trip_generated)
        << 1 << SerializeArgs(GeneratedArgs);
    Diags.Report(diag::note_cc1_round_trip_generated)
        << 2 << SerializeArgs(ComparisonArgs);
    return false;
  }

  Diags.Report(diag::remark_cc1_round_trip_generated)
      << 1 << SerializeArgs(GeneratedArgs);
  Diags.Report(diag::remark_cc1_round_trip_generated)
      << 2 << SerializeArgs(ComparisonArgs);

  return Success2;
}

bool CompilerInvocation::checkCC1RoundTrip(ArrayRef<const char *> Args,
                                           DiagnosticsEngine &Diags,
                                           const char *Argv0) {
  CompilerInvocation DummyInvocation1, DummyInvocation2;
  return RoundTrip(
      [](CompilerInvocation &Invocation, ArrayRef<const char *> CommandLineArgs,
         DiagnosticsEngine &Diags, const char *Argv0) {
        return CreateFromArgsImpl(Invocation, CommandLineArgs, Diags, Argv0);
      },
      [](CompilerInvocation &Invocation, SmallVectorImpl<const char *> &Args,
         StringAllocator SA) {
        Args.push_back("-cc1");
        Invocation.generateCC1CommandLine(Args, SA);
      },
      DummyInvocation1, DummyInvocation2, Args, Diags, Argv0,
      /*CheckAgainstOriginalInvocation=*/true, /*ForceRoundTrip=*/true);
}

static void addDiagnosticArgs(ArgList &Args, OptSpecifier Group,
                              OptSpecifier GroupWithValue,
                              std::vector<std::string> &Diagnostics) {
  for (auto *A : Args.filtered(Group)) {
    if (A->getOption().getKind() == Option::FlagClass) {
      // The argument is a pure flag (such as OPT_Wall or OPT_Wdeprecated). Add
      // its name (minus the "W" or "R" at the beginning) to the diagnostics.
      Diagnostics.push_back(
          std::string(A->getOption().getName().drop_front(1)));
    } else if (A->getOption().matches(GroupWithValue)) {
      // This is -Wfoo= or -Rfoo=, where foo is the name of the diagnostic
      // group. Add only the group name to the diagnostics.
      Diagnostics.push_back(
          std::string(A->getOption().getName().drop_front(1).rtrim("=-")));
    } else {
      // Otherwise, add its value (for OPT_W_Joined and similar).
      Diagnostics.push_back(A->getValue());
    }
  }
}

// Parse the Static Analyzer configuration. If \p Diags is set to nullptr,
// it won't verify the input.
static void parseAnalyzerConfigs(AnalyzerOptions &AnOpts,
                                 DiagnosticsEngine *Diags);

static void getAllNoBuiltinFuncValues(ArgList &Args,
                                      std::vector<std::string> &Funcs) {
  std::vector<std::string> Values = Args.getAllArgValues(OPT_fno_builtin_);
  auto BuiltinEnd = llvm::partition(Values, Builtin::Context::isBuiltinFunc);
  Funcs.insert(Funcs.end(), Values.begin(), BuiltinEnd);
}

static void GenerateAnalyzerArgs(const AnalyzerOptions &Opts,
                                 ArgumentConsumer Consumer) {
  const AnalyzerOptions *AnalyzerOpts = &Opts;

#define ANALYZER_OPTION_WITH_MARSHALLING(...)                                  \
  GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
#include "clang/Driver/Options.inc"
#undef ANALYZER_OPTION_WITH_MARSHALLING

  if (Opts.AnalysisConstraintsOpt != RangeConstraintsModel) {
    switch (Opts.AnalysisConstraintsOpt) {
#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN)                     \
  case NAME##Model:                                                            \
    GenerateArg(Consumer, OPT_analyzer_constraints, CMDFLAG);                  \
    break;
#include "clang/StaticAnalyzer/Core/Analyses.def"
    default:
      llvm_unreachable("Tried to generate unknown analysis constraint.");
    }
  }

  if (Opts.AnalysisDiagOpt != PD_HTML) {
    switch (Opts.AnalysisDiagOpt) {
#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN)                     \
  case PD_##NAME:                                                              \
    GenerateArg(Consumer, OPT_analyzer_output, CMDFLAG);                       \
    break;
#include "clang/StaticAnalyzer/Core/Analyses.def"
    default:
      llvm_unreachable("Tried to generate unknown analysis diagnostic client.");
    }
  }

  if (Opts.AnalysisPurgeOpt != PurgeStmt) {
    switch (Opts.AnalysisPurgeOpt) {
#define ANALYSIS_PURGE(NAME, CMDFLAG, DESC)                                    \
  case NAME:                                                                   \
    GenerateArg(Consumer, OPT_analyzer_purge, CMDFLAG);                        \
    break;
#include "clang/StaticAnalyzer/Core/Analyses.def"
    default:
      llvm_unreachable("Tried to generate unknown analysis purge mode.");
    }
  }

  if (Opts.InliningMode != NoRedundancy) {
    switch (Opts.InliningMode) {
#define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC)                            \
  case NAME:                                                                   \
    GenerateArg(Consumer, OPT_analyzer_inlining_mode, CMDFLAG);                \
    break;
#include "clang/StaticAnalyzer/Core/Analyses.def"
    default:
      llvm_unreachable("Tried to generate unknown analysis inlining mode.");
    }
  }

  for (const auto &CP : Opts.CheckersAndPackages) {
    OptSpecifier Opt =
        CP.second ? OPT_analyzer_checker : OPT_analyzer_disable_checker;
    GenerateArg(Consumer, Opt, CP.first);
  }

  AnalyzerOptions ConfigOpts;
  parseAnalyzerConfigs(ConfigOpts, nullptr);

  // Sort options by key to avoid relying on StringMap iteration order.
  SmallVector<std::pair<StringRef, StringRef>, 4> SortedConfigOpts;
  for (const auto &C : Opts.Config)
    SortedConfigOpts.emplace_back(C.getKey(), C.getValue());
  llvm::sort(SortedConfigOpts, llvm::less_first());

  for (const auto &[Key, Value] : SortedConfigOpts) {
    // Don't generate anything that came from parseAnalyzerConfigs. It would be
    // redundant and may not be valid on the command line.
    auto Entry = ConfigOpts.Config.find(Key);
    if (Entry != ConfigOpts.Config.end() && Entry->getValue() == Value)
      continue;

    GenerateArg(Consumer, OPT_analyzer_config, Key + "=" + Value);
  }

  // Nothing to generate for FullCompilerInvocation.
}

static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
                              DiagnosticsEngine &Diags) {
  unsigned NumErrorsBefore = Diags.getNumErrors();

  AnalyzerOptions *AnalyzerOpts = &Opts;

#define ANALYZER_OPTION_WITH_MARSHALLING(...)                                  \
  PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
#include "clang/Driver/Options.inc"
#undef ANALYZER_OPTION_WITH_MARSHALLING

  if (Arg *A = Args.getLastArg(OPT_analyzer_constraints)) {
    StringRef Name = A->getValue();
    AnalysisConstraints Value = llvm::StringSwitch<AnalysisConstraints>(Name)
#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) \
      .Case(CMDFLAG, NAME##Model)
#include "clang/StaticAnalyzer/Core/Analyses.def"
      .Default(NumConstraints);
    if (Value == NumConstraints) {
      Diags.Report(diag::err_drv_invalid_value)
        << A->getAsString(Args) << Name;
    } else {
#ifndef LLVM_WITH_Z3
      if (Value == AnalysisConstraints::Z3ConstraintsModel) {
        Diags.Report(diag::err_analyzer_not_built_with_z3);
      }
#endif // LLVM_WITH_Z3
      Opts.AnalysisConstraintsOpt = Value;
    }
  }

  if (Arg *A = Args.getLastArg(OPT_analyzer_output)) {
    StringRef Name = A->getValue();
    AnalysisDiagClients Value = llvm::StringSwitch<AnalysisDiagClients>(Name)
#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN) \
      .Case(CMDFLAG, PD_##NAME)
#include "clang/StaticAnalyzer/Core/Analyses.def"
      .Default(NUM_ANALYSIS_DIAG_CLIENTS);
    if (Value == NUM_ANALYSIS_DIAG_CLIENTS) {
      Diags.Report(diag::err_drv_invalid_value)
        << A->getAsString(Args) << Name;
    } else {
      Opts.AnalysisDiagOpt = Value;
    }
  }

  if (Arg *A = Args.getLastArg(OPT_analyzer_purge)) {
    StringRef Name = A->getValue();
    AnalysisPurgeMode Value = llvm::StringSwitch<AnalysisPurgeMode>(Name)
#define ANALYSIS_PURGE(NAME, CMDFLAG, DESC) \
      .Case(CMDFLAG, NAME)
#include "clang/StaticAnalyzer/Core/Analyses.def"
      .Default(NumPurgeModes);
    if (Value == NumPurgeModes) {
      Diags.Report(diag::err_drv_invalid_value)
        << A->getAsString(Args) << Name;
    } else {
      Opts.AnalysisPurgeOpt = Value;
    }
  }

  if (Arg *A = Args.getLastArg(OPT_analyzer_inlining_mode)) {
    StringRef Name = A->getValue();
    AnalysisInliningMode Value = llvm::StringSwitch<AnalysisInliningMode>(Name)
#define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC) \
      .Case(CMDFLAG, NAME)
#include "clang/StaticAnalyzer/Core/Analyses.def"
      .Default(NumInliningModes);
    if (Value == NumInliningModes) {
      Diags.Report(diag::err_drv_invalid_value)
        << A->getAsString(Args) << Name;
    } else {
      Opts.InliningMode = Value;
    }
  }

  Opts.CheckersAndPackages.clear();
  for (const Arg *A :
       Args.filtered(OPT_analyzer_checker, OPT_analyzer_disable_checker)) {
    A->claim();
    bool IsEnabled = A->getOption().getID() == OPT_analyzer_checker;
    // We can have a list of comma separated checker names, e.g:
    // '-analyzer-checker=cocoa,unix'
    StringRef CheckerAndPackageList = A->getValue();
    SmallVector<StringRef, 16> CheckersAndPackages;
    CheckerAndPackageList.split(CheckersAndPackages, ",");
    for (const StringRef &CheckerOrPackage : CheckersAndPackages)
      Opts.CheckersAndPackages.emplace_back(std::string(CheckerOrPackage),
                                            IsEnabled);
  }

  // Go through the analyzer configuration options.
  for (const auto *A : Args.filtered(OPT_analyzer_config)) {

    // We can have a list of comma separated config names, e.g:
    // '-analyzer-config key1=val1,key2=val2'
    StringRef configList = A->getValue();
    SmallVector<StringRef, 4> configVals;
    configList.split(configVals, ",");
    for (const auto &configVal : configVals) {
      StringRef key, val;
      std::tie(key, val) = configVal.split("=");
      if (val.empty()) {
        Diags.Report(SourceLocation(),
                     diag::err_analyzer_config_no_value) << configVal;
        break;
      }
      if (val.contains('=')) {
        Diags.Report(SourceLocation(),
                     diag::err_analyzer_config_multiple_values)
          << configVal;
        break;
      }

      // TODO: Check checker options too, possibly in CheckerRegistry.
      // Leave unknown non-checker configs unclaimed.
      if (!key.contains(":") && Opts.isUnknownAnalyzerConfig(key)) {
        if (Opts.ShouldEmitErrorsOnInvalidConfigValue)
          Diags.Report(diag::err_analyzer_config_unknown) << key;
        continue;
      }

      A->claim();
      Opts.Config[key] = std::string(val);
    }
  }

  if (Opts.ShouldEmitErrorsOnInvalidConfigValue)
    parseAnalyzerConfigs(Opts, &Diags);
  else
    parseAnalyzerConfigs(Opts, nullptr);

  llvm::raw_string_ostream os(Opts.FullCompilerInvocation);
  for (unsigned i = 0; i < Args.getNumInputArgStrings(); ++i) {
    if (i != 0)
      os << " ";
    os << Args.getArgString(i);
  }

  return Diags.getNumErrors() == NumErrorsBefore;
}

static StringRef getStringOption(AnalyzerOptions::ConfigTable &Config,
                                 StringRef OptionName, StringRef DefaultVal) {
  return Config.insert({OptionName, std::string(DefaultVal)}).first->second;
}

static void initOption(AnalyzerOptions::ConfigTable &Config,
                       DiagnosticsEngine *Diags,
                       StringRef &OptionField, StringRef Name,
                       StringRef DefaultVal) {
  // String options may be known to invalid (e.g. if the expected string is a
  // file name, but the file does not exist), those will have to be checked in
  // parseConfigs.
  OptionField = getStringOption(Config, Name, DefaultVal);
}

static void initOption(AnalyzerOptions::ConfigTable &Config,
                       DiagnosticsEngine *Diags,
                       bool &OptionField, StringRef Name, bool DefaultVal) {
  auto PossiblyInvalidVal =
      llvm::StringSwitch<std::optional<bool>>(
          getStringOption(Config, Name, (DefaultVal ? "true" : "false")))
          .Case("true", true)
          .Case("false", false)
          .Default(std::nullopt);

  if (!PossiblyInvalidVal) {
    if (Diags)
      Diags->Report(diag::err_analyzer_config_invalid_input)
        << Name << "a boolean";
    else
      OptionField = DefaultVal;
  } else
    OptionField = *PossiblyInvalidVal;
}

static void initOption(AnalyzerOptions::ConfigTable &Config,
                       DiagnosticsEngine *Diags,
                       unsigned &OptionField, StringRef Name,
                       unsigned DefaultVal) {

  OptionField = DefaultVal;
  bool HasFailed = getStringOption(Config, Name, std::to_string(DefaultVal))
                     .getAsInteger(0, OptionField);
  if (Diags && HasFailed)
    Diags->Report(diag::err_analyzer_config_invalid_input)
      << Name << "an unsigned";
}

static void initOption(AnalyzerOptions::ConfigTable &Config,
                       DiagnosticsEngine *Diags,
                       PositiveAnalyzerOption &OptionField, StringRef Name,
                       unsigned DefaultVal) {
  auto Parsed = PositiveAnalyzerOption::create(
      getStringOption(Config, Name, std::to_string(DefaultVal)));
  if (Parsed.has_value()) {
    OptionField = Parsed.value();
    return;
  }
  if (Diags && !Parsed.has_value())
    Diags->Report(diag::err_analyzer_config_invalid_input)
        << Name << "a positive";

  OptionField = DefaultVal;
}

static void parseAnalyzerConfigs(AnalyzerOptions &AnOpts,
                                 DiagnosticsEngine *Diags) {
  // TODO: There's no need to store the entire configtable, it'd be plenty
  // enough to store checker options.

#define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL)                \
  initOption(AnOpts.Config, Diags, AnOpts.NAME, CMDFLAG, DEFAULT_VAL);
#define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(...)
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.def"

  assert(AnOpts.UserMode == "shallow" || AnOpts.UserMode == "deep");
  const bool InShallowMode = AnOpts.UserMode == "shallow";

#define ANALYZER_OPTION(...)
#define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC,        \
                                             SHALLOW_VAL, DEEP_VAL)            \
  initOption(AnOpts.Config, Diags, AnOpts.NAME, CMDFLAG,                       \
             InShallowMode ? SHALLOW_VAL : DEEP_VAL);
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.def"

  // At this point, AnalyzerOptions is configured. Let's validate some options.

  // FIXME: Here we try to validate the silenced checkers or packages are valid.
  // The current approach only validates the registered checkers which does not
  // contain the runtime enabled checkers and optimally we would validate both.
  if (!AnOpts.RawSilencedCheckersAndPackages.empty()) {
    std::vector<StringRef> Checkers =
        AnOpts.getRegisteredCheckers(/*IncludeExperimental=*/true);
    std::vector<StringRef> Packages =
        AnOpts.getRegisteredPackages(/*IncludeExperimental=*/true);

    SmallVector<StringRef, 16> CheckersAndPackages;
    AnOpts.RawSilencedCheckersAndPackages.split(CheckersAndPackages, ";");

    for (const StringRef &CheckerOrPackage : CheckersAndPackages) {
      if (Diags) {
        bool IsChecker = CheckerOrPackage.contains('.');
        bool IsValidName = IsChecker
                               ? llvm::is_contained(Checkers, CheckerOrPackage)
                               : llvm::is_contained(Packages, CheckerOrPackage);

        if (!IsValidName)
          Diags->Report(diag::err_unknown_analyzer_checker_or_package)
              << CheckerOrPackage;
      }

      AnOpts.SilencedCheckersAndPackages.emplace_back(CheckerOrPackage);
    }
  }

  if (!Diags)
    return;

  if (AnOpts.ShouldTrackConditionsDebug && !AnOpts.ShouldTrackConditions)
    Diags->Report(diag::err_analyzer_config_invalid_input)
        << "track-conditions-debug" << "'track-conditions' to also be enabled";

  if (!AnOpts.CTUDir.empty() && !llvm::sys::fs::is_directory(AnOpts.CTUDir))
    Diags->Report(diag::err_analyzer_config_invalid_input) << "ctu-dir"
                                                           << "a filename";

  if (!AnOpts.ModelPath.empty() &&
      !llvm::sys::fs::is_directory(AnOpts.ModelPath))
    Diags->Report(diag::err_analyzer_config_invalid_input) << "model-path"
                                                           << "a filename";
}

/// Generate a remark argument. This is an inverse of `ParseOptimizationRemark`.
static void
GenerateOptimizationRemark(ArgumentConsumer Consumer, OptSpecifier OptEQ,
                           StringRef Name,
                           const CodeGenOptions::OptRemark &Remark) {
  if (Remark.hasValidPattern()) {
    GenerateArg(Consumer, OptEQ, Remark.Pattern);
  } else if (Remark.Kind == CodeGenOptions::RK_Enabled) {
    GenerateArg(Consumer, OPT_R_Joined, Name);
  } else if (Remark.Kind == CodeGenOptions::RK_Disabled) {
    GenerateArg(Consumer, OPT_R_Joined, StringRef("no-") + Name);
  }
}

/// Parse a remark command line argument. It may be missing, disabled/enabled by
/// '-R[no-]group' or specified with a regular expression by '-Rgroup=regexp'.
/// On top of that, it can be disabled/enabled globally by '-R[no-]everything'.
static CodeGenOptions::OptRemark
ParseOptimizationRemark(DiagnosticsEngine &Diags, ArgList &Args,
                        OptSpecifier OptEQ, StringRef Name) {
  CodeGenOptions::OptRemark Result;

  auto InitializeResultPattern = [&Diags, &Args, &Result](const Arg *A,
                                                          StringRef Pattern) {
    Result.Pattern = Pattern.str();

    std::string RegexError;
    Result.Regex = std::make_shared<llvm::Regex>(Result.Pattern);
    if (!Result.Regex->isValid(RegexError)) {
      Diags.Report(diag::err_drv_optimization_remark_pattern)
          << RegexError << A->getAsString(Args);
      return false;
    }

    return true;
  };

  for (Arg *A : Args) {
    if (A->getOption().matches(OPT_R_Joined)) {
      StringRef Value = A->getValue();

      if (Value == Name)
        Result.Kind = CodeGenOptions::RK_Enabled;
      else if (Value == "everything")
        Result.Kind = CodeGenOptions::RK_EnabledEverything;
      else if (Value.split('-') == std::make_pair(StringRef("no"), Name))
        Result.Kind = CodeGenOptions::RK_Disabled;
      else if (Value == "no-everything")
        Result.Kind = CodeGenOptions::RK_DisabledEverything;
      else
        continue;

      if (Result.Kind == CodeGenOptions::RK_Disabled ||
          Result.Kind == CodeGenOptions::RK_DisabledEverything) {
        Result.Pattern = "";
        Result.Regex = nullptr;
      } else {
        InitializeResultPattern(A, ".*");
      }
    } else if (A->getOption().matches(OptEQ)) {
      Result.Kind = CodeGenOptions::RK_WithPattern;
      if (!InitializeResultPattern(A, A->getValue()))
        return CodeGenOptions::OptRemark();
    }
  }

  return Result;
}

static bool parseDiagnosticLevelMask(StringRef FlagName,
                                     const std::vector<std::string> &Levels,
                                     DiagnosticsEngine &Diags,
                                     DiagnosticLevelMask &M) {
  bool Success = true;
  for (const auto &Level : Levels) {
    DiagnosticLevelMask const PM =
      llvm::StringSwitch<DiagnosticLevelMask>(Level)
        .Case("note",    DiagnosticLevelMask::Note)
        .Case("remark",  DiagnosticLevelMask::Remark)
        .Case("warning", DiagnosticLevelMask::Warning)
        .Case("error",   DiagnosticLevelMask::Error)
        .Default(DiagnosticLevelMask::None);
    if (PM == DiagnosticLevelMask::None) {
      Success = false;
      Diags.Report(diag::err_drv_invalid_value) << FlagName << Level;
    }
    M = M | PM;
  }
  return Success;
}

static void parseSanitizerKinds(StringRef FlagName,
                                const std::vector<std::string> &Sanitizers,
                                DiagnosticsEngine &Diags, SanitizerSet &S) {
  for (const auto &Sanitizer : Sanitizers) {
    SanitizerMask K = parseSanitizerValue(Sanitizer, /*AllowGroups=*/false);
    if (K == SanitizerMask())
      Diags.Report(diag::err_drv_invalid_value) << FlagName << Sanitizer;
    else
      S.set(K, true);
  }
}

static SmallVector<StringRef, 4> serializeSanitizerKinds(SanitizerSet S) {
  SmallVector<StringRef, 4> Values;
  serializeSanitizerSet(S, Values);
  return Values;
}

static SanitizerMaskCutoffs
parseSanitizerWeightedKinds(StringRef FlagName,
                            const std::vector<std::string> &Sanitizers,
                            DiagnosticsEngine &Diags) {
  SanitizerMaskCutoffs Cutoffs;
  for (const auto &Sanitizer : Sanitizers) {
    if (!parseSanitizerWeightedValue(Sanitizer, /*AllowGroups=*/false, Cutoffs))
      Diags.Report(diag::err_drv_invalid_value) << FlagName << Sanitizer;
  }
  return Cutoffs;
}

static void parseXRayInstrumentationBundle(StringRef FlagName, StringRef Bundle,
                                           ArgList &Args, DiagnosticsEngine &D,
                                           XRayInstrSet &S) {
  llvm::SmallVector<StringRef, 2> BundleParts;
  llvm::SplitString(Bundle, BundleParts, ",");
  for (const auto &B : BundleParts) {
    auto Mask = parseXRayInstrValue(B);
    if (Mask == XRayInstrKind::None)
      if (B != "none")
        D.Report(diag::err_drv_invalid_value) << FlagName << Bundle;
      else
        S.Mask = Mask;
    else if (Mask == XRayInstrKind::All)
      S.Mask = Mask;
    else
      S.set(Mask, true);
  }
}

static std::string serializeXRayInstrumentationBundle(const XRayInstrSet &S) {
  llvm::SmallVector<StringRef, 2> BundleParts;
  serializeXRayInstrValue(S, BundleParts);
  std::string Buffer;
  llvm::raw_string_ostream OS(Buffer);
  llvm::interleave(BundleParts, OS, [&OS](StringRef Part) { OS << Part; }, ",");
  return Buffer;
}

// Set the profile kind using fprofile-instrument-use-path.
static void setPGOUseInstrumentor(CodeGenOptions &Opts,
                                  const Twine &ProfileName,
                                  llvm::vfs::FileSystem &FS,
                                  DiagnosticsEngine &Diags) {
  auto ReaderOrErr = llvm::IndexedInstrProfReader::create(ProfileName, FS);
  if (auto E = ReaderOrErr.takeError()) {
    unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
                                            "Error in reading profile %0: %1");
    llvm::handleAllErrors(std::move(E), [&](const llvm::ErrorInfoBase &EI) {
      Diags.Report(DiagID) << ProfileName.str() << EI.message();
    });
    return;
  }
  std::unique_ptr<llvm::IndexedInstrProfReader> PGOReader =
    std::move(ReaderOrErr.get());
  // Currently memprof profiles are only added at the IR level. Mark the profile
  // type as IR in that case as well and the subsequent matching needs to detect
  // which is available (might be one or both).
  if (PGOReader->isIRLevelProfile() || PGOReader->hasMemoryProfile()) {
    if (PGOReader->hasCSIRLevelProfile())
      Opts.setProfileUse(llvm::driver::ProfileInstrKind::ProfileCSIRInstr);
    else
      Opts.setProfileUse(llvm::driver::ProfileInstrKind::ProfileIRInstr);
  } else
    Opts.setProfileUse(llvm::driver::ProfileInstrKind::ProfileClangInstr);
}

void CompilerInvocation::setDefaultPointerAuthOptions(
    PointerAuthOptions &Opts, const LangOptions &LangOpts,
    const llvm::Triple &Triple) {
  assert(Triple.getArch() == llvm::Triple::aarch64);
  if (LangOpts.PointerAuthCalls) {
    using Key = PointerAuthSchema::ARM8_3Key;
    using Discrimination = PointerAuthSchema::Discrimination;
    // If you change anything here, be sure to update <ptrauth.h>.
    Opts.FunctionPointers = PointerAuthSchema(
        Key::ASIA, false,
        LangOpts.PointerAuthFunctionTypeDiscrimination ? Discrimination::Type
                                                       : Discrimination::None);

    Opts.CXXVTablePointers = PointerAuthSchema(
        Key::ASDA, LangOpts.PointerAuthVTPtrAddressDiscrimination,
        LangOpts.PointerAuthVTPtrTypeDiscrimination ? Discrimination::Type
                                                    : Discrimination::None);

    if (LangOpts.PointerAuthTypeInfoVTPtrDiscrimination)
      Opts.CXXTypeInfoVTablePointer =
          PointerAuthSchema(Key::ASDA, true, Discrimination::Constant,
                            StdTypeInfoVTablePointerConstantDiscrimination);
    else
      Opts.CXXTypeInfoVTablePointer =
          PointerAuthSchema(Key::ASDA, false, Discrimination::None);

    Opts.CXXVTTVTablePointers =
        PointerAuthSchema(Key::ASDA, false, Discrimination::None);
    Opts.CXXVirtualFunctionPointers = Opts.CXXVirtualVariadicFunctionPointers =
        PointerAuthSchema(Key::ASIA, true, Discrimination::Decl);
    Opts.CXXMemberFunctionPointers =
        PointerAuthSchema(Key::ASIA, false, Discrimination::Type);

    if (LangOpts.PointerAuthInitFini) {
      Opts.InitFiniPointers = PointerAuthSchema(
          Key::ASIA, LangOpts.PointerAuthInitFiniAddressDiscrimination,
          Discrimination::Constant, InitFiniPointerConstantDiscriminator);
    }

    Opts.ObjCMethodListFunctionPointers =
        PointerAuthSchema(Key::ASIA, true, Discrimination::None);
    Opts.ObjCMethodListPointer =
        PointerAuthSchema(Key::ASDA, true, Discrimination::Constant,
                          MethodListPointerConstantDiscriminator);
    if (LangOpts.PointerAuthObjcIsa) {
      Opts.ObjCIsaPointers =
          PointerAuthSchema(Key::ASDA, true, Discrimination::Constant,
                            IsaPointerConstantDiscriminator);
      Opts.ObjCSuperPointers =
          PointerAuthSchema(Key::ASDA, true, Discrimination::Constant,
                            SuperPointerConstantDiscriminator);
    }

    if (LangOpts.PointerAuthObjcClassROPointers)
      Opts.ObjCClassROPointers =
          PointerAuthSchema(Key::ASDA, true, Discrimination::Constant,
                            ClassROConstantDiscriminator);
  }
  Opts.ReturnAddresses = LangOpts.PointerAuthReturns;
  Opts.AuthTraps = LangOpts.PointerAuthAuthTraps;
  Opts.IndirectGotos = LangOpts.PointerAuthIndirectGotos;
  Opts.AArch64JumpTableHardening = LangOpts.AArch64JumpTableHardening;
}

static void parsePointerAuthOptions(PointerAuthOptions &Opts,
                                    const LangOptions &LangOpts,
                                    const llvm::Triple &Triple,
                                    DiagnosticsEngine &Diags) {
  if (!LangOpts.PointerAuthCalls && !LangOpts.PointerAuthReturns &&
      !LangOpts.PointerAuthAuthTraps && !LangOpts.PointerAuthIndirectGotos &&
      !LangOpts.AArch64JumpTableHardening)
    return;

  CompilerInvocation::setDefaultPointerAuthOptions(Opts, LangOpts, Triple);
}

void CompilerInvocationBase::GenerateCodeGenArgs(const CodeGenOptions &Opts,
                                                 ArgumentConsumer Consumer,
                                                 const llvm::Triple &T,
                                                 const std::string &OutputFile,
                                                 const LangOptions *LangOpts) {
  const CodeGenOptions &CodeGenOpts = Opts;

  if (Opts.OptimizationLevel == 0)
    GenerateArg(Consumer, OPT_O0);
  else
    GenerateArg(Consumer, OPT_O, Twine(Opts.OptimizationLevel));

#define CODEGEN_OPTION_WITH_MARSHALLING(...)                                   \
  GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
#include "clang/Driver/Options.inc"
#undef CODEGEN_OPTION_WITH_MARSHALLING

  if (Opts.OptimizationLevel > 0) {
    if (Opts.Inlining == CodeGenOptions::NormalInlining)
      GenerateArg(Consumer, OPT_finline_functions);
    else if (Opts.Inlining == CodeGenOptions::OnlyHintInlining)
      GenerateArg(Consumer, OPT_finline_hint_functions);
    else if (Opts.Inlining == CodeGenOptions::OnlyAlwaysInlining)
      GenerateArg(Consumer, OPT_fno_inline);
  }

  if (Opts.DirectAccessExternalData && LangOpts->PICLevel != 0)
    GenerateArg(Consumer, OPT_fdirect_access_external_data);
  else if (!Opts.DirectAccessExternalData && LangOpts->PICLevel == 0)
    GenerateArg(Consumer, OPT_fno_direct_access_external_data);

  std::optional<StringRef> DebugInfoVal;
  switch (Opts.DebugInfo) {
  case llvm::codegenoptions::DebugLineTablesOnly:
    DebugInfoVal = "line-tables-only";
    break;
  case llvm::codegenoptions::DebugDirectivesOnly:
    DebugInfoVal = "line-directives-only";
    break;
  case llvm::codegenoptions::DebugInfoConstructor:
    DebugInfoVal = "constructor";
    break;
  case llvm::codegenoptions::LimitedDebugInfo:
    DebugInfoVal = "limited";
    break;
  case llvm::codegenoptions::FullDebugInfo:
    DebugInfoVal = "standalone";
    break;
  case llvm::codegenoptions::UnusedTypeInfo:
    DebugInfoVal = "unused-types";
    break;
  case llvm::codegenoptions::NoDebugInfo: // default value
    DebugInfoVal = std::nullopt;
    break;
  case llvm::codegenoptions::LocTrackingOnly: // implied value
    DebugInfoVal = std::nullopt;
    break;
  }
  if (DebugInfoVal)
    GenerateArg(Consumer, OPT_debug_info_kind_EQ, *DebugInfoVal);

  for (const auto &Prefix : Opts.DebugPrefixMap)
    GenerateArg(Consumer, OPT_fdebug_prefix_map_EQ,
                Prefix.first + "=" + Prefix.second);

  for (const auto &Prefix : Opts.CoveragePrefixMap)
    GenerateArg(Consumer, OPT_fcoverage_prefix_map_EQ,
                Prefix.first + "=" + Prefix.second);

  if (Opts.NewStructPathTBAA)
    GenerateArg(Consumer, OPT_new_struct_path_tbaa);

  if (Opts.OptimizeSize == 1)
    GenerateArg(Consumer, OPT_O, "s");
  else if (Opts.OptimizeSize == 2)
    GenerateArg(Consumer, OPT_O, "z");

  // SimplifyLibCalls is set only in the absence of -fno-builtin and
  // -ffreestanding. We'll consider that when generating them.

  // NoBuiltinFuncs are generated by LangOptions.

  if (Opts.UnrollLoops && Opts.OptimizationLevel <= 1)
    GenerateArg(Consumer, OPT_funroll_loops);
  else if (!Opts.UnrollLoops && Opts.OptimizationLevel > 1)
    GenerateArg(Consumer, OPT_fno_unroll_loops);

  if (Opts.InterchangeLoops)
    GenerateArg(Consumer, OPT_floop_interchange);
  else
    GenerateArg(Consumer, OPT_fno_loop_interchange);

  if (!Opts.BinutilsVersion.empty())
    GenerateArg(Consumer, OPT_fbinutils_version_EQ, Opts.BinutilsVersion);

  if (Opts.DebugNameTable ==
      static_cast<unsigned>(llvm::DICompileUnit::DebugNameTableKind::GNU))
    GenerateArg(Consumer, OPT_ggnu_pubnames);
  else if (Opts.DebugNameTable ==
           static_cast<unsigned>(
               llvm::DICompileUnit::DebugNameTableKind::Default))
    GenerateArg(Consumer, OPT_gpubnames);

  if (Opts.DebugTemplateAlias)
    GenerateArg(Consumer, OPT_gtemplate_alias);

  auto TNK = Opts.getDebugSimpleTemplateNames();
  if (TNK != llvm::codegenoptions::DebugTemplateNamesKind::Full) {
    if (TNK == llvm::codegenoptions::DebugTemplateNamesKind::Simple)
      GenerateArg(Consumer, OPT_gsimple_template_names_EQ, "simple");
    else if (TNK == llvm::codegenoptions::DebugTemplateNamesKind::Mangled)
      GenerateArg(Consumer, OPT_gsimple_template_names_EQ, "mangled");
  }
  // ProfileInstrumentUsePath is marshalled automatically, no need to generate
  // it or PGOUseInstrumentor.

  if (Opts.TimePasses) {
    if (Opts.TimePassesPerRun)
      GenerateArg(Consumer, OPT_ftime_report_EQ, "per-pass-run");
    else
      GenerateArg(Consumer, OPT_ftime_report);

    if (Opts.TimePassesJson)
      GenerateArg(Consumer, OPT_ftime_report_json);
  }

  if (Opts.PrepareForLTO && !Opts.PrepareForThinLTO)
    GenerateArg(Consumer, OPT_flto_EQ, "full");

  if (Opts.PrepareForThinLTO)
    GenerateArg(Consumer, OPT_flto_EQ, "thin");

  if (!Opts.ThinLTOIndexFile.empty())
    GenerateArg(Consumer, OPT_fthinlto_index_EQ, Opts.ThinLTOIndexFile);

  if (Opts.SaveTempsFilePrefix == OutputFile)
    GenerateArg(Consumer, OPT_save_temps_EQ, "obj");

  StringRef MemProfileBasename("memprof.profraw");
  if (!Opts.MemoryProfileOutput.empty()) {
    if (Opts.MemoryProfileOutput == MemProfileBasename) {
      GenerateArg(Consumer, OPT_fmemory_profile);
    } else {
      size_t ArgLength =
          Opts.MemoryProfileOutput.size() - MemProfileBasename.size();
      GenerateArg(Consumer, OPT_fmemory_profile_EQ,
                  Opts.MemoryProfileOutput.substr(0, ArgLength));
    }
  }

  if (memcmp(Opts.CoverageVersion, "0000", 4))
    GenerateArg(Consumer, OPT_coverage_version_EQ,
                StringRef(Opts.CoverageVersion, 4));

  // TODO: Check if we need to generate arguments stored in CmdArgs. (Namely
  //  '-fembed_bitcode', which does not map to any CompilerInvocation field and
  //  won't be generated.)

  if (Opts.XRayInstrumentationBundle.Mask != XRayInstrKind::All) {
    std::string InstrBundle =
        serializeXRayInstrumentationBundle(Opts.XRayInstrumentationBundle);
    if (!InstrBundle.empty())
      GenerateArg(Consumer, OPT_fxray_instrumentation_bundle, InstrBundle);
  }

  if (Opts.CFProtectionReturn && Opts.CFProtectionBranch)
    GenerateArg(Consumer, OPT_fcf_protection_EQ, "full");
  else if (Opts.CFProtectionReturn)
    GenerateArg(Consumer, OPT_fcf_protection_EQ, "return");
  else if (Opts.CFProtectionBranch)
    GenerateArg(Consumer, OPT_fcf_protection_EQ, "branch");

  if (Opts.CFProtectionBranch) {
    switch (Opts.getCFBranchLabelScheme()) {
    case CFBranchLabelSchemeKind::Default:
      break;
#define CF_BRANCH_LABEL_SCHEME(Kind, FlagVal)                                  \
  case CFBranchLabelSchemeKind::Kind:                                          \
    GenerateArg(Consumer, OPT_mcf_branch_label_scheme_EQ, #FlagVal);           \
    break;
#include "clang/Basic/CFProtectionOptions.def"
    }
  }

  if (Opts.FunctionReturnThunks)
    GenerateArg(Consumer, OPT_mfunction_return_EQ, "thunk-extern");

  for (const auto &F : Opts.LinkBitcodeFiles) {
    bool Builtint = F.LinkFlags == llvm::Linker::Flags::LinkOnlyNeeded &&
                    F.PropagateAttrs && F.Internalize;
    GenerateArg(Consumer,
                Builtint ? OPT_mlink_builtin_bitcode : OPT_mlink_bitcode_file,
                F.Filename);
  }

  if (Opts.EmulatedTLS)
    GenerateArg(Consumer, OPT_femulated_tls);

  if (Opts.FPDenormalMode != llvm::DenormalMode::getIEEE())
    GenerateArg(Consumer, OPT_fdenormal_fp_math_EQ, Opts.FPDenormalMode.str());

  if ((Opts.FPDenormalMode != Opts.FP32DenormalMode) ||
      (Opts.FP32DenormalMode != llvm::DenormalMode::getIEEE()))
    GenerateArg(Consumer, OPT_fdenormal_fp_math_f32_EQ,
                Opts.FP32DenormalMode.str());

  if (Opts.StructReturnConvention == CodeGenOptions::SRCK_OnStack) {
    OptSpecifier Opt =
        T.isPPC32() ? OPT_maix_struct_return : OPT_fpcc_struct_return;
    GenerateArg(Consumer, Opt);
  } else if (Opts.StructReturnConvention == CodeGenOptions::SRCK_InRegs) {
    OptSpecifier Opt =
        T.isPPC32() ? OPT_msvr4_struct_return : OPT_freg_struct_return;
    GenerateArg(Consumer, Opt);
  }

  if (Opts.EnableAIXExtendedAltivecABI)
    GenerateArg(Consumer, OPT_mabi_EQ_vec_extabi);

  if (Opts.XCOFFReadOnlyPointers)
    GenerateArg(Consumer, OPT_mxcoff_roptr);

  if (!Opts.OptRecordPasses.empty())
    GenerateArg(Consumer, OPT_opt_record_passes, Opts.OptRecordPasses);

  if (!Opts.OptRecordFormat.empty())
    GenerateArg(Consumer, OPT_opt_record_format, Opts.OptRecordFormat);

  GenerateOptimizationRemark(Consumer, OPT_Rpass_EQ, "pass",
                             Opts.OptimizationRemark);

  GenerateOptimizationRemark(Consumer, OPT_Rpass_missed_EQ, "pass-missed",
                             Opts.OptimizationRemarkMissed);

  GenerateOptimizationRemark(Consumer, OPT_Rpass_analysis_EQ, "pass-analysis",
                             Opts.OptimizationRemarkAnalysis);

  GenerateArg(Consumer, OPT_fdiagnostics_hotness_threshold_EQ,
              Opts.DiagnosticsHotnessThreshold
                  ? Twine(*Opts.DiagnosticsHotnessThreshold)
                  : "auto");

  GenerateArg(Consumer, OPT_fdiagnostics_misexpect_tolerance_EQ,
              Twine(*Opts.DiagnosticsMisExpectTolerance));

  for (StringRef Sanitizer : serializeSanitizerKinds(Opts.SanitizeRecover))
    GenerateArg(Consumer, OPT_fsanitize_recover_EQ, Sanitizer);

  for (StringRef Sanitizer : serializeSanitizerKinds(Opts.SanitizeTrap))
    GenerateArg(Consumer, OPT_fsanitize_trap_EQ, Sanitizer);

  for (StringRef Sanitizer :
       serializeSanitizerKinds(Opts.SanitizeMergeHandlers))
    GenerateArg(Consumer, OPT_fsanitize_merge_handlers_EQ, Sanitizer);

  SmallVector<std::string, 4> Values;
  serializeSanitizerMaskCutoffs(Opts.SanitizeSkipHotCutoffs, Values);
  for (std::string Sanitizer : Values)
    GenerateArg(Consumer, OPT_fsanitize_skip_hot_cutoff_EQ, Sanitizer);

  if (Opts.AllowRuntimeCheckSkipHotCutoff) {
    GenerateArg(Consumer, OPT_fallow_runtime_check_skip_hot_cutoff_EQ,
                std::to_string(*Opts.AllowRuntimeCheckSkipHotCutoff));
  }

  for (StringRef Sanitizer :
       serializeSanitizerKinds(Opts.SanitizeAnnotateDebugInfo))
    GenerateArg(Consumer, OPT_fsanitize_annotate_debug_info_EQ, Sanitizer);

  if (!Opts.EmitVersionIdentMetadata)
    GenerateArg(Consumer, OPT_Qn);

  switch (Opts.FiniteLoops) {
  case CodeGenOptions::FiniteLoopsKind::Language:
    break;
  case CodeGenOptions::FiniteLoopsKind::Always:
    GenerateArg(Consumer, OPT_ffinite_loops);
    break;
  case CodeGenOptions::FiniteLoopsKind::Never:
    GenerateArg(Consumer, OPT_fno_finite_loops);
    break;
  }

  if (Opts.StaticClosure)
    GenerateArg(Consumer, OPT_static_libclosure);
}

bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
                                          InputKind IK,
                                          DiagnosticsEngine &Diags,
                                          const llvm::Triple &T,
                                          const std::string &OutputFile,
                                          const LangOptions &LangOptsRef) {
  unsigned NumErrorsBefore = Diags.getNumErrors();

  unsigned OptimizationLevel = getOptimizationLevel(Args, IK, Diags);
  // TODO: This could be done in Driver
  unsigned MaxOptLevel = 3;
  if (OptimizationLevel > MaxOptLevel) {
    // If the optimization level is not supported, fall back on the default
    // optimization
    Diags.Report(diag::warn_drv_optimization_value)
        << Args.getLastArg(OPT_O)->getAsString(Args) << "-O" << MaxOptLevel;
    OptimizationLevel = MaxOptLevel;
  }
  Opts.OptimizationLevel = OptimizationLevel;

  // The key paths of codegen options defined in Options.td start with
  // "CodeGenOpts.". Let's provide the expected variable name and type.
  CodeGenOptions &CodeGenOpts = Opts;
  // Some codegen options depend on language options. Let's provide the expected
  // variable name and type.
  const LangOptions *LangOpts = &LangOptsRef;

#define CODEGEN_OPTION_WITH_MARSHALLING(...)                                   \
  PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
#include "clang/Driver/Options.inc"
#undef CODEGEN_OPTION_WITH_MARSHALLING

  // At O0 we want to fully disable inlining outside of cases marked with
  // 'alwaysinline' that are required for correctness.
  if (Opts.OptimizationLevel == 0) {
    Opts.setInlining(CodeGenOptions::OnlyAlwaysInlining);
  } else if (const Arg *A = Args.getLastArg(options::OPT_finline_functions,
                                            options::OPT_finline_hint_functions,
                                            options::OPT_fno_inline_functions,
                                            options::OPT_fno_inline)) {
    // Explicit inlining flags can disable some or all inlining even at
    // optimization levels above zero.
    if (A->getOption().matches(options::OPT_finline_functions))
      Opts.setInlining(CodeGenOptions::NormalInlining);
    else if (A->getOption().matches(options::OPT_finline_hint_functions))
      Opts.setInlining(CodeGenOptions::OnlyHintInlining);
    else
      Opts.setInlining(CodeGenOptions::OnlyAlwaysInlining);
  } else {
    Opts.setInlining(CodeGenOptions::NormalInlining);
  }

  // PIC defaults to -fno-direct-access-external-data while non-PIC defaults to
  // -fdirect-access-external-data.
  Opts.DirectAccessExternalData =
      Args.hasArg(OPT_fdirect_access_external_data) ||
      (!Args.hasArg(OPT_fno_direct_access_external_data) &&
       LangOpts->PICLevel == 0);

  if (Arg *A = Args.getLastArg(OPT_debug_info_kind_EQ)) {
    unsigned Val =
        llvm::StringSwitch<unsigned>(A->getValue())
            .Case("line-tables-only", llvm::codegenoptions::DebugLineTablesOnly)
            .Case("line-directives-only",
                  llvm::codegenoptions::DebugDirectivesOnly)
            .Case("constructor", llvm::codegenoptions::DebugInfoConstructor)
            .Case("limited", llvm::codegenoptions::LimitedDebugInfo)
            .Case("standalone", llvm::codegenoptions::FullDebugInfo)
            .Case("unused-types", llvm::codegenoptions::UnusedTypeInfo)
            .Default(~0U);
    if (Val == ~0U)
      Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args)
                                                << A->getValue();
    else
      Opts.setDebugInfo(static_cast<llvm::codegenoptions::DebugInfoKind>(Val));
  }

  // If -fuse-ctor-homing is set and limited debug info is already on, then use
  // constructor homing, and vice versa for -fno-use-ctor-homing.
  if (const Arg *A =
          Args.getLastArg(OPT_fuse_ctor_homing, OPT_fno_use_ctor_homing)) {
    if (A->getOption().matches(OPT_fuse_ctor_homing) &&
        Opts.getDebugInfo() == llvm::codegenoptions::LimitedDebugInfo)
      Opts.setDebugInfo(llvm::codegenoptions::DebugInfoConstructor);
    if (A->getOption().matches(OPT_fno_use_ctor_homing) &&
        Opts.getDebugInfo() == llvm::codegenoptions::DebugInfoConstructor)
      Opts.setDebugInfo(llvm::codegenoptions::LimitedDebugInfo);
  }

  for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ)) {
    auto Split = StringRef(Arg).split('=');
    Opts.DebugPrefixMap.emplace_back(Split.first, Split.second);
  }

  for (const auto &Arg : Args.getAllArgValues(OPT_fcoverage_prefix_map_EQ)) {
    auto Split = StringRef(Arg).split('=');
    Opts.CoveragePrefixMap.emplace_back(Split.first, Split.second);
  }

  const llvm::Triple::ArchType DebugEntryValueArchs[] = {
      llvm::Triple::x86, llvm::Triple::x86_64, llvm::Triple::aarch64,
      llvm::Triple::arm, llvm::Triple::armeb, llvm::Triple::mips,
      llvm::Triple::mipsel, llvm::Triple::mips64, llvm::Triple::mips64el};

  if (Opts.OptimizationLevel > 0 && Opts.hasReducedDebugInfo() &&
      llvm::is_contained(DebugEntryValueArchs, T.getArch()))
    Opts.EmitCallSiteInfo = true;

  if (!Opts.EnableDIPreservationVerify && Opts.DIBugsReportFilePath.size()) {
    Diags.Report(diag::warn_ignoring_verify_debuginfo_preserve_export)
        << Opts.DIBugsReportFilePath;
    Opts.DIBugsReportFilePath = "";
  }

  Opts.NewStructPathTBAA = !Args.hasArg(OPT_no_struct_path_tbaa) &&
                           Args.hasArg(OPT_new_struct_path_tbaa);
  Opts.OptimizeSize = getOptimizationLevelSize(Args);
  Opts.SimplifyLibCalls = !LangOpts->NoBuiltin;
  if (Opts.SimplifyLibCalls)
    Opts.NoBuiltinFuncs = LangOpts->NoBuiltinFuncs;
  Opts.UnrollLoops =
      Args.hasFlag(OPT_funroll_loops, OPT_fno_unroll_loops,
                   (Opts.OptimizationLevel > 1));
  Opts.InterchangeLoops =
      Args.hasFlag(OPT_floop_interchange, OPT_fno_loop_interchange, false);
  Opts.BinutilsVersion =
      std::string(Args.getLastArgValue(OPT_fbinutils_version_EQ));

  Opts.DebugTemplateAlias = Args.hasArg(OPT_gtemplate_alias);

  Opts.DebugNameTable = static_cast<unsigned>(
      Args.hasArg(OPT_ggnu_pubnames)
          ? llvm::DICompileUnit::DebugNameTableKind::GNU
          : Args.hasArg(OPT_gpubnames)
                ? llvm::DICompileUnit::DebugNameTableKind::Default
                : llvm::DICompileUnit::DebugNameTableKind::None);
  if (const Arg *A = Args.getLastArg(OPT_gsimple_template_names_EQ)) {
    StringRef Value = A->getValue();
    if (Value != "simple" && Value != "mangled")
      Diags.Report(diag::err_drv_unsupported_option_argument)
          << A->getSpelling() << A->getValue();
    Opts.setDebugSimpleTemplateNames(
        StringRef(A->getValue()) == "simple"
            ? llvm::codegenoptions::DebugTemplateNamesKind::Simple
            : llvm::codegenoptions::DebugTemplateNamesKind::Mangled);
  }

  if (const Arg *A = Args.getLastArg(OPT_ftime_report, OPT_ftime_report_EQ,
                                     OPT_ftime_report_json)) {
    Opts.TimePasses = true;

    // -ftime-report= is only for new pass manager.
    if (const Arg *EQ = Args.getLastArg(OPT_ftime_report_EQ)) {
      StringRef Val = EQ->getValue();
      if (Val == "per-pass")
        Opts.TimePassesPerRun = false;
      else if (Val == "per-pass-run")
        Opts.TimePassesPerRun = true;
      else
        Diags.Report(diag::err_drv_invalid_value)
            << A->getAsString(Args) << A->getValue();
    }

    if (Args.getLastArg(OPT_ftime_report_json))
      Opts.TimePassesJson = true;
  }

  Opts.PrepareForLTO = false;
  Opts.PrepareForThinLTO = false;
  if (Arg *A = Args.getLastArg(OPT_flto_EQ)) {
    Opts.PrepareForLTO = true;
    StringRef S = A->getValue();
    if (S == "thin")
      Opts.PrepareForThinLTO = true;
    else if (S != "full")
      Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << S;
    if (Args.hasArg(OPT_funified_lto))
      Opts.PrepareForThinLTO = true;
  }
  if (Arg *A = Args.getLastArg(OPT_fthinlto_index_EQ)) {
    if (IK.getLanguage() != Language::LLVM_IR)
      Diags.Report(diag::err_drv_argument_only_allowed_with)
          << A->getAsString(Args) << "-x ir";
    Opts.ThinLTOIndexFile =
        std::string(Args.getLastArgValue(OPT_fthinlto_index_EQ));
  }
  if (Arg *A = Args.getLastArg(OPT_save_temps_EQ))
    Opts.SaveTempsFilePrefix =
        llvm::StringSwitch<std::string>(A->getValue())
            .Case("obj", OutputFile)
            .Default(llvm::sys::path::filename(OutputFile).str());

  // The memory profile runtime appends the pid to make this name more unique.
  const char *MemProfileBasename = "memprof.profraw";
  if (Args.hasArg(OPT_fmemory_profile_EQ)) {
    SmallString<128> Path(Args.getLastArgValue(OPT_fmemory_profile_EQ));
    llvm::sys::path::append(Path, MemProfileBasename);
    Opts.MemoryProfileOutput = std::string(Path);
  } else if (Args.hasArg(OPT_fmemory_profile))
    Opts.MemoryProfileOutput = MemProfileBasename;

  if (Opts.CoverageNotesFile.size() || Opts.CoverageDataFile.size()) {
    if (Args.hasArg(OPT_coverage_version_EQ)) {
      StringRef CoverageVersion = Args.getLastArgValue(OPT_coverage_version_EQ);
      if (CoverageVersion.size() != 4) {
        Diags.Report(diag::err_drv_invalid_value)
            << Args.getLastArg(OPT_coverage_version_EQ)->getAsString(Args)
            << CoverageVersion;
      } else {
        memcpy(Opts.CoverageVersion, CoverageVersion.data(), 4);
      }
    }
  }
  // FIXME: For backend options that are not yet recorded as function
  // attributes in the IR, keep track of them so we can embed them in a
  // separate data section and use them when building the bitcode.
  for (const auto &A : Args) {
    // Do not encode output and input.
    if (A->getOption().getID() == options::OPT_o ||
        A->getOption().getID() == options::OPT_INPUT ||
        A->getOption().getID() == options::OPT_x ||
        A->getOption().getID() == options::OPT_fembed_bitcode ||
        A->getOption().matches(options::OPT_W_Group))
      continue;
    ArgStringList ASL;
    A->render(Args, ASL);
    for (const auto &arg : ASL) {
      StringRef ArgStr(arg);
      llvm::append_range(Opts.CmdArgs, ArgStr);
      // using \00 to separate each commandline options.
      Opts.CmdArgs.push_back('\0');
    }
  }

  auto XRayInstrBundles =
      Args.getAllArgValues(OPT_fxray_instrumentation_bundle);
  if (XRayInstrBundles.empty())
    Opts.XRayInstrumentationBundle.Mask = XRayInstrKind::All;
  else
    for (const auto &A : XRayInstrBundles)
      parseXRayInstrumentationBundle("-fxray-instrumentation-bundle=", A, Args,
                                     Diags, Opts.XRayInstrumentationBundle);

  if (const Arg *A = Args.getLastArg(OPT_fcf_protection_EQ)) {
    StringRef Name = A->getValue();
    if (Name == "full") {
      Opts.CFProtectionReturn = 1;
      Opts.CFProtectionBranch = 1;
    } else if (Name == "return")
      Opts.CFProtectionReturn = 1;
    else if (Name == "branch")
      Opts.CFProtectionBranch = 1;
    else if (Name != "none")
      Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name;
  }

  if (Opts.CFProtectionBranch && T.isRISCV()) {
    if (const Arg *A = Args.getLastArg(OPT_mcf_branch_label_scheme_EQ)) {
      const auto Scheme =
          llvm::StringSwitch<CFBranchLabelSchemeKind>(A->getValue())
#define CF_BRANCH_LABEL_SCHEME(Kind, FlagVal)                                  \
  .Case(#FlagVal, CFBranchLabelSchemeKind::Kind)
#include "clang/Basic/CFProtectionOptions.def"
              .Default(CFBranchLabelSchemeKind::Default);
      if (Scheme != CFBranchLabelSchemeKind::Default)
        Opts.setCFBranchLabelScheme(Scheme);
      else
        Diags.Report(diag::err_drv_invalid_value)
            << A->getAsString(Args) << A->getValue();
    }
  }

  if (const Arg *A = Args.getLastArg(OPT_mfunction_return_EQ)) {
    auto Val = llvm::StringSwitch<llvm::FunctionReturnThunksKind>(A->getValue())
                   .Case("keep", llvm::FunctionReturnThunksKind::Keep)
                   .Case("thunk-extern", llvm::FunctionReturnThunksKind::Extern)
                   .Default(llvm::FunctionReturnThunksKind::Invalid);
    // SystemZ might want to add support for "expolines."
    if (!T.isX86())
      Diags.Report(diag::err_drv_argument_not_allowed_with)
          << A->getSpelling() << T.getTriple();
    else if (Val == llvm::FunctionReturnThunksKind::Invalid)
      Diags.Report(diag::err_drv_invalid_value)
          << A->getAsString(Args) << A->getValue();
    else if (Val == llvm::FunctionReturnThunksKind::Extern &&
             Args.getLastArgValue(OPT_mcmodel_EQ) == "large")
      Diags.Report(diag::err_drv_argument_not_allowed_with)
          << A->getAsString(Args)
          << Args.getLastArg(OPT_mcmodel_EQ)->getAsString(Args);
    else
      Opts.FunctionReturnThunks = static_cast<unsigned>(Val);
  }

  for (auto *A :
       Args.filtered(OPT_mlink_bitcode_file, OPT_mlink_builtin_bitcode)) {
    CodeGenOptions::BitcodeFileToLink F;
    F.Filename = A->getValue();
    if (A->getOption().matches(OPT_mlink_builtin_bitcode)) {
      F.LinkFlags = llvm::Linker::Flags::LinkOnlyNeeded;
      // When linking CUDA bitcode, propagate function attributes so that
      // e.g. libdevice gets fast-math attrs if we're building with fast-math.
      F.PropagateAttrs = true;
      F.Internalize = true;
    }
    Opts.LinkBitcodeFiles.push_back(F);
  }

  if (Arg *A = Args.getLastArg(OPT_fdenormal_fp_math_EQ)) {
    StringRef Val = A->getValue();
    Opts.FPDenormalMode = llvm::parseDenormalFPAttribute(Val);
    Opts.FP32DenormalMode = Opts.FPDenormalMode;
    if (!Opts.FPDenormalMode.isValid())
      Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;
  }

  if (Arg *A = Args.getLastArg(OPT_fdenormal_fp_math_f32_EQ)) {
    StringRef Val = A->getValue();
    Opts.FP32DenormalMode = llvm::parseDenormalFPAttribute(Val);
    if (!Opts.FP32DenormalMode.isValid())
      Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;
  }

  // X86_32 has -fppc-struct-return and -freg-struct-return.
  // PPC32 has -maix-struct-return and -msvr4-struct-return.
  if (Arg *A =
          Args.getLastArg(OPT_fpcc_struct_return, OPT_freg_struct_return,
                          OPT_maix_struct_return, OPT_msvr4_struct_return)) {
    // TODO: We might want to consider enabling these options on AIX in the
    // future.
    if (T.isOSAIX())
      Diags.Report(diag::err_drv_unsupported_opt_for_target)
          << A->getSpelling() << T.str();

    const Option &O = A->getOption();
    if (O.matches(OPT_fpcc_struct_return) ||
        O.matches(OPT_maix_struct_return)) {
      Opts.setStructReturnConvention(CodeGenOptions::SRCK_OnStack);
    } else {
      assert(O.matches(OPT_freg_struct_return) ||
             O.matches(OPT_msvr4_struct_return));
      Opts.setStructReturnConvention(CodeGenOptions::SRCK_InRegs);
    }
  }

  if (Arg *A = Args.getLastArg(OPT_mxcoff_roptr)) {
    if (!T.isOSAIX())
      Diags.Report(diag::err_drv_unsupported_opt_for_target)
          << A->getSpelling() << T.str();

    // Since the storage mapping class is specified per csect,
    // without using data sections, it is less effective to use read-only
    // pointers. Using read-only pointers may cause other RO variables in the
    // same csect to become RW when the linker acts upon `-bforceimprw`;
    // therefore, we require that separate data sections
    // are used when `-mxcoff-roptr` is in effect. We respect the setting of
    // data-sections since we have not found reasons to do otherwise that
    // overcome the user surprise of not respecting the setting.
    if (!Args.hasFlag(OPT_fdata_sections, OPT_fno_data_sections, false))
      Diags.Report(diag::err_roptr_requires_data_sections);

    Opts.XCOFFReadOnlyPointers = true;
  }

  if (Arg *A = Args.getLastArg(OPT_mabi_EQ_quadword_atomics)) {
    if (!T.isOSAIX() || T.isPPC32())
      Diags.Report(diag::err_drv_unsupported_opt_for_target)
        << A->getSpelling() << T.str();
  }

  bool NeedLocTracking = false;

  if (!Opts.OptRecordFile.empty())
    NeedLocTracking = true;

  if (Arg *A = Args.getLastArg(OPT_opt_record_passes)) {
    Opts.OptRecordPasses = A->getValue();
    NeedLocTracking = true;
  }

  if (Arg *A = Args.getLastArg(OPT_opt_record_format)) {
    Opts.OptRecordFormat = A->getValue();
    NeedLocTracking = true;
  }

  Opts.OptimizationRemark =
      ParseOptimizationRemark(Diags, Args, OPT_Rpass_EQ, "pass");

  Opts.OptimizationRemarkMissed =
      ParseOptimizationRemark(Diags, Args, OPT_Rpass_missed_EQ, "pass-missed");

  Opts.OptimizationRemarkAnalysis = ParseOptimizationRemark(
      Diags, Args, OPT_Rpass_analysis_EQ, "pass-analysis");

  NeedLocTracking |= Opts.OptimizationRemark.hasValidPattern() ||
                     Opts.OptimizationRemarkMissed.hasValidPattern() ||
                     Opts.OptimizationRemarkAnalysis.hasValidPattern();

  bool UsingSampleProfile = !Opts.SampleProfileFile.empty();
  bool UsingProfile =
      UsingSampleProfile || !Opts.ProfileInstrumentUsePath.empty();

  if (Opts.DiagnosticsWithHotness && !UsingProfile &&
      // An IR file will contain PGO as metadata
      IK.getLanguage() != Language::LLVM_IR)
    Diags.Report(diag::warn_drv_diagnostics_hotness_requires_pgo)
        << "-fdiagnostics-show-hotness";

  // Parse remarks hotness threshold. Valid value is either integer or 'auto'.
  if (auto *arg =
          Args.getLastArg(options::OPT_fdiagnostics_hotness_threshold_EQ)) {
    auto ResultOrErr =
        llvm::remarks::parseHotnessThresholdOption(arg->getValue());

    if (!ResultOrErr) {
      Diags.Report(diag::err_drv_invalid_diagnotics_hotness_threshold)
          << "-fdiagnostics-hotness-threshold=";
    } else {
      Opts.DiagnosticsHotnessThreshold = *ResultOrErr;
      if ((!Opts.DiagnosticsHotnessThreshold ||
           *Opts.DiagnosticsHotnessThreshold > 0) &&
          !UsingProfile)
        Diags.Report(diag::warn_drv_diagnostics_hotness_requires_pgo)
            << "-fdiagnostics-hotness-threshold=";
    }
  }

  if (auto *arg =
          Args.getLastArg(options::OPT_fdiagnostics_misexpect_tolerance_EQ)) {
    auto ResultOrErr = parseToleranceOption(arg->getValue());

    if (!ResultOrErr) {
      Diags.Report(diag::err_drv_invalid_diagnotics_misexpect_tolerance)
          << "-fdiagnostics-misexpect-tolerance=";
    } else {
      Opts.DiagnosticsMisExpectTolerance = *ResultOrErr;
      if ((!Opts.DiagnosticsMisExpectTolerance ||
           *Opts.DiagnosticsMisExpectTolerance > 0) &&
          !UsingProfile)
        Diags.Report(diag::warn_drv_diagnostics_misexpect_requires_pgo)
            << "-fdiagnostics-misexpect-tolerance=";
    }
  }

  // If the user requested to use a sample profile for PGO, then the
  // backend will need to track source location information so the profile
  // can be incorporated into the IR.
  if (UsingSampleProfile)
    NeedLocTracking = true;

  if (!Opts.StackUsageOutput.empty())
    NeedLocTracking = true;

  // If the user requested a flag that requires source locations available in
  // the backend, make sure that the backend tracks source location information.
  if (NeedLocTracking &&
      Opts.getDebugInfo() == llvm::codegenoptions::NoDebugInfo)
    Opts.setDebugInfo(llvm::codegenoptions::LocTrackingOnly);

  // Parse -fsanitize-recover= arguments.
  // FIXME: Report unrecoverable sanitizers incorrectly specified here.
  parseSanitizerKinds("-fsanitize-recover=",
                      Args.getAllArgValues(OPT_fsanitize_recover_EQ), Diags,
                      Opts.SanitizeRecover);
  parseSanitizerKinds("-fsanitize-trap=",
                      Args.getAllArgValues(OPT_fsanitize_trap_EQ), Diags,
                      Opts.SanitizeTrap);
  parseSanitizerKinds("-fsanitize-merge=",
                      Args.getAllArgValues(OPT_fsanitize_merge_handlers_EQ),
                      Diags, Opts.SanitizeMergeHandlers);

  // Parse -fsanitize-skip-hot-cutoff= arguments.
  Opts.SanitizeSkipHotCutoffs = parseSanitizerWeightedKinds(
      "-fsanitize-skip-hot-cutoff=",
      Args.getAllArgValues(OPT_fsanitize_skip_hot_cutoff_EQ), Diags);

  parseSanitizerKinds(
      "-fsanitize-annotate-debug-info=",
      Args.getAllArgValues(OPT_fsanitize_annotate_debug_info_EQ), Diags,
      Opts.SanitizeAnnotateDebugInfo);

  if (StringRef V =
          Args.getLastArgValue(OPT_fallow_runtime_check_skip_hot_cutoff_EQ);
      !V.empty()) {
    double A;
    if (V.getAsDouble(A) || A < 0.0 || A > 1.0) {
      Diags.Report(diag::err_drv_invalid_value)
          << "-fallow-runtime-check-skip-hot-cutoff=" << V;
    } else {
      Opts.AllowRuntimeCheckSkipHotCutoff = A;
    }
  }

  Opts.EmitVersionIdentMetadata = Args.hasFlag(OPT_Qy, OPT_Qn, true);

  if (!LangOpts->CUDAIsDevice)
    parsePointerAuthOptions(Opts.PointerAuth, *LangOpts, T, Diags);

  if (Args.hasArg(options::OPT_ffinite_loops))
    Opts.FiniteLoops = CodeGenOptions::FiniteLoopsKind::Always;
  else if (Args.hasArg(options::OPT_fno_finite_loops))
    Opts.FiniteLoops = CodeGenOptions::FiniteLoopsKind::Never;

  Opts.EmitIEEENaNCompliantInsts = Args.hasFlag(
      options::OPT_mamdgpu_ieee, options::OPT_mno_amdgpu_ieee, true);
  if (!Opts.EmitIEEENaNCompliantInsts && !LangOptsRef.NoHonorNaNs)
    Diags.Report(diag::err_drv_amdgpu_ieee_without_no_honor_nans);

  Opts.StaticClosure = Args.hasArg(options::OPT_static_libclosure);

  return Diags.getNumErrors() == NumErrorsBefore;
}

static void GenerateDependencyOutputArgs(const DependencyOutputOptions &Opts,
                                         ArgumentConsumer Consumer) {
  const DependencyOutputOptions &DependencyOutputOpts = Opts;
#define DEPENDENCY_OUTPUT_OPTION_WITH_MARSHALLING(...)                         \
  GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
#include "clang/Driver/Options.inc"
#undef DEPENDENCY_OUTPUT_OPTION_WITH_MARSHALLING

  if (Opts.ShowIncludesDest != ShowIncludesDestination::None)
    GenerateArg(Consumer, OPT_show_includes);

  for (const auto &Dep : Opts.ExtraDeps) {
    switch (Dep.second) {
    case EDK_SanitizeIgnorelist:
      // Sanitizer ignorelist arguments are generated from LanguageOptions.
      continue;
    case EDK_ModuleFile:
      // Module file arguments are generated from FrontendOptions and
      // HeaderSearchOptions.
      continue;
    case EDK_ProfileList:
      // Profile list arguments are generated from LanguageOptions via the
      // marshalling infrastructure.
      continue;
    case EDK_DepFileEntry:
      GenerateArg(Consumer, OPT_fdepfile_entry, Dep.first);
      break;
    }
  }
}

static bool ParseDependencyOutputArgs(DependencyOutputOptions &Opts,
                                      ArgList &Args, DiagnosticsEngine &Diags,
                                      frontend::ActionKind Action,
                                      bool ShowLineMarkers) {
  unsigned NumErrorsBefore = Diags.getNumErrors();

  DependencyOutputOptions &DependencyOutputOpts = Opts;
#define DEPENDENCY_OUTPUT_OPTION_WITH_MARSHALLING(...)                         \
  PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
#include "clang/Driver/Options.inc"
#undef DEPENDENCY_OUTPUT_OPTION_WITH_MARSHALLING

  if (Args.hasArg(OPT_show_includes)) {
    // Writing both /showIncludes and preprocessor output to stdout
    // would produce interleaved output, so use stderr for /showIncludes.
    // This behaves the same as cl.exe, when /E, /EP or /P are passed.
    if (Action == frontend::PrintPreprocessedInput || !ShowLineMarkers)
      Opts.ShowIncludesDest = ShowIncludesDestination::Stderr;
    else
      Opts.ShowIncludesDest = ShowIncludesDestination::Stdout;
  } else {
    Opts.ShowIncludesDest = ShowIncludesDestination::None;
  }

  // Add sanitizer ignorelists as extra dependencies.
  // They won't be discovered by the regular preprocessor, so
  // we let make / ninja to know about this implicit dependency.
  if (!Args.hasArg(OPT_fno_sanitize_ignorelist)) {
    for (const auto *A : Args.filtered(OPT_fsanitize_ignorelist_EQ)) {
      StringRef Val = A->getValue();
      if (!Val.contains('='))
        Opts.ExtraDeps.emplace_back(std::string(Val), EDK_SanitizeIgnorelist);
    }
    if (Opts.IncludeSystemHeaders) {
      for (const auto *A : Args.filtered(OPT_fsanitize_system_ignorelist_EQ)) {
        StringRef Val = A->getValue();
        if (!Val.contains('='))
          Opts.ExtraDeps.emplace_back(std::string(Val), EDK_SanitizeIgnorelist);
      }
    }
  }

  // -fprofile-list= dependencies.
  for (const auto &Filename : Args.getAllArgValues(OPT_fprofile_list_EQ))
    Opts.ExtraDeps.emplace_back(Filename, EDK_ProfileList);

  // Propagate the extra dependencies.
  for (const auto *A : Args.filtered(OPT_fdepfile_entry))
    Opts.ExtraDeps.emplace_back(A->getValue(), EDK_DepFileEntry);

  // Only the -fmodule-file=<file> form.
  for (const auto *A : Args.filtered(OPT_fmodule_file)) {
    StringRef Val = A->getValue();
    if (!Val.contains('='))
      Opts.ExtraDeps.emplace_back(std::string(Val), EDK_ModuleFile);
  }

  // Check for invalid combinations of header-include-format
  // and header-include-filtering.
  if (Opts.HeaderIncludeFormat == HIFMT_Textual &&
      Opts.HeaderIncludeFiltering != HIFIL_None) {
    if (Args.hasArg(OPT_header_include_format_EQ))
      Diags.Report(diag::err_drv_print_header_cc1_invalid_combination)
          << headerIncludeFormatKindToString(Opts.HeaderIncludeFormat)
          << headerIncludeFilteringKindToString(Opts.HeaderIncludeFiltering);
    else
      Diags.Report(diag::err_drv_print_header_cc1_invalid_filtering)
          << headerIncludeFilteringKindToString(Opts.HeaderIncludeFiltering);
  } else if (Opts.HeaderIncludeFormat == HIFMT_JSON &&
             Opts.HeaderIncludeFiltering == HIFIL_None) {
    if (Args.hasArg(OPT_header_include_filtering_EQ))
      Diags.Report(diag::err_drv_print_header_cc1_invalid_combination)
          << headerIncludeFormatKindToString(Opts.HeaderIncludeFormat)
          << headerIncludeFilteringKindToString(Opts.HeaderIncludeFiltering);
    else
      Diags.Report(diag::err_drv_print_header_cc1_invalid_format)
          << headerIncludeFormatKindToString(Opts.HeaderIncludeFormat);
  }

  return Diags.getNumErrors() == NumErrorsBefore;
}

static bool parseShowColorsArgs(const ArgList &Args, bool DefaultColor) {
  // Color diagnostics default to auto ("on" if terminal supports) in the driver
  // but default to off in cc1, needing an explicit OPT_fdiagnostics_color.
  // Support both clang's -f[no-]color-diagnostics and gcc's
  // -f[no-]diagnostics-colors[=never|always|auto].
  enum {
    Colors_On,
    Colors_Off,
    Colors_Auto
  } ShowColors = DefaultColor ? Colors_Auto : Colors_Off;
  for (auto *A : Args) {
    const Option &O = A->getOption();
    if (O.matches(options::OPT_fcolor_diagnostics)) {
      ShowColors = Colors_On;
    } else if (O.matches(options::OPT_fno_color_diagnostics)) {
      ShowColors = Colors_Off;
    } else if (O.matches(options::OPT_fdiagnostics_color_EQ)) {
      StringRef Value(A->getValue());
      if (Value == "always")
        ShowColors = Colors_On;
      else if (Value == "never")
        ShowColors = Colors_Off;
      else if (Value == "auto")
        ShowColors = Colors_Auto;
    }
  }
  return ShowColors == Colors_On ||
         (ShowColors == Colors_Auto &&
          llvm::sys::Process::StandardErrHasColors());
}

static bool checkVerifyPrefixes(const std::vector<std::string> &VerifyPrefixes,
                                DiagnosticsEngine &Diags) {
  bool Success = true;
  for (const auto &Prefix : VerifyPrefixes) {
    // Every prefix must start with a letter and contain only alphanumeric
    // characters, hyphens, and underscores.
    auto BadChar = llvm::find_if(Prefix, [](char C) {
      return !isAlphanumeric(C) && C != '-' && C != '_';
    });
    if (BadChar != Prefix.end() || !isLetter(Prefix[0])) {
      Success = false;
      Diags.Report(diag::err_drv_invalid_value) << "-verify=" << Prefix;
      Diags.Report(diag::note_drv_verify_prefix_spelling);
    }
  }
  return Success;
}

static void GenerateFileSystemArgs(const FileSystemOptions &Opts,
                                   ArgumentConsumer Consumer) {
  const FileSystemOptions &FileSystemOpts = Opts;

#define FILE_SYSTEM_OPTION_WITH_MARSHALLING(...)                               \
  GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
#include "clang/Driver/Options.inc"
#undef FILE_SYSTEM_OPTION_WITH_MARSHALLING
}

static bool ParseFileSystemArgs(FileSystemOptions &Opts, const ArgList &Args,
                                DiagnosticsEngine &Diags) {
  unsigned NumErrorsBefore = Diags.getNumErrors();

  FileSystemOptions &FileSystemOpts = Opts;

#define FILE_SYSTEM_OPTION_WITH_MARSHALLING(...)                               \
  PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
#include "clang/Driver/Options.inc"
#undef FILE_SYSTEM_OPTION_WITH_MARSHALLING

  return Diags.getNumErrors() == NumErrorsBefore;
}

static void GenerateMigratorArgs(const MigratorOptions &Opts,
                                 ArgumentConsumer Consumer) {
  const MigratorOptions &MigratorOpts = Opts;
#define MIGRATOR_OPTION_WITH_MARSHALLING(...)                                  \
  GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
#include "clang/Driver/Options.inc"
#undef MIGRATOR_OPTION_WITH_MARSHALLING
}

static bool ParseMigratorArgs(MigratorOptions &Opts, const ArgList &Args,
                              DiagnosticsEngine &Diags) {
  unsigned NumErrorsBefore = Diags.getNumErrors();

  MigratorOptions &MigratorOpts = Opts;

#define MIGRATOR_OPTION_WITH_MARSHALLING(...)                                  \
  PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
#include "clang/Driver/Options.inc"
#undef MIGRATOR_OPTION_WITH_MARSHALLING

  return Diags.getNumErrors() == NumErrorsBefore;
}

void CompilerInvocationBase::GenerateDiagnosticArgs(
    const DiagnosticOptions &Opts, ArgumentConsumer Consumer,
    bool DefaultDiagColor) {
  const DiagnosticOptions *DiagnosticOpts = &Opts;
#define DIAG_OPTION_WITH_MARSHALLING(...)                                      \
  GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
#include "clang/Driver/Options.inc"
#undef DIAG_OPTION_WITH_MARSHALLING

  if (!Opts.DiagnosticSerializationFile.empty())
    GenerateArg(Consumer, OPT_diagnostic_serialized_file,
                Opts.DiagnosticSerializationFile);

  if (Opts.ShowColors)
    GenerateArg(Consumer, OPT_fcolor_diagnostics);

  if (Opts.VerifyDiagnostics &&
      llvm::is_contained(Opts.VerifyPrefixes, "expected"))
    GenerateArg(Consumer, OPT_verify);

  for (const auto &Prefix : Opts.VerifyPrefixes)
    if (Prefix != "expected")
      GenerateArg(Consumer, OPT_verify_EQ, Prefix);

  DiagnosticLevelMask VIU = Opts.getVerifyIgnoreUnexpected();
  if (VIU == DiagnosticLevelMask::None) {
    // This is the default, don't generate anything.
  } else if (VIU == DiagnosticLevelMask::All) {
    GenerateArg(Consumer, OPT_verify_ignore_unexpected);
  } else {
    if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Note) != 0)
      GenerateArg(Consumer, OPT_verify_ignore_unexpected_EQ, "note");
    if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Remark) != 0)
      GenerateArg(Consumer, OPT_verify_ignore_unexpected_EQ, "remark");
    if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Warning) != 0)
      GenerateArg(Consumer, OPT_verify_ignore_unexpected_EQ, "warning");
    if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Error) != 0)
      GenerateArg(Consumer, OPT_verify_ignore_unexpected_EQ, "error");
  }

  for (const auto &Warning : Opts.Warnings) {
    // This option is automatically generated from UndefPrefixes.
    if (Warning == "undef-prefix")
      continue;
    // This option is automatically generated from CheckConstexprFunctionBodies.
    if (Warning == "invalid-constexpr" || Warning == "no-invalid-constexpr")
      continue;
    Consumer(StringRef("-W") + Warning);
  }

  for (const auto &Remark : Opts.Remarks) {
    // These arguments are generated from OptimizationRemark fields of
    // CodeGenOptions.
    StringRef IgnoredRemarks[] = {"pass",          "no-pass",
                                  "pass-analysis", "no-pass-analysis",
                                  "pass-missed",   "no-pass-missed"};
    if (llvm::is_contained(IgnoredRemarks, Remark))
      continue;

    Consumer(StringRef("-R") + Remark);
  }

  if (!Opts.DiagnosticSuppressionMappingsFile.empty()) {
    GenerateArg(Consumer, OPT_warning_suppression_mappings_EQ,
                Opts.DiagnosticSuppressionMappingsFile);
  }
}

std::unique_ptr<DiagnosticOptions>
clang::CreateAndPopulateDiagOpts(ArrayRef<const char *> Argv) {
  auto DiagOpts = std::make_unique<DiagnosticOptions>();
  unsigned MissingArgIndex, MissingArgCount;
  InputArgList Args = getDriverOptTable().ParseArgs(
      Argv.slice(1), MissingArgIndex, MissingArgCount);

  bool ShowColors = true;
  if (std::optional<std::string> NoColor =
          llvm::sys::Process::GetEnv("NO_COLOR");
      NoColor && !NoColor->empty()) {
    // If the user set the NO_COLOR environment variable, we'll honor that
    // unless the command line overrides it.
    ShowColors = false;
  }

  // We ignore MissingArgCount and the return value of ParseDiagnosticArgs.
  // Any errors that would be diagnosed here will also be diagnosed later,
  // when the DiagnosticsEngine actually exists.
  (void)ParseDiagnosticArgs(*DiagOpts, Args, /*Diags=*/nullptr, ShowColors);
  return DiagOpts;
}

bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
                                DiagnosticsEngine *Diags,
                                bool DefaultDiagColor) {
  std::optional<DiagnosticOptions> IgnoringDiagOpts;
  std::optional<DiagnosticsEngine> IgnoringDiags;
  if (!Diags) {
    IgnoringDiagOpts.emplace();
    IgnoringDiags.emplace(new DiagnosticIDs(), *IgnoringDiagOpts,
                          new IgnoringDiagConsumer());
    Diags = &*IgnoringDiags;
  }

  unsigned NumErrorsBefore = Diags->getNumErrors();

  // The key paths of diagnostic options defined in Options.td start with
  // "DiagnosticOpts->". Let's provide the expected variable name and type.
  DiagnosticOptions *DiagnosticOpts = &Opts;

#define DIAG_OPTION_WITH_MARSHALLING(...)                                      \
  PARSE_OPTION_WITH_MARSHALLING(Args, *Diags, __VA_ARGS__)
#include "clang/Driver/Options.inc"
#undef DIAG_OPTION_WITH_MARSHALLING

  llvm::sys::Process::UseANSIEscapeCodes(Opts.UseANSIEscapeCodes);

  if (Arg *A =
          Args.getLastArg(OPT_diagnostic_serialized_file, OPT__serialize_diags))
    Opts.DiagnosticSerializationFile = A->getValue();
  Opts.ShowColors = parseShowColorsArgs(Args, DefaultDiagColor);

  Opts.VerifyDiagnostics = Args.hasArg(OPT_verify) || Args.hasArg(OPT_verify_EQ);
  Opts.VerifyPrefixes = Args.getAllArgValues(OPT_verify_EQ);
  if (Args.hasArg(OPT_verify))
    Opts.VerifyPrefixes.push_back("expected");
  // Keep VerifyPrefixes in its original order for the sake of diagnostics, and
  // then sort it to prepare for fast lookup using std::binary_search.
  if (!checkVerifyPrefixes(Opts.VerifyPrefixes, *Diags))
    Opts.VerifyDiagnostics = false;
  else
    llvm::sort(Opts.VerifyPrefixes);
  DiagnosticLevelMask DiagMask = DiagnosticLevelMask::None;
  parseDiagnosticLevelMask(
      "-verify-ignore-unexpected=",
      Args.getAllArgValues(OPT_verify_ignore_unexpected_EQ), *Diags, DiagMask);
  if (Args.hasArg(OPT_verify_ignore_unexpected))
    DiagMask = DiagnosticLevelMask::All;
  Opts.setVerifyIgnoreUnexpected(DiagMask);
  if (Opts.TabStop == 0 || Opts.TabStop > DiagnosticOptions::MaxTabStop) {
    Diags->Report(diag::warn_ignoring_ftabstop_value)
        << Opts.TabStop << DiagnosticOptions::DefaultTabStop;
    Opts.TabStop = DiagnosticOptions::DefaultTabStop;
  }

  if (const Arg *A = Args.getLastArg(OPT_warning_suppression_mappings_EQ))
    Opts.DiagnosticSuppressionMappingsFile = A->getValue();

  addDiagnosticArgs(Args, OPT_W_Group, OPT_W_value_Group, Opts.Warnings);
  addDiagnosticArgs(Args, OPT_R_Group, OPT_R_value_Group, Opts.Remarks);

  return Diags->getNumErrors() == NumErrorsBefore;
}

/// Parse the argument to the -ftest-module-file-extension
/// command-line argument.
///
/// \returns true on error, false on success.
static bool parseTestModuleFileExtensionArg(StringRef Arg,
                                            std::string &BlockName,
                                            unsigned &MajorVersion,
                                            unsigned &MinorVersion,
                                            bool &Hashed,
                                            std::string &UserInfo) {
  SmallVector<StringRef, 5> Args;
  Arg.split(Args, ':', 5);
  if (Args.size() < 5)
    return true;

  BlockName = std::string(Args[0]);
  if (Args[1].getAsInteger(10, MajorVersion)) return true;
  if (Args[2].getAsInteger(10, MinorVersion)) return true;
  if (Args[3].getAsInteger(2, Hashed)) return true;
  if (Args.size() > 4)
    UserInfo = std::string(Args[4]);
  return false;
}

/// Return a table that associates command line option specifiers with the
/// frontend action. Note: The pair {frontend::PluginAction, OPT_plugin} is
/// intentionally missing, as this case is handled separately from other
/// frontend options.
static const auto &getFrontendActionTable() {
  static const std::pair<frontend::ActionKind, unsigned> Table[] = {
      {frontend::ASTDeclList, OPT_ast_list},

      {frontend::ASTDump, OPT_ast_dump_all_EQ},
      {frontend::ASTDump, OPT_ast_dump_all},
      {frontend::ASTDump, OPT_ast_dump_EQ},
      {frontend::ASTDump, OPT_ast_dump},
      {frontend::ASTDump, OPT_ast_dump_lookups},
      {frontend::ASTDump, OPT_ast_dump_decl_types},

      {frontend::ASTPrint, OPT_ast_print},
      {frontend::ASTView, OPT_ast_view},
      {frontend::DumpCompilerOptions, OPT_compiler_options_dump},
      {frontend::DumpRawTokens, OPT_dump_raw_tokens},
      {frontend::DumpTokens, OPT_dump_tokens},
      {frontend::EmitAssembly, OPT_S},
      {frontend::EmitBC, OPT_emit_llvm_bc},
      {frontend::EmitCIR, OPT_emit_cir},
      {frontend::EmitHTML, OPT_emit_html},
      {frontend::EmitLLVM, OPT_emit_llvm},
      {frontend::EmitLLVMOnly, OPT_emit_llvm_only},
      {frontend::EmitCodeGenOnly, OPT_emit_codegen_only},
      {frontend::EmitObj, OPT_emit_obj},
      {frontend::ExtractAPI, OPT_extract_api},

      {frontend::FixIt, OPT_fixit_EQ},
      {frontend::FixIt, OPT_fixit},

      {frontend::GenerateModule, OPT_emit_module},
      {frontend::GenerateModuleInterface, OPT_emit_module_interface},
      {frontend::GenerateReducedModuleInterface,
       OPT_emit_reduced_module_interface},
      {frontend::GenerateHeaderUnit, OPT_emit_header_unit},
      {frontend::GeneratePCH, OPT_emit_pch},
      {frontend::GenerateInterfaceStubs, OPT_emit_interface_stubs},
      {frontend::InitOnly, OPT_init_only},
      {frontend::ParseSyntaxOnly, OPT_fsyntax_only},
      {frontend::ModuleFileInfo, OPT_module_file_info},
      {frontend::VerifyPCH, OPT_verify_pch},
      {frontend::PrintPreamble, OPT_print_preamble},
      {frontend::PrintPreprocessedInput, OPT_E},
      {frontend::TemplightDump, OPT_templight_dump},
      {frontend::RewriteMacros, OPT_rewrite_macros},
      {frontend::RewriteObjC, OPT_rewrite_objc},
      {frontend::RewriteTest, OPT_rewrite_test},
      {frontend::RunAnalysis, OPT_analyze},
      {frontend::RunPreprocessorOnly, OPT_Eonly},
      {frontend::PrintDependencyDirectivesSourceMinimizerOutput,
       OPT_print_dependency_directives_minimized_source},
  };

  return Table;
}

/// Maps command line option to frontend action.
static std::optional<frontend::ActionKind>
getFrontendAction(OptSpecifier &Opt) {
  for (const auto &ActionOpt : getFrontendActionTable())
    if (ActionOpt.second == Opt.getID())
      return ActionOpt.first;

  return std::nullopt;
}

/// Maps frontend action to command line option.
static std::optional<OptSpecifier>
getProgramActionOpt(frontend::ActionKind ProgramAction) {
  for (const auto &ActionOpt : getFrontendActionTable())
    if (ActionOpt.first == ProgramAction)
      return OptSpecifier(ActionOpt.second);

  return std::nullopt;
}

static void GenerateFrontendArgs(const FrontendOptions &Opts,
                                 ArgumentConsumer Consumer, bool IsHeader) {
  const FrontendOptions &FrontendOpts = Opts;
#define FRONTEND_OPTION_WITH_MARSHALLING(...)                                  \
  GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
#include "clang/Driver/Options.inc"
#undef FRONTEND_OPTION_WITH_MARSHALLING

  std::optional<OptSpecifier> ProgramActionOpt =
      getProgramActionOpt(Opts.ProgramAction);

  // Generating a simple flag covers most frontend actions.
  std::function<void()> GenerateProgramAction = [&]() {
    GenerateArg(Consumer, *ProgramActionOpt);
  };

  if (!ProgramActionOpt) {
    // PluginAction is the only program action handled separately.
    assert(Opts.ProgramAction == frontend::PluginAction &&
           "Frontend action without option.");
    GenerateProgramAction = [&]() {
      GenerateArg(Consumer, OPT_plugin, Opts.ActionName);
    };
  }

  // FIXME: Simplify the complex 'AST dump' command line.
  if (Opts.ProgramAction == frontend::ASTDump) {
    GenerateProgramAction = [&]() {
      // ASTDumpLookups, ASTDumpDeclTypes and ASTDumpFilter are generated via
      // marshalling infrastructure.

      if (Opts.ASTDumpFormat != ADOF_Default) {
        StringRef Format;
        switch (Opts.ASTDumpFormat) {
        case ADOF_Default:
          llvm_unreachable("Default AST dump format.");
        case ADOF_JSON:
          Format = "json";
          break;
        }

        if (Opts.ASTDumpAll)
          GenerateArg(Consumer, OPT_ast_dump_all_EQ, Format);
        if (Opts.ASTDumpDecls)
          GenerateArg(Consumer, OPT_ast_dump_EQ, Format);
      } else {
        if (Opts.ASTDumpAll)
          GenerateArg(Consumer, OPT_ast_dump_all);
        if (Opts.ASTDumpDecls)
          GenerateArg(Consumer, OPT_ast_dump);
      }
    };
  }

  if (Opts.ProgramAction == frontend::FixIt && !Opts.FixItSuffix.empty()) {
    GenerateProgramAction = [&]() {
      GenerateArg(Consumer, OPT_fixit_EQ, Opts.FixItSuffix);
    };
  }

  GenerateProgramAction();

  for (const auto &PluginArgs : Opts.PluginArgs) {
    Option Opt = getDriverOptTable().getOption(OPT_plugin_arg);
    for (const auto &PluginArg : PluginArgs.second)
      denormalizeString(Consumer,
                        Opt.getPrefix() + Opt.getName() + PluginArgs.first,
                        Opt.getKind(), 0, PluginArg);
  }

  for (const auto &Ext : Opts.ModuleFileExtensions)
    if (auto *TestExt = dyn_cast_or_null<TestModuleFileExtension>(Ext.get()))
      GenerateArg(Consumer, OPT_ftest_module_file_extension_EQ, TestExt->str());

  if (!Opts.CodeCompletionAt.FileName.empty())
    GenerateArg(Consumer, OPT_code_completion_at,
                Opts.CodeCompletionAt.ToString());

  for (const auto &Plugin : Opts.Plugins)
    GenerateArg(Consumer, OPT_load, Plugin);

  // ASTDumpDecls and ASTDumpAll already handled with ProgramAction.

  for (const auto &ModuleFile : Opts.ModuleFiles)
    GenerateArg(Consumer, OPT_fmodule_file, ModuleFile);

  if (Opts.AuxTargetCPU)
    GenerateArg(Consumer, OPT_aux_target_cpu, *Opts.AuxTargetCPU);

  if (Opts.AuxTargetFeatures)
    for (const auto &Feature : *Opts.AuxTargetFeatures)
      GenerateArg(Consumer, OPT_aux_target_feature, Feature);

  {
    StringRef Preprocessed = Opts.DashX.isPreprocessed() ? "-cpp-output" : "";
    StringRef ModuleMap =
        Opts.DashX.getFormat() == InputKind::ModuleMap ? "-module-map" : "";
    StringRef HeaderUnit = "";
    switch (Opts.DashX.getHeaderUnitKind()) {
    case InputKind::HeaderUnit_None:
      break;
    case InputKind::HeaderUnit_User:
      HeaderUnit = "-user";
      break;
    case InputKind::HeaderUnit_System:
      HeaderUnit = "-system";
      break;
    case InputKind::HeaderUnit_Abs:
      HeaderUnit = "-header-unit";
      break;
    }
    StringRef Header = IsHeader ? "-header" : "";

    StringRef Lang;
    switch (Opts.DashX.getLanguage()) {
    case Language::C:
      Lang = "c";
      break;
    case Language::OpenCL:
      Lang = "cl";
      break;
    case Language::OpenCLCXX:
      Lang = "clcpp";
      break;
    case Language::CUDA:
      Lang = "cuda";
      break;
    case Language::HIP:
      Lang = "hip";
      break;
    case Language::CXX:
      Lang = "c++";
      break;
    case Language::ObjC:
      Lang = "objective-c";
      break;
    case Language::ObjCXX:
      Lang = "objective-c++";
      break;
    case Language::Asm:
      Lang = "assembler-with-cpp";
      break;
    case Language::Unknown:
      assert(Opts.DashX.getFormat() == InputKind::Precompiled &&
             "Generating -x argument for unknown language (not precompiled).");
      Lang = "ast";
      break;
    case Language::LLVM_IR:
      Lang = "ir";
      break;
    case Language::HLSL:
      Lang = "hlsl";
      break;
    case Language::CIR:
      Lang = "cir";
      break;
    }

    GenerateArg(Consumer, OPT_x,
                Lang + HeaderUnit + Header + ModuleMap + Preprocessed);
  }

  // OPT_INPUT has a unique class, generate it directly.
  for (const auto &Input : Opts.Inputs)
    Consumer(Input.getFile());
}

static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
                              DiagnosticsEngine &Diags, bool &IsHeaderFile) {
  unsigned NumErrorsBefore = Diags.getNumErrors();

  FrontendOptions &FrontendOpts = Opts;

#define FRONTEND_OPTION_WITH_MARSHALLING(...)                                  \
  PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
#include "clang/Driver/Options.inc"
#undef FRONTEND_OPTION_WITH_MARSHALLING

  Opts.ProgramAction = frontend::ParseSyntaxOnly;
  if (const Arg *A = Args.getLastArg(OPT_Action_Group)) {
    OptSpecifier Opt = OptSpecifier(A->getOption().getID());
    std::optional<frontend::ActionKind> ProgramAction = getFrontendAction(Opt);
    assert(ProgramAction && "Option specifier not in Action_Group.");

    if (ProgramAction == frontend::ASTDump &&
        (Opt == OPT_ast_dump_all_EQ || Opt == OPT_ast_dump_EQ)) {
      unsigned Val = llvm::StringSwitch<unsigned>(A->getValue())
                         .CaseLower("default", ADOF_Default)
                         .CaseLower("json", ADOF_JSON)
                         .Default(std::numeric_limits<unsigned>::max());

      if (Val != std::numeric_limits<unsigned>::max())
        Opts.ASTDumpFormat = static_cast<ASTDumpOutputFormat>(Val);
      else {
        Diags.Report(diag::err_drv_invalid_value)
            << A->getAsString(Args) << A->getValue();
        Opts.ASTDumpFormat = ADOF_Default;
      }
    }

    if (ProgramAction == frontend::FixIt && Opt == OPT_fixit_EQ)
      Opts.FixItSuffix = A->getValue();

    if (ProgramAction == frontend::GenerateInterfaceStubs) {
      StringRef ArgStr =
          Args.hasArg(OPT_interface_stub_version_EQ)
              ? Args.getLastArgValue(OPT_interface_stub_version_EQ)
              : "ifs-v1";
      if (ArgStr == "experimental-yaml-elf-v1" ||
          ArgStr == "experimental-ifs-v1" || ArgStr == "experimental-ifs-v2" ||
          ArgStr == "experimental-tapi-elf-v1") {
        std::string ErrorMessage =
            "Invalid interface stub format: " + ArgStr.str() +
            " is deprecated.";
        Diags.Report(diag::err_drv_invalid_value)
            << "Must specify a valid interface stub format type, ie: "
               "-interface-stub-version=ifs-v1"
            << ErrorMessage;
        ProgramAction = frontend::ParseSyntaxOnly;
      } else if (!ArgStr.starts_with("ifs-")) {
        std::string ErrorMessage =
            "Invalid interface stub format: " + ArgStr.str() + ".";
        Diags.Report(diag::err_drv_invalid_value)
            << "Must specify a valid interface stub format type, ie: "
               "-interface-stub-version=ifs-v1"
            << ErrorMessage;
        ProgramAction = frontend::ParseSyntaxOnly;
      }
    }

    Opts.ProgramAction = *ProgramAction;

    // Catch common mistakes when multiple actions are specified for cc1 (e.g.
    // -S -emit-llvm means -emit-llvm while -emit-llvm -S means -S). However, to
    // support driver `-c -Xclang ACTION` (-cc1 -emit-llvm file -main-file-name
    // X ACTION), we suppress the error when the two actions are separated by
    // -main-file-name.
    //
    // As an exception, accept composable -ast-dump*.
    if (!A->getSpelling().starts_with("-ast-dump")) {
      const Arg *SavedAction = nullptr;
      for (const Arg *AA :
           Args.filtered(OPT_Action_Group, OPT_main_file_name)) {
        if (AA->getOption().matches(OPT_main_file_name)) {
          SavedAction = nullptr;
        } else if (!SavedAction) {
          SavedAction = AA;
        } else {
          if (!A->getOption().matches(OPT_ast_dump_EQ))
            Diags.Report(diag::err_fe_invalid_multiple_actions)
                << SavedAction->getSpelling() << A->getSpelling();
          break;
        }
      }
    }
  }

  if (const Arg* A = Args.getLastArg(OPT_plugin)) {
    Opts.Plugins.emplace_back(A->getValue(0));
    Opts.ProgramAction = frontend::PluginAction;
    Opts.ActionName = A->getValue();
  }
  for (const auto *AA : Args.filtered(OPT_plugin_arg))
    Opts.PluginArgs[AA->getValue(0)].emplace_back(AA->getValue(1));

  for (const std::string &Arg :
         Args.getAllArgValues(OPT_ftest_module_file_extension_EQ)) {
    std::string BlockName;
    unsigned MajorVersion;
    unsigned MinorVersion;
    bool Hashed;
    std::string UserInfo;
    if (parseTestModuleFileExtensionArg(Arg, BlockName, MajorVersion,
                                        MinorVersion, Hashed, UserInfo)) {
      Diags.Report(diag::err_test_module_file_extension_format) << Arg;

      continue;
    }

    // Add the testing module file extension.
    Opts.ModuleFileExtensions.push_back(
        std::make_shared<TestModuleFileExtension>(
            BlockName, MajorVersion, MinorVersion, Hashed, UserInfo));
  }

  if (const Arg *A = Args.getLastArg(OPT_code_completion_at)) {
    Opts.CodeCompletionAt =
      ParsedSourceLocation::FromString(A->getValue());
    if (Opts.CodeCompletionAt.FileName.empty()) {
      Diags.Report(diag::err_drv_invalid_value)
          << A->getAsString(Args) << A->getValue();
      Diags.Report(diag::note_command_line_code_loc_requirement);
    }
  }

  Opts.Plugins = Args.getAllArgValues(OPT_load);
  Opts.ASTDumpDecls = Args.hasArg(OPT_ast_dump, OPT_ast_dump_EQ);
  Opts.ASTDumpAll = Args.hasArg(OPT_ast_dump_all, OPT_ast_dump_all_EQ);
  // Only the -fmodule-file=<file> form.
  for (const auto *A : Args.filtered(OPT_fmodule_file)) {
    StringRef Val = A->getValue();
    if (!Val.contains('='))
      Opts.ModuleFiles.push_back(std::string(Val));
  }

  if (Opts.ProgramAction != frontend::GenerateModule && Opts.IsSystemModule)
    Diags.Report(diag::err_drv_argument_only_allowed_with) << "-fsystem-module"
                                                           << "-emit-module";
  if (Args.hasArg(OPT_fclangir) || Args.hasArg(OPT_emit_cir))
    Opts.UseClangIRPipeline = true;

#if CLANG_ENABLE_CIR
  if (Args.hasArg(OPT_clangir_disable_passes))
    Opts.ClangIRDisablePasses = true;

  if (Args.hasArg(OPT_clangir_disable_verifier))
    Opts.ClangIRDisableCIRVerifier = true;
#endif // CLANG_ENABLE_CIR

  if (Args.hasArg(OPT_aux_target_cpu))
    Opts.AuxTargetCPU = std::string(Args.getLastArgValue(OPT_aux_target_cpu));
  if (Args.hasArg(OPT_aux_target_feature))
    Opts.AuxTargetFeatures = Args.getAllArgValues(OPT_aux_target_feature);

  InputKind DashX(Language::Unknown);
  if (const Arg *A = Args.getLastArg(OPT_x)) {
    StringRef XValue = A->getValue();

    // Parse suffixes:
    // '<lang>(-[{header-unit,user,system}-]header|[-module-map][-cpp-output])'.
    // FIXME: Supporting '<lang>-header-cpp-output' would be useful.
    bool Preprocessed = XValue.consume_back("-cpp-output");
    bool ModuleMap = XValue.consume_back("-module-map");
    // Detect and consume the header indicator.
    bool IsHeader =
        XValue != "precompiled-header" && XValue.consume_back("-header");

    // If we have c++-{user,system}-header, that indicates a header unit input
    // likewise, if the user put -fmodule-header together with a header with an
    // absolute path (header-unit-header).
    InputKind::HeaderUnitKind HUK = InputKind::HeaderUnit_None;
    if (IsHeader || Preprocessed) {
      if (XValue.consume_back("-header-unit"))
        HUK = InputKind::HeaderUnit_Abs;
      else if (XValue.consume_back("-system"))
        HUK = InputKind::HeaderUnit_System;
      else if (XValue.consume_back("-user"))
        HUK = InputKind::HeaderUnit_User;
    }

    // The value set by this processing is an un-preprocessed source which is
    // not intended to be a module map or header unit.
    IsHeaderFile = IsHeader && !Preprocessed && !ModuleMap &&
                   HUK == InputKind::HeaderUnit_None;

    // Principal languages.
    DashX = llvm::StringSwitch<InputKind>(XValue)
                .Case("c", Language::C)
                .Case("cl", Language::OpenCL)
                .Case("clcpp", Language::OpenCLCXX)
                .Case("cuda", Language::CUDA)
                .Case("hip", Language::HIP)
                .Case("c++", Language::CXX)
                .Case("objective-c", Language::ObjC)
                .Case("objective-c++", Language::ObjCXX)
                .Case("hlsl", Language::HLSL)
                .Default(Language::Unknown);

    // "objc[++]-cpp-output" is an acceptable synonym for
    // "objective-c[++]-cpp-output".
    if (DashX.isUnknown() && Preprocessed && !IsHeaderFile && !ModuleMap &&
        HUK == InputKind::HeaderUnit_None)
      DashX = llvm::StringSwitch<InputKind>(XValue)
                  .Case("objc", Language::ObjC)
                  .Case("objc++", Language::ObjCXX)
                  .Default(Language::Unknown);

    // Some special cases cannot be combined with suffixes.
    if (DashX.isUnknown() && !Preprocessed && !IsHeaderFile && !ModuleMap &&
        HUK == InputKind::HeaderUnit_None)
      DashX = llvm::StringSwitch<InputKind>(XValue)
                  .Case("cpp-output", InputKind(Language::C).getPreprocessed())
                  .Case("assembler-with-cpp", Language::Asm)
                  .Cases("ast", "pcm", "precompiled-header",
                         InputKind(Language::Unknown, InputKind::Precompiled))
                  .Case("ir", Language::LLVM_IR)
                  .Case("cir", Language::CIR)
                  .Default(Language::Unknown);

    if (DashX.isUnknown())
      Diags.Report(diag::err_drv_invalid_value)
        << A->getAsString(Args) << A->getValue();

    if (Preprocessed)
      DashX = DashX.getPreprocessed();
    // A regular header is considered mutually exclusive with a header unit.
    if (HUK != InputKind::HeaderUnit_None) {
      DashX = DashX.withHeaderUnit(HUK);
      IsHeaderFile = true;
    } else if (IsHeaderFile)
      DashX = DashX.getHeader();
    if (ModuleMap)
      DashX = DashX.withFormat(InputKind::ModuleMap);
  }

  // '-' is the default input if none is given.
  std::vector<std::string> Inputs = Args.getAllArgValues(OPT_INPUT);
  Opts.Inputs.clear();
  if (Inputs.empty())
    Inputs.push_back("-");

  if (DashX.getHeaderUnitKind() != InputKind::HeaderUnit_None &&
      Inputs.size() > 1)
    Diags.Report(diag::err_drv_header_unit_extra_inputs) << Inputs[1];

  for (unsigned i = 0, e = Inputs.size(); i != e; ++i) {
    InputKind IK = DashX;
    if (IK.isUnknown()) {
      IK = FrontendOptions::getInputKindForExtension(
        StringRef(Inputs[i]).rsplit('.').second);
      // FIXME: Warn on this?
      if (IK.isUnknown())
        IK = Language::C;
      // FIXME: Remove this hack.
      if (i == 0)
        DashX = IK;
    }

    bool IsSystem = false;

    // The -emit-module action implicitly takes a module map.
    if (Opts.ProgramAction == frontend::GenerateModule &&
        IK.getFormat() == InputKind::Source) {
      IK = IK.withFormat(InputKind::ModuleMap);
      IsSystem = Opts.IsSystemModule;
    }

    Opts.Inputs.emplace_back(std::move(Inputs[i]), IK, IsSystem);
  }

  Opts.DashX = DashX;

  return Diags.getNumErrors() == NumErrorsBefore;
}

std::string CompilerInvocation::GetResourcesPath(const char *Argv0,
                                                 void *MainAddr) {
  std::string ClangExecutable =
      llvm::sys::fs::getMainExecutable(Argv0, MainAddr);
  return Driver::GetResourcesPath(ClangExecutable);
}

static void GenerateHeaderSearchArgs(const HeaderSearchOptions &Opts,
                                     ArgumentConsumer Consumer) {
  const HeaderSearchOptions *HeaderSearchOpts = &Opts;
#define HEADER_SEARCH_OPTION_WITH_MARSHALLING(...)                             \
  GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
#include "clang/Driver/Options.inc"
#undef HEADER_SEARCH_OPTION_WITH_MARSHALLING

  if (Opts.UseLibcxx)
    GenerateArg(Consumer, OPT_stdlib_EQ, "libc++");

  if (!Opts.ModuleCachePath.empty())
    GenerateArg(Consumer, OPT_fmodules_cache_path, Opts.ModuleCachePath);

  for (const auto &File : Opts.PrebuiltModuleFiles)
    GenerateArg(Consumer, OPT_fmodule_file, File.first + "=" + File.second);

  for (const auto &Path : Opts.PrebuiltModulePaths)
    GenerateArg(Consumer, OPT_fprebuilt_module_path, Path);

  for (const auto &Macro : Opts.ModulesIgnoreMacros)
    GenerateArg(Consumer, OPT_fmodules_ignore_macro, Macro.val());

  auto Matches = [](const HeaderSearchOptions::Entry &Entry,
                    llvm::ArrayRef<frontend::IncludeDirGroup> Groups,
                    std::optional<bool> IsFramework,
                    std::optional<bool> IgnoreSysRoot) {
    return llvm::is_contained(Groups, Entry.Group) &&
           (!IsFramework || (Entry.IsFramework == *IsFramework)) &&
           (!IgnoreSysRoot || (Entry.IgnoreSysRoot == *IgnoreSysRoot));
  };

  auto It = Opts.UserEntries.begin();
  auto End = Opts.UserEntries.end();

  // Add -I... and -F... options in order.
  for (; It < End && Matches(*It, {frontend::Angled}, std::nullopt, true);
       ++It) {
    OptSpecifier Opt = [It, Matches]() {
      if (Matches(*It, frontend::Angled, true, true))
        return OPT_F;
      if (Matches(*It, frontend::Angled, false, true))
        return OPT_I;
      llvm_unreachable("Unexpected HeaderSearchOptions::Entry.");
    }();

    GenerateArg(Consumer, Opt, It->Path);
  }

  // Note: some paths that came from "[-iprefix=xx] -iwithprefixbefore=yy" may
  // have already been generated as "-I[xx]yy". If that's the case, their
  // position on command line was such that this has no semantic impact on
  // include paths.
  for (; It < End &&
         Matches(*It, {frontend::After, frontend::Angled}, false, true);
       ++It) {
    OptSpecifier Opt =
        It->Group == frontend::After ? OPT_iwithprefix : OPT_iwithprefixbefore;
    GenerateArg(Consumer, Opt, It->Path);
  }

  // Note: Some paths that came from "-idirafter=xxyy" may have already been
  // generated as "-iwithprefix=xxyy". If that's the case, their position on
  // command line was such that this has no semantic impact on include paths.
  for (; It < End && Matches(*It, {frontend::After}, false, true); ++It)
    GenerateArg(Consumer, OPT_idirafter, It->Path);
  for (; It < End && Matches(*It, {frontend::Quoted}, false, true); ++It)
    GenerateArg(Consumer, OPT_iquote, It->Path);
  for (; It < End && Matches(*It, {frontend::System}, false, std::nullopt);
       ++It)
    GenerateArg(Consumer, It->IgnoreSysRoot ? OPT_isystem : OPT_iwithsysroot,
                It->Path);
  for (; It < End && Matches(*It, {frontend::System}, true, true); ++It)
    GenerateArg(Consumer, OPT_iframework, It->Path);
  for (; It < End && Matches(*It, {frontend::System}, true, false); ++It)
    GenerateArg(Consumer, OPT_iframeworkwithsysroot, It->Path);

  // Add the paths for the various language specific isystem flags.
  for (; It < End && Matches(*It, {frontend::CSystem}, false, true); ++It)
    GenerateArg(Consumer, OPT_c_isystem, It->Path);
  for (; It < End && Matches(*It, {frontend::CXXSystem}, false, true); ++It)
    GenerateArg(Consumer, OPT_cxx_isystem, It->Path);
  for (; It < End && Matches(*It, {frontend::ObjCSystem}, false, true); ++It)
    GenerateArg(Consumer, OPT_objc_isystem, It->Path);
  for (; It < End && Matches(*It, {frontend::ObjCXXSystem}, false, true); ++It)
    GenerateArg(Consumer, OPT_objcxx_isystem, It->Path);

  // Add the internal paths from a driver that detects standard include paths.
  // Note: Some paths that came from "-internal-isystem" arguments may have
  // already been generated as "-isystem". If that's the case, their position on
  // command line was such that this has no semantic impact on include paths.
  for (; It < End &&
         Matches(*It, {frontend::System, frontend::ExternCSystem}, false, true);
       ++It) {
    OptSpecifier Opt = It->Group == frontend::System
                           ? OPT_internal_isystem
                           : OPT_internal_externc_isystem;
    GenerateArg(Consumer, Opt, It->Path);
  }
  for (; It < End && Matches(*It, {frontend::System}, true, true); ++It)
    GenerateArg(Consumer, OPT_internal_iframework, It->Path);

  assert(It == End && "Unhandled HeaderSearchOption::Entry.");

  // Add the path prefixes which are implicitly treated as being system headers.
  for (const auto &P : Opts.SystemHeaderPrefixes) {
    OptSpecifier Opt = P.IsSystemHeader ? OPT_system_header_prefix
                                        : OPT_no_system_header_prefix;
    GenerateArg(Consumer, Opt, P.Prefix);
  }

  for (const std::string &F : Opts.VFSOverlayFiles)
    GenerateArg(Consumer, OPT_ivfsoverlay, F);
}

static bool ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args,
                                  DiagnosticsEngine &Diags,
                                  const std::string &WorkingDir) {
  unsigned NumErrorsBefore = Diags.getNumErrors();

  HeaderSearchOptions *HeaderSearchOpts = &Opts;

#define HEADER_SEARCH_OPTION_WITH_MARSHALLING(...)                             \
  PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
#include "clang/Driver/Options.inc"
#undef HEADER_SEARCH_OPTION_WITH_MARSHALLING

  if (const Arg *A = Args.getLastArg(OPT_stdlib_EQ))
    Opts.UseLibcxx = (strcmp(A->getValue(), "libc++") == 0);

  // Canonicalize -fmodules-cache-path before storing it.
  SmallString<128> P(Args.getLastArgValue(OPT_fmodules_cache_path));
  if (!(P.empty() || llvm::sys::path::is_absolute(P))) {
    if (WorkingDir.empty())
      llvm::sys::fs::make_absolute(P);
    else
      llvm::sys::fs::make_absolute(WorkingDir, P);
  }
  llvm::sys::path::remove_dots(P);
  Opts.ModuleCachePath = std::string(P);

  // Only the -fmodule-file=<name>=<file> form.
  for (const auto *A : Args.filtered(OPT_fmodule_file)) {
    StringRef Val = A->getValue();
    if (Val.contains('=')) {
      auto Split = Val.split('=');
      Opts.PrebuiltModuleFiles.insert_or_assign(
          std::string(Split.first), std::string(Split.second));
    }
  }
  for (const auto *A : Args.filtered(OPT_fprebuilt_module_path))
    Opts.AddPrebuiltModulePath(A->getValue());

  for (const auto *A : Args.filtered(OPT_fmodules_ignore_macro)) {
    StringRef MacroDef = A->getValue();
    Opts.ModulesIgnoreMacros.insert(
        llvm::CachedHashString(MacroDef.split('=').first));
  }

  // Add -I... and -F... options in order.
  bool IsSysrootSpecified =
      Args.hasArg(OPT__sysroot_EQ) || Args.hasArg(OPT_isysroot);

  // Expand a leading `=` to the sysroot if one was passed (and it's not a
  // framework flag).
  auto PrefixHeaderPath = [IsSysrootSpecified,
                           &Opts](const llvm::opt::Arg *A,
                                  bool IsFramework = false) -> std::string {
    assert(A->getNumValues() && "Unexpected empty search path flag!");
    if (IsSysrootSpecified && !IsFramework && A->getValue()[0] == '=') {
      SmallString<32> Buffer;
      llvm::sys::path::append(Buffer, Opts.Sysroot,
                              llvm::StringRef(A->getValue()).substr(1));
      return std::string(Buffer);
    }
    return A->getValue();
  };

  for (const auto *A : Args.filtered(OPT_I, OPT_F)) {
    bool IsFramework = A->getOption().matches(OPT_F);
    Opts.AddPath(PrefixHeaderPath(A, IsFramework), frontend::Angled,
                 IsFramework, /*IgnoreSysroot=*/true);
  }

  // Add -iprefix/-iwithprefix/-iwithprefixbefore options.
  StringRef Prefix = ""; // FIXME: This isn't the correct default prefix.
  for (const auto *A :
       Args.filtered(OPT_iprefix, OPT_iwithprefix, OPT_iwithprefixbefore)) {
    if (A->getOption().matches(OPT_iprefix))
      Prefix = A->getValue();
    else if (A->getOption().matches(OPT_iwithprefix))
      Opts.AddPath(Prefix.str() + A->getValue(), frontend::After, false, true);
    else
      Opts.AddPath(Prefix.str() + A->getValue(), frontend::Angled, false, true);
  }

  for (const auto *A : Args.filtered(OPT_idirafter))
    Opts.AddPath(PrefixHeaderPath(A), frontend::After, false, true);
  for (const auto *A : Args.filtered(OPT_iquote))
    Opts.AddPath(PrefixHeaderPath(A), frontend::Quoted, false, true);

  for (const auto *A : Args.filtered(OPT_isystem, OPT_iwithsysroot)) {
    if (A->getOption().matches(OPT_iwithsysroot)) {
      Opts.AddPath(A->getValue(), frontend::System, false,
                   /*IgnoreSysRoot=*/false);
      continue;
    }
    Opts.AddPath(PrefixHeaderPath(A), frontend::System, false, true);
  }
  for (const auto *A : Args.filtered(OPT_iframework))
    Opts.AddPath(A->getValue(), frontend::System, true, true);
  for (const auto *A : Args.filtered(OPT_iframeworkwithsysroot))
    Opts.AddPath(A->getValue(), frontend::System, /*IsFramework=*/true,
                 /*IgnoreSysRoot=*/false);

  // Add the paths for the various language specific isystem flags.
  for (const auto *A : Args.filtered(OPT_c_isystem))
    Opts.AddPath(A->getValue(), frontend::CSystem, false, true);
  for (const auto *A : Args.filtered(OPT_cxx_isystem))
    Opts.AddPath(A->getValue(), frontend::CXXSystem, false, true);
  for (const auto *A : Args.filtered(OPT_objc_isystem))
    Opts.AddPath(A->getValue(), frontend::ObjCSystem, false,true);
  for (const auto *A : Args.filtered(OPT_objcxx_isystem))
    Opts.AddPath(A->getValue(), frontend::ObjCXXSystem, false, true);

  // Add the internal paths from a driver that detects standard include paths.
  for (const auto *A :
       Args.filtered(OPT_internal_isystem, OPT_internal_externc_isystem)) {
    frontend::IncludeDirGroup Group = frontend::System;
    if (A->getOption().matches(OPT_internal_externc_isystem))
      Group = frontend::ExternCSystem;
    Opts.AddPath(A->getValue(), Group, false, true);
  }
  for (const auto *A : Args.filtered(OPT_internal_iframework))
    Opts.AddPath(A->getValue(), frontend::System, true, true);

  // Add the path prefixes which are implicitly treated as being system headers.
  for (const auto *A :
       Args.filtered(OPT_system_header_prefix, OPT_no_system_header_prefix))
    Opts.AddSystemHeaderPrefix(
        A->getValue(), A->getOption().matches(OPT_system_header_prefix));

  for (const auto *A : Args.filtered(OPT_ivfsoverlay, OPT_vfsoverlay))
    Opts.AddVFSOverlayFile(A->getValue());

  return Diags.getNumErrors() == NumErrorsBefore;
}

static void GenerateAPINotesArgs(const APINotesOptions &Opts,
                                 ArgumentConsumer Consumer) {
  if (!Opts.SwiftVersion.empty())
    GenerateArg(Consumer, OPT_fapinotes_swift_version,
                Opts.SwiftVersion.getAsString());

  for (const auto &Path : Opts.ModuleSearchPaths)
    GenerateArg(Consumer, OPT_iapinotes_modules, Path);
}

static void ParseAPINotesArgs(APINotesOptions &Opts, ArgList &Args,
                              DiagnosticsEngine &diags) {
  if (const Arg *A = Args.getLastArg(OPT_fapinotes_swift_version)) {
    if (Opts.SwiftVersion.tryParse(A->getValue()))
      diags.Report(diag::err_drv_invalid_value)
          << A->getAsString(Args) << A->getValue();
  }
  for (const Arg *A : Args.filtered(OPT_iapinotes_modules))
    Opts.ModuleSearchPaths.push_back(A->getValue());
}

static void GeneratePointerAuthArgs(const LangOptions &Opts,
                                    ArgumentConsumer Consumer) {
  if (Opts.PointerAuthIntrinsics)
    GenerateArg(Consumer, OPT_fptrauth_intrinsics);
  if (Opts.PointerAuthCalls)
    GenerateArg(Consumer, OPT_fptrauth_calls);
  if (Opts.PointerAuthReturns)
    GenerateArg(Consumer, OPT_fptrauth_returns);
  if (Opts.PointerAuthIndirectGotos)
    GenerateArg(Consumer, OPT_fptrauth_indirect_gotos);
  if (Opts.PointerAuthAuthTraps)
    GenerateArg(Consumer, OPT_fptrauth_auth_traps);
  if (Opts.PointerAuthVTPtrAddressDiscrimination)
    GenerateArg(Consumer, OPT_fptrauth_vtable_pointer_address_discrimination);
  if (Opts.PointerAuthVTPtrTypeDiscrimination)
    GenerateArg(Consumer, OPT_fptrauth_vtable_pointer_type_discrimination);
  if (Opts.PointerAuthTypeInfoVTPtrDiscrimination)
    GenerateArg(Consumer, OPT_fptrauth_type_info_vtable_pointer_discrimination);
  if (Opts.PointerAuthFunctionTypeDiscrimination)
    GenerateArg(Consumer, OPT_fptrauth_function_pointer_type_discrimination);
  if (Opts.PointerAuthInitFini)
    GenerateArg(Consumer, OPT_fptrauth_init_fini);
  if (Opts.PointerAuthInitFiniAddressDiscrimination)
    GenerateArg(Consumer, OPT_fptrauth_init_fini_address_discrimination);
  if (Opts.PointerAuthELFGOT)
    GenerateArg(Consumer, OPT_fptrauth_elf_got);
  if (Opts.AArch64JumpTableHardening)
    GenerateArg(Consumer, OPT_faarch64_jump_table_hardening);
  if (Opts.PointerAuthObjcIsa)
    GenerateArg(Consumer, OPT_fptrauth_objc_isa);
  if (Opts.PointerAuthObjcInterfaceSel)
    GenerateArg(Consumer, OPT_fptrauth_objc_interface_sel);
  if (Opts.PointerAuthObjcClassROPointers)
    GenerateArg(Consumer, OPT_fptrauth_objc_class_ro);
}

static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args,
                                 DiagnosticsEngine &Diags) {
  Opts.PointerAuthIntrinsics = Args.hasArg(OPT_fptrauth_intrinsics);
  Opts.PointerAuthCalls = Args.hasArg(OPT_fptrauth_calls);
  Opts.PointerAuthReturns = Args.hasArg(OPT_fptrauth_returns);
  Opts.PointerAuthIndirectGotos = Args.hasArg(OPT_fptrauth_indirect_gotos);
  Opts.PointerAuthAuthTraps = Args.hasArg(OPT_fptrauth_auth_traps);
  Opts.PointerAuthVTPtrAddressDiscrimination =
      Args.hasArg(OPT_fptrauth_vtable_pointer_address_discrimination);
  Opts.PointerAuthVTPtrTypeDiscrimination =
      Args.hasArg(OPT_fptrauth_vtable_pointer_type_discrimination);
  Opts.PointerAuthTypeInfoVTPtrDiscrimination =
      Args.hasArg(OPT_fptrauth_type_info_vtable_pointer_discrimination);
  Opts.PointerAuthFunctionTypeDiscrimination =
      Args.hasArg(OPT_fptrauth_function_pointer_type_discrimination);
  Opts.PointerAuthInitFini = Args.hasArg(OPT_fptrauth_init_fini);
  Opts.PointerAuthInitFiniAddressDiscrimination =
      Args.hasArg(OPT_fptrauth_init_fini_address_discrimination);
  Opts.PointerAuthELFGOT = Args.hasArg(OPT_fptrauth_elf_got);
  Opts.AArch64JumpTableHardening =
      Args.hasArg(OPT_faarch64_jump_table_hardening);

  Opts.PointerAuthObjcIsa = Args.hasArg(OPT_fptrauth_objc_isa);
  Opts.PointerAuthObjcClassROPointers = Args.hasArg(OPT_fptrauth_objc_class_ro);
  Opts.PointerAuthObjcInterfaceSel =
      Args.hasArg(OPT_fptrauth_objc_interface_sel);

  if (Opts.PointerAuthObjcInterfaceSel)
    Opts.PointerAuthObjcInterfaceSelKey =
        static_cast<unsigned>(PointerAuthSchema::ARM8_3Key::ASDB);
}

/// Check if input file kind and language standard are compatible.
static bool IsInputCompatibleWithStandard(InputKind IK,
                                          const LangStandard &S) {
  switch (IK.getLanguage()) {
  case Language::Unknown:
  case Language::LLVM_IR:
  case Language::CIR:
    llvm_unreachable("should not parse language flags for this input");

  case Language::C:
  case Language::ObjC:
    return S.getLanguage() == Language::C;

  case Language::OpenCL:
    return S.getLanguage() == Language::OpenCL ||
           S.getLanguage() == Language::OpenCLCXX;

  case Language::OpenCLCXX:
    return S.getLanguage() == Language::OpenCLCXX;

  case Language::CXX:
  case Language::ObjCXX:
    return S.getLanguage() == Language::CXX;

  case Language::CUDA:
    // FIXME: What -std= values should be permitted for CUDA compilations?
    return S.getLanguage() == Language::CUDA ||
           S.getLanguage() == Language::CXX;

  case Language::HIP:
    return S.getLanguage() == Language::CXX || S.getLanguage() == Language::HIP;

  case Language::Asm:
    // Accept (and ignore) all -std= values.
    // FIXME: The -std= value is not ignored; it affects the tokenization
    // and preprocessing rules if we're preprocessing this asm input.
    return true;

  case Language::HLSL:
    return S.getLanguage() == Language::HLSL;
  }

  llvm_unreachable("unexpected input language");
}

/// Get language name for given input kind.
static StringRef GetInputKindName(InputKind IK) {
  switch (IK.getLanguage()) {
  case Language::C:
    return "C";
  case Language::ObjC:
    return "Objective-C";
  case Language::CXX:
    return "C++";
  case Language::ObjCXX:
    return "Objective-C++";
  case Language::OpenCL:
    return "OpenCL";
  case Language::OpenCLCXX:
    return "C++ for OpenCL";
  case Language::CUDA:
    return "CUDA";
  case Language::HIP:
    return "HIP";

  case Language::Asm:
    return "Asm";
  case Language::LLVM_IR:
    return "LLVM IR";
  case Language::CIR:
    return "Clang IR";

  case Language::HLSL:
    return "HLSL";

  case Language::Unknown:
    break;
  }
  llvm_unreachable("unknown input language");
}

void CompilerInvocationBase::GenerateLangArgs(const LangOptions &Opts,
                                              ArgumentConsumer Consumer,
                                              const llvm::Triple &T,
                                              InputKind IK) {
  if (IK.getFormat() == InputKind::Precompiled ||
      IK.getLanguage() == Language::LLVM_IR ||
      IK.getLanguage() == Language::CIR) {
    if (Opts.ObjCAutoRefCount)
      GenerateArg(Consumer, OPT_fobjc_arc);
    if (Opts.PICLevel != 0)
      GenerateArg(Consumer, OPT_pic_level, Twine(Opts.PICLevel));
    if (Opts.PIE)
      GenerateArg(Consumer, OPT_pic_is_pie);
    for (StringRef Sanitizer : serializeSanitizerKinds(Opts.Sanitize))
      GenerateArg(Consumer, OPT_fsanitize_EQ, Sanitizer);

    return;
  }

  OptSpecifier StdOpt;
  switch (Opts.LangStd) {
  case LangStandard::lang_opencl10:
  case LangStandard::lang_opencl11:
  case LangStandard::lang_opencl12:
  case LangStandard::lang_opencl20:
  case LangStandard::lang_opencl30:
  case LangStandard::lang_openclcpp10:
  case LangStandard::lang_openclcpp2021:
    StdOpt = OPT_cl_std_EQ;
    break;
  default:
    StdOpt = OPT_std_EQ;
    break;
  }

  auto LangStandard = LangStandard::getLangStandardForKind(Opts.LangStd);
  GenerateArg(Consumer, StdOpt, LangStandard.getName());

  if (Opts.IncludeDefaultHeader)
    GenerateArg(Consumer, OPT_finclude_default_header);
  if (Opts.DeclareOpenCLBuiltins)
    GenerateArg(Consumer, OPT_fdeclare_opencl_builtins);

  const LangOptions *LangOpts = &Opts;

#define LANG_OPTION_WITH_MARSHALLING(...)                                      \
  GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
#include "clang/Driver/Options.inc"
#undef LANG_OPTION_WITH_MARSHALLING

  // The '-fcf-protection=' option is generated by CodeGenOpts generator.

  if (Opts.ObjC) {
    GenerateArg(Consumer, OPT_fobjc_runtime_EQ, Opts.ObjCRuntime.getAsString());

    if (Opts.GC == LangOptions::GCOnly)
      GenerateArg(Consumer, OPT_fobjc_gc_only);
    else if (Opts.GC == LangOptions::HybridGC)
      GenerateArg(Consumer, OPT_fobjc_gc);
    else if (Opts.ObjCAutoRefCount == 1)
      GenerateArg(Consumer, OPT_fobjc_arc);

    if (Opts.ObjCWeakRuntime)
      GenerateArg(Consumer, OPT_fobjc_runtime_has_weak);

    if (Opts.ObjCWeak)
      GenerateArg(Consumer, OPT_fobjc_weak);

    if (Opts.ObjCSubscriptingLegacyRuntime)
      GenerateArg(Consumer, OPT_fobjc_subscripting_legacy_runtime);
  }

  if (Opts.GNUCVersion != 0) {
    unsigned Major = Opts.GNUCVersion / 100 / 100;
    unsigned Minor = (Opts.GNUCVersion / 100) % 100;
    unsigned Patch = Opts.GNUCVersion % 100;
    GenerateArg(Consumer, OPT_fgnuc_version_EQ,
                Twine(Major) + "." + Twine(Minor) + "." + Twine(Patch));
  }

  if (Opts.IgnoreXCOFFVisibility)
    GenerateArg(Consumer, OPT_mignore_xcoff_visibility);

  if (Opts.SignedOverflowBehavior == LangOptions::SOB_Trapping) {
    GenerateArg(Consumer, OPT_ftrapv);
    GenerateArg(Consumer, OPT_ftrapv_handler, Opts.OverflowHandler);
  } else if (Opts.SignedOverflowBehavior == LangOptions::SOB_Defined) {
    GenerateArg(Consumer, OPT_fwrapv);
  }
  if (Opts.PointerOverflowDefined)
    GenerateArg(Consumer, OPT_fwrapv_pointer);

  if (Opts.MSCompatibilityVersion != 0) {
    unsigned Major = Opts.MSCompatibilityVersion / 10000000;
    unsigned Minor = (Opts.MSCompatibilityVersion / 100000) % 100;
    unsigned Subminor = Opts.MSCompatibilityVersion % 100000;
    GenerateArg(Consumer, OPT_fms_compatibility_version,
                Twine(Major) + "." + Twine(Minor) + "." + Twine(Subminor));
  }

  if ((!Opts.GNUMode && !Opts.MSVCCompat && !Opts.CPlusPlus17 && !Opts.C23) ||
      T.isOSzOS()) {
    if (!Opts.Trigraphs)
      GenerateArg(Consumer, OPT_fno_trigraphs);
  } else {
    if (Opts.Trigraphs)
      GenerateArg(Consumer, OPT_ftrigraphs);
  }

  if (T.isOSzOS() && !Opts.ZOSExt)
    GenerateArg(Consumer, OPT_fno_zos_extensions);
  else if (Opts.ZOSExt)
    GenerateArg(Consumer, OPT_fzos_extensions);

  if (Opts.Blocks && !(Opts.OpenCL && Opts.OpenCLVersion == 200))
    GenerateArg(Consumer, OPT_fblocks);

  if (Opts.ConvergentFunctions)
    GenerateArg(Consumer, OPT_fconvergent_functions);
  else
    GenerateArg(Consumer, OPT_fno_convergent_functions);

  if (Opts.NoBuiltin && !Opts.Freestanding)
    GenerateArg(Consumer, OPT_fno_builtin);

  if (!Opts.NoBuiltin)
    for (const auto &Func : Opts.NoBuiltinFuncs)
      GenerateArg(Consumer, OPT_fno_builtin_, Func);

  if (Opts.LongDoubleSize == 128)
    GenerateArg(Consumer, OPT_mlong_double_128);
  else if (Opts.LongDoubleSize == 64)
    GenerateArg(Consumer, OPT_mlong_double_64);
  else if (Opts.LongDoubleSize == 80)
    GenerateArg(Consumer, OPT_mlong_double_80);

  // Not generating '-mrtd', it's just an alias for '-fdefault-calling-conv='.

  // OpenMP was requested via '-fopenmp', not implied by '-fopenmp-simd' or
  // '-fopenmp-targets='.
  if (Opts.OpenMP && !Opts.OpenMPSimd) {
    GenerateArg(Consumer, OPT_fopenmp);

    if (Opts.OpenMP != 51)
      GenerateArg(Consumer, OPT_fopenmp_version_EQ, Twine(Opts.OpenMP));

    if (!Opts.OpenMPUseTLS)
      GenerateArg(Consumer, OPT_fnoopenmp_use_tls);

    if (Opts.OpenMPIsTargetDevice)
      GenerateArg(Consumer, OPT_fopenmp_is_target_device);

    if (Opts.OpenMPIRBuilder)
      GenerateArg(Consumer, OPT_fopenmp_enable_irbuilder);
  }

  if (Opts.OpenMPSimd) {
    GenerateArg(Consumer, OPT_fopenmp_simd);

    if (Opts.OpenMP != 51)
      GenerateArg(Consumer, OPT_fopenmp_version_EQ, Twine(Opts.OpenMP));
  }

  if (Opts.OpenMPThreadSubscription)
    GenerateArg(Consumer, OPT_fopenmp_assume_threads_oversubscription);

  if (Opts.OpenMPTeamSubscription)
    GenerateArg(Consumer, OPT_fopenmp_assume_teams_oversubscription);

  if (Opts.OpenMPTargetDebug != 0)
    GenerateArg(Consumer, OPT_fopenmp_target_debug_EQ,
                Twine(Opts.OpenMPTargetDebug));

  if (Opts.OpenMPCUDANumSMs != 0)
    GenerateArg(Consumer, OPT_fopenmp_cuda_number_of_sm_EQ,
                Twine(Opts.OpenMPCUDANumSMs));

  if (Opts.OpenMPCUDABlocksPerSM != 0)
    GenerateArg(Consumer, OPT_fopenmp_cuda_blocks_per_sm_EQ,
                Twine(Opts.OpenMPCUDABlocksPerSM));

  if (Opts.OpenMPCUDAReductionBufNum != 1024)
    GenerateArg(Consumer, OPT_fopenmp_cuda_teams_reduction_recs_num_EQ,
                Twine(Opts.OpenMPCUDAReductionBufNum));

  if (!Opts.OMPTargetTriples.empty()) {
    std::string Targets;
    llvm::raw_string_ostream OS(Targets);
    llvm::interleave(
        Opts.OMPTargetTriples, OS,
        [&OS](const llvm::Triple &T) { OS << T.str(); }, ",");
    GenerateArg(Consumer, OPT_offload_targets_EQ, Targets);
  }

  if (!Opts.OMPHostIRFile.empty())
    GenerateArg(Consumer, OPT_fopenmp_host_ir_file_path, Opts.OMPHostIRFile);

  if (Opts.OpenMPCUDAMode)
    GenerateArg(Consumer, OPT_fopenmp_cuda_mode);

  if (Opts.OpenACC)
    GenerateArg(Consumer, OPT_fopenacc);

  // The arguments used to set Optimize, OptimizeSize and NoInlineDefine are
  // generated from CodeGenOptions.

  if (Opts.DefaultFPContractMode == LangOptions::FPM_Fast)
    GenerateArg(Consumer, OPT_ffp_contract, "fast");
  else if (Opts.DefaultFPContractMode == LangOptions::FPM_On)
    GenerateArg(Consumer, OPT_ffp_contract, "on");
  else if (Opts.DefaultFPContractMode == LangOptions::FPM_Off)
    GenerateArg(Consumer, OPT_ffp_contract, "off");
  else if (Opts.DefaultFPContractMode == LangOptions::FPM_FastHonorPragmas)
    GenerateArg(Consumer, OPT_ffp_contract, "fast-honor-pragmas");

  for (StringRef Sanitizer : serializeSanitizerKinds(Opts.Sanitize))
    GenerateArg(Consumer, OPT_fsanitize_EQ, Sanitizer);

  // Conflating '-fsanitize-system-ignorelist' and '-fsanitize-ignorelist'.
  for (const std::string &F : Opts.NoSanitizeFiles)
    GenerateArg(Consumer, OPT_fsanitize_ignorelist_EQ, F);

  switch (Opts.getClangABICompat()) {
  case LangOptions::ClangABI::Ver3_8:
    GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "3.8");
    break;
  case LangOptions::ClangABI::Ver4:
    GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "4.0");
    break;
  case LangOptions::ClangABI::Ver6:
    GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "6.0");
    break;
  case LangOptions::ClangABI::Ver7:
    GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "7.0");
    break;
  case LangOptions::ClangABI::Ver9:
    GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "9.0");
    break;
  case LangOptions::ClangABI::Ver11:
    GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "11.0");
    break;
  case LangOptions::ClangABI::Ver12:
    GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "12.0");
    break;
  case LangOptions::ClangABI::Ver14:
    GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "14.0");
    break;
  case LangOptions::ClangABI::Ver15:
    GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "15.0");
    break;
  case LangOptions::ClangABI::Ver17:
    GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "17.0");
    break;
  case LangOptions::ClangABI::Ver18:
    GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "18.0");
    break;
  case LangOptions::ClangABI::Ver19:
    GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "19.0");
    break;
  case LangOptions::ClangABI::Ver20:
    GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "20.0");
    break;
  case LangOptions::ClangABI::Latest:
    break;
  }

  if (Opts.getSignReturnAddressScope() ==
      LangOptions::SignReturnAddressScopeKind::All)
    GenerateArg(Consumer, OPT_msign_return_address_EQ, "all");
  else if (Opts.getSignReturnAddressScope() ==
           LangOptions::SignReturnAddressScopeKind::NonLeaf)
    GenerateArg(Consumer, OPT_msign_return_address_EQ, "non-leaf");

  if (Opts.getSignReturnAddressKey() ==
      LangOptions::SignReturnAddressKeyKind::BKey)
    GenerateArg(Consumer, OPT_msign_return_address_key_EQ, "b_key");

  if (Opts.CXXABI)
    GenerateArg(Consumer, OPT_fcxx_abi_EQ,
                TargetCXXABI::getSpelling(*Opts.CXXABI));

  if (Opts.RelativeCXXABIVTables)
    GenerateArg(Consumer, OPT_fexperimental_relative_cxx_abi_vtables);
  else
    GenerateArg(Consumer, OPT_fno_experimental_relative_cxx_abi_vtables);

  if (Opts.UseTargetPathSeparator)
    GenerateArg(Consumer, OPT_ffile_reproducible);
  else
    GenerateArg(Consumer, OPT_fno_file_reproducible);

  for (const auto &MP : Opts.MacroPrefixMap)
    GenerateArg(Consumer, OPT_fmacro_prefix_map_EQ, MP.first + "=" + MP.second);

  if (!Opts.RandstructSeed.empty())
    GenerateArg(Consumer, OPT_frandomize_layout_seed_EQ, Opts.RandstructSeed);
}

bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
                                       InputKind IK, const llvm::Triple &T,
                                       std::vector<std::string> &Includes,
                                       DiagnosticsEngine &Diags) {
  unsigned NumErrorsBefore = Diags.getNumErrors();

  if (IK.getFormat() == InputKind::Precompiled ||
      IK.getLanguage() == Language::LLVM_IR ||
      IK.getLanguage() == Language::CIR) {
    // ObjCAAutoRefCount and Sanitize LangOpts are used to setup the
    // PassManager in BackendUtil.cpp. They need to be initialized no matter
    // what the input type is.
    if (Args.hasArg(OPT_fobjc_arc))
      Opts.ObjCAutoRefCount = 1;
    // PICLevel and PIELevel are needed during code generation and this should
    // be set regardless of the input type.
    Opts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags);
    Opts.PIE = Args.hasArg(OPT_pic_is_pie);
    parseSanitizerKinds("-fsanitize=", Args.getAllArgValues(OPT_fsanitize_EQ),
                        Diags, Opts.Sanitize);

    return Diags.getNumErrors() == NumErrorsBefore;
  }

  // Other LangOpts are only initialized when the input is not AST or LLVM IR.
  // FIXME: Should we really be parsing this for an Language::Asm input?

  // FIXME: Cleanup per-file based stuff.
  LangStandard::Kind LangStd = LangStandard::lang_unspecified;
  if (const Arg *A = Args.getLastArg(OPT_std_EQ)) {
    LangStd = LangStandard::getLangKind(A->getValue());
    if (LangStd == LangStandard::lang_unspecified) {
      Diags.Report(diag::err_drv_invalid_value)
        << A->getAsString(Args) << A->getValue();
      // Report supported standards with short description.
      for (unsigned KindValue = 0;
           KindValue != LangStandard::lang_unspecified;
           ++KindValue) {
        const LangStandard &Std = LangStandard::getLangStandardForKind(
          static_cast<LangStandard::Kind>(KindValue));
        if (IsInputCompatibleWithStandard(IK, Std)) {
          auto Diag = Diags.Report(diag::note_drv_use_standard);
          Diag << Std.getName() << Std.getDescription();
          unsigned NumAliases = 0;
#define LANGSTANDARD(id, name, lang, desc, features)
#define LANGSTANDARD_ALIAS(id, alias) \
          if (KindValue == LangStandard::lang_##id) ++NumAliases;
#define LANGSTANDARD_ALIAS_DEPR(id, alias)
#include "clang/Basic/LangStandards.def"
          Diag << NumAliases;
#define LANGSTANDARD(id, name, lang, desc, features)
#define LANGSTANDARD_ALIAS(id, alias) \
          if (KindValue == LangStandard::lang_##id) Diag << alias;
#define LANGSTANDARD_ALIAS_DEPR(id, alias)
#include "clang/Basic/LangStandards.def"
        }
      }
    } else {
      // Valid standard, check to make sure language and standard are
      // compatible.
      const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd);
      if (!IsInputCompatibleWithStandard(IK, Std)) {
        Diags.Report(diag::err_drv_argument_not_allowed_with)
          << A->getAsString(Args) << GetInputKindName(IK);
      }
    }
  }

  // -cl-std only applies for OpenCL language standards.
  // Override the -std option in this case.
  if (const Arg *A = Args.getLastArg(OPT_cl_std_EQ)) {
    LangStandard::Kind OpenCLLangStd
      = llvm::StringSwitch<LangStandard::Kind>(A->getValue())
        .Cases("cl", "CL", LangStandard::lang_opencl10)
        .Cases("cl1.0", "CL1.0", LangStandard::lang_opencl10)
        .Cases("cl1.1", "CL1.1", LangStandard::lang_opencl11)
        .Cases("cl1.2", "CL1.2", LangStandard::lang_opencl12)
        .Cases("cl2.0", "CL2.0", LangStandard::lang_opencl20)
        .Cases("cl3.0", "CL3.0", LangStandard::lang_opencl30)
        .Cases("clc++", "CLC++", LangStandard::lang_openclcpp10)
        .Cases("clc++1.0", "CLC++1.0", LangStandard::lang_openclcpp10)
        .Cases("clc++2021", "CLC++2021", LangStandard::lang_openclcpp2021)
        .Default(LangStandard::lang_unspecified);

    if (OpenCLLangStd == LangStandard::lang_unspecified) {
      Diags.Report(diag::err_drv_invalid_value)
        << A->getAsString(Args) << A->getValue();
    }
    else
      LangStd = OpenCLLangStd;
  }

  // These need to be parsed now. They are used to set OpenCL defaults.
  Opts.IncludeDefaultHeader = Args.hasArg(OPT_finclude_default_header);
  Opts.DeclareOpenCLBuiltins = Args.hasArg(OPT_fdeclare_opencl_builtins);

  LangOptions::setLangDefaults(Opts, IK.getLanguage(), T, Includes, LangStd);

  // The key paths of codegen options defined in Options.td start with
  // "LangOpts->". Let's provide the expected variable name and type.
  LangOptions *LangOpts = &Opts;

#define LANG_OPTION_WITH_MARSHALLING(...)                                      \
  PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
#include "clang/Driver/Options.inc"
#undef LANG_OPTION_WITH_MARSHALLING

  if (const Arg *A = Args.getLastArg(OPT_fcf_protection_EQ)) {
    StringRef Name = A->getValue();
    if (Name == "full") {
      Opts.CFProtectionBranch = 1;
      Opts.CFProtectionReturn = 1;
    } else if (Name == "branch") {
      Opts.CFProtectionBranch = 1;
    } else if (Name == "return") {
      Opts.CFProtectionReturn = 1;
    }
  }

  if (Opts.CFProtectionBranch) {
    if (const Arg *A = Args.getLastArg(OPT_mcf_branch_label_scheme_EQ)) {
      const auto Scheme =
          llvm::StringSwitch<CFBranchLabelSchemeKind>(A->getValue())
#define CF_BRANCH_LABEL_SCHEME(Kind, FlagVal)                                  \
  .Case(#FlagVal, CFBranchLabelSchemeKind::Kind)
#include "clang/Basic/CFProtectionOptions.def"
              .Default(CFBranchLabelSchemeKind::Default);
      Opts.setCFBranchLabelScheme(Scheme);
    }
  }

  if ((Args.hasArg(OPT_fsycl_is_device) || Args.hasArg(OPT_fsycl_is_host)) &&
      !Args.hasArg(OPT_sycl_std_EQ)) {
    // If the user supplied -fsycl-is-device or -fsycl-is-host, but failed to
    // provide -sycl-std=, we want to default it to whatever the default SYCL
    // version is. I could not find a way to express this with the options
    // tablegen because we still want this value to be SYCL_None when the user
    // is not in device or host mode.
    Opts.setSYCLVersion(LangOptions::SYCL_Default);
  }

  if (Opts.ObjC) {
    if (Arg *arg = Args.getLastArg(OPT_fobjc_runtime_EQ)) {
      StringRef value = arg->getValue();
      if (Opts.ObjCRuntime.tryParse(value))
        Diags.Report(diag::err_drv_unknown_objc_runtime) << value;
    }

    if (Args.hasArg(OPT_fobjc_gc_only))
      Opts.setGC(LangOptions::GCOnly);
    else if (Args.hasArg(OPT_fobjc_gc))
      Opts.setGC(LangOptions::HybridGC);
    else if (Args.hasArg(OPT_fobjc_arc)) {
      Opts.ObjCAutoRefCount = 1;
      if (!Opts.ObjCRuntime.allowsARC())
        Diags.Report(diag::err_arc_unsupported_on_runtime);
    }

    // ObjCWeakRuntime tracks whether the runtime supports __weak, not
    // whether the feature is actually enabled.  This is predominantly
    // determined by -fobjc-runtime, but we allow it to be overridden
    // from the command line for testing purposes.
    if (Args.hasArg(OPT_fobjc_runtime_has_weak))
      Opts.ObjCWeakRuntime = 1;
    else
      Opts.ObjCWeakRuntime = Opts.ObjCRuntime.allowsWeak();

    // ObjCWeak determines whether __weak is actually enabled.
    // Note that we allow -fno-objc-weak to disable this even in ARC mode.
    if (auto weakArg = Args.getLastArg(OPT_fobjc_weak, OPT_fno_objc_weak)) {
      if (!weakArg->getOption().matches(OPT_fobjc_weak)) {
        assert(!Opts.ObjCWeak);
      } else if (Opts.getGC() != LangOptions::NonGC) {
        Diags.Report(diag::err_objc_weak_with_gc);
      } else if (!Opts.ObjCWeakRuntime) {
        Diags.Report(diag::err_objc_weak_unsupported);
      } else {
        Opts.ObjCWeak = 1;
      }
    } else if (Opts.ObjCAutoRefCount) {
      Opts.ObjCWeak = Opts.ObjCWeakRuntime;
    }

    if (Args.hasArg(OPT_fobjc_subscripting_legacy_runtime))
      Opts.ObjCSubscriptingLegacyRuntime =
        (Opts.ObjCRuntime.getKind() == ObjCRuntime::FragileMacOSX);
  }

  if (Arg *A = Args.getLastArg(options::OPT_fgnuc_version_EQ)) {
    // Check that the version has 1 to 3 components and the minor and patch
    // versions fit in two decimal digits.
    VersionTuple GNUCVer;
    bool Invalid = GNUCVer.tryParse(A->getValue());
    unsigned Major = GNUCVer.getMajor();
    unsigned Minor = GNUCVer.getMinor().value_or(0);
    unsigned Patch = GNUCVer.getSubminor().value_or(0);
    if (Invalid || GNUCVer.getBuild() || Minor >= 100 || Patch >= 100) {
      Diags.Report(diag::err_drv_invalid_value)
          << A->getAsString(Args) << A->getValue();
    }
    Opts.GNUCVersion = Major * 100 * 100 + Minor * 100 + Patch;
  }

  if (T.isOSAIX() && (Args.hasArg(OPT_mignore_xcoff_visibility)))
    Opts.IgnoreXCOFFVisibility = 1;

  if (Args.hasArg(OPT_ftrapv)) {
    Opts.setSignedOverflowBehavior(LangOptions::SOB_Trapping);
    // Set the handler, if one is specified.
    Opts.OverflowHandler =
        std::string(Args.getLastArgValue(OPT_ftrapv_handler));
  }
  else if (Args.hasArg(OPT_fwrapv))
    Opts.setSignedOverflowBehavior(LangOptions::SOB_Defined);
  if (Args.hasArg(OPT_fwrapv_pointer))
    Opts.PointerOverflowDefined = true;

  Opts.MSCompatibilityVersion = 0;
  if (const Arg *A = Args.getLastArg(OPT_fms_compatibility_version)) {
    VersionTuple VT;
    if (VT.tryParse(A->getValue()))
      Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args)
                                                << A->getValue();
    Opts.MSCompatibilityVersion = VT.getMajor() * 10000000 +
                                  VT.getMinor().value_or(0) * 100000 +
                                  VT.getSubminor().value_or(0);
  }

  // Mimicking gcc's behavior, trigraphs are only enabled if -trigraphs
  // is specified, or -std is set to a conforming mode.
  // Trigraphs are disabled by default in C++17 and C23 onwards.
  // For z/OS, trigraphs are enabled by default (without regard to the above).
  Opts.Trigraphs =
      (!Opts.GNUMode && !Opts.MSVCCompat && !Opts.CPlusPlus17 && !Opts.C23) ||
      T.isOSzOS();
  Opts.Trigraphs =
      Args.hasFlag(OPT_ftrigraphs, OPT_fno_trigraphs, Opts.Trigraphs);

  Opts.ZOSExt =
      Args.hasFlag(OPT_fzos_extensions, OPT_fno_zos_extensions, T.isOSzOS());

  Opts.Blocks = Args.hasArg(OPT_fblocks) || (Opts.OpenCL
    && Opts.OpenCLVersion == 200);

  bool HasConvergentOperations = Opts.isTargetDevice() || Opts.OpenCL ||
                                 Opts.HLSL || T.isAMDGPU() || T.isNVPTX();
  Opts.ConvergentFunctions =
      Args.hasFlag(OPT_fconvergent_functions, OPT_fno_convergent_functions,
                   HasConvergentOperations);

  Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding;
  if (!Opts.NoBuiltin)
    getAllNoBuiltinFuncValues(Args, Opts.NoBuiltinFuncs);
  if (Arg *A = Args.getLastArg(options::OPT_LongDouble_Group)) {
    if (A->getOption().matches(options::OPT_mlong_double_64))
      Opts.LongDoubleSize = 64;
    else if (A->getOption().matches(options::OPT_mlong_double_80))
      Opts.LongDoubleSize = 80;
    else if (A->getOption().matches(options::OPT_mlong_double_128))
      Opts.LongDoubleSize = 128;
    else
      Opts.LongDoubleSize = 0;
  }
  if (Opts.FastRelaxedMath || Opts.CLUnsafeMath)
    Opts.setDefaultFPContractMode(LangOptions::FPM_Fast);

  llvm::sort(Opts.ModuleFeatures);

  // -mrtd option
  if (Arg *A = Args.getLastArg(OPT_mrtd)) {
    if (Opts.getDefaultCallingConv() != LangOptions::DCC_None)
      Diags.Report(diag::err_drv_argument_not_allowed_with)
          << A->getSpelling() << "-fdefault-calling-conv";
    else {
      switch (T.getArch()) {
      case llvm::Triple::x86:
        Opts.setDefaultCallingConv(LangOptions::DCC_StdCall);
        break;
      case llvm::Triple::m68k:
        Opts.setDefaultCallingConv(LangOptions::DCC_RtdCall);
        break;
      default:
        Diags.Report(diag::err_drv_argument_not_allowed_with)
            << A->getSpelling() << T.getTriple();
      }
    }
  }

  // Check if -fopenmp is specified and set default version to 5.1.
  Opts.OpenMP = Args.hasArg(OPT_fopenmp) ? 51 : 0;
  // Check if -fopenmp-simd is specified.
  bool IsSimdSpecified =
      Args.hasFlag(options::OPT_fopenmp_simd, options::OPT_fno_openmp_simd,
                   /*Default=*/false);
  Opts.OpenMPSimd = !Opts.OpenMP && IsSimdSpecified;
  Opts.OpenMPUseTLS =
      Opts.OpenMP && !Args.hasArg(options::OPT_fnoopenmp_use_tls);
  Opts.OpenMPIsTargetDevice =
      Opts.OpenMP && Args.hasArg(options::OPT_fopenmp_is_target_device);
  Opts.OpenMPIRBuilder =
      Opts.OpenMP && Args.hasArg(options::OPT_fopenmp_enable_irbuilder);
  bool IsTargetSpecified =
      Opts.OpenMPIsTargetDevice || Args.hasArg(options::OPT_offload_targets_EQ);

  if (Opts.OpenMP || Opts.OpenMPSimd) {
    if (int Version = getLastArgIntValue(
            Args, OPT_fopenmp_version_EQ,
            (IsSimdSpecified || IsTargetSpecified) ? 51 : Opts.OpenMP, Diags))
      Opts.OpenMP = Version;
    // Provide diagnostic when a given target is not expected to be an OpenMP
    // device or host.
    if (!Opts.OpenMPIsTargetDevice) {
      switch (T.getArch()) {
      default:
        break;
      // Add unsupported host targets here:
      case llvm::Triple::nvptx:
      case llvm::Triple::nvptx64:
        Diags.Report(diag::err_drv_omp_host_target_not_supported) << T.str();
        break;
      }
    }
  }

  // Set the flag to prevent the implementation from emitting device exception
  // handling code for those requiring so.
  if ((Opts.OpenMPIsTargetDevice && (T.isNVPTX() || T.isAMDGCN())) ||
      Opts.OpenCLCPlusPlus) {

    Opts.Exceptions = 0;
    Opts.CXXExceptions = 0;
  }
  if (Opts.OpenMPIsTargetDevice && T.isNVPTX()) {
    Opts.OpenMPCUDANumSMs =
        getLastArgIntValue(Args, options::OPT_fopenmp_cuda_number_of_sm_EQ,
                           Opts.OpenMPCUDANumSMs, Diags);
    Opts.OpenMPCUDABlocksPerSM =
        getLastArgIntValue(Args, options::OPT_fopenmp_cuda_blocks_per_sm_EQ,
                           Opts.OpenMPCUDABlocksPerSM, Diags);
    Opts.OpenMPCUDAReductionBufNum = getLastArgIntValue(
        Args, options::OPT_fopenmp_cuda_teams_reduction_recs_num_EQ,
        Opts.OpenMPCUDAReductionBufNum, Diags);
  }

  // Set the value of the debugging flag used in the new offloading device RTL.
  // Set either by a specific value or to a default if not specified.
  if (Opts.OpenMPIsTargetDevice && (Args.hasArg(OPT_fopenmp_target_debug) ||
                                    Args.hasArg(OPT_fopenmp_target_debug_EQ))) {
    Opts.OpenMPTargetDebug = getLastArgIntValue(
        Args, OPT_fopenmp_target_debug_EQ, Opts.OpenMPTargetDebug, Diags);
    if (!Opts.OpenMPTargetDebug && Args.hasArg(OPT_fopenmp_target_debug))
      Opts.OpenMPTargetDebug = 1;
  }

  if (Opts.OpenMPIsTargetDevice) {
    if (Args.hasArg(OPT_fopenmp_assume_teams_oversubscription))
      Opts.OpenMPTeamSubscription = true;
    if (Args.hasArg(OPT_fopenmp_assume_threads_oversubscription))
      Opts.OpenMPThreadSubscription = true;
  }

  // Get the OpenMP target triples if any.
  if (Arg *A = Args.getLastArg(options::OPT_offload_targets_EQ)) {
    enum ArchPtrSize { Arch16Bit, Arch32Bit, Arch64Bit };
    auto getArchPtrSize = [](const llvm::Triple &T) {
      if (T.isArch16Bit())
        return Arch16Bit;
      if (T.isArch32Bit())
        return Arch32Bit;
      assert(T.isArch64Bit() && "Expected 64-bit architecture");
      return Arch64Bit;
    };

    for (unsigned i = 0; i < A->getNumValues(); ++i) {
      llvm::Triple TT(A->getValue(i));

      if (TT.getArch() == llvm::Triple::UnknownArch ||
          !(TT.getArch() == llvm::Triple::aarch64 || TT.isPPC() ||
            TT.getArch() == llvm::Triple::spirv64 ||
            TT.getArch() == llvm::Triple::systemz ||
            TT.getArch() == llvm::Triple::loongarch64 ||
            TT.getArch() == llvm::Triple::nvptx ||
            TT.getArch() == llvm::Triple::nvptx64 || TT.isAMDGCN() ||
            TT.getArch() == llvm::Triple::x86 ||
            TT.getArch() == llvm::Triple::x86_64))
        Diags.Report(diag::err_drv_invalid_omp_target) << A->getValue(i);
      else if (getArchPtrSize(T) != getArchPtrSize(TT))
        Diags.Report(diag::err_drv_incompatible_omp_arch)
            << A->getValue(i) << T.str();
      else
        Opts.OMPTargetTriples.push_back(TT);
    }
  }

  // Get OpenMP host file path if any and report if a non existent file is
  // found
  if (Arg *A = Args.getLastArg(options::OPT_fopenmp_host_ir_file_path)) {
    Opts.OMPHostIRFile = A->getValue();
    if (!llvm::sys::fs::exists(Opts.OMPHostIRFile))
      Diags.Report(diag::err_drv_omp_host_ir_file_not_found)
          << Opts.OMPHostIRFile;
  }

  // Set CUDA mode for OpenMP target NVPTX/AMDGCN if specified in options
  Opts.OpenMPCUDAMode = Opts.OpenMPIsTargetDevice &&
                        (T.isNVPTX() || T.isAMDGCN()) &&
                        Args.hasArg(options::OPT_fopenmp_cuda_mode);

  // OpenACC Configuration.
  if (Args.hasArg(options::OPT_fopenacc))
    Opts.OpenACC = true;

  if (Arg *A = Args.getLastArg(OPT_ffp_contract)) {
    StringRef Val = A->getValue();
    if (Val == "fast")
      Opts.setDefaultFPContractMode(LangOptions::FPM_Fast);
    else if (Val == "on")
      Opts.setDefaultFPContractMode(LangOptions::FPM_On);
    else if (Val == "off")
      Opts.setDefaultFPContractMode(LangOptions::FPM_Off);
    else if (Val == "fast-honor-pragmas")
      Opts.setDefaultFPContractMode(LangOptions::FPM_FastHonorPragmas);
    else
      Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;
  }

  if (auto *A =
          Args.getLastArg(OPT_fsanitize_undefined_ignore_overflow_pattern_EQ)) {
    for (int i = 0, n = A->getNumValues(); i != n; ++i) {
      Opts.OverflowPatternExclusionMask |=
          llvm::StringSwitch<unsigned>(A->getValue(i))
              .Case("none", LangOptionsBase::None)
              .Case("all", LangOptionsBase::All)
              .Case("add-unsigned-overflow-test",
                    LangOptionsBase::AddUnsignedOverflowTest)
              .Case("add-signed-overflow-test",
                    LangOptionsBase::AddSignedOverflowTest)
              .Case("negated-unsigned-const", LangOptionsBase::NegUnsignedConst)
              .Case("unsigned-post-decr-while",
                    LangOptionsBase::PostDecrInWhile)
              .Default(0);
    }
  }

  // Parse -fsanitize= arguments.
  parseSanitizerKinds("-fsanitize=", Args.getAllArgValues(OPT_fsanitize_EQ),
                      Diags, Opts.Sanitize);
  Opts.NoSanitizeFiles = Args.getAllArgValues(OPT_fsanitize_ignorelist_EQ);
  std::vector<std::string> systemIgnorelists =
      Args.getAllArgValues(OPT_fsanitize_system_ignorelist_EQ);
  Opts.NoSanitizeFiles.insert(Opts.NoSanitizeFiles.end(),
                              systemIgnorelists.begin(),
                              systemIgnorelists.end());

  if (Arg *A = Args.getLastArg(OPT_fclang_abi_compat_EQ)) {
    Opts.setClangABICompat(LangOptions::ClangABI::Latest);

    StringRef Ver = A->getValue();
    std::pair<StringRef, StringRef> VerParts = Ver.split('.');
    unsigned Major, Minor = 0;

    // Check the version number is valid: either 3.x (0 <= x <= 9) or
    // y or y.0 (4 <= y <= current version).
    if (!VerParts.first.starts_with("0") &&
        !VerParts.first.getAsInteger(10, Major) && 3 <= Major &&
        Major <= MAX_CLANG_ABI_COMPAT_VERSION &&
        (Major == 3
             ? VerParts.second.size() == 1 &&
                   !VerParts.second.getAsInteger(10, Minor)
             : VerParts.first.size() == Ver.size() || VerParts.second == "0")) {
      // Got a valid version number.
      if (Major == 3 && Minor <= 8)
        Opts.setClangABICompat(LangOptions::ClangABI::Ver3_8);
      else if (Major <= 4)
        Opts.setClangABICompat(LangOptions::ClangABI::Ver4);
      else if (Major <= 6)
        Opts.setClangABICompat(LangOptions::ClangABI::Ver6);
      else if (Major <= 7)
        Opts.setClangABICompat(LangOptions::ClangABI::Ver7);
      else if (Major <= 9)
        Opts.setClangABICompat(LangOptions::ClangABI::Ver9);
      else if (Major <= 11)
        Opts.setClangABICompat(LangOptions::ClangABI::Ver11);
      else if (Major <= 12)
        Opts.setClangABICompat(LangOptions::ClangABI::Ver12);
      else if (Major <= 14)
        Opts.setClangABICompat(LangOptions::ClangABI::Ver14);
      else if (Major <= 15)
        Opts.setClangABICompat(LangOptions::ClangABI::Ver15);
      else if (Major <= 17)
        Opts.setClangABICompat(LangOptions::ClangABI::Ver17);
      else if (Major <= 18)
        Opts.setClangABICompat(LangOptions::ClangABI::Ver18);
      else if (Major <= 19)
        Opts.setClangABICompat(LangOptions::ClangABI::Ver19);
      else if (Major <= 20)
        Opts.setClangABICompat(LangOptions::ClangABI::Ver20);
    } else if (Ver != "latest") {
      Diags.Report(diag::err_drv_invalid_value)
          << A->getAsString(Args) << A->getValue();
    }
  }

  if (Arg *A = Args.getLastArg(OPT_msign_return_address_EQ)) {
    StringRef SignScope = A->getValue();

    if (SignScope.equals_insensitive("none"))
      Opts.setSignReturnAddressScope(
          LangOptions::SignReturnAddressScopeKind::None);
    else if (SignScope.equals_insensitive("all"))
      Opts.setSignReturnAddressScope(
          LangOptions::SignReturnAddressScopeKind::All);
    else if (SignScope.equals_insensitive("non-leaf"))
      Opts.setSignReturnAddressScope(
          LangOptions::SignReturnAddressScopeKind::NonLeaf);
    else
      Diags.Report(diag::err_drv_invalid_value)
          << A->getAsString(Args) << SignScope;

    if (Arg *A = Args.getLastArg(OPT_msign_return_address_key_EQ)) {
      StringRef SignKey = A->getValue();
      if (!SignScope.empty() && !SignKey.empty()) {
        if (SignKey == "a_key")
          Opts.setSignReturnAddressKey(
              LangOptions::SignReturnAddressKeyKind::AKey);
        else if (SignKey == "b_key")
          Opts.setSignReturnAddressKey(
              LangOptions::SignReturnAddressKeyKind::BKey);
        else
          Diags.Report(diag::err_drv_invalid_value)
              << A->getAsString(Args) << SignKey;
      }
    }
  }

  // The value can be empty, which indicates the system default should be used.
  StringRef CXXABI = Args.getLastArgValue(OPT_fcxx_abi_EQ);
  if (!CXXABI.empty()) {
    if (!TargetCXXABI::isABI(CXXABI)) {
      Diags.Report(diag::err_invalid_cxx_abi) << CXXABI;
    } else {
      auto Kind = TargetCXXABI::getKind(CXXABI);
      if (!TargetCXXABI::isSupportedCXXABI(T, Kind))
        Diags.Report(diag::err_unsupported_cxx_abi) << CXXABI << T.str();
      else
        Opts.CXXABI = Kind;
    }
  }

  Opts.RelativeCXXABIVTables =
      Args.hasFlag(options::OPT_fexperimental_relative_cxx_abi_vtables,
                   options::OPT_fno_experimental_relative_cxx_abi_vtables,
                   TargetCXXABI::usesRelativeVTables(T));

  // RTTI is on by default.
  bool HasRTTI = !Args.hasArg(options::OPT_fno_rtti);
  Opts.OmitVTableRTTI =
      Args.hasFlag(options::OPT_fexperimental_omit_vtable_rtti,
                   options::OPT_fno_experimental_omit_vtable_rtti, false);
  if (Opts.OmitVTableRTTI && HasRTTI)
    Diags.Report(diag::err_drv_using_omit_rtti_component_without_no_rtti);

  for (const auto &A : Args.getAllArgValues(OPT_fmacro_prefix_map_EQ)) {
    auto Split = StringRef(A).split('=');
    Opts.MacroPrefixMap.insert(
        {std::string(Split.first), std::string(Split.second)});
  }

  Opts.UseTargetPathSeparator =
      !Args.getLastArg(OPT_fno_file_reproducible) &&
      (Args.getLastArg(OPT_ffile_compilation_dir_EQ) ||
       Args.getLastArg(OPT_fmacro_prefix_map_EQ) ||
       Args.getLastArg(OPT_ffile_reproducible));

  // Error if -mvscale-min is unbounded.
  if (Arg *A = Args.getLastArg(options::OPT_mvscale_min_EQ)) {
    unsigned VScaleMin;
    if (StringRef(A->getValue()).getAsInteger(10, VScaleMin) || VScaleMin == 0)
      Diags.Report(diag::err_cc1_unbounded_vscale_min);
  }
  if (Arg *A = Args.getLastArg(options::OPT_mvscale_streaming_min_EQ)) {
    unsigned VScaleMin;
    if (StringRef(A->getValue()).getAsInteger(10, VScaleMin) || VScaleMin == 0)
      Diags.Report(diag::err_cc1_unbounded_vscale_min);
  }

  if (const Arg *A = Args.getLastArg(OPT_frandomize_layout_seed_file_EQ)) {
    std::ifstream SeedFile(A->getValue(0));

    if (!SeedFile.is_open())
      Diags.Report(diag::err_drv_cannot_open_randomize_layout_seed_file)
          << A->getValue(0);

    std::getline(SeedFile, Opts.RandstructSeed);
  }

  if (const Arg *A = Args.getLastArg(OPT_frandomize_layout_seed_EQ))
    Opts.RandstructSeed = A->getValue(0);

  // Validate options for HLSL
  if (Opts.HLSL) {
    // TODO: Revisit restricting SPIR-V to logical once we've figured out how to
    // handle PhysicalStorageBuffer64 memory model
    if (T.isDXIL() || T.isSPIRVLogical()) {
      enum { ShaderModel, VulkanEnv, ShaderStage };
      enum { OS, Environment };

      int ExpectedOS = T.isSPIRVLogical() ? VulkanEnv : ShaderModel;

      if (T.getOSName().empty()) {
        Diags.Report(diag::err_drv_hlsl_bad_shader_required_in_target)
            << ExpectedOS << OS << T.str();
      } else if (T.getEnvironmentName().empty()) {
        Diags.Report(diag::err_drv_hlsl_bad_shader_required_in_target)
            << ShaderStage << Environment << T.str();
      } else if (!T.isShaderStageEnvironment()) {
        Diags.Report(diag::err_drv_hlsl_bad_shader_unsupported)
            << ShaderStage << T.getEnvironmentName() << T.str();
      }

      if (T.isDXIL()) {
        if (!T.isShaderModelOS() || T.getOSVersion() == VersionTuple(0)) {
          Diags.Report(diag::err_drv_hlsl_bad_shader_unsupported)
              << ShaderModel << T.getOSName() << T.str();
        }
        // Validate that if fnative-half-type is given, that
        // the language standard is at least hlsl2018, and that
        // the target shader model is at least 6.2.
        if (Args.getLastArg(OPT_fnative_half_type)) {
          const LangStandard &Std =
              LangStandard::getLangStandardForKind(Opts.LangStd);
          if (!(Opts.LangStd >= LangStandard::lang_hlsl2018 &&
                T.getOSVersion() >= VersionTuple(6, 2)))
            Diags.Report(diag::err_drv_hlsl_16bit_types_unsupported)
                << "-enable-16bit-types" << true << Std.getName()
                << T.getOSVersion().getAsString();
        }
      } else if (T.isSPIRVLogical()) {
        if (!T.isVulkanOS() || T.getVulkanVersion() == VersionTuple(0)) {
          Diags.Report(diag::err_drv_hlsl_bad_shader_unsupported)
              << VulkanEnv << T.getOSName() << T.str();
        }
        if (Args.getLastArg(OPT_fnative_half_type)) {
          const LangStandard &Std =
              LangStandard::getLangStandardForKind(Opts.LangStd);
          if (!(Opts.LangStd >= LangStandard::lang_hlsl2018))
            Diags.Report(diag::err_drv_hlsl_16bit_types_unsupported)
                << "-fnative-half-type" << false << Std.getName();
        }
      } else {
        llvm_unreachable("expected DXIL or SPIR-V target");
      }
    } else
      Diags.Report(diag::err_drv_hlsl_unsupported_target) << T.str();

    if (Opts.LangStd < LangStandard::lang_hlsl202x) {
      const LangStandard &Requested =
          LangStandard::getLangStandardForKind(Opts.LangStd);
      const LangStandard &Recommended =
          LangStandard::getLangStandardForKind(LangStandard::lang_hlsl202x);
      Diags.Report(diag::warn_hlsl_langstd_minimal)
          << Requested.getName() << Recommended.getName();
    }
  }

  return Diags.getNumErrors() == NumErrorsBefore;
}

static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) {
  switch (Action) {
  case frontend::ASTDeclList:
  case frontend::ASTDump:
  case frontend::ASTPrint:
  case frontend::ASTView:
  case frontend::EmitAssembly:
  case frontend::EmitBC:
  case frontend::EmitCIR:
  case frontend::EmitHTML:
  case frontend::EmitLLVM:
  case frontend::EmitLLVMOnly:
  case frontend::EmitCodeGenOnly:
  case frontend::EmitObj:
  case frontend::ExtractAPI:
  case frontend::FixIt:
  case frontend::GenerateModule:
  case frontend::GenerateModuleInterface:
  case frontend::GenerateReducedModuleInterface:
  case frontend::GenerateHeaderUnit:
  case frontend::GeneratePCH:
  case frontend::GenerateInterfaceStubs:
  case frontend::ParseSyntaxOnly:
  case frontend::ModuleFileInfo:
  case frontend::VerifyPCH:
  case frontend::PluginAction:
  case frontend::RewriteObjC:
  case frontend::RewriteTest:
  case frontend::RunAnalysis:
  case frontend::TemplightDump:
    return false;

  case frontend::DumpCompilerOptions:
  case frontend::DumpRawTokens:
  case frontend::DumpTokens:
  case frontend::InitOnly:
  case frontend::PrintPreamble:
  case frontend::PrintPreprocessedInput:
  case frontend::RewriteMacros:
  case frontend::RunPreprocessorOnly:
  case frontend::PrintDependencyDirectivesSourceMinimizerOutput:
    return true;
  }
  llvm_unreachable("invalid frontend action");
}

static bool isCodeGenAction(frontend::ActionKind Action) {
  switch (Action) {
  case frontend::EmitAssembly:
  case frontend::EmitBC:
  case frontend::EmitCIR:
  case frontend::EmitHTML:
  case frontend::EmitLLVM:
  case frontend::EmitLLVMOnly:
  case frontend::EmitCodeGenOnly:
  case frontend::EmitObj:
  case frontend::GenerateModule:
  case frontend::GenerateModuleInterface:
  case frontend::GenerateReducedModuleInterface:
  case frontend::GenerateHeaderUnit:
  case frontend::GeneratePCH:
  case frontend::GenerateInterfaceStubs:
    return true;
  case frontend::ASTDeclList:
  case frontend::ASTDump:
  case frontend::ASTPrint:
  case frontend::ASTView:
  case frontend::ExtractAPI:
  case frontend::FixIt:
  case frontend::ParseSyntaxOnly:
  case frontend::ModuleFileInfo:
  case frontend::VerifyPCH:
  case frontend::PluginAction:
  case frontend::RewriteObjC:
  case frontend::RewriteTest:
  case frontend::RunAnalysis:
  case frontend::TemplightDump:
  case frontend::DumpCompilerOptions:
  case frontend::DumpRawTokens:
  case frontend::DumpTokens:
  case frontend::InitOnly:
  case frontend::PrintPreamble:
  case frontend::PrintPreprocessedInput:
  case frontend::RewriteMacros:
  case frontend::RunPreprocessorOnly:
  case frontend::PrintDependencyDirectivesSourceMinimizerOutput:
    return false;
  }
  llvm_unreachable("invalid frontend action");
}

static void GeneratePreprocessorArgs(const PreprocessorOptions &Opts,
                                     ArgumentConsumer Consumer,
                                     const LangOptions &LangOpts,
                                     const FrontendOptions &FrontendOpts,
                                     const CodeGenOptions &CodeGenOpts) {
  const PreprocessorOptions *PreprocessorOpts = &Opts;

#define PREPROCESSOR_OPTION_WITH_MARSHALLING(...)                              \
  GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
#include "clang/Driver/Options.inc"
#undef PREPROCESSOR_OPTION_WITH_MARSHALLING

  if (Opts.PCHWithHdrStop && !Opts.PCHWithHdrStopCreate)
    GenerateArg(Consumer, OPT_pch_through_hdrstop_use);

  for (const auto &D : Opts.DeserializedPCHDeclsToErrorOn)
    GenerateArg(Consumer, OPT_error_on_deserialized_pch_decl, D);

  if (Opts.PrecompiledPreambleBytes != std::make_pair(0u, false))
    GenerateArg(Consumer, OPT_preamble_bytes_EQ,
                Twine(Opts.PrecompiledPreambleBytes.first) + "," +
                    (Opts.PrecompiledPreambleBytes.second ? "1" : "0"));

  for (const auto &M : Opts.Macros) {
    // Don't generate __CET__ macro definitions. They are implied by the
    // -fcf-protection option that is generated elsewhere.
    if (M.first == "__CET__=1" && !M.second &&
        !CodeGenOpts.CFProtectionReturn && CodeGenOpts.CFProtectionBranch)
      continue;
    if (M.first == "__CET__=2" && !M.second && CodeGenOpts.CFProtectionReturn &&
        !CodeGenOpts.CFProtectionBranch)
      continue;
    if (M.first == "__CET__=3" && !M.second && CodeGenOpts.CFProtectionReturn &&
        CodeGenOpts.CFProtectionBranch)
      continue;

    GenerateArg(Consumer, M.second ? OPT_U : OPT_D, M.first);
  }

  for (const auto &I : Opts.Includes) {
    // Don't generate OpenCL includes. They are implied by other flags that are
    // generated elsewhere.
    if (LangOpts.OpenCL && LangOpts.IncludeDefaultHeader &&
        ((LangOpts.DeclareOpenCLBuiltins && I == "opencl-c-base.h") ||
         I == "opencl-c.h"))
      continue;
    // Don't generate HLSL includes. They are implied by other flags that are
    // generated elsewhere.
    if (LangOpts.HLSL && I == "hlsl.h")
      continue;

    GenerateArg(Consumer, OPT_include, I);
  }

  for (const auto &CI : Opts.ChainedIncludes)
    GenerateArg(Consumer, OPT_chain_include, CI);

  for (const auto &RF : Opts.RemappedFiles)
    GenerateArg(Consumer, OPT_remap_file, RF.first + ";" + RF.second);

  if (Opts.SourceDateEpoch)
    GenerateArg(Consumer, OPT_source_date_epoch, Twine(*Opts.SourceDateEpoch));

  if (Opts.DefineTargetOSMacros)
    GenerateArg(Consumer, OPT_fdefine_target_os_macros);

  for (const auto &EmbedEntry : Opts.EmbedEntries)
    GenerateArg(Consumer, OPT_embed_dir_EQ, EmbedEntry);

  // Don't handle LexEditorPlaceholders. It is implied by the action that is
  // generated elsewhere.
}

static bool ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
                                  DiagnosticsEngine &Diags,
                                  frontend::ActionKind Action,
                                  const FrontendOptions &FrontendOpts) {
  unsigned NumErrorsBefore = Diags.getNumErrors();

  PreprocessorOptions *PreprocessorOpts = &Opts;

#define PREPROCESSOR_OPTION_WITH_MARSHALLING(...)                              \
  PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
#include "clang/Driver/Options.inc"
#undef PREPROCESSOR_OPTION_WITH_MARSHALLING

  Opts.PCHWithHdrStop = Args.hasArg(OPT_pch_through_hdrstop_create) ||
                        Args.hasArg(OPT_pch_through_hdrstop_use);

  for (const auto *A : Args.filtered(OPT_error_on_deserialized_pch_decl))
    Opts.DeserializedPCHDeclsToErrorOn.insert(A->getValue());

  if (const Arg *A = Args.getLastArg(OPT_preamble_bytes_EQ)) {
    StringRef Value(A->getValue());
    size_t Comma = Value.find(',');
    unsigned Bytes = 0;
    unsigned EndOfLine = 0;

    if (Comma == StringRef::npos ||
        Value.substr(0, Comma).getAsInteger(10, Bytes) ||
        Value.substr(Comma + 1).getAsInteger(10, EndOfLine))
      Diags.Report(diag::err_drv_preamble_format);
    else {
      Opts.PrecompiledPreambleBytes.first = Bytes;
      Opts.PrecompiledPreambleBytes.second = (EndOfLine != 0);
    }
  }

  // Add macros from the command line.
  for (const auto *A : Args.filtered(OPT_D, OPT_U)) {
    if (A->getOption().matches(OPT_D))
      Opts.addMacroDef(A->getValue());
    else
      Opts.addMacroUndef(A->getValue());
  }

  // Add the ordered list of -includes.
  for (const auto *A : Args.filtered(OPT_include))
    Opts.Includes.emplace_back(A->getValue());

  for (const auto *A : Args.filtered(OPT_chain_include))
    Opts.ChainedIncludes.emplace_back(A->getValue());

  for (const auto *A : Args.filtered(OPT_remap_file)) {
    std::pair<StringRef, StringRef> Split = StringRef(A->getValue()).split(';');

    if (Split.second.empty()) {
      Diags.Report(diag::err_drv_invalid_remap_file) << A->getAsString(Args);
      continue;
    }

    Opts.addRemappedFile(Split.first, Split.second);
  }

  if (const Arg *A = Args.getLastArg(OPT_source_date_epoch)) {
    StringRef Epoch = A->getValue();
    // SOURCE_DATE_EPOCH, if specified, must be a non-negative decimal integer.
    // On time64 systems, pick 253402300799 (the UNIX timestamp of
    // 9999-12-31T23:59:59Z) as the upper bound.
    const uint64_t MaxTimestamp =
        std::min<uint64_t>(std::numeric_limits<time_t>::max(), 253402300799);
    uint64_t V;
    if (Epoch.getAsInteger(10, V) || V > MaxTimestamp) {
      Diags.Report(diag::err_fe_invalid_source_date_epoch)
          << Epoch << MaxTimestamp;
    } else {
      Opts.SourceDateEpoch = V;
    }
  }

  for (const auto *A : Args.filtered(OPT_embed_dir_EQ)) {
    StringRef Val = A->getValue();
    Opts.EmbedEntries.push_back(std::string(Val));
  }

  // Always avoid lexing editor placeholders when we're just running the
  // preprocessor as we never want to emit the
  // "editor placeholder in source file" error in PP only mode.
  if (isStrictlyPreprocessorAction(Action))
    Opts.LexEditorPlaceholders = false;

  Opts.DefineTargetOSMacros =
      Args.hasFlag(OPT_fdefine_target_os_macros,
                   OPT_fno_define_target_os_macros, Opts.DefineTargetOSMacros);

  return Diags.getNumErrors() == NumErrorsBefore;
}

static void
GeneratePreprocessorOutputArgs(const PreprocessorOutputOptions &Opts,
                               ArgumentConsumer Consumer,
                               frontend::ActionKind Action) {
  const PreprocessorOutputOptions &PreprocessorOutputOpts = Opts;

#define PREPROCESSOR_OUTPUT_OPTION_WITH_MARSHALLING(...)                       \
  GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
#include "clang/Driver/Options.inc"
#undef PREPROCESSOR_OUTPUT_OPTION_WITH_MARSHALLING

  bool Generate_dM = isStrictlyPreprocessorAction(Action) && !Opts.ShowCPP;
  if (Generate_dM)
    GenerateArg(Consumer, OPT_dM);
  if (!Generate_dM && Opts.ShowMacros)
    GenerateArg(Consumer, OPT_dD);
  if (Opts.DirectivesOnly)
    GenerateArg(Consumer, OPT_fdirectives_only);
}

static bool ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts,
                                        ArgList &Args, DiagnosticsEngine &Diags,
                                        frontend::ActionKind Action) {
  unsigned NumErrorsBefore = Diags.getNumErrors();

  PreprocessorOutputOptions &PreprocessorOutputOpts = Opts;

#define PREPROCESSOR_OUTPUT_OPTION_WITH_MARSHALLING(...)                       \
  PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
#include "clang/Driver/Options.inc"
#undef PREPROCESSOR_OUTPUT_OPTION_WITH_MARSHALLING

  Opts.ShowCPP = isStrictlyPreprocessorAction(Action) && !Args.hasArg(OPT_dM);
  Opts.ShowMacros = Args.hasArg(OPT_dM) || Args.hasArg(OPT_dD);
  Opts.DirectivesOnly = Args.hasArg(OPT_fdirectives_only);

  return Diags.getNumErrors() == NumErrorsBefore;
}

static void GenerateTargetArgs(const TargetOptions &Opts,
                               ArgumentConsumer Consumer) {
  const TargetOptions *TargetOpts = &Opts;
#define TARGET_OPTION_WITH_MARSHALLING(...)                                    \
  GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
#include "clang/Driver/Options.inc"
#undef TARGET_OPTION_WITH_MARSHALLING

  if (!Opts.SDKVersion.empty())
    GenerateArg(Consumer, OPT_target_sdk_version_EQ,
                Opts.SDKVersion.getAsString());
  if (!Opts.DarwinTargetVariantSDKVersion.empty())
    GenerateArg(Consumer, OPT_darwin_target_variant_sdk_version_EQ,
                Opts.DarwinTargetVariantSDKVersion.getAsString());
}

static bool ParseTargetArgs(TargetOptions &Opts, ArgList &Args,
                            DiagnosticsEngine &Diags) {
  unsigned NumErrorsBefore = Diags.getNumErrors();

  TargetOptions *TargetOpts = &Opts;

#define TARGET_OPTION_WITH_MARSHALLING(...)                                    \
  PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
#include "clang/Driver/Options.inc"
#undef TARGET_OPTION_WITH_MARSHALLING

  if (Arg *A = Args.getLastArg(options::OPT_target_sdk_version_EQ)) {
    llvm::VersionTuple Version;
    if (Version.tryParse(A->getValue()))
      Diags.Report(diag::err_drv_invalid_value)
          << A->getAsString(Args) << A->getValue();
    else
      Opts.SDKVersion = Version;
  }
  if (Arg *A =
          Args.getLastArg(options::OPT_darwin_target_variant_sdk_version_EQ)) {
    llvm::VersionTuple Version;
    if (Version.tryParse(A->getValue()))
      Diags.Report(diag::err_drv_invalid_value)
          << A->getAsString(Args) << A->getValue();
    else
      Opts.DarwinTargetVariantSDKVersion = Version;
  }

  return Diags.getNumErrors() == NumErrorsBefore;
}

bool CompilerInvocation::CreateFromArgsImpl(
    CompilerInvocation &Res, ArrayRef<const char *> CommandLineArgs,
    DiagnosticsEngine &Diags, const char *Argv0) {
  unsigned NumErrorsBefore = Diags.getNumErrors();

  // Parse the arguments.
  const OptTable &Opts = getDriverOptTable();
  llvm::opt::Visibility VisibilityMask(options::CC1Option);
  unsigned MissingArgIndex, MissingArgCount;
  InputArgList Args = Opts.ParseArgs(CommandLineArgs, MissingArgIndex,
                                     MissingArgCount, VisibilityMask);
  LangOptions &LangOpts = Res.getLangOpts();

  // Check for missing argument error.
  if (MissingArgCount)
    Diags.Report(diag::err_drv_missing_argument)
        << Args.getArgString(MissingArgIndex) << MissingArgCount;

  // Issue errors on unknown arguments.
  for (const auto *A : Args.filtered(OPT_UNKNOWN)) {
    auto ArgString = A->getAsString(Args);
    std::string Nearest;
    if (Opts.findNearest(ArgString, Nearest, VisibilityMask) > 1)
      Diags.Report(diag::err_drv_unknown_argument) << ArgString;
    else
      Diags.Report(diag::err_drv_unknown_argument_with_suggestion)
          << ArgString << Nearest;
  }

  ParseFileSystemArgs(Res.getFileSystemOpts(), Args, Diags);
  ParseMigratorArgs(Res.getMigratorOpts(), Args, Diags);
  ParseAnalyzerArgs(Res.getAnalyzerOpts(), Args, Diags);
  ParseDiagnosticArgs(Res.getDiagnosticOpts(), Args, &Diags,
                      /*DefaultDiagColor=*/false);
  ParseFrontendArgs(Res.getFrontendOpts(), Args, Diags, LangOpts.IsHeaderFile);
  // FIXME: We shouldn't have to pass the DashX option around here
  InputKind DashX = Res.getFrontendOpts().DashX;
  ParseTargetArgs(Res.getTargetOpts(), Args, Diags);
  llvm::Triple T(Res.getTargetOpts().Triple);
  ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), Args, Diags,
                        Res.getFileSystemOpts().WorkingDir);
  if (Res.getFrontendOpts().GenReducedBMI ||
      Res.getFrontendOpts().ProgramAction ==
          frontend::GenerateReducedModuleInterface ||
      Res.getFrontendOpts().ProgramAction ==
          frontend::GenerateModuleInterface) {
    Res.getHeaderSearchOpts().ModulesSkipDiagnosticOptions = true;
    Res.getHeaderSearchOpts().ModulesSkipHeaderSearchPaths = true;
  }
  ParseAPINotesArgs(Res.getAPINotesOpts(), Args, Diags);

  ParsePointerAuthArgs(LangOpts, Args, Diags);

  ParseLangArgs(LangOpts, Args, DashX, T, Res.getPreprocessorOpts().Includes,
                Diags);
  if (Res.getFrontendOpts().ProgramAction == frontend::RewriteObjC)
    LangOpts.ObjCExceptions = 1;

  for (auto Warning : Res.getDiagnosticOpts().Warnings) {
    if (Warning == "misexpect" &&
        !Diags.isIgnored(diag::warn_profile_data_misexpect, SourceLocation())) {
      Res.getCodeGenOpts().MisExpect = true;
    }
  }

  if (LangOpts.CUDA) {
    // During CUDA device-side compilation, the aux triple is the
    // triple used for host compilation.
    if (LangOpts.CUDAIsDevice)
      Res.getTargetOpts().HostTriple = Res.getFrontendOpts().AuxTriple;
  }

  if (LangOpts.OpenACC && !Res.getFrontendOpts().UseClangIRPipeline &&
      isCodeGenAction(Res.getFrontendOpts().ProgramAction))
    Diags.Report(diag::warn_drv_openacc_without_cir);

  // Set the triple of the host for OpenMP device compile.
  if (LangOpts.OpenMPIsTargetDevice)
    Res.getTargetOpts().HostTriple = Res.getFrontendOpts().AuxTriple;

  ParseCodeGenArgs(Res.getCodeGenOpts(), Args, DashX, Diags, T,
                   Res.getFrontendOpts().OutputFile, LangOpts);

  // FIXME: Override value name discarding when asan or msan is used because the
  // backend passes depend on the name of the alloca in order to print out
  // names.
  Res.getCodeGenOpts().DiscardValueNames &=
      !LangOpts.Sanitize.has(SanitizerKind::Address) &&
      !LangOpts.Sanitize.has(SanitizerKind::KernelAddress) &&
      !LangOpts.Sanitize.has(SanitizerKind::Memory) &&
      !LangOpts.Sanitize.has(SanitizerKind::KernelMemory);

  ParsePreprocessorArgs(Res.getPreprocessorOpts(), Args, Diags,
                        Res.getFrontendOpts().ProgramAction,
                        Res.getFrontendOpts());
  ParsePreprocessorOutputArgs(Res.getPreprocessorOutputOpts(), Args, Diags,
                              Res.getFrontendOpts().ProgramAction);

  ParseDependencyOutputArgs(Res.getDependencyOutputOpts(), Args, Diags,
                            Res.getFrontendOpts().ProgramAction,
                            Res.getPreprocessorOutputOpts().ShowLineMarkers);
  if (!Res.getDependencyOutputOpts().OutputFile.empty() &&
      Res.getDependencyOutputOpts().Targets.empty())
    Diags.Report(diag::err_fe_dependency_file_requires_MT);

  // If sanitizer is enabled, disable OPT_ffine_grained_bitfield_accesses.
  if (Res.getCodeGenOpts().FineGrainedBitfieldAccesses &&
      !Res.getLangOpts().Sanitize.empty()) {
    Res.getCodeGenOpts().FineGrainedBitfieldAccesses = false;
    Diags.Report(diag::warn_drv_fine_grained_bitfield_accesses_ignored);
  }

  // Store the command-line for using in the CodeView backend.
  if (Res.getCodeGenOpts().CodeViewCommandLine) {
    Res.getCodeGenOpts().Argv0 = Argv0;
    append_range(Res.getCodeGenOpts().CommandLineArgs, CommandLineArgs);
  }

  // Set PGOOptions. Need to create a temporary VFS to read the profile
  // to determine the PGO type.
  if (!Res.getCodeGenOpts().ProfileInstrumentUsePath.empty()) {
    auto FS =
        createVFSFromOverlayFiles(Res.getHeaderSearchOpts().VFSOverlayFiles,
                                  Diags, llvm::vfs::getRealFileSystem());
    setPGOUseInstrumentor(Res.getCodeGenOpts(),
                          Res.getCodeGenOpts().ProfileInstrumentUsePath, *FS,
                          Diags);
  }

  FixupInvocation(Res, Diags, Args, DashX);

  return Diags.getNumErrors() == NumErrorsBefore;
}

bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Invocation,
                                        ArrayRef<const char *> CommandLineArgs,
                                        DiagnosticsEngine &Diags,
                                        const char *Argv0) {
  CompilerInvocation DummyInvocation;

  return RoundTrip(
      [](CompilerInvocation &Invocation, ArrayRef<const char *> CommandLineArgs,
         DiagnosticsEngine &Diags, const char *Argv0) {
        return CreateFromArgsImpl(Invocation, CommandLineArgs, Diags, Argv0);
      },
      [](CompilerInvocation &Invocation, SmallVectorImpl<const char *> &Args,
         StringAllocator SA) {
        Args.push_back("-cc1");
        Invocation.generateCC1CommandLine(Args, SA);
      },
      Invocation, DummyInvocation, CommandLineArgs, Diags, Argv0);
}

std::string CompilerInvocation::getModuleHash() const {
  // FIXME: Consider using SHA1 instead of MD5.
  llvm::HashBuilder<llvm::MD5, llvm::endianness::native> HBuilder;

  // Note: For QoI reasons, the things we use as a hash here should all be
  // dumped via the -module-info flag.

  // Start the signature with the compiler version.
  HBuilder.add(getClangFullRepositoryVersion());

  // Also include the serialization version, in case LLVM_APPEND_VC_REV is off
  // and getClangFullRepositoryVersion() doesn't include git revision.
  HBuilder.add(serialization::VERSION_MAJOR, serialization::VERSION_MINOR);

  // Extend the signature with the language options
  // FIXME: Replace with C++20 `using enum LangOptions::CompatibilityKind`.
  using CK = LangOptions::CompatibilityKind;
#define LANGOPT(Name, Bits, Default, Compatibility, Description)               \
  if constexpr (CK::Compatibility != CK::Benign)                               \
    HBuilder.add(LangOpts->Name);
#define ENUM_LANGOPT(Name, Type, Bits, Default, Compatibility, Description)    \
  if constexpr (CK::Compatibility != CK::Benign)                               \
    HBuilder.add(static_cast<unsigned>(LangOpts->get##Name()));
#include "clang/Basic/LangOptions.def"

  HBuilder.addRange(getLangOpts().ModuleFeatures);

  HBuilder.add(getLangOpts().ObjCRuntime);
  HBuilder.addRange(getLangOpts().CommentOpts.BlockCommandNames);

  // Extend the signature with the target options.
  HBuilder.add(getTargetOpts().Triple, getTargetOpts().CPU,
               getTargetOpts().TuneCPU, getTargetOpts().ABI);
  HBuilder.addRange(getTargetOpts().FeaturesAsWritten);

  // Extend the signature with preprocessor options.
  const PreprocessorOptions &ppOpts = getPreprocessorOpts();
  HBuilder.add(ppOpts.UsePredefines, ppOpts.DetailedRecord);

  const HeaderSearchOptions &hsOpts = getHeaderSearchOpts();
  for (const auto &Macro : getPreprocessorOpts().Macros) {
    // If we're supposed to ignore this macro for the purposes of modules,
    // don't put it into the hash.
    if (!hsOpts.ModulesIgnoreMacros.empty()) {
      // Check whether we're ignoring this macro.
      StringRef MacroDef = Macro.first;
      if (hsOpts.ModulesIgnoreMacros.count(
              llvm::CachedHashString(MacroDef.split('=').first)))
        continue;
    }

    HBuilder.add(Macro);
  }

  // Extend the signature with the sysroot and other header search options.
  HBuilder.add(hsOpts.Sysroot, hsOpts.ModuleFormat, hsOpts.UseDebugInfo,
               hsOpts.UseBuiltinIncludes, hsOpts.UseStandardSystemIncludes,
               hsOpts.UseStandardCXXIncludes, hsOpts.UseLibcxx,
               hsOpts.ModulesValidateDiagnosticOptions);
  HBuilder.add(hsOpts.ResourceDir);

  if (hsOpts.ModulesStrictContextHash) {
    HBuilder.addRange(hsOpts.SystemHeaderPrefixes);
    HBuilder.addRange(hsOpts.UserEntries);
    HBuilder.addRange(hsOpts.VFSOverlayFiles);

    const DiagnosticOptions &diagOpts = getDiagnosticOpts();
#define DIAGOPT(Name, Bits, Default) HBuilder.add(diagOpts.Name);
#define ENUM_DIAGOPT(Name, Type, Bits, Default)                                \
  HBuilder.add(diagOpts.get##Name());
#include "clang/Basic/DiagnosticOptions.def"
#undef DIAGOPT
#undef ENUM_DIAGOPT
  }

  // Extend the signature with the user build path.
  HBuilder.add(hsOpts.ModuleUserBuildPath);

  // Extend the signature with the module file extensions.
  for (const auto &ext : getFrontendOpts().ModuleFileExtensions)
    ext->hashExtension(HBuilder);

  // Extend the signature with the Swift version for API notes.
  const APINotesOptions &APINotesOpts = getAPINotesOpts();
  if (!APINotesOpts.SwiftVersion.empty()) {
    HBuilder.add(APINotesOpts.SwiftVersion.getMajor());
    if (auto Minor = APINotesOpts.SwiftVersion.getMinor())
      HBuilder.add(*Minor);
    if (auto Subminor = APINotesOpts.SwiftVersion.getSubminor())
      HBuilder.add(*Subminor);
    if (auto Build = APINotesOpts.SwiftVersion.getBuild())
      HBuilder.add(*Build);
  }

  // Extend the signature with affecting codegen options.
  {
    using CK = CodeGenOptions::CompatibilityKind;
#define CODEGENOPT(Name, Bits, Default, Compatibility)                         \
  if constexpr (CK::Compatibility != CK::Benign)                               \
    HBuilder.add(CodeGenOpts->Name);
#define ENUM_CODEGENOPT(Name, Type, Bits, Default, Compatibility)              \
  if constexpr (CK::Compatibility != CK::Benign)                               \
    HBuilder.add(static_cast<unsigned>(CodeGenOpts->get##Name()));
#define DEBUGOPT(Name, Bits, Default, Compatibility)
#define VALUE_DEBUGOPT(Name, Bits, Default, Compatibility)
#define ENUM_DEBUGOPT(Name, Type, Bits, Default, Compatibility)
#include "clang/Basic/CodeGenOptions.def"
  }

  // When compiling with -gmodules, also hash -fdebug-prefix-map as it
  // affects the debug info in the PCM.
  if (getCodeGenOpts().DebugTypeExtRefs)
    HBuilder.addRange(getCodeGenOpts().DebugPrefixMap);

  // Extend the signature with the affecting debug options.
  if (getHeaderSearchOpts().ModuleFormat == "obj") {
    // FIXME: Replace with C++20 `using enum CodeGenOptions::CompatibilityKind`.
    using CK = CodeGenOptions::CompatibilityKind;
#define DEBUGOPT(Name, Bits, Default, Compatibility)                           \
  if constexpr (CK::Compatibility != CK::Benign)                               \
    HBuilder.add(CodeGenOpts->Name);
#define VALUE_DEBUGOPT(Name, Bits, Default, Compatibility)                     \
  if constexpr (CK::Compatibility != CK::Benign)                               \
    HBuilder.add(CodeGenOpts->Name);
#define ENUM_DEBUGOPT(Name, Type, Bits, Default, Compatibility)                \
  if constexpr (CK::Compatibility != CK::Benign)                               \
    HBuilder.add(static_cast<unsigned>(CodeGenOpts->get##Name()));
#include "clang/Basic/DebugOptions.def"
  }

  // Extend the signature with the enabled sanitizers, if at least one is
  // enabled. Sanitizers which cannot affect AST generation aren't hashed.
  SanitizerSet SanHash = getLangOpts().Sanitize;
  SanHash.clear(getPPTransparentSanitizers());
  if (!SanHash.empty())
    HBuilder.add(SanHash.Mask);

  llvm::MD5::MD5Result Result;
  HBuilder.getHasher().final(Result);
  uint64_t Hash = Result.high() ^ Result.low();
  return toString(llvm::APInt(64, Hash), 36, /*Signed=*/false);
}

void CompilerInvocationBase::generateCC1CommandLine(
    ArgumentConsumer Consumer) const {
  llvm::Triple T(getTargetOpts().Triple);

  GenerateFileSystemArgs(getFileSystemOpts(), Consumer);
  GenerateMigratorArgs(getMigratorOpts(), Consumer);
  GenerateAnalyzerArgs(getAnalyzerOpts(), Consumer);
  GenerateDiagnosticArgs(getDiagnosticOpts(), Consumer,
                         /*DefaultDiagColor=*/false);
  GenerateFrontendArgs(getFrontendOpts(), Consumer, getLangOpts().IsHeaderFile);
  GenerateTargetArgs(getTargetOpts(), Consumer);
  GenerateHeaderSearchArgs(getHeaderSearchOpts(), Consumer);
  GenerateAPINotesArgs(getAPINotesOpts(), Consumer);
  GeneratePointerAuthArgs(getLangOpts(), Consumer);
  GenerateLangArgs(getLangOpts(), Consumer, T, getFrontendOpts().DashX);
  GenerateCodeGenArgs(getCodeGenOpts(), Consumer, T,
                      getFrontendOpts().OutputFile, &getLangOpts());
  GeneratePreprocessorArgs(getPreprocessorOpts(), Consumer, getLangOpts(),
                           getFrontendOpts(), getCodeGenOpts());
  GeneratePreprocessorOutputArgs(getPreprocessorOutputOpts(), Consumer,
                                 getFrontendOpts().ProgramAction);
  GenerateDependencyOutputArgs(getDependencyOutputOpts(), Consumer);
}

std::vector<std::string> CompilerInvocationBase::getCC1CommandLine() const {
  std::vector<std::string> Args{"-cc1"};
  generateCC1CommandLine(
      [&Args](const Twine &Arg) { Args.push_back(Arg.str()); });
  return Args;
}

void CompilerInvocation::resetNonModularOptions() {
  getLangOpts().resetNonModularOptions();
  getPreprocessorOpts().resetNonModularOptions();
  getCodeGenOpts().resetNonModularOptions(getHeaderSearchOpts().ModuleFormat);
}

void CompilerInvocation::clearImplicitModuleBuildOptions() {
  getLangOpts().ImplicitModules = false;
  getHeaderSearchOpts().ImplicitModuleMaps = false;
  getHeaderSearchOpts().ModuleCachePath.clear();
  getHeaderSearchOpts().ModulesValidateOncePerBuildSession = false;
  getHeaderSearchOpts().BuildSessionTimestamp = 0;
  // The specific values we canonicalize to for pruning don't affect behaviour,
  /// so use the default values so they may be dropped from the command-line.
  getHeaderSearchOpts().ModuleCachePruneInterval = 7 * 24 * 60 * 60;
  getHeaderSearchOpts().ModuleCachePruneAfter = 31 * 24 * 60 * 60;
}

IntrusiveRefCntPtr<llvm::vfs::FileSystem>
clang::createVFSFromCompilerInvocation(const CompilerInvocation &CI,
                                       DiagnosticsEngine &Diags) {
  return createVFSFromCompilerInvocation(CI, Diags,
                                         llvm::vfs::getRealFileSystem());
}

IntrusiveRefCntPtr<llvm::vfs::FileSystem>
clang::createVFSFromCompilerInvocation(
    const CompilerInvocation &CI, DiagnosticsEngine &Diags,
    IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS) {
  return createVFSFromOverlayFiles(CI.getHeaderSearchOpts().VFSOverlayFiles,
                                   Diags, std::move(BaseFS));
}

IntrusiveRefCntPtr<llvm::vfs::FileSystem> clang::createVFSFromOverlayFiles(
    ArrayRef<std::string> VFSOverlayFiles, DiagnosticsEngine &Diags,
    IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS) {
  if (VFSOverlayFiles.empty())
    return BaseFS;

  IntrusiveRefCntPtr<llvm::vfs::FileSystem> Result = BaseFS;
  // earlier vfs files are on the bottom
  for (const auto &File : VFSOverlayFiles) {
    llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buffer =
        Result->getBufferForFile(File);
    if (!Buffer) {
      Diags.Report(diag::err_missing_vfs_overlay_file) << File;
      continue;
    }

    IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS = llvm::vfs::getVFSFromYAML(
        std::move(Buffer.get()), /*DiagHandler*/ nullptr, File,
        /*DiagContext*/ nullptr, Result);
    if (!FS) {
      Diags.Report(diag::err_invalid_vfs_overlay) << File;
      continue;
    }

    Result = FS;
  }
  return Result;
}
