//===- Visitor.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/Visitor.h"
#include "clang/AST/Availability.h"
#include "clang/AST/ParentMapContext.h"
#include "clang/AST/VTableBuilder.h"
#include "clang/Basic/Linkage.h"
#include "clang/InstallAPI/DylibVerifier.h"
#include "clang/InstallAPI/FrontendRecords.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Mangler.h"

using namespace llvm;
using namespace llvm::MachO;

namespace {
enum class CXXLinkage {
  ExternalLinkage,
  LinkOnceODRLinkage,
  WeakODRLinkage,
  PrivateLinkage,
};
}

namespace clang::installapi {

// Exported NamedDecl needs to have external linkage and
// default visibility from LinkageComputer.
static bool isExported(const NamedDecl *D) {
  auto LV = D->getLinkageAndVisibility();
  return isExternallyVisible(LV.getLinkage()) &&
         (LV.getVisibility() == DefaultVisibility);
}

static bool isInlined(const FunctionDecl *D) {
  bool HasInlineAttribute = false;
  bool NoCXXAttr =
      (!D->getASTContext().getLangOpts().CPlusPlus &&
       !D->getASTContext().getTargetInfo().getCXXABI().isMicrosoft() &&
       !D->hasAttr<DLLExportAttr>());

  // Check all redeclarations to find an inline attribute or keyword.
  for (const auto *RD : D->redecls()) {
    if (!RD->isInlined())
      continue;
    HasInlineAttribute = true;
    if (!(NoCXXAttr || RD->hasAttr<GNUInlineAttr>()))
      continue;
    if (RD->doesThisDeclarationHaveABody() &&
        RD->isInlineDefinitionExternallyVisible())
      return false;
  }

  if (!HasInlineAttribute)
    return false;

  return true;
}

static SymbolFlags getFlags(bool WeakDef, bool ThreadLocal = false) {
  SymbolFlags Result = SymbolFlags::None;
  if (WeakDef)
    Result |= SymbolFlags::WeakDefined;
  if (ThreadLocal)
    Result |= SymbolFlags::ThreadLocalValue;

  return Result;
}

void InstallAPIVisitor::HandleTranslationUnit(ASTContext &ASTCtx) {
  if (ASTCtx.getDiagnostics().hasErrorOccurred())
    return;

  auto *D = ASTCtx.getTranslationUnitDecl();
  TraverseDecl(D);
}

std::string InstallAPIVisitor::getMangledName(const NamedDecl *D) const {
  SmallString<256> Name;
  if (MC->shouldMangleDeclName(D)) {
    raw_svector_ostream NStream(Name);
    MC->mangleName(D, NStream);
  } else
    Name += D->getNameAsString();

  return getBackendMangledName(Name);
}

std::string InstallAPIVisitor::getBackendMangledName(Twine Name) const {
  SmallString<256> FinalName;
  Mangler::getNameWithPrefix(FinalName, Name, DataLayout(Layout));
  return std::string(FinalName);
}

std::optional<HeaderType>
InstallAPIVisitor::getAccessForDecl(const NamedDecl *D) const {
  SourceLocation Loc = D->getLocation();
  if (Loc.isInvalid())
    return std::nullopt;

  // If the loc refers to a macro expansion, InstallAPI needs to first get the
  // file location of the expansion.
  auto FileLoc = SrcMgr.getFileLoc(Loc);
  FileID ID = SrcMgr.getFileID(FileLoc);
  if (ID.isInvalid())
    return std::nullopt;

  const FileEntry *FE = SrcMgr.getFileEntryForID(ID);
  if (!FE)
    return std::nullopt;

  auto Header = Ctx.findAndRecordFile(FE, PP);
  if (!Header.has_value())
    return std::nullopt;

  HeaderType Access = Header.value();
  assert(Access != HeaderType::Unknown && "unexpected access level for global");
  return Access;
}

/// Check if the interface itself or any of its super classes have an
/// exception attribute. InstallAPI needs to export an additional symbol
/// ("OBJC_EHTYPE_$CLASS_NAME") if any of the classes have the exception
/// attribute.
static bool hasObjCExceptionAttribute(const ObjCInterfaceDecl *D) {
  for (; D != nullptr; D = D->getSuperClass())
    if (D->hasAttr<ObjCExceptionAttr>())
      return true;

  return false;
}
void InstallAPIVisitor::recordObjCInstanceVariables(
    const ASTContext &ASTCtx, ObjCContainerRecord *Record, StringRef SuperClass,
    const llvm::iterator_range<
        DeclContext::specific_decl_iterator<ObjCIvarDecl>>
        Ivars) {
  RecordLinkage Linkage = RecordLinkage::Exported;
  const RecordLinkage ContainerLinkage = Record->getLinkage();
  // If fragile, set to unknown.
  if (ASTCtx.getLangOpts().ObjCRuntime.isFragile())
    Linkage = RecordLinkage::Unknown;
  // Linkage should be inherited from container.
  else if (ContainerLinkage != RecordLinkage::Unknown)
    Linkage = ContainerLinkage;
  for (const auto *IV : Ivars) {
    auto Access = getAccessForDecl(IV);
    if (!Access)
      continue;
    StringRef Name = IV->getName();
    const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(IV);
    auto AC = IV->getCanonicalAccessControl();
    auto [ObjCIVR, FA] =
        Ctx.Slice->addObjCIVar(Record, Name, Linkage, Avail, IV, *Access, AC);
    Ctx.Verifier->verify(ObjCIVR, FA, SuperClass);
  }
}

bool InstallAPIVisitor::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
  // Skip forward declaration for classes (@class)
  if (!D->isThisDeclarationADefinition())
    return true;

  // Skip over declarations that access could not be collected for.
  auto Access = getAccessForDecl(D);
  if (!Access)
    return true;

  StringRef Name = D->getObjCRuntimeNameAsString();
  const RecordLinkage Linkage =
      isExported(D) ? RecordLinkage::Exported : RecordLinkage::Internal;
  const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(D);
  const bool IsEHType =
      (!D->getASTContext().getLangOpts().ObjCRuntime.isFragile() &&
       hasObjCExceptionAttribute(D));

  auto [Class, FA] =
      Ctx.Slice->addObjCInterface(Name, Linkage, Avail, D, *Access, IsEHType);
  Ctx.Verifier->verify(Class, FA);

  // Get base class.
  StringRef SuperClassName;
  if (const auto *SuperClass = D->getSuperClass())
    SuperClassName = SuperClass->getObjCRuntimeNameAsString();

  recordObjCInstanceVariables(D->getASTContext(), Class, Class->getName(),
                              D->ivars());
  return true;
}

bool InstallAPIVisitor::VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
  StringRef CategoryName = D->getName();
  // Skip over declarations that access could not be collected for.
  auto Access = getAccessForDecl(D);
  if (!Access)
    return true;
  const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(D);
  const ObjCInterfaceDecl *InterfaceD = D->getClassInterface();
  const StringRef InterfaceName = InterfaceD->getName();

  ObjCCategoryRecord *CategoryRecord =
      Ctx.Slice->addObjCCategory(InterfaceName, CategoryName, Avail, D, *Access)
          .first;
  recordObjCInstanceVariables(D->getASTContext(), CategoryRecord, InterfaceName,
                              D->ivars());
  return true;
}

bool InstallAPIVisitor::VisitVarDecl(const VarDecl *D) {
  // Skip function parameters.
  if (isa<ParmVarDecl>(D))
    return true;

  // Skip variables in records. They are handled separately for C++.
  if (D->getDeclContext()->isRecord())
    return true;

  // Skip anything inside functions or methods.
  if (!D->isDefinedOutsideFunctionOrMethod())
    return true;

  // If this is a template but not specialization or instantiation, skip.
  if (D->getASTContext().getTemplateOrSpecializationInfo(D) &&
      D->getTemplateSpecializationKind() == TSK_Undeclared)
    return true;

  // Skip over declarations that access could not collected for.
  auto Access = getAccessForDecl(D);
  if (!Access)
    return true;

  const RecordLinkage Linkage =
      isExported(D) ? RecordLinkage::Exported : RecordLinkage::Internal;
  const bool WeakDef = D->hasAttr<WeakAttr>();
  const bool ThreadLocal = D->getTLSKind() != VarDecl::TLS_None;
  const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(D);
  auto [GR, FA] = Ctx.Slice->addGlobal(getMangledName(D), Linkage,
                                       GlobalRecord::Kind::Variable, Avail, D,
                                       *Access, getFlags(WeakDef, ThreadLocal));
  Ctx.Verifier->verify(GR, FA);
  return true;
}

bool InstallAPIVisitor::VisitFunctionDecl(const FunctionDecl *D) {
  if (const CXXMethodDecl *M = dyn_cast<CXXMethodDecl>(D)) {
    // Skip member function in class templates.
    if (M->getParent()->getDescribedClassTemplate() != nullptr)
      return true;

    // Skip methods in CXX RecordDecls.
    for (const DynTypedNode &P : D->getASTContext().getParents(*M)) {
      if (P.get<CXXRecordDecl>())
        return true;
    }

    // Skip CXX ConstructorDecls and DestructorDecls.
    if (isa<CXXConstructorDecl>(M) || isa<CXXDestructorDecl>(M))
      return true;
  }

  // Skip templated functions.
  switch (D->getTemplatedKind()) {
  case FunctionDecl::TK_NonTemplate:
  case FunctionDecl::TK_DependentNonTemplate:
    break;
  case FunctionDecl::TK_MemberSpecialization:
  case FunctionDecl::TK_FunctionTemplateSpecialization:
    if (auto *TempInfo = D->getTemplateSpecializationInfo()) {
      if (!TempInfo->isExplicitInstantiationOrSpecialization())
        return true;
    }
    break;
  case FunctionDecl::TK_FunctionTemplate:
  case FunctionDecl::TK_DependentFunctionTemplateSpecialization:
    return true;
  }

  auto Access = getAccessForDecl(D);
  if (!Access)
    return true;
  auto Name = getMangledName(D);
  const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(D);
  const bool ExplicitInstantiation = D->getTemplateSpecializationKind() ==
                                     TSK_ExplicitInstantiationDeclaration;
  const bool WeakDef = ExplicitInstantiation || D->hasAttr<WeakAttr>();
  const bool Inlined = isInlined(D);
  const RecordLinkage Linkage = (Inlined || !isExported(D))
                                    ? RecordLinkage::Internal
                                    : RecordLinkage::Exported;
  auto [GR, FA] =
      Ctx.Slice->addGlobal(Name, Linkage, GlobalRecord::Kind::Function, Avail,
                           D, *Access, getFlags(WeakDef), Inlined);
  Ctx.Verifier->verify(GR, FA);
  return true;
}

static bool hasVTable(const CXXRecordDecl *D) {
  // Check if vtable symbols should be emitted, only dynamic classes need
  // vtables.
  if (!D->hasDefinition() || !D->isDynamicClass())
    return false;

  assert(D->isExternallyVisible() && "Should be externally visible");
  assert(D->isCompleteDefinition() && "Only works on complete definitions");

  const CXXMethodDecl *KeyFunctionD =
      D->getASTContext().getCurrentKeyFunction(D);
  // If this class has a key function, then there is a vtable, possibly internal
  // though.
  if (KeyFunctionD) {
    switch (KeyFunctionD->getTemplateSpecializationKind()) {
    case TSK_Undeclared:
    case TSK_ExplicitSpecialization:
    case TSK_ImplicitInstantiation:
    case TSK_ExplicitInstantiationDefinition:
      return true;
    case TSK_ExplicitInstantiationDeclaration:
      llvm_unreachable(
          "Unexpected TemplateSpecializationKind for key function");
    }
  } else if (D->isAbstract()) {
    // If the class is abstract and it doesn't have a key function, it is a
    // 'pure' virtual class. It doesn't need a vtable.
    return false;
  }

  switch (D->getTemplateSpecializationKind()) {
  case TSK_Undeclared:
  case TSK_ExplicitSpecialization:
  case TSK_ImplicitInstantiation:
    return false;

  case TSK_ExplicitInstantiationDeclaration:
  case TSK_ExplicitInstantiationDefinition:
    return true;
  }

  llvm_unreachable("Invalid TemplateSpecializationKind!");
}

static CXXLinkage getVTableLinkage(const CXXRecordDecl *D) {
  assert((D->hasDefinition() && D->isDynamicClass()) && "Record has no vtable");
  assert(D->isExternallyVisible() && "Record should be externally visible");
  if (D->getVisibility() == HiddenVisibility)
    return CXXLinkage::PrivateLinkage;

  const CXXMethodDecl *KeyFunctionD =
      D->getASTContext().getCurrentKeyFunction(D);
  if (KeyFunctionD) {
    // If this class has a key function, use that to determine the
    // linkage of the vtable.
    switch (KeyFunctionD->getTemplateSpecializationKind()) {
    case TSK_Undeclared:
    case TSK_ExplicitSpecialization:
      if (isInlined(KeyFunctionD))
        return CXXLinkage::LinkOnceODRLinkage;
      return CXXLinkage::ExternalLinkage;
    case TSK_ImplicitInstantiation:
      llvm_unreachable("No external vtable for implicit instantiations");
    case TSK_ExplicitInstantiationDefinition:
      return CXXLinkage::WeakODRLinkage;
    case TSK_ExplicitInstantiationDeclaration:
      llvm_unreachable(
          "Unexpected TemplateSpecializationKind for key function");
    }
  }

  switch (D->getTemplateSpecializationKind()) {
  case TSK_Undeclared:
  case TSK_ExplicitSpecialization:
  case TSK_ImplicitInstantiation:
    return CXXLinkage::LinkOnceODRLinkage;
  case TSK_ExplicitInstantiationDeclaration:
  case TSK_ExplicitInstantiationDefinition:
    return CXXLinkage::WeakODRLinkage;
  }

  llvm_unreachable("Invalid TemplateSpecializationKind!");
}

static bool isRTTIWeakDef(const CXXRecordDecl *D) {
  if (D->hasAttr<WeakAttr>())
    return true;

  if (D->isAbstract() && D->getASTContext().getCurrentKeyFunction(D) == nullptr)
    return true;

  if (D->isDynamicClass())
    return getVTableLinkage(D) != CXXLinkage::ExternalLinkage;

  return false;
}

static bool hasRTTI(const CXXRecordDecl *D) {
  if (!D->getASTContext().getLangOpts().RTTI)
    return false;

  if (!D->hasDefinition())
    return false;

  if (!D->isDynamicClass())
    return false;

  // Don't emit weak-def RTTI information. InstallAPI cannot reliably determine
  // if the final binary will have those weak defined RTTI symbols. This depends
  // on the optimization level and if the class has been instantiated and used.
  //
  // Luckily, the Apple static linker doesn't need those weak defined RTTI
  // symbols for linking. They are only needed by the runtime linker. That means
  // they can be safely dropped.
  if (isRTTIWeakDef(D))
    return false;

  return true;
}

std::string
InstallAPIVisitor::getMangledCXXRTTIName(const CXXRecordDecl *D) const {
  SmallString<256> Name;
  raw_svector_ostream NameStream(Name);
  MC->mangleCXXRTTIName(QualType(D->getTypeForDecl(), 0), NameStream);

  return getBackendMangledName(Name);
}

std::string InstallAPIVisitor::getMangledCXXRTTI(const CXXRecordDecl *D) const {
  SmallString<256> Name;
  raw_svector_ostream NameStream(Name);
  MC->mangleCXXRTTI(QualType(D->getTypeForDecl(), 0), NameStream);

  return getBackendMangledName(Name);
}

std::string
InstallAPIVisitor::getMangledCXXVTableName(const CXXRecordDecl *D) const {
  SmallString<256> Name;
  raw_svector_ostream NameStream(Name);
  MC->mangleCXXVTable(D, NameStream);

  return getBackendMangledName(Name);
}

std::string InstallAPIVisitor::getMangledCXXThunk(
    const GlobalDecl &D, const ThunkInfo &Thunk, bool ElideOverrideInfo) const {
  SmallString<256> Name;
  raw_svector_ostream NameStream(Name);
  const auto *Method = cast<CXXMethodDecl>(D.getDecl());
  if (const auto *Dtor = dyn_cast<CXXDestructorDecl>(Method))
    MC->mangleCXXDtorThunk(Dtor, D.getDtorType(), Thunk, ElideOverrideInfo,
                           NameStream);
  else
    MC->mangleThunk(Method, Thunk, ElideOverrideInfo, NameStream);

  return getBackendMangledName(Name);
}

std::string InstallAPIVisitor::getMangledCtorDtor(const CXXMethodDecl *D,
                                                  int Type) const {
  SmallString<256> Name;
  raw_svector_ostream NameStream(Name);
  GlobalDecl GD;
  if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(D))
    GD = GlobalDecl(Ctor, CXXCtorType(Type));
  else {
    const auto *Dtor = cast<CXXDestructorDecl>(D);
    GD = GlobalDecl(Dtor, CXXDtorType(Type));
  }
  MC->mangleName(GD, NameStream);
  return getBackendMangledName(Name);
}

void InstallAPIVisitor::emitVTableSymbols(const CXXRecordDecl *D,
                                          const AvailabilityInfo &Avail,
                                          const HeaderType Access,
                                          bool EmittedVTable) {
  if (hasVTable(D)) {
    EmittedVTable = true;
    const CXXLinkage VTableLinkage = getVTableLinkage(D);
    if (VTableLinkage == CXXLinkage::ExternalLinkage ||
        VTableLinkage == CXXLinkage::WeakODRLinkage) {
      const std::string Name = getMangledCXXVTableName(D);
      const bool WeakDef = VTableLinkage == CXXLinkage::WeakODRLinkage;
      auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
                                           GlobalRecord::Kind::Variable, Avail,
                                           D, Access, getFlags(WeakDef));
      Ctx.Verifier->verify(GR, FA);
      if (!D->getDescribedClassTemplate() && !D->isInvalidDecl()) {
        VTableContextBase *VTable = D->getASTContext().getVTableContext();
        auto AddThunk = [&](GlobalDecl GD) {
          const ItaniumVTableContext::ThunkInfoVectorTy *Thunks =
              VTable->getThunkInfo(GD);
          if (!Thunks)
            return;

          for (const auto &Thunk : *Thunks) {
            const std::string Name =
                getMangledCXXThunk(GD, Thunk, /*ElideOverrideInfo=*/true);
            auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
                                                 GlobalRecord::Kind::Function,
                                                 Avail, GD.getDecl(), Access);
            Ctx.Verifier->verify(GR, FA);
          }
        };

        for (const auto *Method : D->methods()) {
          if (isa<CXXConstructorDecl>(Method) || !Method->isVirtual())
            continue;

          if (auto Dtor = dyn_cast<CXXDestructorDecl>(Method)) {
            // Skip default destructor.
            if (Dtor->isDefaulted())
              continue;
            AddThunk({Dtor, Dtor_Deleting});
            AddThunk({Dtor, Dtor_Complete});
          } else
            AddThunk(Method);
        }
      }
    }
  }

  if (!EmittedVTable)
    return;

  if (hasRTTI(D)) {
    std::string Name = getMangledCXXRTTI(D);
    auto [GR, FA] =
        Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
                             GlobalRecord::Kind::Variable, Avail, D, Access);
    Ctx.Verifier->verify(GR, FA);

    Name = getMangledCXXRTTIName(D);
    auto [NamedGR, NamedFA] =
        Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
                             GlobalRecord::Kind::Variable, Avail, D, Access);
    Ctx.Verifier->verify(NamedGR, NamedFA);
  }

  for (const auto &It : D->bases()) {
    const CXXRecordDecl *Base =
        cast<CXXRecordDecl>(It.getType()->castAs<RecordType>()->getDecl());
    const auto BaseAccess = getAccessForDecl(Base);
    if (!BaseAccess)
      continue;
    const AvailabilityInfo BaseAvail = AvailabilityInfo::createFromDecl(Base);
    emitVTableSymbols(Base, BaseAvail, *BaseAccess, /*EmittedVTable=*/true);
  }
}

bool InstallAPIVisitor::VisitCXXRecordDecl(const CXXRecordDecl *D) {
  if (!D->isCompleteDefinition())
    return true;

  // Skip templated classes.
  if (D->getDescribedClassTemplate() != nullptr)
    return true;

  // Skip partial templated classes too.
  if (isa<ClassTemplatePartialSpecializationDecl>(D))
    return true;

  auto Access = getAccessForDecl(D);
  if (!Access)
    return true;
  const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(D);

  // Check whether to emit the vtable/rtti symbols.
  if (isExported(D))
    emitVTableSymbols(D, Avail, *Access);

  TemplateSpecializationKind ClassSK = TSK_Undeclared;
  bool KeepInlineAsWeak = false;
  if (auto *Templ = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
    ClassSK = Templ->getTemplateSpecializationKind();
    if (ClassSK == TSK_ExplicitInstantiationDeclaration)
      KeepInlineAsWeak = true;
  }

  // Record the class methods.
  for (const auto *M : D->methods()) {
    // Inlined methods are usually not emitted, except when it comes from a
    // specialized template.
    bool WeakDef = false;
    if (isInlined(M)) {
      if (!KeepInlineAsWeak)
        continue;

      WeakDef = true;
    }

    if (!isExported(M))
      continue;

    switch (M->getTemplateSpecializationKind()) {
    case TSK_Undeclared:
    case TSK_ExplicitSpecialization:
      break;
    case TSK_ImplicitInstantiation:
      continue;
    case TSK_ExplicitInstantiationDeclaration:
      if (ClassSK == TSK_ExplicitInstantiationDeclaration)
        WeakDef = true;
      break;
    case TSK_ExplicitInstantiationDefinition:
      WeakDef = true;
      break;
    }

    if (!M->isUserProvided())
      continue;

    // Methods that are deleted are not exported.
    if (M->isDeleted())
      continue;

    const auto Access = getAccessForDecl(M);
    if (!Access)
      return true;
    const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(M);

    if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(M)) {
      // Defaulted constructors are not exported.
      if (Ctor->isDefaulted())
        continue;

      std::string Name = getMangledCtorDtor(M, Ctor_Base);
      auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
                                           GlobalRecord::Kind::Function, Avail,
                                           D, *Access, getFlags(WeakDef));
      Ctx.Verifier->verify(GR, FA);

      if (!D->isAbstract()) {
        std::string Name = getMangledCtorDtor(M, Ctor_Complete);
        auto [GR, FA] = Ctx.Slice->addGlobal(
            Name, RecordLinkage::Exported, GlobalRecord::Kind::Function, Avail,
            D, *Access, getFlags(WeakDef));
        Ctx.Verifier->verify(GR, FA);
      }

      continue;
    }

    if (const auto *Dtor = dyn_cast<CXXDestructorDecl>(M)) {
      // Defaulted destructors are not exported.
      if (Dtor->isDefaulted())
        continue;

      std::string Name = getMangledCtorDtor(M, Dtor_Base);
      auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
                                           GlobalRecord::Kind::Function, Avail,
                                           D, *Access, getFlags(WeakDef));
      Ctx.Verifier->verify(GR, FA);

      Name = getMangledCtorDtor(M, Dtor_Complete);
      auto [CompleteGR, CompleteFA] = Ctx.Slice->addGlobal(
          Name, RecordLinkage::Exported, GlobalRecord::Kind::Function, Avail, D,
          *Access, getFlags(WeakDef));
      Ctx.Verifier->verify(CompleteGR, CompleteFA);

      if (Dtor->isVirtual()) {
        Name = getMangledCtorDtor(M, Dtor_Deleting);
        auto [VirtualGR, VirtualFA] = Ctx.Slice->addGlobal(
            Name, RecordLinkage::Exported, GlobalRecord::Kind::Function, Avail,
            D, *Access, getFlags(WeakDef));
        Ctx.Verifier->verify(VirtualGR, VirtualFA);
      }

      continue;
    }

    // Though abstract methods can map to exports, this is generally unexpected.
    // Except in the case of destructors. Only ignore pure virtuals after
    // checking if the member function was a destructor.
    if (M->isPureVirtual())
      continue;

    std::string Name = getMangledName(M);
    auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
                                         GlobalRecord::Kind::Function, Avail, M,
                                         *Access, getFlags(WeakDef));
    Ctx.Verifier->verify(GR, FA);
  }

  if (auto *Templ = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
    if (!Templ->isExplicitInstantiationOrSpecialization())
      return true;
  }

  using var_iter = CXXRecordDecl::specific_decl_iterator<VarDecl>;
  using var_range = iterator_range<var_iter>;
  for (const auto *Var : var_range(D->decls())) {
    // Skip const static member variables.
    // \code
    // struct S {
    //   static const int x = 0;
    // };
    // \endcode
    if (Var->isStaticDataMember() && Var->hasInit())
      continue;

    // Skip unexported var decls.
    if (!isExported(Var))
      continue;

    const std::string Name = getMangledName(Var);
    const auto Access = getAccessForDecl(Var);
    if (!Access)
      return true;
    const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(Var);
    const bool WeakDef = Var->hasAttr<WeakAttr>() || KeepInlineAsWeak;

    auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
                                         GlobalRecord::Kind::Variable, Avail, D,
                                         *Access, getFlags(WeakDef));
    Ctx.Verifier->verify(GR, FA);
  }

  return true;
}

} // namespace clang::installapi
