xref: /llvm-project/clang/lib/Sema/SemaAPINotes.cpp (revision f09a6f632584c2b34f8f2d048a5420b040bb1005)
1440b1743SEgor Zhdan //===--- SemaAPINotes.cpp - API Notes Handling ----------------------------===//
2440b1743SEgor Zhdan //
3440b1743SEgor Zhdan // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4440b1743SEgor Zhdan // See https://llvm.org/LICENSE.txt for license information.
5440b1743SEgor Zhdan // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6440b1743SEgor Zhdan //
7440b1743SEgor Zhdan //===----------------------------------------------------------------------===//
8440b1743SEgor Zhdan //
9440b1743SEgor Zhdan //  This file implements the mapping from API notes to declaration attributes.
10440b1743SEgor Zhdan //
11440b1743SEgor Zhdan //===----------------------------------------------------------------------===//
12440b1743SEgor Zhdan 
134862febdSGábor Horváth #include "CheckExprLifetime.h"
145f4e3a3cSGábor Horváth #include "TypeLocBuilder.h"
15440b1743SEgor Zhdan #include "clang/APINotes/APINotesReader.h"
16440b1743SEgor Zhdan #include "clang/AST/Decl.h"
177ac78f13SGábor Horváth #include "clang/AST/DeclCXX.h"
18440b1743SEgor Zhdan #include "clang/AST/DeclObjC.h"
195f4e3a3cSGábor Horváth #include "clang/AST/TypeLoc.h"
20440b1743SEgor Zhdan #include "clang/Basic/SourceLocation.h"
21440b1743SEgor Zhdan #include "clang/Lex/Lexer.h"
2231a203faSVlad Serebrennikov #include "clang/Sema/SemaObjC.h"
236b755b0cSVlad Serebrennikov #include "clang/Sema/SemaSwift.h"
2448ef912eSNikita Popov #include <stack>
25440b1743SEgor Zhdan 
26440b1743SEgor Zhdan using namespace clang;
27440b1743SEgor Zhdan 
28440b1743SEgor Zhdan namespace {
29440b1743SEgor Zhdan enum class IsActive_t : bool { Inactive, Active };
30440b1743SEgor Zhdan enum class IsSubstitution_t : bool { Original, Replacement };
31440b1743SEgor Zhdan 
32440b1743SEgor Zhdan struct VersionedInfoMetadata {
33440b1743SEgor Zhdan   /// An empty version refers to unversioned metadata.
34440b1743SEgor Zhdan   VersionTuple Version;
35440b1743SEgor Zhdan   unsigned IsActive : 1;
36440b1743SEgor Zhdan   unsigned IsReplacement : 1;
37440b1743SEgor Zhdan 
38440b1743SEgor Zhdan   VersionedInfoMetadata(VersionTuple Version, IsActive_t Active,
39440b1743SEgor Zhdan                         IsSubstitution_t Replacement)
40440b1743SEgor Zhdan       : Version(Version), IsActive(Active == IsActive_t::Active),
41440b1743SEgor Zhdan         IsReplacement(Replacement == IsSubstitution_t::Replacement) {}
42440b1743SEgor Zhdan };
43440b1743SEgor Zhdan } // end anonymous namespace
44440b1743SEgor Zhdan 
45440b1743SEgor Zhdan /// Determine whether this is a multi-level pointer type.
46440b1743SEgor Zhdan static bool isIndirectPointerType(QualType Type) {
47440b1743SEgor Zhdan   QualType Pointee = Type->getPointeeType();
48440b1743SEgor Zhdan   if (Pointee.isNull())
49440b1743SEgor Zhdan     return false;
50440b1743SEgor Zhdan 
51440b1743SEgor Zhdan   return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() ||
52440b1743SEgor Zhdan          Pointee->isMemberPointerType();
53440b1743SEgor Zhdan }
54440b1743SEgor Zhdan 
55440b1743SEgor Zhdan /// Apply nullability to the given declaration.
56440b1743SEgor Zhdan static void applyNullability(Sema &S, Decl *D, NullabilityKind Nullability,
57440b1743SEgor Zhdan                              VersionedInfoMetadata Metadata) {
58440b1743SEgor Zhdan   if (!Metadata.IsActive)
59440b1743SEgor Zhdan     return;
60440b1743SEgor Zhdan 
61932949dbSEgor Zhdan   auto GetModified =
62932949dbSEgor Zhdan       [&](Decl *D, QualType QT,
63932949dbSEgor Zhdan           NullabilityKind Nullability) -> std::optional<QualType> {
64440b1743SEgor Zhdan     QualType Original = QT;
65440b1743SEgor Zhdan     S.CheckImplicitNullabilityTypeSpecifier(QT, Nullability, D->getLocation(),
66440b1743SEgor Zhdan                                             isa<ParmVarDecl>(D),
67440b1743SEgor Zhdan                                             /*OverrideExisting=*/true);
68932949dbSEgor Zhdan     return (QT.getTypePtr() != Original.getTypePtr()) ? std::optional(QT)
69932949dbSEgor Zhdan                                                       : std::nullopt;
70440b1743SEgor Zhdan   };
71440b1743SEgor Zhdan 
72440b1743SEgor Zhdan   if (auto Function = dyn_cast<FunctionDecl>(D)) {
73932949dbSEgor Zhdan     if (auto Modified =
74932949dbSEgor Zhdan             GetModified(D, Function->getReturnType(), Nullability)) {
75932949dbSEgor Zhdan       const FunctionType *FnType = Function->getType()->castAs<FunctionType>();
76932949dbSEgor Zhdan       if (const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(FnType))
77932949dbSEgor Zhdan         Function->setType(S.Context.getFunctionType(
78932949dbSEgor Zhdan             *Modified, proto->getParamTypes(), proto->getExtProtoInfo()));
79932949dbSEgor Zhdan       else
80932949dbSEgor Zhdan         Function->setType(
81932949dbSEgor Zhdan             S.Context.getFunctionNoProtoType(*Modified, FnType->getExtInfo()));
82440b1743SEgor Zhdan     }
83440b1743SEgor Zhdan   } else if (auto Method = dyn_cast<ObjCMethodDecl>(D)) {
84932949dbSEgor Zhdan     if (auto Modified = GetModified(D, Method->getReturnType(), Nullability)) {
85932949dbSEgor Zhdan       Method->setReturnType(*Modified);
86440b1743SEgor Zhdan 
87440b1743SEgor Zhdan       // Make it a context-sensitive keyword if we can.
88932949dbSEgor Zhdan       if (!isIndirectPointerType(*Modified))
89440b1743SEgor Zhdan         Method->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
90440b1743SEgor Zhdan             Method->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
91440b1743SEgor Zhdan     }
92440b1743SEgor Zhdan   } else if (auto Value = dyn_cast<ValueDecl>(D)) {
93932949dbSEgor Zhdan     if (auto Modified = GetModified(D, Value->getType(), Nullability)) {
94932949dbSEgor Zhdan       Value->setType(*Modified);
95440b1743SEgor Zhdan 
96440b1743SEgor Zhdan       // Make it a context-sensitive keyword if we can.
97440b1743SEgor Zhdan       if (auto Parm = dyn_cast<ParmVarDecl>(D)) {
98932949dbSEgor Zhdan         if (Parm->isObjCMethodParameter() && !isIndirectPointerType(*Modified))
99440b1743SEgor Zhdan           Parm->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
100440b1743SEgor Zhdan               Parm->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
101440b1743SEgor Zhdan       }
102440b1743SEgor Zhdan     }
103440b1743SEgor Zhdan   } else if (auto Property = dyn_cast<ObjCPropertyDecl>(D)) {
104932949dbSEgor Zhdan     if (auto Modified = GetModified(D, Property->getType(), Nullability)) {
105932949dbSEgor Zhdan       Property->setType(*Modified, Property->getTypeSourceInfo());
106440b1743SEgor Zhdan 
107440b1743SEgor Zhdan       // Make it a property attribute if we can.
108932949dbSEgor Zhdan       if (!isIndirectPointerType(*Modified))
109440b1743SEgor Zhdan         Property->setPropertyAttributes(
110440b1743SEgor Zhdan             ObjCPropertyAttribute::kind_null_resettable);
111440b1743SEgor Zhdan     }
112440b1743SEgor Zhdan   }
113440b1743SEgor Zhdan }
114440b1743SEgor Zhdan 
115440b1743SEgor Zhdan /// Copy a string into ASTContext-allocated memory.
116440b1743SEgor Zhdan static StringRef ASTAllocateString(ASTContext &Ctx, StringRef String) {
117440b1743SEgor Zhdan   void *mem = Ctx.Allocate(String.size(), alignof(char *));
118440b1743SEgor Zhdan   memcpy(mem, String.data(), String.size());
119440b1743SEgor Zhdan   return StringRef(static_cast<char *>(mem), String.size());
120440b1743SEgor Zhdan }
121440b1743SEgor Zhdan 
122440b1743SEgor Zhdan static AttributeCommonInfo getPlaceholderAttrInfo() {
123440b1743SEgor Zhdan   return AttributeCommonInfo(SourceRange(),
124440b1743SEgor Zhdan                              AttributeCommonInfo::UnknownAttribute,
125440b1743SEgor Zhdan                              {AttributeCommonInfo::AS_GNU,
126440b1743SEgor Zhdan                               /*Spelling*/ 0, /*IsAlignas*/ false,
127440b1743SEgor Zhdan                               /*IsRegularKeywordAttribute*/ false});
128440b1743SEgor Zhdan }
129440b1743SEgor Zhdan 
130440b1743SEgor Zhdan namespace {
131440b1743SEgor Zhdan template <typename A> struct AttrKindFor {};
132440b1743SEgor Zhdan 
133440b1743SEgor Zhdan #define ATTR(X)                                                                \
134440b1743SEgor Zhdan   template <> struct AttrKindFor<X##Attr> {                                    \
135440b1743SEgor Zhdan     static const attr::Kind value = attr::X;                                   \
136440b1743SEgor Zhdan   };
137440b1743SEgor Zhdan #include "clang/Basic/AttrList.inc"
138440b1743SEgor Zhdan 
139440b1743SEgor Zhdan /// Handle an attribute introduced by API notes.
140440b1743SEgor Zhdan ///
141440b1743SEgor Zhdan /// \param IsAddition Whether we should add a new attribute
142440b1743SEgor Zhdan /// (otherwise, we might remove an existing attribute).
143440b1743SEgor Zhdan /// \param CreateAttr Create the new attribute to be added.
144440b1743SEgor Zhdan template <typename A>
145440b1743SEgor Zhdan void handleAPINotedAttribute(
146440b1743SEgor Zhdan     Sema &S, Decl *D, bool IsAddition, VersionedInfoMetadata Metadata,
147440b1743SEgor Zhdan     llvm::function_ref<A *()> CreateAttr,
148440b1743SEgor Zhdan     llvm::function_ref<Decl::attr_iterator(const Decl *)> GetExistingAttr) {
149440b1743SEgor Zhdan   if (Metadata.IsActive) {
150440b1743SEgor Zhdan     auto Existing = GetExistingAttr(D);
151440b1743SEgor Zhdan     if (Existing != D->attr_end()) {
152440b1743SEgor Zhdan       // Remove the existing attribute, and treat it as a superseded
153440b1743SEgor Zhdan       // non-versioned attribute.
154440b1743SEgor Zhdan       auto *Versioned = SwiftVersionedAdditionAttr::CreateImplicit(
155440b1743SEgor Zhdan           S.Context, Metadata.Version, *Existing, /*IsReplacedByActive*/ true);
156440b1743SEgor Zhdan 
157440b1743SEgor Zhdan       D->getAttrs().erase(Existing);
158440b1743SEgor Zhdan       D->addAttr(Versioned);
159440b1743SEgor Zhdan     }
160440b1743SEgor Zhdan 
161440b1743SEgor Zhdan     // If we're supposed to add a new attribute, do so.
162440b1743SEgor Zhdan     if (IsAddition) {
163440b1743SEgor Zhdan       if (auto Attr = CreateAttr())
164440b1743SEgor Zhdan         D->addAttr(Attr);
165440b1743SEgor Zhdan     }
166440b1743SEgor Zhdan 
167440b1743SEgor Zhdan     return;
168440b1743SEgor Zhdan   }
169440b1743SEgor Zhdan   if (IsAddition) {
170440b1743SEgor Zhdan     if (auto Attr = CreateAttr()) {
171440b1743SEgor Zhdan       auto *Versioned = SwiftVersionedAdditionAttr::CreateImplicit(
172440b1743SEgor Zhdan           S.Context, Metadata.Version, Attr,
173440b1743SEgor Zhdan           /*IsReplacedByActive*/ Metadata.IsReplacement);
174440b1743SEgor Zhdan       D->addAttr(Versioned);
175440b1743SEgor Zhdan     }
176440b1743SEgor Zhdan   } else {
177440b1743SEgor Zhdan     // FIXME: This isn't preserving enough information for things like
178440b1743SEgor Zhdan     // availability, where we're trying to remove a /specific/ kind of
179440b1743SEgor Zhdan     // attribute.
180440b1743SEgor Zhdan     auto *Versioned = SwiftVersionedRemovalAttr::CreateImplicit(
181440b1743SEgor Zhdan         S.Context, Metadata.Version, AttrKindFor<A>::value,
182440b1743SEgor Zhdan         /*IsReplacedByActive*/ Metadata.IsReplacement);
183440b1743SEgor Zhdan     D->addAttr(Versioned);
184440b1743SEgor Zhdan   }
185440b1743SEgor Zhdan }
186440b1743SEgor Zhdan 
187440b1743SEgor Zhdan template <typename A>
188440b1743SEgor Zhdan void handleAPINotedAttribute(Sema &S, Decl *D, bool ShouldAddAttribute,
189440b1743SEgor Zhdan                              VersionedInfoMetadata Metadata,
190440b1743SEgor Zhdan                              llvm::function_ref<A *()> CreateAttr) {
191440b1743SEgor Zhdan   handleAPINotedAttribute<A>(
192440b1743SEgor Zhdan       S, D, ShouldAddAttribute, Metadata, CreateAttr, [](const Decl *D) {
193440b1743SEgor Zhdan         return llvm::find_if(D->attrs(),
194440b1743SEgor Zhdan                              [](const Attr *Next) { return isa<A>(Next); });
195440b1743SEgor Zhdan       });
196440b1743SEgor Zhdan }
197440b1743SEgor Zhdan } // namespace
198440b1743SEgor Zhdan 
199440b1743SEgor Zhdan template <typename A>
200440b1743SEgor Zhdan static void handleAPINotedRetainCountAttribute(Sema &S, Decl *D,
201440b1743SEgor Zhdan                                                bool ShouldAddAttribute,
202440b1743SEgor Zhdan                                                VersionedInfoMetadata Metadata) {
203440b1743SEgor Zhdan   // The template argument has a default to make the "removal" case more
204440b1743SEgor Zhdan   // concise; it doesn't matter /which/ attribute is being removed.
205440b1743SEgor Zhdan   handleAPINotedAttribute<A>(
206440b1743SEgor Zhdan       S, D, ShouldAddAttribute, Metadata,
207440b1743SEgor Zhdan       [&] { return new (S.Context) A(S.Context, getPlaceholderAttrInfo()); },
208440b1743SEgor Zhdan       [](const Decl *D) -> Decl::attr_iterator {
209440b1743SEgor Zhdan         return llvm::find_if(D->attrs(), [](const Attr *Next) -> bool {
210440b1743SEgor Zhdan           return isa<CFReturnsRetainedAttr>(Next) ||
211440b1743SEgor Zhdan                  isa<CFReturnsNotRetainedAttr>(Next) ||
212440b1743SEgor Zhdan                  isa<NSReturnsRetainedAttr>(Next) ||
213440b1743SEgor Zhdan                  isa<NSReturnsNotRetainedAttr>(Next) ||
214440b1743SEgor Zhdan                  isa<CFAuditedTransferAttr>(Next);
215440b1743SEgor Zhdan         });
216440b1743SEgor Zhdan       });
217440b1743SEgor Zhdan }
218440b1743SEgor Zhdan 
219440b1743SEgor Zhdan static void handleAPINotedRetainCountConvention(
220440b1743SEgor Zhdan     Sema &S, Decl *D, VersionedInfoMetadata Metadata,
221440b1743SEgor Zhdan     std::optional<api_notes::RetainCountConventionKind> Convention) {
222440b1743SEgor Zhdan   if (!Convention)
223440b1743SEgor Zhdan     return;
224440b1743SEgor Zhdan   switch (*Convention) {
225440b1743SEgor Zhdan   case api_notes::RetainCountConventionKind::None:
226440b1743SEgor Zhdan     if (isa<FunctionDecl>(D)) {
227440b1743SEgor Zhdan       handleAPINotedRetainCountAttribute<CFUnknownTransferAttr>(
228440b1743SEgor Zhdan           S, D, /*shouldAddAttribute*/ true, Metadata);
229440b1743SEgor Zhdan     } else {
230440b1743SEgor Zhdan       handleAPINotedRetainCountAttribute<CFReturnsRetainedAttr>(
231440b1743SEgor Zhdan           S, D, /*shouldAddAttribute*/ false, Metadata);
232440b1743SEgor Zhdan     }
233440b1743SEgor Zhdan     break;
234440b1743SEgor Zhdan   case api_notes::RetainCountConventionKind::CFReturnsRetained:
235440b1743SEgor Zhdan     handleAPINotedRetainCountAttribute<CFReturnsRetainedAttr>(
236440b1743SEgor Zhdan         S, D, /*shouldAddAttribute*/ true, Metadata);
237440b1743SEgor Zhdan     break;
238440b1743SEgor Zhdan   case api_notes::RetainCountConventionKind::CFReturnsNotRetained:
239440b1743SEgor Zhdan     handleAPINotedRetainCountAttribute<CFReturnsNotRetainedAttr>(
240440b1743SEgor Zhdan         S, D, /*shouldAddAttribute*/ true, Metadata);
241440b1743SEgor Zhdan     break;
242440b1743SEgor Zhdan   case api_notes::RetainCountConventionKind::NSReturnsRetained:
243440b1743SEgor Zhdan     handleAPINotedRetainCountAttribute<NSReturnsRetainedAttr>(
244440b1743SEgor Zhdan         S, D, /*shouldAddAttribute*/ true, Metadata);
245440b1743SEgor Zhdan     break;
246440b1743SEgor Zhdan   case api_notes::RetainCountConventionKind::NSReturnsNotRetained:
247440b1743SEgor Zhdan     handleAPINotedRetainCountAttribute<NSReturnsNotRetainedAttr>(
248440b1743SEgor Zhdan         S, D, /*shouldAddAttribute*/ true, Metadata);
249440b1743SEgor Zhdan     break;
250440b1743SEgor Zhdan   }
251440b1743SEgor Zhdan }
252440b1743SEgor Zhdan 
253440b1743SEgor Zhdan static void ProcessAPINotes(Sema &S, Decl *D,
254440b1743SEgor Zhdan                             const api_notes::CommonEntityInfo &Info,
255440b1743SEgor Zhdan                             VersionedInfoMetadata Metadata) {
256440b1743SEgor Zhdan   // Availability
257440b1743SEgor Zhdan   if (Info.Unavailable) {
258440b1743SEgor Zhdan     handleAPINotedAttribute<UnavailableAttr>(S, D, true, Metadata, [&] {
259440b1743SEgor Zhdan       return new (S.Context)
260440b1743SEgor Zhdan           UnavailableAttr(S.Context, getPlaceholderAttrInfo(),
261440b1743SEgor Zhdan                           ASTAllocateString(S.Context, Info.UnavailableMsg));
262440b1743SEgor Zhdan     });
263440b1743SEgor Zhdan   }
264440b1743SEgor Zhdan 
265440b1743SEgor Zhdan   if (Info.UnavailableInSwift) {
266440b1743SEgor Zhdan     handleAPINotedAttribute<AvailabilityAttr>(
267440b1743SEgor Zhdan         S, D, true, Metadata,
268440b1743SEgor Zhdan         [&] {
269440b1743SEgor Zhdan           return new (S.Context) AvailabilityAttr(
270440b1743SEgor Zhdan               S.Context, getPlaceholderAttrInfo(),
271440b1743SEgor Zhdan               &S.Context.Idents.get("swift"), VersionTuple(), VersionTuple(),
272440b1743SEgor Zhdan               VersionTuple(),
273440b1743SEgor Zhdan               /*Unavailable=*/true,
274440b1743SEgor Zhdan               ASTAllocateString(S.Context, Info.UnavailableMsg),
275440b1743SEgor Zhdan               /*Strict=*/false,
276440b1743SEgor Zhdan               /*Replacement=*/StringRef(),
2773f33c4c1SHelena Kotas               /*Priority=*/Sema::AP_Explicit,
2783f33c4c1SHelena Kotas               /*Environment=*/nullptr);
279440b1743SEgor Zhdan         },
280440b1743SEgor Zhdan         [](const Decl *D) {
281440b1743SEgor Zhdan           return llvm::find_if(D->attrs(), [](const Attr *next) -> bool {
282440b1743SEgor Zhdan             if (const auto *AA = dyn_cast<AvailabilityAttr>(next))
283440b1743SEgor Zhdan               if (const auto *II = AA->getPlatform())
284440b1743SEgor Zhdan                 return II->isStr("swift");
285440b1743SEgor Zhdan             return false;
286440b1743SEgor Zhdan           });
287440b1743SEgor Zhdan         });
288440b1743SEgor Zhdan   }
289440b1743SEgor Zhdan 
290440b1743SEgor Zhdan   // swift_private
291440b1743SEgor Zhdan   if (auto SwiftPrivate = Info.isSwiftPrivate()) {
292440b1743SEgor Zhdan     handleAPINotedAttribute<SwiftPrivateAttr>(
293440b1743SEgor Zhdan         S, D, *SwiftPrivate, Metadata, [&] {
294440b1743SEgor Zhdan           return new (S.Context)
295440b1743SEgor Zhdan               SwiftPrivateAttr(S.Context, getPlaceholderAttrInfo());
296440b1743SEgor Zhdan         });
297440b1743SEgor Zhdan   }
298440b1743SEgor Zhdan 
299440b1743SEgor Zhdan   // swift_name
300440b1743SEgor Zhdan   if (!Info.SwiftName.empty()) {
301440b1743SEgor Zhdan     handleAPINotedAttribute<SwiftNameAttr>(
302440b1743SEgor Zhdan         S, D, true, Metadata, [&]() -> SwiftNameAttr * {
303440b1743SEgor Zhdan           AttributeFactory AF{};
304440b1743SEgor Zhdan           AttributePool AP{AF};
305440b1743SEgor Zhdan           auto &C = S.getASTContext();
306440b1743SEgor Zhdan           ParsedAttr *SNA =
307440b1743SEgor Zhdan               AP.create(&C.Idents.get("swift_name"), SourceRange(), nullptr,
308440b1743SEgor Zhdan                         SourceLocation(), nullptr, nullptr, nullptr,
309440b1743SEgor Zhdan                         ParsedAttr::Form::GNU());
310440b1743SEgor Zhdan 
3116b755b0cSVlad Serebrennikov           if (!S.Swift().DiagnoseName(D, Info.SwiftName, D->getLocation(), *SNA,
312440b1743SEgor Zhdan                                       /*IsAsync=*/false))
313440b1743SEgor Zhdan             return nullptr;
314440b1743SEgor Zhdan 
315440b1743SEgor Zhdan           return new (S.Context)
316440b1743SEgor Zhdan               SwiftNameAttr(S.Context, getPlaceholderAttrInfo(),
317440b1743SEgor Zhdan                             ASTAllocateString(S.Context, Info.SwiftName));
318440b1743SEgor Zhdan         });
319440b1743SEgor Zhdan   }
320440b1743SEgor Zhdan }
321440b1743SEgor Zhdan 
322440b1743SEgor Zhdan static void ProcessAPINotes(Sema &S, Decl *D,
323440b1743SEgor Zhdan                             const api_notes::CommonTypeInfo &Info,
324440b1743SEgor Zhdan                             VersionedInfoMetadata Metadata) {
325440b1743SEgor Zhdan   // swift_bridge
326440b1743SEgor Zhdan   if (auto SwiftBridge = Info.getSwiftBridge()) {
327440b1743SEgor Zhdan     handleAPINotedAttribute<SwiftBridgeAttr>(
328440b1743SEgor Zhdan         S, D, !SwiftBridge->empty(), Metadata, [&] {
329440b1743SEgor Zhdan           return new (S.Context)
330440b1743SEgor Zhdan               SwiftBridgeAttr(S.Context, getPlaceholderAttrInfo(),
331440b1743SEgor Zhdan                               ASTAllocateString(S.Context, *SwiftBridge));
332440b1743SEgor Zhdan         });
333440b1743SEgor Zhdan   }
334440b1743SEgor Zhdan 
335440b1743SEgor Zhdan   // ns_error_domain
336440b1743SEgor Zhdan   if (auto NSErrorDomain = Info.getNSErrorDomain()) {
337440b1743SEgor Zhdan     handleAPINotedAttribute<NSErrorDomainAttr>(
338440b1743SEgor Zhdan         S, D, !NSErrorDomain->empty(), Metadata, [&] {
339440b1743SEgor Zhdan           return new (S.Context)
340440b1743SEgor Zhdan               NSErrorDomainAttr(S.Context, getPlaceholderAttrInfo(),
341440b1743SEgor Zhdan                                 &S.Context.Idents.get(*NSErrorDomain));
342440b1743SEgor Zhdan         });
343440b1743SEgor Zhdan   }
344440b1743SEgor Zhdan 
345440b1743SEgor Zhdan   ProcessAPINotes(S, D, static_cast<const api_notes::CommonEntityInfo &>(Info),
346440b1743SEgor Zhdan                   Metadata);
347440b1743SEgor Zhdan }
348440b1743SEgor Zhdan 
349440b1743SEgor Zhdan /// Check that the replacement type provided by API notes is reasonable.
350440b1743SEgor Zhdan ///
351440b1743SEgor Zhdan /// This is a very weak form of ABI check.
352440b1743SEgor Zhdan static bool checkAPINotesReplacementType(Sema &S, SourceLocation Loc,
353440b1743SEgor Zhdan                                          QualType OrigType,
354440b1743SEgor Zhdan                                          QualType ReplacementType) {
355440b1743SEgor Zhdan   if (S.Context.getTypeSize(OrigType) !=
356440b1743SEgor Zhdan       S.Context.getTypeSize(ReplacementType)) {
357440b1743SEgor Zhdan     S.Diag(Loc, diag::err_incompatible_replacement_type)
358440b1743SEgor Zhdan         << ReplacementType << OrigType;
359440b1743SEgor Zhdan     return true;
360440b1743SEgor Zhdan   }
361440b1743SEgor Zhdan 
362440b1743SEgor Zhdan   return false;
363440b1743SEgor Zhdan }
364440b1743SEgor Zhdan 
365440b1743SEgor Zhdan /// Process API notes for a variable or property.
366440b1743SEgor Zhdan static void ProcessAPINotes(Sema &S, Decl *D,
367440b1743SEgor Zhdan                             const api_notes::VariableInfo &Info,
368440b1743SEgor Zhdan                             VersionedInfoMetadata Metadata) {
369440b1743SEgor Zhdan   // Type override.
370440b1743SEgor Zhdan   if (Metadata.IsActive && !Info.getType().empty() &&
371440b1743SEgor Zhdan       S.ParseTypeFromStringCallback) {
372440b1743SEgor Zhdan     auto ParsedType = S.ParseTypeFromStringCallback(
373440b1743SEgor Zhdan         Info.getType(), "<API Notes>", D->getLocation());
374440b1743SEgor Zhdan     if (ParsedType.isUsable()) {
375440b1743SEgor Zhdan       QualType Type = Sema::GetTypeFromParser(ParsedType.get());
376440b1743SEgor Zhdan       auto TypeInfo =
377440b1743SEgor Zhdan           S.Context.getTrivialTypeSourceInfo(Type, D->getLocation());
378440b1743SEgor Zhdan 
379440b1743SEgor Zhdan       if (auto Var = dyn_cast<VarDecl>(D)) {
380440b1743SEgor Zhdan         // Make adjustments to parameter types.
381440b1743SEgor Zhdan         if (isa<ParmVarDecl>(Var)) {
38231a203faSVlad Serebrennikov           Type = S.ObjC().AdjustParameterTypeForObjCAutoRefCount(
383440b1743SEgor Zhdan               Type, D->getLocation(), TypeInfo);
384440b1743SEgor Zhdan           Type = S.Context.getAdjustedParameterType(Type);
385440b1743SEgor Zhdan         }
386440b1743SEgor Zhdan 
387440b1743SEgor Zhdan         if (!checkAPINotesReplacementType(S, Var->getLocation(), Var->getType(),
388440b1743SEgor Zhdan                                           Type)) {
389440b1743SEgor Zhdan           Var->setType(Type);
390440b1743SEgor Zhdan           Var->setTypeSourceInfo(TypeInfo);
391440b1743SEgor Zhdan         }
392440b1743SEgor Zhdan       } else if (auto Property = dyn_cast<ObjCPropertyDecl>(D)) {
393440b1743SEgor Zhdan         if (!checkAPINotesReplacementType(S, Property->getLocation(),
394440b1743SEgor Zhdan                                           Property->getType(), Type))
395440b1743SEgor Zhdan           Property->setType(Type, TypeInfo);
396440b1743SEgor Zhdan 
397440b1743SEgor Zhdan       } else
398440b1743SEgor Zhdan         llvm_unreachable("API notes allowed a type on an unknown declaration");
399440b1743SEgor Zhdan     }
400440b1743SEgor Zhdan   }
401440b1743SEgor Zhdan 
402440b1743SEgor Zhdan   // Nullability.
403440b1743SEgor Zhdan   if (auto Nullability = Info.getNullability())
404440b1743SEgor Zhdan     applyNullability(S, D, *Nullability, Metadata);
405440b1743SEgor Zhdan 
406440b1743SEgor Zhdan   // Handle common entity information.
407440b1743SEgor Zhdan   ProcessAPINotes(S, D, static_cast<const api_notes::CommonEntityInfo &>(Info),
408440b1743SEgor Zhdan                   Metadata);
409440b1743SEgor Zhdan }
410440b1743SEgor Zhdan 
411440b1743SEgor Zhdan /// Process API notes for a parameter.
412440b1743SEgor Zhdan static void ProcessAPINotes(Sema &S, ParmVarDecl *D,
413440b1743SEgor Zhdan                             const api_notes::ParamInfo &Info,
414440b1743SEgor Zhdan                             VersionedInfoMetadata Metadata) {
415440b1743SEgor Zhdan   // noescape
416440b1743SEgor Zhdan   if (auto NoEscape = Info.isNoEscape())
417440b1743SEgor Zhdan     handleAPINotedAttribute<NoEscapeAttr>(S, D, *NoEscape, Metadata, [&] {
418440b1743SEgor Zhdan       return new (S.Context) NoEscapeAttr(S.Context, getPlaceholderAttrInfo());
419440b1743SEgor Zhdan     });
420440b1743SEgor Zhdan 
4217ac78f13SGábor Horváth   if (auto Lifetimebound = Info.isLifetimebound())
4227ac78f13SGábor Horváth     handleAPINotedAttribute<LifetimeBoundAttr>(
4237ac78f13SGábor Horváth         S, D, *Lifetimebound, Metadata, [&] {
4247ac78f13SGábor Horváth           return new (S.Context)
4257ac78f13SGábor Horváth               LifetimeBoundAttr(S.Context, getPlaceholderAttrInfo());
4267ac78f13SGábor Horváth         });
4277ac78f13SGábor Horváth 
428440b1743SEgor Zhdan   // Retain count convention
429440b1743SEgor Zhdan   handleAPINotedRetainCountConvention(S, D, Metadata,
430440b1743SEgor Zhdan                                       Info.getRetainCountConvention());
431440b1743SEgor Zhdan 
432440b1743SEgor Zhdan   // Handle common entity information.
433440b1743SEgor Zhdan   ProcessAPINotes(S, D, static_cast<const api_notes::VariableInfo &>(Info),
434440b1743SEgor Zhdan                   Metadata);
435440b1743SEgor Zhdan }
436440b1743SEgor Zhdan 
437440b1743SEgor Zhdan /// Process API notes for a global variable.
438440b1743SEgor Zhdan static void ProcessAPINotes(Sema &S, VarDecl *D,
439440b1743SEgor Zhdan                             const api_notes::GlobalVariableInfo &Info,
440440b1743SEgor Zhdan                             VersionedInfoMetadata metadata) {
441440b1743SEgor Zhdan   // Handle common entity information.
442440b1743SEgor Zhdan   ProcessAPINotes(S, D, static_cast<const api_notes::VariableInfo &>(Info),
443440b1743SEgor Zhdan                   metadata);
444440b1743SEgor Zhdan }
445440b1743SEgor Zhdan 
446b8169771SEgor Zhdan /// Process API notes for a C field.
447b8169771SEgor Zhdan static void ProcessAPINotes(Sema &S, FieldDecl *D,
448b8169771SEgor Zhdan                             const api_notes::FieldInfo &Info,
449b8169771SEgor Zhdan                             VersionedInfoMetadata metadata) {
450b8169771SEgor Zhdan   // Handle common entity information.
451b8169771SEgor Zhdan   ProcessAPINotes(S, D, static_cast<const api_notes::VariableInfo &>(Info),
452b8169771SEgor Zhdan                   metadata);
453b8169771SEgor Zhdan }
454b8169771SEgor Zhdan 
455440b1743SEgor Zhdan /// Process API notes for an Objective-C property.
456440b1743SEgor Zhdan static void ProcessAPINotes(Sema &S, ObjCPropertyDecl *D,
457440b1743SEgor Zhdan                             const api_notes::ObjCPropertyInfo &Info,
458440b1743SEgor Zhdan                             VersionedInfoMetadata Metadata) {
459440b1743SEgor Zhdan   // Handle common entity information.
460440b1743SEgor Zhdan   ProcessAPINotes(S, D, static_cast<const api_notes::VariableInfo &>(Info),
461440b1743SEgor Zhdan                   Metadata);
462440b1743SEgor Zhdan 
463440b1743SEgor Zhdan   if (auto AsAccessors = Info.getSwiftImportAsAccessors()) {
464440b1743SEgor Zhdan     handleAPINotedAttribute<SwiftImportPropertyAsAccessorsAttr>(
465440b1743SEgor Zhdan         S, D, *AsAccessors, Metadata, [&] {
466440b1743SEgor Zhdan           return new (S.Context) SwiftImportPropertyAsAccessorsAttr(
467440b1743SEgor Zhdan               S.Context, getPlaceholderAttrInfo());
468440b1743SEgor Zhdan         });
469440b1743SEgor Zhdan   }
470440b1743SEgor Zhdan }
471440b1743SEgor Zhdan 
472440b1743SEgor Zhdan namespace {
473440b1743SEgor Zhdan typedef llvm::PointerUnion<FunctionDecl *, ObjCMethodDecl *> FunctionOrMethod;
474440b1743SEgor Zhdan }
475440b1743SEgor Zhdan 
476440b1743SEgor Zhdan /// Process API notes for a function or method.
477440b1743SEgor Zhdan static void ProcessAPINotes(Sema &S, FunctionOrMethod AnyFunc,
478440b1743SEgor Zhdan                             const api_notes::FunctionInfo &Info,
479440b1743SEgor Zhdan                             VersionedInfoMetadata Metadata) {
480440b1743SEgor Zhdan   // Find the declaration itself.
481*f09a6f63SKazu Hirata   FunctionDecl *FD = dyn_cast<FunctionDecl *>(AnyFunc);
482440b1743SEgor Zhdan   Decl *D = FD;
483440b1743SEgor Zhdan   ObjCMethodDecl *MD = nullptr;
484440b1743SEgor Zhdan   if (!D) {
4851e3e199eSKazu Hirata     MD = cast<ObjCMethodDecl *>(AnyFunc);
486440b1743SEgor Zhdan     D = MD;
487440b1743SEgor Zhdan   }
488440b1743SEgor Zhdan 
489b074f253Selizabethandrews   assert((FD || MD) && "Expecting Function or ObjCMethod");
490b074f253Selizabethandrews 
491440b1743SEgor Zhdan   // Nullability of return type.
492440b1743SEgor Zhdan   if (Info.NullabilityAudited)
493440b1743SEgor Zhdan     applyNullability(S, D, Info.getReturnTypeInfo(), Metadata);
494440b1743SEgor Zhdan 
495440b1743SEgor Zhdan   // Parameters.
496440b1743SEgor Zhdan   unsigned NumParams = FD ? FD->getNumParams() : MD->param_size();
497440b1743SEgor Zhdan 
498440b1743SEgor Zhdan   bool AnyTypeChanged = false;
499440b1743SEgor Zhdan   for (unsigned I = 0; I != NumParams; ++I) {
500440b1743SEgor Zhdan     ParmVarDecl *Param = FD ? FD->getParamDecl(I) : MD->param_begin()[I];
501440b1743SEgor Zhdan     QualType ParamTypeBefore = Param->getType();
502440b1743SEgor Zhdan 
503440b1743SEgor Zhdan     if (I < Info.Params.size())
504440b1743SEgor Zhdan       ProcessAPINotes(S, Param, Info.Params[I], Metadata);
505440b1743SEgor Zhdan 
506440b1743SEgor Zhdan     // Nullability.
507440b1743SEgor Zhdan     if (Info.NullabilityAudited)
508440b1743SEgor Zhdan       applyNullability(S, Param, Info.getParamTypeInfo(I), Metadata);
509440b1743SEgor Zhdan 
510440b1743SEgor Zhdan     if (ParamTypeBefore.getAsOpaquePtr() != Param->getType().getAsOpaquePtr())
511440b1743SEgor Zhdan       AnyTypeChanged = true;
512440b1743SEgor Zhdan   }
513440b1743SEgor Zhdan 
51448f7f63aSfahadnayyar   // returns_(un)retained
51548f7f63aSfahadnayyar   if (!Info.SwiftReturnOwnership.empty())
51648f7f63aSfahadnayyar     D->addAttr(SwiftAttrAttr::Create(S.Context,
51748f7f63aSfahadnayyar                                      "returns_" + Info.SwiftReturnOwnership));
51848f7f63aSfahadnayyar 
519440b1743SEgor Zhdan   // Result type override.
520440b1743SEgor Zhdan   QualType OverriddenResultType;
521440b1743SEgor Zhdan   if (Metadata.IsActive && !Info.ResultType.empty() &&
522440b1743SEgor Zhdan       S.ParseTypeFromStringCallback) {
523440b1743SEgor Zhdan     auto ParsedType = S.ParseTypeFromStringCallback(
524440b1743SEgor Zhdan         Info.ResultType, "<API Notes>", D->getLocation());
525440b1743SEgor Zhdan     if (ParsedType.isUsable()) {
526440b1743SEgor Zhdan       QualType ResultType = Sema::GetTypeFromParser(ParsedType.get());
527440b1743SEgor Zhdan 
528440b1743SEgor Zhdan       if (MD) {
529440b1743SEgor Zhdan         if (!checkAPINotesReplacementType(S, D->getLocation(),
530440b1743SEgor Zhdan                                           MD->getReturnType(), ResultType)) {
531440b1743SEgor Zhdan           auto ResultTypeInfo =
532440b1743SEgor Zhdan               S.Context.getTrivialTypeSourceInfo(ResultType, D->getLocation());
533440b1743SEgor Zhdan           MD->setReturnType(ResultType);
534440b1743SEgor Zhdan           MD->setReturnTypeSourceInfo(ResultTypeInfo);
535440b1743SEgor Zhdan         }
536440b1743SEgor Zhdan       } else if (!checkAPINotesReplacementType(
537440b1743SEgor Zhdan                      S, FD->getLocation(), FD->getReturnType(), ResultType)) {
538440b1743SEgor Zhdan         OverriddenResultType = ResultType;
539440b1743SEgor Zhdan         AnyTypeChanged = true;
540440b1743SEgor Zhdan       }
541440b1743SEgor Zhdan     }
542440b1743SEgor Zhdan   }
543440b1743SEgor Zhdan 
544440b1743SEgor Zhdan   // If the result type or any of the parameter types changed for a function
545440b1743SEgor Zhdan   // declaration, we have to rebuild the type.
546440b1743SEgor Zhdan   if (FD && AnyTypeChanged) {
547440b1743SEgor Zhdan     if (const auto *fnProtoType = FD->getType()->getAs<FunctionProtoType>()) {
548440b1743SEgor Zhdan       if (OverriddenResultType.isNull())
549440b1743SEgor Zhdan         OverriddenResultType = fnProtoType->getReturnType();
550440b1743SEgor Zhdan 
551440b1743SEgor Zhdan       SmallVector<QualType, 4> ParamTypes;
552440b1743SEgor Zhdan       for (auto Param : FD->parameters())
553440b1743SEgor Zhdan         ParamTypes.push_back(Param->getType());
554440b1743SEgor Zhdan 
555440b1743SEgor Zhdan       FD->setType(S.Context.getFunctionType(OverriddenResultType, ParamTypes,
556440b1743SEgor Zhdan                                             fnProtoType->getExtProtoInfo()));
557440b1743SEgor Zhdan     } else if (!OverriddenResultType.isNull()) {
558440b1743SEgor Zhdan       const auto *FnNoProtoType = FD->getType()->castAs<FunctionNoProtoType>();
559440b1743SEgor Zhdan       FD->setType(S.Context.getFunctionNoProtoType(
560440b1743SEgor Zhdan           OverriddenResultType, FnNoProtoType->getExtInfo()));
561440b1743SEgor Zhdan     }
562440b1743SEgor Zhdan   }
563440b1743SEgor Zhdan 
564440b1743SEgor Zhdan   // Retain count convention
565440b1743SEgor Zhdan   handleAPINotedRetainCountConvention(S, D, Metadata,
566440b1743SEgor Zhdan                                       Info.getRetainCountConvention());
567440b1743SEgor Zhdan 
568440b1743SEgor Zhdan   // Handle common entity information.
569440b1743SEgor Zhdan   ProcessAPINotes(S, D, static_cast<const api_notes::CommonEntityInfo &>(Info),
570440b1743SEgor Zhdan                   Metadata);
571440b1743SEgor Zhdan }
572440b1743SEgor Zhdan 
5738a79dc7eSEgor Zhdan /// Process API notes for a C++ method.
5748a79dc7eSEgor Zhdan static void ProcessAPINotes(Sema &S, CXXMethodDecl *Method,
5758a79dc7eSEgor Zhdan                             const api_notes::CXXMethodInfo &Info,
5768a79dc7eSEgor Zhdan                             VersionedInfoMetadata Metadata) {
5774862febdSGábor Horváth   if (Info.This && Info.This->isLifetimebound() &&
5784862febdSGábor Horváth       !sema::implicitObjectParamIsLifetimeBound(Method)) {
5795f4e3a3cSGábor Horváth     auto MethodType = Method->getType();
5805f4e3a3cSGábor Horváth     auto *attr = ::new (S.Context)
5815f4e3a3cSGábor Horváth         LifetimeBoundAttr(S.Context, getPlaceholderAttrInfo());
5825f4e3a3cSGábor Horváth     QualType AttributedType =
5835f4e3a3cSGábor Horváth         S.Context.getAttributedType(attr, MethodType, MethodType);
5845f4e3a3cSGábor Horváth     TypeLocBuilder TLB;
5855f4e3a3cSGábor Horváth     TLB.pushFullCopy(Method->getTypeSourceInfo()->getTypeLoc());
5865f4e3a3cSGábor Horváth     AttributedTypeLoc TyLoc = TLB.push<AttributedTypeLoc>(AttributedType);
5875f4e3a3cSGábor Horváth     TyLoc.setAttr(attr);
5885f4e3a3cSGábor Horváth     Method->setType(AttributedType);
5895f4e3a3cSGábor Horváth     Method->setTypeSourceInfo(TLB.getTypeSourceInfo(S.Context, AttributedType));
5905f4e3a3cSGábor Horváth   }
5915f4e3a3cSGábor Horváth 
5928a79dc7eSEgor Zhdan   ProcessAPINotes(S, (FunctionOrMethod)Method, Info, Metadata);
5938a79dc7eSEgor Zhdan }
5948a79dc7eSEgor Zhdan 
595440b1743SEgor Zhdan /// Process API notes for a global function.
596440b1743SEgor Zhdan static void ProcessAPINotes(Sema &S, FunctionDecl *D,
597440b1743SEgor Zhdan                             const api_notes::GlobalFunctionInfo &Info,
598440b1743SEgor Zhdan                             VersionedInfoMetadata Metadata) {
599440b1743SEgor Zhdan   // Handle common function information.
600440b1743SEgor Zhdan   ProcessAPINotes(S, FunctionOrMethod(D),
601440b1743SEgor Zhdan                   static_cast<const api_notes::FunctionInfo &>(Info), Metadata);
602440b1743SEgor Zhdan }
603440b1743SEgor Zhdan 
604440b1743SEgor Zhdan /// Process API notes for an enumerator.
605440b1743SEgor Zhdan static void ProcessAPINotes(Sema &S, EnumConstantDecl *D,
606440b1743SEgor Zhdan                             const api_notes::EnumConstantInfo &Info,
607440b1743SEgor Zhdan                             VersionedInfoMetadata Metadata) {
608440b1743SEgor Zhdan   // Handle common information.
609440b1743SEgor Zhdan   ProcessAPINotes(S, D, static_cast<const api_notes::CommonEntityInfo &>(Info),
610440b1743SEgor Zhdan                   Metadata);
611440b1743SEgor Zhdan }
612440b1743SEgor Zhdan 
613440b1743SEgor Zhdan /// Process API notes for an Objective-C method.
614440b1743SEgor Zhdan static void ProcessAPINotes(Sema &S, ObjCMethodDecl *D,
615440b1743SEgor Zhdan                             const api_notes::ObjCMethodInfo &Info,
616440b1743SEgor Zhdan                             VersionedInfoMetadata Metadata) {
617440b1743SEgor Zhdan   // Designated initializers.
618440b1743SEgor Zhdan   if (Info.DesignatedInit) {
619440b1743SEgor Zhdan     handleAPINotedAttribute<ObjCDesignatedInitializerAttr>(
620440b1743SEgor Zhdan         S, D, true, Metadata, [&] {
621440b1743SEgor Zhdan           if (ObjCInterfaceDecl *IFace = D->getClassInterface())
622440b1743SEgor Zhdan             IFace->setHasDesignatedInitializers();
623440b1743SEgor Zhdan 
624440b1743SEgor Zhdan           return new (S.Context) ObjCDesignatedInitializerAttr(
625440b1743SEgor Zhdan               S.Context, getPlaceholderAttrInfo());
626440b1743SEgor Zhdan         });
627440b1743SEgor Zhdan   }
628440b1743SEgor Zhdan 
629440b1743SEgor Zhdan   // Handle common function information.
630440b1743SEgor Zhdan   ProcessAPINotes(S, FunctionOrMethod(D),
631440b1743SEgor Zhdan                   static_cast<const api_notes::FunctionInfo &>(Info), Metadata);
632440b1743SEgor Zhdan }
633440b1743SEgor Zhdan 
634440b1743SEgor Zhdan /// Process API notes for a tag.
635440b1743SEgor Zhdan static void ProcessAPINotes(Sema &S, TagDecl *D, const api_notes::TagInfo &Info,
636440b1743SEgor Zhdan                             VersionedInfoMetadata Metadata) {
637440b1743SEgor Zhdan   if (auto ImportAs = Info.SwiftImportAs)
638440b1743SEgor Zhdan     D->addAttr(SwiftAttrAttr::Create(S.Context, "import_" + ImportAs.value()));
639440b1743SEgor Zhdan 
640440b1743SEgor Zhdan   if (auto RetainOp = Info.SwiftRetainOp)
641440b1743SEgor Zhdan     D->addAttr(SwiftAttrAttr::Create(S.Context, "retain:" + RetainOp.value()));
642440b1743SEgor Zhdan 
643440b1743SEgor Zhdan   if (auto ReleaseOp = Info.SwiftReleaseOp)
644440b1743SEgor Zhdan     D->addAttr(
645440b1743SEgor Zhdan         SwiftAttrAttr::Create(S.Context, "release:" + ReleaseOp.value()));
646440b1743SEgor Zhdan 
647dc8c217dSEgor Zhdan   if (auto ConformsTo = Info.SwiftConformance)
648dc8c217dSEgor Zhdan     D->addAttr(
649dc8c217dSEgor Zhdan         SwiftAttrAttr::Create(S.Context, "conforms_to:" + ConformsTo.value()));
650dc8c217dSEgor Zhdan 
651b2098db2SEgor Zhdan   if (auto Copyable = Info.isSwiftCopyable()) {
652b2098db2SEgor Zhdan     if (!*Copyable)
653b2098db2SEgor Zhdan       D->addAttr(SwiftAttrAttr::Create(S.Context, "~Copyable"));
654b2098db2SEgor Zhdan   }
655b2098db2SEgor Zhdan 
656d2db9bd7SGábor Horváth   if (auto Escapable = Info.isSwiftEscapable()) {
657d2db9bd7SGábor Horváth     D->addAttr(SwiftAttrAttr::Create(S.Context,
658d2db9bd7SGábor Horváth                                      *Escapable ? "Escapable" : "~Escapable"));
659d2db9bd7SGábor Horváth   }
660d2db9bd7SGábor Horváth 
661440b1743SEgor Zhdan   if (auto Extensibility = Info.EnumExtensibility) {
662440b1743SEgor Zhdan     using api_notes::EnumExtensibilityKind;
663440b1743SEgor Zhdan     bool ShouldAddAttribute = (*Extensibility != EnumExtensibilityKind::None);
664440b1743SEgor Zhdan     handleAPINotedAttribute<EnumExtensibilityAttr>(
665440b1743SEgor Zhdan         S, D, ShouldAddAttribute, Metadata, [&] {
666440b1743SEgor Zhdan           EnumExtensibilityAttr::Kind kind;
667440b1743SEgor Zhdan           switch (*Extensibility) {
668440b1743SEgor Zhdan           case EnumExtensibilityKind::None:
669440b1743SEgor Zhdan             llvm_unreachable("remove only");
670440b1743SEgor Zhdan           case EnumExtensibilityKind::Open:
671440b1743SEgor Zhdan             kind = EnumExtensibilityAttr::Open;
672440b1743SEgor Zhdan             break;
673440b1743SEgor Zhdan           case EnumExtensibilityKind::Closed:
674440b1743SEgor Zhdan             kind = EnumExtensibilityAttr::Closed;
675440b1743SEgor Zhdan             break;
676440b1743SEgor Zhdan           }
677440b1743SEgor Zhdan           return new (S.Context)
678440b1743SEgor Zhdan               EnumExtensibilityAttr(S.Context, getPlaceholderAttrInfo(), kind);
679440b1743SEgor Zhdan         });
680440b1743SEgor Zhdan   }
681440b1743SEgor Zhdan 
682440b1743SEgor Zhdan   if (auto FlagEnum = Info.isFlagEnum()) {
683440b1743SEgor Zhdan     handleAPINotedAttribute<FlagEnumAttr>(S, D, *FlagEnum, Metadata, [&] {
684440b1743SEgor Zhdan       return new (S.Context) FlagEnumAttr(S.Context, getPlaceholderAttrInfo());
685440b1743SEgor Zhdan     });
686440b1743SEgor Zhdan   }
687440b1743SEgor Zhdan 
688440b1743SEgor Zhdan   // Handle common type information.
689440b1743SEgor Zhdan   ProcessAPINotes(S, D, static_cast<const api_notes::CommonTypeInfo &>(Info),
690440b1743SEgor Zhdan                   Metadata);
691440b1743SEgor Zhdan }
692440b1743SEgor Zhdan 
693440b1743SEgor Zhdan /// Process API notes for a typedef.
694440b1743SEgor Zhdan static void ProcessAPINotes(Sema &S, TypedefNameDecl *D,
695440b1743SEgor Zhdan                             const api_notes::TypedefInfo &Info,
696440b1743SEgor Zhdan                             VersionedInfoMetadata Metadata) {
697440b1743SEgor Zhdan   // swift_wrapper
698440b1743SEgor Zhdan   using SwiftWrapperKind = api_notes::SwiftNewTypeKind;
699440b1743SEgor Zhdan 
700440b1743SEgor Zhdan   if (auto SwiftWrapper = Info.SwiftWrapper) {
701440b1743SEgor Zhdan     handleAPINotedAttribute<SwiftNewTypeAttr>(
702440b1743SEgor Zhdan         S, D, *SwiftWrapper != SwiftWrapperKind::None, Metadata, [&] {
703440b1743SEgor Zhdan           SwiftNewTypeAttr::NewtypeKind Kind;
704440b1743SEgor Zhdan           switch (*SwiftWrapper) {
705440b1743SEgor Zhdan           case SwiftWrapperKind::None:
706440b1743SEgor Zhdan             llvm_unreachable("Shouldn't build an attribute");
707440b1743SEgor Zhdan 
708440b1743SEgor Zhdan           case SwiftWrapperKind::Struct:
709440b1743SEgor Zhdan             Kind = SwiftNewTypeAttr::NK_Struct;
710440b1743SEgor Zhdan             break;
711440b1743SEgor Zhdan 
712440b1743SEgor Zhdan           case SwiftWrapperKind::Enum:
713440b1743SEgor Zhdan             Kind = SwiftNewTypeAttr::NK_Enum;
714440b1743SEgor Zhdan             break;
715440b1743SEgor Zhdan           }
716440b1743SEgor Zhdan           AttributeCommonInfo SyntaxInfo{
717440b1743SEgor Zhdan               SourceRange(),
718440b1743SEgor Zhdan               AttributeCommonInfo::AT_SwiftNewType,
719440b1743SEgor Zhdan               {AttributeCommonInfo::AS_GNU, SwiftNewTypeAttr::GNU_swift_wrapper,
720440b1743SEgor Zhdan                /*IsAlignas*/ false, /*IsRegularKeywordAttribute*/ false}};
721440b1743SEgor Zhdan           return new (S.Context) SwiftNewTypeAttr(S.Context, SyntaxInfo, Kind);
722440b1743SEgor Zhdan         });
723440b1743SEgor Zhdan   }
724440b1743SEgor Zhdan 
725440b1743SEgor Zhdan   // Handle common type information.
726440b1743SEgor Zhdan   ProcessAPINotes(S, D, static_cast<const api_notes::CommonTypeInfo &>(Info),
727440b1743SEgor Zhdan                   Metadata);
728440b1743SEgor Zhdan }
729440b1743SEgor Zhdan 
730440b1743SEgor Zhdan /// Process API notes for an Objective-C class or protocol.
731440b1743SEgor Zhdan static void ProcessAPINotes(Sema &S, ObjCContainerDecl *D,
73282ee7ae3SEgor Zhdan                             const api_notes::ContextInfo &Info,
733440b1743SEgor Zhdan                             VersionedInfoMetadata Metadata) {
734440b1743SEgor Zhdan   // Handle common type information.
735440b1743SEgor Zhdan   ProcessAPINotes(S, D, static_cast<const api_notes::CommonTypeInfo &>(Info),
736440b1743SEgor Zhdan                   Metadata);
737440b1743SEgor Zhdan }
738440b1743SEgor Zhdan 
739440b1743SEgor Zhdan /// Process API notes for an Objective-C class.
740440b1743SEgor Zhdan static void ProcessAPINotes(Sema &S, ObjCInterfaceDecl *D,
74182ee7ae3SEgor Zhdan                             const api_notes::ContextInfo &Info,
742440b1743SEgor Zhdan                             VersionedInfoMetadata Metadata) {
743440b1743SEgor Zhdan   if (auto AsNonGeneric = Info.getSwiftImportAsNonGeneric()) {
744440b1743SEgor Zhdan     handleAPINotedAttribute<SwiftImportAsNonGenericAttr>(
745440b1743SEgor Zhdan         S, D, *AsNonGeneric, Metadata, [&] {
746440b1743SEgor Zhdan           return new (S.Context)
747440b1743SEgor Zhdan               SwiftImportAsNonGenericAttr(S.Context, getPlaceholderAttrInfo());
748440b1743SEgor Zhdan         });
749440b1743SEgor Zhdan   }
750440b1743SEgor Zhdan 
751440b1743SEgor Zhdan   if (auto ObjcMembers = Info.getSwiftObjCMembers()) {
752440b1743SEgor Zhdan     handleAPINotedAttribute<SwiftObjCMembersAttr>(
753440b1743SEgor Zhdan         S, D, *ObjcMembers, Metadata, [&] {
754440b1743SEgor Zhdan           return new (S.Context)
755440b1743SEgor Zhdan               SwiftObjCMembersAttr(S.Context, getPlaceholderAttrInfo());
756440b1743SEgor Zhdan         });
757440b1743SEgor Zhdan   }
758440b1743SEgor Zhdan 
759440b1743SEgor Zhdan   // Handle information common to Objective-C classes and protocols.
760440b1743SEgor Zhdan   ProcessAPINotes(S, static_cast<clang::ObjCContainerDecl *>(D), Info,
761440b1743SEgor Zhdan                   Metadata);
762440b1743SEgor Zhdan }
763440b1743SEgor Zhdan 
764440b1743SEgor Zhdan /// If we're applying API notes with an active, non-default version, and the
765440b1743SEgor Zhdan /// versioned API notes have a SwiftName but the declaration normally wouldn't
766440b1743SEgor Zhdan /// have one, add a removal attribute to make it clear that the new SwiftName
767440b1743SEgor Zhdan /// attribute only applies to the active version of \p D, not to all versions.
768440b1743SEgor Zhdan ///
769440b1743SEgor Zhdan /// This must be run \em before processing API notes for \p D, because otherwise
770440b1743SEgor Zhdan /// any existing SwiftName attribute will have been packaged up in a
771440b1743SEgor Zhdan /// SwiftVersionedAdditionAttr.
772440b1743SEgor Zhdan template <typename SpecificInfo>
773440b1743SEgor Zhdan static void maybeAttachUnversionedSwiftName(
774440b1743SEgor Zhdan     Sema &S, Decl *D,
775440b1743SEgor Zhdan     const api_notes::APINotesReader::VersionedInfo<SpecificInfo> Info) {
776440b1743SEgor Zhdan   if (D->hasAttr<SwiftNameAttr>())
777440b1743SEgor Zhdan     return;
778440b1743SEgor Zhdan   if (!Info.getSelected())
779440b1743SEgor Zhdan     return;
780440b1743SEgor Zhdan 
781440b1743SEgor Zhdan   // Is the active slice versioned, and does it set a Swift name?
782440b1743SEgor Zhdan   VersionTuple SelectedVersion;
783440b1743SEgor Zhdan   SpecificInfo SelectedInfoSlice;
784440b1743SEgor Zhdan   std::tie(SelectedVersion, SelectedInfoSlice) = Info[*Info.getSelected()];
785440b1743SEgor Zhdan   if (SelectedVersion.empty())
786440b1743SEgor Zhdan     return;
787440b1743SEgor Zhdan   if (SelectedInfoSlice.SwiftName.empty())
788440b1743SEgor Zhdan     return;
789440b1743SEgor Zhdan 
790440b1743SEgor Zhdan   // Does the unversioned slice /not/ set a Swift name?
791440b1743SEgor Zhdan   for (const auto &VersionAndInfoSlice : Info) {
792440b1743SEgor Zhdan     if (!VersionAndInfoSlice.first.empty())
793440b1743SEgor Zhdan       continue;
794440b1743SEgor Zhdan     if (!VersionAndInfoSlice.second.SwiftName.empty())
795440b1743SEgor Zhdan       return;
796440b1743SEgor Zhdan   }
797440b1743SEgor Zhdan 
798440b1743SEgor Zhdan   // Then explicitly call that out with a removal attribute.
799440b1743SEgor Zhdan   VersionedInfoMetadata DummyFutureMetadata(
800440b1743SEgor Zhdan       SelectedVersion, IsActive_t::Inactive, IsSubstitution_t::Replacement);
801440b1743SEgor Zhdan   handleAPINotedAttribute<SwiftNameAttr>(
802440b1743SEgor Zhdan       S, D, /*add*/ false, DummyFutureMetadata, []() -> SwiftNameAttr * {
803440b1743SEgor Zhdan         llvm_unreachable("should not try to add an attribute here");
804440b1743SEgor Zhdan       });
805440b1743SEgor Zhdan }
806440b1743SEgor Zhdan 
807440b1743SEgor Zhdan /// Processes all versions of versioned API notes.
808440b1743SEgor Zhdan ///
809440b1743SEgor Zhdan /// Just dispatches to the various ProcessAPINotes functions in this file.
810440b1743SEgor Zhdan template <typename SpecificDecl, typename SpecificInfo>
811440b1743SEgor Zhdan static void ProcessVersionedAPINotes(
812440b1743SEgor Zhdan     Sema &S, SpecificDecl *D,
813440b1743SEgor Zhdan     const api_notes::APINotesReader::VersionedInfo<SpecificInfo> Info) {
814440b1743SEgor Zhdan 
815440b1743SEgor Zhdan   maybeAttachUnversionedSwiftName(S, D, Info);
816440b1743SEgor Zhdan 
817440b1743SEgor Zhdan   unsigned Selected = Info.getSelected().value_or(Info.size());
818440b1743SEgor Zhdan 
819440b1743SEgor Zhdan   VersionTuple Version;
820440b1743SEgor Zhdan   SpecificInfo InfoSlice;
821440b1743SEgor Zhdan   for (unsigned i = 0, e = Info.size(); i != e; ++i) {
822440b1743SEgor Zhdan     std::tie(Version, InfoSlice) = Info[i];
823440b1743SEgor Zhdan     auto Active = (i == Selected) ? IsActive_t::Active : IsActive_t::Inactive;
824440b1743SEgor Zhdan     auto Replacement = IsSubstitution_t::Original;
825440b1743SEgor Zhdan     if (Active == IsActive_t::Inactive && Version.empty()) {
826440b1743SEgor Zhdan       Replacement = IsSubstitution_t::Replacement;
827440b1743SEgor Zhdan       Version = Info[Selected].first;
828440b1743SEgor Zhdan     }
829440b1743SEgor Zhdan     ProcessAPINotes(S, D, InfoSlice,
830440b1743SEgor Zhdan                     VersionedInfoMetadata(Version, Active, Replacement));
831440b1743SEgor Zhdan   }
832440b1743SEgor Zhdan }
833440b1743SEgor Zhdan 
8344d5f81caSEgor Zhdan static std::optional<api_notes::Context>
8354d5f81caSEgor Zhdan UnwindNamespaceContext(DeclContext *DC, api_notes::APINotesManager &APINotes) {
8368a79dc7eSEgor Zhdan   if (auto NamespaceContext = dyn_cast<NamespaceDecl>(DC)) {
8374d5f81caSEgor Zhdan     for (auto Reader : APINotes.findAPINotes(NamespaceContext->getLocation())) {
838440b1743SEgor Zhdan       // Retrieve the context ID for the parent namespace of the decl.
839440b1743SEgor Zhdan       std::stack<NamespaceDecl *> NamespaceStack;
840440b1743SEgor Zhdan       {
841440b1743SEgor Zhdan         for (auto CurrentNamespace = NamespaceContext; CurrentNamespace;
842440b1743SEgor Zhdan              CurrentNamespace =
843440b1743SEgor Zhdan                  dyn_cast<NamespaceDecl>(CurrentNamespace->getParent())) {
844440b1743SEgor Zhdan           if (!CurrentNamespace->isInlineNamespace())
845440b1743SEgor Zhdan             NamespaceStack.push(CurrentNamespace);
846440b1743SEgor Zhdan         }
847440b1743SEgor Zhdan       }
848440b1743SEgor Zhdan       std::optional<api_notes::ContextID> NamespaceID;
849440b1743SEgor Zhdan       while (!NamespaceStack.empty()) {
850440b1743SEgor Zhdan         auto CurrentNamespace = NamespaceStack.top();
851440b1743SEgor Zhdan         NamespaceStack.pop();
8524d5f81caSEgor Zhdan         NamespaceID =
8534d5f81caSEgor Zhdan             Reader->lookupNamespaceID(CurrentNamespace->getName(), NamespaceID);
854440b1743SEgor Zhdan         if (!NamespaceID)
8554d5f81caSEgor Zhdan           return std::nullopt;
856440b1743SEgor Zhdan       }
857440b1743SEgor Zhdan       if (NamespaceID)
8588a79dc7eSEgor Zhdan         return api_notes::Context(*NamespaceID,
8598a79dc7eSEgor Zhdan                                   api_notes::ContextKind::Namespace);
860440b1743SEgor Zhdan     }
861440b1743SEgor Zhdan   }
8628a79dc7eSEgor Zhdan   return std::nullopt;
8634d5f81caSEgor Zhdan }
8644d5f81caSEgor Zhdan 
8654d5f81caSEgor Zhdan static std::optional<api_notes::Context>
8664d5f81caSEgor Zhdan UnwindTagContext(TagDecl *DC, api_notes::APINotesManager &APINotes) {
8674d5f81caSEgor Zhdan   assert(DC && "tag context must not be null");
8684d5f81caSEgor Zhdan   for (auto Reader : APINotes.findAPINotes(DC->getLocation())) {
8694d5f81caSEgor Zhdan     // Retrieve the context ID for the parent tag of the decl.
8704d5f81caSEgor Zhdan     std::stack<TagDecl *> TagStack;
8714d5f81caSEgor Zhdan     {
8724d5f81caSEgor Zhdan       for (auto CurrentTag = DC; CurrentTag;
8734d5f81caSEgor Zhdan            CurrentTag = dyn_cast<TagDecl>(CurrentTag->getParent()))
8744d5f81caSEgor Zhdan         TagStack.push(CurrentTag);
8754d5f81caSEgor Zhdan     }
8764d5f81caSEgor Zhdan     assert(!TagStack.empty());
8774d5f81caSEgor Zhdan     std::optional<api_notes::Context> Ctx =
8784d5f81caSEgor Zhdan         UnwindNamespaceContext(TagStack.top()->getDeclContext(), APINotes);
8794d5f81caSEgor Zhdan     while (!TagStack.empty()) {
8804d5f81caSEgor Zhdan       auto CurrentTag = TagStack.top();
8814d5f81caSEgor Zhdan       TagStack.pop();
8824d5f81caSEgor Zhdan       auto CtxID = Reader->lookupTagID(CurrentTag->getName(), Ctx);
8834d5f81caSEgor Zhdan       if (!CtxID)
8844d5f81caSEgor Zhdan         return std::nullopt;
8854d5f81caSEgor Zhdan       Ctx = api_notes::Context(*CtxID, api_notes::ContextKind::Tag);
8864d5f81caSEgor Zhdan     }
8874d5f81caSEgor Zhdan     return Ctx;
8884d5f81caSEgor Zhdan   }
8894d5f81caSEgor Zhdan   return std::nullopt;
8904d5f81caSEgor Zhdan }
8914d5f81caSEgor Zhdan 
8924d5f81caSEgor Zhdan /// Process API notes that are associated with this declaration, mapping them
8934d5f81caSEgor Zhdan /// to attributes as appropriate.
8944d5f81caSEgor Zhdan void Sema::ProcessAPINotes(Decl *D) {
8954d5f81caSEgor Zhdan   if (!D)
8964d5f81caSEgor Zhdan     return;
897440b1743SEgor Zhdan 
8987ac78f13SGábor Horváth   auto *DC = D->getDeclContext();
8998a79dc7eSEgor Zhdan   // Globals.
9007ac78f13SGábor Horváth   if (DC->isFileContext() || DC->isNamespace() || DC->isExternCContext() ||
9017ac78f13SGábor Horváth       DC->isExternCXXContext()) {
9028a79dc7eSEgor Zhdan     std::optional<api_notes::Context> APINotesContext =
9037ac78f13SGábor Horváth         UnwindNamespaceContext(DC, APINotes);
904440b1743SEgor Zhdan     // Global variables.
905440b1743SEgor Zhdan     if (auto VD = dyn_cast<VarDecl>(D)) {
906440b1743SEgor Zhdan       for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
907440b1743SEgor Zhdan         auto Info =
908440b1743SEgor Zhdan             Reader->lookupGlobalVariable(VD->getName(), APINotesContext);
909440b1743SEgor Zhdan         ProcessVersionedAPINotes(*this, VD, Info);
910440b1743SEgor Zhdan       }
911440b1743SEgor Zhdan 
912440b1743SEgor Zhdan       return;
913440b1743SEgor Zhdan     }
914440b1743SEgor Zhdan 
915440b1743SEgor Zhdan     // Global functions.
916440b1743SEgor Zhdan     if (auto FD = dyn_cast<FunctionDecl>(D)) {
917440b1743SEgor Zhdan       if (FD->getDeclName().isIdentifier()) {
918440b1743SEgor Zhdan         for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
919440b1743SEgor Zhdan           auto Info =
920440b1743SEgor Zhdan               Reader->lookupGlobalFunction(FD->getName(), APINotesContext);
921440b1743SEgor Zhdan           ProcessVersionedAPINotes(*this, FD, Info);
922440b1743SEgor Zhdan         }
923440b1743SEgor Zhdan       }
924440b1743SEgor Zhdan 
925440b1743SEgor Zhdan       return;
926440b1743SEgor Zhdan     }
927440b1743SEgor Zhdan 
928440b1743SEgor Zhdan     // Objective-C classes.
929440b1743SEgor Zhdan     if (auto Class = dyn_cast<ObjCInterfaceDecl>(D)) {
930440b1743SEgor Zhdan       for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
931440b1743SEgor Zhdan         auto Info = Reader->lookupObjCClassInfo(Class->getName());
932440b1743SEgor Zhdan         ProcessVersionedAPINotes(*this, Class, Info);
933440b1743SEgor Zhdan       }
934440b1743SEgor Zhdan 
935440b1743SEgor Zhdan       return;
936440b1743SEgor Zhdan     }
937440b1743SEgor Zhdan 
938440b1743SEgor Zhdan     // Objective-C protocols.
939440b1743SEgor Zhdan     if (auto Protocol = dyn_cast<ObjCProtocolDecl>(D)) {
940440b1743SEgor Zhdan       for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
941440b1743SEgor Zhdan         auto Info = Reader->lookupObjCProtocolInfo(Protocol->getName());
942440b1743SEgor Zhdan         ProcessVersionedAPINotes(*this, Protocol, Info);
943440b1743SEgor Zhdan       }
944440b1743SEgor Zhdan 
945440b1743SEgor Zhdan       return;
946440b1743SEgor Zhdan     }
947440b1743SEgor Zhdan 
948440b1743SEgor Zhdan     // Tags
949440b1743SEgor Zhdan     if (auto Tag = dyn_cast<TagDecl>(D)) {
950694fd1f2SDoug Gregor       // Determine the name of the entity to search for. If this is an
951694fd1f2SDoug Gregor       // anonymous tag that gets its linked name from a typedef, look for the
952694fd1f2SDoug Gregor       // typedef name. This allows tag-specific information to be added
953694fd1f2SDoug Gregor       // to the declaration.
954694fd1f2SDoug Gregor       std::string LookupName;
955694fd1f2SDoug Gregor       if (auto typedefName = Tag->getTypedefNameForAnonDecl())
956694fd1f2SDoug Gregor         LookupName = typedefName->getName().str();
957694fd1f2SDoug Gregor       else
958694fd1f2SDoug Gregor         LookupName = Tag->getName().str();
959440b1743SEgor Zhdan 
960440b1743SEgor Zhdan       // Use the source location to discern if this Tag is an OPTIONS macro.
961440b1743SEgor Zhdan       // For now we would like to limit this trick of looking up the APINote tag
962440b1743SEgor Zhdan       // using the EnumDecl's QualType in the case where the enum is anonymous.
963440b1743SEgor Zhdan       // This is only being used to support APINotes lookup for C++
964440b1743SEgor Zhdan       // NS/CF_OPTIONS when C++-Interop is enabled.
965440b1743SEgor Zhdan       std::string MacroName =
966440b1743SEgor Zhdan           LookupName.empty() && Tag->getOuterLocStart().isMacroID()
967440b1743SEgor Zhdan               ? clang::Lexer::getImmediateMacroName(
968440b1743SEgor Zhdan                     Tag->getOuterLocStart(),
969440b1743SEgor Zhdan                     Tag->getASTContext().getSourceManager(), LangOpts)
970440b1743SEgor Zhdan                     .str()
971440b1743SEgor Zhdan               : "";
972440b1743SEgor Zhdan 
973440b1743SEgor Zhdan       if (LookupName.empty() && isa<clang::EnumDecl>(Tag) &&
974440b1743SEgor Zhdan           (MacroName == "CF_OPTIONS" || MacroName == "NS_OPTIONS" ||
975440b1743SEgor Zhdan            MacroName == "OBJC_OPTIONS" || MacroName == "SWIFT_OPTIONS")) {
976440b1743SEgor Zhdan 
977440b1743SEgor Zhdan         clang::QualType T = llvm::cast<clang::EnumDecl>(Tag)->getIntegerType();
978440b1743SEgor Zhdan         LookupName = clang::QualType::getAsString(
979440b1743SEgor Zhdan             T.split(), getASTContext().getPrintingPolicy());
980440b1743SEgor Zhdan       }
981440b1743SEgor Zhdan 
982440b1743SEgor Zhdan       for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
9834d5f81caSEgor Zhdan         if (auto ParentTag = dyn_cast<TagDecl>(Tag->getDeclContext()))
9844d5f81caSEgor Zhdan           APINotesContext = UnwindTagContext(ParentTag, APINotes);
985440b1743SEgor Zhdan         auto Info = Reader->lookupTag(LookupName, APINotesContext);
986440b1743SEgor Zhdan         ProcessVersionedAPINotes(*this, Tag, Info);
987440b1743SEgor Zhdan       }
988440b1743SEgor Zhdan 
989440b1743SEgor Zhdan       return;
990440b1743SEgor Zhdan     }
991440b1743SEgor Zhdan 
992440b1743SEgor Zhdan     // Typedefs
993440b1743SEgor Zhdan     if (auto Typedef = dyn_cast<TypedefNameDecl>(D)) {
994440b1743SEgor Zhdan       for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
995440b1743SEgor Zhdan         auto Info = Reader->lookupTypedef(Typedef->getName(), APINotesContext);
996440b1743SEgor Zhdan         ProcessVersionedAPINotes(*this, Typedef, Info);
997440b1743SEgor Zhdan       }
998440b1743SEgor Zhdan 
999440b1743SEgor Zhdan       return;
1000440b1743SEgor Zhdan     }
1001440b1743SEgor Zhdan   }
1002440b1743SEgor Zhdan 
1003440b1743SEgor Zhdan   // Enumerators.
10047ac78f13SGábor Horváth   if (DC->getRedeclContext()->isFileContext() ||
10057ac78f13SGábor Horváth       DC->getRedeclContext()->isExternCContext()) {
1006440b1743SEgor Zhdan     if (auto EnumConstant = dyn_cast<EnumConstantDecl>(D)) {
1007440b1743SEgor Zhdan       for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
1008440b1743SEgor Zhdan         auto Info = Reader->lookupEnumConstant(EnumConstant->getName());
1009440b1743SEgor Zhdan         ProcessVersionedAPINotes(*this, EnumConstant, Info);
1010440b1743SEgor Zhdan       }
1011440b1743SEgor Zhdan 
1012440b1743SEgor Zhdan       return;
1013440b1743SEgor Zhdan     }
1014440b1743SEgor Zhdan   }
1015440b1743SEgor Zhdan 
10167ac78f13SGábor Horváth   if (auto ObjCContainer = dyn_cast<ObjCContainerDecl>(DC)) {
1017440b1743SEgor Zhdan     // Location function that looks up an Objective-C context.
1018440b1743SEgor Zhdan     auto GetContext = [&](api_notes::APINotesReader *Reader)
1019440b1743SEgor Zhdan         -> std::optional<api_notes::ContextID> {
1020440b1743SEgor Zhdan       if (auto Protocol = dyn_cast<ObjCProtocolDecl>(ObjCContainer)) {
1021440b1743SEgor Zhdan         if (auto Found = Reader->lookupObjCProtocolID(Protocol->getName()))
1022440b1743SEgor Zhdan           return *Found;
1023440b1743SEgor Zhdan 
1024440b1743SEgor Zhdan         return std::nullopt;
1025440b1743SEgor Zhdan       }
1026440b1743SEgor Zhdan 
1027440b1743SEgor Zhdan       if (auto Impl = dyn_cast<ObjCCategoryImplDecl>(ObjCContainer)) {
1028440b1743SEgor Zhdan         if (auto Cat = Impl->getCategoryDecl())
1029440b1743SEgor Zhdan           ObjCContainer = Cat->getClassInterface();
1030440b1743SEgor Zhdan         else
1031440b1743SEgor Zhdan           return std::nullopt;
1032440b1743SEgor Zhdan       }
1033440b1743SEgor Zhdan 
1034440b1743SEgor Zhdan       if (auto Category = dyn_cast<ObjCCategoryDecl>(ObjCContainer)) {
1035440b1743SEgor Zhdan         if (Category->getClassInterface())
1036440b1743SEgor Zhdan           ObjCContainer = Category->getClassInterface();
1037440b1743SEgor Zhdan         else
1038440b1743SEgor Zhdan           return std::nullopt;
1039440b1743SEgor Zhdan       }
1040440b1743SEgor Zhdan 
1041440b1743SEgor Zhdan       if (auto Impl = dyn_cast<ObjCImplDecl>(ObjCContainer)) {
1042440b1743SEgor Zhdan         if (Impl->getClassInterface())
1043440b1743SEgor Zhdan           ObjCContainer = Impl->getClassInterface();
1044440b1743SEgor Zhdan         else
1045440b1743SEgor Zhdan           return std::nullopt;
1046440b1743SEgor Zhdan       }
1047440b1743SEgor Zhdan 
1048440b1743SEgor Zhdan       if (auto Class = dyn_cast<ObjCInterfaceDecl>(ObjCContainer)) {
1049440b1743SEgor Zhdan         if (auto Found = Reader->lookupObjCClassID(Class->getName()))
1050440b1743SEgor Zhdan           return *Found;
1051440b1743SEgor Zhdan 
1052440b1743SEgor Zhdan         return std::nullopt;
1053440b1743SEgor Zhdan       }
1054440b1743SEgor Zhdan 
1055440b1743SEgor Zhdan       return std::nullopt;
1056440b1743SEgor Zhdan     };
1057440b1743SEgor Zhdan 
1058440b1743SEgor Zhdan     // Objective-C methods.
1059440b1743SEgor Zhdan     if (auto Method = dyn_cast<ObjCMethodDecl>(D)) {
1060440b1743SEgor Zhdan       for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
1061440b1743SEgor Zhdan         if (auto Context = GetContext(Reader)) {
1062440b1743SEgor Zhdan           // Map the selector.
1063440b1743SEgor Zhdan           Selector Sel = Method->getSelector();
1064440b1743SEgor Zhdan           SmallVector<StringRef, 2> SelPieces;
1065440b1743SEgor Zhdan           if (Sel.isUnarySelector()) {
1066440b1743SEgor Zhdan             SelPieces.push_back(Sel.getNameForSlot(0));
1067440b1743SEgor Zhdan           } else {
1068440b1743SEgor Zhdan             for (unsigned i = 0, n = Sel.getNumArgs(); i != n; ++i)
1069440b1743SEgor Zhdan               SelPieces.push_back(Sel.getNameForSlot(i));
1070440b1743SEgor Zhdan           }
1071440b1743SEgor Zhdan 
1072440b1743SEgor Zhdan           api_notes::ObjCSelectorRef SelectorRef;
1073440b1743SEgor Zhdan           SelectorRef.NumArgs = Sel.getNumArgs();
1074440b1743SEgor Zhdan           SelectorRef.Identifiers = SelPieces;
1075440b1743SEgor Zhdan 
1076440b1743SEgor Zhdan           auto Info = Reader->lookupObjCMethod(*Context, SelectorRef,
1077440b1743SEgor Zhdan                                                Method->isInstanceMethod());
1078440b1743SEgor Zhdan           ProcessVersionedAPINotes(*this, Method, Info);
1079440b1743SEgor Zhdan         }
1080440b1743SEgor Zhdan       }
1081440b1743SEgor Zhdan     }
1082440b1743SEgor Zhdan 
1083440b1743SEgor Zhdan     // Objective-C properties.
1084440b1743SEgor Zhdan     if (auto Property = dyn_cast<ObjCPropertyDecl>(D)) {
1085440b1743SEgor Zhdan       for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
1086440b1743SEgor Zhdan         if (auto Context = GetContext(Reader)) {
1087440b1743SEgor Zhdan           bool isInstanceProperty =
1088440b1743SEgor Zhdan               (Property->getPropertyAttributesAsWritten() &
1089440b1743SEgor Zhdan                ObjCPropertyAttribute::kind_class) == 0;
1090440b1743SEgor Zhdan           auto Info = Reader->lookupObjCProperty(*Context, Property->getName(),
1091440b1743SEgor Zhdan                                                  isInstanceProperty);
1092440b1743SEgor Zhdan           ProcessVersionedAPINotes(*this, Property, Info);
1093440b1743SEgor Zhdan         }
1094440b1743SEgor Zhdan       }
1095440b1743SEgor Zhdan 
1096440b1743SEgor Zhdan       return;
1097440b1743SEgor Zhdan     }
1098440b1743SEgor Zhdan   }
10998a79dc7eSEgor Zhdan 
11007ac78f13SGábor Horváth   if (auto TagContext = dyn_cast<TagDecl>(DC)) {
11018a79dc7eSEgor Zhdan     if (auto CXXMethod = dyn_cast<CXXMethodDecl>(D)) {
1102c66d25d1SEgor Zhdan       if (!isa<CXXConstructorDecl>(CXXMethod) &&
1103c66d25d1SEgor Zhdan           !isa<CXXDestructorDecl>(CXXMethod) &&
1104c66d25d1SEgor Zhdan           !isa<CXXConversionDecl>(CXXMethod) &&
1105c66d25d1SEgor Zhdan           !CXXMethod->isOverloadedOperator()) {
11068a79dc7eSEgor Zhdan         for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
11074d5f81caSEgor Zhdan           if (auto Context = UnwindTagContext(TagContext, APINotes)) {
11084d5f81caSEgor Zhdan             auto Info =
11094d5f81caSEgor Zhdan                 Reader->lookupCXXMethod(Context->id, CXXMethod->getName());
11108a79dc7eSEgor Zhdan             ProcessVersionedAPINotes(*this, CXXMethod, Info);
11118a79dc7eSEgor Zhdan           }
11128a79dc7eSEgor Zhdan         }
11138a79dc7eSEgor Zhdan       }
1114c66d25d1SEgor Zhdan     }
11154d5f81caSEgor Zhdan 
1116b8169771SEgor Zhdan     if (auto Field = dyn_cast<FieldDecl>(D)) {
1117b8169771SEgor Zhdan       if (!Field->isUnnamedBitField() && !Field->isAnonymousStructOrUnion()) {
1118b8169771SEgor Zhdan         for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
1119b8169771SEgor Zhdan           if (auto Context = UnwindTagContext(TagContext, APINotes)) {
1120b8169771SEgor Zhdan             auto Info = Reader->lookupField(Context->id, Field->getName());
1121b8169771SEgor Zhdan             ProcessVersionedAPINotes(*this, Field, Info);
1122b8169771SEgor Zhdan           }
1123b8169771SEgor Zhdan         }
1124b8169771SEgor Zhdan       }
1125b8169771SEgor Zhdan     }
1126b8169771SEgor Zhdan 
11274d5f81caSEgor Zhdan     if (auto Tag = dyn_cast<TagDecl>(D)) {
11284d5f81caSEgor Zhdan       for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
11294d5f81caSEgor Zhdan         if (auto Context = UnwindTagContext(TagContext, APINotes)) {
11304d5f81caSEgor Zhdan           auto Info = Reader->lookupTag(Tag->getName(), Context);
11314d5f81caSEgor Zhdan           ProcessVersionedAPINotes(*this, Tag, Info);
11324d5f81caSEgor Zhdan         }
11334d5f81caSEgor Zhdan       }
11344d5f81caSEgor Zhdan     }
11358a79dc7eSEgor Zhdan   }
1136440b1743SEgor Zhdan }
1137