brintos

brintos / llvm-project-archived public Read only

0
0
Text · 45.5 KiB · 0d8d0fa Raw
1227 lines · cpp
1//===--- SemaAPINotes.cpp - API Notes Handling ----------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9//  This file implements the mapping from API notes to declaration attributes.10//11//===----------------------------------------------------------------------===//12 13#include "TypeLocBuilder.h"14#include "clang/APINotes/APINotesReader.h"15#include "clang/APINotes/Types.h"16#include "clang/AST/Decl.h"17#include "clang/AST/DeclCXX.h"18#include "clang/AST/DeclObjC.h"19#include "clang/AST/TypeLoc.h"20#include "clang/Analysis/Analyses/LifetimeSafety/LifetimeAnnotations.h"21#include "clang/Basic/SourceLocation.h"22#include "clang/Lex/Lexer.h"23#include "clang/Sema/SemaObjC.h"24#include "clang/Sema/SemaSwift.h"25#include <stack>26 27using namespace clang;28 29namespace {30enum class IsActive_t : bool { Inactive, Active };31enum class IsSubstitution_t : bool { Original, Replacement };32 33struct VersionedInfoMetadata {34  /// An empty version refers to unversioned metadata.35  VersionTuple Version;36  unsigned IsActive : 1;37  unsigned IsReplacement : 1;38 39  VersionedInfoMetadata(VersionTuple Version, IsActive_t Active,40                        IsSubstitution_t Replacement)41      : Version(Version), IsActive(Active == IsActive_t::Active),42        IsReplacement(Replacement == IsSubstitution_t::Replacement) {}43};44} // end anonymous namespace45 46/// Determine whether this is a multi-level pointer type.47static bool isIndirectPointerType(QualType Type) {48  QualType Pointee = Type->getPointeeType();49  if (Pointee.isNull())50    return false;51 52  return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() ||53         Pointee->isMemberPointerType();54}55 56static void applyAPINotesType(Sema &S, Decl *decl, StringRef typeString,57                              VersionedInfoMetadata metadata) {58  if (typeString.empty())59 60    return;61 62  // Version-independent APINotes add "type" annotations63  // with a versioned attribute for the client to select and apply.64  if (S.captureSwiftVersionIndependentAPINotes()) {65    auto *typeAttr = SwiftTypeAttr::CreateImplicit(S.Context, typeString);66    auto *versioned = SwiftVersionedAdditionAttr::CreateImplicit(67        S.Context, metadata.Version, typeAttr, metadata.IsReplacement);68    decl->addAttr(versioned);69  } else {70    if (!metadata.IsActive)71      return;72    S.ApplyAPINotesType(decl, typeString);73  }74}75 76/// Apply nullability to the given declaration.77static void applyNullability(Sema &S, Decl *decl, NullabilityKind nullability,78                             VersionedInfoMetadata metadata) {79  // Version-independent APINotes add "nullability" annotations80  // with a versioned attribute for the client to select and apply.81  if (S.captureSwiftVersionIndependentAPINotes()) {82    SwiftNullabilityAttr::Kind attrNullabilityKind;83    switch (nullability) {84    case NullabilityKind::NonNull:85      attrNullabilityKind = SwiftNullabilityAttr::Kind::NonNull;86      break;87    case NullabilityKind::Nullable:88      attrNullabilityKind = SwiftNullabilityAttr::Kind::Nullable;89      break;90    case NullabilityKind::Unspecified:91      attrNullabilityKind = SwiftNullabilityAttr::Kind::Unspecified;92      break;93    case NullabilityKind::NullableResult:94      attrNullabilityKind = SwiftNullabilityAttr::Kind::NullableResult;95      break;96    }97    auto *nullabilityAttr =98        SwiftNullabilityAttr::CreateImplicit(S.Context, attrNullabilityKind);99    auto *versioned = SwiftVersionedAdditionAttr::CreateImplicit(100        S.Context, metadata.Version, nullabilityAttr, metadata.IsReplacement);101    decl->addAttr(versioned);102    return;103  } else {104    if (!metadata.IsActive)105      return;106 107    S.ApplyNullability(decl, nullability);108  }109}110 111/// Copy a string into ASTContext-allocated memory.112static StringRef ASTAllocateString(ASTContext &Ctx, StringRef String) {113  void *mem = Ctx.Allocate(String.size(), alignof(char *));114  memcpy(mem, String.data(), String.size());115  return StringRef(static_cast<char *>(mem), String.size());116}117 118static AttributeCommonInfo getPlaceholderAttrInfo() {119  return AttributeCommonInfo(SourceRange(),120                             AttributeCommonInfo::UnknownAttribute,121                             {AttributeCommonInfo::AS_GNU,122                              /*Spelling*/ 0, /*IsAlignas*/ false,123                              /*IsRegularKeywordAttribute*/ false});124}125 126namespace {127template <typename A> struct AttrKindFor {};128 129#define ATTR(X)                                                                \130  template <> struct AttrKindFor<X##Attr> {                                    \131    static const attr::Kind value = attr::X;                                   \132  };133#include "clang/Basic/AttrList.inc"134 135/// Handle an attribute introduced by API notes.136///137/// \param IsAddition Whether we should add a new attribute138/// (otherwise, we might remove an existing attribute).139/// \param CreateAttr Create the new attribute to be added.140template <typename A>141void handleAPINotedAttribute(142    Sema &S, Decl *D, bool IsAddition, VersionedInfoMetadata Metadata,143    llvm::function_ref<A *()> CreateAttr,144    llvm::function_ref<Decl::attr_iterator(const Decl *)> GetExistingAttr) {145  if (Metadata.IsActive) {146    auto Existing = GetExistingAttr(D);147    if (Existing != D->attr_end()) {148      // Remove the existing attribute, and treat it as a superseded149      // non-versioned attribute.150      auto *Versioned = SwiftVersionedAdditionAttr::CreateImplicit(151          S.Context, Metadata.Version, *Existing, /*IsReplacedByActive*/ true);152 153      D->getAttrs().erase(Existing);154      D->addAttr(Versioned);155    }156 157    // If we're supposed to add a new attribute, do so.158    if (IsAddition) {159      if (auto Attr = CreateAttr())160        D->addAttr(Attr);161    }162 163    return;164  }165  if (IsAddition) {166    if (auto Attr = CreateAttr()) {167      auto *Versioned = SwiftVersionedAdditionAttr::CreateImplicit(168          S.Context, Metadata.Version, Attr,169          /*IsReplacedByActive*/ Metadata.IsReplacement);170      D->addAttr(Versioned);171    }172  } else {173    // FIXME: This isn't preserving enough information for things like174    // availability, where we're trying to remove a /specific/ kind of175    // attribute.176    auto *Versioned = SwiftVersionedRemovalAttr::CreateImplicit(177        S.Context, Metadata.Version, AttrKindFor<A>::value,178        /*IsReplacedByActive*/ Metadata.IsReplacement);179    D->addAttr(Versioned);180  }181}182 183template <typename A>184void handleAPINotedAttribute(Sema &S, Decl *D, bool ShouldAddAttribute,185                             VersionedInfoMetadata Metadata,186                             llvm::function_ref<A *()> CreateAttr) {187  handleAPINotedAttribute<A>(188      S, D, ShouldAddAttribute, Metadata, CreateAttr, [](const Decl *D) {189        return llvm::find_if(D->attrs(),190                             [](const Attr *Next) { return isa<A>(Next); });191      });192}193} // namespace194 195template <typename A>196static void handleAPINotedRetainCountAttribute(Sema &S, Decl *D,197                                               bool ShouldAddAttribute,198                                               VersionedInfoMetadata Metadata) {199  // The template argument has a default to make the "removal" case more200  // concise; it doesn't matter /which/ attribute is being removed.201  handleAPINotedAttribute<A>(202      S, D, ShouldAddAttribute, Metadata,203      [&] { return new (S.Context) A(S.Context, getPlaceholderAttrInfo()); },204      [](const Decl *D) -> Decl::attr_iterator {205        return llvm::find_if(D->attrs(), [](const Attr *Next) -> bool {206          return isa<CFReturnsRetainedAttr>(Next) ||207                 isa<CFReturnsNotRetainedAttr>(Next) ||208                 isa<NSReturnsRetainedAttr>(Next) ||209                 isa<NSReturnsNotRetainedAttr>(Next) ||210                 isa<CFAuditedTransferAttr>(Next);211        });212      });213}214 215static void handleAPINotedRetainCountConvention(216    Sema &S, Decl *D, VersionedInfoMetadata Metadata,217    std::optional<api_notes::RetainCountConventionKind> Convention) {218  if (!Convention)219    return;220  switch (*Convention) {221  case api_notes::RetainCountConventionKind::None:222    if (isa<FunctionDecl>(D)) {223      handleAPINotedRetainCountAttribute<CFUnknownTransferAttr>(224          S, D, /*shouldAddAttribute*/ true, Metadata);225    } else {226      handleAPINotedRetainCountAttribute<CFReturnsRetainedAttr>(227          S, D, /*shouldAddAttribute*/ false, Metadata);228    }229    break;230  case api_notes::RetainCountConventionKind::CFReturnsRetained:231    handleAPINotedRetainCountAttribute<CFReturnsRetainedAttr>(232        S, D, /*shouldAddAttribute*/ true, Metadata);233    break;234  case api_notes::RetainCountConventionKind::CFReturnsNotRetained:235    handleAPINotedRetainCountAttribute<CFReturnsNotRetainedAttr>(236        S, D, /*shouldAddAttribute*/ true, Metadata);237    break;238  case api_notes::RetainCountConventionKind::NSReturnsRetained:239    handleAPINotedRetainCountAttribute<NSReturnsRetainedAttr>(240        S, D, /*shouldAddAttribute*/ true, Metadata);241    break;242  case api_notes::RetainCountConventionKind::NSReturnsNotRetained:243    handleAPINotedRetainCountAttribute<NSReturnsNotRetainedAttr>(244        S, D, /*shouldAddAttribute*/ true, Metadata);245    break;246  }247}248 249static void ProcessAPINotes(Sema &S, Decl *D,250                            const api_notes::CommonEntityInfo &Info,251                            VersionedInfoMetadata Metadata) {252  // Availability253  if (Info.Unavailable) {254    handleAPINotedAttribute<UnavailableAttr>(S, D, true, Metadata, [&] {255      return new (S.Context)256          UnavailableAttr(S.Context, getPlaceholderAttrInfo(),257                          ASTAllocateString(S.Context, Info.UnavailableMsg));258    });259  }260 261  if (Info.UnavailableInSwift) {262    handleAPINotedAttribute<AvailabilityAttr>(263        S, D, true, Metadata,264        [&] {265          return new (S.Context) AvailabilityAttr(266              S.Context, getPlaceholderAttrInfo(),267              &S.Context.Idents.get("swift"), VersionTuple(), VersionTuple(),268              VersionTuple(),269              /*Unavailable=*/true,270              ASTAllocateString(S.Context, Info.UnavailableMsg),271              /*Strict=*/false,272              /*Replacement=*/StringRef(),273              /*Priority=*/Sema::AP_Explicit,274              /*Environment=*/nullptr);275        },276        [](const Decl *D) {277          return llvm::find_if(D->attrs(), [](const Attr *next) -> bool {278            if (const auto *AA = dyn_cast<AvailabilityAttr>(next))279              if (const auto *II = AA->getPlatform())280                return II->isStr("swift");281            return false;282          });283        });284  }285 286  // swift_private287  if (auto SwiftPrivate = Info.isSwiftPrivate()) {288    handleAPINotedAttribute<SwiftPrivateAttr>(289        S, D, *SwiftPrivate, Metadata, [&] {290          return new (S.Context)291              SwiftPrivateAttr(S.Context, getPlaceholderAttrInfo());292        });293  }294 295  // swift_safety296  if (auto SafetyKind = Info.getSwiftSafety()) {297    bool Addition = *SafetyKind != api_notes::SwiftSafetyKind::Unspecified;298    handleAPINotedAttribute<SwiftAttrAttr>(299        S, D, Addition, Metadata,300        [&] {301          return SwiftAttrAttr::Create(302              S.Context, *SafetyKind == api_notes::SwiftSafetyKind::Safe303                             ? "safe"304                             : "unsafe");305        },306        [](const Decl *D) {307          return llvm::find_if(D->attrs(), [](const Attr *attr) {308            if (const auto *swiftAttr = dyn_cast<SwiftAttrAttr>(attr)) {309              if (swiftAttr->getAttribute() == "safe" ||310                  swiftAttr->getAttribute() == "unsafe")311                return true;312            }313            return false;314          });315        });316  }317 318  // swift_name319  if (!Info.SwiftName.empty()) {320    handleAPINotedAttribute<SwiftNameAttr>(321        S, D, true, Metadata, [&]() -> SwiftNameAttr * {322          AttributeFactory AF{};323          AttributePool AP{AF};324          auto &C = S.getASTContext();325          ParsedAttr *SNA = AP.create(326              &C.Idents.get("swift_name"), SourceRange(), AttributeScopeInfo(),327              nullptr, nullptr, nullptr, ParsedAttr::Form::GNU());328 329          if (!S.Swift().DiagnoseName(D, Info.SwiftName, D->getLocation(), *SNA,330                                      /*IsAsync=*/false))331            return nullptr;332 333          return new (S.Context)334              SwiftNameAttr(S.Context, getPlaceholderAttrInfo(),335                            ASTAllocateString(S.Context, Info.SwiftName));336        });337  }338}339 340static void ProcessAPINotes(Sema &S, Decl *D,341                            const api_notes::CommonTypeInfo &Info,342                            VersionedInfoMetadata Metadata) {343  // swift_bridge344  if (auto SwiftBridge = Info.getSwiftBridge()) {345    handleAPINotedAttribute<SwiftBridgeAttr>(346        S, D, !SwiftBridge->empty(), Metadata, [&] {347          return new (S.Context)348              SwiftBridgeAttr(S.Context, getPlaceholderAttrInfo(),349                              ASTAllocateString(S.Context, *SwiftBridge));350        });351  }352 353  // ns_error_domain354  if (auto NSErrorDomain = Info.getNSErrorDomain()) {355    handleAPINotedAttribute<NSErrorDomainAttr>(356        S, D, !NSErrorDomain->empty(), Metadata, [&] {357          return new (S.Context)358              NSErrorDomainAttr(S.Context, getPlaceholderAttrInfo(),359                                &S.Context.Idents.get(*NSErrorDomain));360        });361  }362 363  if (auto ConformsTo = Info.getSwiftConformance())364    D->addAttr(365        SwiftAttrAttr::Create(S.Context, "conforms_to:" + ConformsTo.value()));366 367  ProcessAPINotes(S, D, static_cast<const api_notes::CommonEntityInfo &>(Info),368                  Metadata);369}370 371/// Check that the replacement type provided by API notes is reasonable.372///373/// This is a very weak form of ABI check.374static bool checkAPINotesReplacementType(Sema &S, SourceLocation Loc,375                                         QualType OrigType,376                                         QualType ReplacementType) {377  if (S.Context.getTypeSize(OrigType) !=378      S.Context.getTypeSize(ReplacementType)) {379    S.Diag(Loc, diag::err_incompatible_replacement_type)380        << ReplacementType << OrigType;381    return true;382  }383 384  return false;385}386 387void Sema::ApplyAPINotesType(Decl *D, StringRef TypeString) {388  if (!TypeString.empty() && ParseTypeFromStringCallback) {389    auto ParsedType = ParseTypeFromStringCallback(TypeString, "<API Notes>",390                                                  D->getLocation());391    if (ParsedType.isUsable()) {392      QualType Type = Sema::GetTypeFromParser(ParsedType.get());393      auto TypeInfo = Context.getTrivialTypeSourceInfo(Type, D->getLocation());394      if (auto Var = dyn_cast<VarDecl>(D)) {395        // Make adjustments to parameter types.396        if (isa<ParmVarDecl>(Var)) {397          Type = ObjC().AdjustParameterTypeForObjCAutoRefCount(398              Type, D->getLocation(), TypeInfo);399          Type = Context.getAdjustedParameterType(Type);400        }401 402        if (!checkAPINotesReplacementType(*this, Var->getLocation(),403                                          Var->getType(), Type)) {404          Var->setType(Type);405          Var->setTypeSourceInfo(TypeInfo);406        }407      } else if (auto property = dyn_cast<ObjCPropertyDecl>(D)) {408        if (!checkAPINotesReplacementType(*this, property->getLocation(),409                                          property->getType(), Type)) {410          property->setType(Type, TypeInfo);411        }412      } else {413        llvm_unreachable("API notes allowed a type on an unknown declaration");414      }415    }416  }417}418 419void Sema::ApplyNullability(Decl *D, NullabilityKind Nullability) {420  auto GetModified =421      [&](class Decl *D, QualType QT,422          NullabilityKind Nullability) -> std::optional<QualType> {423    QualType Original = QT;424    CheckImplicitNullabilityTypeSpecifier(QT, Nullability, D->getLocation(),425                                          isa<ParmVarDecl>(D),426                                          /*OverrideExisting=*/true);427    return (QT.getTypePtr() != Original.getTypePtr()) ? std::optional(QT)428                                                      : std::nullopt;429  };430 431  if (auto Function = dyn_cast<FunctionDecl>(D)) {432    if (auto Modified =433            GetModified(D, Function->getReturnType(), Nullability)) {434      const FunctionType *FnType = Function->getType()->castAs<FunctionType>();435      if (const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(FnType))436        Function->setType(Context.getFunctionType(437            *Modified, proto->getParamTypes(), proto->getExtProtoInfo()));438      else439        Function->setType(440            Context.getFunctionNoProtoType(*Modified, FnType->getExtInfo()));441    }442  } else if (auto Method = dyn_cast<ObjCMethodDecl>(D)) {443    if (auto Modified = GetModified(D, Method->getReturnType(), Nullability)) {444      Method->setReturnType(*Modified);445 446      // Make it a context-sensitive keyword if we can.447      if (!isIndirectPointerType(*Modified))448        Method->setObjCDeclQualifier(Decl::ObjCDeclQualifier(449            Method->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));450    }451  } else if (auto Value = dyn_cast<ValueDecl>(D)) {452    if (auto Modified = GetModified(D, Value->getType(), Nullability)) {453      Value->setType(*Modified);454 455      // Make it a context-sensitive keyword if we can.456      if (auto Parm = dyn_cast<ParmVarDecl>(D)) {457        if (Parm->isObjCMethodParameter() && !isIndirectPointerType(*Modified))458          Parm->setObjCDeclQualifier(Decl::ObjCDeclQualifier(459              Parm->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));460      }461    }462  } else if (auto Property = dyn_cast<ObjCPropertyDecl>(D)) {463    if (auto Modified = GetModified(D, Property->getType(), Nullability)) {464      Property->setType(*Modified, Property->getTypeSourceInfo());465 466      // Make it a property attribute if we can.467      if (!isIndirectPointerType(*Modified))468        Property->setPropertyAttributes(469            ObjCPropertyAttribute::kind_null_resettable);470    }471  }472}473 474/// Process API notes for a variable or property.475static void ProcessAPINotes(Sema &S, Decl *D,476                            const api_notes::VariableInfo &Info,477                            VersionedInfoMetadata Metadata) {478  // Type override.479  applyAPINotesType(S, D, Info.getType(), Metadata);480 481  // Nullability.482  if (auto Nullability = Info.getNullability())483    applyNullability(S, D, *Nullability, Metadata);484 485  // Handle common entity information.486  ProcessAPINotes(S, D, static_cast<const api_notes::CommonEntityInfo &>(Info),487                  Metadata);488}489 490/// Process API notes for a parameter.491static void ProcessAPINotes(Sema &S, ParmVarDecl *D,492                            const api_notes::ParamInfo &Info,493                            VersionedInfoMetadata Metadata) {494  // noescape495  if (auto NoEscape = Info.isNoEscape())496    handleAPINotedAttribute<NoEscapeAttr>(S, D, *NoEscape, Metadata, [&] {497      return new (S.Context) NoEscapeAttr(S.Context, getPlaceholderAttrInfo());498    });499 500  if (auto Lifetimebound = Info.isLifetimebound())501    handleAPINotedAttribute<LifetimeBoundAttr>(502        S, D, *Lifetimebound, Metadata, [&] {503          return new (S.Context)504              LifetimeBoundAttr(S.Context, getPlaceholderAttrInfo());505        });506 507  // Retain count convention508  handleAPINotedRetainCountConvention(S, D, Metadata,509                                      Info.getRetainCountConvention());510 511  // Handle common entity information.512  ProcessAPINotes(S, D, static_cast<const api_notes::VariableInfo &>(Info),513                  Metadata);514}515 516/// Process API notes for a global variable.517static void ProcessAPINotes(Sema &S, VarDecl *D,518                            const api_notes::GlobalVariableInfo &Info,519                            VersionedInfoMetadata metadata) {520  // Handle common entity information.521  ProcessAPINotes(S, D, static_cast<const api_notes::VariableInfo &>(Info),522                  metadata);523}524 525/// Process API notes for a C field.526static void ProcessAPINotes(Sema &S, FieldDecl *D,527                            const api_notes::FieldInfo &Info,528                            VersionedInfoMetadata metadata) {529  // Handle common entity information.530  ProcessAPINotes(S, D, static_cast<const api_notes::VariableInfo &>(Info),531                  metadata);532}533 534/// Process API notes for an Objective-C property.535static void ProcessAPINotes(Sema &S, ObjCPropertyDecl *D,536                            const api_notes::ObjCPropertyInfo &Info,537                            VersionedInfoMetadata Metadata) {538  // Handle common entity information.539  ProcessAPINotes(S, D, static_cast<const api_notes::VariableInfo &>(Info),540                  Metadata);541 542  if (auto AsAccessors = Info.getSwiftImportAsAccessors()) {543    handleAPINotedAttribute<SwiftImportPropertyAsAccessorsAttr>(544        S, D, *AsAccessors, Metadata, [&] {545          return new (S.Context) SwiftImportPropertyAsAccessorsAttr(546              S.Context, getPlaceholderAttrInfo());547        });548  }549}550 551namespace {552typedef llvm::PointerUnion<FunctionDecl *, ObjCMethodDecl *> FunctionOrMethod;553}554 555/// Process API notes for a function or method.556static void ProcessAPINotes(Sema &S, FunctionOrMethod AnyFunc,557                            const api_notes::FunctionInfo &Info,558                            VersionedInfoMetadata Metadata) {559  // Find the declaration itself.560  FunctionDecl *FD = dyn_cast<FunctionDecl *>(AnyFunc);561  Decl *D = FD;562  ObjCMethodDecl *MD = nullptr;563  if (!D) {564    MD = cast<ObjCMethodDecl *>(AnyFunc);565    D = MD;566  }567 568  assert((FD || MD) && "Expecting Function or ObjCMethod");569 570  // Nullability of return type.571  if (Info.NullabilityAudited)572    applyNullability(S, D, Info.getReturnTypeInfo(), Metadata);573 574  // Parameters.575  unsigned NumParams = FD ? FD->getNumParams() : MD->param_size();576 577  bool AnyTypeChanged = false;578  for (unsigned I = 0; I != NumParams; ++I) {579    ParmVarDecl *Param = FD ? FD->getParamDecl(I) : MD->param_begin()[I];580    QualType ParamTypeBefore = Param->getType();581 582    if (I < Info.Params.size())583      ProcessAPINotes(S, Param, Info.Params[I], Metadata);584 585    // Nullability.586    if (Info.NullabilityAudited)587      applyNullability(S, Param, Info.getParamTypeInfo(I), Metadata);588 589    if (ParamTypeBefore.getAsOpaquePtr() != Param->getType().getAsOpaquePtr())590      AnyTypeChanged = true;591  }592 593  // returns_(un)retained594  if (!Info.SwiftReturnOwnership.empty())595    D->addAttr(SwiftAttrAttr::Create(S.Context,596                                     "returns_" + Info.SwiftReturnOwnership));597 598  // Result type override.599  QualType OverriddenResultType;600  if (Metadata.IsActive && !Info.ResultType.empty() &&601      S.ParseTypeFromStringCallback) {602    auto ParsedType = S.ParseTypeFromStringCallback(603        Info.ResultType, "<API Notes>", D->getLocation());604    if (ParsedType.isUsable()) {605      QualType ResultType = Sema::GetTypeFromParser(ParsedType.get());606 607      if (MD) {608        if (!checkAPINotesReplacementType(S, D->getLocation(),609                                          MD->getReturnType(), ResultType)) {610          auto ResultTypeInfo =611              S.Context.getTrivialTypeSourceInfo(ResultType, D->getLocation());612          MD->setReturnType(ResultType);613          MD->setReturnTypeSourceInfo(ResultTypeInfo);614        }615      } else if (!checkAPINotesReplacementType(616                     S, FD->getLocation(), FD->getReturnType(), ResultType)) {617        OverriddenResultType = ResultType;618        AnyTypeChanged = true;619      }620    }621  }622 623  // If the result type or any of the parameter types changed for a function624  // declaration, we have to rebuild the type.625  if (FD && AnyTypeChanged) {626    if (const auto *fnProtoType = FD->getType()->getAs<FunctionProtoType>()) {627      if (OverriddenResultType.isNull())628        OverriddenResultType = fnProtoType->getReturnType();629 630      SmallVector<QualType, 4> ParamTypes;631      for (auto Param : FD->parameters())632        ParamTypes.push_back(Param->getType());633 634      FD->setType(S.Context.getFunctionType(OverriddenResultType, ParamTypes,635                                            fnProtoType->getExtProtoInfo()));636    } else if (!OverriddenResultType.isNull()) {637      const auto *FnNoProtoType = FD->getType()->castAs<FunctionNoProtoType>();638      FD->setType(S.Context.getFunctionNoProtoType(639          OverriddenResultType, FnNoProtoType->getExtInfo()));640    }641  }642 643  // Retain count convention644  handleAPINotedRetainCountConvention(S, D, Metadata,645                                      Info.getRetainCountConvention());646 647  // Handle common entity information.648  ProcessAPINotes(S, D, static_cast<const api_notes::CommonEntityInfo &>(Info),649                  Metadata);650}651 652/// Process API notes for a C++ method.653static void ProcessAPINotes(Sema &S, CXXMethodDecl *Method,654                            const api_notes::CXXMethodInfo &Info,655                            VersionedInfoMetadata Metadata) {656  if (Info.This && Info.This->isLifetimebound() &&657      !lifetimes::implicitObjectParamIsLifetimeBound(Method)) {658    auto MethodType = Method->getType();659    auto *attr = ::new (S.Context)660        LifetimeBoundAttr(S.Context, getPlaceholderAttrInfo());661    QualType AttributedType =662        S.Context.getAttributedType(attr, MethodType, MethodType);663    TypeLocBuilder TLB;664    TLB.pushFullCopy(Method->getTypeSourceInfo()->getTypeLoc());665    AttributedTypeLoc TyLoc = TLB.push<AttributedTypeLoc>(AttributedType);666    TyLoc.setAttr(attr);667    Method->setType(AttributedType);668    Method->setTypeSourceInfo(TLB.getTypeSourceInfo(S.Context, AttributedType));669  }670 671  ProcessAPINotes(S, (FunctionOrMethod)Method, Info, Metadata);672}673 674/// Process API notes for a global function.675static void ProcessAPINotes(Sema &S, FunctionDecl *D,676                            const api_notes::GlobalFunctionInfo &Info,677                            VersionedInfoMetadata Metadata) {678  // Handle common function information.679  ProcessAPINotes(S, FunctionOrMethod(D),680                  static_cast<const api_notes::FunctionInfo &>(Info), Metadata);681}682 683/// Process API notes for an enumerator.684static void ProcessAPINotes(Sema &S, EnumConstantDecl *D,685                            const api_notes::EnumConstantInfo &Info,686                            VersionedInfoMetadata Metadata) {687  // Handle common information.688  ProcessAPINotes(S, D, static_cast<const api_notes::CommonEntityInfo &>(Info),689                  Metadata);690}691 692/// Process API notes for an Objective-C method.693static void ProcessAPINotes(Sema &S, ObjCMethodDecl *D,694                            const api_notes::ObjCMethodInfo &Info,695                            VersionedInfoMetadata Metadata) {696  // Designated initializers.697  if (Info.DesignatedInit) {698    handleAPINotedAttribute<ObjCDesignatedInitializerAttr>(699        S, D, true, Metadata, [&] {700          if (ObjCInterfaceDecl *IFace = D->getClassInterface())701            IFace->setHasDesignatedInitializers();702 703          return new (S.Context) ObjCDesignatedInitializerAttr(704              S.Context, getPlaceholderAttrInfo());705        });706  }707 708  // Handle common function information.709  ProcessAPINotes(S, FunctionOrMethod(D),710                  static_cast<const api_notes::FunctionInfo &>(Info), Metadata);711}712 713/// Process API notes for a tag.714static void ProcessAPINotes(Sema &S, TagDecl *D, const api_notes::TagInfo &Info,715                            VersionedInfoMetadata Metadata) {716  if (auto ImportAs = Info.SwiftImportAs)717    D->addAttr(SwiftAttrAttr::Create(S.Context, "import_" + ImportAs.value()));718 719  if (auto RetainOp = Info.SwiftRetainOp)720    D->addAttr(SwiftAttrAttr::Create(S.Context, "retain:" + RetainOp.value()));721 722  if (auto ReleaseOp = Info.SwiftReleaseOp)723    D->addAttr(724        SwiftAttrAttr::Create(S.Context, "release:" + ReleaseOp.value()));725  if (auto DestroyOp = Info.SwiftDestroyOp)726    D->addAttr(727        SwiftAttrAttr::Create(S.Context, "destroy:" + DestroyOp.value()));728  if (auto DefaultOwnership = Info.SwiftDefaultOwnership)729    D->addAttr(SwiftAttrAttr::Create(730        S.Context, "returned_as_" + DefaultOwnership.value() + "_by_default"));731 732  if (auto Copyable = Info.isSwiftCopyable()) {733    if (!*Copyable)734      D->addAttr(SwiftAttrAttr::Create(S.Context, "~Copyable"));735  }736 737  if (auto Escapable = Info.isSwiftEscapable()) {738    D->addAttr(SwiftAttrAttr::Create(S.Context,739                                     *Escapable ? "Escapable" : "~Escapable"));740  }741 742  if (auto Extensibility = Info.EnumExtensibility) {743    using api_notes::EnumExtensibilityKind;744    bool ShouldAddAttribute = (*Extensibility != EnumExtensibilityKind::None);745    handleAPINotedAttribute<EnumExtensibilityAttr>(746        S, D, ShouldAddAttribute, Metadata, [&] {747          EnumExtensibilityAttr::Kind kind;748          switch (*Extensibility) {749          case EnumExtensibilityKind::None:750            llvm_unreachable("remove only");751          case EnumExtensibilityKind::Open:752            kind = EnumExtensibilityAttr::Open;753            break;754          case EnumExtensibilityKind::Closed:755            kind = EnumExtensibilityAttr::Closed;756            break;757          }758          return new (S.Context)759              EnumExtensibilityAttr(S.Context, getPlaceholderAttrInfo(), kind);760        });761  }762 763  if (auto FlagEnum = Info.isFlagEnum()) {764    handleAPINotedAttribute<FlagEnumAttr>(S, D, *FlagEnum, Metadata, [&] {765      return new (S.Context) FlagEnumAttr(S.Context, getPlaceholderAttrInfo());766    });767  }768 769  // Handle common type information.770  ProcessAPINotes(S, D, static_cast<const api_notes::CommonTypeInfo &>(Info),771                  Metadata);772}773 774/// Process API notes for a typedef.775static void ProcessAPINotes(Sema &S, TypedefNameDecl *D,776                            const api_notes::TypedefInfo &Info,777                            VersionedInfoMetadata Metadata) {778  // swift_wrapper779  using SwiftWrapperKind = api_notes::SwiftNewTypeKind;780 781  if (auto SwiftWrapper = Info.SwiftWrapper) {782    handleAPINotedAttribute<SwiftNewTypeAttr>(783        S, D, *SwiftWrapper != SwiftWrapperKind::None, Metadata, [&] {784          SwiftNewTypeAttr::NewtypeKind Kind;785          switch (*SwiftWrapper) {786          case SwiftWrapperKind::None:787            llvm_unreachable("Shouldn't build an attribute");788 789          case SwiftWrapperKind::Struct:790            Kind = SwiftNewTypeAttr::NK_Struct;791            break;792 793          case SwiftWrapperKind::Enum:794            Kind = SwiftNewTypeAttr::NK_Enum;795            break;796          }797          AttributeCommonInfo SyntaxInfo{798              SourceRange(),799              AttributeCommonInfo::AT_SwiftNewType,800              {AttributeCommonInfo::AS_GNU, SwiftNewTypeAttr::GNU_swift_wrapper,801               /*IsAlignas*/ false, /*IsRegularKeywordAttribute*/ false}};802          return new (S.Context) SwiftNewTypeAttr(S.Context, SyntaxInfo, Kind);803        });804  }805 806  // Handle common type information.807  ProcessAPINotes(S, D, static_cast<const api_notes::CommonTypeInfo &>(Info),808                  Metadata);809}810 811/// Process API notes for an Objective-C class or protocol.812static void ProcessAPINotes(Sema &S, ObjCContainerDecl *D,813                            const api_notes::ContextInfo &Info,814                            VersionedInfoMetadata Metadata) {815  // Handle common type information.816  ProcessAPINotes(S, D, static_cast<const api_notes::CommonTypeInfo &>(Info),817                  Metadata);818}819 820/// Process API notes for an Objective-C class.821static void ProcessAPINotes(Sema &S, ObjCInterfaceDecl *D,822                            const api_notes::ContextInfo &Info,823                            VersionedInfoMetadata Metadata) {824  if (auto AsNonGeneric = Info.getSwiftImportAsNonGeneric()) {825    handleAPINotedAttribute<SwiftImportAsNonGenericAttr>(826        S, D, *AsNonGeneric, Metadata, [&] {827          return new (S.Context)828              SwiftImportAsNonGenericAttr(S.Context, getPlaceholderAttrInfo());829        });830  }831 832  if (auto ObjcMembers = Info.getSwiftObjCMembers()) {833    handleAPINotedAttribute<SwiftObjCMembersAttr>(834        S, D, *ObjcMembers, Metadata, [&] {835          return new (S.Context)836              SwiftObjCMembersAttr(S.Context, getPlaceholderAttrInfo());837        });838  }839 840  // Handle information common to Objective-C classes and protocols.841  ProcessAPINotes(S, static_cast<clang::ObjCContainerDecl *>(D), Info,842                  Metadata);843}844 845/// If we're applying API notes with an active, non-default version, and the846/// versioned API notes have a SwiftName but the declaration normally wouldn't847/// have one, add a removal attribute to make it clear that the new SwiftName848/// attribute only applies to the active version of \p D, not to all versions.849///850/// This must be run \em before processing API notes for \p D, because otherwise851/// any existing SwiftName attribute will have been packaged up in a852/// SwiftVersionedAdditionAttr.853template <typename SpecificInfo>854static void maybeAttachUnversionedSwiftName(855    Sema &S, Decl *D,856    const api_notes::APINotesReader::VersionedInfo<SpecificInfo> Info) {857  if (D->hasAttr<SwiftNameAttr>())858    return;859  if (!Info.getSelected())860    return;861 862  // Is the active slice versioned, and does it set a Swift name?863  VersionTuple SelectedVersion;864  SpecificInfo SelectedInfoSlice;865  std::tie(SelectedVersion, SelectedInfoSlice) = Info[*Info.getSelected()];866  if (SelectedVersion.empty())867    return;868  if (SelectedInfoSlice.SwiftName.empty())869    return;870 871  // Does the unversioned slice /not/ set a Swift name?872  for (const auto &VersionAndInfoSlice : Info) {873    if (!VersionAndInfoSlice.first.empty())874      continue;875    if (!VersionAndInfoSlice.second.SwiftName.empty())876      return;877  }878 879  // Then explicitly call that out with a removal attribute.880  VersionedInfoMetadata DummyFutureMetadata(881      SelectedVersion, IsActive_t::Inactive, IsSubstitution_t::Replacement);882  handleAPINotedAttribute<SwiftNameAttr>(883      S, D, /*add*/ false, DummyFutureMetadata, []() -> SwiftNameAttr * {884        llvm_unreachable("should not try to add an attribute here");885      });886}887 888/// Processes all versions of versioned API notes.889///890/// Just dispatches to the various ProcessAPINotes functions in this file.891template <typename SpecificDecl, typename SpecificInfo>892static void ProcessVersionedAPINotes(893    Sema &S, SpecificDecl *D,894    const api_notes::APINotesReader::VersionedInfo<SpecificInfo> Info) {895 896  if (!S.captureSwiftVersionIndependentAPINotes())897    maybeAttachUnversionedSwiftName(S, D, Info);898 899  unsigned Selected = Info.getSelected().value_or(Info.size());900 901  VersionTuple Version;902  SpecificInfo InfoSlice;903  for (unsigned i = 0, e = Info.size(); i != e; ++i) {904    std::tie(Version, InfoSlice) = Info[i];905    auto Active = (i == Selected) ? IsActive_t::Active : IsActive_t::Inactive;906    auto Replacement = IsSubstitution_t::Original;907 908    // When collection all APINotes as version-independent,909    // capture all as inactive and defer to the client select the910    // right one.911    if (S.captureSwiftVersionIndependentAPINotes()) {912      Active = IsActive_t::Inactive;913      Replacement = IsSubstitution_t::Original;914    } else if (Active == IsActive_t::Inactive && Version.empty()) {915      Replacement = IsSubstitution_t::Replacement;916      Version = Info[Selected].first;917    }918 919    ProcessAPINotes(S, D, InfoSlice,920                    VersionedInfoMetadata(Version, Active, Replacement));921  }922}923 924static std::optional<api_notes::Context>925UnwindNamespaceContext(DeclContext *DC, api_notes::APINotesManager &APINotes) {926  if (auto NamespaceContext = dyn_cast<NamespaceDecl>(DC)) {927    for (auto Reader : APINotes.findAPINotes(NamespaceContext->getLocation())) {928      // Retrieve the context ID for the parent namespace of the decl.929      std::stack<NamespaceDecl *> NamespaceStack;930      {931        for (auto CurrentNamespace = NamespaceContext; CurrentNamespace;932             CurrentNamespace =933                 dyn_cast<NamespaceDecl>(CurrentNamespace->getParent())) {934          if (!CurrentNamespace->isInlineNamespace())935            NamespaceStack.push(CurrentNamespace);936        }937      }938      std::optional<api_notes::ContextID> NamespaceID;939      while (!NamespaceStack.empty()) {940        auto CurrentNamespace = NamespaceStack.top();941        NamespaceStack.pop();942        NamespaceID =943            Reader->lookupNamespaceID(CurrentNamespace->getName(), NamespaceID);944        if (!NamespaceID)945          return std::nullopt;946      }947      if (NamespaceID)948        return api_notes::Context(*NamespaceID,949                                  api_notes::ContextKind::Namespace);950    }951  }952  return std::nullopt;953}954 955static std::optional<api_notes::Context>956UnwindTagContext(TagDecl *DC, api_notes::APINotesManager &APINotes) {957  assert(DC && "tag context must not be null");958  for (auto Reader : APINotes.findAPINotes(DC->getLocation())) {959    // Retrieve the context ID for the parent tag of the decl.960    std::stack<TagDecl *> TagStack;961    {962      for (auto CurrentTag = DC; CurrentTag;963           CurrentTag = dyn_cast<TagDecl>(CurrentTag->getParent()))964        TagStack.push(CurrentTag);965    }966    assert(!TagStack.empty());967    std::optional<api_notes::Context> Ctx =968        UnwindNamespaceContext(TagStack.top()->getDeclContext(), APINotes);969    while (!TagStack.empty()) {970      auto CurrentTag = TagStack.top();971      TagStack.pop();972      auto CtxID = Reader->lookupTagID(CurrentTag->getName(), Ctx);973      if (!CtxID)974        return std::nullopt;975      Ctx = api_notes::Context(*CtxID, api_notes::ContextKind::Tag);976    }977    return Ctx;978  }979  return std::nullopt;980}981 982/// Process API notes that are associated with this declaration, mapping them983/// to attributes as appropriate.984void Sema::ProcessAPINotes(Decl *D) {985  if (!D)986    return;987 988  auto *DC = D->getDeclContext();989  // Globals.990  if (DC->isFileContext() || DC->isNamespace() || DC->isExternCContext() ||991      DC->isExternCXXContext()) {992    std::optional<api_notes::Context> APINotesContext =993        UnwindNamespaceContext(DC, APINotes);994    // Global variables.995    if (auto VD = dyn_cast<VarDecl>(D)) {996      for (auto Reader : APINotes.findAPINotes(D->getLocation())) {997        auto Info =998            Reader->lookupGlobalVariable(VD->getName(), APINotesContext);999        ProcessVersionedAPINotes(*this, VD, Info);1000      }1001 1002      return;1003    }1004 1005    // Global functions.1006    if (auto FD = dyn_cast<FunctionDecl>(D)) {1007      if (FD->getDeclName().isIdentifier()) {1008        for (auto Reader : APINotes.findAPINotes(D->getLocation())) {1009          auto Info =1010              Reader->lookupGlobalFunction(FD->getName(), APINotesContext);1011          ProcessVersionedAPINotes(*this, FD, Info);1012        }1013      }1014 1015      return;1016    }1017 1018    // Objective-C classes.1019    if (auto Class = dyn_cast<ObjCInterfaceDecl>(D)) {1020      for (auto Reader : APINotes.findAPINotes(D->getLocation())) {1021        auto Info = Reader->lookupObjCClassInfo(Class->getName());1022        ProcessVersionedAPINotes(*this, Class, Info);1023      }1024 1025      return;1026    }1027 1028    // Objective-C protocols.1029    if (auto Protocol = dyn_cast<ObjCProtocolDecl>(D)) {1030      for (auto Reader : APINotes.findAPINotes(D->getLocation())) {1031        auto Info = Reader->lookupObjCProtocolInfo(Protocol->getName());1032        ProcessVersionedAPINotes(*this, Protocol, Info);1033      }1034 1035      return;1036    }1037 1038    // Tags1039    if (auto Tag = dyn_cast<TagDecl>(D)) {1040      // Determine the name of the entity to search for. If this is an1041      // anonymous tag that gets its linked name from a typedef, look for the1042      // typedef name. This allows tag-specific information to be added1043      // to the declaration.1044      std::string LookupName;1045      if (auto typedefName = Tag->getTypedefNameForAnonDecl())1046        LookupName = typedefName->getName().str();1047      else1048        LookupName = Tag->getName().str();1049 1050      // Use the source location to discern if this Tag is an OPTIONS macro.1051      // For now we would like to limit this trick of looking up the APINote tag1052      // using the EnumDecl's QualType in the case where the enum is anonymous.1053      // This is only being used to support APINotes lookup for C++1054      // NS/CF_OPTIONS when C++-Interop is enabled.1055      std::string MacroName =1056          LookupName.empty() && Tag->getOuterLocStart().isMacroID()1057              ? clang::Lexer::getImmediateMacroName(1058                    Tag->getOuterLocStart(),1059                    Tag->getASTContext().getSourceManager(), LangOpts)1060                    .str()1061              : "";1062 1063      if (LookupName.empty() && isa<clang::EnumDecl>(Tag) &&1064          (MacroName == "CF_OPTIONS" || MacroName == "NS_OPTIONS" ||1065           MacroName == "OBJC_OPTIONS" || MacroName == "SWIFT_OPTIONS")) {1066 1067        clang::QualType T = llvm::cast<clang::EnumDecl>(Tag)->getIntegerType();1068        LookupName = clang::QualType::getAsString(1069            T.split(), getASTContext().getPrintingPolicy());1070      }1071 1072      for (auto Reader : APINotes.findAPINotes(D->getLocation())) {1073        if (auto ParentTag = dyn_cast<TagDecl>(Tag->getDeclContext()))1074          APINotesContext = UnwindTagContext(ParentTag, APINotes);1075        auto Info = Reader->lookupTag(LookupName, APINotesContext);1076        ProcessVersionedAPINotes(*this, Tag, Info);1077      }1078 1079      return;1080    }1081 1082    // Typedefs1083    if (auto Typedef = dyn_cast<TypedefNameDecl>(D)) {1084      for (auto Reader : APINotes.findAPINotes(D->getLocation())) {1085        auto Info = Reader->lookupTypedef(Typedef->getName(), APINotesContext);1086        ProcessVersionedAPINotes(*this, Typedef, Info);1087      }1088 1089      return;1090    }1091  }1092 1093  // Enumerators.1094  if (DC->getRedeclContext()->isFileContext() ||1095      DC->getRedeclContext()->isExternCContext()) {1096    if (auto EnumConstant = dyn_cast<EnumConstantDecl>(D)) {1097      for (auto Reader : APINotes.findAPINotes(D->getLocation())) {1098        auto Info = Reader->lookupEnumConstant(EnumConstant->getName());1099        ProcessVersionedAPINotes(*this, EnumConstant, Info);1100      }1101 1102      return;1103    }1104  }1105 1106  if (auto ObjCContainer = dyn_cast<ObjCContainerDecl>(DC)) {1107    // Location function that looks up an Objective-C context.1108    auto GetContext = [&](api_notes::APINotesReader *Reader)1109        -> std::optional<api_notes::ContextID> {1110      if (auto Protocol = dyn_cast<ObjCProtocolDecl>(ObjCContainer)) {1111        if (auto Found = Reader->lookupObjCProtocolID(Protocol->getName()))1112          return *Found;1113 1114        return std::nullopt;1115      }1116 1117      if (auto Impl = dyn_cast<ObjCCategoryImplDecl>(ObjCContainer)) {1118        if (auto Cat = Impl->getCategoryDecl())1119          ObjCContainer = Cat->getClassInterface();1120        else1121          return std::nullopt;1122      }1123 1124      if (auto Category = dyn_cast<ObjCCategoryDecl>(ObjCContainer)) {1125        if (Category->getClassInterface())1126          ObjCContainer = Category->getClassInterface();1127        else1128          return std::nullopt;1129      }1130 1131      if (auto Impl = dyn_cast<ObjCImplDecl>(ObjCContainer)) {1132        if (Impl->getClassInterface())1133          ObjCContainer = Impl->getClassInterface();1134        else1135          return std::nullopt;1136      }1137 1138      if (auto Class = dyn_cast<ObjCInterfaceDecl>(ObjCContainer)) {1139        if (auto Found = Reader->lookupObjCClassID(Class->getName()))1140          return *Found;1141 1142        return std::nullopt;1143      }1144 1145      return std::nullopt;1146    };1147 1148    // Objective-C methods.1149    if (auto Method = dyn_cast<ObjCMethodDecl>(D)) {1150      for (auto Reader : APINotes.findAPINotes(D->getLocation())) {1151        if (auto Context = GetContext(Reader)) {1152          // Map the selector.1153          Selector Sel = Method->getSelector();1154          SmallVector<StringRef, 2> SelPieces;1155          if (Sel.isUnarySelector()) {1156            SelPieces.push_back(Sel.getNameForSlot(0));1157          } else {1158            for (unsigned i = 0, n = Sel.getNumArgs(); i != n; ++i)1159              SelPieces.push_back(Sel.getNameForSlot(i));1160          }1161 1162          api_notes::ObjCSelectorRef SelectorRef;1163          SelectorRef.NumArgs = Sel.getNumArgs();1164          SelectorRef.Identifiers = SelPieces;1165 1166          auto Info = Reader->lookupObjCMethod(*Context, SelectorRef,1167                                               Method->isInstanceMethod());1168          ProcessVersionedAPINotes(*this, Method, Info);1169        }1170      }1171    }1172 1173    // Objective-C properties.1174    if (auto Property = dyn_cast<ObjCPropertyDecl>(D)) {1175      for (auto Reader : APINotes.findAPINotes(D->getLocation())) {1176        if (auto Context = GetContext(Reader)) {1177          bool isInstanceProperty =1178              (Property->getPropertyAttributesAsWritten() &1179               ObjCPropertyAttribute::kind_class) == 0;1180          auto Info = Reader->lookupObjCProperty(*Context, Property->getName(),1181                                                 isInstanceProperty);1182          ProcessVersionedAPINotes(*this, Property, Info);1183        }1184      }1185 1186      return;1187    }1188  }1189 1190  if (auto TagContext = dyn_cast<TagDecl>(DC)) {1191    if (auto CXXMethod = dyn_cast<CXXMethodDecl>(D)) {1192      if (!isa<CXXConstructorDecl>(CXXMethod) &&1193          !isa<CXXDestructorDecl>(CXXMethod) &&1194          !isa<CXXConversionDecl>(CXXMethod) &&1195          !CXXMethod->isOverloadedOperator()) {1196        for (auto Reader : APINotes.findAPINotes(D->getLocation())) {1197          if (auto Context = UnwindTagContext(TagContext, APINotes)) {1198            auto Info =1199                Reader->lookupCXXMethod(Context->id, CXXMethod->getName());1200            ProcessVersionedAPINotes(*this, CXXMethod, Info);1201          }1202        }1203      }1204    }1205 1206    if (auto Field = dyn_cast<FieldDecl>(D)) {1207      if (!Field->isUnnamedBitField() && !Field->isAnonymousStructOrUnion()) {1208        for (auto Reader : APINotes.findAPINotes(D->getLocation())) {1209          if (auto Context = UnwindTagContext(TagContext, APINotes)) {1210            auto Info = Reader->lookupField(Context->id, Field->getName());1211            ProcessVersionedAPINotes(*this, Field, Info);1212          }1213        }1214      }1215    }1216 1217    if (auto Tag = dyn_cast<TagDecl>(D)) {1218      for (auto Reader : APINotes.findAPINotes(D->getLocation())) {1219        if (auto Context = UnwindTagContext(TagContext, APINotes)) {1220          auto Info = Reader->lookupTag(Tag->getName(), Context);1221          ProcessVersionedAPINotes(*this, Tag, Info);1222        }1223      }1224    }1225  }1226}1227