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