//===--- SemaAPINotes.cpp - API Notes Handling ----------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
//  This file implements the mapping from API notes to declaration attributes.
//
//===----------------------------------------------------------------------===//

#include "CheckExprLifetime.h"
#include "TypeLocBuilder.h"
#include "clang/APINotes/APINotesReader.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Lex/Lexer.h"
#include "clang/Sema/SemaObjC.h"
#include "clang/Sema/SemaSwift.h"
#include <stack>

using namespace clang;

namespace {
enum class IsActive_t : bool { Inactive, Active };
enum class IsSubstitution_t : bool { Original, Replacement };

struct VersionedInfoMetadata {
  /// An empty version refers to unversioned metadata.
  VersionTuple Version;
  unsigned IsActive : 1;
  unsigned IsReplacement : 1;

  VersionedInfoMetadata(VersionTuple Version, IsActive_t Active,
                        IsSubstitution_t Replacement)
      : Version(Version), IsActive(Active == IsActive_t::Active),
        IsReplacement(Replacement == IsSubstitution_t::Replacement) {}
};
} // end anonymous namespace

/// Determine whether this is a multi-level pointer type.
static bool isIndirectPointerType(QualType Type) {
  QualType Pointee = Type->getPointeeType();
  if (Pointee.isNull())
    return false;

  return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() ||
         Pointee->isMemberPointerType();
}

static void applyAPINotesType(Sema &S, Decl *decl, StringRef typeString,
                              VersionedInfoMetadata metadata) {
  if (typeString.empty())

    return;

  // Version-independent APINotes add "type" annotations
  // with a versioned attribute for the client to select and apply.
  if (S.captureSwiftVersionIndependentAPINotes()) {
    auto *typeAttr = SwiftTypeAttr::CreateImplicit(S.Context, typeString);
    auto *versioned = SwiftVersionedAdditionAttr::CreateImplicit(
        S.Context, metadata.Version, typeAttr, metadata.IsReplacement);
    decl->addAttr(versioned);
  } else {
    if (!metadata.IsActive)
      return;
    S.ApplyAPINotesType(decl, typeString);
  }
}

/// Apply nullability to the given declaration.
static void applyNullability(Sema &S, Decl *decl, NullabilityKind nullability,
                             VersionedInfoMetadata metadata) {
  // Version-independent APINotes add "nullability" annotations
  // with a versioned attribute for the client to select and apply.
  if (S.captureSwiftVersionIndependentAPINotes()) {
    SwiftNullabilityAttr::Kind attrNullabilityKind;
    switch (nullability) {
    case NullabilityKind::NonNull:
      attrNullabilityKind = SwiftNullabilityAttr::Kind::NonNull;
      break;
    case NullabilityKind::Nullable:
      attrNullabilityKind = SwiftNullabilityAttr::Kind::Nullable;
      break;
    case NullabilityKind::Unspecified:
      attrNullabilityKind = SwiftNullabilityAttr::Kind::Unspecified;
      break;
    case NullabilityKind::NullableResult:
      attrNullabilityKind = SwiftNullabilityAttr::Kind::NullableResult;
      break;
    }
    auto *nullabilityAttr =
        SwiftNullabilityAttr::CreateImplicit(S.Context, attrNullabilityKind);
    auto *versioned = SwiftVersionedAdditionAttr::CreateImplicit(
        S.Context, metadata.Version, nullabilityAttr, metadata.IsReplacement);
    decl->addAttr(versioned);
    return;
  } else {
    if (!metadata.IsActive)
      return;

    S.ApplyNullability(decl, nullability);
  }
}

/// Copy a string into ASTContext-allocated memory.
static StringRef ASTAllocateString(ASTContext &Ctx, StringRef String) {
  void *mem = Ctx.Allocate(String.size(), alignof(char *));
  memcpy(mem, String.data(), String.size());
  return StringRef(static_cast<char *>(mem), String.size());
}

static AttributeCommonInfo getPlaceholderAttrInfo() {
  return AttributeCommonInfo(SourceRange(),
                             AttributeCommonInfo::UnknownAttribute,
                             {AttributeCommonInfo::AS_GNU,
                              /*Spelling*/ 0, /*IsAlignas*/ false,
                              /*IsRegularKeywordAttribute*/ false});
}

namespace {
template <typename A> struct AttrKindFor {};

#define ATTR(X)                                                                \
  template <> struct AttrKindFor<X##Attr> {                                    \
    static const attr::Kind value = attr::X;                                   \
  };
#include "clang/Basic/AttrList.inc"

/// Handle an attribute introduced by API notes.
///
/// \param IsAddition Whether we should add a new attribute
/// (otherwise, we might remove an existing attribute).
/// \param CreateAttr Create the new attribute to be added.
template <typename A>
void handleAPINotedAttribute(
    Sema &S, Decl *D, bool IsAddition, VersionedInfoMetadata Metadata,
    llvm::function_ref<A *()> CreateAttr,
    llvm::function_ref<Decl::attr_iterator(const Decl *)> GetExistingAttr) {
  if (Metadata.IsActive) {
    auto Existing = GetExistingAttr(D);
    if (Existing != D->attr_end()) {
      // Remove the existing attribute, and treat it as a superseded
      // non-versioned attribute.
      auto *Versioned = SwiftVersionedAdditionAttr::CreateImplicit(
          S.Context, Metadata.Version, *Existing, /*IsReplacedByActive*/ true);

      D->getAttrs().erase(Existing);
      D->addAttr(Versioned);
    }

    // If we're supposed to add a new attribute, do so.
    if (IsAddition) {
      if (auto Attr = CreateAttr())
        D->addAttr(Attr);
    }

    return;
  }
  if (IsAddition) {
    if (auto Attr = CreateAttr()) {
      auto *Versioned = SwiftVersionedAdditionAttr::CreateImplicit(
          S.Context, Metadata.Version, Attr,
          /*IsReplacedByActive*/ Metadata.IsReplacement);
      D->addAttr(Versioned);
    }
  } else {
    // FIXME: This isn't preserving enough information for things like
    // availability, where we're trying to remove a /specific/ kind of
    // attribute.
    auto *Versioned = SwiftVersionedRemovalAttr::CreateImplicit(
        S.Context, Metadata.Version, AttrKindFor<A>::value,
        /*IsReplacedByActive*/ Metadata.IsReplacement);
    D->addAttr(Versioned);
  }
}

template <typename A>
void handleAPINotedAttribute(Sema &S, Decl *D, bool ShouldAddAttribute,
                             VersionedInfoMetadata Metadata,
                             llvm::function_ref<A *()> CreateAttr) {
  handleAPINotedAttribute<A>(
      S, D, ShouldAddAttribute, Metadata, CreateAttr, [](const Decl *D) {
        return llvm::find_if(D->attrs(),
                             [](const Attr *Next) { return isa<A>(Next); });
      });
}
} // namespace

template <typename A>
static void handleAPINotedRetainCountAttribute(Sema &S, Decl *D,
                                               bool ShouldAddAttribute,
                                               VersionedInfoMetadata Metadata) {
  // The template argument has a default to make the "removal" case more
  // concise; it doesn't matter /which/ attribute is being removed.
  handleAPINotedAttribute<A>(
      S, D, ShouldAddAttribute, Metadata,
      [&] { return new (S.Context) A(S.Context, getPlaceholderAttrInfo()); },
      [](const Decl *D) -> Decl::attr_iterator {
        return llvm::find_if(D->attrs(), [](const Attr *Next) -> bool {
          return isa<CFReturnsRetainedAttr>(Next) ||
                 isa<CFReturnsNotRetainedAttr>(Next) ||
                 isa<NSReturnsRetainedAttr>(Next) ||
                 isa<NSReturnsNotRetainedAttr>(Next) ||
                 isa<CFAuditedTransferAttr>(Next);
        });
      });
}

static void handleAPINotedRetainCountConvention(
    Sema &S, Decl *D, VersionedInfoMetadata Metadata,
    std::optional<api_notes::RetainCountConventionKind> Convention) {
  if (!Convention)
    return;
  switch (*Convention) {
  case api_notes::RetainCountConventionKind::None:
    if (isa<FunctionDecl>(D)) {
      handleAPINotedRetainCountAttribute<CFUnknownTransferAttr>(
          S, D, /*shouldAddAttribute*/ true, Metadata);
    } else {
      handleAPINotedRetainCountAttribute<CFReturnsRetainedAttr>(
          S, D, /*shouldAddAttribute*/ false, Metadata);
    }
    break;
  case api_notes::RetainCountConventionKind::CFReturnsRetained:
    handleAPINotedRetainCountAttribute<CFReturnsRetainedAttr>(
        S, D, /*shouldAddAttribute*/ true, Metadata);
    break;
  case api_notes::RetainCountConventionKind::CFReturnsNotRetained:
    handleAPINotedRetainCountAttribute<CFReturnsNotRetainedAttr>(
        S, D, /*shouldAddAttribute*/ true, Metadata);
    break;
  case api_notes::RetainCountConventionKind::NSReturnsRetained:
    handleAPINotedRetainCountAttribute<NSReturnsRetainedAttr>(
        S, D, /*shouldAddAttribute*/ true, Metadata);
    break;
  case api_notes::RetainCountConventionKind::NSReturnsNotRetained:
    handleAPINotedRetainCountAttribute<NSReturnsNotRetainedAttr>(
        S, D, /*shouldAddAttribute*/ true, Metadata);
    break;
  }
}

static void ProcessAPINotes(Sema &S, Decl *D,
                            const api_notes::CommonEntityInfo &Info,
                            VersionedInfoMetadata Metadata) {
  // Availability
  if (Info.Unavailable) {
    handleAPINotedAttribute<UnavailableAttr>(S, D, true, Metadata, [&] {
      return new (S.Context)
          UnavailableAttr(S.Context, getPlaceholderAttrInfo(),
                          ASTAllocateString(S.Context, Info.UnavailableMsg));
    });
  }

  if (Info.UnavailableInSwift) {
    handleAPINotedAttribute<AvailabilityAttr>(
        S, D, true, Metadata,
        [&] {
          return new (S.Context) AvailabilityAttr(
              S.Context, getPlaceholderAttrInfo(),
              &S.Context.Idents.get("swift"), VersionTuple(), VersionTuple(),
              VersionTuple(),
              /*Unavailable=*/true,
              ASTAllocateString(S.Context, Info.UnavailableMsg),
              /*Strict=*/false,
              /*Replacement=*/StringRef(),
              /*Priority=*/Sema::AP_Explicit,
              /*Environment=*/nullptr);
        },
        [](const Decl *D) {
          return llvm::find_if(D->attrs(), [](const Attr *next) -> bool {
            if (const auto *AA = dyn_cast<AvailabilityAttr>(next))
              if (const auto *II = AA->getPlatform())
                return II->isStr("swift");
            return false;
          });
        });
  }

  // swift_private
  if (auto SwiftPrivate = Info.isSwiftPrivate()) {
    handleAPINotedAttribute<SwiftPrivateAttr>(
        S, D, *SwiftPrivate, Metadata, [&] {
          return new (S.Context)
              SwiftPrivateAttr(S.Context, getPlaceholderAttrInfo());
        });
  }

  // swift_name
  if (!Info.SwiftName.empty()) {
    handleAPINotedAttribute<SwiftNameAttr>(
        S, D, true, Metadata, [&]() -> SwiftNameAttr * {
          AttributeFactory AF{};
          AttributePool AP{AF};
          auto &C = S.getASTContext();
          ParsedAttr *SNA = AP.create(
              &C.Idents.get("swift_name"), SourceRange(), AttributeScopeInfo(),
              nullptr, nullptr, nullptr, ParsedAttr::Form::GNU());

          if (!S.Swift().DiagnoseName(D, Info.SwiftName, D->getLocation(), *SNA,
                                      /*IsAsync=*/false))
            return nullptr;

          return new (S.Context)
              SwiftNameAttr(S.Context, getPlaceholderAttrInfo(),
                            ASTAllocateString(S.Context, Info.SwiftName));
        });
  }
}

static void ProcessAPINotes(Sema &S, Decl *D,
                            const api_notes::CommonTypeInfo &Info,
                            VersionedInfoMetadata Metadata) {
  // swift_bridge
  if (auto SwiftBridge = Info.getSwiftBridge()) {
    handleAPINotedAttribute<SwiftBridgeAttr>(
        S, D, !SwiftBridge->empty(), Metadata, [&] {
          return new (S.Context)
              SwiftBridgeAttr(S.Context, getPlaceholderAttrInfo(),
                              ASTAllocateString(S.Context, *SwiftBridge));
        });
  }

  // ns_error_domain
  if (auto NSErrorDomain = Info.getNSErrorDomain()) {
    handleAPINotedAttribute<NSErrorDomainAttr>(
        S, D, !NSErrorDomain->empty(), Metadata, [&] {
          return new (S.Context)
              NSErrorDomainAttr(S.Context, getPlaceholderAttrInfo(),
                                &S.Context.Idents.get(*NSErrorDomain));
        });
  }

  ProcessAPINotes(S, D, static_cast<const api_notes::CommonEntityInfo &>(Info),
                  Metadata);
}

/// Check that the replacement type provided by API notes is reasonable.
///
/// This is a very weak form of ABI check.
static bool checkAPINotesReplacementType(Sema &S, SourceLocation Loc,
                                         QualType OrigType,
                                         QualType ReplacementType) {
  if (S.Context.getTypeSize(OrigType) !=
      S.Context.getTypeSize(ReplacementType)) {
    S.Diag(Loc, diag::err_incompatible_replacement_type)
        << ReplacementType << OrigType;
    return true;
  }

  return false;
}

void Sema::ApplyAPINotesType(Decl *D, StringRef TypeString) {
  if (!TypeString.empty() && ParseTypeFromStringCallback) {
    auto ParsedType = ParseTypeFromStringCallback(TypeString, "<API Notes>",
                                                  D->getLocation());
    if (ParsedType.isUsable()) {
      QualType Type = Sema::GetTypeFromParser(ParsedType.get());
      auto TypeInfo = Context.getTrivialTypeSourceInfo(Type, D->getLocation());
      if (auto Var = dyn_cast<VarDecl>(D)) {
        // Make adjustments to parameter types.
        if (isa<ParmVarDecl>(Var)) {
          Type = ObjC().AdjustParameterTypeForObjCAutoRefCount(
              Type, D->getLocation(), TypeInfo);
          Type = Context.getAdjustedParameterType(Type);
        }

        if (!checkAPINotesReplacementType(*this, Var->getLocation(),
                                          Var->getType(), Type)) {
          Var->setType(Type);
          Var->setTypeSourceInfo(TypeInfo);
        }
      } else if (auto property = dyn_cast<ObjCPropertyDecl>(D)) {
        if (!checkAPINotesReplacementType(*this, property->getLocation(),
                                          property->getType(), Type)) {
          property->setType(Type, TypeInfo);
        }
      } else {
        llvm_unreachable("API notes allowed a type on an unknown declaration");
      }
    }
  }
}

void Sema::ApplyNullability(Decl *D, NullabilityKind Nullability) {
  auto GetModified =
      [&](class Decl *D, QualType QT,
          NullabilityKind Nullability) -> std::optional<QualType> {
    QualType Original = QT;
    CheckImplicitNullabilityTypeSpecifier(QT, Nullability, D->getLocation(),
                                          isa<ParmVarDecl>(D),
                                          /*OverrideExisting=*/true);
    return (QT.getTypePtr() != Original.getTypePtr()) ? std::optional(QT)
                                                      : std::nullopt;
  };

  if (auto Function = dyn_cast<FunctionDecl>(D)) {
    if (auto Modified =
            GetModified(D, Function->getReturnType(), Nullability)) {
      const FunctionType *FnType = Function->getType()->castAs<FunctionType>();
      if (const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(FnType))
        Function->setType(Context.getFunctionType(
            *Modified, proto->getParamTypes(), proto->getExtProtoInfo()));
      else
        Function->setType(
            Context.getFunctionNoProtoType(*Modified, FnType->getExtInfo()));
    }
  } else if (auto Method = dyn_cast<ObjCMethodDecl>(D)) {
    if (auto Modified = GetModified(D, Method->getReturnType(), Nullability)) {
      Method->setReturnType(*Modified);

      // Make it a context-sensitive keyword if we can.
      if (!isIndirectPointerType(*Modified))
        Method->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
            Method->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
    }
  } else if (auto Value = dyn_cast<ValueDecl>(D)) {
    if (auto Modified = GetModified(D, Value->getType(), Nullability)) {
      Value->setType(*Modified);

      // Make it a context-sensitive keyword if we can.
      if (auto Parm = dyn_cast<ParmVarDecl>(D)) {
        if (Parm->isObjCMethodParameter() && !isIndirectPointerType(*Modified))
          Parm->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
              Parm->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
      }
    }
  } else if (auto Property = dyn_cast<ObjCPropertyDecl>(D)) {
    if (auto Modified = GetModified(D, Property->getType(), Nullability)) {
      Property->setType(*Modified, Property->getTypeSourceInfo());

      // Make it a property attribute if we can.
      if (!isIndirectPointerType(*Modified))
        Property->setPropertyAttributes(
            ObjCPropertyAttribute::kind_null_resettable);
    }
  }
}

/// Process API notes for a variable or property.
static void ProcessAPINotes(Sema &S, Decl *D,
                            const api_notes::VariableInfo &Info,
                            VersionedInfoMetadata Metadata) {
  // Type override.
  applyAPINotesType(S, D, Info.getType(), Metadata);

  // Nullability.
  if (auto Nullability = Info.getNullability())
    applyNullability(S, D, *Nullability, Metadata);

  // Handle common entity information.
  ProcessAPINotes(S, D, static_cast<const api_notes::CommonEntityInfo &>(Info),
                  Metadata);
}

/// Process API notes for a parameter.
static void ProcessAPINotes(Sema &S, ParmVarDecl *D,
                            const api_notes::ParamInfo &Info,
                            VersionedInfoMetadata Metadata) {
  // noescape
  if (auto NoEscape = Info.isNoEscape())
    handleAPINotedAttribute<NoEscapeAttr>(S, D, *NoEscape, Metadata, [&] {
      return new (S.Context) NoEscapeAttr(S.Context, getPlaceholderAttrInfo());
    });

  if (auto Lifetimebound = Info.isLifetimebound())
    handleAPINotedAttribute<LifetimeBoundAttr>(
        S, D, *Lifetimebound, Metadata, [&] {
          return new (S.Context)
              LifetimeBoundAttr(S.Context, getPlaceholderAttrInfo());
        });

  // Retain count convention
  handleAPINotedRetainCountConvention(S, D, Metadata,
                                      Info.getRetainCountConvention());

  // Handle common entity information.
  ProcessAPINotes(S, D, static_cast<const api_notes::VariableInfo &>(Info),
                  Metadata);
}

/// Process API notes for a global variable.
static void ProcessAPINotes(Sema &S, VarDecl *D,
                            const api_notes::GlobalVariableInfo &Info,
                            VersionedInfoMetadata metadata) {
  // Handle common entity information.
  ProcessAPINotes(S, D, static_cast<const api_notes::VariableInfo &>(Info),
                  metadata);
}

/// Process API notes for a C field.
static void ProcessAPINotes(Sema &S, FieldDecl *D,
                            const api_notes::FieldInfo &Info,
                            VersionedInfoMetadata metadata) {
  // Handle common entity information.
  ProcessAPINotes(S, D, static_cast<const api_notes::VariableInfo &>(Info),
                  metadata);
}

/// Process API notes for an Objective-C property.
static void ProcessAPINotes(Sema &S, ObjCPropertyDecl *D,
                            const api_notes::ObjCPropertyInfo &Info,
                            VersionedInfoMetadata Metadata) {
  // Handle common entity information.
  ProcessAPINotes(S, D, static_cast<const api_notes::VariableInfo &>(Info),
                  Metadata);

  if (auto AsAccessors = Info.getSwiftImportAsAccessors()) {
    handleAPINotedAttribute<SwiftImportPropertyAsAccessorsAttr>(
        S, D, *AsAccessors, Metadata, [&] {
          return new (S.Context) SwiftImportPropertyAsAccessorsAttr(
              S.Context, getPlaceholderAttrInfo());
        });
  }
}

namespace {
typedef llvm::PointerUnion<FunctionDecl *, ObjCMethodDecl *> FunctionOrMethod;
}

/// Process API notes for a function or method.
static void ProcessAPINotes(Sema &S, FunctionOrMethod AnyFunc,
                            const api_notes::FunctionInfo &Info,
                            VersionedInfoMetadata Metadata) {
  // Find the declaration itself.
  FunctionDecl *FD = dyn_cast<FunctionDecl *>(AnyFunc);
  Decl *D = FD;
  ObjCMethodDecl *MD = nullptr;
  if (!D) {
    MD = cast<ObjCMethodDecl *>(AnyFunc);
    D = MD;
  }

  assert((FD || MD) && "Expecting Function or ObjCMethod");

  // Nullability of return type.
  if (Info.NullabilityAudited)
    applyNullability(S, D, Info.getReturnTypeInfo(), Metadata);

  // Parameters.
  unsigned NumParams = FD ? FD->getNumParams() : MD->param_size();

  bool AnyTypeChanged = false;
  for (unsigned I = 0; I != NumParams; ++I) {
    ParmVarDecl *Param = FD ? FD->getParamDecl(I) : MD->param_begin()[I];
    QualType ParamTypeBefore = Param->getType();

    if (I < Info.Params.size())
      ProcessAPINotes(S, Param, Info.Params[I], Metadata);

    // Nullability.
    if (Info.NullabilityAudited)
      applyNullability(S, Param, Info.getParamTypeInfo(I), Metadata);

    if (ParamTypeBefore.getAsOpaquePtr() != Param->getType().getAsOpaquePtr())
      AnyTypeChanged = true;
  }

  // returns_(un)retained
  if (!Info.SwiftReturnOwnership.empty())
    D->addAttr(SwiftAttrAttr::Create(S.Context,
                                     "returns_" + Info.SwiftReturnOwnership));

  // Result type override.
  QualType OverriddenResultType;
  if (Metadata.IsActive && !Info.ResultType.empty() &&
      S.ParseTypeFromStringCallback) {
    auto ParsedType = S.ParseTypeFromStringCallback(
        Info.ResultType, "<API Notes>", D->getLocation());
    if (ParsedType.isUsable()) {
      QualType ResultType = Sema::GetTypeFromParser(ParsedType.get());

      if (MD) {
        if (!checkAPINotesReplacementType(S, D->getLocation(),
                                          MD->getReturnType(), ResultType)) {
          auto ResultTypeInfo =
              S.Context.getTrivialTypeSourceInfo(ResultType, D->getLocation());
          MD->setReturnType(ResultType);
          MD->setReturnTypeSourceInfo(ResultTypeInfo);
        }
      } else if (!checkAPINotesReplacementType(
                     S, FD->getLocation(), FD->getReturnType(), ResultType)) {
        OverriddenResultType = ResultType;
        AnyTypeChanged = true;
      }
    }
  }

  // If the result type or any of the parameter types changed for a function
  // declaration, we have to rebuild the type.
  if (FD && AnyTypeChanged) {
    if (const auto *fnProtoType = FD->getType()->getAs<FunctionProtoType>()) {
      if (OverriddenResultType.isNull())
        OverriddenResultType = fnProtoType->getReturnType();

      SmallVector<QualType, 4> ParamTypes;
      for (auto Param : FD->parameters())
        ParamTypes.push_back(Param->getType());

      FD->setType(S.Context.getFunctionType(OverriddenResultType, ParamTypes,
                                            fnProtoType->getExtProtoInfo()));
    } else if (!OverriddenResultType.isNull()) {
      const auto *FnNoProtoType = FD->getType()->castAs<FunctionNoProtoType>();
      FD->setType(S.Context.getFunctionNoProtoType(
          OverriddenResultType, FnNoProtoType->getExtInfo()));
    }
  }

  // Retain count convention
  handleAPINotedRetainCountConvention(S, D, Metadata,
                                      Info.getRetainCountConvention());

  // Handle common entity information.
  ProcessAPINotes(S, D, static_cast<const api_notes::CommonEntityInfo &>(Info),
                  Metadata);
}

/// Process API notes for a C++ method.
static void ProcessAPINotes(Sema &S, CXXMethodDecl *Method,
                            const api_notes::CXXMethodInfo &Info,
                            VersionedInfoMetadata Metadata) {
  if (Info.This && Info.This->isLifetimebound() &&
      !sema::implicitObjectParamIsLifetimeBound(Method)) {
    auto MethodType = Method->getType();
    auto *attr = ::new (S.Context)
        LifetimeBoundAttr(S.Context, getPlaceholderAttrInfo());
    QualType AttributedType =
        S.Context.getAttributedType(attr, MethodType, MethodType);
    TypeLocBuilder TLB;
    TLB.pushFullCopy(Method->getTypeSourceInfo()->getTypeLoc());
    AttributedTypeLoc TyLoc = TLB.push<AttributedTypeLoc>(AttributedType);
    TyLoc.setAttr(attr);
    Method->setType(AttributedType);
    Method->setTypeSourceInfo(TLB.getTypeSourceInfo(S.Context, AttributedType));
  }

  ProcessAPINotes(S, (FunctionOrMethod)Method, Info, Metadata);
}

/// Process API notes for a global function.
static void ProcessAPINotes(Sema &S, FunctionDecl *D,
                            const api_notes::GlobalFunctionInfo &Info,
                            VersionedInfoMetadata Metadata) {
  // Handle common function information.
  ProcessAPINotes(S, FunctionOrMethod(D),
                  static_cast<const api_notes::FunctionInfo &>(Info), Metadata);
}

/// Process API notes for an enumerator.
static void ProcessAPINotes(Sema &S, EnumConstantDecl *D,
                            const api_notes::EnumConstantInfo &Info,
                            VersionedInfoMetadata Metadata) {
  // Handle common information.
  ProcessAPINotes(S, D, static_cast<const api_notes::CommonEntityInfo &>(Info),
                  Metadata);
}

/// Process API notes for an Objective-C method.
static void ProcessAPINotes(Sema &S, ObjCMethodDecl *D,
                            const api_notes::ObjCMethodInfo &Info,
                            VersionedInfoMetadata Metadata) {
  // Designated initializers.
  if (Info.DesignatedInit) {
    handleAPINotedAttribute<ObjCDesignatedInitializerAttr>(
        S, D, true, Metadata, [&] {
          if (ObjCInterfaceDecl *IFace = D->getClassInterface())
            IFace->setHasDesignatedInitializers();

          return new (S.Context) ObjCDesignatedInitializerAttr(
              S.Context, getPlaceholderAttrInfo());
        });
  }

  // Handle common function information.
  ProcessAPINotes(S, FunctionOrMethod(D),
                  static_cast<const api_notes::FunctionInfo &>(Info), Metadata);
}

/// Process API notes for a tag.
static void ProcessAPINotes(Sema &S, TagDecl *D, const api_notes::TagInfo &Info,
                            VersionedInfoMetadata Metadata) {
  if (auto ImportAs = Info.SwiftImportAs)
    D->addAttr(SwiftAttrAttr::Create(S.Context, "import_" + ImportAs.value()));

  if (auto RetainOp = Info.SwiftRetainOp)
    D->addAttr(SwiftAttrAttr::Create(S.Context, "retain:" + RetainOp.value()));

  if (auto ReleaseOp = Info.SwiftReleaseOp)
    D->addAttr(
        SwiftAttrAttr::Create(S.Context, "release:" + ReleaseOp.value()));
  if (auto DefaultOwnership = Info.SwiftDefaultOwnership)
    D->addAttr(SwiftAttrAttr::Create(
        S.Context, "returned_as_" + DefaultOwnership.value() + "_by_default"));

  if (auto ConformsTo = Info.SwiftConformance)
    D->addAttr(
        SwiftAttrAttr::Create(S.Context, "conforms_to:" + ConformsTo.value()));

  if (auto Copyable = Info.isSwiftCopyable()) {
    if (!*Copyable)
      D->addAttr(SwiftAttrAttr::Create(S.Context, "~Copyable"));
  }

  if (auto Escapable = Info.isSwiftEscapable()) {
    D->addAttr(SwiftAttrAttr::Create(S.Context,
                                     *Escapable ? "Escapable" : "~Escapable"));
  }

  if (auto Extensibility = Info.EnumExtensibility) {
    using api_notes::EnumExtensibilityKind;
    bool ShouldAddAttribute = (*Extensibility != EnumExtensibilityKind::None);
    handleAPINotedAttribute<EnumExtensibilityAttr>(
        S, D, ShouldAddAttribute, Metadata, [&] {
          EnumExtensibilityAttr::Kind kind;
          switch (*Extensibility) {
          case EnumExtensibilityKind::None:
            llvm_unreachable("remove only");
          case EnumExtensibilityKind::Open:
            kind = EnumExtensibilityAttr::Open;
            break;
          case EnumExtensibilityKind::Closed:
            kind = EnumExtensibilityAttr::Closed;
            break;
          }
          return new (S.Context)
              EnumExtensibilityAttr(S.Context, getPlaceholderAttrInfo(), kind);
        });
  }

  if (auto FlagEnum = Info.isFlagEnum()) {
    handleAPINotedAttribute<FlagEnumAttr>(S, D, *FlagEnum, Metadata, [&] {
      return new (S.Context) FlagEnumAttr(S.Context, getPlaceholderAttrInfo());
    });
  }

  // Handle common type information.
  ProcessAPINotes(S, D, static_cast<const api_notes::CommonTypeInfo &>(Info),
                  Metadata);
}

/// Process API notes for a typedef.
static void ProcessAPINotes(Sema &S, TypedefNameDecl *D,
                            const api_notes::TypedefInfo &Info,
                            VersionedInfoMetadata Metadata) {
  // swift_wrapper
  using SwiftWrapperKind = api_notes::SwiftNewTypeKind;

  if (auto SwiftWrapper = Info.SwiftWrapper) {
    handleAPINotedAttribute<SwiftNewTypeAttr>(
        S, D, *SwiftWrapper != SwiftWrapperKind::None, Metadata, [&] {
          SwiftNewTypeAttr::NewtypeKind Kind;
          switch (*SwiftWrapper) {
          case SwiftWrapperKind::None:
            llvm_unreachable("Shouldn't build an attribute");

          case SwiftWrapperKind::Struct:
            Kind = SwiftNewTypeAttr::NK_Struct;
            break;

          case SwiftWrapperKind::Enum:
            Kind = SwiftNewTypeAttr::NK_Enum;
            break;
          }
          AttributeCommonInfo SyntaxInfo{
              SourceRange(),
              AttributeCommonInfo::AT_SwiftNewType,
              {AttributeCommonInfo::AS_GNU, SwiftNewTypeAttr::GNU_swift_wrapper,
               /*IsAlignas*/ false, /*IsRegularKeywordAttribute*/ false}};
          return new (S.Context) SwiftNewTypeAttr(S.Context, SyntaxInfo, Kind);
        });
  }

  // Handle common type information.
  ProcessAPINotes(S, D, static_cast<const api_notes::CommonTypeInfo &>(Info),
                  Metadata);
}

/// Process API notes for an Objective-C class or protocol.
static void ProcessAPINotes(Sema &S, ObjCContainerDecl *D,
                            const api_notes::ContextInfo &Info,
                            VersionedInfoMetadata Metadata) {
  // Handle common type information.
  ProcessAPINotes(S, D, static_cast<const api_notes::CommonTypeInfo &>(Info),
                  Metadata);
}

/// Process API notes for an Objective-C class.
static void ProcessAPINotes(Sema &S, ObjCInterfaceDecl *D,
                            const api_notes::ContextInfo &Info,
                            VersionedInfoMetadata Metadata) {
  if (auto AsNonGeneric = Info.getSwiftImportAsNonGeneric()) {
    handleAPINotedAttribute<SwiftImportAsNonGenericAttr>(
        S, D, *AsNonGeneric, Metadata, [&] {
          return new (S.Context)
              SwiftImportAsNonGenericAttr(S.Context, getPlaceholderAttrInfo());
        });
  }

  if (auto ObjcMembers = Info.getSwiftObjCMembers()) {
    handleAPINotedAttribute<SwiftObjCMembersAttr>(
        S, D, *ObjcMembers, Metadata, [&] {
          return new (S.Context)
              SwiftObjCMembersAttr(S.Context, getPlaceholderAttrInfo());
        });
  }

  // Handle information common to Objective-C classes and protocols.
  ProcessAPINotes(S, static_cast<clang::ObjCContainerDecl *>(D), Info,
                  Metadata);
}

/// If we're applying API notes with an active, non-default version, and the
/// versioned API notes have a SwiftName but the declaration normally wouldn't
/// have one, add a removal attribute to make it clear that the new SwiftName
/// attribute only applies to the active version of \p D, not to all versions.
///
/// This must be run \em before processing API notes for \p D, because otherwise
/// any existing SwiftName attribute will have been packaged up in a
/// SwiftVersionedAdditionAttr.
template <typename SpecificInfo>
static void maybeAttachUnversionedSwiftName(
    Sema &S, Decl *D,
    const api_notes::APINotesReader::VersionedInfo<SpecificInfo> Info) {
  if (D->hasAttr<SwiftNameAttr>())
    return;
  if (!Info.getSelected())
    return;

  // Is the active slice versioned, and does it set a Swift name?
  VersionTuple SelectedVersion;
  SpecificInfo SelectedInfoSlice;
  std::tie(SelectedVersion, SelectedInfoSlice) = Info[*Info.getSelected()];
  if (SelectedVersion.empty())
    return;
  if (SelectedInfoSlice.SwiftName.empty())
    return;

  // Does the unversioned slice /not/ set a Swift name?
  for (const auto &VersionAndInfoSlice : Info) {
    if (!VersionAndInfoSlice.first.empty())
      continue;
    if (!VersionAndInfoSlice.second.SwiftName.empty())
      return;
  }

  // Then explicitly call that out with a removal attribute.
  VersionedInfoMetadata DummyFutureMetadata(
      SelectedVersion, IsActive_t::Inactive, IsSubstitution_t::Replacement);
  handleAPINotedAttribute<SwiftNameAttr>(
      S, D, /*add*/ false, DummyFutureMetadata, []() -> SwiftNameAttr * {
        llvm_unreachable("should not try to add an attribute here");
      });
}

/// Processes all versions of versioned API notes.
///
/// Just dispatches to the various ProcessAPINotes functions in this file.
template <typename SpecificDecl, typename SpecificInfo>
static void ProcessVersionedAPINotes(
    Sema &S, SpecificDecl *D,
    const api_notes::APINotesReader::VersionedInfo<SpecificInfo> Info) {

  if (!S.captureSwiftVersionIndependentAPINotes())
    maybeAttachUnversionedSwiftName(S, D, Info);

  unsigned Selected = Info.getSelected().value_or(Info.size());

  VersionTuple Version;
  SpecificInfo InfoSlice;
  for (unsigned i = 0, e = Info.size(); i != e; ++i) {
    std::tie(Version, InfoSlice) = Info[i];
    auto Active = (i == Selected) ? IsActive_t::Active : IsActive_t::Inactive;
    auto Replacement = IsSubstitution_t::Original;

    // When collection all APINotes as version-independent,
    // capture all as inactive and defer to the client select the
    // right one.
    if (S.captureSwiftVersionIndependentAPINotes()) {
      Active = IsActive_t::Inactive;
      Replacement = IsSubstitution_t::Original;
    } else if (Active == IsActive_t::Inactive && Version.empty()) {
      Replacement = IsSubstitution_t::Replacement;
      Version = Info[Selected].first;
    }

    ProcessAPINotes(S, D, InfoSlice,
                    VersionedInfoMetadata(Version, Active, Replacement));
  }
}

static std::optional<api_notes::Context>
UnwindNamespaceContext(DeclContext *DC, api_notes::APINotesManager &APINotes) {
  if (auto NamespaceContext = dyn_cast<NamespaceDecl>(DC)) {
    for (auto Reader : APINotes.findAPINotes(NamespaceContext->getLocation())) {
      // Retrieve the context ID for the parent namespace of the decl.
      std::stack<NamespaceDecl *> NamespaceStack;
      {
        for (auto CurrentNamespace = NamespaceContext; CurrentNamespace;
             CurrentNamespace =
                 dyn_cast<NamespaceDecl>(CurrentNamespace->getParent())) {
          if (!CurrentNamespace->isInlineNamespace())
            NamespaceStack.push(CurrentNamespace);
        }
      }
      std::optional<api_notes::ContextID> NamespaceID;
      while (!NamespaceStack.empty()) {
        auto CurrentNamespace = NamespaceStack.top();
        NamespaceStack.pop();
        NamespaceID =
            Reader->lookupNamespaceID(CurrentNamespace->getName(), NamespaceID);
        if (!NamespaceID)
          return std::nullopt;
      }
      if (NamespaceID)
        return api_notes::Context(*NamespaceID,
                                  api_notes::ContextKind::Namespace);
    }
  }
  return std::nullopt;
}

static std::optional<api_notes::Context>
UnwindTagContext(TagDecl *DC, api_notes::APINotesManager &APINotes) {
  assert(DC && "tag context must not be null");
  for (auto Reader : APINotes.findAPINotes(DC->getLocation())) {
    // Retrieve the context ID for the parent tag of the decl.
    std::stack<TagDecl *> TagStack;
    {
      for (auto CurrentTag = DC; CurrentTag;
           CurrentTag = dyn_cast<TagDecl>(CurrentTag->getParent()))
        TagStack.push(CurrentTag);
    }
    assert(!TagStack.empty());
    std::optional<api_notes::Context> Ctx =
        UnwindNamespaceContext(TagStack.top()->getDeclContext(), APINotes);
    while (!TagStack.empty()) {
      auto CurrentTag = TagStack.top();
      TagStack.pop();
      auto CtxID = Reader->lookupTagID(CurrentTag->getName(), Ctx);
      if (!CtxID)
        return std::nullopt;
      Ctx = api_notes::Context(*CtxID, api_notes::ContextKind::Tag);
    }
    return Ctx;
  }
  return std::nullopt;
}

/// Process API notes that are associated with this declaration, mapping them
/// to attributes as appropriate.
void Sema::ProcessAPINotes(Decl *D) {
  if (!D)
    return;

  auto *DC = D->getDeclContext();
  // Globals.
  if (DC->isFileContext() || DC->isNamespace() || DC->isExternCContext() ||
      DC->isExternCXXContext()) {
    std::optional<api_notes::Context> APINotesContext =
        UnwindNamespaceContext(DC, APINotes);
    // Global variables.
    if (auto VD = dyn_cast<VarDecl>(D)) {
      for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
        auto Info =
            Reader->lookupGlobalVariable(VD->getName(), APINotesContext);
        ProcessVersionedAPINotes(*this, VD, Info);
      }

      return;
    }

    // Global functions.
    if (auto FD = dyn_cast<FunctionDecl>(D)) {
      if (FD->getDeclName().isIdentifier()) {
        for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
          auto Info =
              Reader->lookupGlobalFunction(FD->getName(), APINotesContext);
          ProcessVersionedAPINotes(*this, FD, Info);
        }
      }

      return;
    }

    // Objective-C classes.
    if (auto Class = dyn_cast<ObjCInterfaceDecl>(D)) {
      for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
        auto Info = Reader->lookupObjCClassInfo(Class->getName());
        ProcessVersionedAPINotes(*this, Class, Info);
      }

      return;
    }

    // Objective-C protocols.
    if (auto Protocol = dyn_cast<ObjCProtocolDecl>(D)) {
      for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
        auto Info = Reader->lookupObjCProtocolInfo(Protocol->getName());
        ProcessVersionedAPINotes(*this, Protocol, Info);
      }

      return;
    }

    // Tags
    if (auto Tag = dyn_cast<TagDecl>(D)) {
      // Determine the name of the entity to search for. If this is an
      // anonymous tag that gets its linked name from a typedef, look for the
      // typedef name. This allows tag-specific information to be added
      // to the declaration.
      std::string LookupName;
      if (auto typedefName = Tag->getTypedefNameForAnonDecl())
        LookupName = typedefName->getName().str();
      else
        LookupName = Tag->getName().str();

      // Use the source location to discern if this Tag is an OPTIONS macro.
      // For now we would like to limit this trick of looking up the APINote tag
      // using the EnumDecl's QualType in the case where the enum is anonymous.
      // This is only being used to support APINotes lookup for C++
      // NS/CF_OPTIONS when C++-Interop is enabled.
      std::string MacroName =
          LookupName.empty() && Tag->getOuterLocStart().isMacroID()
              ? clang::Lexer::getImmediateMacroName(
                    Tag->getOuterLocStart(),
                    Tag->getASTContext().getSourceManager(), LangOpts)
                    .str()
              : "";

      if (LookupName.empty() && isa<clang::EnumDecl>(Tag) &&
          (MacroName == "CF_OPTIONS" || MacroName == "NS_OPTIONS" ||
           MacroName == "OBJC_OPTIONS" || MacroName == "SWIFT_OPTIONS")) {

        clang::QualType T = llvm::cast<clang::EnumDecl>(Tag)->getIntegerType();
        LookupName = clang::QualType::getAsString(
            T.split(), getASTContext().getPrintingPolicy());
      }

      for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
        if (auto ParentTag = dyn_cast<TagDecl>(Tag->getDeclContext()))
          APINotesContext = UnwindTagContext(ParentTag, APINotes);
        auto Info = Reader->lookupTag(LookupName, APINotesContext);
        ProcessVersionedAPINotes(*this, Tag, Info);
      }

      return;
    }

    // Typedefs
    if (auto Typedef = dyn_cast<TypedefNameDecl>(D)) {
      for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
        auto Info = Reader->lookupTypedef(Typedef->getName(), APINotesContext);
        ProcessVersionedAPINotes(*this, Typedef, Info);
      }

      return;
    }
  }

  // Enumerators.
  if (DC->getRedeclContext()->isFileContext() ||
      DC->getRedeclContext()->isExternCContext()) {
    if (auto EnumConstant = dyn_cast<EnumConstantDecl>(D)) {
      for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
        auto Info = Reader->lookupEnumConstant(EnumConstant->getName());
        ProcessVersionedAPINotes(*this, EnumConstant, Info);
      }

      return;
    }
  }

  if (auto ObjCContainer = dyn_cast<ObjCContainerDecl>(DC)) {
    // Location function that looks up an Objective-C context.
    auto GetContext = [&](api_notes::APINotesReader *Reader)
        -> std::optional<api_notes::ContextID> {
      if (auto Protocol = dyn_cast<ObjCProtocolDecl>(ObjCContainer)) {
        if (auto Found = Reader->lookupObjCProtocolID(Protocol->getName()))
          return *Found;

        return std::nullopt;
      }

      if (auto Impl = dyn_cast<ObjCCategoryImplDecl>(ObjCContainer)) {
        if (auto Cat = Impl->getCategoryDecl())
          ObjCContainer = Cat->getClassInterface();
        else
          return std::nullopt;
      }

      if (auto Category = dyn_cast<ObjCCategoryDecl>(ObjCContainer)) {
        if (Category->getClassInterface())
          ObjCContainer = Category->getClassInterface();
        else
          return std::nullopt;
      }

      if (auto Impl = dyn_cast<ObjCImplDecl>(ObjCContainer)) {
        if (Impl->getClassInterface())
          ObjCContainer = Impl->getClassInterface();
        else
          return std::nullopt;
      }

      if (auto Class = dyn_cast<ObjCInterfaceDecl>(ObjCContainer)) {
        if (auto Found = Reader->lookupObjCClassID(Class->getName()))
          return *Found;

        return std::nullopt;
      }

      return std::nullopt;
    };

    // Objective-C methods.
    if (auto Method = dyn_cast<ObjCMethodDecl>(D)) {
      for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
        if (auto Context = GetContext(Reader)) {
          // Map the selector.
          Selector Sel = Method->getSelector();
          SmallVector<StringRef, 2> SelPieces;
          if (Sel.isUnarySelector()) {
            SelPieces.push_back(Sel.getNameForSlot(0));
          } else {
            for (unsigned i = 0, n = Sel.getNumArgs(); i != n; ++i)
              SelPieces.push_back(Sel.getNameForSlot(i));
          }

          api_notes::ObjCSelectorRef SelectorRef;
          SelectorRef.NumArgs = Sel.getNumArgs();
          SelectorRef.Identifiers = SelPieces;

          auto Info = Reader->lookupObjCMethod(*Context, SelectorRef,
                                               Method->isInstanceMethod());
          ProcessVersionedAPINotes(*this, Method, Info);
        }
      }
    }

    // Objective-C properties.
    if (auto Property = dyn_cast<ObjCPropertyDecl>(D)) {
      for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
        if (auto Context = GetContext(Reader)) {
          bool isInstanceProperty =
              (Property->getPropertyAttributesAsWritten() &
               ObjCPropertyAttribute::kind_class) == 0;
          auto Info = Reader->lookupObjCProperty(*Context, Property->getName(),
                                                 isInstanceProperty);
          ProcessVersionedAPINotes(*this, Property, Info);
        }
      }

      return;
    }
  }

  if (auto TagContext = dyn_cast<TagDecl>(DC)) {
    if (auto CXXMethod = dyn_cast<CXXMethodDecl>(D)) {
      if (!isa<CXXConstructorDecl>(CXXMethod) &&
          !isa<CXXDestructorDecl>(CXXMethod) &&
          !isa<CXXConversionDecl>(CXXMethod) &&
          !CXXMethod->isOverloadedOperator()) {
        for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
          if (auto Context = UnwindTagContext(TagContext, APINotes)) {
            auto Info =
                Reader->lookupCXXMethod(Context->id, CXXMethod->getName());
            ProcessVersionedAPINotes(*this, CXXMethod, Info);
          }
        }
      }
    }

    if (auto Field = dyn_cast<FieldDecl>(D)) {
      if (!Field->isUnnamedBitField() && !Field->isAnonymousStructOrUnion()) {
        for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
          if (auto Context = UnwindTagContext(TagContext, APINotes)) {
            auto Info = Reader->lookupField(Context->id, Field->getName());
            ProcessVersionedAPINotes(*this, Field, Info);
          }
        }
      }
    }

    if (auto Tag = dyn_cast<TagDecl>(D)) {
      for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
        if (auto Context = UnwindTagContext(TagContext, APINotes)) {
          auto Info = Reader->lookupTag(Tag->getName(), Context);
          ProcessVersionedAPINotes(*this, Tag, Info);
        }
      }
    }
  }
}
