//===- DylibVerifier.cpp ----------------------------------------*- C++--*-===//
//
// 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/InstallAPI/DylibVerifier.h"
#include "DiagnosticBuilderWrappers.h"
#include "clang/InstallAPI/FrontendRecords.h"
#include "clang/InstallAPI/InstallAPIDiagnostic.h"
#include "llvm/Demangle/Demangle.h"
#include "llvm/TextAPI/DylibReader.h"

using namespace llvm::MachO;

namespace clang {
namespace installapi {

ArchitectureSet &LibAttrs::getArchSet(StringRef Attr) {
  auto *It = llvm::find_if(LibraryAttributes, [&Attr](const auto &Input) {
    return Attr == Input.first;
  });
  if (It != LibraryAttributes.end())
    return It->second;
  LibraryAttributes.push_back({Attr.str(), ArchitectureSet()});
  return LibraryAttributes.back().second;
}

std::optional<LibAttrs::Entry> LibAttrs::find(StringRef Attr) const {
  auto *It = llvm::find_if(LibraryAttributes, [&Attr](const auto &Input) {
    return Attr == Input.first;
  });
  if (It == LibraryAttributes.end())
    return std::nullopt;
  return *It;
}

/// Metadata stored about a mapping of a declaration to a symbol.
struct DylibVerifier::SymbolContext {
  // Name to use for all querying and verification
  // purposes.
  std::string SymbolName{""};

  // Kind to map symbol type against record.
  EncodeKind Kind = EncodeKind::GlobalSymbol;

  // Frontend Attributes tied to the AST.
  const FrontendAttrs *FA = nullptr;

  // The ObjCInterface symbol type, if applicable.
  ObjCIFSymbolKind ObjCIFKind = ObjCIFSymbolKind::None;

  // Whether Decl is inlined.
  bool Inlined = false;
};

struct DylibVerifier::DWARFContext {
  // Track whether DSYM parsing has already been attempted to avoid re-parsing.
  bool ParsedDSYM{false};

  // Lookup table for source locations by symbol name.
  DylibReader::SymbolToSourceLocMap SourceLocs{};
};

static bool isCppMangled(StringRef Name) {
  // InstallAPI currently only supports itanium manglings.
  return (Name.starts_with("_Z") || Name.starts_with("__Z") ||
          Name.starts_with("___Z"));
}

static std::string demangle(StringRef Name) {
  // InstallAPI currently only supports itanium manglings.
  if (!isCppMangled(Name))
    return Name.str();
  char *Result = llvm::itaniumDemangle(Name);
  if (!Result)
    return Name.str();

  std::string Demangled(Result);
  free(Result);
  return Demangled;
}

std::string DylibVerifier::getAnnotatedName(const Record *R,
                                            SymbolContext &SymCtx,
                                            bool ValidSourceLoc) {
  assert(!SymCtx.SymbolName.empty() && "Expected symbol name");

  const StringRef SymbolName = SymCtx.SymbolName;
  std::string PrettyName =
      (Demangle && (SymCtx.Kind == EncodeKind::GlobalSymbol))
          ? demangle(SymbolName)
          : SymbolName.str();

  std::string Annotation;
  if (R->isWeakDefined())
    Annotation += "(weak-def) ";
  if (R->isWeakReferenced())
    Annotation += "(weak-ref) ";
  if (R->isThreadLocalValue())
    Annotation += "(tlv) ";

  // Check if symbol represents only part of a @interface declaration.
  switch (SymCtx.ObjCIFKind) {
  default:
    break;
  case ObjCIFSymbolKind::EHType:
    return Annotation + "Exception Type of " + PrettyName;
  case ObjCIFSymbolKind::MetaClass:
    return Annotation + "Metaclass of " + PrettyName;
  case ObjCIFSymbolKind::Class:
    return Annotation + "Class of " + PrettyName;
  }

  // Only print symbol type prefix or leading "_" if there is no source location
  // tied to it. This can only ever happen when the location has to come from
  // debug info.
  if (ValidSourceLoc) {
    StringRef PrettyNameRef(PrettyName);
    if ((SymCtx.Kind == EncodeKind::GlobalSymbol) &&
        !isCppMangled(SymbolName) && PrettyNameRef.starts_with("_"))
      return Annotation + PrettyNameRef.drop_front(1).str();
    return Annotation + PrettyName;
  }

  switch (SymCtx.Kind) {
  case EncodeKind::GlobalSymbol:
    return Annotation + PrettyName;
  case EncodeKind::ObjectiveCInstanceVariable:
    return Annotation + "(ObjC IVar) " + PrettyName;
  case EncodeKind::ObjectiveCClass:
    return Annotation + "(ObjC Class) " + PrettyName;
  case EncodeKind::ObjectiveCClassEHType:
    return Annotation + "(ObjC Class EH) " + PrettyName;
  }

  llvm_unreachable("unexpected case for EncodeKind");
}

static DylibVerifier::Result updateResult(const DylibVerifier::Result Prev,
                                          const DylibVerifier::Result Curr) {
  if (Prev == Curr)
    return Prev;

  // Never update from invalid or noverify state.
  if ((Prev == DylibVerifier::Result::Invalid) ||
      (Prev == DylibVerifier::Result::NoVerify))
    return Prev;

  // Don't let an ignored verification remove a valid one.
  if (Prev == DylibVerifier::Result::Valid &&
      Curr == DylibVerifier::Result::Ignore)
    return Prev;

  return Curr;
}
// __private_extern__ is a deprecated specifier that clang does not
// respect in all contexts, it should just be considered hidden for InstallAPI.
static bool shouldIgnorePrivateExternAttr(const Decl *D) {
  if (const FunctionDecl *FD = cast<FunctionDecl>(D))
    return FD->getStorageClass() == StorageClass::SC_PrivateExtern;
  if (const VarDecl *VD = cast<VarDecl>(D))
    return VD->getStorageClass() == StorageClass::SC_PrivateExtern;

  return false;
}

Record *findRecordFromSlice(const RecordsSlice *Slice, StringRef Name,
                            EncodeKind Kind) {
  switch (Kind) {
  case EncodeKind::GlobalSymbol:
    return Slice->findGlobal(Name);
  case EncodeKind::ObjectiveCInstanceVariable:
    return Slice->findObjCIVar(Name.contains('.'), Name);
  case EncodeKind::ObjectiveCClass:
  case EncodeKind::ObjectiveCClassEHType:
    return Slice->findObjCInterface(Name);
  }
  llvm_unreachable("unexpected end when finding record");
}

void DylibVerifier::updateState(Result State) {
  Ctx.FrontendState = updateResult(Ctx.FrontendState, State);
}

void DylibVerifier::addSymbol(const Record *R, SymbolContext &SymCtx,
                              TargetList &&Targets) {
  if (Targets.empty())
    Targets = {Ctx.Target};

  Exports->addGlobal(SymCtx.Kind, SymCtx.SymbolName, R->getFlags(), Targets);
}

bool DylibVerifier::shouldIgnoreObsolete(const Record *R, SymbolContext &SymCtx,
                                         const Record *DR) {
  if (!SymCtx.FA->Avail.isObsoleted())
    return false;

  if (Zippered)
    DeferredZipperedSymbols[SymCtx.SymbolName].emplace_back(ZipperedDeclSource{
        SymCtx.FA, &Ctx.Diag->getSourceManager(), Ctx.Target});
  return true;
}

bool DylibVerifier::shouldIgnoreReexport(const Record *R,
                                         SymbolContext &SymCtx) const {
  StringRef SymName = SymCtx.SymbolName;
  // Linker directive symbols can never be ignored.
  if (SymName.starts_with("$ld$"))
    return false;

  if (Reexports.empty())
    return false;

  for (const InterfaceFile &Lib : Reexports) {
    if (!Lib.hasTarget(Ctx.Target))
      continue;
    if (auto Sym = Lib.getSymbol(SymCtx.Kind, SymName, SymCtx.ObjCIFKind))
      if ((*Sym)->hasTarget(Ctx.Target))
        return true;
  }
  return false;
}

bool DylibVerifier::shouldIgnoreInternalZipperedSymbol(
    const Record *R, const SymbolContext &SymCtx) const {
  if (!Zippered)
    return false;

  return Exports->findSymbol(SymCtx.Kind, SymCtx.SymbolName,
                             SymCtx.ObjCIFKind) != nullptr;
}

bool DylibVerifier::shouldIgnoreZipperedAvailability(const Record *R,
                                                     SymbolContext &SymCtx) {
  if (!(Zippered && SymCtx.FA->Avail.isUnavailable()))
    return false;

  // Collect source location incase there is an exported symbol to diagnose
  // during `verifyRemainingSymbols`.
  DeferredZipperedSymbols[SymCtx.SymbolName].emplace_back(
      ZipperedDeclSource{SymCtx.FA, SourceManagers.back().get(), Ctx.Target});

  return true;
}

bool DylibVerifier::compareObjCInterfaceSymbols(const Record *R,
                                                SymbolContext &SymCtx,
                                                const ObjCInterfaceRecord *DR) {
  const bool IsDeclVersionComplete =
      ((SymCtx.ObjCIFKind & ObjCIFSymbolKind::Class) ==
       ObjCIFSymbolKind::Class) &&
      ((SymCtx.ObjCIFKind & ObjCIFSymbolKind::MetaClass) ==
       ObjCIFSymbolKind::MetaClass);

  const bool IsDylibVersionComplete = DR->isCompleteInterface();

  // The common case, a complete ObjCInterface.
  if (IsDeclVersionComplete && IsDylibVersionComplete)
    return true;

  auto PrintDiagnostic = [&](auto SymLinkage, const Record *Record,
                             StringRef SymName, bool PrintAsWarning = false) {
    if (SymLinkage == RecordLinkage::Unknown)
      Ctx.emitDiag([&]() {
        Ctx.Diag->Report(SymCtx.FA->Loc, PrintAsWarning
                                             ? diag::warn_library_missing_symbol
                                             : diag::err_library_missing_symbol)
            << SymName;
      });
    else
      Ctx.emitDiag([&]() {
        Ctx.Diag->Report(SymCtx.FA->Loc, PrintAsWarning
                                             ? diag::warn_library_hidden_symbol
                                             : diag::err_library_hidden_symbol)
            << SymName;
      });
  };

  if (IsDeclVersionComplete) {
    // The decl represents a complete ObjCInterface, but the symbols in the
    // dylib do not. Determine which symbol is missing. To keep older projects
    // building, treat this as a warning.
    if (!DR->isExportedSymbol(ObjCIFSymbolKind::Class)) {
      SymCtx.ObjCIFKind = ObjCIFSymbolKind::Class;
      PrintDiagnostic(DR->getLinkageForSymbol(ObjCIFSymbolKind::Class), R,
                      getAnnotatedName(R, SymCtx),
                      /*PrintAsWarning=*/true);
    }
    if (!DR->isExportedSymbol(ObjCIFSymbolKind::MetaClass)) {
      SymCtx.ObjCIFKind = ObjCIFSymbolKind::MetaClass;
      PrintDiagnostic(DR->getLinkageForSymbol(ObjCIFSymbolKind::MetaClass), R,
                      getAnnotatedName(R, SymCtx),
                      /*PrintAsWarning=*/true);
    }
    return true;
  }

  if (DR->isExportedSymbol(SymCtx.ObjCIFKind)) {
    if (!IsDylibVersionComplete) {
      // Both the declaration and dylib have a non-complete interface.
      SymCtx.Kind = EncodeKind::GlobalSymbol;
      SymCtx.SymbolName = R->getName();
    }
    return true;
  }

  // At this point that means there was not a matching class symbol
  // to represent the one discovered as a declaration.
  PrintDiagnostic(DR->getLinkageForSymbol(SymCtx.ObjCIFKind), R,
                  SymCtx.SymbolName);
  return false;
}

DylibVerifier::Result DylibVerifier::compareVisibility(const Record *R,
                                                       SymbolContext &SymCtx,
                                                       const Record *DR) {

  if (R->isExported()) {
    if (!DR) {
      Ctx.emitDiag([&]() {
        Ctx.Diag->Report(SymCtx.FA->Loc, diag::err_library_missing_symbol)
            << getAnnotatedName(R, SymCtx);
      });
      return Result::Invalid;
    }
    if (DR->isInternal()) {
      Ctx.emitDiag([&]() {
        Ctx.Diag->Report(SymCtx.FA->Loc, diag::err_library_hidden_symbol)
            << getAnnotatedName(R, SymCtx);
      });
      return Result::Invalid;
    }
  }

  // Emit a diagnostic for hidden declarations with external symbols, except
  // when theres an inlined attribute.
  if ((R->isInternal() && !SymCtx.Inlined) && DR && DR->isExported()) {

    if (Mode == VerificationMode::ErrorsOnly)
      return Result::Ignore;

    if (shouldIgnorePrivateExternAttr(SymCtx.FA->D))
      return Result::Ignore;

    if (shouldIgnoreInternalZipperedSymbol(R, SymCtx))
      return Result::Ignore;

    unsigned ID;
    Result Outcome;
    if (Mode == VerificationMode::ErrorsAndWarnings) {
      ID = diag::warn_header_hidden_symbol;
      Outcome = Result::Ignore;
    } else {
      ID = diag::err_header_hidden_symbol;
      Outcome = Result::Invalid;
    }
    Ctx.emitDiag([&]() {
      Ctx.Diag->Report(SymCtx.FA->Loc, ID) << getAnnotatedName(R, SymCtx);
    });
    return Outcome;
  }

  if (R->isInternal())
    return Result::Ignore;

  return Result::Valid;
}

DylibVerifier::Result DylibVerifier::compareAvailability(const Record *R,
                                                         SymbolContext &SymCtx,
                                                         const Record *DR) {
  if (!SymCtx.FA->Avail.isUnavailable())
    return Result::Valid;

  if (shouldIgnoreZipperedAvailability(R, SymCtx))
    return Result::Ignore;

  const bool IsDeclAvailable = SymCtx.FA->Avail.isUnavailable();

  switch (Mode) {
  case VerificationMode::ErrorsAndWarnings:
    Ctx.emitDiag([&]() {
      Ctx.Diag->Report(SymCtx.FA->Loc, diag::warn_header_availability_mismatch)
          << getAnnotatedName(R, SymCtx) << IsDeclAvailable << IsDeclAvailable;
    });
    return Result::Ignore;
  case VerificationMode::Pedantic:
    Ctx.emitDiag([&]() {
      Ctx.Diag->Report(SymCtx.FA->Loc, diag::err_header_availability_mismatch)
          << getAnnotatedName(R, SymCtx) << IsDeclAvailable << IsDeclAvailable;
    });
    return Result::Invalid;
  case VerificationMode::ErrorsOnly:
    return Result::Ignore;
  case VerificationMode::Invalid:
    llvm_unreachable("Unexpected verification mode symbol verification");
  }
  llvm_unreachable("Unexpected verification mode symbol verification");
}

bool DylibVerifier::compareSymbolFlags(const Record *R, SymbolContext &SymCtx,
                                       const Record *DR) {
  if (DR->isThreadLocalValue() && !R->isThreadLocalValue()) {
    Ctx.emitDiag([&]() {
      Ctx.Diag->Report(SymCtx.FA->Loc, diag::err_dylib_symbol_flags_mismatch)
          << getAnnotatedName(DR, SymCtx) << DR->isThreadLocalValue();
    });
    return false;
  }
  if (!DR->isThreadLocalValue() && R->isThreadLocalValue()) {
    Ctx.emitDiag([&]() {
      Ctx.Diag->Report(SymCtx.FA->Loc, diag::err_header_symbol_flags_mismatch)
          << getAnnotatedName(R, SymCtx) << R->isThreadLocalValue();
    });
    return false;
  }

  if (DR->isWeakDefined() && !R->isWeakDefined()) {
    Ctx.emitDiag([&]() {
      Ctx.Diag->Report(SymCtx.FA->Loc, diag::err_dylib_symbol_flags_mismatch)
          << getAnnotatedName(DR, SymCtx) << R->isWeakDefined();
    });
    return false;
  }
  if (!DR->isWeakDefined() && R->isWeakDefined()) {
    Ctx.emitDiag([&]() {
      Ctx.Diag->Report(SymCtx.FA->Loc, diag::err_header_symbol_flags_mismatch)
          << getAnnotatedName(R, SymCtx) << R->isWeakDefined();
    });
    return false;
  }

  return true;
}

DylibVerifier::Result DylibVerifier::verifyImpl(Record *R,
                                                SymbolContext &SymCtx) {
  R->setVerify();
  if (!canVerify()) {
    // Accumulate symbols when not in verifying against dylib.
    if (R->isExported() && !SymCtx.FA->Avail.isUnavailable() &&
        !SymCtx.FA->Avail.isObsoleted()) {
      addSymbol(R, SymCtx);
    }
    return Ctx.FrontendState;
  }

  if (shouldIgnoreReexport(R, SymCtx)) {
    updateState(Result::Ignore);
    return Ctx.FrontendState;
  }

  Record *DR =
      findRecordFromSlice(Ctx.DylibSlice, SymCtx.SymbolName, SymCtx.Kind);
  if (DR)
    DR->setVerify();

  if (shouldIgnoreObsolete(R, SymCtx, DR)) {
    updateState(Result::Ignore);
    return Ctx.FrontendState;
  }

  // Unavailable declarations don't need matching symbols.
  if (SymCtx.FA->Avail.isUnavailable() && (!DR || DR->isInternal())) {
    updateState(Result::Valid);
    return Ctx.FrontendState;
  }

  Result VisibilityCheck = compareVisibility(R, SymCtx, DR);
  if (VisibilityCheck != Result::Valid) {
    updateState(VisibilityCheck);
    return Ctx.FrontendState;
  }

  // All missing symbol cases to diagnose have been handled now.
  if (!DR) {
    updateState(Result::Ignore);
    return Ctx.FrontendState;
  }

  // Check for mismatching ObjC interfaces.
  if (SymCtx.ObjCIFKind != ObjCIFSymbolKind::None) {
    if (!compareObjCInterfaceSymbols(
            R, SymCtx, Ctx.DylibSlice->findObjCInterface(DR->getName()))) {
      updateState(Result::Invalid);
      return Ctx.FrontendState;
    }
  }

  Result AvailabilityCheck = compareAvailability(R, SymCtx, DR);
  if (AvailabilityCheck != Result::Valid) {
    updateState(AvailabilityCheck);
    return Ctx.FrontendState;
  }

  if (!compareSymbolFlags(R, SymCtx, DR)) {
    updateState(Result::Invalid);
    return Ctx.FrontendState;
  }

  addSymbol(R, SymCtx);
  updateState(Result::Valid);
  return Ctx.FrontendState;
}

bool DylibVerifier::canVerify() {
  return Ctx.FrontendState != Result::NoVerify;
}

void DylibVerifier::assignSlice(const Target &T) {
  assert(T == Ctx.Target && "Active targets should match.");
  if (Dylib.empty())
    return;

  // Note: there are no reexport slices with binaries, as opposed to TBD files,
  // so it can be assumed that the target match is the active top-level library.
  auto It = find_if(
      Dylib, [&T](const auto &Slice) { return T == Slice->getTarget(); });

  assert(It != Dylib.end() && "Target slice should always exist.");
  Ctx.DylibSlice = It->get();
}

void DylibVerifier::setTarget(const Target &T) {
  Ctx.Target = T;
  Ctx.DiscoveredFirstError = false;
  if (Dylib.empty()) {
    updateState(Result::NoVerify);
    return;
  }
  updateState(Result::Ignore);
  assignSlice(T);
}

void DylibVerifier::setSourceManager(
    IntrusiveRefCntPtr<SourceManager> SourceMgr) {
  if (!Ctx.Diag)
    return;
  SourceManagers.push_back(std::move(SourceMgr));
  Ctx.Diag->setSourceManager(SourceManagers.back().get());
}

DylibVerifier::Result DylibVerifier::verify(ObjCIVarRecord *R,
                                            const FrontendAttrs *FA,
                                            const StringRef SuperClass) {
  if (R->isVerified())
    return getState();

  std::string FullName =
      ObjCIVarRecord::createScopedName(SuperClass, R->getName());
  SymbolContext SymCtx{FullName, EncodeKind::ObjectiveCInstanceVariable, FA};
  return verifyImpl(R, SymCtx);
}

static ObjCIFSymbolKind assignObjCIFSymbolKind(const ObjCInterfaceRecord *R) {
  ObjCIFSymbolKind Result = ObjCIFSymbolKind::None;
  if (R->getLinkageForSymbol(ObjCIFSymbolKind::Class) != RecordLinkage::Unknown)
    Result |= ObjCIFSymbolKind::Class;
  if (R->getLinkageForSymbol(ObjCIFSymbolKind::MetaClass) !=
      RecordLinkage::Unknown)
    Result |= ObjCIFSymbolKind::MetaClass;
  if (R->getLinkageForSymbol(ObjCIFSymbolKind::EHType) !=
      RecordLinkage::Unknown)
    Result |= ObjCIFSymbolKind::EHType;
  return Result;
}

DylibVerifier::Result DylibVerifier::verify(ObjCInterfaceRecord *R,
                                            const FrontendAttrs *FA) {
  if (R->isVerified())
    return getState();
  SymbolContext SymCtx;
  SymCtx.SymbolName = R->getName();
  SymCtx.ObjCIFKind = assignObjCIFSymbolKind(R);

  SymCtx.Kind = R->hasExceptionAttribute() ? EncodeKind::ObjectiveCClassEHType
                                           : EncodeKind::ObjectiveCClass;
  SymCtx.FA = FA;

  return verifyImpl(R, SymCtx);
}

DylibVerifier::Result DylibVerifier::verify(GlobalRecord *R,
                                            const FrontendAttrs *FA) {
  if (R->isVerified())
    return getState();

  // Global classifications could be obfusciated with `asm`.
  SimpleSymbol Sym = parseSymbol(R->getName());
  SymbolContext SymCtx;
  SymCtx.SymbolName = Sym.Name;
  SymCtx.Kind = Sym.Kind;
  SymCtx.FA = FA;
  SymCtx.Inlined = R->isInlined();
  return verifyImpl(R, SymCtx);
}

void DylibVerifier::VerifierContext::emitDiag(llvm::function_ref<void()> Report,
                                              RecordLoc *Loc) {
  if (!DiscoveredFirstError) {
    Diag->Report(diag::warn_target)
        << (PrintArch ? getArchitectureName(Target.Arch)
                      : getTargetTripleName(Target));
    DiscoveredFirstError = true;
  }
  if (Loc && Loc->isValid())
    llvm::errs() << Loc->File << ":" << Loc->Line << ":" << 0 << ": ";

  Report();
}

// The existence of weak-defined RTTI can not always be inferred from the
// header files because they can be generated as part of an implementation
// file.
// InstallAPI doesn't warn about weak-defined RTTI, because this doesn't affect
// static linking and so can be ignored for text-api files.
static bool shouldIgnoreCpp(StringRef Name, bool IsWeakDef) {
  return (IsWeakDef &&
          (Name.starts_with("__ZTI") || Name.starts_with("__ZTS")));
}
void DylibVerifier::visitSymbolInDylib(const Record &R, SymbolContext &SymCtx) {
  // Undefined symbols should not be in InstallAPI generated text-api files.
  if (R.isUndefined()) {
    updateState(Result::Valid);
    return;
  }

  // Internal symbols should not be in InstallAPI generated text-api files.
  if (R.isInternal()) {
    updateState(Result::Valid);
    return;
  }

  // Allow zippered symbols with potentially mismatching availability
  // between macOS and macCatalyst in the final text-api file.
  const StringRef SymbolName(SymCtx.SymbolName);
  if (const Symbol *Sym = Exports->findSymbol(SymCtx.Kind, SymCtx.SymbolName,
                                              SymCtx.ObjCIFKind)) {
    if (Sym->hasArchitecture(Ctx.Target.Arch)) {
      updateState(Result::Ignore);
      return;
    }
  }

  const bool IsLinkerSymbol = SymbolName.starts_with("$ld$");

  if (R.isVerified()) {
    // Check for unavailable symbols.
    // This should only occur in the zippered case where we ignored
    // availability until all headers have been parsed.
    auto It = DeferredZipperedSymbols.find(SymCtx.SymbolName);
    if (It == DeferredZipperedSymbols.end()) {
      updateState(Result::Valid);
      return;
    }

    ZipperedDeclSources Locs;
    for (const ZipperedDeclSource &ZSource : It->second) {
      if (ZSource.FA->Avail.isObsoleted()) {
        updateState(Result::Ignore);
        return;
      }
      if (ZSource.T.Arch != Ctx.Target.Arch)
        continue;
      Locs.emplace_back(ZSource);
    }
    assert(Locs.size() == 2 && "Expected two decls for zippered symbol");

    // Print violating declarations per platform.
    for (const ZipperedDeclSource &ZSource : Locs) {
      unsigned DiagID = 0;
      if (Mode == VerificationMode::Pedantic || IsLinkerSymbol) {
        updateState(Result::Invalid);
        DiagID = diag::err_header_availability_mismatch;
      } else if (Mode == VerificationMode::ErrorsAndWarnings) {
        updateState(Result::Ignore);
        DiagID = diag::warn_header_availability_mismatch;
      } else {
        updateState(Result::Ignore);
        return;
      }
      // Bypass emitDiag banner and print the target everytime.
      Ctx.Diag->setSourceManager(ZSource.SrcMgr);
      Ctx.Diag->Report(diag::warn_target) << getTargetTripleName(ZSource.T);
      Ctx.Diag->Report(ZSource.FA->Loc, DiagID)
          << getAnnotatedName(&R, SymCtx) << ZSource.FA->Avail.isUnavailable()
          << ZSource.FA->Avail.isUnavailable();
    }
    return;
  }

  if (shouldIgnoreCpp(SymbolName, R.isWeakDefined())) {
    updateState(Result::Valid);
    return;
  }

  if (Aliases.count({SymbolName.str(), SymCtx.Kind})) {
    updateState(Result::Valid);
    return;
  }

  // All checks at this point classify as some kind of violation.
  // The different verification modes dictate whether they are reported to the
  // user.
  if (IsLinkerSymbol || (Mode > VerificationMode::ErrorsOnly))
    accumulateSrcLocForDylibSymbols();
  RecordLoc Loc = DWARFCtx->SourceLocs.lookup(SymCtx.SymbolName);

  // Regardless of verification mode, error out on mismatched special linker
  // symbols.
  if (IsLinkerSymbol) {
    Ctx.emitDiag(
        [&]() {
          Ctx.Diag->Report(diag::err_header_symbol_missing)
              << getAnnotatedName(&R, SymCtx, Loc.isValid());
        },
        &Loc);
    updateState(Result::Invalid);
    return;
  }

  // Missing declarations for exported symbols are hard errors on Pedantic mode.
  if (Mode == VerificationMode::Pedantic) {
    Ctx.emitDiag(
        [&]() {
          Ctx.Diag->Report(diag::err_header_symbol_missing)
              << getAnnotatedName(&R, SymCtx, Loc.isValid());
        },
        &Loc);
    updateState(Result::Invalid);
    return;
  }

  // Missing declarations for exported symbols are warnings on ErrorsAndWarnings
  // mode.
  if (Mode == VerificationMode::ErrorsAndWarnings) {
    Ctx.emitDiag(
        [&]() {
          Ctx.Diag->Report(diag::warn_header_symbol_missing)
              << getAnnotatedName(&R, SymCtx, Loc.isValid());
        },
        &Loc);
    updateState(Result::Ignore);
    return;
  }

  // Missing declarations are dropped for ErrorsOnly mode. It is the last
  // remaining mode.
  updateState(Result::Ignore);
}

void DylibVerifier::visitGlobal(const GlobalRecord &R) {
  SymbolContext SymCtx;
  SimpleSymbol Sym = parseSymbol(R.getName());
  SymCtx.SymbolName = Sym.Name;
  SymCtx.Kind = Sym.Kind;
  visitSymbolInDylib(R, SymCtx);
}

void DylibVerifier::visitObjCIVar(const ObjCIVarRecord &R,
                                  const StringRef Super) {
  SymbolContext SymCtx;
  SymCtx.SymbolName = ObjCIVarRecord::createScopedName(Super, R.getName());
  SymCtx.Kind = EncodeKind::ObjectiveCInstanceVariable;
  visitSymbolInDylib(R, SymCtx);
}

void DylibVerifier::accumulateSrcLocForDylibSymbols() {
  if (DSYMPath.empty())
    return;

  assert(DWARFCtx != nullptr && "Expected an initialized DWARFContext");
  if (DWARFCtx->ParsedDSYM)
    return;
  DWARFCtx->ParsedDSYM = true;
  DWARFCtx->SourceLocs =
      DylibReader::accumulateSourceLocFromDSYM(DSYMPath, Ctx.Target);
}

void DylibVerifier::visitObjCInterface(const ObjCInterfaceRecord &R) {
  SymbolContext SymCtx;
  SymCtx.SymbolName = R.getName();
  SymCtx.ObjCIFKind = assignObjCIFSymbolKind(&R);
  if (SymCtx.ObjCIFKind > ObjCIFSymbolKind::EHType) {
    if (R.hasExceptionAttribute()) {
      SymCtx.Kind = EncodeKind::ObjectiveCClassEHType;
      visitSymbolInDylib(R, SymCtx);
    }
    SymCtx.Kind = EncodeKind::ObjectiveCClass;
    visitSymbolInDylib(R, SymCtx);
  } else {
    SymCtx.Kind = R.hasExceptionAttribute() ? EncodeKind::ObjectiveCClassEHType
                                            : EncodeKind::ObjectiveCClass;
    visitSymbolInDylib(R, SymCtx);
  }

  for (const ObjCIVarRecord *IV : R.getObjCIVars())
    visitObjCIVar(*IV, R.getName());
}

void DylibVerifier::visitObjCCategory(const ObjCCategoryRecord &R) {
  for (const ObjCIVarRecord *IV : R.getObjCIVars())
    visitObjCIVar(*IV, R.getSuperClassName());
}

DylibVerifier::Result DylibVerifier::verifyRemainingSymbols() {
  if (getState() == Result::NoVerify)
    return Result::NoVerify;
  assert(!Dylib.empty() && "No binary to verify against");

  DWARFContext DWARFInfo;
  DWARFCtx = &DWARFInfo;
  Ctx.Target = Target(Architecture::AK_unknown, PlatformType::PLATFORM_UNKNOWN);
  for (std::shared_ptr<RecordsSlice> Slice : Dylib) {
    if (Ctx.Target.Arch == Slice->getTarget().Arch)
      continue;
    Ctx.DiscoveredFirstError = false;
    Ctx.PrintArch = true;
    Ctx.Target = Slice->getTarget();
    Ctx.DylibSlice = Slice.get();
    Slice->visit(*this);
  }
  return getState();
}

bool DylibVerifier::verifyBinaryAttrs(const ArrayRef<Target> ProvidedTargets,
                                      const BinaryAttrs &ProvidedBA,
                                      const LibAttrs &ProvidedReexports,
                                      const LibAttrs &ProvidedClients,
                                      const LibAttrs &ProvidedRPaths,
                                      const FileType &FT) {
  assert(!Dylib.empty() && "Need dylib to verify.");

  // Pickup any load commands that can differ per slice to compare.
  TargetList DylibTargets;
  LibAttrs DylibReexports;
  LibAttrs DylibClients;
  LibAttrs DylibRPaths;
  for (const std::shared_ptr<RecordsSlice> &RS : Dylib) {
    DylibTargets.push_back(RS->getTarget());
    const BinaryAttrs &BinInfo = RS->getBinaryAttrs();
    for (const StringRef LibName : BinInfo.RexportedLibraries)
      DylibReexports.getArchSet(LibName).set(DylibTargets.back().Arch);
    for (const StringRef LibName : BinInfo.AllowableClients)
      DylibClients.getArchSet(LibName).set(DylibTargets.back().Arch);
    // Compare attributes that are only representable in >= TBD_V5.
    if (FT >= FileType::TBD_V5)
      for (const StringRef Name : BinInfo.RPaths)
        DylibRPaths.getArchSet(Name).set(DylibTargets.back().Arch);
  }

  // Check targets first.
  ArchitectureSet ProvidedArchs = mapToArchitectureSet(ProvidedTargets);
  ArchitectureSet DylibArchs = mapToArchitectureSet(DylibTargets);
  if (ProvidedArchs != DylibArchs) {
    Ctx.Diag->Report(diag::err_architecture_mismatch)
        << ProvidedArchs << DylibArchs;
    return false;
  }
  auto ProvidedPlatforms = mapToPlatformVersionSet(ProvidedTargets);
  auto DylibPlatforms = mapToPlatformVersionSet(DylibTargets);
  if (ProvidedPlatforms != DylibPlatforms) {
    const bool DiffMinOS =
        mapToPlatformSet(ProvidedTargets) == mapToPlatformSet(DylibTargets);
    if (DiffMinOS)
      Ctx.Diag->Report(diag::warn_platform_mismatch)
          << ProvidedPlatforms << DylibPlatforms;
    else {
      Ctx.Diag->Report(diag::err_platform_mismatch)
          << ProvidedPlatforms << DylibPlatforms;
      return false;
    }
  }

  // Because InstallAPI requires certain attributes to match across architecture
  // slices, take the first one to compare those with.
  const BinaryAttrs &DylibBA = (*Dylib.begin())->getBinaryAttrs();

  if (ProvidedBA.InstallName != DylibBA.InstallName) {
    Ctx.Diag->Report(diag::err_install_name_mismatch)
        << ProvidedBA.InstallName << DylibBA.InstallName;
    return false;
  }

  if (ProvidedBA.CurrentVersion != DylibBA.CurrentVersion) {
    Ctx.Diag->Report(diag::err_current_version_mismatch)
        << ProvidedBA.CurrentVersion << DylibBA.CurrentVersion;
    return false;
  }

  if (ProvidedBA.CompatVersion != DylibBA.CompatVersion) {
    Ctx.Diag->Report(diag::err_compatibility_version_mismatch)
        << ProvidedBA.CompatVersion << DylibBA.CompatVersion;
    return false;
  }

  if (ProvidedBA.AppExtensionSafe != DylibBA.AppExtensionSafe) {
    Ctx.Diag->Report(diag::err_appextension_safe_mismatch)
        << (ProvidedBA.AppExtensionSafe ? "true" : "false")
        << (DylibBA.AppExtensionSafe ? "true" : "false");
    return false;
  }

  if (!DylibBA.TwoLevelNamespace) {
    Ctx.Diag->Report(diag::err_no_twolevel_namespace);
    return false;
  }

  if (ProvidedBA.OSLibNotForSharedCache != DylibBA.OSLibNotForSharedCache) {
    Ctx.Diag->Report(diag::err_shared_cache_eligiblity_mismatch)
        << (ProvidedBA.OSLibNotForSharedCache ? "true" : "false")
        << (DylibBA.OSLibNotForSharedCache ? "true" : "false");
    return false;
  }

  if (ProvidedBA.ParentUmbrella.empty() && !DylibBA.ParentUmbrella.empty()) {
    Ctx.Diag->Report(diag::err_parent_umbrella_missing)
        << "installAPI option" << DylibBA.ParentUmbrella;
    return false;
  }

  if (!ProvidedBA.ParentUmbrella.empty() && DylibBA.ParentUmbrella.empty()) {
    Ctx.Diag->Report(diag::err_parent_umbrella_missing)
        << "binary file" << ProvidedBA.ParentUmbrella;
    return false;
  }

  if ((!ProvidedBA.ParentUmbrella.empty()) &&
      (ProvidedBA.ParentUmbrella != DylibBA.ParentUmbrella)) {
    Ctx.Diag->Report(diag::err_parent_umbrella_mismatch)
        << ProvidedBA.ParentUmbrella << DylibBA.ParentUmbrella;
    return false;
  }

  auto CompareLibraries = [&](const LibAttrs &Provided, const LibAttrs &Dylib,
                              unsigned DiagID_missing, unsigned DiagID_mismatch,
                              bool Fatal = true) {
    if (Provided == Dylib)
      return true;

    for (const LibAttrs::Entry &PEntry : Provided.get()) {
      const auto &[PAttr, PArchSet] = PEntry;
      auto DAttrEntry = Dylib.find(PAttr);
      if (!DAttrEntry) {
        Ctx.Diag->Report(DiagID_missing) << "binary file" << PEntry;
        if (Fatal)
          return false;
      }

      if (PArchSet != DAttrEntry->second) {
        Ctx.Diag->Report(DiagID_mismatch) << PEntry << *DAttrEntry;
        if (Fatal)
          return false;
      }
    }

    for (const LibAttrs::Entry &DEntry : Dylib.get()) {
      const auto &[DAttr, DArchSet] = DEntry;
      const auto &PAttrEntry = Provided.find(DAttr);
      if (!PAttrEntry) {
        Ctx.Diag->Report(DiagID_missing) << "installAPI option" << DEntry;
        if (!Fatal)
          continue;
        return false;
      }

      if (PAttrEntry->second != DArchSet) {
        if (Fatal)
          llvm_unreachable("this case was already covered above.");
      }
    }
    return true;
  };

  if (!CompareLibraries(ProvidedReexports, DylibReexports,
                        diag::err_reexported_libraries_missing,
                        diag::err_reexported_libraries_mismatch))
    return false;

  if (!CompareLibraries(ProvidedClients, DylibClients,
                        diag::err_allowable_clients_missing,
                        diag::err_allowable_clients_mismatch))
    return false;

  if (FT >= FileType::TBD_V5) {
    // Ignore rpath differences if building an asan variant, since the
    //   compiler injects additional paths.
    // FIXME: Building with sanitizers does not always change the install
    //   name, so this is not a foolproof solution.
    if (!ProvidedBA.InstallName.ends_with("_asan")) {
      if (!CompareLibraries(ProvidedRPaths, DylibRPaths,
                            diag::warn_rpaths_missing,
                            diag::warn_rpaths_mismatch,
                            /*Fatal=*/false))
        return true;
    }
  }

  return true;
}

std::unique_ptr<SymbolSet> DylibVerifier::takeExports() {
  for (const auto &[Alias, Base] : Aliases) {
    TargetList Targets;
    SymbolFlags Flags = SymbolFlags::None;
    if (const Symbol *Sym = Exports->findSymbol(Base.second, Base.first)) {
      Flags = Sym->getFlags();
      Targets = {Sym->targets().begin(), Sym->targets().end()};
    }

    Record R(Alias.first, RecordLinkage::Exported, Flags);
    SymbolContext SymCtx;
    SymCtx.SymbolName = Alias.first;
    SymCtx.Kind = Alias.second;
    addSymbol(&R, SymCtx, std::move(Targets));
  }

  return std::move(Exports);
}

} // namespace installapi
} // namespace clang
