//===--- SemaAPINotes.cpp - API Notes Handling ----------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements the mapping from API notes to declaration attributes.
//
//===----------------------------------------------------------------------===//

#include "clang/Sema/SemaInternal.h"
#include "clang/AST/DeclObjC.h"
#include "clang/APINotes/APINotesReader.h"
using namespace clang;

namespace {
  enum IsActive_t : bool {
    IsNotActive,
    IsActive
  };
  enum IsReplacement_t : bool {
    IsNotReplacement,
    IsReplacement
  };

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

    VersionedInfoMetadata(VersionTuple version, IsActive_t active,
                          IsReplacement_t replacement)
      : Version(version), IsActive(active == IsActive_t::IsActive),
        IsReplacement(replacement == IsReplacement_t::IsReplacement) {}
  };
} // end anonymous namespace

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

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

// Apply nullability to the given declaration.
static void applyNullability(Sema &S, Decl *decl, NullabilityKind nullability,
                             VersionedInfoMetadata metadata) {
  if (!metadata.IsActive)
    return;

  QualType type;

  // Nullability for a function/method appertains to the retain type.
  if (auto function = dyn_cast<FunctionDecl>(decl)) {
    type = function->getReturnType();
  } else if (auto method = dyn_cast<ObjCMethodDecl>(decl)) {
    type = method->getReturnType();
  } else if (auto value = dyn_cast<ValueDecl>(decl)) {
    type = value->getType();
  } else if (auto property = dyn_cast<ObjCPropertyDecl>(decl)) {
    type = property->getType();
  } else {
    return;
  }

  // Check the nullability specifier on this type.
  QualType origType = type;
  S.checkNullabilityTypeSpecifier(type, nullability, decl->getLocation(),
                                  /*isContextSensitive=*/false,
                                  isa<ParmVarDecl>(decl), /*implicit=*/true,
                                  /*overrideExisting=*/true);
  if (type.getTypePtr() == origType.getTypePtr())
    return;

  if (auto function = dyn_cast<FunctionDecl>(decl)) {
    const FunctionType *fnType = function->getType()->castAs<FunctionType>();
    if (const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(fnType)) {
      function->setType(S.Context.getFunctionType(type, proto->getParamTypes(),
                                                  proto->getExtProtoInfo()));
    } else {
      function->setType(S.Context.getFunctionNoProtoType(type,
                                                         fnType->getExtInfo()));
    }
  } else if (auto method = dyn_cast<ObjCMethodDecl>(decl)) {
    method->setReturnType(type);

    // Make it a context-sensitive keyword if we can.
    if (!isMultiLevelPointerType(type)) {
      method->setObjCDeclQualifier(
        Decl::ObjCDeclQualifier(method->getObjCDeclQualifier() |
                                Decl::OBJC_TQ_CSNullability));
    }
  } else if (auto value = dyn_cast<ValueDecl>(decl)) {
    value->setType(type);

    // Make it a context-sensitive keyword if we can.
    if (auto parm = dyn_cast<ParmVarDecl>(decl)) {
      if (parm->isObjCMethodParameter() && !isMultiLevelPointerType(type)) {
        parm->setObjCDeclQualifier(
          Decl::ObjCDeclQualifier(parm->getObjCDeclQualifier() |
                                  Decl::OBJC_TQ_CSNullability));
      }
    }
  } else if (auto property = dyn_cast<ObjCPropertyDecl>(decl)) {
    property->setType(type, property->getTypeSourceInfo());

    // Make it a property attribute if we can.
    if (!isMultiLevelPointerType(type)) {
      property->setPropertyAttributes(
        ObjCPropertyDecl::OBJC_PR_null_resettable);
    }
  } else {
    llvm_unreachable("cannot handle nullability here");
  }
}

/// Copy a string into ASTContext-allocated memory.
static StringRef CopyString(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());
}

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 shouldAddAttribute 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 shouldAddAttribute,
         VersionedInfoMetadata metadata,
         llvm::function_ref<A *()> createAttr,
         llvm::function_ref<specific_attr_iterator<A>(Decl*)> getExistingAttr) {
    if (metadata.IsActive) {
      auto end = D->specific_attr_end<A>();
      auto existing = getExistingAttr(D);
      if (existing != end) {
        // Remove the existing attribute, and treat it as a superseded
        // non-versioned attribute.
        auto *versioned = SwiftVersionedAttr::CreateImplicit(
            S.Context, metadata.Version, *existing, /*IsReplacedByActive*/true);

        D->getAttrs().erase(existing.getCurrent());
        D->addAttr(versioned);
      }

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

    } else {
      if (shouldAddAttribute) {
        if (auto attr = createAttr()) {
          auto *versioned = SwiftVersionedAttr::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,
    [](Decl *decl) {
        return decl->specific_attr_begin<A>();
    });
  }
}

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 UnavailableAttr::CreateImplicit(S.Context,
                                               CopyString(S.Context,
                                                          info.UnavailableMsg));
    });
  }

  if (info.UnavailableInSwift) {
    handleAPINotedAttribute<AvailabilityAttr>(S, D, true, metadata, [&] {
      return AvailabilityAttr::CreateImplicit(
                   S.Context,
                   &S.Context.Idents.get("swift"),
                   VersionTuple(),
                   VersionTuple(),
                   VersionTuple(),
                   /*Unavailable=*/true,
                   CopyString(S.Context, info.UnavailableMsg),
                   /*Strict=*/false,
                   /*Replacement=*/StringRef());
    },
    [](Decl *decl) {
      auto existing = decl->specific_attr_begin<AvailabilityAttr>(),
        end = decl->specific_attr_end<AvailabilityAttr>();
      while (existing != end) {
        if (auto platform = (*existing)->getPlatform()) {
          if (platform->isStr("swift"))
            break;
        }

        ++existing;
      }

      return existing;
    });
  }

  // swift_private
  if (auto swiftPrivate = info.isSwiftPrivate()) {
    handleAPINotedAttribute<SwiftPrivateAttr>(S, D, *swiftPrivate, metadata,
                                              [&] {
      return SwiftPrivateAttr::CreateImplicit(S.Context);
    });
  }

  // swift_name
  if (!info.SwiftName.empty()) {
    handleAPINotedAttribute<SwiftNameAttr>(S, D, true, metadata,
                                           [&]() -> SwiftNameAttr * {
      auto &APINoteName = S.getASTContext().Idents.get("SwiftName API Note");
      
      if (!S.DiagnoseSwiftName(D, info.SwiftName, D->getLocation(),
                               &APINoteName)) {
        return nullptr;
      }

      return SwiftNameAttr::CreateImplicit(S.Context,
                                           CopyString(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 SwiftBridgeAttr::CreateImplicit(S.Context,
                                             CopyString(S.Context,
                                                        *swiftBridge));
    });
  }

  // ns_error_domain
  if (auto nsErrorDomain = info.getNSErrorDomain()) {
    handleAPINotedAttribute<NSErrorDomainAttr>(S, D, !nsErrorDomain->empty(),
                                               metadata, [&] {
      return NSErrorDomainAttr::CreateImplicit(
               S.Context,
               &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;
}

/// Process API notes for a variable or property.
static void ProcessAPINotes(Sema &S, Decl *D,
                            const api_notes::VariableInfo &info,
                            VersionedInfoMetadata metadata) {
  // Type override.
  if (metadata.IsActive && !info.getType().empty() &&
      S.ParseTypeFromStringCallback) {
    auto parsedType = S.ParseTypeFromStringCallback(info.getType(),
                                                    "<API Notes>",
                                                    D->getLocation());
    if (parsedType.isUsable()) {
      QualType type = Sema::GetTypeFromParser(parsedType.get());
      auto typeInfo =
        S.Context.getTrivialTypeSourceInfo(type, D->getLocation());

      if (auto var = dyn_cast<VarDecl>(D)) {
        // Make adjustments to parameter types.
        if (isa<ParmVarDecl>(var)) {
          type = S.adjustParameterTypeForObjCAutoRefCount(type,
                                                          D->getLocation());
          type = S.Context.getAdjustedParameterType(type);
        }

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

  // 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 NoEscapeAttr::CreateImplicit(S.Context);
    });
  }

  // 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 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 SwiftImportPropertyAsAccessorsAttr::CreateImplicit(S.Context);
    });
  }
}

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 = AnyFunc.dyn_cast<FunctionDecl *>();
  Decl *D = FD;
  ObjCMethodDecl *MD = 0;
  if (!D) {
    MD = AnyFunc.get<ObjCMethodDecl *>();
    D = MD;
  }

  // Nullability of return type.
  if (info.NullabilityAudited) {
    applyNullability(S, D, info.getReturnTypeInfo(), metadata);
  }

  // Parameters.
  unsigned NumParams;
  if (FD)
    NumParams = FD->getNumParams();
  else
    NumParams = MD->param_size();

  bool anyTypeChanged = false;
  for (unsigned I = 0; I != NumParams; ++I) {
    ParmVarDecl *Param;
    if (FD)
      Param = FD->getParamDecl(I);
    else
      Param = 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;
  }

  // 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()));
    }
  }

  // Handle common entity information.
  ProcessAPINotes(S, D, static_cast<const api_notes::CommonEntityInfo &>(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 ObjCDesignatedInitializerAttr::CreateImplicit(S.Context);
    });
  }

  // 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 extensibility = info.EnumExtensibility) {
    using api_notes::EnumExtensibilityKind;
    bool shouldAddAttribute = (*extensibility != EnumExtensibilityKind::None);
    handleAPINotedAttribute<EnumExtensibilityAttr>(S, D, shouldAddAttribute,
                                                   metadata, [&] {
      EnumExtensibilityAttr::Kind kind;
      switch (extensibility.getValue()) {
      case EnumExtensibilityKind::None:
        llvm_unreachable("remove only");
      case EnumExtensibilityKind::Open:
        kind = EnumExtensibilityAttr::Open;
        break;
      case EnumExtensibilityKind::Closed:
        kind = EnumExtensibilityAttr::Closed;
        break;
      }
      return EnumExtensibilityAttr::CreateImplicit(S.Context, kind);
    });
  }

  if (auto flagEnum = info.isFlagEnum()) {
    handleAPINotedAttribute<FlagEnumAttr>(S, D, flagEnum.getValue(), metadata,
                                          [&] {
      return FlagEnumAttr::CreateImplicit(S.Context);
    });
  }

  // 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::SwiftWrapperKind;

  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;
        }
        return SwiftNewtypeAttr::CreateImplicit(
                 S.Context,
                 SwiftNewtypeAttr::GNU_swift_wrapper,
                 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::ObjCContextInfo &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::ObjCContextInfo &info,
                            VersionedInfoMetadata metadata) {
  if (auto asNonGeneric = info.getSwiftImportAsNonGeneric()) {
    handleAPINotedAttribute<SwiftImportAsNonGenericAttr>(S, D, *asNonGeneric,
                                                         metadata, [&] {
      return SwiftImportAsNonGenericAttr::CreateImplicit(S.Context);
    });
  }

    if (auto objcMembers = info.getSwiftObjCMembers()) {
    handleAPINotedAttribute<SwiftObjCMembersAttr>(S, D, *objcMembers,
                                                         metadata, [&] {
      return SwiftObjCMembersAttr::CreateImplicit(S.Context);
    });
  }

  // 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 
/// SwiftVersionedAttr.
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, IsNotActive,
                                            IsReplacement);
  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) {

  maybeAttachUnversionedSwiftName(S, D, Info);

  unsigned Selected = Info.getSelected().getValueOr(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 : IsNotActive;
    auto Replacement = IsNotReplacement;
    if (Active == IsNotActive && Version.empty()) {
      Replacement = IsReplacement;
      Version = Info[Selected].first;
    }
    ProcessAPINotes(S, D, InfoSlice, VersionedInfoMetadata(Version, Active,
                                                           Replacement));
  }
}

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

  // Globals.
  if (D->getDeclContext()->isFileContext()) {
    // Global variables.
    if (auto VD = dyn_cast<VarDecl>(D)) {
      for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
        auto Info = Reader->lookupGlobalVariable(VD->getName());
        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());
          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)) {
      for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
        auto Info = Reader->lookupTag(Tag->getName());
        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());
        ProcessVersionedAPINotes(*this, Typedef, Info);
      }

      return;
    }

    return;
  }

  // Enumerators.
  if (D->getDeclContext()->getRedeclContext()->isFileContext()) {
    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>(D->getDeclContext())) {
    // Location function that looks up an Objective-C context.
    auto GetContext = [&](api_notes::APINotesReader *Reader)
                        -> Optional<api_notes::ContextID> {
      if (auto Protocol = dyn_cast<ObjCProtocolDecl>(ObjCContainer)) {
        if (auto Found = Reader->lookupObjCProtocolID(Protocol->getName()))
          return *Found;

        return None;
      }

      if (auto Impl = dyn_cast<ObjCCategoryImplDecl>(ObjCContainer)) {
        if (auto Cat = Impl->getCategoryDecl())
          ObjCContainer = Cat;
        else
          return None;
      }

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

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

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

        return None;

      }

      return None;
    };

    // 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.NumPieces = 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() &
               ObjCPropertyDecl::OBJC_PR_class) == 0;
          auto Info = Reader->lookupObjCProperty(*Context, Property->getName(),
                                                 isInstanceProperty);
          ProcessVersionedAPINotes(*this, Property, Info);
        }
      }

      return;
    }

    return;
  }
}
