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