//===-- 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/DirectoryScanner.h"
#include "clang/InstallAPI/FileList.h"
#include "clang/InstallAPI/HeaderFile.h"
#include "clang/InstallAPI/InstallAPIDiagnostic.h"
#include "llvm/BinaryFormat/Magic.h"
#include "llvm/Support/JSON.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 {

#define OPTTABLE_STR_TABLE_CODE
#include "InstallAPIOpts.inc"
#undef OPTTABLE_STR_TABLE_CODE

#define OPTTABLE_PREFIXES_TABLE_CODE
#include "InstallAPIOpts.inc"
#undef OPTTABLE_PREFIXES_TABLE_CODE

#define OPTTABLE_PREFIXES_UNION_CODE
#include "InstallAPIOpts.inc"
#undef OPTTABLE_PREFIXES_UNION_CODE

/// Create table mapping all options defined in InstallAPIOpts.td.
static constexpr OptTable::Info InfoTable[] = {
#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
#include "InstallAPIOpts.inc"
#undef OPTION
};

namespace {

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

} // end anonymous namespace.

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

/// Parse JSON input into argument list.
///
/* Expected input format.
 *  { "label" : ["-ClangArg1", "-ClangArg2"] }
 */
///
/// Input is interpreted as "-Xlabel ClangArg1 -XLabel ClangArg2".
static Expected<llvm::opt::InputArgList>
getArgListFromJSON(const StringRef Input, llvm::opt::OptTable *Table,
                   std::vector<std::string> &Storage) {
  using namespace json;
  Expected<Value> ValOrErr = json::parse(Input);
  if (!ValOrErr)
    return ValOrErr.takeError();

  const Object *Root = ValOrErr->getAsObject();
  if (!Root)
    return llvm::opt::InputArgList();

  for (const auto &KV : *Root) {
    const Array *ArgList = KV.getSecond().getAsArray();
    std::string Label = "-X" + KV.getFirst().str();
    if (!ArgList)
      return make_error<TextAPIError>(TextAPIErrorCode::InvalidInputFormat);
    for (auto Arg : *ArgList) {
      std::optional<StringRef> ArgStr = Arg.getAsString();
      if (!ArgStr)
        return make_error<TextAPIError>(TextAPIErrorCode::InvalidInputFormat);
      Storage.emplace_back(Label);
      Storage.emplace_back(*ArgStr);
    }
  }

  std::vector<const char *> CArgs(Storage.size());
  for (StringRef Str : Storage)
    CArgs.emplace_back(Str.data());

  unsigned MissingArgIndex, MissingArgCount;
  return Table->ParseArgs(CArgs, MissingArgIndex, MissingArgCount);
}

bool Options::processDriverOptions(InputArgList &Args) {
  // Handle inputs.
  for (const StringRef Path : Args.getAllArgValues(drv::OPT_INPUT)) {
    // Assume any input that is not a directory is a filelist.
    // InstallAPI does not accept multiple directories, so retain the last one.
    if (FM->getOptionalDirectoryRef(Path))
      DriverOpts.InputDirectory = Path.str();
    else
      DriverOpts.FileLists.emplace_back(Path.str());
  }

  // 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();
    auto &UniqueArgs = FEOpts.UniqueArgs[Label];
    if (AValues.empty())
      UniqueArgs.emplace_back(ASpelling.str());
    else
      for (const StringRef Val : AValues)
        UniqueArgs.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::processOptionList(InputArgList &Args,
                                llvm::opt::OptTable *Table) {
  Arg *A = Args.getLastArg(OPT_option_list);
  if (!A)
    return true;

  const StringRef Path = A->getValue(0);
  auto InputOrErr = FM->getBufferForFile(Path);
  if (auto Err = InputOrErr.getError()) {
    Diags->Report(diag::err_cannot_open_file) << Path << Err.message();
    return false;
  }
  // Backing storage referenced for argument processing.
  std::vector<std::string> Storage;
  auto ArgsOrErr =
      getArgListFromJSON((*InputOrErr)->getBuffer(), Table, Storage);

  if (auto Err = ArgsOrErr.takeError()) {
    Diags->Report(diag::err_cannot_read_input_list)
        << "option" << Path << toString(std::move(Err));
    return false;
  }
  return processInstallAPIXOptions(*ArgsOrErr);
}

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->getOptionalDirectoryRef(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 {};

  if (!processOptionList(ParsedArgs, Table.get()))
    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)) {
    auto It = ArgToArchMap.find(A);
    LinkerOpts.AllowableClients.getArchSet(A->getValue()) =
        It != ArgToArchMap.end() ? It->second : ArchitectureSet();
    A->claim();
  }

  for (const Arg *A : ParsedArgs.filtered(OPT_reexport_l)) {
    auto It = ArgToArchMap.find(A);
    LinkerOpts.ReexportedLibraries.getArchSet(A->getValue()) =
        It != ArgToArchMap.end() ? It->second : ArchitectureSet();
    A->claim();
  }

  for (const Arg *A : ParsedArgs.filtered(OPT_reexport_library)) {
    auto It = ArgToArchMap.find(A);
    LinkerOpts.ReexportedLibraryPaths.getArchSet(A->getValue()) =
        It != ArgToArchMap.end() ? It->second : ArchitectureSet();
    A->claim();
  }

  for (const Arg *A : ParsedArgs.filtered(OPT_reexport_framework)) {
    auto It = ArgToArchMap.find(A);
    LinkerOpts.ReexportedFrameworks.getArchSet(A->getValue()) =
        It != ArgToArchMap.end() ? It->second : ArchitectureSet();
    A->claim();
  }

  for (const Arg *A : ParsedArgs.filtered(OPT_rpath)) {
    auto It = ArgToArchMap.find(A);
    LinkerOpts.RPaths.getArchSet(A->getValue()) =
        It != ArgToArchMap.end() ? It->second : 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::append_range(ClangDriverArgs, A->getValues());
  }
  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;
  for (const auto &T : DriverOpts.Targets)
    AllArchs.set(T.first.Arch);
  auto assignDefaultLibAttrs = [&AllArchs](LibAttrs &Attrs) {
    for (auto &[_, Archs] : Attrs.get())
      if (Archs.empty())
        Archs = 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::append_range(FrontendArgs, A->getValues());
  }
}

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);
  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.getArchSet(InstallName) = Archs;
    ReexportIFs.emplace_back(std::move(*Reexport));
    return true;
  };

  PlatformSet Platforms;
  for (const auto &T : DriverOpts.Targets)
    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);
    llvm::append_range(FwkSearchPaths, PlatformSearchPaths);
    for (const auto &[Lib, Archs] : LinkerOpts.ReexportedFrameworks.get()) {
      std::string Name = (Lib + ".framework/" + Lib);
      std::string Path = findLibrary(Name, *FM, FwkSearchPaths, {}, {});
      if (Path.empty()) {
        Diags->Report(diag::err_cannot_find_reexport) << false << Lib;
        return {};
      }
      if (DriverOpts.TraceLibraryLocation)
        errs() << Path << "\n";

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

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

    AccumulateReexports(Path, Archs);
  }

  for (const auto &[Lib, Archs] : LinkerOpts.ReexportedLibraryPaths.get())
    AccumulateReexports(Lib, Archs);

  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)
          << "symbol alias" << 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 =
        Library::getFrameworkNameFromInstallName(LinkerOpts.InstallName);

  /// Process inputs headers.
  // 1. For headers discovered by directory scanning, sort them.
  // 2. For headers discovered by filelist, respect ordering.
  // 3. Append extra headers and mark any excluded headers.
  // 4. Finally, surface up umbrella headers to top of the list.
  if (!DriverOpts.InputDirectory.empty()) {
    DirectoryScanner Scanner(*FM, LinkerOpts.IsDylib
                                      ? ScanMode::ScanDylibs
                                      : ScanMode::ScanFrameworks);
    SmallString<PATH_MAX> NormalizedPath(DriverOpts.InputDirectory);
    FM->getVirtualFileSystem().makeAbsolute(NormalizedPath);
    sys::path::remove_dots(NormalizedPath, /*remove_dot_dot=*/true);
    if (llvm::Error Err = Scanner.scan(NormalizedPath)) {
      Diags->Report(diag::err_directory_scanning)
          << DriverOpts.InputDirectory << std::move(Err);
      return Ctx;
    }
    std::vector<Library> InputLibraries = Scanner.takeLibraries();
    if (InputLibraries.size() > 1) {
      Diags->Report(diag::err_more_than_one_library);
      return Ctx;
    }
    llvm::append_range(Ctx.InputHeaders,
                       DirectoryScanner::getHeaders(InputLibraries));
    llvm::stable_sort(Ctx.InputHeaders);
  }

  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)
          << "header file" << 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));
  for (StringRef Path : PlatformSearchPaths) {
    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
