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