//===- 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/DiagnosticFrontend.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/Frontend/CommandLineSourceLoc.h"
#include "clang/Frontend/DependencyOutputOptions.h"
#include "clang/Frontend/FrontendOptions.h"
#include "clang/Frontend/MigratorOptions.h"
#include "clang/Frontend/PreprocessorOutputOptions.h"
#include "clang/Frontend/SSAFOptions.h"
#include "clang/Frontend/TextDiagnosticBuffer.h"
#include "clang/Frontend/Utils.h"
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Options/Options.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 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>()),
      SSAFOpts(std::make_shared<ssaf::SSAFOptions>()) {}

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());
    SSAFOpts = make_shared_copy(X.getSSAFOpts());
  }
  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;
    SSAFOpts = X.SSAFOpts;
  }
  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);
}

ssaf::SSAFOptions &CowCompilerInvocation::getMutSSAFOpts() {
  return ensureOwned(SSAFOpts);
}

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

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

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

using ArgumentConsumer = CompilerInvocation::ArgumentConsumer;

static llvm::StringRef lookupStrInTable(unsigned Offset) {
  return getDriverOptTable().getStrTable()[Offset];
}

#define SIMPLE_ENUM_VALUE_TABLE
#include "clang/Options/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());
}

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

#define GENERATE_OPTION_WITH_MARSHALLING(                                      \
    CONSUMER, PREFIX_TYPE, SPELLING_OFFSET, ID, KIND, GROUP, ALIAS, ALIASARGS, \
    FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, VALUES, \
    SUBCOMMANDIDS_OFFSET, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE,   \
    IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, TABLE_INDEX)       \
  if ((VISIBILITY) & options::CC1Option) {                                     \
    if (ALWAYS_EMIT || (KEYPATH != static_cast<decltype(KEYPATH)>(             \
                                       ((IMPLIED_CHECK) ? (IMPLIED_VALUE)      \
                                                        : (DEFAULT_VALUE)))))  \
      DENORMALIZER(CONSUMER, SPELLING_OFFSET, Option::KIND##Class,             \
                   TABLE_INDEX, 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::Default &&
      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;
  }

  if (Args.hasArg(OPT_freflection) && !LangOpts.CPlusPlus26) {
    Diags.Report(diag::err_drv_reflection_requires_cxx26)
        << Args.getLastArg(options::OPT_freflection)->getAsString(Args);
  }

  LangOpts.NamedLoops =
      Args.hasFlag(OPT_fnamed_loops, OPT_fno_named_loops, LangOpts.C2y);

  // 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";

  // SYCL requires C++; reject C inputs on both device and host.
  if ((LangOpts.SYCLIsDevice || LangOpts.SYCLIsHost) && !LangOpts.CPlusPlus)
    Diags.Report(diag::err_drv_argument_not_allowed_with)
        << GetInputKindName(IK) << "-fsycl";

  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_fdx_rootsignature_define) && !LangOpts.HLSL)
    Diags.Report(diag::err_drv_argument_not_allowed_with)
        << "-fdx-rootsignature-define" << 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);

  // HLSL invocations should always have -Wconversion, -Wvector-conversion, and
  // -Wmatrix-conversion by default.
  if (LangOpts.HLSL) {
    auto &Warnings = Invocation.getDiagnosticOpts().Warnings;
    if (!llvm::is_contained(Warnings, "conversion"))
      Warnings.insert(Warnings.begin(), "conversion");
    if (!llvm::is_contained(Warnings, "vector-conversion"))
      Warnings.insert(Warnings.begin(), "vector-conversion");
    if (!llvm::is_contained(Warnings, "matrix-conversion"))
      Warnings.insert(Warnings.begin(), "matrix-conversion");
  }

  // 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 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(DiagnosticIDs::create(), 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 llvm::equal(A, B, [](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/Options/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 void GenerateSSAFArgs(const ssaf::SSAFOptions &Opts,
                             ArgumentConsumer Consumer) {
  const ssaf::SSAFOptions *SSAFOpts = &Opts;

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

static bool ParseSSAFArgs(ssaf::SSAFOptions &Opts, ArgList &Args,
                          DiagnosticsEngine &Diags) {
  unsigned NumErrorsBefore = Diags.getNumErrors();

  ssaf::SSAFOptions *SSAFOpts = &Opts;

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

  return Diags.getNumErrors() == NumErrorsBefore;
}

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/Options/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";
}

/// 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;
}

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);

    if (LangOpts.PointerAuthVTTVTPtrDiscrimination)
      Opts.CXXVTTVTablePointers = PointerAuthSchema(
          Key::ASDA, LangOpts.PointerAuthVTPtrAddressDiscrimination,
          LangOpts.PointerAuthVTPtrTypeDiscrimination ? Discrimination::Type
                                                      : Discrimination::None);
    else
      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);

    Opts.BlockInvocationFunctionPointers =
        PointerAuthSchema(Key::ASIA, true, Discrimination::None);
    Opts.BlockHelperFunctionPointers =
        PointerAuthSchema(Key::ASIA, true, Discrimination::None);
    Opts.BlockByrefHelperFunctionPointers =
        PointerAuthSchema(Key::ASIA, true, Discrimination::None);
    if (LangOpts.PointerAuthBlockDescriptorPointers)
      Opts.BlockDescriptorPointers =
          PointerAuthSchema(Key::ASDA, true, Discrimination::Constant,
                            BlockDescriptorConstantDiscriminator);

    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/Options/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.FuseLoops)
    GenerateArg(Consumer, OPT_fexperimental_loop_fusion);

  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");

  if (!Opts.SaveDynDbgTempsFilePrefix.empty())
    GenerateArg(Consumer, OPT_save_dynamic_debugging_temps);

  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.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();

  Opts.OptimizationLevel = getOptimizationLevel(Args, IK, Diags);

  // 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/Options/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);
  }

  if (Opts.OptimizationLevel > 0 && Opts.hasReducedDebugInfo() &&
      T.supportsDebugEntryValues())
    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));
  // Match the LLVM pipeline default (PipelineTuningOptions::LoopInterchange),
  // which enables the pass whenever the optimization pipeline runs.
  Opts.InterchangeLoops =
      Args.hasFlag(OPT_floop_interchange, OPT_fno_loop_interchange, true);
  Opts.FuseLoops = Args.hasFlag(OPT_fexperimental_loop_fusion,
                                OPT_fno_experimental_loop_fusion, 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 (Args.hasArg(OPT_ftime_report, OPT_ftime_report_EQ, OPT_ftime_report_json,
                  OPT_stats_file_timers)) {
    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)
            << EQ->getAsString(Args) << EQ->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());

  if (Args.getLastArg(OPT_save_dynamic_debugging_temps))
    Opts.SaveDynDbgTempsFilePrefix = OutputFile;

  // 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.StackUsageFile.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);

  if (!Opts.HLSLRecordCommandLine.empty()) {
    auto ParsedArgs =
        clang::parseEscapedCommandLine(Opts.HLSLRecordCommandLine.c_str());
    if (!ParsedArgs)
      Diags.Report(diag::err_drv_invalid_escaped_command_line)
          << llvm::toString(ParsedArgs.takeError());
    else
      Opts.HLSLParsedCommandLine = std::move(*ParsedArgs);
  }

  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/Options/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/Options/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 ShowColorsKind parseShowColorsMode(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].
  ShowColorsKind Mode =
      DefaultColor ? ShowColorsKind::Auto : ShowColorsKind::Off;
  for (auto *A : Args) {
    const Option &O = A->getOption();
    if (O.matches(options::OPT_fcolor_diagnostics)) {
      Mode = ShowColorsKind::On;
    } else if (O.matches(options::OPT_fno_color_diagnostics)) {
      Mode = ShowColorsKind::Off;
    } else if (O.matches(options::OPT_fdiagnostics_color_EQ)) {
      StringRef Value(A->getValue());
      if (Value == "always")
        Mode = ShowColorsKind::On;
      else if (Value == "never")
        Mode = ShowColorsKind::Off;
      else if (Value == "auto")
        Mode = ShowColorsKind::Auto;
    }
  }
  return Mode;
}

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/Options/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/Options/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/Options/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/Options/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/Options/Options.inc"
#undef DIAG_OPTION_WITH_MARSHALLING

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

  switch (Opts.getShowColors()) {
  case ShowColorsKind::On:
    GenerateArg(Consumer, OPT_fcolor_diagnostics);
    break;
  case ShowColorsKind::Off:
    GenerateArg(Consumer, OPT_fno_color_diagnostics);
    break;
  case ShowColorsKind::Auto:
    break;
  }

  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);

  if (Opts.VerifyDirectives) {
    GenerateArg(Consumer, OPT_verify_directives);
  }

  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(DiagnosticIDs::create(), *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/Options/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.setShowColors(parseShowColorsMode(Args, DefaultDiagColor));

  Opts.VerifyDiagnostics = Args.hasArg(OPT_verify) || Args.hasArg(OPT_verify_EQ);
  Opts.VerifyDirectives = Args.hasArg(OPT_verify_directives);
  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;
}

unsigned clang::getOptimizationLevel(const 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) ||
        A->getOption().matches(options::OPT_O4))
      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;

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

  unsigned MaxOptLevel = 3;
  if (DefaultOpt > 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;
    DefaultOpt = MaxOptLevel;
  }

  return DefaultOpt;
}

unsigned clang::getOptimizationLevelSize(const 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;
}

/// 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::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/Options/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/Options/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_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;

  if (Args.hasArg(OPT_clangir_lib_opt) || Args.hasArg(OPT_clangir_lib_opt_EQ))
    Opts.ClangIRLibOptEnabled = 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;

  // CIR is a source-level frontend pipeline. When the input is already LLVM IR
  // (e.g. during the backend phase of OpenMP offloading), the standard LLVM
  // backend should be used instead.
  if (Opts.UseClangIRPipeline && DashX.getLanguage() == Language::LLVM_IR)
    Opts.UseClangIRPipeline = false;

  return Diags.getNumErrors() == NumErrorsBefore;
}

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/Options/Options.inc"
#undef HEADER_SEARCH_OPTION_WITH_MARSHALLING

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

  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());

  for (const auto &Path : Opts.ModulesIgnoreSearchPaths)
    GenerateArg(Consumer, OPT_fmodules_ignore_search_path, Path.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) {
  unsigned NumErrorsBefore = Diags.getNumErrors();

  HeaderSearchOptions *HeaderSearchOpts = &Opts;

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

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

  // 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));
  }

  for (const auto *A : Args.filtered(OPT_fmodules_ignore_search_path))
    Opts.ModulesIgnoreSearchPaths.insert(llvm::CachedHashString(A->getValue()));

  // 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.PointerAuthVTTVTPtrDiscrimination)
    GenerateArg(Consumer, OPT_fptrauth_vtt_vtable_pointer_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);
  if (Opts.PointerAuthBlockDescriptorPointers)
    GenerateArg(Consumer, OPT_fptrauth_block_descriptor_pointers);
}

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.PointerAuthVTTVTPtrDiscrimination =
      Args.hasArg(OPT_fptrauth_vtt_vtable_pointer_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.PointerAuthBlockDescriptorPointers =
      Args.hasArg(OPT_fptrauth_block_descriptor_pointers);
  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);
    for (StringRef Sanitizer :
         serializeSanitizerKinds(Opts.UBSanFeatureIgnoredSanitize))
      GenerateArg(Consumer, OPT_fsanitize_ignore_for_ubsan_feature_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/Options/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) {
    if (!Opts.MSVCCompat)
      GenerateArg(Consumer, OPT_fwrapv);
  } else if (Opts.MSVCCompat) {
    GenerateArg(Consumer, OPT_fno_wrapv);
  }
  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.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.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);
  for (StringRef Sanitizer :
       serializeSanitizerKinds(Opts.UBSanFeatureIgnoredSanitize))
    GenerateArg(Consumer, OPT_fsanitize_ignore_for_ubsan_feature_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()) {
#define ABI_VER_MAJOR_MINOR(Major, Minor)                                      \
  case LangOptions::ClangABI::Ver##Major##_##Minor:                            \
    GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, #Major "." #Minor);        \
    break;
#define ABI_VER_MAJOR(Major)                                                   \
  case LangOptions::ClangABI::Ver##Major:                                      \
    GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, #Major ".0");              \
    break;
#define ABI_VER_LATEST(Latest)                                                 \
  case LangOptions::ClangABI::Latest:                                          \
    break;
#include "clang/Basic/ABIVersions.def"
  }

  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);

  if (Opts.AllocTokenMax)
    GenerateArg(Consumer, OPT_falloc_token_max_EQ,
                std::to_string(*Opts.AllocTokenMax));

  if (Opts.AllocTokenMode) {
    StringRef S = llvm::getAllocTokenModeAsString(*Opts.AllocTokenMode);
    GenerateArg(Consumer, OPT_falloc_token_mode_EQ, S);
  }
  // Generate args for matrix types.
  if (Opts.MatrixTypes) {
    if (Opts.getDefaultMatrixMemoryLayout() ==
        LangOptions::MatrixMemoryLayout::MatrixColMajor)
      GenerateArg(Consumer, OPT_fmatrix_memory_layout_EQ, "column-major");
    if (Opts.getDefaultMatrixMemoryLayout() ==
        LangOptions::MatrixMemoryLayout::MatrixRowMajor)
      GenerateArg(Consumer, OPT_fmatrix_memory_layout_EQ, "row-major");
  }
}

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);
    parseSanitizerKinds(
        "-fsanitize-ignore-for-ubsan-feature=",
        Args.getAllArgValues(OPT_fsanitize_ignore_for_ubsan_feature_EQ), Diags,
        Opts.UBSanFeatureIgnoredSanitize);

    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, version)
#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, version)
#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({"cl3.1", "CL3.1"}, LangStandard::lang_opencl31)
            .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/Options/Options.inc"
#undef LANG_OPTION_WITH_MARSHALLING

  // "Modules semantics" (e.g. cross-translation-unit declaration merging) are
  // needed for both Clang (header) modules and C++20 modules, so enable them
  // for either.
  Opts.Modules = Opts.ClangModules || Opts.CPlusPlusModules;

  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.hasFlag(OPT_fwrapv, OPT_fno_wrapv, Opts.MSVCCompat)) {
    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.isGPU()) || 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);
  }

  // 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);
    }
  }

  // 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);
  parseSanitizerKinds(
      "-fsanitize-ignore-for-ubsan-feature=",
      Args.getAllArgValues(OPT_fsanitize_ignore_for_ubsan_feature_EQ), Diags,
      Opts.UBSanFeatureIgnoredSanitize);
  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('.');
    int 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.
#define ABI_VER_MAJOR_MINOR(Major_, Minor_)                                    \
  if (std::tuple(Major, Minor) <= std::tuple(Major_, Minor_))                  \
    Opts.setClangABICompat(LangOptions::ClangABI::Ver##Major_##_##Minor_);     \
  else
#define ABI_VER_MAJOR(Major_)                                                  \
  if (Major <= Major_)                                                         \
    Opts.setClangABICompat(LangOptions::ClangABI::Ver##Major_);                \
  else
#define ABI_VER_LATEST(Latest)                                                 \
  { /* Equivalent to latest version - do nothing */                            \
  }
#include "clang/Basic/ABIVersions.def"
    } 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);

  if (const auto *Arg = Args.getLastArg(options::OPT_falloc_token_max_EQ)) {
    StringRef S = Arg->getValue();
    uint64_t Value = 0;
    if (S.getAsInteger(0, Value))
      Diags.Report(diag::err_drv_invalid_value) << Arg->getAsString(Args) << S;
    else
      Opts.AllocTokenMax = Value;
  }

  if (const auto *Arg = Args.getLastArg(options::OPT_falloc_token_mode_EQ)) {
    StringRef S = Arg->getValue();
    if (auto Mode = getAllocTokenModeFromString(S))
      Opts.AllocTokenMode = Mode;
    else
      Diags.Report(diag::err_drv_invalid_value) << Arg->getAsString(Args) << S;
  }

  // Enable options for matrix types.
  if (Opts.MatrixTypes) {
    if (const Arg *A = Args.getLastArg(OPT_fmatrix_memory_layout_EQ)) {
      StringRef ClangValue = A->getValue();
      if (ClangValue == "row-major")
        Opts.setDefaultMatrixMemoryLayout(
            LangOptions::MatrixMemoryLayout::MatrixRowMajor);
      else
        Opts.setDefaultMatrixMemoryLayout(
            LangOptions::MatrixMemoryLayout::MatrixColMajor);

      for (Arg *A : Args.filtered(options::OPT_mllvm)) {
        StringRef OptValue = A->getValue();
        if (OptValue.consume_front("-matrix-default-layout=") &&
            ClangValue != OptValue)
          Diags.Report(diag::err_conflicting_matrix_layout_flags)
              << ClangValue << OptValue;
      }
    }
  }

  // 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) ||
            Args.getLastArg(OPT_fnative_int16_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) ||
            Args.getLastArg(OPT_fnative_int16_type)) {
          const char *Str = Args.getLastArg(OPT_fnative_half_type)
                                ? "-fnative-half-type"
                                : "-fnative-int16-type";
          const LangStandard &Std =
              LangStandard::getLangStandardForKind(Opts.LangStd);
          if (!(Opts.LangStd >= LangStandard::lang_hlsl2018))
            Diags.Report(diag::err_drv_hlsl_16bit_types_unsupported)
                << Str << 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:
    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::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/Options/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/Options/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/Options/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/Options/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/Options/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());

  // Generate AMDGPU xnack and sramecc flags.
  if (Opts.AMDGPUXnackState == TargetOptions::AMDGPUFeatureState::Enabled)
    GenerateArg(Consumer, OPT_mxnack);
  else if (Opts.AMDGPUXnackState == TargetOptions::AMDGPUFeatureState::Disabled)
    GenerateArg(Consumer, OPT_mno_xnack);

  if (Opts.AMDGPUSramEccState == TargetOptions::AMDGPUFeatureState::Enabled)
    GenerateArg(Consumer, OPT_msramecc);
  else if (Opts.AMDGPUSramEccState ==
           TargetOptions::AMDGPUFeatureState::Disabled)
    GenerateArg(Consumer, OPT_mno_sramecc);
}

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/Options/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;
  }

  if (Arg *A = Args.getLastArg(options::OPT_mxnack, options::OPT_mno_xnack)) {
    bool IsEnabled = A->getOption().matches(options::OPT_mxnack);
    Opts.AMDGPUXnackState = IsEnabled
                                ? TargetOptions::AMDGPUFeatureState::Enabled
                                : TargetOptions::AMDGPUFeatureState::Disabled;
  }

  if (Arg *A =
          Args.getLastArg(options::OPT_msramecc, options::OPT_mno_sramecc)) {
    bool IsEnabled = A->getOption().matches(options::OPT_msramecc);
    Opts.AMDGPUSramEccState = IsEnabled
                                  ? TargetOptions::AMDGPUFeatureState::Enabled
                                  : TargetOptions::AMDGPUFeatureState::Disabled;
  }

  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);
  ParseSSAFArgs(Res.getSSAFOpts(), Args, Diags);
  ParseDiagnosticArgs(Res.getDiagnosticOpts(), Args, &Diags);
  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);
  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;

  // Set the default and host triples for SYCL device compilation.
  if (LangOpts.SYCLIsDevice) {
    if (!Args.hasArg(options::OPT_triple))
      Res.getTargetOpts().Triple = "spirv64-unknown-unknown";
    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);
  }

  if (!Res.getCodeGenOpts().ProfileInstrumentUsePath.empty() &&
      Res.getCodeGenOpts().getProfileUse() ==
          llvm::driver::ProfileInstrKind::ProfileNone)
    Diags.Report(diag::err_drv_profile_instrument_use_path_with_no_kind);

  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::computeContextHash() 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
  const unsigned LanguageOptionValues[] = {
#define HASH_LANGOPT_Benign(Value)
#define HASH_LANGOPT_Compatible(Value) Value,
#define HASH_LANGOPT_NotCompatible(Value) Value,
#define LANGOPT(Name, Bits, Default, Compatibility, Description)               \
  HASH_LANGOPT_##Compatibility(LangOpts->Name)
#define ENUM_LANGOPT(Name, Type, Bits, Default, Compatibility, Description)    \
  HASH_LANGOPT_##Compatibility(static_cast<unsigned>(LangOpts->get##Name()))
#include "clang/Basic/LangOptions.def"
  };
#undef HASH_LANGOPT_Benign
#undef HASH_LANGOPT_Compatible
#undef HASH_LANGOPT_NotCompatible
  // addRangeElements preserves the HBuilder.add sequence and excludes the
  // LanguageOptionValues element count.
  HBuilder.addRangeElements(LanguageOptionValues);

  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);

    for (const auto &UserEntry : hsOpts.UserEntries) {
      // If we're supposed to ignore this search path for the purposes of
      // modules, don't put it into the hash.
      if (!hsOpts.ModulesIgnoreSearchPaths.empty()) {
        // Check whether we're ignoring this search path.
        StringRef Path = UserEntry.Path;
        if (hsOpts.ModulesIgnoreSearchPaths.count(llvm::CachedHashString(Path)))
          continue;
      }

      HBuilder.add(UserEntry);
    }

    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 CowCompilerInvocation::visitMutPaths(
    llvm::function_ref<VisitMutResult(StringRef, std::string &)> Cb) {
  std::string NewValue;

#define RETURN_IF(OPTS, PATH)                                                  \
  do {                                                                         \
    VisitMutResult Res = Cb(PATH, NewValue);                                   \
    if (Res.Replace) {                                                         \
      (void)ensureOwned(OPTS);                                                 \
      PATH.clear();                                                            \
      std::swap(PATH, NewValue);                                               \
    }                                                                          \
    if (Res.Terminate)                                                         \
      return;                                                                  \
  } while (0)

#define RETURN_IF_MANY(OPTS, PATHS)                                            \
  do {                                                                         \
    for (unsigned I = 0, E = PATHS.size(); I != E; ++I)                        \
      RETURN_IF(OPTS, PATHS[I]);                                               \
  } while (0)

  // Header search paths.
  RETURN_IF(HSOpts, HSOpts->Sysroot);
  for (auto &Entry : HSOpts->UserEntries)
    if (Entry.IgnoreSysRoot)
      RETURN_IF(HSOpts, Entry.Path);
  RETURN_IF(HSOpts, HSOpts->ResourceDir);
  RETURN_IF(HSOpts, HSOpts->ModuleCachePath);
  RETURN_IF(HSOpts, HSOpts->ModuleUserBuildPath);
  for (auto &[Name, File] : HSOpts->PrebuiltModuleFiles)
    RETURN_IF(HSOpts, File);
  RETURN_IF_MANY(HSOpts, HSOpts->PrebuiltModulePaths);
  RETURN_IF_MANY(HSOpts, HSOpts->VFSOverlayFiles);

  // Preprocessor options.
  RETURN_IF_MANY(PPOpts, PPOpts->MacroIncludes);
  RETURN_IF_MANY(PPOpts, PPOpts->Includes);
  RETURN_IF(PPOpts, PPOpts->ImplicitPCHInclude);

  // Frontend options.
  for (auto &Input : FrontendOpts->Inputs) {
    if (Input.isBuffer())
      continue;

    RETURN_IF(FrontendOpts, Input.File);
  }
  // TODO: Also report output files such as FrontendOpts->OutputFile;
  RETURN_IF(FrontendOpts, FrontendOpts->CodeCompletionAt.FileName);
  RETURN_IF_MANY(FrontendOpts, FrontendOpts->ModuleMapFiles);
  RETURN_IF_MANY(FrontendOpts, FrontendOpts->ModuleFiles);
  RETURN_IF_MANY(FrontendOpts, FrontendOpts->ModulesEmbedFiles);
  RETURN_IF_MANY(FrontendOpts, FrontendOpts->ASTMergeFiles);
  RETURN_IF(FrontendOpts, FrontendOpts->OverrideRecordLayoutsFile);
  RETURN_IF(FrontendOpts, FrontendOpts->StatsFile);

  // Filesystem options.
  RETURN_IF(FSOpts, FSOpts->WorkingDir);

  // Codegen options.
  RETURN_IF(CodeGenOpts, CodeGenOpts->DebugCompilationDir);
  RETURN_IF(CodeGenOpts, CodeGenOpts->CoverageCompilationDir);

  // Sanitizer options.
  RETURN_IF_MANY(LangOpts, LangOpts->NoSanitizeFiles);

  // Coverage mappings.
  RETURN_IF(CodeGenOpts, CodeGenOpts->ProfileInstrumentUsePath);
  RETURN_IF(CodeGenOpts, CodeGenOpts->SampleProfileFile);
  RETURN_IF(CodeGenOpts, CodeGenOpts->ProfileRemappingFile);

  // Dependency output options.
  for (auto &ExtraDep : DependencyOutputOpts->ExtraDeps)
    RETURN_IF(DependencyOutputOpts, ExtraDep.first);
}

void CowCompilerInvocation::visitPaths(
    llvm::function_ref<VisitConstResult(StringRef)> Cb) const {
  // The const_cast here is OK, because our callback never tries to modify.
  return const_cast<CowCompilerInvocation *>(this)->visitMutPaths(
      [&Cb](StringRef Path, std::string &) { return Cb(Path); });
}

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

  GenerateFileSystemArgs(getFileSystemOpts(), Consumer);
  GenerateMigratorArgs(getMigratorOpts(), Consumer);
  GenerateAnalyzerArgs(getAnalyzerOpts(), Consumer);
  GenerateSSAFArgs(getSSAFOpts(), 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;
}
