//===-- Options.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 "Options.h"
#include "clang/Basic/DiagnosticIDs.h"
#include "clang/Driver/Driver.h"
#include "clang/InstallAPI/FileList.h"
#include "clang/InstallAPI/HeaderFile.h"
#include "clang/InstallAPI/InstallAPIDiagnostic.h"
#include "llvm/BinaryFormat/Magic.h"
#include "llvm/Support/Program.h"
#include "llvm/TargetParser/Host.h"
#include "llvm/TextAPI/DylibReader.h"
#include "llvm/TextAPI/TextAPIError.h"
#include "llvm/TextAPI/TextAPIReader.h"
#include "llvm/TextAPI/TextAPIWriter.h"

using namespace llvm;
using namespace llvm::opt;
using namespace llvm::MachO;

namespace drv = clang::driver::options;

namespace clang {
namespace installapi {

/// Create prefix string literals used in InstallAPIOpts.td.
#define PREFIX(NAME, VALUE)                                                    \
  static constexpr llvm::StringLiteral NAME##_init[] = VALUE;                  \
  static constexpr llvm::ArrayRef<llvm::StringLiteral> NAME(                   \
      NAME##_init, std::size(NAME##_init) - 1);
#include "InstallAPIOpts.inc"
#undef PREFIX

static constexpr const llvm::StringLiteral PrefixTable_init[] =
#define PREFIX_UNION(VALUES) VALUES
#include "InstallAPIOpts.inc"
#undef PREFIX_UNION
    ;
static constexpr const ArrayRef<StringLiteral>
    PrefixTable(PrefixTable_init, std::size(PrefixTable_init) - 1);

/// Create table mapping all options defined in InstallAPIOpts.td.
static constexpr OptTable::Info InfoTable[] = {
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS,         \
               VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR,     \
               VALUES)                                                         \
  {PREFIX,                                                                     \
   NAME,                                                                       \
   HELPTEXT,                                                                   \
   HELPTEXTSFORVARIANTS,                                                       \
   METAVAR,                                                                    \
   OPT_##ID,                                                                   \
   Option::KIND##Class,                                                        \
   PARAM,                                                                      \
   FLAGS,                                                                      \
   VISIBILITY,                                                                 \
   OPT_##GROUP,                                                                \
   OPT_##ALIAS,                                                                \
   ALIASARGS,                                                                  \
   VALUES},
#include "InstallAPIOpts.inc"
#undef OPTION
};

namespace {

/// \brief Create OptTable class for parsing actual command line arguments.
class DriverOptTable : public opt::PrecomputedOptTable {
public:
  DriverOptTable() : PrecomputedOptTable(InfoTable, PrefixTable) {}
};

} // end anonymous namespace.

static llvm::opt::OptTable *createDriverOptTable() {
  return new DriverOptTable();
}

bool Options::processDriverOptions(InputArgList &Args) {
  // Handle inputs.
  llvm::append_range(DriverOpts.FileLists,
                     Args.getAllArgValues(drv::OPT_INPUT));

  // Handle output.
  SmallString<PATH_MAX> OutputPath;
  if (auto *Arg = Args.getLastArg(drv::OPT_o)) {
    OutputPath = Arg->getValue();
    if (OutputPath != "-")
      FM->makeAbsolutePath(OutputPath);
    DriverOpts.OutputPath = std::string(OutputPath);
  }
  if (DriverOpts.OutputPath.empty()) {
    Diags->Report(diag::err_no_output_file);
    return false;
  }

  // Do basic error checking first for mixing -target and -arch options.
  auto *ArgArch = Args.getLastArgNoClaim(drv::OPT_arch);
  auto *ArgTarget = Args.getLastArgNoClaim(drv::OPT_target);
  auto *ArgTargetVariant =
      Args.getLastArgNoClaim(drv::OPT_darwin_target_variant);
  if (ArgArch && (ArgTarget || ArgTargetVariant)) {
    Diags->Report(clang::diag::err_drv_argument_not_allowed_with)
        << ArgArch->getAsString(Args)
        << (ArgTarget ? ArgTarget : ArgTargetVariant)->getAsString(Args);
    return false;
  }

  auto *ArgMinTargetOS = Args.getLastArgNoClaim(drv::OPT_mtargetos_EQ);
  if ((ArgTarget || ArgTargetVariant) && ArgMinTargetOS) {
    Diags->Report(clang::diag::err_drv_cannot_mix_options)
        << ArgTarget->getAsString(Args) << ArgMinTargetOS->getAsString(Args);
    return false;
  }

  // Capture target triples first.
  if (ArgTarget) {
    for (const Arg *A : Args.filtered(drv::OPT_target)) {
      A->claim();
      llvm::Triple TargetTriple(A->getValue());
      Target TAPITarget = Target(TargetTriple);
      if ((TAPITarget.Arch == AK_unknown) ||
          (TAPITarget.Platform == PLATFORM_UNKNOWN)) {
        Diags->Report(clang::diag::err_drv_unsupported_opt_for_target)
            << "installapi" << TargetTriple.str();
        return false;
      }
      DriverOpts.Targets[TAPITarget] = TargetTriple;
    }
  }

  // Capture target variants.
  DriverOpts.Zippered = ArgTargetVariant != nullptr;
  for (Arg *A : Args.filtered(drv::OPT_darwin_target_variant)) {
    A->claim();
    Triple Variant(A->getValue());
    if (Variant.getVendor() != Triple::Apple) {
      Diags->Report(diag::err_unsupported_vendor)
          << Variant.getVendorName() << A->getAsString(Args);
      return false;
    }

    switch (Variant.getOS()) {
    default:
      Diags->Report(diag::err_unsupported_os)
          << Variant.getOSName() << A->getAsString(Args);
      return false;
    case Triple::MacOSX:
    case Triple::IOS:
      break;
    }

    switch (Variant.getEnvironment()) {
    default:
      Diags->Report(diag::err_unsupported_environment)
          << Variant.getEnvironmentName() << A->getAsString(Args);
      return false;
    case Triple::UnknownEnvironment:
    case Triple::MacABI:
      break;
    }

    Target TAPIVariant(Variant);
    // See if there is a matching --target option for this --target-variant
    // option.
    auto It = find_if(DriverOpts.Targets, [&](const auto &T) {
      return (T.first.Arch == TAPIVariant.Arch) &&
             (T.first.Platform != PlatformType::PLATFORM_UNKNOWN);
    });

    if (It == DriverOpts.Targets.end()) {
      Diags->Report(diag::err_no_matching_target) << Variant.str();
      return false;
    }

    DriverOpts.Targets[TAPIVariant] = Variant;
  }

  DriverOpts.Verbose = Args.hasArgNoClaim(drv::OPT_v);

  return true;
}

bool Options::processInstallAPIXOptions(InputArgList &Args) {
  for (arg_iterator It = Args.begin(), End = Args.end(); It != End; ++It) {
    Arg *A = *It;
    if (A->getOption().matches(OPT_Xarch__)) {
      if (!processXarchOption(Args, It))
        return false;
      continue;
    } else if (A->getOption().matches(OPT_Xplatform__)) {
      if (!processXplatformOption(Args, It))
        return false;
      continue;
    } else if (A->getOption().matches(OPT_Xproject)) {
      if (!processXprojectOption(Args, It))
        return false;
      continue;
    } else if (!A->getOption().matches(OPT_X__))
      continue;

    // Handle any user defined labels.
    const StringRef Label = A->getValue(0);

    // Ban "public" and "private" labels.
    if ((Label.lower() == "public") || (Label.lower() == "private")) {
      Diags->Report(diag::err_invalid_label) << Label;
      return false;
    }

    auto NextIt = std::next(It);
    if (NextIt == End) {
      Diags->Report(clang::diag::err_drv_missing_argument)
          << A->getAsString(Args) << 1;
      return false;
    }
    Arg *NextA = *NextIt;
    switch ((ID)NextA->getOption().getID()) {
    case OPT_D:
    case OPT_U:
      break;
    default:
      Diags->Report(clang::diag::err_drv_argument_not_allowed_with)
          << A->getAsString(Args) << NextA->getAsString(Args);
      return false;
    }
    const StringRef ASpelling = NextA->getSpelling();
    const auto &AValues = NextA->getValues();
    if (AValues.empty())
      FEOpts.UniqueArgs[Label].emplace_back(ASpelling.str());
    else
      for (const StringRef Val : AValues)
        FEOpts.UniqueArgs[Label].emplace_back((ASpelling + Val).str());

    A->claim();
    NextA->claim();
  }

  return true;
}

bool Options::processXplatformOption(InputArgList &Args, arg_iterator Curr) {
  Arg *A = *Curr;

  PlatformType Platform = getPlatformFromName(A->getValue(0));
  if (Platform == PLATFORM_UNKNOWN) {
    Diags->Report(diag::err_unsupported_os)
        << getPlatformName(Platform) << A->getAsString(Args);
    return false;
  }
  auto NextIt = std::next(Curr);
  if (NextIt == Args.end()) {
    Diags->Report(diag::err_drv_missing_argument) << A->getAsString(Args) << 1;
    return false;
  }

  Arg *NextA = *NextIt;
  switch ((ID)NextA->getOption().getID()) {
  case OPT_iframework:
    FEOpts.SystemFwkPaths.emplace_back(NextA->getValue(), Platform);
    break;
  default:
    Diags->Report(diag::err_drv_invalid_argument_to_option)
        << A->getAsString(Args) << NextA->getAsString(Args);
    return false;
  }

  A->claim();
  NextA->claim();

  return true;
}

bool Options::processXprojectOption(InputArgList &Args, arg_iterator Curr) {
  Arg *A = *Curr;
  auto NextIt = std::next(Curr);
  if (NextIt == Args.end()) {
    Diags->Report(diag::err_drv_missing_argument) << A->getAsString(Args) << 1;
    return false;
  }

  Arg *NextA = *NextIt;
  switch ((ID)NextA->getOption().getID()) {
  case OPT_fobjc_arc:
  case OPT_fmodules:
  case OPT_fmodules_cache_path:
  case OPT_include_:
  case OPT_fvisibility_EQ:
    break;
  default:
    Diags->Report(diag::err_drv_argument_not_allowed_with)
        << A->getAsString(Args) << NextA->getAsString(Args);
    return false;
  }

  std::string ArgString = NextA->getSpelling().str();
  for (const StringRef Val : NextA->getValues())
    ArgString += Val.str();

  ProjectLevelArgs.push_back(ArgString);
  A->claim();
  NextA->claim();

  return true;
}

bool Options::processXarchOption(InputArgList &Args, arg_iterator Curr) {
  Arg *CurrArg = *Curr;
  Architecture Arch = getArchitectureFromName(CurrArg->getValue(0));
  if (Arch == AK_unknown) {
    Diags->Report(diag::err_drv_invalid_arch_name)
        << CurrArg->getAsString(Args);
    return false;
  }

  auto NextIt = std::next(Curr);
  if (NextIt == Args.end()) {
    Diags->Report(diag::err_drv_missing_argument)
        << CurrArg->getAsString(Args) << 1;
    return false;
  }

  // InstallAPI has a limited understanding of supported Xarch options.
  // Currently this is restricted to linker inputs.
  const Arg *NextArg = *NextIt;
  switch (NextArg->getOption().getID()) {
  case OPT_allowable_client:
  case OPT_reexport_l:
  case OPT_reexport_framework:
  case OPT_reexport_library:
  case OPT_rpath:
    break;
  default:
    Diags->Report(diag::err_drv_invalid_argument_to_option)
        << NextArg->getAsString(Args) << CurrArg->getAsString(Args);
    return false;
  }

  ArgToArchMap[NextArg] = Arch;
  CurrArg->claim();

  return true;
}

bool Options::processLinkerOptions(InputArgList &Args) {
  // Handle required arguments.
  if (const Arg *A = Args.getLastArg(drv::OPT_install__name))
    LinkerOpts.InstallName = A->getValue();
  if (LinkerOpts.InstallName.empty()) {
    Diags->Report(diag::err_no_install_name);
    return false;
  }

  // Defaulted or optional arguments.
  if (auto *Arg = Args.getLastArg(drv::OPT_current__version))
    LinkerOpts.CurrentVersion.parse64(Arg->getValue());

  if (auto *Arg = Args.getLastArg(drv::OPT_compatibility__version))
    LinkerOpts.CompatVersion.parse64(Arg->getValue());

  if (auto *Arg = Args.getLastArg(drv::OPT_compatibility__version))
    LinkerOpts.CompatVersion.parse64(Arg->getValue());

  if (auto *Arg = Args.getLastArg(drv::OPT_umbrella))
    LinkerOpts.ParentUmbrella = Arg->getValue();

  LinkerOpts.IsDylib = Args.hasArg(drv::OPT_dynamiclib);

  for (auto *Arg : Args.filtered(drv::OPT_alias_list)) {
    LinkerOpts.AliasLists.emplace_back(Arg->getValue());
    Arg->claim();
  }

  LinkerOpts.AppExtensionSafe = Args.hasFlag(
      drv::OPT_fapplication_extension, drv::OPT_fno_application_extension,
      /*Default=*/LinkerOpts.AppExtensionSafe);

  if (::getenv("LD_NO_ENCRYPT") != nullptr)
    LinkerOpts.AppExtensionSafe = true;

  if (::getenv("LD_APPLICATION_EXTENSION_SAFE") != nullptr)
    LinkerOpts.AppExtensionSafe = true;

  // Capture library paths.
  PathSeq LibraryPaths;
  for (const Arg *A : Args.filtered(drv::OPT_L)) {
    LibraryPaths.emplace_back(A->getValue());
    A->claim();
  }

  if (!LibraryPaths.empty())
    LinkerOpts.LibPaths = std::move(LibraryPaths);

  return true;
}

// NOTE: Do not claim any arguments, as they will be passed along for CC1
// invocations.
bool Options::processFrontendOptions(InputArgList &Args) {
  // Capture language mode.
  if (auto *A = Args.getLastArgNoClaim(drv::OPT_x)) {
    FEOpts.LangMode = llvm::StringSwitch<clang::Language>(A->getValue())
                          .Case("c", clang::Language::C)
                          .Case("c++", clang::Language::CXX)
                          .Case("objective-c", clang::Language::ObjC)
                          .Case("objective-c++", clang::Language::ObjCXX)
                          .Default(clang::Language::Unknown);

    if (FEOpts.LangMode == clang::Language::Unknown) {
      Diags->Report(clang::diag::err_drv_invalid_value)
          << A->getAsString(Args) << A->getValue();
      return false;
    }
  }
  for (auto *A : Args.filtered(drv::OPT_ObjC, drv::OPT_ObjCXX)) {
    if (A->getOption().matches(drv::OPT_ObjC))
      FEOpts.LangMode = clang::Language::ObjC;
    else
      FEOpts.LangMode = clang::Language::ObjCXX;
  }

  // Capture Sysroot.
  if (const Arg *A = Args.getLastArgNoClaim(drv::OPT_isysroot)) {
    SmallString<PATH_MAX> Path(A->getValue());
    FM->makeAbsolutePath(Path);
    if (!FM->getOptionalDirectoryRef(Path)) {
      Diags->Report(diag::err_missing_sysroot) << Path;
      return false;
    }
    FEOpts.ISysroot = std::string(Path);
  } else if (FEOpts.ISysroot.empty()) {
    // Mirror CLANG and obtain the isysroot from the SDKROOT environment
    // variable, if it wasn't defined by the  command line.
    if (auto *Env = ::getenv("SDKROOT")) {
      if (StringRef(Env) != "/" && llvm::sys::path::is_absolute(Env) &&
          FM->getOptionalFileRef(Env))
        FEOpts.ISysroot = Env;
    }
  }

  // Capture system frameworks for all platforms.
  for (const Arg *A : Args.filtered(drv::OPT_iframework))
    FEOpts.SystemFwkPaths.emplace_back(A->getValue(),
                                       std::optional<PlatformType>{});

  // Capture framework paths.
  PathSeq FrameworkPaths;
  for (const Arg *A : Args.filtered(drv::OPT_F))
    FrameworkPaths.emplace_back(A->getValue());

  if (!FrameworkPaths.empty())
    FEOpts.FwkPaths = std::move(FrameworkPaths);

  // Add default framework/library paths.
  PathSeq DefaultLibraryPaths = {"/usr/lib", "/usr/local/lib"};
  PathSeq DefaultFrameworkPaths = {"/Library/Frameworks",
                                   "/System/Library/Frameworks"};

  for (const StringRef LibPath : DefaultLibraryPaths) {
    SmallString<PATH_MAX> Path(FEOpts.ISysroot);
    sys::path::append(Path, LibPath);
    LinkerOpts.LibPaths.emplace_back(Path.str());
  }
  for (const StringRef FwkPath : DefaultFrameworkPaths) {
    SmallString<PATH_MAX> Path(FEOpts.ISysroot);
    sys::path::append(Path, FwkPath);
    FEOpts.SystemFwkPaths.emplace_back(Path.str(),
                                       std::optional<PlatformType>{});
  }

  return true;
}

bool Options::addFilePaths(InputArgList &Args, PathSeq &Headers,
                           OptSpecifier ID) {
  for (const StringRef Path : Args.getAllArgValues(ID)) {
    if ((bool)FM->getDirectory(Path, /*CacheFailure=*/false)) {
      auto InputHeadersOrErr = enumerateFiles(*FM, Path);
      if (!InputHeadersOrErr) {
        Diags->Report(diag::err_cannot_open_file)
            << Path << toString(InputHeadersOrErr.takeError());
        return false;
      }
      // Sort headers to ensure deterministic behavior.
      sort(*InputHeadersOrErr);
      for (StringRef H : *InputHeadersOrErr)
        Headers.emplace_back(std::move(H));
    } else
      Headers.emplace_back(Path);
  }
  return true;
}

std::vector<const char *>
Options::processAndFilterOutInstallAPIOptions(ArrayRef<const char *> Args) {
  std::unique_ptr<llvm::opt::OptTable> Table;
  Table.reset(createDriverOptTable());

  unsigned MissingArgIndex, MissingArgCount;
  auto ParsedArgs = Table->ParseArgs(Args.slice(1), MissingArgIndex,
                                     MissingArgCount, Visibility());

  // Capture InstallAPI only driver options.
  if (!processInstallAPIXOptions(ParsedArgs))
    return {};

  DriverOpts.Demangle = ParsedArgs.hasArg(OPT_demangle);

  if (auto *A = ParsedArgs.getLastArg(OPT_filetype)) {
    DriverOpts.OutFT = TextAPIWriter::parseFileType(A->getValue());
    if (DriverOpts.OutFT == FileType::Invalid) {
      Diags->Report(clang::diag::err_drv_invalid_value)
          << A->getAsString(ParsedArgs) << A->getValue();
      return {};
    }
  }

  if (const Arg *A = ParsedArgs.getLastArg(OPT_verify_mode_EQ)) {
    DriverOpts.VerifyMode =
        StringSwitch<VerificationMode>(A->getValue())
            .Case("ErrorsOnly", VerificationMode::ErrorsOnly)
            .Case("ErrorsAndWarnings", VerificationMode::ErrorsAndWarnings)
            .Case("Pedantic", VerificationMode::Pedantic)
            .Default(VerificationMode::Invalid);

    if (DriverOpts.VerifyMode == VerificationMode::Invalid) {
      Diags->Report(clang::diag::err_drv_invalid_value)
          << A->getAsString(ParsedArgs) << A->getValue();
      return {};
    }
  }

  if (const Arg *A = ParsedArgs.getLastArg(OPT_verify_against))
    DriverOpts.DylibToVerify = A->getValue();

  if (const Arg *A = ParsedArgs.getLastArg(OPT_dsym))
    DriverOpts.DSYMPath = A->getValue();

  DriverOpts.TraceLibraryLocation = ParsedArgs.hasArg(OPT_t);

  // Linker options not handled by clang driver.
  LinkerOpts.OSLibNotForSharedCache =
      ParsedArgs.hasArg(OPT_not_for_dyld_shared_cache);

  for (const Arg *A : ParsedArgs.filtered(OPT_allowable_client)) {
    LinkerOpts.AllowableClients[A->getValue()] =
        ArgToArchMap.count(A) ? ArgToArchMap[A] : ArchitectureSet();
    A->claim();
  }

  for (const Arg *A : ParsedArgs.filtered(OPT_reexport_l)) {
    LinkerOpts.ReexportedLibraries[A->getValue()] =
        ArgToArchMap.count(A) ? ArgToArchMap[A] : ArchitectureSet();
    A->claim();
  }

  for (const Arg *A : ParsedArgs.filtered(OPT_reexport_library)) {
    LinkerOpts.ReexportedLibraryPaths[A->getValue()] =
        ArgToArchMap.count(A) ? ArgToArchMap[A] : ArchitectureSet();
    A->claim();
  }

  for (const Arg *A : ParsedArgs.filtered(OPT_reexport_framework)) {
    LinkerOpts.ReexportedFrameworks[A->getValue()] =
        ArgToArchMap.count(A) ? ArgToArchMap[A] : ArchitectureSet();
    A->claim();
  }

  for (const Arg *A : ParsedArgs.filtered(OPT_rpath)) {
    LinkerOpts.RPaths[A->getValue()] =
        ArgToArchMap.count(A) ? ArgToArchMap[A] : ArchitectureSet();
    A->claim();
  }

  // Handle exclude & extra header directories or files.
  auto handleAdditionalInputArgs = [&](PathSeq &Headers,
                                       clang::installapi::ID OptID) {
    if (ParsedArgs.hasArgNoClaim(OptID))
      Headers.clear();
    return addFilePaths(ParsedArgs, Headers, OptID);
  };

  if (!handleAdditionalInputArgs(DriverOpts.ExtraPublicHeaders,
                                 OPT_extra_public_header))
    return {};

  if (!handleAdditionalInputArgs(DriverOpts.ExtraPrivateHeaders,
                                 OPT_extra_private_header))
    return {};
  if (!handleAdditionalInputArgs(DriverOpts.ExtraProjectHeaders,
                                 OPT_extra_project_header))
    return {};

  if (!handleAdditionalInputArgs(DriverOpts.ExcludePublicHeaders,
                                 OPT_exclude_public_header))
    return {};
  if (!handleAdditionalInputArgs(DriverOpts.ExcludePrivateHeaders,
                                 OPT_exclude_private_header))
    return {};
  if (!handleAdditionalInputArgs(DriverOpts.ExcludeProjectHeaders,
                                 OPT_exclude_project_header))
    return {};

  // Handle umbrella headers.
  if (const Arg *A = ParsedArgs.getLastArg(OPT_public_umbrella_header))
    DriverOpts.PublicUmbrellaHeader = A->getValue();

  if (const Arg *A = ParsedArgs.getLastArg(OPT_private_umbrella_header))
    DriverOpts.PrivateUmbrellaHeader = A->getValue();

  if (const Arg *A = ParsedArgs.getLastArg(OPT_project_umbrella_header))
    DriverOpts.ProjectUmbrellaHeader = A->getValue();

  /// Any unclaimed arguments should be forwarded to the clang driver.
  std::vector<const char *> ClangDriverArgs(ParsedArgs.size());
  for (const Arg *A : ParsedArgs) {
    if (A->isClaimed())
      continue;
    // Forward along unclaimed but overlapping arguments to the clang driver.
    if (A->getOption().getID() > (unsigned)OPT_UNKNOWN) {
      ClangDriverArgs.push_back(A->getSpelling().data());
    } else
      llvm::copy(A->getValues(), std::back_inserter(ClangDriverArgs));
  }
  return ClangDriverArgs;
}

Options::Options(DiagnosticsEngine &Diag, FileManager *FM,
                 ArrayRef<const char *> Args, const StringRef ProgName)
    : Diags(&Diag), FM(FM) {

  // First process InstallAPI specific options.
  auto DriverArgs = processAndFilterOutInstallAPIOptions(Args);
  if (Diags->hasErrorOccurred())
    return;

  // Set up driver to parse remaining input arguments.
  clang::driver::Driver Driver(ProgName, llvm::sys::getDefaultTargetTriple(),
                               *Diags, "clang installapi tool");
  auto TargetAndMode =
      clang::driver::ToolChain::getTargetAndModeFromProgramName(ProgName);
  Driver.setTargetAndMode(TargetAndMode);
  bool HasError = false;
  llvm::opt::InputArgList ArgList =
      Driver.ParseArgStrings(DriverArgs, /*UseDriverMode=*/true, HasError);
  if (HasError)
    return;
  Driver.setCheckInputsExist(false);

  if (!processDriverOptions(ArgList))
    return;

  if (!processLinkerOptions(ArgList))
    return;

  if (!processFrontendOptions(ArgList))
    return;

  // After all InstallAPI necessary arguments have been collected. Go back and
  // assign values that were unknown before the clang driver opt table was used.
  ArchitectureSet AllArchs;
  llvm::for_each(DriverOpts.Targets,
                 [&AllArchs](const auto &T) { AllArchs.set(T.first.Arch); });
  auto assignDefaultLibAttrs = [&AllArchs](LibAttrs &Attrs) {
    for (StringMapEntry<ArchitectureSet> &Entry : Attrs)
      if (Entry.getValue().empty())
        Entry.setValue(AllArchs);
  };
  assignDefaultLibAttrs(LinkerOpts.AllowableClients);
  assignDefaultLibAttrs(LinkerOpts.ReexportedFrameworks);
  assignDefaultLibAttrs(LinkerOpts.ReexportedLibraries);
  assignDefaultLibAttrs(LinkerOpts.ReexportedLibraryPaths);
  assignDefaultLibAttrs(LinkerOpts.RPaths);

  /// Force cc1 options that should always be on.
  FrontendArgs = {"-fsyntax-only", "-Wprivate-extern"};

  /// Any unclaimed arguments should be handled by invoking the clang frontend.
  for (const Arg *A : ArgList) {
    if (A->isClaimed())
      continue;
    FrontendArgs.emplace_back(A->getSpelling());
    llvm::copy(A->getValues(), std::back_inserter(FrontendArgs));
  }
}

static const Regex Rule("(.+)/(.+)\\.framework/");
static StringRef getFrameworkNameFromInstallName(StringRef InstallName) {
  SmallVector<StringRef, 3> Match;
  Rule.match(InstallName, &Match);
  if (Match.empty())
    return "";
  return Match.back();
}

static Expected<std::unique_ptr<InterfaceFile>>
getInterfaceFile(const StringRef Filename) {
  ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
      MemoryBuffer::getFile(Filename);
  if (auto Err = BufferOrErr.getError())
    return errorCodeToError(std::move(Err));

  auto Buffer = std::move(*BufferOrErr);
  std::unique_ptr<InterfaceFile> IF;
  switch (identify_magic(Buffer->getBuffer())) {
  case file_magic::macho_dynamically_linked_shared_lib:
  case file_magic::macho_dynamically_linked_shared_lib_stub:
  case file_magic::macho_universal_binary:
    return DylibReader::get(Buffer->getMemBufferRef());
    break;
  case file_magic::tapi_file:
    return TextAPIReader::get(Buffer->getMemBufferRef());
  default:
    return make_error<TextAPIError>(TextAPIErrorCode::InvalidInputFormat,
                                    "unsupported library file format");
  }
  llvm_unreachable("unexpected failure in getInterface");
}

std::pair<LibAttrs, ReexportedInterfaces> Options::getReexportedLibraries() {
  LibAttrs Reexports;
  ReexportedInterfaces ReexportIFs;
  auto AccumulateReexports = [&](StringRef Path, const ArchitectureSet &Archs) {
    auto ReexportIFOrErr = getInterfaceFile(Path);
    if (!ReexportIFOrErr)
      return false;
    std::unique_ptr<InterfaceFile> Reexport = std::move(*ReexportIFOrErr);
    StringRef InstallName = Reexport->getInstallName();
    assert(!InstallName.empty() && "Parse error for install name");
    Reexports.insert({InstallName, Archs});
    ReexportIFs.emplace_back(std::move(*Reexport));
    return true;
  };

  PlatformSet Platforms;
  llvm::for_each(DriverOpts.Targets,
                 [&](const auto &T) { Platforms.insert(T.first.Platform); });
  // Populate search paths by looking at user paths before system ones.
  PathSeq FwkSearchPaths(FEOpts.FwkPaths.begin(), FEOpts.FwkPaths.end());
  for (const PlatformType P : Platforms) {
    PathSeq PlatformSearchPaths = getPathsForPlatform(FEOpts.SystemFwkPaths, P);
    FwkSearchPaths.insert(FwkSearchPaths.end(), PlatformSearchPaths.begin(),
                          PlatformSearchPaths.end());
    for (const StringMapEntry<ArchitectureSet> &Lib :
         LinkerOpts.ReexportedFrameworks) {
      std::string Name = (Lib.getKey() + ".framework/" + Lib.getKey()).str();
      std::string Path = findLibrary(Name, *FM, FwkSearchPaths, {}, {});
      if (Path.empty()) {
        Diags->Report(diag::err_cannot_find_reexport) << false << Lib.getKey();
        return {};
      }
      if (DriverOpts.TraceLibraryLocation)
        errs() << Path << "\n";

      AccumulateReexports(Path, Lib.getValue());
    }
    FwkSearchPaths.resize(FwkSearchPaths.size() - PlatformSearchPaths.size());
  }

  for (const StringMapEntry<ArchitectureSet> &Lib :
       LinkerOpts.ReexportedLibraries) {
    std::string Name = "lib" + Lib.getKey().str() + ".dylib";
    std::string Path = findLibrary(Name, *FM, {}, LinkerOpts.LibPaths, {});
    if (Path.empty()) {
      Diags->Report(diag::err_cannot_find_reexport) << true << Lib.getKey();
      return {};
    }
    if (DriverOpts.TraceLibraryLocation)
      errs() << Path << "\n";

    AccumulateReexports(Path, Lib.getValue());
  }

  for (const StringMapEntry<ArchitectureSet> &Lib :
       LinkerOpts.ReexportedLibraryPaths)
    AccumulateReexports(Lib.getKey(), Lib.getValue());

  return {std::move(Reexports), std::move(ReexportIFs)};
}

InstallAPIContext Options::createContext() {
  InstallAPIContext Ctx;
  Ctx.FM = FM;
  Ctx.Diags = Diags;

  // InstallAPI requires two level namespacing.
  Ctx.BA.TwoLevelNamespace = true;

  Ctx.BA.InstallName = LinkerOpts.InstallName;
  Ctx.BA.CurrentVersion = LinkerOpts.CurrentVersion;
  Ctx.BA.CompatVersion = LinkerOpts.CompatVersion;
  Ctx.BA.AppExtensionSafe = LinkerOpts.AppExtensionSafe;
  Ctx.BA.ParentUmbrella = LinkerOpts.ParentUmbrella;
  Ctx.BA.OSLibNotForSharedCache = LinkerOpts.OSLibNotForSharedCache;
  Ctx.FT = DriverOpts.OutFT;
  Ctx.OutputLoc = DriverOpts.OutputPath;
  Ctx.LangMode = FEOpts.LangMode;

  auto [Reexports, ReexportedIFs] = getReexportedLibraries();
  if (Diags->hasErrorOccurred())
    return Ctx;
  Ctx.Reexports = Reexports;

  // Collect symbols from alias lists.
  AliasMap Aliases;
  for (const StringRef ListPath : LinkerOpts.AliasLists) {
    auto Buffer = FM->getBufferForFile(ListPath);
    if (auto Err = Buffer.getError()) {
      Diags->Report(diag::err_cannot_open_file) << ListPath << Err.message();
      return Ctx;
    }
    Expected<AliasMap> Result = parseAliasList(Buffer.get());
    if (!Result) {
      Diags->Report(diag::err_cannot_read_input_list)
          << /*IsFileList=*/false << ListPath << toString(Result.takeError());
      return Ctx;
    }
    Aliases.insert(Result.get().begin(), Result.get().end());
  }

  // Attempt to find umbrella headers by capturing framework name.
  StringRef FrameworkName;
  if (!LinkerOpts.IsDylib)
    FrameworkName = getFrameworkNameFromInstallName(LinkerOpts.InstallName);

  // Process inputs.
  for (const StringRef ListPath : DriverOpts.FileLists) {
    auto Buffer = FM->getBufferForFile(ListPath);
    if (auto Err = Buffer.getError()) {
      Diags->Report(diag::err_cannot_open_file) << ListPath << Err.message();
      return Ctx;
    }
    if (auto Err = FileListReader::loadHeaders(std::move(Buffer.get()),
                                               Ctx.InputHeaders, FM)) {
      Diags->Report(diag::err_cannot_read_input_list)
          << /*IsFileList=*/true << ListPath << std::move(Err);
      return Ctx;
    }
  }
  // After initial input has been processed, add any extra headers.
  auto HandleExtraHeaders = [&](PathSeq &Headers, HeaderType Type) -> bool {
    assert(Type != HeaderType::Unknown && "Missing header type.");
    for (const StringRef Path : Headers) {
      if (!FM->getOptionalFileRef(Path)) {
        Diags->Report(diag::err_no_such_header_file) << Path << (unsigned)Type;
        return false;
      }
      SmallString<PATH_MAX> FullPath(Path);
      FM->makeAbsolutePath(FullPath);

      auto IncludeName = createIncludeHeaderName(FullPath);
      Ctx.InputHeaders.emplace_back(
          FullPath, Type, IncludeName.has_value() ? *IncludeName : "");
      Ctx.InputHeaders.back().setExtra();
    }
    return true;
  };

  if (!HandleExtraHeaders(DriverOpts.ExtraPublicHeaders, HeaderType::Public) ||
      !HandleExtraHeaders(DriverOpts.ExtraPrivateHeaders,
                          HeaderType::Private) ||
      !HandleExtraHeaders(DriverOpts.ExtraProjectHeaders, HeaderType::Project))
    return Ctx;

  // After all headers have been added, consider excluded headers.
  std::vector<std::unique_ptr<HeaderGlob>> ExcludedHeaderGlobs;
  std::set<FileEntryRef> ExcludedHeaderFiles;
  auto ParseGlobs = [&](const PathSeq &Paths, HeaderType Type) {
    assert(Type != HeaderType::Unknown && "Missing header type.");
    for (const StringRef Path : Paths) {
      auto Glob = HeaderGlob::create(Path, Type);
      if (Glob)
        ExcludedHeaderGlobs.emplace_back(std::move(Glob.get()));
      else {
        consumeError(Glob.takeError());
        if (auto File = FM->getFileRef(Path))
          ExcludedHeaderFiles.emplace(*File);
        else {
          Diags->Report(diag::err_no_such_header_file)
              << Path << (unsigned)Type;
          return false;
        }
      }
    }
    return true;
  };

  if (!ParseGlobs(DriverOpts.ExcludePublicHeaders, HeaderType::Public) ||
      !ParseGlobs(DriverOpts.ExcludePrivateHeaders, HeaderType::Private) ||
      !ParseGlobs(DriverOpts.ExcludeProjectHeaders, HeaderType::Project))
    return Ctx;

  for (HeaderFile &Header : Ctx.InputHeaders) {
    for (auto &Glob : ExcludedHeaderGlobs)
      if (Glob->match(Header))
        Header.setExcluded();
  }
  if (!ExcludedHeaderFiles.empty()) {
    for (HeaderFile &Header : Ctx.InputHeaders) {
      auto FileRef = FM->getFileRef(Header.getPath());
      if (!FileRef)
        continue;
      if (ExcludedHeaderFiles.count(*FileRef))
        Header.setExcluded();
    }
  }
  // Report if glob was ignored.
  for (const auto &Glob : ExcludedHeaderGlobs)
    if (!Glob->didMatch())
      Diags->Report(diag::warn_glob_did_not_match) << Glob->str();

  // Mark any explicit or inferred umbrella headers. If one exists, move
  // that to the beginning of the input headers.
  auto MarkandMoveUmbrellaInHeaders = [&](llvm::Regex &Regex,
                                          HeaderType Type) -> bool {
    auto It = find_if(Ctx.InputHeaders, [&Regex, Type](const HeaderFile &H) {
      return (H.getType() == Type) && Regex.match(H.getPath());
    });

    if (It == Ctx.InputHeaders.end())
      return false;
    It->setUmbrellaHeader();

    // Because there can be an umbrella header per header type,
    // find the first non umbrella header to swap position with.
    auto BeginPos = find_if(Ctx.InputHeaders, [](const HeaderFile &H) {
      return !H.isUmbrellaHeader();
    });
    if (BeginPos != Ctx.InputHeaders.end() && BeginPos < It)
      std::swap(*BeginPos, *It);
    return true;
  };

  auto FindUmbrellaHeader = [&](StringRef HeaderPath, HeaderType Type) -> bool {
    assert(Type != HeaderType::Unknown && "Missing header type.");
    if (!HeaderPath.empty()) {
      auto EscapedString = Regex::escape(HeaderPath);
      Regex UmbrellaRegex(EscapedString);
      if (!MarkandMoveUmbrellaInHeaders(UmbrellaRegex, Type)) {
        Diags->Report(diag::err_no_such_umbrella_header_file)
            << HeaderPath << (unsigned)Type;
        return false;
      }
    } else if (!FrameworkName.empty() && (Type != HeaderType::Project)) {
      auto UmbrellaName = "/" + Regex::escape(FrameworkName);
      if (Type == HeaderType::Public)
        UmbrellaName += "\\.h";
      else
        UmbrellaName += "[_]?Private\\.h";
      Regex UmbrellaRegex(UmbrellaName);
      MarkandMoveUmbrellaInHeaders(UmbrellaRegex, Type);
    }
    return true;
  };
  if (!FindUmbrellaHeader(DriverOpts.PublicUmbrellaHeader,
                          HeaderType::Public) ||
      !FindUmbrellaHeader(DriverOpts.PrivateUmbrellaHeader,
                          HeaderType::Private) ||
      !FindUmbrellaHeader(DriverOpts.ProjectUmbrellaHeader,
                          HeaderType::Project))
    return Ctx;

  // Parse binary dylib and initialize verifier.
  if (DriverOpts.DylibToVerify.empty()) {
    Ctx.Verifier = std::make_unique<DylibVerifier>();
    return Ctx;
  }

  auto Buffer = FM->getBufferForFile(DriverOpts.DylibToVerify);
  if (auto Err = Buffer.getError()) {
    Diags->Report(diag::err_cannot_open_file)
        << DriverOpts.DylibToVerify << Err.message();
    return Ctx;
  }

  DylibReader::ParseOption PO;
  PO.Undefineds = false;
  Expected<Records> Slices =
      DylibReader::readFile((*Buffer)->getMemBufferRef(), PO);
  if (auto Err = Slices.takeError()) {
    Diags->Report(diag::err_cannot_open_file)
        << DriverOpts.DylibToVerify << std::move(Err);
    return Ctx;
  }

  Ctx.Verifier = std::make_unique<DylibVerifier>(
      std::move(*Slices), std::move(ReexportedIFs), std::move(Aliases), Diags,
      DriverOpts.VerifyMode, DriverOpts.Zippered, DriverOpts.Demangle,
      DriverOpts.DSYMPath);
  return Ctx;
}

void Options::addConditionalCC1Args(std::vector<std::string> &ArgStrings,
                                    const llvm::Triple &Targ,
                                    const HeaderType Type) {
  // Unique to architecture (Xarch) options hold no arguments to pass along for
  // frontend.

  // Add specific to platform arguments.
  PathSeq PlatformSearchPaths =
      getPathsForPlatform(FEOpts.SystemFwkPaths, mapToPlatformType(Targ));
  llvm::for_each(PlatformSearchPaths, [&ArgStrings](const StringRef Path) {
    ArgStrings.push_back("-iframework");
    ArgStrings.push_back(Path.str());
  });

  // Add specific to header type arguments.
  if (Type == HeaderType::Project)
    for (const StringRef A : ProjectLevelArgs)
      ArgStrings.emplace_back(A);
}

} // namespace installapi
} // namespace clang
