xref: /openbsd-src/gnu/llvm/clang/lib/AST/DeclObjC.cpp (revision 12c855180aad702bbcca06e0398d774beeafb155)
1e5dd7070Spatrick //===- DeclObjC.cpp - ObjC Declaration AST Node Implementation ------------===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick //
9e5dd7070Spatrick // This file implements the Objective-C related Decl classes.
10e5dd7070Spatrick //
11e5dd7070Spatrick //===----------------------------------------------------------------------===//
12e5dd7070Spatrick 
13e5dd7070Spatrick #include "clang/AST/DeclObjC.h"
14e5dd7070Spatrick #include "clang/AST/ASTContext.h"
15e5dd7070Spatrick #include "clang/AST/ASTMutationListener.h"
16e5dd7070Spatrick #include "clang/AST/Attr.h"
17e5dd7070Spatrick #include "clang/AST/Decl.h"
18e5dd7070Spatrick #include "clang/AST/DeclBase.h"
19*12c85518Srobert #include "clang/AST/ODRHash.h"
20e5dd7070Spatrick #include "clang/AST/Stmt.h"
21e5dd7070Spatrick #include "clang/AST/Type.h"
22e5dd7070Spatrick #include "clang/AST/TypeLoc.h"
23e5dd7070Spatrick #include "clang/Basic/IdentifierTable.h"
24e5dd7070Spatrick #include "clang/Basic/LLVM.h"
25e5dd7070Spatrick #include "clang/Basic/LangOptions.h"
26e5dd7070Spatrick #include "clang/Basic/SourceLocation.h"
27e5dd7070Spatrick #include "llvm/ADT/SmallString.h"
28e5dd7070Spatrick #include "llvm/ADT/SmallVector.h"
29e5dd7070Spatrick #include "llvm/Support/Casting.h"
30e5dd7070Spatrick #include "llvm/Support/ErrorHandling.h"
31e5dd7070Spatrick #include "llvm/Support/raw_ostream.h"
32e5dd7070Spatrick #include <algorithm>
33e5dd7070Spatrick #include <cassert>
34e5dd7070Spatrick #include <cstdint>
35e5dd7070Spatrick #include <cstring>
36a9ac8606Spatrick #include <queue>
37e5dd7070Spatrick #include <utility>
38e5dd7070Spatrick 
39e5dd7070Spatrick using namespace clang;
40e5dd7070Spatrick 
41e5dd7070Spatrick //===----------------------------------------------------------------------===//
42e5dd7070Spatrick // ObjCListBase
43e5dd7070Spatrick //===----------------------------------------------------------------------===//
44e5dd7070Spatrick 
set(void * const * InList,unsigned Elts,ASTContext & Ctx)45e5dd7070Spatrick void ObjCListBase::set(void *const* InList, unsigned Elts, ASTContext &Ctx) {
46e5dd7070Spatrick   List = nullptr;
47e5dd7070Spatrick   if (Elts == 0) return;  // Setting to an empty list is a noop.
48e5dd7070Spatrick 
49e5dd7070Spatrick   List = new (Ctx) void*[Elts];
50e5dd7070Spatrick   NumElts = Elts;
51e5dd7070Spatrick   memcpy(List, InList, sizeof(void*)*Elts);
52e5dd7070Spatrick }
53e5dd7070Spatrick 
set(ObjCProtocolDecl * const * InList,unsigned Elts,const SourceLocation * Locs,ASTContext & Ctx)54e5dd7070Spatrick void ObjCProtocolList::set(ObjCProtocolDecl* const* InList, unsigned Elts,
55e5dd7070Spatrick                            const SourceLocation *Locs, ASTContext &Ctx) {
56e5dd7070Spatrick   if (Elts == 0)
57e5dd7070Spatrick     return;
58e5dd7070Spatrick 
59e5dd7070Spatrick   Locations = new (Ctx) SourceLocation[Elts];
60e5dd7070Spatrick   memcpy(Locations, Locs, sizeof(SourceLocation) * Elts);
61e5dd7070Spatrick   set(InList, Elts, Ctx);
62e5dd7070Spatrick }
63e5dd7070Spatrick 
64e5dd7070Spatrick //===----------------------------------------------------------------------===//
65e5dd7070Spatrick // ObjCInterfaceDecl
66e5dd7070Spatrick //===----------------------------------------------------------------------===//
67e5dd7070Spatrick 
ObjCContainerDecl(Kind DK,DeclContext * DC,IdentifierInfo * Id,SourceLocation nameLoc,SourceLocation atStartLoc)68e5dd7070Spatrick ObjCContainerDecl::ObjCContainerDecl(Kind DK, DeclContext *DC,
69e5dd7070Spatrick                                      IdentifierInfo *Id, SourceLocation nameLoc,
70e5dd7070Spatrick                                      SourceLocation atStartLoc)
71e5dd7070Spatrick     : NamedDecl(DK, DC, nameLoc, Id), DeclContext(DK) {
72e5dd7070Spatrick   setAtStartLoc(atStartLoc);
73e5dd7070Spatrick }
74e5dd7070Spatrick 
anchor()75e5dd7070Spatrick void ObjCContainerDecl::anchor() {}
76e5dd7070Spatrick 
77e5dd7070Spatrick /// getIvarDecl - This method looks up an ivar in this ContextDecl.
78e5dd7070Spatrick ///
79e5dd7070Spatrick ObjCIvarDecl *
getIvarDecl(IdentifierInfo * Id) const80e5dd7070Spatrick ObjCContainerDecl::getIvarDecl(IdentifierInfo *Id) const {
81e5dd7070Spatrick   lookup_result R = lookup(Id);
82e5dd7070Spatrick   for (lookup_iterator Ivar = R.begin(), IvarEnd = R.end();
83e5dd7070Spatrick        Ivar != IvarEnd; ++Ivar) {
84e5dd7070Spatrick     if (auto *ivar = dyn_cast<ObjCIvarDecl>(*Ivar))
85e5dd7070Spatrick       return ivar;
86e5dd7070Spatrick   }
87e5dd7070Spatrick   return nullptr;
88e5dd7070Spatrick }
89e5dd7070Spatrick 
90e5dd7070Spatrick // Get the local instance/class method declared in this interface.
91e5dd7070Spatrick ObjCMethodDecl *
getMethod(Selector Sel,bool isInstance,bool AllowHidden) const92e5dd7070Spatrick ObjCContainerDecl::getMethod(Selector Sel, bool isInstance,
93e5dd7070Spatrick                              bool AllowHidden) const {
94e5dd7070Spatrick   // If this context is a hidden protocol definition, don't find any
95e5dd7070Spatrick   // methods there.
96e5dd7070Spatrick   if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(this)) {
97e5dd7070Spatrick     if (const ObjCProtocolDecl *Def = Proto->getDefinition())
98ec727ea7Spatrick       if (!Def->isUnconditionallyVisible() && !AllowHidden)
99e5dd7070Spatrick         return nullptr;
100e5dd7070Spatrick   }
101e5dd7070Spatrick 
102e5dd7070Spatrick   // Since instance & class methods can have the same name, the loop below
103e5dd7070Spatrick   // ensures we get the correct method.
104e5dd7070Spatrick   //
105e5dd7070Spatrick   // @interface Whatever
106e5dd7070Spatrick   // - (int) class_method;
107e5dd7070Spatrick   // + (float) class_method;
108e5dd7070Spatrick   // @end
109e5dd7070Spatrick   lookup_result R = lookup(Sel);
110e5dd7070Spatrick   for (lookup_iterator Meth = R.begin(), MethEnd = R.end();
111e5dd7070Spatrick        Meth != MethEnd; ++Meth) {
112e5dd7070Spatrick     auto *MD = dyn_cast<ObjCMethodDecl>(*Meth);
113e5dd7070Spatrick     if (MD && MD->isInstanceMethod() == isInstance)
114e5dd7070Spatrick       return MD;
115e5dd7070Spatrick   }
116e5dd7070Spatrick   return nullptr;
117e5dd7070Spatrick }
118e5dd7070Spatrick 
119e5dd7070Spatrick /// This routine returns 'true' if a user declared setter method was
120e5dd7070Spatrick /// found in the class, its protocols, its super classes or categories.
121e5dd7070Spatrick /// It also returns 'true' if one of its categories has declared a 'readwrite'
122e5dd7070Spatrick /// property.  This is because, user must provide a setter method for the
123e5dd7070Spatrick /// category's 'readwrite' property.
HasUserDeclaredSetterMethod(const ObjCPropertyDecl * Property) const124e5dd7070Spatrick bool ObjCContainerDecl::HasUserDeclaredSetterMethod(
125e5dd7070Spatrick     const ObjCPropertyDecl *Property) const {
126e5dd7070Spatrick   Selector Sel = Property->getSetterName();
127e5dd7070Spatrick   lookup_result R = lookup(Sel);
128e5dd7070Spatrick   for (lookup_iterator Meth = R.begin(), MethEnd = R.end();
129e5dd7070Spatrick        Meth != MethEnd; ++Meth) {
130e5dd7070Spatrick     auto *MD = dyn_cast<ObjCMethodDecl>(*Meth);
131e5dd7070Spatrick     if (MD && MD->isInstanceMethod() && !MD->isImplicit())
132e5dd7070Spatrick       return true;
133e5dd7070Spatrick   }
134e5dd7070Spatrick 
135e5dd7070Spatrick   if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(this)) {
136e5dd7070Spatrick     // Also look into categories, including class extensions, looking
137e5dd7070Spatrick     // for a user declared instance method.
138e5dd7070Spatrick     for (const auto *Cat : ID->visible_categories()) {
139e5dd7070Spatrick       if (ObjCMethodDecl *MD = Cat->getInstanceMethod(Sel))
140e5dd7070Spatrick         if (!MD->isImplicit())
141e5dd7070Spatrick           return true;
142e5dd7070Spatrick       if (Cat->IsClassExtension())
143e5dd7070Spatrick         continue;
144e5dd7070Spatrick       // Also search through the categories looking for a 'readwrite'
145e5dd7070Spatrick       // declaration of this property. If one found, presumably a setter will
146e5dd7070Spatrick       // be provided (properties declared in categories will not get
147e5dd7070Spatrick       // auto-synthesized).
148e5dd7070Spatrick       for (const auto *P : Cat->properties())
149e5dd7070Spatrick         if (P->getIdentifier() == Property->getIdentifier()) {
150ec727ea7Spatrick           if (P->getPropertyAttributes() &
151ec727ea7Spatrick               ObjCPropertyAttribute::kind_readwrite)
152e5dd7070Spatrick             return true;
153e5dd7070Spatrick           break;
154e5dd7070Spatrick         }
155e5dd7070Spatrick     }
156e5dd7070Spatrick 
157e5dd7070Spatrick     // Also look into protocols, for a user declared instance method.
158e5dd7070Spatrick     for (const auto *Proto : ID->all_referenced_protocols())
159e5dd7070Spatrick       if (Proto->HasUserDeclaredSetterMethod(Property))
160e5dd7070Spatrick         return true;
161e5dd7070Spatrick 
162e5dd7070Spatrick     // And in its super class.
163e5dd7070Spatrick     ObjCInterfaceDecl *OSC = ID->getSuperClass();
164e5dd7070Spatrick     while (OSC) {
165e5dd7070Spatrick       if (OSC->HasUserDeclaredSetterMethod(Property))
166e5dd7070Spatrick         return true;
167e5dd7070Spatrick       OSC = OSC->getSuperClass();
168e5dd7070Spatrick     }
169e5dd7070Spatrick   }
170e5dd7070Spatrick   if (const auto *PD = dyn_cast<ObjCProtocolDecl>(this))
171e5dd7070Spatrick     for (const auto *PI : PD->protocols())
172e5dd7070Spatrick       if (PI->HasUserDeclaredSetterMethod(Property))
173e5dd7070Spatrick         return true;
174e5dd7070Spatrick   return false;
175e5dd7070Spatrick }
176e5dd7070Spatrick 
177e5dd7070Spatrick ObjCPropertyDecl *
findPropertyDecl(const DeclContext * DC,const IdentifierInfo * propertyID,ObjCPropertyQueryKind queryKind)178e5dd7070Spatrick ObjCPropertyDecl::findPropertyDecl(const DeclContext *DC,
179e5dd7070Spatrick                                    const IdentifierInfo *propertyID,
180e5dd7070Spatrick                                    ObjCPropertyQueryKind queryKind) {
181e5dd7070Spatrick   // If this context is a hidden protocol definition, don't find any
182e5dd7070Spatrick   // property.
183e5dd7070Spatrick   if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(DC)) {
184e5dd7070Spatrick     if (const ObjCProtocolDecl *Def = Proto->getDefinition())
185ec727ea7Spatrick       if (!Def->isUnconditionallyVisible())
186e5dd7070Spatrick         return nullptr;
187e5dd7070Spatrick   }
188e5dd7070Spatrick 
189e5dd7070Spatrick   // If context is class, then lookup property in its visible extensions.
190e5dd7070Spatrick   // This comes before property is looked up in primary class.
191e5dd7070Spatrick   if (auto *IDecl = dyn_cast<ObjCInterfaceDecl>(DC)) {
192e5dd7070Spatrick     for (const auto *Ext : IDecl->visible_extensions())
193e5dd7070Spatrick       if (ObjCPropertyDecl *PD = ObjCPropertyDecl::findPropertyDecl(Ext,
194e5dd7070Spatrick                                                        propertyID,
195e5dd7070Spatrick                                                        queryKind))
196e5dd7070Spatrick         return PD;
197e5dd7070Spatrick   }
198e5dd7070Spatrick 
199e5dd7070Spatrick   DeclContext::lookup_result R = DC->lookup(propertyID);
200e5dd7070Spatrick   ObjCPropertyDecl *classProp = nullptr;
201e5dd7070Spatrick   for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E;
202e5dd7070Spatrick        ++I)
203e5dd7070Spatrick     if (auto *PD = dyn_cast<ObjCPropertyDecl>(*I)) {
204e5dd7070Spatrick       // If queryKind is unknown, we return the instance property if one
205e5dd7070Spatrick       // exists; otherwise we return the class property.
206e5dd7070Spatrick       if ((queryKind == ObjCPropertyQueryKind::OBJC_PR_query_unknown &&
207e5dd7070Spatrick            !PD->isClassProperty()) ||
208e5dd7070Spatrick           (queryKind == ObjCPropertyQueryKind::OBJC_PR_query_class &&
209e5dd7070Spatrick            PD->isClassProperty()) ||
210e5dd7070Spatrick           (queryKind == ObjCPropertyQueryKind::OBJC_PR_query_instance &&
211e5dd7070Spatrick            !PD->isClassProperty()))
212e5dd7070Spatrick         return PD;
213e5dd7070Spatrick 
214e5dd7070Spatrick       if (PD->isClassProperty())
215e5dd7070Spatrick         classProp = PD;
216e5dd7070Spatrick     }
217e5dd7070Spatrick 
218e5dd7070Spatrick   if (queryKind == ObjCPropertyQueryKind::OBJC_PR_query_unknown)
219e5dd7070Spatrick     // We can't find the instance property, return the class property.
220e5dd7070Spatrick     return classProp;
221e5dd7070Spatrick 
222e5dd7070Spatrick   return nullptr;
223e5dd7070Spatrick }
224e5dd7070Spatrick 
225e5dd7070Spatrick IdentifierInfo *
getDefaultSynthIvarName(ASTContext & Ctx) const226e5dd7070Spatrick ObjCPropertyDecl::getDefaultSynthIvarName(ASTContext &Ctx) const {
227e5dd7070Spatrick   SmallString<128> ivarName;
228e5dd7070Spatrick   {
229e5dd7070Spatrick     llvm::raw_svector_ostream os(ivarName);
230e5dd7070Spatrick     os << '_' << getIdentifier()->getName();
231e5dd7070Spatrick   }
232e5dd7070Spatrick   return &Ctx.Idents.get(ivarName.str());
233e5dd7070Spatrick }
234e5dd7070Spatrick 
getProperty(const IdentifierInfo * Id,bool IsInstance) const235*12c85518Srobert ObjCPropertyDecl *ObjCContainerDecl::getProperty(const IdentifierInfo *Id,
236*12c85518Srobert                                                  bool IsInstance) const {
237*12c85518Srobert   for (auto *LookupResult : lookup(Id)) {
238*12c85518Srobert     if (auto *Prop = dyn_cast<ObjCPropertyDecl>(LookupResult)) {
239*12c85518Srobert       if (Prop->isInstanceProperty() == IsInstance) {
240*12c85518Srobert         return Prop;
241*12c85518Srobert       }
242*12c85518Srobert     }
243*12c85518Srobert   }
244*12c85518Srobert   return nullptr;
245*12c85518Srobert }
246*12c85518Srobert 
247e5dd7070Spatrick /// FindPropertyDeclaration - Finds declaration of the property given its name
248e5dd7070Spatrick /// in 'PropertyId' and returns it. It returns 0, if not found.
FindPropertyDeclaration(const IdentifierInfo * PropertyId,ObjCPropertyQueryKind QueryKind) const249e5dd7070Spatrick ObjCPropertyDecl *ObjCContainerDecl::FindPropertyDeclaration(
250e5dd7070Spatrick     const IdentifierInfo *PropertyId,
251e5dd7070Spatrick     ObjCPropertyQueryKind QueryKind) const {
252e5dd7070Spatrick   // Don't find properties within hidden protocol definitions.
253e5dd7070Spatrick   if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(this)) {
254e5dd7070Spatrick     if (const ObjCProtocolDecl *Def = Proto->getDefinition())
255ec727ea7Spatrick       if (!Def->isUnconditionallyVisible())
256e5dd7070Spatrick         return nullptr;
257e5dd7070Spatrick   }
258e5dd7070Spatrick 
259e5dd7070Spatrick   // Search the extensions of a class first; they override what's in
260e5dd7070Spatrick   // the class itself.
261e5dd7070Spatrick   if (const auto *ClassDecl = dyn_cast<ObjCInterfaceDecl>(this)) {
262e5dd7070Spatrick     for (const auto *Ext : ClassDecl->visible_extensions()) {
263e5dd7070Spatrick       if (auto *P = Ext->FindPropertyDeclaration(PropertyId, QueryKind))
264e5dd7070Spatrick         return P;
265e5dd7070Spatrick     }
266e5dd7070Spatrick   }
267e5dd7070Spatrick 
268e5dd7070Spatrick   if (ObjCPropertyDecl *PD =
269e5dd7070Spatrick         ObjCPropertyDecl::findPropertyDecl(cast<DeclContext>(this), PropertyId,
270e5dd7070Spatrick                                            QueryKind))
271e5dd7070Spatrick     return PD;
272e5dd7070Spatrick 
273e5dd7070Spatrick   switch (getKind()) {
274e5dd7070Spatrick     default:
275e5dd7070Spatrick       break;
276e5dd7070Spatrick     case Decl::ObjCProtocol: {
277e5dd7070Spatrick       const auto *PID = cast<ObjCProtocolDecl>(this);
278e5dd7070Spatrick       for (const auto *I : PID->protocols())
279e5dd7070Spatrick         if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId,
280e5dd7070Spatrick                                                              QueryKind))
281e5dd7070Spatrick           return P;
282e5dd7070Spatrick       break;
283e5dd7070Spatrick     }
284e5dd7070Spatrick     case Decl::ObjCInterface: {
285e5dd7070Spatrick       const auto *OID = cast<ObjCInterfaceDecl>(this);
286e5dd7070Spatrick       // Look through categories (but not extensions; they were handled above).
287e5dd7070Spatrick       for (const auto *Cat : OID->visible_categories()) {
288e5dd7070Spatrick         if (!Cat->IsClassExtension())
289e5dd7070Spatrick           if (ObjCPropertyDecl *P = Cat->FindPropertyDeclaration(
290e5dd7070Spatrick                                              PropertyId, QueryKind))
291e5dd7070Spatrick             return P;
292e5dd7070Spatrick       }
293e5dd7070Spatrick 
294e5dd7070Spatrick       // Look through protocols.
295e5dd7070Spatrick       for (const auto *I : OID->all_referenced_protocols())
296e5dd7070Spatrick         if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId,
297e5dd7070Spatrick                                                              QueryKind))
298e5dd7070Spatrick           return P;
299e5dd7070Spatrick 
300e5dd7070Spatrick       // Finally, check the super class.
301e5dd7070Spatrick       if (const ObjCInterfaceDecl *superClass = OID->getSuperClass())
302e5dd7070Spatrick         return superClass->FindPropertyDeclaration(PropertyId, QueryKind);
303e5dd7070Spatrick       break;
304e5dd7070Spatrick     }
305e5dd7070Spatrick     case Decl::ObjCCategory: {
306e5dd7070Spatrick       const auto *OCD = cast<ObjCCategoryDecl>(this);
307e5dd7070Spatrick       // Look through protocols.
308e5dd7070Spatrick       if (!OCD->IsClassExtension())
309e5dd7070Spatrick         for (const auto *I : OCD->protocols())
310e5dd7070Spatrick           if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId,
311e5dd7070Spatrick                                                                QueryKind))
312e5dd7070Spatrick             return P;
313e5dd7070Spatrick       break;
314e5dd7070Spatrick     }
315e5dd7070Spatrick   }
316e5dd7070Spatrick   return nullptr;
317e5dd7070Spatrick }
318e5dd7070Spatrick 
anchor()319e5dd7070Spatrick void ObjCInterfaceDecl::anchor() {}
320e5dd7070Spatrick 
getTypeParamList() const321e5dd7070Spatrick ObjCTypeParamList *ObjCInterfaceDecl::getTypeParamList() const {
322e5dd7070Spatrick   // If this particular declaration has a type parameter list, return it.
323e5dd7070Spatrick   if (ObjCTypeParamList *written = getTypeParamListAsWritten())
324e5dd7070Spatrick     return written;
325e5dd7070Spatrick 
326e5dd7070Spatrick   // If there is a definition, return its type parameter list.
327e5dd7070Spatrick   if (const ObjCInterfaceDecl *def = getDefinition())
328e5dd7070Spatrick     return def->getTypeParamListAsWritten();
329e5dd7070Spatrick 
330e5dd7070Spatrick   // Otherwise, look at previous declarations to determine whether any
331e5dd7070Spatrick   // of them has a type parameter list, skipping over those
332e5dd7070Spatrick   // declarations that do not.
333e5dd7070Spatrick   for (const ObjCInterfaceDecl *decl = getMostRecentDecl(); decl;
334e5dd7070Spatrick        decl = decl->getPreviousDecl()) {
335e5dd7070Spatrick     if (ObjCTypeParamList *written = decl->getTypeParamListAsWritten())
336e5dd7070Spatrick       return written;
337e5dd7070Spatrick   }
338e5dd7070Spatrick 
339e5dd7070Spatrick   return nullptr;
340e5dd7070Spatrick }
341e5dd7070Spatrick 
setTypeParamList(ObjCTypeParamList * TPL)342e5dd7070Spatrick void ObjCInterfaceDecl::setTypeParamList(ObjCTypeParamList *TPL) {
343e5dd7070Spatrick   TypeParamList = TPL;
344e5dd7070Spatrick   if (!TPL)
345e5dd7070Spatrick     return;
346e5dd7070Spatrick   // Set the declaration context of each of the type parameters.
347e5dd7070Spatrick   for (auto *typeParam : *TypeParamList)
348e5dd7070Spatrick     typeParam->setDeclContext(this);
349e5dd7070Spatrick }
350e5dd7070Spatrick 
getSuperClass() const351e5dd7070Spatrick ObjCInterfaceDecl *ObjCInterfaceDecl::getSuperClass() const {
352e5dd7070Spatrick   // FIXME: Should make sure no callers ever do this.
353e5dd7070Spatrick   if (!hasDefinition())
354e5dd7070Spatrick     return nullptr;
355e5dd7070Spatrick 
356e5dd7070Spatrick   if (data().ExternallyCompleted)
357e5dd7070Spatrick     LoadExternalDefinition();
358e5dd7070Spatrick 
359e5dd7070Spatrick   if (const ObjCObjectType *superType = getSuperClassType()) {
360e5dd7070Spatrick     if (ObjCInterfaceDecl *superDecl = superType->getInterface()) {
361e5dd7070Spatrick       if (ObjCInterfaceDecl *superDef = superDecl->getDefinition())
362e5dd7070Spatrick         return superDef;
363e5dd7070Spatrick 
364e5dd7070Spatrick       return superDecl;
365e5dd7070Spatrick     }
366e5dd7070Spatrick   }
367e5dd7070Spatrick 
368e5dd7070Spatrick   return nullptr;
369e5dd7070Spatrick }
370e5dd7070Spatrick 
getSuperClassLoc() const371e5dd7070Spatrick SourceLocation ObjCInterfaceDecl::getSuperClassLoc() const {
372e5dd7070Spatrick   if (TypeSourceInfo *superTInfo = getSuperClassTInfo())
373e5dd7070Spatrick     return superTInfo->getTypeLoc().getBeginLoc();
374e5dd7070Spatrick 
375e5dd7070Spatrick   return SourceLocation();
376e5dd7070Spatrick }
377e5dd7070Spatrick 
378e5dd7070Spatrick /// FindPropertyVisibleInPrimaryClass - Finds declaration of the property
379e5dd7070Spatrick /// with name 'PropertyId' in the primary class; including those in protocols
380e5dd7070Spatrick /// (direct or indirect) used by the primary class.
381e5dd7070Spatrick ObjCPropertyDecl *
FindPropertyVisibleInPrimaryClass(IdentifierInfo * PropertyId,ObjCPropertyQueryKind QueryKind) const382e5dd7070Spatrick ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass(
383e5dd7070Spatrick                        IdentifierInfo *PropertyId,
384e5dd7070Spatrick                        ObjCPropertyQueryKind QueryKind) const {
385e5dd7070Spatrick   // FIXME: Should make sure no callers ever do this.
386e5dd7070Spatrick   if (!hasDefinition())
387e5dd7070Spatrick     return nullptr;
388e5dd7070Spatrick 
389e5dd7070Spatrick   if (data().ExternallyCompleted)
390e5dd7070Spatrick     LoadExternalDefinition();
391e5dd7070Spatrick 
392e5dd7070Spatrick   if (ObjCPropertyDecl *PD =
393e5dd7070Spatrick       ObjCPropertyDecl::findPropertyDecl(cast<DeclContext>(this), PropertyId,
394e5dd7070Spatrick                                          QueryKind))
395e5dd7070Spatrick     return PD;
396e5dd7070Spatrick 
397e5dd7070Spatrick   // Look through protocols.
398e5dd7070Spatrick   for (const auto *I : all_referenced_protocols())
399e5dd7070Spatrick     if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId,
400e5dd7070Spatrick                                                          QueryKind))
401e5dd7070Spatrick       return P;
402e5dd7070Spatrick 
403e5dd7070Spatrick   return nullptr;
404e5dd7070Spatrick }
405e5dd7070Spatrick 
collectPropertiesToImplement(PropertyMap & PM) const406*12c85518Srobert void ObjCInterfaceDecl::collectPropertiesToImplement(PropertyMap &PM) const {
407e5dd7070Spatrick   for (auto *Prop : properties()) {
408e5dd7070Spatrick     PM[std::make_pair(Prop->getIdentifier(), Prop->isClassProperty())] = Prop;
409e5dd7070Spatrick   }
410e5dd7070Spatrick   for (const auto *Ext : known_extensions()) {
411e5dd7070Spatrick     const ObjCCategoryDecl *ClassExt = Ext;
412e5dd7070Spatrick     for (auto *Prop : ClassExt->properties()) {
413e5dd7070Spatrick       PM[std::make_pair(Prop->getIdentifier(), Prop->isClassProperty())] = Prop;
414e5dd7070Spatrick     }
415e5dd7070Spatrick   }
416e5dd7070Spatrick   for (const auto *PI : all_referenced_protocols())
417*12c85518Srobert     PI->collectPropertiesToImplement(PM);
418e5dd7070Spatrick   // Note, the properties declared only in class extensions are still copied
419e5dd7070Spatrick   // into the main @interface's property list, and therefore we don't
420e5dd7070Spatrick   // explicitly, have to search class extension properties.
421e5dd7070Spatrick }
422e5dd7070Spatrick 
isArcWeakrefUnavailable() const423e5dd7070Spatrick bool ObjCInterfaceDecl::isArcWeakrefUnavailable() const {
424e5dd7070Spatrick   const ObjCInterfaceDecl *Class = this;
425e5dd7070Spatrick   while (Class) {
426e5dd7070Spatrick     if (Class->hasAttr<ArcWeakrefUnavailableAttr>())
427e5dd7070Spatrick       return true;
428e5dd7070Spatrick     Class = Class->getSuperClass();
429e5dd7070Spatrick   }
430e5dd7070Spatrick   return false;
431e5dd7070Spatrick }
432e5dd7070Spatrick 
isObjCRequiresPropertyDefs() const433e5dd7070Spatrick const ObjCInterfaceDecl *ObjCInterfaceDecl::isObjCRequiresPropertyDefs() const {
434e5dd7070Spatrick   const ObjCInterfaceDecl *Class = this;
435e5dd7070Spatrick   while (Class) {
436e5dd7070Spatrick     if (Class->hasAttr<ObjCRequiresPropertyDefsAttr>())
437e5dd7070Spatrick       return Class;
438e5dd7070Spatrick     Class = Class->getSuperClass();
439e5dd7070Spatrick   }
440e5dd7070Spatrick   return nullptr;
441e5dd7070Spatrick }
442e5dd7070Spatrick 
mergeClassExtensionProtocolList(ObjCProtocolDecl * const * ExtList,unsigned ExtNum,ASTContext & C)443e5dd7070Spatrick void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
444e5dd7070Spatrick                               ObjCProtocolDecl *const* ExtList, unsigned ExtNum,
445e5dd7070Spatrick                               ASTContext &C) {
446e5dd7070Spatrick   if (data().ExternallyCompleted)
447e5dd7070Spatrick     LoadExternalDefinition();
448e5dd7070Spatrick 
449e5dd7070Spatrick   if (data().AllReferencedProtocols.empty() &&
450e5dd7070Spatrick       data().ReferencedProtocols.empty()) {
451e5dd7070Spatrick     data().AllReferencedProtocols.set(ExtList, ExtNum, C);
452e5dd7070Spatrick     return;
453e5dd7070Spatrick   }
454e5dd7070Spatrick 
455e5dd7070Spatrick   // Check for duplicate protocol in class's protocol list.
456e5dd7070Spatrick   // This is O(n*m). But it is extremely rare and number of protocols in
457e5dd7070Spatrick   // class or its extension are very few.
458e5dd7070Spatrick   SmallVector<ObjCProtocolDecl *, 8> ProtocolRefs;
459e5dd7070Spatrick   for (unsigned i = 0; i < ExtNum; i++) {
460e5dd7070Spatrick     bool protocolExists = false;
461e5dd7070Spatrick     ObjCProtocolDecl *ProtoInExtension = ExtList[i];
462e5dd7070Spatrick     for (auto *Proto : all_referenced_protocols()) {
463e5dd7070Spatrick       if (C.ProtocolCompatibleWithProtocol(ProtoInExtension, Proto)) {
464e5dd7070Spatrick         protocolExists = true;
465e5dd7070Spatrick         break;
466e5dd7070Spatrick       }
467e5dd7070Spatrick     }
468e5dd7070Spatrick     // Do we want to warn on a protocol in extension class which
469e5dd7070Spatrick     // already exist in the class? Probably not.
470e5dd7070Spatrick     if (!protocolExists)
471e5dd7070Spatrick       ProtocolRefs.push_back(ProtoInExtension);
472e5dd7070Spatrick   }
473e5dd7070Spatrick 
474e5dd7070Spatrick   if (ProtocolRefs.empty())
475e5dd7070Spatrick     return;
476e5dd7070Spatrick 
477e5dd7070Spatrick   // Merge ProtocolRefs into class's protocol list;
478e5dd7070Spatrick   ProtocolRefs.append(all_referenced_protocol_begin(),
479e5dd7070Spatrick                       all_referenced_protocol_end());
480e5dd7070Spatrick 
481e5dd7070Spatrick   data().AllReferencedProtocols.set(ProtocolRefs.data(), ProtocolRefs.size(),C);
482e5dd7070Spatrick }
483e5dd7070Spatrick 
484e5dd7070Spatrick const ObjCInterfaceDecl *
findInterfaceWithDesignatedInitializers() const485e5dd7070Spatrick ObjCInterfaceDecl::findInterfaceWithDesignatedInitializers() const {
486e5dd7070Spatrick   const ObjCInterfaceDecl *IFace = this;
487e5dd7070Spatrick   while (IFace) {
488e5dd7070Spatrick     if (IFace->hasDesignatedInitializers())
489e5dd7070Spatrick       return IFace;
490e5dd7070Spatrick     if (!IFace->inheritsDesignatedInitializers())
491e5dd7070Spatrick       break;
492e5dd7070Spatrick     IFace = IFace->getSuperClass();
493e5dd7070Spatrick   }
494e5dd7070Spatrick   return nullptr;
495e5dd7070Spatrick }
496e5dd7070Spatrick 
isIntroducingInitializers(const ObjCInterfaceDecl * D)497e5dd7070Spatrick static bool isIntroducingInitializers(const ObjCInterfaceDecl *D) {
498e5dd7070Spatrick   for (const auto *MD : D->instance_methods()) {
499e5dd7070Spatrick     if (MD->getMethodFamily() == OMF_init && !MD->isOverriding())
500e5dd7070Spatrick       return true;
501e5dd7070Spatrick   }
502e5dd7070Spatrick   for (const auto *Ext : D->visible_extensions()) {
503e5dd7070Spatrick     for (const auto *MD : Ext->instance_methods()) {
504e5dd7070Spatrick       if (MD->getMethodFamily() == OMF_init && !MD->isOverriding())
505e5dd7070Spatrick         return true;
506e5dd7070Spatrick     }
507e5dd7070Spatrick   }
508e5dd7070Spatrick   if (const auto *ImplD = D->getImplementation()) {
509e5dd7070Spatrick     for (const auto *MD : ImplD->instance_methods()) {
510e5dd7070Spatrick       if (MD->getMethodFamily() == OMF_init && !MD->isOverriding())
511e5dd7070Spatrick         return true;
512e5dd7070Spatrick     }
513e5dd7070Spatrick   }
514e5dd7070Spatrick   return false;
515e5dd7070Spatrick }
516e5dd7070Spatrick 
inheritsDesignatedInitializers() const517e5dd7070Spatrick bool ObjCInterfaceDecl::inheritsDesignatedInitializers() const {
518e5dd7070Spatrick   switch (data().InheritedDesignatedInitializers) {
519e5dd7070Spatrick   case DefinitionData::IDI_Inherited:
520e5dd7070Spatrick     return true;
521e5dd7070Spatrick   case DefinitionData::IDI_NotInherited:
522e5dd7070Spatrick     return false;
523e5dd7070Spatrick   case DefinitionData::IDI_Unknown:
524e5dd7070Spatrick     // If the class introduced initializers we conservatively assume that we
525e5dd7070Spatrick     // don't know if any of them is a designated initializer to avoid possible
526e5dd7070Spatrick     // misleading warnings.
527e5dd7070Spatrick     if (isIntroducingInitializers(this)) {
528e5dd7070Spatrick       data().InheritedDesignatedInitializers = DefinitionData::IDI_NotInherited;
529e5dd7070Spatrick     } else {
530e5dd7070Spatrick       if (auto SuperD = getSuperClass()) {
531e5dd7070Spatrick         data().InheritedDesignatedInitializers =
532e5dd7070Spatrick           SuperD->declaresOrInheritsDesignatedInitializers() ?
533e5dd7070Spatrick             DefinitionData::IDI_Inherited :
534e5dd7070Spatrick             DefinitionData::IDI_NotInherited;
535e5dd7070Spatrick       } else {
536e5dd7070Spatrick         data().InheritedDesignatedInitializers =
537e5dd7070Spatrick           DefinitionData::IDI_NotInherited;
538e5dd7070Spatrick       }
539e5dd7070Spatrick     }
540e5dd7070Spatrick     assert(data().InheritedDesignatedInitializers
541e5dd7070Spatrick              != DefinitionData::IDI_Unknown);
542e5dd7070Spatrick     return data().InheritedDesignatedInitializers ==
543e5dd7070Spatrick         DefinitionData::IDI_Inherited;
544e5dd7070Spatrick   }
545e5dd7070Spatrick 
546e5dd7070Spatrick   llvm_unreachable("unexpected InheritedDesignatedInitializers value");
547e5dd7070Spatrick }
548e5dd7070Spatrick 
getDesignatedInitializers(llvm::SmallVectorImpl<const ObjCMethodDecl * > & Methods) const549e5dd7070Spatrick void ObjCInterfaceDecl::getDesignatedInitializers(
550e5dd7070Spatrick     llvm::SmallVectorImpl<const ObjCMethodDecl *> &Methods) const {
551e5dd7070Spatrick   // Check for a complete definition and recover if not so.
552e5dd7070Spatrick   if (!isThisDeclarationADefinition())
553e5dd7070Spatrick     return;
554e5dd7070Spatrick   if (data().ExternallyCompleted)
555e5dd7070Spatrick     LoadExternalDefinition();
556e5dd7070Spatrick 
557e5dd7070Spatrick   const ObjCInterfaceDecl *IFace= findInterfaceWithDesignatedInitializers();
558e5dd7070Spatrick   if (!IFace)
559e5dd7070Spatrick     return;
560e5dd7070Spatrick 
561e5dd7070Spatrick   for (const auto *MD : IFace->instance_methods())
562e5dd7070Spatrick     if (MD->isThisDeclarationADesignatedInitializer())
563e5dd7070Spatrick       Methods.push_back(MD);
564e5dd7070Spatrick   for (const auto *Ext : IFace->visible_extensions()) {
565e5dd7070Spatrick     for (const auto *MD : Ext->instance_methods())
566e5dd7070Spatrick       if (MD->isThisDeclarationADesignatedInitializer())
567e5dd7070Spatrick         Methods.push_back(MD);
568e5dd7070Spatrick   }
569e5dd7070Spatrick }
570e5dd7070Spatrick 
isDesignatedInitializer(Selector Sel,const ObjCMethodDecl ** InitMethod) const571e5dd7070Spatrick bool ObjCInterfaceDecl::isDesignatedInitializer(Selector Sel,
572e5dd7070Spatrick                                       const ObjCMethodDecl **InitMethod) const {
573e5dd7070Spatrick   bool HasCompleteDef = isThisDeclarationADefinition();
574e5dd7070Spatrick   // During deserialization the data record for the ObjCInterfaceDecl could
575e5dd7070Spatrick   // be made invariant by reusing the canonical decl. Take this into account
576e5dd7070Spatrick   // when checking for the complete definition.
577e5dd7070Spatrick   if (!HasCompleteDef && getCanonicalDecl()->hasDefinition() &&
578e5dd7070Spatrick       getCanonicalDecl()->getDefinition() == getDefinition())
579e5dd7070Spatrick     HasCompleteDef = true;
580e5dd7070Spatrick 
581e5dd7070Spatrick   // Check for a complete definition and recover if not so.
582e5dd7070Spatrick   if (!HasCompleteDef)
583e5dd7070Spatrick     return false;
584e5dd7070Spatrick 
585e5dd7070Spatrick   if (data().ExternallyCompleted)
586e5dd7070Spatrick     LoadExternalDefinition();
587e5dd7070Spatrick 
588e5dd7070Spatrick   const ObjCInterfaceDecl *IFace= findInterfaceWithDesignatedInitializers();
589e5dd7070Spatrick   if (!IFace)
590e5dd7070Spatrick     return false;
591e5dd7070Spatrick 
592e5dd7070Spatrick   if (const ObjCMethodDecl *MD = IFace->getInstanceMethod(Sel)) {
593e5dd7070Spatrick     if (MD->isThisDeclarationADesignatedInitializer()) {
594e5dd7070Spatrick       if (InitMethod)
595e5dd7070Spatrick         *InitMethod = MD;
596e5dd7070Spatrick       return true;
597e5dd7070Spatrick     }
598e5dd7070Spatrick   }
599e5dd7070Spatrick   for (const auto *Ext : IFace->visible_extensions()) {
600e5dd7070Spatrick     if (const ObjCMethodDecl *MD = Ext->getInstanceMethod(Sel)) {
601e5dd7070Spatrick       if (MD->isThisDeclarationADesignatedInitializer()) {
602e5dd7070Spatrick         if (InitMethod)
603e5dd7070Spatrick           *InitMethod = MD;
604e5dd7070Spatrick         return true;
605e5dd7070Spatrick       }
606e5dd7070Spatrick     }
607e5dd7070Spatrick   }
608e5dd7070Spatrick   return false;
609e5dd7070Spatrick }
610e5dd7070Spatrick 
allocateDefinitionData()611e5dd7070Spatrick void ObjCInterfaceDecl::allocateDefinitionData() {
612e5dd7070Spatrick   assert(!hasDefinition() && "ObjC class already has a definition");
613e5dd7070Spatrick   Data.setPointer(new (getASTContext()) DefinitionData());
614e5dd7070Spatrick   Data.getPointer()->Definition = this;
615e5dd7070Spatrick }
616e5dd7070Spatrick 
startDefinition()617e5dd7070Spatrick void ObjCInterfaceDecl::startDefinition() {
618e5dd7070Spatrick   allocateDefinitionData();
619e5dd7070Spatrick 
620e5dd7070Spatrick   // Update all of the declarations with a pointer to the definition.
621e5dd7070Spatrick   for (auto *RD : redecls()) {
622e5dd7070Spatrick     if (RD != this)
623e5dd7070Spatrick       RD->Data = Data;
624e5dd7070Spatrick   }
625e5dd7070Spatrick }
626e5dd7070Spatrick 
startDuplicateDefinitionForComparison()627*12c85518Srobert void ObjCInterfaceDecl::startDuplicateDefinitionForComparison() {
628*12c85518Srobert   Data.setPointer(nullptr);
629*12c85518Srobert   allocateDefinitionData();
630*12c85518Srobert   // Don't propagate data to other redeclarations.
631*12c85518Srobert }
632*12c85518Srobert 
mergeDuplicateDefinitionWithCommon(const ObjCInterfaceDecl * Definition)633*12c85518Srobert void ObjCInterfaceDecl::mergeDuplicateDefinitionWithCommon(
634*12c85518Srobert     const ObjCInterfaceDecl *Definition) {
635*12c85518Srobert   Data = Definition->Data;
636*12c85518Srobert }
637*12c85518Srobert 
lookupInstanceVariable(IdentifierInfo * ID,ObjCInterfaceDecl * & clsDeclared)638e5dd7070Spatrick ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(IdentifierInfo *ID,
639e5dd7070Spatrick                                               ObjCInterfaceDecl *&clsDeclared) {
640e5dd7070Spatrick   // FIXME: Should make sure no callers ever do this.
641e5dd7070Spatrick   if (!hasDefinition())
642e5dd7070Spatrick     return nullptr;
643e5dd7070Spatrick 
644e5dd7070Spatrick   if (data().ExternallyCompleted)
645e5dd7070Spatrick     LoadExternalDefinition();
646e5dd7070Spatrick 
647e5dd7070Spatrick   ObjCInterfaceDecl* ClassDecl = this;
648e5dd7070Spatrick   while (ClassDecl != nullptr) {
649e5dd7070Spatrick     if (ObjCIvarDecl *I = ClassDecl->getIvarDecl(ID)) {
650e5dd7070Spatrick       clsDeclared = ClassDecl;
651e5dd7070Spatrick       return I;
652e5dd7070Spatrick     }
653e5dd7070Spatrick 
654e5dd7070Spatrick     for (const auto *Ext : ClassDecl->visible_extensions()) {
655e5dd7070Spatrick       if (ObjCIvarDecl *I = Ext->getIvarDecl(ID)) {
656e5dd7070Spatrick         clsDeclared = ClassDecl;
657e5dd7070Spatrick         return I;
658e5dd7070Spatrick       }
659e5dd7070Spatrick     }
660e5dd7070Spatrick 
661e5dd7070Spatrick     ClassDecl = ClassDecl->getSuperClass();
662e5dd7070Spatrick   }
663e5dd7070Spatrick   return nullptr;
664e5dd7070Spatrick }
665e5dd7070Spatrick 
666e5dd7070Spatrick /// lookupInheritedClass - This method returns ObjCInterfaceDecl * of the super
667e5dd7070Spatrick /// class whose name is passed as argument. If it is not one of the super classes
668e5dd7070Spatrick /// the it returns NULL.
lookupInheritedClass(const IdentifierInfo * ICName)669e5dd7070Spatrick ObjCInterfaceDecl *ObjCInterfaceDecl::lookupInheritedClass(
670e5dd7070Spatrick                                         const IdentifierInfo*ICName) {
671e5dd7070Spatrick   // FIXME: Should make sure no callers ever do this.
672e5dd7070Spatrick   if (!hasDefinition())
673e5dd7070Spatrick     return nullptr;
674e5dd7070Spatrick 
675e5dd7070Spatrick   if (data().ExternallyCompleted)
676e5dd7070Spatrick     LoadExternalDefinition();
677e5dd7070Spatrick 
678e5dd7070Spatrick   ObjCInterfaceDecl* ClassDecl = this;
679e5dd7070Spatrick   while (ClassDecl != nullptr) {
680e5dd7070Spatrick     if (ClassDecl->getIdentifier() == ICName)
681e5dd7070Spatrick       return ClassDecl;
682e5dd7070Spatrick     ClassDecl = ClassDecl->getSuperClass();
683e5dd7070Spatrick   }
684e5dd7070Spatrick   return nullptr;
685e5dd7070Spatrick }
686e5dd7070Spatrick 
687e5dd7070Spatrick ObjCProtocolDecl *
lookupNestedProtocol(IdentifierInfo * Name)688e5dd7070Spatrick ObjCInterfaceDecl::lookupNestedProtocol(IdentifierInfo *Name) {
689e5dd7070Spatrick   for (auto *P : all_referenced_protocols())
690e5dd7070Spatrick     if (P->lookupProtocolNamed(Name))
691e5dd7070Spatrick       return P;
692e5dd7070Spatrick   ObjCInterfaceDecl *SuperClass = getSuperClass();
693e5dd7070Spatrick   return SuperClass ? SuperClass->lookupNestedProtocol(Name) : nullptr;
694e5dd7070Spatrick }
695e5dd7070Spatrick 
696e5dd7070Spatrick /// lookupMethod - This method returns an instance/class method by looking in
697e5dd7070Spatrick /// the class, its categories, and its super classes (using a linear search).
698e5dd7070Spatrick /// When argument category "C" is specified, any implicit method found
699e5dd7070Spatrick /// in this category is ignored.
lookupMethod(Selector Sel,bool isInstance,bool shallowCategoryLookup,bool followSuper,const ObjCCategoryDecl * C) const700e5dd7070Spatrick ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel,
701e5dd7070Spatrick                                                 bool isInstance,
702e5dd7070Spatrick                                                 bool shallowCategoryLookup,
703e5dd7070Spatrick                                                 bool followSuper,
704e5dd7070Spatrick                                                 const ObjCCategoryDecl *C) const
705e5dd7070Spatrick {
706e5dd7070Spatrick   // FIXME: Should make sure no callers ever do this.
707e5dd7070Spatrick   if (!hasDefinition())
708e5dd7070Spatrick     return nullptr;
709e5dd7070Spatrick 
710e5dd7070Spatrick   const ObjCInterfaceDecl* ClassDecl = this;
711e5dd7070Spatrick   ObjCMethodDecl *MethodDecl = nullptr;
712e5dd7070Spatrick 
713e5dd7070Spatrick   if (data().ExternallyCompleted)
714e5dd7070Spatrick     LoadExternalDefinition();
715e5dd7070Spatrick 
716e5dd7070Spatrick   while (ClassDecl) {
717e5dd7070Spatrick     // 1. Look through primary class.
718e5dd7070Spatrick     if ((MethodDecl = ClassDecl->getMethod(Sel, isInstance)))
719e5dd7070Spatrick       return MethodDecl;
720e5dd7070Spatrick 
721e5dd7070Spatrick     // 2. Didn't find one yet - now look through categories.
722e5dd7070Spatrick     for (const auto *Cat : ClassDecl->visible_categories())
723e5dd7070Spatrick       if ((MethodDecl = Cat->getMethod(Sel, isInstance)))
724e5dd7070Spatrick         if (C != Cat || !MethodDecl->isImplicit())
725e5dd7070Spatrick           return MethodDecl;
726e5dd7070Spatrick 
727e5dd7070Spatrick     // 3. Didn't find one yet - look through primary class's protocols.
728e5dd7070Spatrick     for (const auto *I : ClassDecl->protocols())
729e5dd7070Spatrick       if ((MethodDecl = I->lookupMethod(Sel, isInstance)))
730e5dd7070Spatrick         return MethodDecl;
731e5dd7070Spatrick 
732e5dd7070Spatrick     // 4. Didn't find one yet - now look through categories' protocols
733e5dd7070Spatrick     if (!shallowCategoryLookup)
734e5dd7070Spatrick       for (const auto *Cat : ClassDecl->visible_categories()) {
735e5dd7070Spatrick         // Didn't find one yet - look through protocols.
736e5dd7070Spatrick         const ObjCList<ObjCProtocolDecl> &Protocols =
737e5dd7070Spatrick           Cat->getReferencedProtocols();
738e5dd7070Spatrick         for (auto *Protocol : Protocols)
739e5dd7070Spatrick           if ((MethodDecl = Protocol->lookupMethod(Sel, isInstance)))
740e5dd7070Spatrick             if (C != Cat || !MethodDecl->isImplicit())
741e5dd7070Spatrick               return MethodDecl;
742e5dd7070Spatrick       }
743e5dd7070Spatrick 
744e5dd7070Spatrick 
745e5dd7070Spatrick     if (!followSuper)
746e5dd7070Spatrick       return nullptr;
747e5dd7070Spatrick 
748e5dd7070Spatrick     // 5. Get to the super class (if any).
749e5dd7070Spatrick     ClassDecl = ClassDecl->getSuperClass();
750e5dd7070Spatrick   }
751e5dd7070Spatrick   return nullptr;
752e5dd7070Spatrick }
753e5dd7070Spatrick 
754e5dd7070Spatrick // Will search "local" class/category implementations for a method decl.
755e5dd7070Spatrick // If failed, then we search in class's root for an instance method.
756e5dd7070Spatrick // Returns 0 if no method is found.
lookupPrivateMethod(const Selector & Sel,bool Instance) const757e5dd7070Spatrick ObjCMethodDecl *ObjCInterfaceDecl::lookupPrivateMethod(
758e5dd7070Spatrick                                    const Selector &Sel,
759e5dd7070Spatrick                                    bool Instance) const {
760e5dd7070Spatrick   // FIXME: Should make sure no callers ever do this.
761e5dd7070Spatrick   if (!hasDefinition())
762e5dd7070Spatrick     return nullptr;
763e5dd7070Spatrick 
764e5dd7070Spatrick   if (data().ExternallyCompleted)
765e5dd7070Spatrick     LoadExternalDefinition();
766e5dd7070Spatrick 
767e5dd7070Spatrick   ObjCMethodDecl *Method = nullptr;
768e5dd7070Spatrick   if (ObjCImplementationDecl *ImpDecl = getImplementation())
769e5dd7070Spatrick     Method = Instance ? ImpDecl->getInstanceMethod(Sel)
770e5dd7070Spatrick                       : ImpDecl->getClassMethod(Sel);
771e5dd7070Spatrick 
772e5dd7070Spatrick   // Look through local category implementations associated with the class.
773e5dd7070Spatrick   if (!Method)
774e5dd7070Spatrick     Method = getCategoryMethod(Sel, Instance);
775e5dd7070Spatrick 
776e5dd7070Spatrick   // Before we give up, check if the selector is an instance method.
777e5dd7070Spatrick   // But only in the root. This matches gcc's behavior and what the
778e5dd7070Spatrick   // runtime expects.
779e5dd7070Spatrick   if (!Instance && !Method && !getSuperClass()) {
780e5dd7070Spatrick     Method = lookupInstanceMethod(Sel);
781e5dd7070Spatrick     // Look through local category implementations associated
782e5dd7070Spatrick     // with the root class.
783e5dd7070Spatrick     if (!Method)
784e5dd7070Spatrick       Method = lookupPrivateMethod(Sel, true);
785e5dd7070Spatrick   }
786e5dd7070Spatrick 
787e5dd7070Spatrick   if (!Method && getSuperClass())
788e5dd7070Spatrick     return getSuperClass()->lookupPrivateMethod(Sel, Instance);
789e5dd7070Spatrick   return Method;
790e5dd7070Spatrick }
791e5dd7070Spatrick 
getODRHash()792*12c85518Srobert unsigned ObjCInterfaceDecl::getODRHash() {
793*12c85518Srobert   assert(hasDefinition() && "ODRHash only for records with definitions");
794*12c85518Srobert 
795*12c85518Srobert   // Previously calculated hash is stored in DefinitionData.
796*12c85518Srobert   if (hasODRHash())
797*12c85518Srobert     return data().ODRHash;
798*12c85518Srobert 
799*12c85518Srobert   // Only calculate hash on first call of getODRHash per record.
800*12c85518Srobert   ODRHash Hasher;
801*12c85518Srobert   Hasher.AddObjCInterfaceDecl(getDefinition());
802*12c85518Srobert   data().ODRHash = Hasher.CalculateHash();
803*12c85518Srobert   setHasODRHash(true);
804*12c85518Srobert 
805*12c85518Srobert   return data().ODRHash;
806*12c85518Srobert }
807*12c85518Srobert 
hasODRHash() const808*12c85518Srobert bool ObjCInterfaceDecl::hasODRHash() const {
809*12c85518Srobert   if (!hasDefinition())
810*12c85518Srobert     return false;
811*12c85518Srobert   return data().HasODRHash;
812*12c85518Srobert }
813*12c85518Srobert 
setHasODRHash(bool HasHash)814*12c85518Srobert void ObjCInterfaceDecl::setHasODRHash(bool HasHash) {
815*12c85518Srobert   assert(hasDefinition() && "Cannot set ODRHash without definition");
816*12c85518Srobert   data().HasODRHash = HasHash;
817*12c85518Srobert }
818*12c85518Srobert 
819e5dd7070Spatrick //===----------------------------------------------------------------------===//
820e5dd7070Spatrick // ObjCMethodDecl
821e5dd7070Spatrick //===----------------------------------------------------------------------===//
822e5dd7070Spatrick 
ObjCMethodDecl(SourceLocation beginLoc,SourceLocation endLoc,Selector SelInfo,QualType T,TypeSourceInfo * ReturnTInfo,DeclContext * contextDecl,bool isInstance,bool isVariadic,bool isPropertyAccessor,bool isSynthesizedAccessorStub,bool isImplicitlyDeclared,bool isDefined,ImplementationControl impControl,bool HasRelatedResultType)823e5dd7070Spatrick ObjCMethodDecl::ObjCMethodDecl(
824e5dd7070Spatrick     SourceLocation beginLoc, SourceLocation endLoc, Selector SelInfo,
825e5dd7070Spatrick     QualType T, TypeSourceInfo *ReturnTInfo, DeclContext *contextDecl,
826e5dd7070Spatrick     bool isInstance, bool isVariadic, bool isPropertyAccessor,
827e5dd7070Spatrick     bool isSynthesizedAccessorStub, bool isImplicitlyDeclared, bool isDefined,
828e5dd7070Spatrick     ImplementationControl impControl, bool HasRelatedResultType)
829e5dd7070Spatrick     : NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo),
830e5dd7070Spatrick       DeclContext(ObjCMethod), MethodDeclType(T), ReturnTInfo(ReturnTInfo),
831e5dd7070Spatrick       DeclEndLoc(endLoc) {
832e5dd7070Spatrick 
833e5dd7070Spatrick   // Initialized the bits stored in DeclContext.
834e5dd7070Spatrick   ObjCMethodDeclBits.Family =
835e5dd7070Spatrick       static_cast<ObjCMethodFamily>(InvalidObjCMethodFamily);
836e5dd7070Spatrick   setInstanceMethod(isInstance);
837e5dd7070Spatrick   setVariadic(isVariadic);
838e5dd7070Spatrick   setPropertyAccessor(isPropertyAccessor);
839e5dd7070Spatrick   setSynthesizedAccessorStub(isSynthesizedAccessorStub);
840e5dd7070Spatrick   setDefined(isDefined);
841e5dd7070Spatrick   setIsRedeclaration(false);
842e5dd7070Spatrick   setHasRedeclaration(false);
843e5dd7070Spatrick   setDeclImplementation(impControl);
844e5dd7070Spatrick   setObjCDeclQualifier(OBJC_TQ_None);
845e5dd7070Spatrick   setRelatedResultType(HasRelatedResultType);
846e5dd7070Spatrick   setSelLocsKind(SelLoc_StandardNoSpace);
847e5dd7070Spatrick   setOverriding(false);
848e5dd7070Spatrick   setHasSkippedBody(false);
849e5dd7070Spatrick 
850e5dd7070Spatrick   setImplicit(isImplicitlyDeclared);
851e5dd7070Spatrick }
852e5dd7070Spatrick 
Create(ASTContext & C,SourceLocation beginLoc,SourceLocation endLoc,Selector SelInfo,QualType T,TypeSourceInfo * ReturnTInfo,DeclContext * contextDecl,bool isInstance,bool isVariadic,bool isPropertyAccessor,bool isSynthesizedAccessorStub,bool isImplicitlyDeclared,bool isDefined,ImplementationControl impControl,bool HasRelatedResultType)853e5dd7070Spatrick ObjCMethodDecl *ObjCMethodDecl::Create(
854e5dd7070Spatrick     ASTContext &C, SourceLocation beginLoc, SourceLocation endLoc,
855e5dd7070Spatrick     Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo,
856e5dd7070Spatrick     DeclContext *contextDecl, bool isInstance, bool isVariadic,
857e5dd7070Spatrick     bool isPropertyAccessor, bool isSynthesizedAccessorStub,
858e5dd7070Spatrick     bool isImplicitlyDeclared, bool isDefined, ImplementationControl impControl,
859e5dd7070Spatrick     bool HasRelatedResultType) {
860e5dd7070Spatrick   return new (C, contextDecl) ObjCMethodDecl(
861e5dd7070Spatrick       beginLoc, endLoc, SelInfo, T, ReturnTInfo, contextDecl, isInstance,
862e5dd7070Spatrick       isVariadic, isPropertyAccessor, isSynthesizedAccessorStub,
863e5dd7070Spatrick       isImplicitlyDeclared, isDefined, impControl, HasRelatedResultType);
864e5dd7070Spatrick }
865e5dd7070Spatrick 
CreateDeserialized(ASTContext & C,unsigned ID)866e5dd7070Spatrick ObjCMethodDecl *ObjCMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
867e5dd7070Spatrick   return new (C, ID) ObjCMethodDecl(SourceLocation(), SourceLocation(),
868e5dd7070Spatrick                                     Selector(), QualType(), nullptr, nullptr);
869e5dd7070Spatrick }
870e5dd7070Spatrick 
isDirectMethod() const871e5dd7070Spatrick bool ObjCMethodDecl::isDirectMethod() const {
872a9ac8606Spatrick   return hasAttr<ObjCDirectAttr>() &&
873a9ac8606Spatrick          !getASTContext().getLangOpts().ObjCDisableDirectMethodsForTesting;
874e5dd7070Spatrick }
875e5dd7070Spatrick 
isThisDeclarationADesignatedInitializer() const876e5dd7070Spatrick bool ObjCMethodDecl::isThisDeclarationADesignatedInitializer() const {
877e5dd7070Spatrick   return getMethodFamily() == OMF_init &&
878e5dd7070Spatrick       hasAttr<ObjCDesignatedInitializerAttr>();
879e5dd7070Spatrick }
880e5dd7070Spatrick 
definedInNSObject(const ASTContext & Ctx) const881e5dd7070Spatrick bool ObjCMethodDecl::definedInNSObject(const ASTContext &Ctx) const {
882e5dd7070Spatrick   if (const auto *PD = dyn_cast<const ObjCProtocolDecl>(getDeclContext()))
883e5dd7070Spatrick     return PD->getIdentifier() == Ctx.getNSObjectName();
884e5dd7070Spatrick   if (const auto *ID = dyn_cast<const ObjCInterfaceDecl>(getDeclContext()))
885e5dd7070Spatrick     return ID->getIdentifier() == Ctx.getNSObjectName();
886e5dd7070Spatrick   return false;
887e5dd7070Spatrick }
888e5dd7070Spatrick 
isDesignatedInitializerForTheInterface(const ObjCMethodDecl ** InitMethod) const889e5dd7070Spatrick bool ObjCMethodDecl::isDesignatedInitializerForTheInterface(
890e5dd7070Spatrick     const ObjCMethodDecl **InitMethod) const {
891e5dd7070Spatrick   if (getMethodFamily() != OMF_init)
892e5dd7070Spatrick     return false;
893e5dd7070Spatrick   const DeclContext *DC = getDeclContext();
894e5dd7070Spatrick   if (isa<ObjCProtocolDecl>(DC))
895e5dd7070Spatrick     return false;
896e5dd7070Spatrick   if (const ObjCInterfaceDecl *ID = getClassInterface())
897e5dd7070Spatrick     return ID->isDesignatedInitializer(getSelector(), InitMethod);
898e5dd7070Spatrick   return false;
899e5dd7070Spatrick }
900e5dd7070Spatrick 
hasParamDestroyedInCallee() const901*12c85518Srobert bool ObjCMethodDecl::hasParamDestroyedInCallee() const {
902*12c85518Srobert   for (auto *param : parameters()) {
903*12c85518Srobert     if (param->isDestroyedInCallee())
904*12c85518Srobert       return true;
905*12c85518Srobert   }
906*12c85518Srobert   return false;
907*12c85518Srobert }
908*12c85518Srobert 
getBody() const909e5dd7070Spatrick Stmt *ObjCMethodDecl::getBody() const {
910e5dd7070Spatrick   return Body.get(getASTContext().getExternalSource());
911e5dd7070Spatrick }
912e5dd7070Spatrick 
setAsRedeclaration(const ObjCMethodDecl * PrevMethod)913e5dd7070Spatrick void ObjCMethodDecl::setAsRedeclaration(const ObjCMethodDecl *PrevMethod) {
914e5dd7070Spatrick   assert(PrevMethod);
915e5dd7070Spatrick   getASTContext().setObjCMethodRedeclaration(PrevMethod, this);
916e5dd7070Spatrick   setIsRedeclaration(true);
917e5dd7070Spatrick   PrevMethod->setHasRedeclaration(true);
918e5dd7070Spatrick }
919e5dd7070Spatrick 
setParamsAndSelLocs(ASTContext & C,ArrayRef<ParmVarDecl * > Params,ArrayRef<SourceLocation> SelLocs)920e5dd7070Spatrick void ObjCMethodDecl::setParamsAndSelLocs(ASTContext &C,
921e5dd7070Spatrick                                          ArrayRef<ParmVarDecl*> Params,
922e5dd7070Spatrick                                          ArrayRef<SourceLocation> SelLocs) {
923e5dd7070Spatrick   ParamsAndSelLocs = nullptr;
924e5dd7070Spatrick   NumParams = Params.size();
925e5dd7070Spatrick   if (Params.empty() && SelLocs.empty())
926e5dd7070Spatrick     return;
927e5dd7070Spatrick 
928e5dd7070Spatrick   static_assert(alignof(ParmVarDecl *) >= alignof(SourceLocation),
929e5dd7070Spatrick                 "Alignment not sufficient for SourceLocation");
930e5dd7070Spatrick 
931e5dd7070Spatrick   unsigned Size = sizeof(ParmVarDecl *) * NumParams +
932e5dd7070Spatrick                   sizeof(SourceLocation) * SelLocs.size();
933e5dd7070Spatrick   ParamsAndSelLocs = C.Allocate(Size);
934e5dd7070Spatrick   std::copy(Params.begin(), Params.end(), getParams());
935e5dd7070Spatrick   std::copy(SelLocs.begin(), SelLocs.end(), getStoredSelLocs());
936e5dd7070Spatrick }
937e5dd7070Spatrick 
getSelectorLocs(SmallVectorImpl<SourceLocation> & SelLocs) const938e5dd7070Spatrick void ObjCMethodDecl::getSelectorLocs(
939e5dd7070Spatrick                                SmallVectorImpl<SourceLocation> &SelLocs) const {
940e5dd7070Spatrick   for (unsigned i = 0, e = getNumSelectorLocs(); i != e; ++i)
941e5dd7070Spatrick     SelLocs.push_back(getSelectorLoc(i));
942e5dd7070Spatrick }
943e5dd7070Spatrick 
setMethodParams(ASTContext & C,ArrayRef<ParmVarDecl * > Params,ArrayRef<SourceLocation> SelLocs)944e5dd7070Spatrick void ObjCMethodDecl::setMethodParams(ASTContext &C,
945e5dd7070Spatrick                                      ArrayRef<ParmVarDecl*> Params,
946e5dd7070Spatrick                                      ArrayRef<SourceLocation> SelLocs) {
947e5dd7070Spatrick   assert((!SelLocs.empty() || isImplicit()) &&
948e5dd7070Spatrick          "No selector locs for non-implicit method");
949e5dd7070Spatrick   if (isImplicit())
950*12c85518Srobert     return setParamsAndSelLocs(C, Params, std::nullopt);
951e5dd7070Spatrick 
952e5dd7070Spatrick   setSelLocsKind(hasStandardSelectorLocs(getSelector(), SelLocs, Params,
953e5dd7070Spatrick                                         DeclEndLoc));
954e5dd7070Spatrick   if (getSelLocsKind() != SelLoc_NonStandard)
955*12c85518Srobert     return setParamsAndSelLocs(C, Params, std::nullopt);
956e5dd7070Spatrick 
957e5dd7070Spatrick   setParamsAndSelLocs(C, Params, SelLocs);
958e5dd7070Spatrick }
959e5dd7070Spatrick 
960e5dd7070Spatrick /// A definition will return its interface declaration.
961e5dd7070Spatrick /// An interface declaration will return its definition.
962e5dd7070Spatrick /// Otherwise it will return itself.
getNextRedeclarationImpl()963e5dd7070Spatrick ObjCMethodDecl *ObjCMethodDecl::getNextRedeclarationImpl() {
964e5dd7070Spatrick   ASTContext &Ctx = getASTContext();
965e5dd7070Spatrick   ObjCMethodDecl *Redecl = nullptr;
966e5dd7070Spatrick   if (hasRedeclaration())
967e5dd7070Spatrick     Redecl = const_cast<ObjCMethodDecl*>(Ctx.getObjCMethodRedeclaration(this));
968e5dd7070Spatrick   if (Redecl)
969e5dd7070Spatrick     return Redecl;
970e5dd7070Spatrick 
971e5dd7070Spatrick   auto *CtxD = cast<Decl>(getDeclContext());
972e5dd7070Spatrick 
973e5dd7070Spatrick   if (!CtxD->isInvalidDecl()) {
974e5dd7070Spatrick     if (auto *IFD = dyn_cast<ObjCInterfaceDecl>(CtxD)) {
975e5dd7070Spatrick       if (ObjCImplementationDecl *ImplD = Ctx.getObjCImplementation(IFD))
976e5dd7070Spatrick         if (!ImplD->isInvalidDecl())
977e5dd7070Spatrick           Redecl = ImplD->getMethod(getSelector(), isInstanceMethod());
978e5dd7070Spatrick 
979e5dd7070Spatrick     } else if (auto *CD = dyn_cast<ObjCCategoryDecl>(CtxD)) {
980e5dd7070Spatrick       if (ObjCCategoryImplDecl *ImplD = Ctx.getObjCImplementation(CD))
981e5dd7070Spatrick         if (!ImplD->isInvalidDecl())
982e5dd7070Spatrick           Redecl = ImplD->getMethod(getSelector(), isInstanceMethod());
983e5dd7070Spatrick 
984e5dd7070Spatrick     } else if (auto *ImplD = dyn_cast<ObjCImplementationDecl>(CtxD)) {
985e5dd7070Spatrick       if (ObjCInterfaceDecl *IFD = ImplD->getClassInterface())
986e5dd7070Spatrick         if (!IFD->isInvalidDecl())
987e5dd7070Spatrick           Redecl = IFD->getMethod(getSelector(), isInstanceMethod());
988e5dd7070Spatrick 
989e5dd7070Spatrick     } else if (auto *CImplD = dyn_cast<ObjCCategoryImplDecl>(CtxD)) {
990e5dd7070Spatrick       if (ObjCCategoryDecl *CatD = CImplD->getCategoryDecl())
991e5dd7070Spatrick         if (!CatD->isInvalidDecl())
992e5dd7070Spatrick           Redecl = CatD->getMethod(getSelector(), isInstanceMethod());
993e5dd7070Spatrick     }
994e5dd7070Spatrick   }
995e5dd7070Spatrick 
996e5dd7070Spatrick   // Ensure that the discovered method redeclaration has a valid declaration
997e5dd7070Spatrick   // context. Used to prevent infinite loops when iterating redeclarations in
998e5dd7070Spatrick   // a partially invalid AST.
999e5dd7070Spatrick   if (Redecl && cast<Decl>(Redecl->getDeclContext())->isInvalidDecl())
1000e5dd7070Spatrick     Redecl = nullptr;
1001e5dd7070Spatrick 
1002e5dd7070Spatrick   if (!Redecl && isRedeclaration()) {
1003e5dd7070Spatrick     // This is the last redeclaration, go back to the first method.
1004e5dd7070Spatrick     return cast<ObjCContainerDecl>(CtxD)->getMethod(getSelector(),
1005a9ac8606Spatrick                                                     isInstanceMethod(),
1006a9ac8606Spatrick                                                     /*AllowHidden=*/true);
1007e5dd7070Spatrick   }
1008e5dd7070Spatrick 
1009e5dd7070Spatrick   return Redecl ? Redecl : this;
1010e5dd7070Spatrick }
1011e5dd7070Spatrick 
getCanonicalDecl()1012e5dd7070Spatrick ObjCMethodDecl *ObjCMethodDecl::getCanonicalDecl() {
1013e5dd7070Spatrick   auto *CtxD = cast<Decl>(getDeclContext());
1014e5dd7070Spatrick   const auto &Sel = getSelector();
1015e5dd7070Spatrick 
1016e5dd7070Spatrick   if (auto *ImplD = dyn_cast<ObjCImplementationDecl>(CtxD)) {
1017e5dd7070Spatrick     if (ObjCInterfaceDecl *IFD = ImplD->getClassInterface()) {
1018e5dd7070Spatrick       // When the container is the ObjCImplementationDecl (the primary
1019e5dd7070Spatrick       // @implementation), then the canonical Decl is either in
1020e5dd7070Spatrick       // the class Interface, or in any of its extension.
1021e5dd7070Spatrick       //
1022e5dd7070Spatrick       // So when we don't find it in the ObjCInterfaceDecl,
1023e5dd7070Spatrick       // sift through extensions too.
1024e5dd7070Spatrick       if (ObjCMethodDecl *MD = IFD->getMethod(Sel, isInstanceMethod()))
1025e5dd7070Spatrick         return MD;
1026e5dd7070Spatrick       for (auto *Ext : IFD->known_extensions())
1027e5dd7070Spatrick         if (ObjCMethodDecl *MD = Ext->getMethod(Sel, isInstanceMethod()))
1028e5dd7070Spatrick           return MD;
1029e5dd7070Spatrick     }
1030e5dd7070Spatrick   } else if (auto *CImplD = dyn_cast<ObjCCategoryImplDecl>(CtxD)) {
1031e5dd7070Spatrick     if (ObjCCategoryDecl *CatD = CImplD->getCategoryDecl())
1032e5dd7070Spatrick       if (ObjCMethodDecl *MD = CatD->getMethod(Sel, isInstanceMethod()))
1033e5dd7070Spatrick         return MD;
1034e5dd7070Spatrick   }
1035e5dd7070Spatrick 
1036e5dd7070Spatrick   if (isRedeclaration()) {
1037e5dd7070Spatrick     // It is possible that we have not done deserializing the ObjCMethod yet.
1038e5dd7070Spatrick     ObjCMethodDecl *MD =
1039a9ac8606Spatrick         cast<ObjCContainerDecl>(CtxD)->getMethod(Sel, isInstanceMethod(),
1040a9ac8606Spatrick                                                  /*AllowHidden=*/true);
1041e5dd7070Spatrick     return MD ? MD : this;
1042e5dd7070Spatrick   }
1043e5dd7070Spatrick 
1044e5dd7070Spatrick   return this;
1045e5dd7070Spatrick }
1046e5dd7070Spatrick 
getEndLoc() const1047e5dd7070Spatrick SourceLocation ObjCMethodDecl::getEndLoc() const {
1048e5dd7070Spatrick   if (Stmt *Body = getBody())
1049e5dd7070Spatrick     return Body->getEndLoc();
1050e5dd7070Spatrick   return DeclEndLoc;
1051e5dd7070Spatrick }
1052e5dd7070Spatrick 
getMethodFamily() const1053e5dd7070Spatrick ObjCMethodFamily ObjCMethodDecl::getMethodFamily() const {
1054e5dd7070Spatrick   auto family = static_cast<ObjCMethodFamily>(ObjCMethodDeclBits.Family);
1055e5dd7070Spatrick   if (family != static_cast<unsigned>(InvalidObjCMethodFamily))
1056e5dd7070Spatrick     return family;
1057e5dd7070Spatrick 
1058e5dd7070Spatrick   // Check for an explicit attribute.
1059e5dd7070Spatrick   if (const ObjCMethodFamilyAttr *attr = getAttr<ObjCMethodFamilyAttr>()) {
1060e5dd7070Spatrick     // The unfortunate necessity of mapping between enums here is due
1061e5dd7070Spatrick     // to the attributes framework.
1062e5dd7070Spatrick     switch (attr->getFamily()) {
1063e5dd7070Spatrick     case ObjCMethodFamilyAttr::OMF_None: family = OMF_None; break;
1064e5dd7070Spatrick     case ObjCMethodFamilyAttr::OMF_alloc: family = OMF_alloc; break;
1065e5dd7070Spatrick     case ObjCMethodFamilyAttr::OMF_copy: family = OMF_copy; break;
1066e5dd7070Spatrick     case ObjCMethodFamilyAttr::OMF_init: family = OMF_init; break;
1067e5dd7070Spatrick     case ObjCMethodFamilyAttr::OMF_mutableCopy: family = OMF_mutableCopy; break;
1068e5dd7070Spatrick     case ObjCMethodFamilyAttr::OMF_new: family = OMF_new; break;
1069e5dd7070Spatrick     }
1070e5dd7070Spatrick     ObjCMethodDeclBits.Family = family;
1071e5dd7070Spatrick     return family;
1072e5dd7070Spatrick   }
1073e5dd7070Spatrick 
1074e5dd7070Spatrick   family = getSelector().getMethodFamily();
1075e5dd7070Spatrick   switch (family) {
1076e5dd7070Spatrick   case OMF_None: break;
1077e5dd7070Spatrick 
1078e5dd7070Spatrick   // init only has a conventional meaning for an instance method, and
1079e5dd7070Spatrick   // it has to return an object.
1080e5dd7070Spatrick   case OMF_init:
1081e5dd7070Spatrick     if (!isInstanceMethod() || !getReturnType()->isObjCObjectPointerType())
1082e5dd7070Spatrick       family = OMF_None;
1083e5dd7070Spatrick     break;
1084e5dd7070Spatrick 
1085e5dd7070Spatrick   // alloc/copy/new have a conventional meaning for both class and
1086e5dd7070Spatrick   // instance methods, but they require an object return.
1087e5dd7070Spatrick   case OMF_alloc:
1088e5dd7070Spatrick   case OMF_copy:
1089e5dd7070Spatrick   case OMF_mutableCopy:
1090e5dd7070Spatrick   case OMF_new:
1091e5dd7070Spatrick     if (!getReturnType()->isObjCObjectPointerType())
1092e5dd7070Spatrick       family = OMF_None;
1093e5dd7070Spatrick     break;
1094e5dd7070Spatrick 
1095e5dd7070Spatrick   // These selectors have a conventional meaning only for instance methods.
1096e5dd7070Spatrick   case OMF_dealloc:
1097e5dd7070Spatrick   case OMF_finalize:
1098e5dd7070Spatrick   case OMF_retain:
1099e5dd7070Spatrick   case OMF_release:
1100e5dd7070Spatrick   case OMF_autorelease:
1101e5dd7070Spatrick   case OMF_retainCount:
1102e5dd7070Spatrick   case OMF_self:
1103e5dd7070Spatrick     if (!isInstanceMethod())
1104e5dd7070Spatrick       family = OMF_None;
1105e5dd7070Spatrick     break;
1106e5dd7070Spatrick 
1107e5dd7070Spatrick   case OMF_initialize:
1108e5dd7070Spatrick     if (isInstanceMethod() || !getReturnType()->isVoidType())
1109e5dd7070Spatrick       family = OMF_None;
1110e5dd7070Spatrick     break;
1111e5dd7070Spatrick 
1112e5dd7070Spatrick   case OMF_performSelector:
1113e5dd7070Spatrick     if (!isInstanceMethod() || !getReturnType()->isObjCIdType())
1114e5dd7070Spatrick       family = OMF_None;
1115e5dd7070Spatrick     else {
1116e5dd7070Spatrick       unsigned noParams = param_size();
1117e5dd7070Spatrick       if (noParams < 1 || noParams > 3)
1118e5dd7070Spatrick         family = OMF_None;
1119e5dd7070Spatrick       else {
1120e5dd7070Spatrick         ObjCMethodDecl::param_type_iterator it = param_type_begin();
1121e5dd7070Spatrick         QualType ArgT = (*it);
1122e5dd7070Spatrick         if (!ArgT->isObjCSelType()) {
1123e5dd7070Spatrick           family = OMF_None;
1124e5dd7070Spatrick           break;
1125e5dd7070Spatrick         }
1126e5dd7070Spatrick         while (--noParams) {
1127e5dd7070Spatrick           it++;
1128e5dd7070Spatrick           ArgT = (*it);
1129e5dd7070Spatrick           if (!ArgT->isObjCIdType()) {
1130e5dd7070Spatrick             family = OMF_None;
1131e5dd7070Spatrick             break;
1132e5dd7070Spatrick           }
1133e5dd7070Spatrick         }
1134e5dd7070Spatrick       }
1135e5dd7070Spatrick     }
1136e5dd7070Spatrick     break;
1137e5dd7070Spatrick 
1138e5dd7070Spatrick   }
1139e5dd7070Spatrick 
1140e5dd7070Spatrick   // Cache the result.
1141e5dd7070Spatrick   ObjCMethodDeclBits.Family = family;
1142e5dd7070Spatrick   return family;
1143e5dd7070Spatrick }
1144e5dd7070Spatrick 
getSelfType(ASTContext & Context,const ObjCInterfaceDecl * OID,bool & selfIsPseudoStrong,bool & selfIsConsumed) const1145e5dd7070Spatrick QualType ObjCMethodDecl::getSelfType(ASTContext &Context,
1146e5dd7070Spatrick                                      const ObjCInterfaceDecl *OID,
1147e5dd7070Spatrick                                      bool &selfIsPseudoStrong,
1148e5dd7070Spatrick                                      bool &selfIsConsumed) const {
1149e5dd7070Spatrick   QualType selfTy;
1150e5dd7070Spatrick   selfIsPseudoStrong = false;
1151e5dd7070Spatrick   selfIsConsumed = false;
1152e5dd7070Spatrick   if (isInstanceMethod()) {
1153e5dd7070Spatrick     // There may be no interface context due to error in declaration
1154e5dd7070Spatrick     // of the interface (which has been reported). Recover gracefully.
1155e5dd7070Spatrick     if (OID) {
1156e5dd7070Spatrick       selfTy = Context.getObjCInterfaceType(OID);
1157e5dd7070Spatrick       selfTy = Context.getObjCObjectPointerType(selfTy);
1158e5dd7070Spatrick     } else {
1159e5dd7070Spatrick       selfTy = Context.getObjCIdType();
1160e5dd7070Spatrick     }
1161e5dd7070Spatrick   } else // we have a factory method.
1162e5dd7070Spatrick     selfTy = Context.getObjCClassType();
1163e5dd7070Spatrick 
1164e5dd7070Spatrick   if (Context.getLangOpts().ObjCAutoRefCount) {
1165e5dd7070Spatrick     if (isInstanceMethod()) {
1166e5dd7070Spatrick       selfIsConsumed = hasAttr<NSConsumesSelfAttr>();
1167e5dd7070Spatrick 
1168e5dd7070Spatrick       // 'self' is always __strong.  It's actually pseudo-strong except
1169e5dd7070Spatrick       // in init methods (or methods labeled ns_consumes_self), though.
1170e5dd7070Spatrick       Qualifiers qs;
1171e5dd7070Spatrick       qs.setObjCLifetime(Qualifiers::OCL_Strong);
1172e5dd7070Spatrick       selfTy = Context.getQualifiedType(selfTy, qs);
1173e5dd7070Spatrick 
1174e5dd7070Spatrick       // In addition, 'self' is const unless this is an init method.
1175e5dd7070Spatrick       if (getMethodFamily() != OMF_init && !selfIsConsumed) {
1176e5dd7070Spatrick         selfTy = selfTy.withConst();
1177e5dd7070Spatrick         selfIsPseudoStrong = true;
1178e5dd7070Spatrick       }
1179e5dd7070Spatrick     }
1180e5dd7070Spatrick     else {
1181e5dd7070Spatrick       assert(isClassMethod());
1182e5dd7070Spatrick       // 'self' is always const in class methods.
1183e5dd7070Spatrick       selfTy = selfTy.withConst();
1184e5dd7070Spatrick       selfIsPseudoStrong = true;
1185e5dd7070Spatrick     }
1186e5dd7070Spatrick   }
1187e5dd7070Spatrick   return selfTy;
1188e5dd7070Spatrick }
1189e5dd7070Spatrick 
createImplicitParams(ASTContext & Context,const ObjCInterfaceDecl * OID)1190e5dd7070Spatrick void ObjCMethodDecl::createImplicitParams(ASTContext &Context,
1191e5dd7070Spatrick                                           const ObjCInterfaceDecl *OID) {
1192e5dd7070Spatrick   bool selfIsPseudoStrong, selfIsConsumed;
1193e5dd7070Spatrick   QualType selfTy =
1194e5dd7070Spatrick     getSelfType(Context, OID, selfIsPseudoStrong, selfIsConsumed);
1195e5dd7070Spatrick   auto *Self = ImplicitParamDecl::Create(Context, this, SourceLocation(),
1196e5dd7070Spatrick                                          &Context.Idents.get("self"), selfTy,
1197e5dd7070Spatrick                                          ImplicitParamDecl::ObjCSelf);
1198e5dd7070Spatrick   setSelfDecl(Self);
1199e5dd7070Spatrick 
1200e5dd7070Spatrick   if (selfIsConsumed)
1201e5dd7070Spatrick     Self->addAttr(NSConsumedAttr::CreateImplicit(Context));
1202e5dd7070Spatrick 
1203e5dd7070Spatrick   if (selfIsPseudoStrong)
1204e5dd7070Spatrick     Self->setARCPseudoStrong(true);
1205e5dd7070Spatrick 
1206e5dd7070Spatrick   setCmdDecl(ImplicitParamDecl::Create(
1207e5dd7070Spatrick       Context, this, SourceLocation(), &Context.Idents.get("_cmd"),
1208e5dd7070Spatrick       Context.getObjCSelType(), ImplicitParamDecl::ObjCCmd));
1209e5dd7070Spatrick }
1210e5dd7070Spatrick 
getClassInterface()1211e5dd7070Spatrick ObjCInterfaceDecl *ObjCMethodDecl::getClassInterface() {
1212e5dd7070Spatrick   if (auto *ID = dyn_cast<ObjCInterfaceDecl>(getDeclContext()))
1213e5dd7070Spatrick     return ID;
1214e5dd7070Spatrick   if (auto *CD = dyn_cast<ObjCCategoryDecl>(getDeclContext()))
1215e5dd7070Spatrick     return CD->getClassInterface();
1216e5dd7070Spatrick   if (auto *IMD = dyn_cast<ObjCImplDecl>(getDeclContext()))
1217e5dd7070Spatrick     return IMD->getClassInterface();
1218e5dd7070Spatrick   if (isa<ObjCProtocolDecl>(getDeclContext()))
1219e5dd7070Spatrick     return nullptr;
1220e5dd7070Spatrick   llvm_unreachable("unknown method context");
1221e5dd7070Spatrick }
1222e5dd7070Spatrick 
getCategory()1223a9ac8606Spatrick ObjCCategoryDecl *ObjCMethodDecl::getCategory() {
1224a9ac8606Spatrick   if (auto *CD = dyn_cast<ObjCCategoryDecl>(getDeclContext()))
1225a9ac8606Spatrick     return CD;
1226a9ac8606Spatrick   if (auto *IMD = dyn_cast<ObjCCategoryImplDecl>(getDeclContext()))
1227a9ac8606Spatrick     return IMD->getCategoryDecl();
1228a9ac8606Spatrick   return nullptr;
1229a9ac8606Spatrick }
1230a9ac8606Spatrick 
getReturnTypeSourceRange() const1231e5dd7070Spatrick SourceRange ObjCMethodDecl::getReturnTypeSourceRange() const {
1232e5dd7070Spatrick   const auto *TSI = getReturnTypeSourceInfo();
1233e5dd7070Spatrick   if (TSI)
1234e5dd7070Spatrick     return TSI->getTypeLoc().getSourceRange();
1235e5dd7070Spatrick   return SourceRange();
1236e5dd7070Spatrick }
1237e5dd7070Spatrick 
getSendResultType() const1238e5dd7070Spatrick QualType ObjCMethodDecl::getSendResultType() const {
1239e5dd7070Spatrick   ASTContext &Ctx = getASTContext();
1240e5dd7070Spatrick   return getReturnType().getNonLValueExprType(Ctx)
1241e5dd7070Spatrick            .substObjCTypeArgs(Ctx, {}, ObjCSubstitutionContext::Result);
1242e5dd7070Spatrick }
1243e5dd7070Spatrick 
getSendResultType(QualType receiverType) const1244e5dd7070Spatrick QualType ObjCMethodDecl::getSendResultType(QualType receiverType) const {
1245e5dd7070Spatrick   // FIXME: Handle related result types here.
1246e5dd7070Spatrick 
1247e5dd7070Spatrick   return getReturnType().getNonLValueExprType(getASTContext())
1248e5dd7070Spatrick            .substObjCMemberType(receiverType, getDeclContext(),
1249e5dd7070Spatrick                                 ObjCSubstitutionContext::Result);
1250e5dd7070Spatrick }
1251e5dd7070Spatrick 
CollectOverriddenMethodsRecurse(const ObjCContainerDecl * Container,const ObjCMethodDecl * Method,SmallVectorImpl<const ObjCMethodDecl * > & Methods,bool MovedToSuper)1252e5dd7070Spatrick static void CollectOverriddenMethodsRecurse(const ObjCContainerDecl *Container,
1253e5dd7070Spatrick                                             const ObjCMethodDecl *Method,
1254e5dd7070Spatrick                                SmallVectorImpl<const ObjCMethodDecl *> &Methods,
1255e5dd7070Spatrick                                             bool MovedToSuper) {
1256e5dd7070Spatrick   if (!Container)
1257e5dd7070Spatrick     return;
1258e5dd7070Spatrick 
1259e5dd7070Spatrick   // In categories look for overridden methods from protocols. A method from
1260e5dd7070Spatrick   // category is not "overridden" since it is considered as the "same" method
1261e5dd7070Spatrick   // (same USR) as the one from the interface.
1262e5dd7070Spatrick   if (const auto *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
1263e5dd7070Spatrick     // Check whether we have a matching method at this category but only if we
1264e5dd7070Spatrick     // are at the super class level.
1265e5dd7070Spatrick     if (MovedToSuper)
1266e5dd7070Spatrick       if (ObjCMethodDecl *
1267e5dd7070Spatrick             Overridden = Container->getMethod(Method->getSelector(),
1268e5dd7070Spatrick                                               Method->isInstanceMethod(),
1269e5dd7070Spatrick                                               /*AllowHidden=*/true))
1270e5dd7070Spatrick         if (Method != Overridden) {
1271e5dd7070Spatrick           // We found an override at this category; there is no need to look
1272e5dd7070Spatrick           // into its protocols.
1273e5dd7070Spatrick           Methods.push_back(Overridden);
1274e5dd7070Spatrick           return;
1275e5dd7070Spatrick         }
1276e5dd7070Spatrick 
1277e5dd7070Spatrick     for (const auto *P : Category->protocols())
1278e5dd7070Spatrick       CollectOverriddenMethodsRecurse(P, Method, Methods, MovedToSuper);
1279e5dd7070Spatrick     return;
1280e5dd7070Spatrick   }
1281e5dd7070Spatrick 
1282e5dd7070Spatrick   // Check whether we have a matching method at this level.
1283e5dd7070Spatrick   if (const ObjCMethodDecl *
1284e5dd7070Spatrick         Overridden = Container->getMethod(Method->getSelector(),
1285e5dd7070Spatrick                                           Method->isInstanceMethod(),
1286e5dd7070Spatrick                                           /*AllowHidden=*/true))
1287e5dd7070Spatrick     if (Method != Overridden) {
1288e5dd7070Spatrick       // We found an override at this level; there is no need to look
1289e5dd7070Spatrick       // into other protocols or categories.
1290e5dd7070Spatrick       Methods.push_back(Overridden);
1291e5dd7070Spatrick       return;
1292e5dd7070Spatrick     }
1293e5dd7070Spatrick 
1294e5dd7070Spatrick   if (const auto *Protocol = dyn_cast<ObjCProtocolDecl>(Container)){
1295e5dd7070Spatrick     for (const auto *P : Protocol->protocols())
1296e5dd7070Spatrick       CollectOverriddenMethodsRecurse(P, Method, Methods, MovedToSuper);
1297e5dd7070Spatrick   }
1298e5dd7070Spatrick 
1299e5dd7070Spatrick   if (const auto *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
1300e5dd7070Spatrick     for (const auto *P : Interface->protocols())
1301e5dd7070Spatrick       CollectOverriddenMethodsRecurse(P, Method, Methods, MovedToSuper);
1302e5dd7070Spatrick 
1303e5dd7070Spatrick     for (const auto *Cat : Interface->known_categories())
1304e5dd7070Spatrick       CollectOverriddenMethodsRecurse(Cat, Method, Methods, MovedToSuper);
1305e5dd7070Spatrick 
1306e5dd7070Spatrick     if (const ObjCInterfaceDecl *Super = Interface->getSuperClass())
1307e5dd7070Spatrick       return CollectOverriddenMethodsRecurse(Super, Method, Methods,
1308e5dd7070Spatrick                                              /*MovedToSuper=*/true);
1309e5dd7070Spatrick   }
1310e5dd7070Spatrick }
1311e5dd7070Spatrick 
CollectOverriddenMethods(const ObjCContainerDecl * Container,const ObjCMethodDecl * Method,SmallVectorImpl<const ObjCMethodDecl * > & Methods)1312e5dd7070Spatrick static inline void CollectOverriddenMethods(const ObjCContainerDecl *Container,
1313e5dd7070Spatrick                                             const ObjCMethodDecl *Method,
1314e5dd7070Spatrick                              SmallVectorImpl<const ObjCMethodDecl *> &Methods) {
1315e5dd7070Spatrick   CollectOverriddenMethodsRecurse(Container, Method, Methods,
1316e5dd7070Spatrick                                   /*MovedToSuper=*/false);
1317e5dd7070Spatrick }
1318e5dd7070Spatrick 
collectOverriddenMethodsSlow(const ObjCMethodDecl * Method,SmallVectorImpl<const ObjCMethodDecl * > & overridden)1319e5dd7070Spatrick static void collectOverriddenMethodsSlow(const ObjCMethodDecl *Method,
1320e5dd7070Spatrick                           SmallVectorImpl<const ObjCMethodDecl *> &overridden) {
1321e5dd7070Spatrick   assert(Method->isOverriding());
1322e5dd7070Spatrick 
1323e5dd7070Spatrick   if (const auto *ProtD =
1324e5dd7070Spatrick           dyn_cast<ObjCProtocolDecl>(Method->getDeclContext())) {
1325e5dd7070Spatrick     CollectOverriddenMethods(ProtD, Method, overridden);
1326e5dd7070Spatrick 
1327e5dd7070Spatrick   } else if (const auto *IMD =
1328e5dd7070Spatrick                  dyn_cast<ObjCImplDecl>(Method->getDeclContext())) {
1329e5dd7070Spatrick     const ObjCInterfaceDecl *ID = IMD->getClassInterface();
1330e5dd7070Spatrick     if (!ID)
1331e5dd7070Spatrick       return;
1332e5dd7070Spatrick     // Start searching for overridden methods using the method from the
1333e5dd7070Spatrick     // interface as starting point.
1334e5dd7070Spatrick     if (const ObjCMethodDecl *IFaceMeth = ID->getMethod(Method->getSelector(),
1335e5dd7070Spatrick                                                     Method->isInstanceMethod(),
1336e5dd7070Spatrick                                                     /*AllowHidden=*/true))
1337e5dd7070Spatrick       Method = IFaceMeth;
1338e5dd7070Spatrick     CollectOverriddenMethods(ID, Method, overridden);
1339e5dd7070Spatrick 
1340e5dd7070Spatrick   } else if (const auto *CatD =
1341e5dd7070Spatrick                  dyn_cast<ObjCCategoryDecl>(Method->getDeclContext())) {
1342e5dd7070Spatrick     const ObjCInterfaceDecl *ID = CatD->getClassInterface();
1343e5dd7070Spatrick     if (!ID)
1344e5dd7070Spatrick       return;
1345e5dd7070Spatrick     // Start searching for overridden methods using the method from the
1346e5dd7070Spatrick     // interface as starting point.
1347e5dd7070Spatrick     if (const ObjCMethodDecl *IFaceMeth = ID->getMethod(Method->getSelector(),
1348e5dd7070Spatrick                                                      Method->isInstanceMethod(),
1349e5dd7070Spatrick                                                      /*AllowHidden=*/true))
1350e5dd7070Spatrick       Method = IFaceMeth;
1351e5dd7070Spatrick     CollectOverriddenMethods(ID, Method, overridden);
1352e5dd7070Spatrick 
1353e5dd7070Spatrick   } else {
1354e5dd7070Spatrick     CollectOverriddenMethods(
1355e5dd7070Spatrick                   dyn_cast_or_null<ObjCContainerDecl>(Method->getDeclContext()),
1356e5dd7070Spatrick                   Method, overridden);
1357e5dd7070Spatrick   }
1358e5dd7070Spatrick }
1359e5dd7070Spatrick 
getOverriddenMethods(SmallVectorImpl<const ObjCMethodDecl * > & Overridden) const1360e5dd7070Spatrick void ObjCMethodDecl::getOverriddenMethods(
1361e5dd7070Spatrick                     SmallVectorImpl<const ObjCMethodDecl *> &Overridden) const {
1362e5dd7070Spatrick   const ObjCMethodDecl *Method = this;
1363e5dd7070Spatrick 
1364e5dd7070Spatrick   if (Method->isRedeclaration()) {
1365a9ac8606Spatrick     Method = cast<ObjCContainerDecl>(Method->getDeclContext())
1366a9ac8606Spatrick                  ->getMethod(Method->getSelector(), Method->isInstanceMethod(),
1367a9ac8606Spatrick                              /*AllowHidden=*/true);
1368e5dd7070Spatrick   }
1369e5dd7070Spatrick 
1370e5dd7070Spatrick   if (Method->isOverriding()) {
1371e5dd7070Spatrick     collectOverriddenMethodsSlow(Method, Overridden);
1372e5dd7070Spatrick     assert(!Overridden.empty() &&
1373e5dd7070Spatrick            "ObjCMethodDecl's overriding bit is not as expected");
1374e5dd7070Spatrick   }
1375e5dd7070Spatrick }
1376e5dd7070Spatrick 
1377e5dd7070Spatrick const ObjCPropertyDecl *
findPropertyDecl(bool CheckOverrides) const1378e5dd7070Spatrick ObjCMethodDecl::findPropertyDecl(bool CheckOverrides) const {
1379e5dd7070Spatrick   Selector Sel = getSelector();
1380e5dd7070Spatrick   unsigned NumArgs = Sel.getNumArgs();
1381e5dd7070Spatrick   if (NumArgs > 1)
1382e5dd7070Spatrick     return nullptr;
1383e5dd7070Spatrick 
1384e5dd7070Spatrick   if (isPropertyAccessor()) {
1385e5dd7070Spatrick     const auto *Container = cast<ObjCContainerDecl>(getParent());
1386e5dd7070Spatrick     // For accessor stubs, go back to the interface.
1387e5dd7070Spatrick     if (auto *ImplDecl = dyn_cast<ObjCImplDecl>(Container))
1388e5dd7070Spatrick       if (isSynthesizedAccessorStub())
1389e5dd7070Spatrick         Container = ImplDecl->getClassInterface();
1390e5dd7070Spatrick 
1391e5dd7070Spatrick     bool IsGetter = (NumArgs == 0);
1392e5dd7070Spatrick     bool IsInstance = isInstanceMethod();
1393e5dd7070Spatrick 
1394e5dd7070Spatrick     /// Local function that attempts to find a matching property within the
1395e5dd7070Spatrick     /// given Objective-C container.
1396e5dd7070Spatrick     auto findMatchingProperty =
1397e5dd7070Spatrick       [&](const ObjCContainerDecl *Container) -> const ObjCPropertyDecl * {
1398e5dd7070Spatrick       if (IsInstance) {
1399e5dd7070Spatrick         for (const auto *I : Container->instance_properties()) {
1400e5dd7070Spatrick           Selector NextSel = IsGetter ? I->getGetterName()
1401e5dd7070Spatrick                                       : I->getSetterName();
1402e5dd7070Spatrick           if (NextSel == Sel)
1403e5dd7070Spatrick             return I;
1404e5dd7070Spatrick         }
1405e5dd7070Spatrick       } else {
1406e5dd7070Spatrick         for (const auto *I : Container->class_properties()) {
1407e5dd7070Spatrick           Selector NextSel = IsGetter ? I->getGetterName()
1408e5dd7070Spatrick                                       : I->getSetterName();
1409e5dd7070Spatrick           if (NextSel == Sel)
1410e5dd7070Spatrick             return I;
1411e5dd7070Spatrick         }
1412e5dd7070Spatrick       }
1413e5dd7070Spatrick 
1414e5dd7070Spatrick       return nullptr;
1415e5dd7070Spatrick     };
1416e5dd7070Spatrick 
1417e5dd7070Spatrick     // Look in the container we were given.
1418e5dd7070Spatrick     if (const auto *Found = findMatchingProperty(Container))
1419e5dd7070Spatrick       return Found;
1420e5dd7070Spatrick 
1421e5dd7070Spatrick     // If we're in a category or extension, look in the main class.
1422e5dd7070Spatrick     const ObjCInterfaceDecl *ClassDecl = nullptr;
1423e5dd7070Spatrick     if (const auto *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
1424e5dd7070Spatrick       ClassDecl = Category->getClassInterface();
1425e5dd7070Spatrick       if (const auto *Found = findMatchingProperty(ClassDecl))
1426e5dd7070Spatrick         return Found;
1427e5dd7070Spatrick     } else {
1428e5dd7070Spatrick       // Determine whether the container is a class.
1429ec727ea7Spatrick       ClassDecl = cast<ObjCInterfaceDecl>(Container);
1430e5dd7070Spatrick     }
1431ec727ea7Spatrick     assert(ClassDecl && "Failed to find main class");
1432e5dd7070Spatrick 
1433e5dd7070Spatrick     // If we have a class, check its visible extensions.
1434e5dd7070Spatrick     for (const auto *Ext : ClassDecl->visible_extensions()) {
1435e5dd7070Spatrick       if (Ext == Container)
1436e5dd7070Spatrick         continue;
1437e5dd7070Spatrick       if (const auto *Found = findMatchingProperty(Ext))
1438e5dd7070Spatrick         return Found;
1439e5dd7070Spatrick     }
1440e5dd7070Spatrick 
1441e5dd7070Spatrick     assert(isSynthesizedAccessorStub() && "expected an accessor stub");
1442ec727ea7Spatrick 
1443e5dd7070Spatrick     for (const auto *Cat : ClassDecl->known_categories()) {
1444e5dd7070Spatrick       if (Cat == Container)
1445e5dd7070Spatrick         continue;
1446e5dd7070Spatrick       if (const auto *Found = findMatchingProperty(Cat))
1447e5dd7070Spatrick         return Found;
1448e5dd7070Spatrick     }
1449e5dd7070Spatrick 
1450e5dd7070Spatrick     llvm_unreachable("Marked as a property accessor but no property found!");
1451e5dd7070Spatrick   }
1452e5dd7070Spatrick 
1453e5dd7070Spatrick   if (!CheckOverrides)
1454e5dd7070Spatrick     return nullptr;
1455e5dd7070Spatrick 
1456e5dd7070Spatrick   using OverridesTy = SmallVector<const ObjCMethodDecl *, 8>;
1457e5dd7070Spatrick 
1458e5dd7070Spatrick   OverridesTy Overrides;
1459e5dd7070Spatrick   getOverriddenMethods(Overrides);
1460e5dd7070Spatrick   for (const auto *Override : Overrides)
1461e5dd7070Spatrick     if (const ObjCPropertyDecl *Prop = Override->findPropertyDecl(false))
1462e5dd7070Spatrick       return Prop;
1463e5dd7070Spatrick 
1464e5dd7070Spatrick   return nullptr;
1465e5dd7070Spatrick }
1466e5dd7070Spatrick 
1467e5dd7070Spatrick //===----------------------------------------------------------------------===//
1468e5dd7070Spatrick // ObjCTypeParamDecl
1469e5dd7070Spatrick //===----------------------------------------------------------------------===//
1470e5dd7070Spatrick 
anchor()1471e5dd7070Spatrick void ObjCTypeParamDecl::anchor() {}
1472e5dd7070Spatrick 
Create(ASTContext & ctx,DeclContext * dc,ObjCTypeParamVariance variance,SourceLocation varianceLoc,unsigned index,SourceLocation nameLoc,IdentifierInfo * name,SourceLocation colonLoc,TypeSourceInfo * boundInfo)1473e5dd7070Spatrick ObjCTypeParamDecl *ObjCTypeParamDecl::Create(ASTContext &ctx, DeclContext *dc,
1474e5dd7070Spatrick                                              ObjCTypeParamVariance variance,
1475e5dd7070Spatrick                                              SourceLocation varianceLoc,
1476e5dd7070Spatrick                                              unsigned index,
1477e5dd7070Spatrick                                              SourceLocation nameLoc,
1478e5dd7070Spatrick                                              IdentifierInfo *name,
1479e5dd7070Spatrick                                              SourceLocation colonLoc,
1480e5dd7070Spatrick                                              TypeSourceInfo *boundInfo) {
1481e5dd7070Spatrick   auto *TPDecl =
1482e5dd7070Spatrick     new (ctx, dc) ObjCTypeParamDecl(ctx, dc, variance, varianceLoc, index,
1483e5dd7070Spatrick                                     nameLoc, name, colonLoc, boundInfo);
1484e5dd7070Spatrick   QualType TPType = ctx.getObjCTypeParamType(TPDecl, {});
1485e5dd7070Spatrick   TPDecl->setTypeForDecl(TPType.getTypePtr());
1486e5dd7070Spatrick   return TPDecl;
1487e5dd7070Spatrick }
1488e5dd7070Spatrick 
CreateDeserialized(ASTContext & ctx,unsigned ID)1489e5dd7070Spatrick ObjCTypeParamDecl *ObjCTypeParamDecl::CreateDeserialized(ASTContext &ctx,
1490e5dd7070Spatrick                                                          unsigned ID) {
1491e5dd7070Spatrick   return new (ctx, ID) ObjCTypeParamDecl(ctx, nullptr,
1492e5dd7070Spatrick                                          ObjCTypeParamVariance::Invariant,
1493e5dd7070Spatrick                                          SourceLocation(), 0, SourceLocation(),
1494e5dd7070Spatrick                                          nullptr, SourceLocation(), nullptr);
1495e5dd7070Spatrick }
1496e5dd7070Spatrick 
getSourceRange() const1497e5dd7070Spatrick SourceRange ObjCTypeParamDecl::getSourceRange() const {
1498e5dd7070Spatrick   SourceLocation startLoc = VarianceLoc;
1499e5dd7070Spatrick   if (startLoc.isInvalid())
1500e5dd7070Spatrick     startLoc = getLocation();
1501e5dd7070Spatrick 
1502e5dd7070Spatrick   if (hasExplicitBound()) {
1503e5dd7070Spatrick     return SourceRange(startLoc,
1504e5dd7070Spatrick                        getTypeSourceInfo()->getTypeLoc().getEndLoc());
1505e5dd7070Spatrick   }
1506e5dd7070Spatrick 
1507e5dd7070Spatrick   return SourceRange(startLoc);
1508e5dd7070Spatrick }
1509e5dd7070Spatrick 
1510e5dd7070Spatrick //===----------------------------------------------------------------------===//
1511e5dd7070Spatrick // ObjCTypeParamList
1512e5dd7070Spatrick //===----------------------------------------------------------------------===//
ObjCTypeParamList(SourceLocation lAngleLoc,ArrayRef<ObjCTypeParamDecl * > typeParams,SourceLocation rAngleLoc)1513e5dd7070Spatrick ObjCTypeParamList::ObjCTypeParamList(SourceLocation lAngleLoc,
1514e5dd7070Spatrick                                      ArrayRef<ObjCTypeParamDecl *> typeParams,
1515e5dd7070Spatrick                                      SourceLocation rAngleLoc)
1516a9ac8606Spatrick     : Brackets(lAngleLoc, rAngleLoc), NumParams(typeParams.size()) {
1517e5dd7070Spatrick   std::copy(typeParams.begin(), typeParams.end(), begin());
1518e5dd7070Spatrick }
1519e5dd7070Spatrick 
create(ASTContext & ctx,SourceLocation lAngleLoc,ArrayRef<ObjCTypeParamDecl * > typeParams,SourceLocation rAngleLoc)1520e5dd7070Spatrick ObjCTypeParamList *ObjCTypeParamList::create(
1521e5dd7070Spatrick                      ASTContext &ctx,
1522e5dd7070Spatrick                      SourceLocation lAngleLoc,
1523e5dd7070Spatrick                      ArrayRef<ObjCTypeParamDecl *> typeParams,
1524e5dd7070Spatrick                      SourceLocation rAngleLoc) {
1525e5dd7070Spatrick   void *mem =
1526e5dd7070Spatrick       ctx.Allocate(totalSizeToAlloc<ObjCTypeParamDecl *>(typeParams.size()),
1527e5dd7070Spatrick                    alignof(ObjCTypeParamList));
1528e5dd7070Spatrick   return new (mem) ObjCTypeParamList(lAngleLoc, typeParams, rAngleLoc);
1529e5dd7070Spatrick }
1530e5dd7070Spatrick 
gatherDefaultTypeArgs(SmallVectorImpl<QualType> & typeArgs) const1531e5dd7070Spatrick void ObjCTypeParamList::gatherDefaultTypeArgs(
1532e5dd7070Spatrick        SmallVectorImpl<QualType> &typeArgs) const {
1533e5dd7070Spatrick   typeArgs.reserve(size());
1534*12c85518Srobert   for (auto *typeParam : *this)
1535e5dd7070Spatrick     typeArgs.push_back(typeParam->getUnderlyingType());
1536e5dd7070Spatrick }
1537e5dd7070Spatrick 
1538e5dd7070Spatrick //===----------------------------------------------------------------------===//
1539e5dd7070Spatrick // ObjCInterfaceDecl
1540e5dd7070Spatrick //===----------------------------------------------------------------------===//
1541e5dd7070Spatrick 
Create(const ASTContext & C,DeclContext * DC,SourceLocation atLoc,IdentifierInfo * Id,ObjCTypeParamList * typeParamList,ObjCInterfaceDecl * PrevDecl,SourceLocation ClassLoc,bool isInternal)1542e5dd7070Spatrick ObjCInterfaceDecl *ObjCInterfaceDecl::Create(const ASTContext &C,
1543e5dd7070Spatrick                                              DeclContext *DC,
1544e5dd7070Spatrick                                              SourceLocation atLoc,
1545e5dd7070Spatrick                                              IdentifierInfo *Id,
1546e5dd7070Spatrick                                              ObjCTypeParamList *typeParamList,
1547e5dd7070Spatrick                                              ObjCInterfaceDecl *PrevDecl,
1548e5dd7070Spatrick                                              SourceLocation ClassLoc,
1549e5dd7070Spatrick                                              bool isInternal){
1550e5dd7070Spatrick   auto *Result = new (C, DC)
1551e5dd7070Spatrick       ObjCInterfaceDecl(C, DC, atLoc, Id, typeParamList, ClassLoc, PrevDecl,
1552e5dd7070Spatrick                         isInternal);
1553e5dd7070Spatrick   Result->Data.setInt(!C.getLangOpts().Modules);
1554e5dd7070Spatrick   C.getObjCInterfaceType(Result, PrevDecl);
1555e5dd7070Spatrick   return Result;
1556e5dd7070Spatrick }
1557e5dd7070Spatrick 
CreateDeserialized(const ASTContext & C,unsigned ID)1558e5dd7070Spatrick ObjCInterfaceDecl *ObjCInterfaceDecl::CreateDeserialized(const ASTContext &C,
1559e5dd7070Spatrick                                                          unsigned ID) {
1560e5dd7070Spatrick   auto *Result = new (C, ID)
1561e5dd7070Spatrick       ObjCInterfaceDecl(C, nullptr, SourceLocation(), nullptr, nullptr,
1562e5dd7070Spatrick                         SourceLocation(), nullptr, false);
1563e5dd7070Spatrick   Result->Data.setInt(!C.getLangOpts().Modules);
1564e5dd7070Spatrick   return Result;
1565e5dd7070Spatrick }
1566e5dd7070Spatrick 
ObjCInterfaceDecl(const ASTContext & C,DeclContext * DC,SourceLocation AtLoc,IdentifierInfo * Id,ObjCTypeParamList * typeParamList,SourceLocation CLoc,ObjCInterfaceDecl * PrevDecl,bool IsInternal)1567e5dd7070Spatrick ObjCInterfaceDecl::ObjCInterfaceDecl(const ASTContext &C, DeclContext *DC,
1568e5dd7070Spatrick                                      SourceLocation AtLoc, IdentifierInfo *Id,
1569e5dd7070Spatrick                                      ObjCTypeParamList *typeParamList,
1570e5dd7070Spatrick                                      SourceLocation CLoc,
1571e5dd7070Spatrick                                      ObjCInterfaceDecl *PrevDecl,
1572e5dd7070Spatrick                                      bool IsInternal)
1573e5dd7070Spatrick     : ObjCContainerDecl(ObjCInterface, DC, Id, CLoc, AtLoc),
1574e5dd7070Spatrick       redeclarable_base(C) {
1575e5dd7070Spatrick   setPreviousDecl(PrevDecl);
1576e5dd7070Spatrick 
1577e5dd7070Spatrick   // Copy the 'data' pointer over.
1578e5dd7070Spatrick   if (PrevDecl)
1579e5dd7070Spatrick     Data = PrevDecl->Data;
1580e5dd7070Spatrick 
1581e5dd7070Spatrick   setImplicit(IsInternal);
1582e5dd7070Spatrick 
1583e5dd7070Spatrick   setTypeParamList(typeParamList);
1584e5dd7070Spatrick }
1585e5dd7070Spatrick 
LoadExternalDefinition() const1586e5dd7070Spatrick void ObjCInterfaceDecl::LoadExternalDefinition() const {
1587e5dd7070Spatrick   assert(data().ExternallyCompleted && "Class is not externally completed");
1588e5dd7070Spatrick   data().ExternallyCompleted = false;
1589e5dd7070Spatrick   getASTContext().getExternalSource()->CompleteType(
1590e5dd7070Spatrick                                         const_cast<ObjCInterfaceDecl *>(this));
1591e5dd7070Spatrick }
1592e5dd7070Spatrick 
setExternallyCompleted()1593e5dd7070Spatrick void ObjCInterfaceDecl::setExternallyCompleted() {
1594e5dd7070Spatrick   assert(getASTContext().getExternalSource() &&
1595e5dd7070Spatrick          "Class can't be externally completed without an external source");
1596e5dd7070Spatrick   assert(hasDefinition() &&
1597e5dd7070Spatrick          "Forward declarations can't be externally completed");
1598e5dd7070Spatrick   data().ExternallyCompleted = true;
1599e5dd7070Spatrick }
1600e5dd7070Spatrick 
setHasDesignatedInitializers()1601e5dd7070Spatrick void ObjCInterfaceDecl::setHasDesignatedInitializers() {
1602e5dd7070Spatrick   // Check for a complete definition and recover if not so.
1603e5dd7070Spatrick   if (!isThisDeclarationADefinition())
1604e5dd7070Spatrick     return;
1605e5dd7070Spatrick   data().HasDesignatedInitializers = true;
1606e5dd7070Spatrick }
1607e5dd7070Spatrick 
hasDesignatedInitializers() const1608e5dd7070Spatrick bool ObjCInterfaceDecl::hasDesignatedInitializers() const {
1609e5dd7070Spatrick   // Check for a complete definition and recover if not so.
1610e5dd7070Spatrick   if (!isThisDeclarationADefinition())
1611e5dd7070Spatrick     return false;
1612e5dd7070Spatrick   if (data().ExternallyCompleted)
1613e5dd7070Spatrick     LoadExternalDefinition();
1614e5dd7070Spatrick 
1615e5dd7070Spatrick   return data().HasDesignatedInitializers;
1616e5dd7070Spatrick }
1617e5dd7070Spatrick 
1618e5dd7070Spatrick StringRef
getObjCRuntimeNameAsString() const1619e5dd7070Spatrick ObjCInterfaceDecl::getObjCRuntimeNameAsString() const {
1620e5dd7070Spatrick   if (const auto *ObjCRTName = getAttr<ObjCRuntimeNameAttr>())
1621e5dd7070Spatrick     return ObjCRTName->getMetadataName();
1622e5dd7070Spatrick 
1623e5dd7070Spatrick   return getName();
1624e5dd7070Spatrick }
1625e5dd7070Spatrick 
1626e5dd7070Spatrick StringRef
getObjCRuntimeNameAsString() const1627e5dd7070Spatrick ObjCImplementationDecl::getObjCRuntimeNameAsString() const {
1628e5dd7070Spatrick   if (ObjCInterfaceDecl *ID =
1629e5dd7070Spatrick       const_cast<ObjCImplementationDecl*>(this)->getClassInterface())
1630e5dd7070Spatrick     return ID->getObjCRuntimeNameAsString();
1631e5dd7070Spatrick 
1632e5dd7070Spatrick   return getName();
1633e5dd7070Spatrick }
1634e5dd7070Spatrick 
getImplementation() const1635e5dd7070Spatrick ObjCImplementationDecl *ObjCInterfaceDecl::getImplementation() const {
1636e5dd7070Spatrick   if (const ObjCInterfaceDecl *Def = getDefinition()) {
1637e5dd7070Spatrick     if (data().ExternallyCompleted)
1638e5dd7070Spatrick       LoadExternalDefinition();
1639e5dd7070Spatrick 
1640e5dd7070Spatrick     return getASTContext().getObjCImplementation(
1641e5dd7070Spatrick              const_cast<ObjCInterfaceDecl*>(Def));
1642e5dd7070Spatrick   }
1643e5dd7070Spatrick 
1644e5dd7070Spatrick   // FIXME: Should make sure no callers ever do this.
1645e5dd7070Spatrick   return nullptr;
1646e5dd7070Spatrick }
1647e5dd7070Spatrick 
setImplementation(ObjCImplementationDecl * ImplD)1648e5dd7070Spatrick void ObjCInterfaceDecl::setImplementation(ObjCImplementationDecl *ImplD) {
1649e5dd7070Spatrick   getASTContext().setObjCImplementation(getDefinition(), ImplD);
1650e5dd7070Spatrick }
1651e5dd7070Spatrick 
1652e5dd7070Spatrick namespace {
1653e5dd7070Spatrick 
1654e5dd7070Spatrick struct SynthesizeIvarChunk {
1655e5dd7070Spatrick   uint64_t Size;
1656e5dd7070Spatrick   ObjCIvarDecl *Ivar;
1657e5dd7070Spatrick 
SynthesizeIvarChunk__anoncb998e9e0211::SynthesizeIvarChunk1658e5dd7070Spatrick   SynthesizeIvarChunk(uint64_t size, ObjCIvarDecl *ivar)
1659e5dd7070Spatrick       : Size(size), Ivar(ivar) {}
1660e5dd7070Spatrick };
1661e5dd7070Spatrick 
operator <(const SynthesizeIvarChunk & LHS,const SynthesizeIvarChunk & RHS)1662e5dd7070Spatrick bool operator<(const SynthesizeIvarChunk & LHS,
1663e5dd7070Spatrick                const SynthesizeIvarChunk &RHS) {
1664e5dd7070Spatrick     return LHS.Size < RHS.Size;
1665e5dd7070Spatrick }
1666e5dd7070Spatrick 
1667e5dd7070Spatrick } // namespace
1668e5dd7070Spatrick 
1669e5dd7070Spatrick /// all_declared_ivar_begin - return first ivar declared in this class,
1670e5dd7070Spatrick /// its extensions and its implementation. Lazily build the list on first
1671e5dd7070Spatrick /// access.
1672e5dd7070Spatrick ///
1673e5dd7070Spatrick /// Caveat: The list returned by this method reflects the current
1674e5dd7070Spatrick /// state of the parser. The cache will be updated for every ivar
1675e5dd7070Spatrick /// added by an extension or the implementation when they are
1676e5dd7070Spatrick /// encountered.
1677e5dd7070Spatrick /// See also ObjCIvarDecl::Create().
all_declared_ivar_begin()1678e5dd7070Spatrick ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() {
1679e5dd7070Spatrick   // FIXME: Should make sure no callers ever do this.
1680e5dd7070Spatrick   if (!hasDefinition())
1681e5dd7070Spatrick     return nullptr;
1682e5dd7070Spatrick 
1683e5dd7070Spatrick   ObjCIvarDecl *curIvar = nullptr;
1684e5dd7070Spatrick   if (!data().IvarList) {
1685*12c85518Srobert     // Force ivar deserialization upfront, before building IvarList.
1686*12c85518Srobert     (void)ivar_empty();
1687*12c85518Srobert     for (const auto *Ext : known_extensions()) {
1688*12c85518Srobert       (void)Ext->ivar_empty();
1689*12c85518Srobert     }
1690e5dd7070Spatrick     if (!ivar_empty()) {
1691e5dd7070Spatrick       ObjCInterfaceDecl::ivar_iterator I = ivar_begin(), E = ivar_end();
1692e5dd7070Spatrick       data().IvarList = *I; ++I;
1693e5dd7070Spatrick       for (curIvar = data().IvarList; I != E; curIvar = *I, ++I)
1694e5dd7070Spatrick         curIvar->setNextIvar(*I);
1695e5dd7070Spatrick     }
1696e5dd7070Spatrick 
1697e5dd7070Spatrick     for (const auto *Ext : known_extensions()) {
1698e5dd7070Spatrick       if (!Ext->ivar_empty()) {
1699e5dd7070Spatrick         ObjCCategoryDecl::ivar_iterator
1700e5dd7070Spatrick           I = Ext->ivar_begin(),
1701e5dd7070Spatrick           E = Ext->ivar_end();
1702e5dd7070Spatrick         if (!data().IvarList) {
1703e5dd7070Spatrick           data().IvarList = *I; ++I;
1704e5dd7070Spatrick           curIvar = data().IvarList;
1705e5dd7070Spatrick         }
1706e5dd7070Spatrick         for ( ;I != E; curIvar = *I, ++I)
1707e5dd7070Spatrick           curIvar->setNextIvar(*I);
1708e5dd7070Spatrick       }
1709e5dd7070Spatrick     }
1710e5dd7070Spatrick     data().IvarListMissingImplementation = true;
1711e5dd7070Spatrick   }
1712e5dd7070Spatrick 
1713e5dd7070Spatrick   // cached and complete!
1714e5dd7070Spatrick   if (!data().IvarListMissingImplementation)
1715e5dd7070Spatrick       return data().IvarList;
1716e5dd7070Spatrick 
1717e5dd7070Spatrick   if (ObjCImplementationDecl *ImplDecl = getImplementation()) {
1718e5dd7070Spatrick     data().IvarListMissingImplementation = false;
1719e5dd7070Spatrick     if (!ImplDecl->ivar_empty()) {
1720e5dd7070Spatrick       SmallVector<SynthesizeIvarChunk, 16> layout;
1721e5dd7070Spatrick       for (auto *IV : ImplDecl->ivars()) {
1722e5dd7070Spatrick         if (IV->getSynthesize() && !IV->isInvalidDecl()) {
1723e5dd7070Spatrick           layout.push_back(SynthesizeIvarChunk(
1724e5dd7070Spatrick                              IV->getASTContext().getTypeSize(IV->getType()), IV));
1725e5dd7070Spatrick           continue;
1726e5dd7070Spatrick         }
1727e5dd7070Spatrick         if (!data().IvarList)
1728e5dd7070Spatrick           data().IvarList = IV;
1729e5dd7070Spatrick         else
1730e5dd7070Spatrick           curIvar->setNextIvar(IV);
1731e5dd7070Spatrick         curIvar = IV;
1732e5dd7070Spatrick       }
1733e5dd7070Spatrick 
1734e5dd7070Spatrick       if (!layout.empty()) {
1735e5dd7070Spatrick         // Order synthesized ivars by their size.
1736e5dd7070Spatrick         llvm::stable_sort(layout);
1737e5dd7070Spatrick         unsigned Ix = 0, EIx = layout.size();
1738e5dd7070Spatrick         if (!data().IvarList) {
1739e5dd7070Spatrick           data().IvarList = layout[0].Ivar; Ix++;
1740e5dd7070Spatrick           curIvar = data().IvarList;
1741e5dd7070Spatrick         }
1742e5dd7070Spatrick         for ( ; Ix != EIx; curIvar = layout[Ix].Ivar, Ix++)
1743e5dd7070Spatrick           curIvar->setNextIvar(layout[Ix].Ivar);
1744e5dd7070Spatrick       }
1745e5dd7070Spatrick     }
1746e5dd7070Spatrick   }
1747e5dd7070Spatrick   return data().IvarList;
1748e5dd7070Spatrick }
1749e5dd7070Spatrick 
1750e5dd7070Spatrick /// FindCategoryDeclaration - Finds category declaration in the list of
1751e5dd7070Spatrick /// categories for this class and returns it. Name of the category is passed
1752e5dd7070Spatrick /// in 'CategoryId'. If category not found, return 0;
1753e5dd7070Spatrick ///
1754e5dd7070Spatrick ObjCCategoryDecl *
FindCategoryDeclaration(IdentifierInfo * CategoryId) const1755e5dd7070Spatrick ObjCInterfaceDecl::FindCategoryDeclaration(IdentifierInfo *CategoryId) const {
1756e5dd7070Spatrick   // FIXME: Should make sure no callers ever do this.
1757e5dd7070Spatrick   if (!hasDefinition())
1758e5dd7070Spatrick     return nullptr;
1759e5dd7070Spatrick 
1760e5dd7070Spatrick   if (data().ExternallyCompleted)
1761e5dd7070Spatrick     LoadExternalDefinition();
1762e5dd7070Spatrick 
1763e5dd7070Spatrick   for (auto *Cat : visible_categories())
1764e5dd7070Spatrick     if (Cat->getIdentifier() == CategoryId)
1765e5dd7070Spatrick       return Cat;
1766e5dd7070Spatrick 
1767e5dd7070Spatrick   return nullptr;
1768e5dd7070Spatrick }
1769e5dd7070Spatrick 
1770e5dd7070Spatrick ObjCMethodDecl *
getCategoryInstanceMethod(Selector Sel) const1771e5dd7070Spatrick ObjCInterfaceDecl::getCategoryInstanceMethod(Selector Sel) const {
1772e5dd7070Spatrick   for (const auto *Cat : visible_categories()) {
1773e5dd7070Spatrick     if (ObjCCategoryImplDecl *Impl = Cat->getImplementation())
1774e5dd7070Spatrick       if (ObjCMethodDecl *MD = Impl->getInstanceMethod(Sel))
1775e5dd7070Spatrick         return MD;
1776e5dd7070Spatrick   }
1777e5dd7070Spatrick 
1778e5dd7070Spatrick   return nullptr;
1779e5dd7070Spatrick }
1780e5dd7070Spatrick 
getCategoryClassMethod(Selector Sel) const1781e5dd7070Spatrick ObjCMethodDecl *ObjCInterfaceDecl::getCategoryClassMethod(Selector Sel) const {
1782e5dd7070Spatrick   for (const auto *Cat : visible_categories()) {
1783e5dd7070Spatrick     if (ObjCCategoryImplDecl *Impl = Cat->getImplementation())
1784e5dd7070Spatrick       if (ObjCMethodDecl *MD = Impl->getClassMethod(Sel))
1785e5dd7070Spatrick         return MD;
1786e5dd7070Spatrick   }
1787e5dd7070Spatrick 
1788e5dd7070Spatrick   return nullptr;
1789e5dd7070Spatrick }
1790e5dd7070Spatrick 
1791e5dd7070Spatrick /// ClassImplementsProtocol - Checks that 'lProto' protocol
1792e5dd7070Spatrick /// has been implemented in IDecl class, its super class or categories (if
1793e5dd7070Spatrick /// lookupCategory is true).
ClassImplementsProtocol(ObjCProtocolDecl * lProto,bool lookupCategory,bool RHSIsQualifiedID)1794e5dd7070Spatrick bool ObjCInterfaceDecl::ClassImplementsProtocol(ObjCProtocolDecl *lProto,
1795e5dd7070Spatrick                                     bool lookupCategory,
1796e5dd7070Spatrick                                     bool RHSIsQualifiedID) {
1797e5dd7070Spatrick   if (!hasDefinition())
1798e5dd7070Spatrick     return false;
1799e5dd7070Spatrick 
1800e5dd7070Spatrick   ObjCInterfaceDecl *IDecl = this;
1801e5dd7070Spatrick   // 1st, look up the class.
1802e5dd7070Spatrick   for (auto *PI : IDecl->protocols()){
1803e5dd7070Spatrick     if (getASTContext().ProtocolCompatibleWithProtocol(lProto, PI))
1804e5dd7070Spatrick       return true;
1805e5dd7070Spatrick     // This is dubious and is added to be compatible with gcc.  In gcc, it is
1806e5dd7070Spatrick     // also allowed assigning a protocol-qualified 'id' type to a LHS object
1807e5dd7070Spatrick     // when protocol in qualified LHS is in list of protocols in the rhs 'id'
1808e5dd7070Spatrick     // object. This IMO, should be a bug.
1809e5dd7070Spatrick     // FIXME: Treat this as an extension, and flag this as an error when GCC
1810e5dd7070Spatrick     // extensions are not enabled.
1811e5dd7070Spatrick     if (RHSIsQualifiedID &&
1812e5dd7070Spatrick         getASTContext().ProtocolCompatibleWithProtocol(PI, lProto))
1813e5dd7070Spatrick       return true;
1814e5dd7070Spatrick   }
1815e5dd7070Spatrick 
1816e5dd7070Spatrick   // 2nd, look up the category.
1817e5dd7070Spatrick   if (lookupCategory)
1818e5dd7070Spatrick     for (const auto *Cat : visible_categories()) {
1819e5dd7070Spatrick       for (auto *PI : Cat->protocols())
1820e5dd7070Spatrick         if (getASTContext().ProtocolCompatibleWithProtocol(lProto, PI))
1821e5dd7070Spatrick           return true;
1822e5dd7070Spatrick     }
1823e5dd7070Spatrick 
1824e5dd7070Spatrick   // 3rd, look up the super class(s)
1825e5dd7070Spatrick   if (IDecl->getSuperClass())
1826e5dd7070Spatrick     return
1827e5dd7070Spatrick   IDecl->getSuperClass()->ClassImplementsProtocol(lProto, lookupCategory,
1828e5dd7070Spatrick                                                   RHSIsQualifiedID);
1829e5dd7070Spatrick 
1830e5dd7070Spatrick   return false;
1831e5dd7070Spatrick }
1832e5dd7070Spatrick 
1833e5dd7070Spatrick //===----------------------------------------------------------------------===//
1834e5dd7070Spatrick // ObjCIvarDecl
1835e5dd7070Spatrick //===----------------------------------------------------------------------===//
1836e5dd7070Spatrick 
anchor()1837e5dd7070Spatrick void ObjCIvarDecl::anchor() {}
1838e5dd7070Spatrick 
Create(ASTContext & C,ObjCContainerDecl * DC,SourceLocation StartLoc,SourceLocation IdLoc,IdentifierInfo * Id,QualType T,TypeSourceInfo * TInfo,AccessControl ac,Expr * BW,bool synthesized)1839e5dd7070Spatrick ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC,
1840e5dd7070Spatrick                                    SourceLocation StartLoc,
1841e5dd7070Spatrick                                    SourceLocation IdLoc, IdentifierInfo *Id,
1842e5dd7070Spatrick                                    QualType T, TypeSourceInfo *TInfo,
1843e5dd7070Spatrick                                    AccessControl ac, Expr *BW,
1844e5dd7070Spatrick                                    bool synthesized) {
1845e5dd7070Spatrick   if (DC) {
1846e5dd7070Spatrick     // Ivar's can only appear in interfaces, implementations (via synthesized
1847e5dd7070Spatrick     // properties), and class extensions (via direct declaration, or synthesized
1848e5dd7070Spatrick     // properties).
1849e5dd7070Spatrick     //
1850e5dd7070Spatrick     // FIXME: This should really be asserting this:
1851e5dd7070Spatrick     //   (isa<ObjCCategoryDecl>(DC) &&
1852e5dd7070Spatrick     //    cast<ObjCCategoryDecl>(DC)->IsClassExtension()))
1853e5dd7070Spatrick     // but unfortunately we sometimes place ivars into non-class extension
1854e5dd7070Spatrick     // categories on error. This breaks an AST invariant, and should not be
1855e5dd7070Spatrick     // fixed.
1856e5dd7070Spatrick     assert((isa<ObjCInterfaceDecl>(DC) || isa<ObjCImplementationDecl>(DC) ||
1857e5dd7070Spatrick             isa<ObjCCategoryDecl>(DC)) &&
1858e5dd7070Spatrick            "Invalid ivar decl context!");
1859e5dd7070Spatrick     // Once a new ivar is created in any of class/class-extension/implementation
1860e5dd7070Spatrick     // decl contexts, the previously built IvarList must be rebuilt.
1861e5dd7070Spatrick     auto *ID = dyn_cast<ObjCInterfaceDecl>(DC);
1862e5dd7070Spatrick     if (!ID) {
1863e5dd7070Spatrick       if (auto *IM = dyn_cast<ObjCImplementationDecl>(DC))
1864e5dd7070Spatrick         ID = IM->getClassInterface();
1865e5dd7070Spatrick       else
1866e5dd7070Spatrick         ID = cast<ObjCCategoryDecl>(DC)->getClassInterface();
1867e5dd7070Spatrick     }
1868e5dd7070Spatrick     ID->setIvarList(nullptr);
1869e5dd7070Spatrick   }
1870e5dd7070Spatrick 
1871e5dd7070Spatrick   return new (C, DC) ObjCIvarDecl(DC, StartLoc, IdLoc, Id, T, TInfo, ac, BW,
1872e5dd7070Spatrick                                   synthesized);
1873e5dd7070Spatrick }
1874e5dd7070Spatrick 
CreateDeserialized(ASTContext & C,unsigned ID)1875e5dd7070Spatrick ObjCIvarDecl *ObjCIvarDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
1876e5dd7070Spatrick   return new (C, ID) ObjCIvarDecl(nullptr, SourceLocation(), SourceLocation(),
1877e5dd7070Spatrick                                   nullptr, QualType(), nullptr,
1878e5dd7070Spatrick                                   ObjCIvarDecl::None, nullptr, false);
1879e5dd7070Spatrick }
1880e5dd7070Spatrick 
getContainingInterface()1881*12c85518Srobert ObjCInterfaceDecl *ObjCIvarDecl::getContainingInterface() {
1882*12c85518Srobert   auto *DC = cast<ObjCContainerDecl>(getDeclContext());
1883e5dd7070Spatrick 
1884e5dd7070Spatrick   switch (DC->getKind()) {
1885e5dd7070Spatrick   default:
1886e5dd7070Spatrick   case ObjCCategoryImpl:
1887e5dd7070Spatrick   case ObjCProtocol:
1888e5dd7070Spatrick     llvm_unreachable("invalid ivar container!");
1889e5dd7070Spatrick 
1890e5dd7070Spatrick     // Ivars can only appear in class extension categories.
1891e5dd7070Spatrick   case ObjCCategory: {
1892*12c85518Srobert     auto *CD = cast<ObjCCategoryDecl>(DC);
1893e5dd7070Spatrick     assert(CD->IsClassExtension() && "invalid container for ivar!");
1894e5dd7070Spatrick     return CD->getClassInterface();
1895e5dd7070Spatrick   }
1896e5dd7070Spatrick 
1897e5dd7070Spatrick   case ObjCImplementation:
1898e5dd7070Spatrick     return cast<ObjCImplementationDecl>(DC)->getClassInterface();
1899e5dd7070Spatrick 
1900e5dd7070Spatrick   case ObjCInterface:
1901e5dd7070Spatrick     return cast<ObjCInterfaceDecl>(DC);
1902e5dd7070Spatrick   }
1903e5dd7070Spatrick }
1904e5dd7070Spatrick 
getUsageType(QualType objectType) const1905e5dd7070Spatrick QualType ObjCIvarDecl::getUsageType(QualType objectType) const {
1906e5dd7070Spatrick   return getType().substObjCMemberType(objectType, getDeclContext(),
1907e5dd7070Spatrick                                        ObjCSubstitutionContext::Property);
1908e5dd7070Spatrick }
1909e5dd7070Spatrick 
1910e5dd7070Spatrick //===----------------------------------------------------------------------===//
1911e5dd7070Spatrick // ObjCAtDefsFieldDecl
1912e5dd7070Spatrick //===----------------------------------------------------------------------===//
1913e5dd7070Spatrick 
anchor()1914e5dd7070Spatrick void ObjCAtDefsFieldDecl::anchor() {}
1915e5dd7070Spatrick 
1916e5dd7070Spatrick ObjCAtDefsFieldDecl
Create(ASTContext & C,DeclContext * DC,SourceLocation StartLoc,SourceLocation IdLoc,IdentifierInfo * Id,QualType T,Expr * BW)1917e5dd7070Spatrick *ObjCAtDefsFieldDecl::Create(ASTContext &C, DeclContext *DC,
1918e5dd7070Spatrick                              SourceLocation StartLoc,  SourceLocation IdLoc,
1919e5dd7070Spatrick                              IdentifierInfo *Id, QualType T, Expr *BW) {
1920e5dd7070Spatrick   return new (C, DC) ObjCAtDefsFieldDecl(DC, StartLoc, IdLoc, Id, T, BW);
1921e5dd7070Spatrick }
1922e5dd7070Spatrick 
CreateDeserialized(ASTContext & C,unsigned ID)1923e5dd7070Spatrick ObjCAtDefsFieldDecl *ObjCAtDefsFieldDecl::CreateDeserialized(ASTContext &C,
1924e5dd7070Spatrick                                                              unsigned ID) {
1925e5dd7070Spatrick   return new (C, ID) ObjCAtDefsFieldDecl(nullptr, SourceLocation(),
1926e5dd7070Spatrick                                          SourceLocation(), nullptr, QualType(),
1927e5dd7070Spatrick                                          nullptr);
1928e5dd7070Spatrick }
1929e5dd7070Spatrick 
1930e5dd7070Spatrick //===----------------------------------------------------------------------===//
1931e5dd7070Spatrick // ObjCProtocolDecl
1932e5dd7070Spatrick //===----------------------------------------------------------------------===//
1933e5dd7070Spatrick 
anchor()1934e5dd7070Spatrick void ObjCProtocolDecl::anchor() {}
1935e5dd7070Spatrick 
ObjCProtocolDecl(ASTContext & C,DeclContext * DC,IdentifierInfo * Id,SourceLocation nameLoc,SourceLocation atStartLoc,ObjCProtocolDecl * PrevDecl)1936e5dd7070Spatrick ObjCProtocolDecl::ObjCProtocolDecl(ASTContext &C, DeclContext *DC,
1937e5dd7070Spatrick                                    IdentifierInfo *Id, SourceLocation nameLoc,
1938e5dd7070Spatrick                                    SourceLocation atStartLoc,
1939e5dd7070Spatrick                                    ObjCProtocolDecl *PrevDecl)
1940e5dd7070Spatrick     : ObjCContainerDecl(ObjCProtocol, DC, Id, nameLoc, atStartLoc),
1941e5dd7070Spatrick       redeclarable_base(C) {
1942e5dd7070Spatrick   setPreviousDecl(PrevDecl);
1943e5dd7070Spatrick   if (PrevDecl)
1944e5dd7070Spatrick     Data = PrevDecl->Data;
1945e5dd7070Spatrick }
1946e5dd7070Spatrick 
Create(ASTContext & C,DeclContext * DC,IdentifierInfo * Id,SourceLocation nameLoc,SourceLocation atStartLoc,ObjCProtocolDecl * PrevDecl)1947e5dd7070Spatrick ObjCProtocolDecl *ObjCProtocolDecl::Create(ASTContext &C, DeclContext *DC,
1948e5dd7070Spatrick                                            IdentifierInfo *Id,
1949e5dd7070Spatrick                                            SourceLocation nameLoc,
1950e5dd7070Spatrick                                            SourceLocation atStartLoc,
1951e5dd7070Spatrick                                            ObjCProtocolDecl *PrevDecl) {
1952e5dd7070Spatrick   auto *Result =
1953e5dd7070Spatrick       new (C, DC) ObjCProtocolDecl(C, DC, Id, nameLoc, atStartLoc, PrevDecl);
1954e5dd7070Spatrick   Result->Data.setInt(!C.getLangOpts().Modules);
1955e5dd7070Spatrick   return Result;
1956e5dd7070Spatrick }
1957e5dd7070Spatrick 
CreateDeserialized(ASTContext & C,unsigned ID)1958e5dd7070Spatrick ObjCProtocolDecl *ObjCProtocolDecl::CreateDeserialized(ASTContext &C,
1959e5dd7070Spatrick                                                        unsigned ID) {
1960e5dd7070Spatrick   ObjCProtocolDecl *Result =
1961e5dd7070Spatrick       new (C, ID) ObjCProtocolDecl(C, nullptr, nullptr, SourceLocation(),
1962e5dd7070Spatrick                                    SourceLocation(), nullptr);
1963e5dd7070Spatrick   Result->Data.setInt(!C.getLangOpts().Modules);
1964e5dd7070Spatrick   return Result;
1965e5dd7070Spatrick }
1966e5dd7070Spatrick 
isNonRuntimeProtocol() const1967a9ac8606Spatrick bool ObjCProtocolDecl::isNonRuntimeProtocol() const {
1968a9ac8606Spatrick   return hasAttr<ObjCNonRuntimeProtocolAttr>();
1969a9ac8606Spatrick }
1970a9ac8606Spatrick 
getImpliedProtocols(llvm::DenseSet<const ObjCProtocolDecl * > & IPs) const1971a9ac8606Spatrick void ObjCProtocolDecl::getImpliedProtocols(
1972a9ac8606Spatrick     llvm::DenseSet<const ObjCProtocolDecl *> &IPs) const {
1973a9ac8606Spatrick   std::queue<const ObjCProtocolDecl *> WorkQueue;
1974a9ac8606Spatrick   WorkQueue.push(this);
1975a9ac8606Spatrick 
1976a9ac8606Spatrick   while (!WorkQueue.empty()) {
1977a9ac8606Spatrick     const auto *PD = WorkQueue.front();
1978a9ac8606Spatrick     WorkQueue.pop();
1979a9ac8606Spatrick     for (const auto *Parent : PD->protocols()) {
1980a9ac8606Spatrick       const auto *Can = Parent->getCanonicalDecl();
1981a9ac8606Spatrick       auto Result = IPs.insert(Can);
1982a9ac8606Spatrick       if (Result.second)
1983a9ac8606Spatrick         WorkQueue.push(Parent);
1984a9ac8606Spatrick     }
1985a9ac8606Spatrick   }
1986a9ac8606Spatrick }
1987a9ac8606Spatrick 
lookupProtocolNamed(IdentifierInfo * Name)1988e5dd7070Spatrick ObjCProtocolDecl *ObjCProtocolDecl::lookupProtocolNamed(IdentifierInfo *Name) {
1989e5dd7070Spatrick   ObjCProtocolDecl *PDecl = this;
1990e5dd7070Spatrick 
1991e5dd7070Spatrick   if (Name == getIdentifier())
1992e5dd7070Spatrick     return PDecl;
1993e5dd7070Spatrick 
1994e5dd7070Spatrick   for (auto *I : protocols())
1995e5dd7070Spatrick     if ((PDecl = I->lookupProtocolNamed(Name)))
1996e5dd7070Spatrick       return PDecl;
1997e5dd7070Spatrick 
1998e5dd7070Spatrick   return nullptr;
1999e5dd7070Spatrick }
2000e5dd7070Spatrick 
2001e5dd7070Spatrick // lookupMethod - Lookup a instance/class method in the protocol and protocols
2002e5dd7070Spatrick // it inherited.
lookupMethod(Selector Sel,bool isInstance) const2003e5dd7070Spatrick ObjCMethodDecl *ObjCProtocolDecl::lookupMethod(Selector Sel,
2004e5dd7070Spatrick                                                bool isInstance) const {
2005e5dd7070Spatrick   ObjCMethodDecl *MethodDecl = nullptr;
2006e5dd7070Spatrick 
2007e5dd7070Spatrick   // If there is no definition or the definition is hidden, we don't find
2008e5dd7070Spatrick   // anything.
2009e5dd7070Spatrick   const ObjCProtocolDecl *Def = getDefinition();
2010ec727ea7Spatrick   if (!Def || !Def->isUnconditionallyVisible())
2011e5dd7070Spatrick     return nullptr;
2012e5dd7070Spatrick 
2013e5dd7070Spatrick   if ((MethodDecl = getMethod(Sel, isInstance)))
2014e5dd7070Spatrick     return MethodDecl;
2015e5dd7070Spatrick 
2016e5dd7070Spatrick   for (const auto *I : protocols())
2017e5dd7070Spatrick     if ((MethodDecl = I->lookupMethod(Sel, isInstance)))
2018e5dd7070Spatrick       return MethodDecl;
2019e5dd7070Spatrick   return nullptr;
2020e5dd7070Spatrick }
2021e5dd7070Spatrick 
allocateDefinitionData()2022e5dd7070Spatrick void ObjCProtocolDecl::allocateDefinitionData() {
2023e5dd7070Spatrick   assert(!Data.getPointer() && "Protocol already has a definition!");
2024e5dd7070Spatrick   Data.setPointer(new (getASTContext()) DefinitionData);
2025e5dd7070Spatrick   Data.getPointer()->Definition = this;
2026*12c85518Srobert   Data.getPointer()->HasODRHash = false;
2027e5dd7070Spatrick }
2028e5dd7070Spatrick 
startDefinition()2029e5dd7070Spatrick void ObjCProtocolDecl::startDefinition() {
2030e5dd7070Spatrick   allocateDefinitionData();
2031e5dd7070Spatrick 
2032e5dd7070Spatrick   // Update all of the declarations with a pointer to the definition.
2033e5dd7070Spatrick   for (auto *RD : redecls())
2034e5dd7070Spatrick     RD->Data = this->Data;
2035e5dd7070Spatrick }
2036e5dd7070Spatrick 
startDuplicateDefinitionForComparison()2037*12c85518Srobert void ObjCProtocolDecl::startDuplicateDefinitionForComparison() {
2038*12c85518Srobert   Data.setPointer(nullptr);
2039*12c85518Srobert   allocateDefinitionData();
2040*12c85518Srobert   // Don't propagate data to other redeclarations.
2041*12c85518Srobert }
2042*12c85518Srobert 
mergeDuplicateDefinitionWithCommon(const ObjCProtocolDecl * Definition)2043*12c85518Srobert void ObjCProtocolDecl::mergeDuplicateDefinitionWithCommon(
2044*12c85518Srobert     const ObjCProtocolDecl *Definition) {
2045*12c85518Srobert   Data = Definition->Data;
2046*12c85518Srobert }
2047*12c85518Srobert 
collectPropertiesToImplement(PropertyMap & PM) const2048*12c85518Srobert void ObjCProtocolDecl::collectPropertiesToImplement(PropertyMap &PM) const {
2049e5dd7070Spatrick   if (const ObjCProtocolDecl *PDecl = getDefinition()) {
2050e5dd7070Spatrick     for (auto *Prop : PDecl->properties()) {
2051e5dd7070Spatrick       // Insert into PM if not there already.
2052e5dd7070Spatrick       PM.insert(std::make_pair(
2053e5dd7070Spatrick           std::make_pair(Prop->getIdentifier(), Prop->isClassProperty()),
2054e5dd7070Spatrick           Prop));
2055e5dd7070Spatrick     }
2056e5dd7070Spatrick     // Scan through protocol's protocols.
2057e5dd7070Spatrick     for (const auto *PI : PDecl->protocols())
2058*12c85518Srobert       PI->collectPropertiesToImplement(PM);
2059e5dd7070Spatrick   }
2060e5dd7070Spatrick }
2061e5dd7070Spatrick 
collectInheritedProtocolProperties(const ObjCPropertyDecl * Property,ProtocolPropertySet & PS,PropertyDeclOrder & PO) const2062e5dd7070Spatrick void ObjCProtocolDecl::collectInheritedProtocolProperties(
2063e5dd7070Spatrick     const ObjCPropertyDecl *Property, ProtocolPropertySet &PS,
2064e5dd7070Spatrick     PropertyDeclOrder &PO) const {
2065e5dd7070Spatrick   if (const ObjCProtocolDecl *PDecl = getDefinition()) {
2066e5dd7070Spatrick     if (!PS.insert(PDecl).second)
2067e5dd7070Spatrick       return;
2068e5dd7070Spatrick     for (auto *Prop : PDecl->properties()) {
2069e5dd7070Spatrick       if (Prop == Property)
2070e5dd7070Spatrick         continue;
2071e5dd7070Spatrick       if (Prop->getIdentifier() == Property->getIdentifier()) {
2072e5dd7070Spatrick         PO.push_back(Prop);
2073e5dd7070Spatrick         return;
2074e5dd7070Spatrick       }
2075e5dd7070Spatrick     }
2076e5dd7070Spatrick     // Scan through protocol's protocols which did not have a matching property.
2077e5dd7070Spatrick     for (const auto *PI : PDecl->protocols())
2078e5dd7070Spatrick       PI->collectInheritedProtocolProperties(Property, PS, PO);
2079e5dd7070Spatrick   }
2080e5dd7070Spatrick }
2081e5dd7070Spatrick 
2082e5dd7070Spatrick StringRef
getObjCRuntimeNameAsString() const2083e5dd7070Spatrick ObjCProtocolDecl::getObjCRuntimeNameAsString() const {
2084e5dd7070Spatrick   if (const auto *ObjCRTName = getAttr<ObjCRuntimeNameAttr>())
2085e5dd7070Spatrick     return ObjCRTName->getMetadataName();
2086e5dd7070Spatrick 
2087e5dd7070Spatrick   return getName();
2088e5dd7070Spatrick }
2089e5dd7070Spatrick 
getODRHash()2090*12c85518Srobert unsigned ObjCProtocolDecl::getODRHash() {
2091*12c85518Srobert   assert(hasDefinition() && "ODRHash only for records with definitions");
2092*12c85518Srobert 
2093*12c85518Srobert   // Previously calculated hash is stored in DefinitionData.
2094*12c85518Srobert   if (hasODRHash())
2095*12c85518Srobert     return data().ODRHash;
2096*12c85518Srobert 
2097*12c85518Srobert   // Only calculate hash on first call of getODRHash per record.
2098*12c85518Srobert   ODRHash Hasher;
2099*12c85518Srobert   Hasher.AddObjCProtocolDecl(getDefinition());
2100*12c85518Srobert   data().ODRHash = Hasher.CalculateHash();
2101*12c85518Srobert   setHasODRHash(true);
2102*12c85518Srobert 
2103*12c85518Srobert   return data().ODRHash;
2104*12c85518Srobert }
2105*12c85518Srobert 
hasODRHash() const2106*12c85518Srobert bool ObjCProtocolDecl::hasODRHash() const {
2107*12c85518Srobert   if (!hasDefinition())
2108*12c85518Srobert     return false;
2109*12c85518Srobert   return data().HasODRHash;
2110*12c85518Srobert }
2111*12c85518Srobert 
setHasODRHash(bool HasHash)2112*12c85518Srobert void ObjCProtocolDecl::setHasODRHash(bool HasHash) {
2113*12c85518Srobert   assert(hasDefinition() && "Cannot set ODRHash without definition");
2114*12c85518Srobert   data().HasODRHash = HasHash;
2115*12c85518Srobert }
2116*12c85518Srobert 
2117e5dd7070Spatrick //===----------------------------------------------------------------------===//
2118e5dd7070Spatrick // ObjCCategoryDecl
2119e5dd7070Spatrick //===----------------------------------------------------------------------===//
2120e5dd7070Spatrick 
anchor()2121e5dd7070Spatrick void ObjCCategoryDecl::anchor() {}
2122e5dd7070Spatrick 
ObjCCategoryDecl(DeclContext * DC,SourceLocation AtLoc,SourceLocation ClassNameLoc,SourceLocation CategoryNameLoc,IdentifierInfo * Id,ObjCInterfaceDecl * IDecl,ObjCTypeParamList * typeParamList,SourceLocation IvarLBraceLoc,SourceLocation IvarRBraceLoc)2123e5dd7070Spatrick ObjCCategoryDecl::ObjCCategoryDecl(DeclContext *DC, SourceLocation AtLoc,
2124e5dd7070Spatrick                                    SourceLocation ClassNameLoc,
2125e5dd7070Spatrick                                    SourceLocation CategoryNameLoc,
2126e5dd7070Spatrick                                    IdentifierInfo *Id, ObjCInterfaceDecl *IDecl,
2127e5dd7070Spatrick                                    ObjCTypeParamList *typeParamList,
2128e5dd7070Spatrick                                    SourceLocation IvarLBraceLoc,
2129e5dd7070Spatrick                                    SourceLocation IvarRBraceLoc)
2130e5dd7070Spatrick     : ObjCContainerDecl(ObjCCategory, DC, Id, ClassNameLoc, AtLoc),
2131e5dd7070Spatrick       ClassInterface(IDecl), CategoryNameLoc(CategoryNameLoc),
2132e5dd7070Spatrick       IvarLBraceLoc(IvarLBraceLoc), IvarRBraceLoc(IvarRBraceLoc) {
2133e5dd7070Spatrick   setTypeParamList(typeParamList);
2134e5dd7070Spatrick }
2135e5dd7070Spatrick 
Create(ASTContext & C,DeclContext * DC,SourceLocation AtLoc,SourceLocation ClassNameLoc,SourceLocation CategoryNameLoc,IdentifierInfo * Id,ObjCInterfaceDecl * IDecl,ObjCTypeParamList * typeParamList,SourceLocation IvarLBraceLoc,SourceLocation IvarRBraceLoc)2136e5dd7070Spatrick ObjCCategoryDecl *ObjCCategoryDecl::Create(ASTContext &C, DeclContext *DC,
2137e5dd7070Spatrick                                            SourceLocation AtLoc,
2138e5dd7070Spatrick                                            SourceLocation ClassNameLoc,
2139e5dd7070Spatrick                                            SourceLocation CategoryNameLoc,
2140e5dd7070Spatrick                                            IdentifierInfo *Id,
2141e5dd7070Spatrick                                            ObjCInterfaceDecl *IDecl,
2142e5dd7070Spatrick                                            ObjCTypeParamList *typeParamList,
2143e5dd7070Spatrick                                            SourceLocation IvarLBraceLoc,
2144e5dd7070Spatrick                                            SourceLocation IvarRBraceLoc) {
2145e5dd7070Spatrick   auto *CatDecl =
2146e5dd7070Spatrick       new (C, DC) ObjCCategoryDecl(DC, AtLoc, ClassNameLoc, CategoryNameLoc, Id,
2147e5dd7070Spatrick                                    IDecl, typeParamList, IvarLBraceLoc,
2148e5dd7070Spatrick                                    IvarRBraceLoc);
2149e5dd7070Spatrick   if (IDecl) {
2150e5dd7070Spatrick     // Link this category into its class's category list.
2151e5dd7070Spatrick     CatDecl->NextClassCategory = IDecl->getCategoryListRaw();
2152e5dd7070Spatrick     if (IDecl->hasDefinition()) {
2153e5dd7070Spatrick       IDecl->setCategoryListRaw(CatDecl);
2154e5dd7070Spatrick       if (ASTMutationListener *L = C.getASTMutationListener())
2155e5dd7070Spatrick         L->AddedObjCCategoryToInterface(CatDecl, IDecl);
2156e5dd7070Spatrick     }
2157e5dd7070Spatrick   }
2158e5dd7070Spatrick 
2159e5dd7070Spatrick   return CatDecl;
2160e5dd7070Spatrick }
2161e5dd7070Spatrick 
CreateDeserialized(ASTContext & C,unsigned ID)2162e5dd7070Spatrick ObjCCategoryDecl *ObjCCategoryDecl::CreateDeserialized(ASTContext &C,
2163e5dd7070Spatrick                                                        unsigned ID) {
2164e5dd7070Spatrick   return new (C, ID) ObjCCategoryDecl(nullptr, SourceLocation(),
2165e5dd7070Spatrick                                       SourceLocation(), SourceLocation(),
2166e5dd7070Spatrick                                       nullptr, nullptr, nullptr);
2167e5dd7070Spatrick }
2168e5dd7070Spatrick 
getImplementation() const2169e5dd7070Spatrick ObjCCategoryImplDecl *ObjCCategoryDecl::getImplementation() const {
2170e5dd7070Spatrick   return getASTContext().getObjCImplementation(
2171e5dd7070Spatrick                                            const_cast<ObjCCategoryDecl*>(this));
2172e5dd7070Spatrick }
2173e5dd7070Spatrick 
setImplementation(ObjCCategoryImplDecl * ImplD)2174e5dd7070Spatrick void ObjCCategoryDecl::setImplementation(ObjCCategoryImplDecl *ImplD) {
2175e5dd7070Spatrick   getASTContext().setObjCImplementation(this, ImplD);
2176e5dd7070Spatrick }
2177e5dd7070Spatrick 
setTypeParamList(ObjCTypeParamList * TPL)2178e5dd7070Spatrick void ObjCCategoryDecl::setTypeParamList(ObjCTypeParamList *TPL) {
2179e5dd7070Spatrick   TypeParamList = TPL;
2180e5dd7070Spatrick   if (!TPL)
2181e5dd7070Spatrick     return;
2182e5dd7070Spatrick   // Set the declaration context of each of the type parameters.
2183e5dd7070Spatrick   for (auto *typeParam : *TypeParamList)
2184e5dd7070Spatrick     typeParam->setDeclContext(this);
2185e5dd7070Spatrick }
2186e5dd7070Spatrick 
2187e5dd7070Spatrick //===----------------------------------------------------------------------===//
2188e5dd7070Spatrick // ObjCCategoryImplDecl
2189e5dd7070Spatrick //===----------------------------------------------------------------------===//
2190e5dd7070Spatrick 
anchor()2191e5dd7070Spatrick void ObjCCategoryImplDecl::anchor() {}
2192e5dd7070Spatrick 
2193e5dd7070Spatrick ObjCCategoryImplDecl *
Create(ASTContext & C,DeclContext * DC,IdentifierInfo * Id,ObjCInterfaceDecl * ClassInterface,SourceLocation nameLoc,SourceLocation atStartLoc,SourceLocation CategoryNameLoc)2194e5dd7070Spatrick ObjCCategoryImplDecl::Create(ASTContext &C, DeclContext *DC,
2195e5dd7070Spatrick                              IdentifierInfo *Id,
2196e5dd7070Spatrick                              ObjCInterfaceDecl *ClassInterface,
2197e5dd7070Spatrick                              SourceLocation nameLoc,
2198e5dd7070Spatrick                              SourceLocation atStartLoc,
2199e5dd7070Spatrick                              SourceLocation CategoryNameLoc) {
2200e5dd7070Spatrick   if (ClassInterface && ClassInterface->hasDefinition())
2201e5dd7070Spatrick     ClassInterface = ClassInterface->getDefinition();
2202e5dd7070Spatrick   return new (C, DC) ObjCCategoryImplDecl(DC, Id, ClassInterface, nameLoc,
2203e5dd7070Spatrick                                           atStartLoc, CategoryNameLoc);
2204e5dd7070Spatrick }
2205e5dd7070Spatrick 
CreateDeserialized(ASTContext & C,unsigned ID)2206e5dd7070Spatrick ObjCCategoryImplDecl *ObjCCategoryImplDecl::CreateDeserialized(ASTContext &C,
2207e5dd7070Spatrick                                                                unsigned ID) {
2208e5dd7070Spatrick   return new (C, ID) ObjCCategoryImplDecl(nullptr, nullptr, nullptr,
2209e5dd7070Spatrick                                           SourceLocation(), SourceLocation(),
2210e5dd7070Spatrick                                           SourceLocation());
2211e5dd7070Spatrick }
2212e5dd7070Spatrick 
getCategoryDecl() const2213e5dd7070Spatrick ObjCCategoryDecl *ObjCCategoryImplDecl::getCategoryDecl() const {
2214e5dd7070Spatrick   // The class interface might be NULL if we are working with invalid code.
2215e5dd7070Spatrick   if (const ObjCInterfaceDecl *ID = getClassInterface())
2216e5dd7070Spatrick     return ID->FindCategoryDeclaration(getIdentifier());
2217e5dd7070Spatrick   return nullptr;
2218e5dd7070Spatrick }
2219e5dd7070Spatrick 
anchor()2220e5dd7070Spatrick void ObjCImplDecl::anchor() {}
2221e5dd7070Spatrick 
addPropertyImplementation(ObjCPropertyImplDecl * property)2222e5dd7070Spatrick void ObjCImplDecl::addPropertyImplementation(ObjCPropertyImplDecl *property) {
2223e5dd7070Spatrick   // FIXME: The context should be correct before we get here.
2224e5dd7070Spatrick   property->setLexicalDeclContext(this);
2225e5dd7070Spatrick   addDecl(property);
2226e5dd7070Spatrick }
2227e5dd7070Spatrick 
setClassInterface(ObjCInterfaceDecl * IFace)2228e5dd7070Spatrick void ObjCImplDecl::setClassInterface(ObjCInterfaceDecl *IFace) {
2229e5dd7070Spatrick   ASTContext &Ctx = getASTContext();
2230e5dd7070Spatrick 
2231e5dd7070Spatrick   if (auto *ImplD = dyn_cast_or_null<ObjCImplementationDecl>(this)) {
2232e5dd7070Spatrick     if (IFace)
2233e5dd7070Spatrick       Ctx.setObjCImplementation(IFace, ImplD);
2234e5dd7070Spatrick 
2235e5dd7070Spatrick   } else if (auto *ImplD = dyn_cast_or_null<ObjCCategoryImplDecl>(this)) {
2236e5dd7070Spatrick     if (ObjCCategoryDecl *CD = IFace->FindCategoryDeclaration(getIdentifier()))
2237e5dd7070Spatrick       Ctx.setObjCImplementation(CD, ImplD);
2238e5dd7070Spatrick   }
2239e5dd7070Spatrick 
2240e5dd7070Spatrick   ClassInterface = IFace;
2241e5dd7070Spatrick }
2242e5dd7070Spatrick 
2243e5dd7070Spatrick /// FindPropertyImplIvarDecl - This method lookup the ivar in the list of
2244e5dd7070Spatrick /// properties implemented in this \@implementation block and returns
2245e5dd7070Spatrick /// the implemented property that uses it.
2246e5dd7070Spatrick ObjCPropertyImplDecl *ObjCImplDecl::
FindPropertyImplIvarDecl(IdentifierInfo * ivarId) const2247e5dd7070Spatrick FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const {
2248e5dd7070Spatrick   for (auto *PID : property_impls())
2249e5dd7070Spatrick     if (PID->getPropertyIvarDecl() &&
2250e5dd7070Spatrick         PID->getPropertyIvarDecl()->getIdentifier() == ivarId)
2251e5dd7070Spatrick       return PID;
2252e5dd7070Spatrick   return nullptr;
2253e5dd7070Spatrick }
2254e5dd7070Spatrick 
2255e5dd7070Spatrick /// FindPropertyImplDecl - This method looks up a previous ObjCPropertyImplDecl
2256e5dd7070Spatrick /// added to the list of those properties \@synthesized/\@dynamic in this
2257e5dd7070Spatrick /// category \@implementation block.
2258e5dd7070Spatrick ObjCPropertyImplDecl *ObjCImplDecl::
FindPropertyImplDecl(IdentifierInfo * Id,ObjCPropertyQueryKind QueryKind) const2259e5dd7070Spatrick FindPropertyImplDecl(IdentifierInfo *Id,
2260e5dd7070Spatrick                      ObjCPropertyQueryKind QueryKind) const {
2261e5dd7070Spatrick   ObjCPropertyImplDecl *ClassPropImpl = nullptr;
2262e5dd7070Spatrick   for (auto *PID : property_impls())
2263e5dd7070Spatrick     // If queryKind is unknown, we return the instance property if one
2264e5dd7070Spatrick     // exists; otherwise we return the class property.
2265e5dd7070Spatrick     if (PID->getPropertyDecl()->getIdentifier() == Id) {
2266e5dd7070Spatrick       if ((QueryKind == ObjCPropertyQueryKind::OBJC_PR_query_unknown &&
2267e5dd7070Spatrick            !PID->getPropertyDecl()->isClassProperty()) ||
2268e5dd7070Spatrick           (QueryKind == ObjCPropertyQueryKind::OBJC_PR_query_class &&
2269e5dd7070Spatrick            PID->getPropertyDecl()->isClassProperty()) ||
2270e5dd7070Spatrick           (QueryKind == ObjCPropertyQueryKind::OBJC_PR_query_instance &&
2271e5dd7070Spatrick            !PID->getPropertyDecl()->isClassProperty()))
2272e5dd7070Spatrick         return PID;
2273e5dd7070Spatrick 
2274e5dd7070Spatrick       if (PID->getPropertyDecl()->isClassProperty())
2275e5dd7070Spatrick         ClassPropImpl = PID;
2276e5dd7070Spatrick     }
2277e5dd7070Spatrick 
2278e5dd7070Spatrick   if (QueryKind == ObjCPropertyQueryKind::OBJC_PR_query_unknown)
2279e5dd7070Spatrick     // We can't find the instance property, return the class property.
2280e5dd7070Spatrick     return ClassPropImpl;
2281e5dd7070Spatrick 
2282e5dd7070Spatrick   return nullptr;
2283e5dd7070Spatrick }
2284e5dd7070Spatrick 
operator <<(raw_ostream & OS,const ObjCCategoryImplDecl & CID)2285e5dd7070Spatrick raw_ostream &clang::operator<<(raw_ostream &OS,
2286e5dd7070Spatrick                                const ObjCCategoryImplDecl &CID) {
2287e5dd7070Spatrick   OS << CID.getName();
2288e5dd7070Spatrick   return OS;
2289e5dd7070Spatrick }
2290e5dd7070Spatrick 
2291e5dd7070Spatrick //===----------------------------------------------------------------------===//
2292e5dd7070Spatrick // ObjCImplementationDecl
2293e5dd7070Spatrick //===----------------------------------------------------------------------===//
2294e5dd7070Spatrick 
anchor()2295e5dd7070Spatrick void ObjCImplementationDecl::anchor() {}
2296e5dd7070Spatrick 
2297e5dd7070Spatrick ObjCImplementationDecl *
Create(ASTContext & C,DeclContext * DC,ObjCInterfaceDecl * ClassInterface,ObjCInterfaceDecl * SuperDecl,SourceLocation nameLoc,SourceLocation atStartLoc,SourceLocation superLoc,SourceLocation IvarLBraceLoc,SourceLocation IvarRBraceLoc)2298e5dd7070Spatrick ObjCImplementationDecl::Create(ASTContext &C, DeclContext *DC,
2299e5dd7070Spatrick                                ObjCInterfaceDecl *ClassInterface,
2300e5dd7070Spatrick                                ObjCInterfaceDecl *SuperDecl,
2301e5dd7070Spatrick                                SourceLocation nameLoc,
2302e5dd7070Spatrick                                SourceLocation atStartLoc,
2303e5dd7070Spatrick                                SourceLocation superLoc,
2304e5dd7070Spatrick                                SourceLocation IvarLBraceLoc,
2305e5dd7070Spatrick                                SourceLocation IvarRBraceLoc) {
2306e5dd7070Spatrick   if (ClassInterface && ClassInterface->hasDefinition())
2307e5dd7070Spatrick     ClassInterface = ClassInterface->getDefinition();
2308e5dd7070Spatrick   return new (C, DC) ObjCImplementationDecl(DC, ClassInterface, SuperDecl,
2309e5dd7070Spatrick                                             nameLoc, atStartLoc, superLoc,
2310e5dd7070Spatrick                                             IvarLBraceLoc, IvarRBraceLoc);
2311e5dd7070Spatrick }
2312e5dd7070Spatrick 
2313e5dd7070Spatrick ObjCImplementationDecl *
CreateDeserialized(ASTContext & C,unsigned ID)2314e5dd7070Spatrick ObjCImplementationDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
2315e5dd7070Spatrick   return new (C, ID) ObjCImplementationDecl(nullptr, nullptr, nullptr,
2316e5dd7070Spatrick                                             SourceLocation(), SourceLocation());
2317e5dd7070Spatrick }
2318e5dd7070Spatrick 
setIvarInitializers(ASTContext & C,CXXCtorInitializer ** initializers,unsigned numInitializers)2319e5dd7070Spatrick void ObjCImplementationDecl::setIvarInitializers(ASTContext &C,
2320e5dd7070Spatrick                                              CXXCtorInitializer ** initializers,
2321e5dd7070Spatrick                                                  unsigned numInitializers) {
2322e5dd7070Spatrick   if (numInitializers > 0) {
2323e5dd7070Spatrick     NumIvarInitializers = numInitializers;
2324e5dd7070Spatrick     auto **ivarInitializers = new (C) CXXCtorInitializer*[NumIvarInitializers];
2325e5dd7070Spatrick     memcpy(ivarInitializers, initializers,
2326e5dd7070Spatrick            numInitializers * sizeof(CXXCtorInitializer*));
2327e5dd7070Spatrick     IvarInitializers = ivarInitializers;
2328e5dd7070Spatrick   }
2329e5dd7070Spatrick }
2330e5dd7070Spatrick 
2331e5dd7070Spatrick ObjCImplementationDecl::init_const_iterator
init_begin() const2332e5dd7070Spatrick ObjCImplementationDecl::init_begin() const {
2333e5dd7070Spatrick   return IvarInitializers.get(getASTContext().getExternalSource());
2334e5dd7070Spatrick }
2335e5dd7070Spatrick 
operator <<(raw_ostream & OS,const ObjCImplementationDecl & ID)2336e5dd7070Spatrick raw_ostream &clang::operator<<(raw_ostream &OS,
2337e5dd7070Spatrick                                const ObjCImplementationDecl &ID) {
2338e5dd7070Spatrick   OS << ID.getName();
2339e5dd7070Spatrick   return OS;
2340e5dd7070Spatrick }
2341e5dd7070Spatrick 
2342e5dd7070Spatrick //===----------------------------------------------------------------------===//
2343e5dd7070Spatrick // ObjCCompatibleAliasDecl
2344e5dd7070Spatrick //===----------------------------------------------------------------------===//
2345e5dd7070Spatrick 
anchor()2346e5dd7070Spatrick void ObjCCompatibleAliasDecl::anchor() {}
2347e5dd7070Spatrick 
2348e5dd7070Spatrick ObjCCompatibleAliasDecl *
Create(ASTContext & C,DeclContext * DC,SourceLocation L,IdentifierInfo * Id,ObjCInterfaceDecl * AliasedClass)2349e5dd7070Spatrick ObjCCompatibleAliasDecl::Create(ASTContext &C, DeclContext *DC,
2350e5dd7070Spatrick                                 SourceLocation L,
2351e5dd7070Spatrick                                 IdentifierInfo *Id,
2352e5dd7070Spatrick                                 ObjCInterfaceDecl* AliasedClass) {
2353e5dd7070Spatrick   return new (C, DC) ObjCCompatibleAliasDecl(DC, L, Id, AliasedClass);
2354e5dd7070Spatrick }
2355e5dd7070Spatrick 
2356e5dd7070Spatrick ObjCCompatibleAliasDecl *
CreateDeserialized(ASTContext & C,unsigned ID)2357e5dd7070Spatrick ObjCCompatibleAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
2358e5dd7070Spatrick   return new (C, ID) ObjCCompatibleAliasDecl(nullptr, SourceLocation(),
2359e5dd7070Spatrick                                              nullptr, nullptr);
2360e5dd7070Spatrick }
2361e5dd7070Spatrick 
2362e5dd7070Spatrick //===----------------------------------------------------------------------===//
2363e5dd7070Spatrick // ObjCPropertyDecl
2364e5dd7070Spatrick //===----------------------------------------------------------------------===//
2365e5dd7070Spatrick 
anchor()2366e5dd7070Spatrick void ObjCPropertyDecl::anchor() {}
2367e5dd7070Spatrick 
Create(ASTContext & C,DeclContext * DC,SourceLocation L,IdentifierInfo * Id,SourceLocation AtLoc,SourceLocation LParenLoc,QualType T,TypeSourceInfo * TSI,PropertyControl propControl)2368e5dd7070Spatrick ObjCPropertyDecl *ObjCPropertyDecl::Create(ASTContext &C, DeclContext *DC,
2369e5dd7070Spatrick                                            SourceLocation L,
2370e5dd7070Spatrick                                            IdentifierInfo *Id,
2371e5dd7070Spatrick                                            SourceLocation AtLoc,
2372e5dd7070Spatrick                                            SourceLocation LParenLoc,
2373e5dd7070Spatrick                                            QualType T,
2374e5dd7070Spatrick                                            TypeSourceInfo *TSI,
2375e5dd7070Spatrick                                            PropertyControl propControl) {
2376e5dd7070Spatrick   return new (C, DC) ObjCPropertyDecl(DC, L, Id, AtLoc, LParenLoc, T, TSI,
2377e5dd7070Spatrick                                       propControl);
2378e5dd7070Spatrick }
2379e5dd7070Spatrick 
CreateDeserialized(ASTContext & C,unsigned ID)2380e5dd7070Spatrick ObjCPropertyDecl *ObjCPropertyDecl::CreateDeserialized(ASTContext &C,
2381e5dd7070Spatrick                                                        unsigned ID) {
2382e5dd7070Spatrick   return new (C, ID) ObjCPropertyDecl(nullptr, SourceLocation(), nullptr,
2383e5dd7070Spatrick                                       SourceLocation(), SourceLocation(),
2384e5dd7070Spatrick                                       QualType(), nullptr, None);
2385e5dd7070Spatrick }
2386e5dd7070Spatrick 
getUsageType(QualType objectType) const2387e5dd7070Spatrick QualType ObjCPropertyDecl::getUsageType(QualType objectType) const {
2388e5dd7070Spatrick   return DeclType.substObjCMemberType(objectType, getDeclContext(),
2389e5dd7070Spatrick                                       ObjCSubstitutionContext::Property);
2390e5dd7070Spatrick }
2391e5dd7070Spatrick 
isDirectProperty() const2392a9ac8606Spatrick bool ObjCPropertyDecl::isDirectProperty() const {
2393a9ac8606Spatrick   return (PropertyAttributes & ObjCPropertyAttribute::kind_direct) &&
2394a9ac8606Spatrick          !getASTContext().getLangOpts().ObjCDisableDirectMethodsForTesting;
2395a9ac8606Spatrick }
2396a9ac8606Spatrick 
2397e5dd7070Spatrick //===----------------------------------------------------------------------===//
2398e5dd7070Spatrick // ObjCPropertyImplDecl
2399e5dd7070Spatrick //===----------------------------------------------------------------------===//
2400e5dd7070Spatrick 
Create(ASTContext & C,DeclContext * DC,SourceLocation atLoc,SourceLocation L,ObjCPropertyDecl * property,Kind PK,ObjCIvarDecl * ivar,SourceLocation ivarLoc)2401e5dd7070Spatrick ObjCPropertyImplDecl *ObjCPropertyImplDecl::Create(ASTContext &C,
2402e5dd7070Spatrick                                                    DeclContext *DC,
2403e5dd7070Spatrick                                                    SourceLocation atLoc,
2404e5dd7070Spatrick                                                    SourceLocation L,
2405e5dd7070Spatrick                                                    ObjCPropertyDecl *property,
2406e5dd7070Spatrick                                                    Kind PK,
2407e5dd7070Spatrick                                                    ObjCIvarDecl *ivar,
2408e5dd7070Spatrick                                                    SourceLocation ivarLoc) {
2409e5dd7070Spatrick   return new (C, DC) ObjCPropertyImplDecl(DC, atLoc, L, property, PK, ivar,
2410e5dd7070Spatrick                                           ivarLoc);
2411e5dd7070Spatrick }
2412e5dd7070Spatrick 
CreateDeserialized(ASTContext & C,unsigned ID)2413e5dd7070Spatrick ObjCPropertyImplDecl *ObjCPropertyImplDecl::CreateDeserialized(ASTContext &C,
2414e5dd7070Spatrick                                                                unsigned ID) {
2415e5dd7070Spatrick   return new (C, ID) ObjCPropertyImplDecl(nullptr, SourceLocation(),
2416e5dd7070Spatrick                                           SourceLocation(), nullptr, Dynamic,
2417e5dd7070Spatrick                                           nullptr, SourceLocation());
2418e5dd7070Spatrick }
2419e5dd7070Spatrick 
getSourceRange() const2420e5dd7070Spatrick SourceRange ObjCPropertyImplDecl::getSourceRange() const {
2421e5dd7070Spatrick   SourceLocation EndLoc = getLocation();
2422e5dd7070Spatrick   if (IvarLoc.isValid())
2423e5dd7070Spatrick     EndLoc = IvarLoc;
2424e5dd7070Spatrick 
2425e5dd7070Spatrick   return SourceRange(AtLoc, EndLoc);
2426e5dd7070Spatrick }
2427