106f32e7eSjoerg //===- DeclObjC.cpp - ObjC Declaration AST Node Implementation ------------===//
206f32e7eSjoerg //
306f32e7eSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406f32e7eSjoerg // See https://llvm.org/LICENSE.txt for license information.
506f32e7eSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606f32e7eSjoerg //
706f32e7eSjoerg //===----------------------------------------------------------------------===//
806f32e7eSjoerg //
906f32e7eSjoerg // This file implements the Objective-C related Decl classes.
1006f32e7eSjoerg //
1106f32e7eSjoerg //===----------------------------------------------------------------------===//
1206f32e7eSjoerg 
1306f32e7eSjoerg #include "clang/AST/DeclObjC.h"
1406f32e7eSjoerg #include "clang/AST/ASTContext.h"
1506f32e7eSjoerg #include "clang/AST/ASTMutationListener.h"
1606f32e7eSjoerg #include "clang/AST/Attr.h"
1706f32e7eSjoerg #include "clang/AST/Decl.h"
1806f32e7eSjoerg #include "clang/AST/DeclBase.h"
1906f32e7eSjoerg #include "clang/AST/Stmt.h"
2006f32e7eSjoerg #include "clang/AST/Type.h"
2106f32e7eSjoerg #include "clang/AST/TypeLoc.h"
2206f32e7eSjoerg #include "clang/Basic/IdentifierTable.h"
2306f32e7eSjoerg #include "clang/Basic/LLVM.h"
2406f32e7eSjoerg #include "clang/Basic/LangOptions.h"
2506f32e7eSjoerg #include "clang/Basic/SourceLocation.h"
2606f32e7eSjoerg #include "llvm/ADT/None.h"
2706f32e7eSjoerg #include "llvm/ADT/SmallString.h"
2806f32e7eSjoerg #include "llvm/ADT/SmallVector.h"
2906f32e7eSjoerg #include "llvm/Support/Casting.h"
3006f32e7eSjoerg #include "llvm/Support/ErrorHandling.h"
3106f32e7eSjoerg #include "llvm/Support/raw_ostream.h"
3206f32e7eSjoerg #include <algorithm>
3306f32e7eSjoerg #include <cassert>
3406f32e7eSjoerg #include <cstdint>
3506f32e7eSjoerg #include <cstring>
36*13fbcb42Sjoerg #include <queue>
3706f32e7eSjoerg #include <utility>
3806f32e7eSjoerg 
3906f32e7eSjoerg using namespace clang;
4006f32e7eSjoerg 
4106f32e7eSjoerg //===----------------------------------------------------------------------===//
4206f32e7eSjoerg // ObjCListBase
4306f32e7eSjoerg //===----------------------------------------------------------------------===//
4406f32e7eSjoerg 
set(void * const * InList,unsigned Elts,ASTContext & Ctx)4506f32e7eSjoerg void ObjCListBase::set(void *const* InList, unsigned Elts, ASTContext &Ctx) {
4606f32e7eSjoerg   List = nullptr;
4706f32e7eSjoerg   if (Elts == 0) return;  // Setting to an empty list is a noop.
4806f32e7eSjoerg 
4906f32e7eSjoerg   List = new (Ctx) void*[Elts];
5006f32e7eSjoerg   NumElts = Elts;
5106f32e7eSjoerg   memcpy(List, InList, sizeof(void*)*Elts);
5206f32e7eSjoerg }
5306f32e7eSjoerg 
set(ObjCProtocolDecl * const * InList,unsigned Elts,const SourceLocation * Locs,ASTContext & Ctx)5406f32e7eSjoerg void ObjCProtocolList::set(ObjCProtocolDecl* const* InList, unsigned Elts,
5506f32e7eSjoerg                            const SourceLocation *Locs, ASTContext &Ctx) {
5606f32e7eSjoerg   if (Elts == 0)
5706f32e7eSjoerg     return;
5806f32e7eSjoerg 
5906f32e7eSjoerg   Locations = new (Ctx) SourceLocation[Elts];
6006f32e7eSjoerg   memcpy(Locations, Locs, sizeof(SourceLocation) * Elts);
6106f32e7eSjoerg   set(InList, Elts, Ctx);
6206f32e7eSjoerg }
6306f32e7eSjoerg 
6406f32e7eSjoerg //===----------------------------------------------------------------------===//
6506f32e7eSjoerg // ObjCInterfaceDecl
6606f32e7eSjoerg //===----------------------------------------------------------------------===//
6706f32e7eSjoerg 
ObjCContainerDecl(Kind DK,DeclContext * DC,IdentifierInfo * Id,SourceLocation nameLoc,SourceLocation atStartLoc)6806f32e7eSjoerg ObjCContainerDecl::ObjCContainerDecl(Kind DK, DeclContext *DC,
6906f32e7eSjoerg                                      IdentifierInfo *Id, SourceLocation nameLoc,
7006f32e7eSjoerg                                      SourceLocation atStartLoc)
7106f32e7eSjoerg     : NamedDecl(DK, DC, nameLoc, Id), DeclContext(DK) {
7206f32e7eSjoerg   setAtStartLoc(atStartLoc);
7306f32e7eSjoerg }
7406f32e7eSjoerg 
anchor()7506f32e7eSjoerg void ObjCContainerDecl::anchor() {}
7606f32e7eSjoerg 
7706f32e7eSjoerg /// getIvarDecl - This method looks up an ivar in this ContextDecl.
7806f32e7eSjoerg ///
7906f32e7eSjoerg ObjCIvarDecl *
getIvarDecl(IdentifierInfo * Id) const8006f32e7eSjoerg ObjCContainerDecl::getIvarDecl(IdentifierInfo *Id) const {
8106f32e7eSjoerg   lookup_result R = lookup(Id);
8206f32e7eSjoerg   for (lookup_iterator Ivar = R.begin(), IvarEnd = R.end();
8306f32e7eSjoerg        Ivar != IvarEnd; ++Ivar) {
8406f32e7eSjoerg     if (auto *ivar = dyn_cast<ObjCIvarDecl>(*Ivar))
8506f32e7eSjoerg       return ivar;
8606f32e7eSjoerg   }
8706f32e7eSjoerg   return nullptr;
8806f32e7eSjoerg }
8906f32e7eSjoerg 
9006f32e7eSjoerg // Get the local instance/class method declared in this interface.
9106f32e7eSjoerg ObjCMethodDecl *
getMethod(Selector Sel,bool isInstance,bool AllowHidden) const9206f32e7eSjoerg ObjCContainerDecl::getMethod(Selector Sel, bool isInstance,
9306f32e7eSjoerg                              bool AllowHidden) const {
9406f32e7eSjoerg   // If this context is a hidden protocol definition, don't find any
9506f32e7eSjoerg   // methods there.
9606f32e7eSjoerg   if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(this)) {
9706f32e7eSjoerg     if (const ObjCProtocolDecl *Def = Proto->getDefinition())
98*13fbcb42Sjoerg       if (!Def->isUnconditionallyVisible() && !AllowHidden)
9906f32e7eSjoerg         return nullptr;
10006f32e7eSjoerg   }
10106f32e7eSjoerg 
10206f32e7eSjoerg   // Since instance & class methods can have the same name, the loop below
10306f32e7eSjoerg   // ensures we get the correct method.
10406f32e7eSjoerg   //
10506f32e7eSjoerg   // @interface Whatever
10606f32e7eSjoerg   // - (int) class_method;
10706f32e7eSjoerg   // + (float) class_method;
10806f32e7eSjoerg   // @end
10906f32e7eSjoerg   lookup_result R = lookup(Sel);
11006f32e7eSjoerg   for (lookup_iterator Meth = R.begin(), MethEnd = R.end();
11106f32e7eSjoerg        Meth != MethEnd; ++Meth) {
11206f32e7eSjoerg     auto *MD = dyn_cast<ObjCMethodDecl>(*Meth);
11306f32e7eSjoerg     if (MD && MD->isInstanceMethod() == isInstance)
11406f32e7eSjoerg       return MD;
11506f32e7eSjoerg   }
11606f32e7eSjoerg   return nullptr;
11706f32e7eSjoerg }
11806f32e7eSjoerg 
11906f32e7eSjoerg /// This routine returns 'true' if a user declared setter method was
12006f32e7eSjoerg /// found in the class, its protocols, its super classes or categories.
12106f32e7eSjoerg /// It also returns 'true' if one of its categories has declared a 'readwrite'
12206f32e7eSjoerg /// property.  This is because, user must provide a setter method for the
12306f32e7eSjoerg /// category's 'readwrite' property.
HasUserDeclaredSetterMethod(const ObjCPropertyDecl * Property) const12406f32e7eSjoerg bool ObjCContainerDecl::HasUserDeclaredSetterMethod(
12506f32e7eSjoerg     const ObjCPropertyDecl *Property) const {
12606f32e7eSjoerg   Selector Sel = Property->getSetterName();
12706f32e7eSjoerg   lookup_result R = lookup(Sel);
12806f32e7eSjoerg   for (lookup_iterator Meth = R.begin(), MethEnd = R.end();
12906f32e7eSjoerg        Meth != MethEnd; ++Meth) {
13006f32e7eSjoerg     auto *MD = dyn_cast<ObjCMethodDecl>(*Meth);
13106f32e7eSjoerg     if (MD && MD->isInstanceMethod() && !MD->isImplicit())
13206f32e7eSjoerg       return true;
13306f32e7eSjoerg   }
13406f32e7eSjoerg 
13506f32e7eSjoerg   if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(this)) {
13606f32e7eSjoerg     // Also look into categories, including class extensions, looking
13706f32e7eSjoerg     // for a user declared instance method.
13806f32e7eSjoerg     for (const auto *Cat : ID->visible_categories()) {
13906f32e7eSjoerg       if (ObjCMethodDecl *MD = Cat->getInstanceMethod(Sel))
14006f32e7eSjoerg         if (!MD->isImplicit())
14106f32e7eSjoerg           return true;
14206f32e7eSjoerg       if (Cat->IsClassExtension())
14306f32e7eSjoerg         continue;
14406f32e7eSjoerg       // Also search through the categories looking for a 'readwrite'
14506f32e7eSjoerg       // declaration of this property. If one found, presumably a setter will
14606f32e7eSjoerg       // be provided (properties declared in categories will not get
14706f32e7eSjoerg       // auto-synthesized).
14806f32e7eSjoerg       for (const auto *P : Cat->properties())
14906f32e7eSjoerg         if (P->getIdentifier() == Property->getIdentifier()) {
150*13fbcb42Sjoerg           if (P->getPropertyAttributes() &
151*13fbcb42Sjoerg               ObjCPropertyAttribute::kind_readwrite)
15206f32e7eSjoerg             return true;
15306f32e7eSjoerg           break;
15406f32e7eSjoerg         }
15506f32e7eSjoerg     }
15606f32e7eSjoerg 
15706f32e7eSjoerg     // Also look into protocols, for a user declared instance method.
15806f32e7eSjoerg     for (const auto *Proto : ID->all_referenced_protocols())
15906f32e7eSjoerg       if (Proto->HasUserDeclaredSetterMethod(Property))
16006f32e7eSjoerg         return true;
16106f32e7eSjoerg 
16206f32e7eSjoerg     // And in its super class.
16306f32e7eSjoerg     ObjCInterfaceDecl *OSC = ID->getSuperClass();
16406f32e7eSjoerg     while (OSC) {
16506f32e7eSjoerg       if (OSC->HasUserDeclaredSetterMethod(Property))
16606f32e7eSjoerg         return true;
16706f32e7eSjoerg       OSC = OSC->getSuperClass();
16806f32e7eSjoerg     }
16906f32e7eSjoerg   }
17006f32e7eSjoerg   if (const auto *PD = dyn_cast<ObjCProtocolDecl>(this))
17106f32e7eSjoerg     for (const auto *PI : PD->protocols())
17206f32e7eSjoerg       if (PI->HasUserDeclaredSetterMethod(Property))
17306f32e7eSjoerg         return true;
17406f32e7eSjoerg   return false;
17506f32e7eSjoerg }
17606f32e7eSjoerg 
17706f32e7eSjoerg ObjCPropertyDecl *
findPropertyDecl(const DeclContext * DC,const IdentifierInfo * propertyID,ObjCPropertyQueryKind queryKind)17806f32e7eSjoerg ObjCPropertyDecl::findPropertyDecl(const DeclContext *DC,
17906f32e7eSjoerg                                    const IdentifierInfo *propertyID,
18006f32e7eSjoerg                                    ObjCPropertyQueryKind queryKind) {
18106f32e7eSjoerg   // If this context is a hidden protocol definition, don't find any
18206f32e7eSjoerg   // property.
18306f32e7eSjoerg   if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(DC)) {
18406f32e7eSjoerg     if (const ObjCProtocolDecl *Def = Proto->getDefinition())
185*13fbcb42Sjoerg       if (!Def->isUnconditionallyVisible())
18606f32e7eSjoerg         return nullptr;
18706f32e7eSjoerg   }
18806f32e7eSjoerg 
18906f32e7eSjoerg   // If context is class, then lookup property in its visible extensions.
19006f32e7eSjoerg   // This comes before property is looked up in primary class.
19106f32e7eSjoerg   if (auto *IDecl = dyn_cast<ObjCInterfaceDecl>(DC)) {
19206f32e7eSjoerg     for (const auto *Ext : IDecl->visible_extensions())
19306f32e7eSjoerg       if (ObjCPropertyDecl *PD = ObjCPropertyDecl::findPropertyDecl(Ext,
19406f32e7eSjoerg                                                        propertyID,
19506f32e7eSjoerg                                                        queryKind))
19606f32e7eSjoerg         return PD;
19706f32e7eSjoerg   }
19806f32e7eSjoerg 
19906f32e7eSjoerg   DeclContext::lookup_result R = DC->lookup(propertyID);
20006f32e7eSjoerg   ObjCPropertyDecl *classProp = nullptr;
20106f32e7eSjoerg   for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E;
20206f32e7eSjoerg        ++I)
20306f32e7eSjoerg     if (auto *PD = dyn_cast<ObjCPropertyDecl>(*I)) {
20406f32e7eSjoerg       // If queryKind is unknown, we return the instance property if one
20506f32e7eSjoerg       // exists; otherwise we return the class property.
20606f32e7eSjoerg       if ((queryKind == ObjCPropertyQueryKind::OBJC_PR_query_unknown &&
20706f32e7eSjoerg            !PD->isClassProperty()) ||
20806f32e7eSjoerg           (queryKind == ObjCPropertyQueryKind::OBJC_PR_query_class &&
20906f32e7eSjoerg            PD->isClassProperty()) ||
21006f32e7eSjoerg           (queryKind == ObjCPropertyQueryKind::OBJC_PR_query_instance &&
21106f32e7eSjoerg            !PD->isClassProperty()))
21206f32e7eSjoerg         return PD;
21306f32e7eSjoerg 
21406f32e7eSjoerg       if (PD->isClassProperty())
21506f32e7eSjoerg         classProp = PD;
21606f32e7eSjoerg     }
21706f32e7eSjoerg 
21806f32e7eSjoerg   if (queryKind == ObjCPropertyQueryKind::OBJC_PR_query_unknown)
21906f32e7eSjoerg     // We can't find the instance property, return the class property.
22006f32e7eSjoerg     return classProp;
22106f32e7eSjoerg 
22206f32e7eSjoerg   return nullptr;
22306f32e7eSjoerg }
22406f32e7eSjoerg 
22506f32e7eSjoerg IdentifierInfo *
getDefaultSynthIvarName(ASTContext & Ctx) const22606f32e7eSjoerg ObjCPropertyDecl::getDefaultSynthIvarName(ASTContext &Ctx) const {
22706f32e7eSjoerg   SmallString<128> ivarName;
22806f32e7eSjoerg   {
22906f32e7eSjoerg     llvm::raw_svector_ostream os(ivarName);
23006f32e7eSjoerg     os << '_' << getIdentifier()->getName();
23106f32e7eSjoerg   }
23206f32e7eSjoerg   return &Ctx.Idents.get(ivarName.str());
23306f32e7eSjoerg }
23406f32e7eSjoerg 
23506f32e7eSjoerg /// FindPropertyDeclaration - Finds declaration of the property given its name
23606f32e7eSjoerg /// in 'PropertyId' and returns it. It returns 0, if not found.
FindPropertyDeclaration(const IdentifierInfo * PropertyId,ObjCPropertyQueryKind QueryKind) const23706f32e7eSjoerg ObjCPropertyDecl *ObjCContainerDecl::FindPropertyDeclaration(
23806f32e7eSjoerg     const IdentifierInfo *PropertyId,
23906f32e7eSjoerg     ObjCPropertyQueryKind QueryKind) const {
24006f32e7eSjoerg   // Don't find properties within hidden protocol definitions.
24106f32e7eSjoerg   if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(this)) {
24206f32e7eSjoerg     if (const ObjCProtocolDecl *Def = Proto->getDefinition())
243*13fbcb42Sjoerg       if (!Def->isUnconditionallyVisible())
24406f32e7eSjoerg         return nullptr;
24506f32e7eSjoerg   }
24606f32e7eSjoerg 
24706f32e7eSjoerg   // Search the extensions of a class first; they override what's in
24806f32e7eSjoerg   // the class itself.
24906f32e7eSjoerg   if (const auto *ClassDecl = dyn_cast<ObjCInterfaceDecl>(this)) {
25006f32e7eSjoerg     for (const auto *Ext : ClassDecl->visible_extensions()) {
25106f32e7eSjoerg       if (auto *P = Ext->FindPropertyDeclaration(PropertyId, QueryKind))
25206f32e7eSjoerg         return P;
25306f32e7eSjoerg     }
25406f32e7eSjoerg   }
25506f32e7eSjoerg 
25606f32e7eSjoerg   if (ObjCPropertyDecl *PD =
25706f32e7eSjoerg         ObjCPropertyDecl::findPropertyDecl(cast<DeclContext>(this), PropertyId,
25806f32e7eSjoerg                                            QueryKind))
25906f32e7eSjoerg     return PD;
26006f32e7eSjoerg 
26106f32e7eSjoerg   switch (getKind()) {
26206f32e7eSjoerg     default:
26306f32e7eSjoerg       break;
26406f32e7eSjoerg     case Decl::ObjCProtocol: {
26506f32e7eSjoerg       const auto *PID = cast<ObjCProtocolDecl>(this);
26606f32e7eSjoerg       for (const auto *I : PID->protocols())
26706f32e7eSjoerg         if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId,
26806f32e7eSjoerg                                                              QueryKind))
26906f32e7eSjoerg           return P;
27006f32e7eSjoerg       break;
27106f32e7eSjoerg     }
27206f32e7eSjoerg     case Decl::ObjCInterface: {
27306f32e7eSjoerg       const auto *OID = cast<ObjCInterfaceDecl>(this);
27406f32e7eSjoerg       // Look through categories (but not extensions; they were handled above).
27506f32e7eSjoerg       for (const auto *Cat : OID->visible_categories()) {
27606f32e7eSjoerg         if (!Cat->IsClassExtension())
27706f32e7eSjoerg           if (ObjCPropertyDecl *P = Cat->FindPropertyDeclaration(
27806f32e7eSjoerg                                              PropertyId, QueryKind))
27906f32e7eSjoerg             return P;
28006f32e7eSjoerg       }
28106f32e7eSjoerg 
28206f32e7eSjoerg       // Look through protocols.
28306f32e7eSjoerg       for (const auto *I : OID->all_referenced_protocols())
28406f32e7eSjoerg         if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId,
28506f32e7eSjoerg                                                              QueryKind))
28606f32e7eSjoerg           return P;
28706f32e7eSjoerg 
28806f32e7eSjoerg       // Finally, check the super class.
28906f32e7eSjoerg       if (const ObjCInterfaceDecl *superClass = OID->getSuperClass())
29006f32e7eSjoerg         return superClass->FindPropertyDeclaration(PropertyId, QueryKind);
29106f32e7eSjoerg       break;
29206f32e7eSjoerg     }
29306f32e7eSjoerg     case Decl::ObjCCategory: {
29406f32e7eSjoerg       const auto *OCD = cast<ObjCCategoryDecl>(this);
29506f32e7eSjoerg       // Look through protocols.
29606f32e7eSjoerg       if (!OCD->IsClassExtension())
29706f32e7eSjoerg         for (const auto *I : OCD->protocols())
29806f32e7eSjoerg           if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId,
29906f32e7eSjoerg                                                                QueryKind))
30006f32e7eSjoerg             return P;
30106f32e7eSjoerg       break;
30206f32e7eSjoerg     }
30306f32e7eSjoerg   }
30406f32e7eSjoerg   return nullptr;
30506f32e7eSjoerg }
30606f32e7eSjoerg 
anchor()30706f32e7eSjoerg void ObjCInterfaceDecl::anchor() {}
30806f32e7eSjoerg 
getTypeParamList() const30906f32e7eSjoerg ObjCTypeParamList *ObjCInterfaceDecl::getTypeParamList() const {
31006f32e7eSjoerg   // If this particular declaration has a type parameter list, return it.
31106f32e7eSjoerg   if (ObjCTypeParamList *written = getTypeParamListAsWritten())
31206f32e7eSjoerg     return written;
31306f32e7eSjoerg 
31406f32e7eSjoerg   // If there is a definition, return its type parameter list.
31506f32e7eSjoerg   if (const ObjCInterfaceDecl *def = getDefinition())
31606f32e7eSjoerg     return def->getTypeParamListAsWritten();
31706f32e7eSjoerg 
31806f32e7eSjoerg   // Otherwise, look at previous declarations to determine whether any
31906f32e7eSjoerg   // of them has a type parameter list, skipping over those
32006f32e7eSjoerg   // declarations that do not.
32106f32e7eSjoerg   for (const ObjCInterfaceDecl *decl = getMostRecentDecl(); decl;
32206f32e7eSjoerg        decl = decl->getPreviousDecl()) {
32306f32e7eSjoerg     if (ObjCTypeParamList *written = decl->getTypeParamListAsWritten())
32406f32e7eSjoerg       return written;
32506f32e7eSjoerg   }
32606f32e7eSjoerg 
32706f32e7eSjoerg   return nullptr;
32806f32e7eSjoerg }
32906f32e7eSjoerg 
setTypeParamList(ObjCTypeParamList * TPL)33006f32e7eSjoerg void ObjCInterfaceDecl::setTypeParamList(ObjCTypeParamList *TPL) {
33106f32e7eSjoerg   TypeParamList = TPL;
33206f32e7eSjoerg   if (!TPL)
33306f32e7eSjoerg     return;
33406f32e7eSjoerg   // Set the declaration context of each of the type parameters.
33506f32e7eSjoerg   for (auto *typeParam : *TypeParamList)
33606f32e7eSjoerg     typeParam->setDeclContext(this);
33706f32e7eSjoerg }
33806f32e7eSjoerg 
getSuperClass() const33906f32e7eSjoerg ObjCInterfaceDecl *ObjCInterfaceDecl::getSuperClass() const {
34006f32e7eSjoerg   // FIXME: Should make sure no callers ever do this.
34106f32e7eSjoerg   if (!hasDefinition())
34206f32e7eSjoerg     return nullptr;
34306f32e7eSjoerg 
34406f32e7eSjoerg   if (data().ExternallyCompleted)
34506f32e7eSjoerg     LoadExternalDefinition();
34606f32e7eSjoerg 
34706f32e7eSjoerg   if (const ObjCObjectType *superType = getSuperClassType()) {
34806f32e7eSjoerg     if (ObjCInterfaceDecl *superDecl = superType->getInterface()) {
34906f32e7eSjoerg       if (ObjCInterfaceDecl *superDef = superDecl->getDefinition())
35006f32e7eSjoerg         return superDef;
35106f32e7eSjoerg 
35206f32e7eSjoerg       return superDecl;
35306f32e7eSjoerg     }
35406f32e7eSjoerg   }
35506f32e7eSjoerg 
35606f32e7eSjoerg   return nullptr;
35706f32e7eSjoerg }
35806f32e7eSjoerg 
getSuperClassLoc() const35906f32e7eSjoerg SourceLocation ObjCInterfaceDecl::getSuperClassLoc() const {
36006f32e7eSjoerg   if (TypeSourceInfo *superTInfo = getSuperClassTInfo())
36106f32e7eSjoerg     return superTInfo->getTypeLoc().getBeginLoc();
36206f32e7eSjoerg 
36306f32e7eSjoerg   return SourceLocation();
36406f32e7eSjoerg }
36506f32e7eSjoerg 
36606f32e7eSjoerg /// FindPropertyVisibleInPrimaryClass - Finds declaration of the property
36706f32e7eSjoerg /// with name 'PropertyId' in the primary class; including those in protocols
36806f32e7eSjoerg /// (direct or indirect) used by the primary class.
36906f32e7eSjoerg ObjCPropertyDecl *
FindPropertyVisibleInPrimaryClass(IdentifierInfo * PropertyId,ObjCPropertyQueryKind QueryKind) const37006f32e7eSjoerg ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass(
37106f32e7eSjoerg                        IdentifierInfo *PropertyId,
37206f32e7eSjoerg                        ObjCPropertyQueryKind QueryKind) const {
37306f32e7eSjoerg   // FIXME: Should make sure no callers ever do this.
37406f32e7eSjoerg   if (!hasDefinition())
37506f32e7eSjoerg     return nullptr;
37606f32e7eSjoerg 
37706f32e7eSjoerg   if (data().ExternallyCompleted)
37806f32e7eSjoerg     LoadExternalDefinition();
37906f32e7eSjoerg 
38006f32e7eSjoerg   if (ObjCPropertyDecl *PD =
38106f32e7eSjoerg       ObjCPropertyDecl::findPropertyDecl(cast<DeclContext>(this), PropertyId,
38206f32e7eSjoerg                                          QueryKind))
38306f32e7eSjoerg     return PD;
38406f32e7eSjoerg 
38506f32e7eSjoerg   // Look through protocols.
38606f32e7eSjoerg   for (const auto *I : all_referenced_protocols())
38706f32e7eSjoerg     if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId,
38806f32e7eSjoerg                                                          QueryKind))
38906f32e7eSjoerg       return P;
39006f32e7eSjoerg 
39106f32e7eSjoerg   return nullptr;
39206f32e7eSjoerg }
39306f32e7eSjoerg 
collectPropertiesToImplement(PropertyMap & PM,PropertyDeclOrder & PO) const39406f32e7eSjoerg void ObjCInterfaceDecl::collectPropertiesToImplement(PropertyMap &PM,
39506f32e7eSjoerg                                                      PropertyDeclOrder &PO) const {
39606f32e7eSjoerg   for (auto *Prop : properties()) {
39706f32e7eSjoerg     PM[std::make_pair(Prop->getIdentifier(), Prop->isClassProperty())] = Prop;
39806f32e7eSjoerg     PO.push_back(Prop);
39906f32e7eSjoerg   }
40006f32e7eSjoerg   for (const auto *Ext : known_extensions()) {
40106f32e7eSjoerg     const ObjCCategoryDecl *ClassExt = Ext;
40206f32e7eSjoerg     for (auto *Prop : ClassExt->properties()) {
40306f32e7eSjoerg       PM[std::make_pair(Prop->getIdentifier(), Prop->isClassProperty())] = Prop;
40406f32e7eSjoerg       PO.push_back(Prop);
40506f32e7eSjoerg     }
40606f32e7eSjoerg   }
40706f32e7eSjoerg   for (const auto *PI : all_referenced_protocols())
40806f32e7eSjoerg     PI->collectPropertiesToImplement(PM, PO);
40906f32e7eSjoerg   // Note, the properties declared only in class extensions are still copied
41006f32e7eSjoerg   // into the main @interface's property list, and therefore we don't
41106f32e7eSjoerg   // explicitly, have to search class extension properties.
41206f32e7eSjoerg }
41306f32e7eSjoerg 
isArcWeakrefUnavailable() const41406f32e7eSjoerg bool ObjCInterfaceDecl::isArcWeakrefUnavailable() const {
41506f32e7eSjoerg   const ObjCInterfaceDecl *Class = this;
41606f32e7eSjoerg   while (Class) {
41706f32e7eSjoerg     if (Class->hasAttr<ArcWeakrefUnavailableAttr>())
41806f32e7eSjoerg       return true;
41906f32e7eSjoerg     Class = Class->getSuperClass();
42006f32e7eSjoerg   }
42106f32e7eSjoerg   return false;
42206f32e7eSjoerg }
42306f32e7eSjoerg 
isObjCRequiresPropertyDefs() const42406f32e7eSjoerg const ObjCInterfaceDecl *ObjCInterfaceDecl::isObjCRequiresPropertyDefs() const {
42506f32e7eSjoerg   const ObjCInterfaceDecl *Class = this;
42606f32e7eSjoerg   while (Class) {
42706f32e7eSjoerg     if (Class->hasAttr<ObjCRequiresPropertyDefsAttr>())
42806f32e7eSjoerg       return Class;
42906f32e7eSjoerg     Class = Class->getSuperClass();
43006f32e7eSjoerg   }
43106f32e7eSjoerg   return nullptr;
43206f32e7eSjoerg }
43306f32e7eSjoerg 
mergeClassExtensionProtocolList(ObjCProtocolDecl * const * ExtList,unsigned ExtNum,ASTContext & C)43406f32e7eSjoerg void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
43506f32e7eSjoerg                               ObjCProtocolDecl *const* ExtList, unsigned ExtNum,
43606f32e7eSjoerg                               ASTContext &C) {
43706f32e7eSjoerg   if (data().ExternallyCompleted)
43806f32e7eSjoerg     LoadExternalDefinition();
43906f32e7eSjoerg 
44006f32e7eSjoerg   if (data().AllReferencedProtocols.empty() &&
44106f32e7eSjoerg       data().ReferencedProtocols.empty()) {
44206f32e7eSjoerg     data().AllReferencedProtocols.set(ExtList, ExtNum, C);
44306f32e7eSjoerg     return;
44406f32e7eSjoerg   }
44506f32e7eSjoerg 
44606f32e7eSjoerg   // Check for duplicate protocol in class's protocol list.
44706f32e7eSjoerg   // This is O(n*m). But it is extremely rare and number of protocols in
44806f32e7eSjoerg   // class or its extension are very few.
44906f32e7eSjoerg   SmallVector<ObjCProtocolDecl *, 8> ProtocolRefs;
45006f32e7eSjoerg   for (unsigned i = 0; i < ExtNum; i++) {
45106f32e7eSjoerg     bool protocolExists = false;
45206f32e7eSjoerg     ObjCProtocolDecl *ProtoInExtension = ExtList[i];
45306f32e7eSjoerg     for (auto *Proto : all_referenced_protocols()) {
45406f32e7eSjoerg       if (C.ProtocolCompatibleWithProtocol(ProtoInExtension, Proto)) {
45506f32e7eSjoerg         protocolExists = true;
45606f32e7eSjoerg         break;
45706f32e7eSjoerg       }
45806f32e7eSjoerg     }
45906f32e7eSjoerg     // Do we want to warn on a protocol in extension class which
46006f32e7eSjoerg     // already exist in the class? Probably not.
46106f32e7eSjoerg     if (!protocolExists)
46206f32e7eSjoerg       ProtocolRefs.push_back(ProtoInExtension);
46306f32e7eSjoerg   }
46406f32e7eSjoerg 
46506f32e7eSjoerg   if (ProtocolRefs.empty())
46606f32e7eSjoerg     return;
46706f32e7eSjoerg 
46806f32e7eSjoerg   // Merge ProtocolRefs into class's protocol list;
46906f32e7eSjoerg   ProtocolRefs.append(all_referenced_protocol_begin(),
47006f32e7eSjoerg                       all_referenced_protocol_end());
47106f32e7eSjoerg 
47206f32e7eSjoerg   data().AllReferencedProtocols.set(ProtocolRefs.data(), ProtocolRefs.size(),C);
47306f32e7eSjoerg }
47406f32e7eSjoerg 
47506f32e7eSjoerg const ObjCInterfaceDecl *
findInterfaceWithDesignatedInitializers() const47606f32e7eSjoerg ObjCInterfaceDecl::findInterfaceWithDesignatedInitializers() const {
47706f32e7eSjoerg   const ObjCInterfaceDecl *IFace = this;
47806f32e7eSjoerg   while (IFace) {
47906f32e7eSjoerg     if (IFace->hasDesignatedInitializers())
48006f32e7eSjoerg       return IFace;
48106f32e7eSjoerg     if (!IFace->inheritsDesignatedInitializers())
48206f32e7eSjoerg       break;
48306f32e7eSjoerg     IFace = IFace->getSuperClass();
48406f32e7eSjoerg   }
48506f32e7eSjoerg   return nullptr;
48606f32e7eSjoerg }
48706f32e7eSjoerg 
isIntroducingInitializers(const ObjCInterfaceDecl * D)48806f32e7eSjoerg static bool isIntroducingInitializers(const ObjCInterfaceDecl *D) {
48906f32e7eSjoerg   for (const auto *MD : D->instance_methods()) {
49006f32e7eSjoerg     if (MD->getMethodFamily() == OMF_init && !MD->isOverriding())
49106f32e7eSjoerg       return true;
49206f32e7eSjoerg   }
49306f32e7eSjoerg   for (const auto *Ext : D->visible_extensions()) {
49406f32e7eSjoerg     for (const auto *MD : Ext->instance_methods()) {
49506f32e7eSjoerg       if (MD->getMethodFamily() == OMF_init && !MD->isOverriding())
49606f32e7eSjoerg         return true;
49706f32e7eSjoerg     }
49806f32e7eSjoerg   }
49906f32e7eSjoerg   if (const auto *ImplD = D->getImplementation()) {
50006f32e7eSjoerg     for (const auto *MD : ImplD->instance_methods()) {
50106f32e7eSjoerg       if (MD->getMethodFamily() == OMF_init && !MD->isOverriding())
50206f32e7eSjoerg         return true;
50306f32e7eSjoerg     }
50406f32e7eSjoerg   }
50506f32e7eSjoerg   return false;
50606f32e7eSjoerg }
50706f32e7eSjoerg 
inheritsDesignatedInitializers() const50806f32e7eSjoerg bool ObjCInterfaceDecl::inheritsDesignatedInitializers() const {
50906f32e7eSjoerg   switch (data().InheritedDesignatedInitializers) {
51006f32e7eSjoerg   case DefinitionData::IDI_Inherited:
51106f32e7eSjoerg     return true;
51206f32e7eSjoerg   case DefinitionData::IDI_NotInherited:
51306f32e7eSjoerg     return false;
51406f32e7eSjoerg   case DefinitionData::IDI_Unknown:
51506f32e7eSjoerg     // If the class introduced initializers we conservatively assume that we
51606f32e7eSjoerg     // don't know if any of them is a designated initializer to avoid possible
51706f32e7eSjoerg     // misleading warnings.
51806f32e7eSjoerg     if (isIntroducingInitializers(this)) {
51906f32e7eSjoerg       data().InheritedDesignatedInitializers = DefinitionData::IDI_NotInherited;
52006f32e7eSjoerg     } else {
52106f32e7eSjoerg       if (auto SuperD = getSuperClass()) {
52206f32e7eSjoerg         data().InheritedDesignatedInitializers =
52306f32e7eSjoerg           SuperD->declaresOrInheritsDesignatedInitializers() ?
52406f32e7eSjoerg             DefinitionData::IDI_Inherited :
52506f32e7eSjoerg             DefinitionData::IDI_NotInherited;
52606f32e7eSjoerg       } else {
52706f32e7eSjoerg         data().InheritedDesignatedInitializers =
52806f32e7eSjoerg           DefinitionData::IDI_NotInherited;
52906f32e7eSjoerg       }
53006f32e7eSjoerg     }
53106f32e7eSjoerg     assert(data().InheritedDesignatedInitializers
53206f32e7eSjoerg              != DefinitionData::IDI_Unknown);
53306f32e7eSjoerg     return data().InheritedDesignatedInitializers ==
53406f32e7eSjoerg         DefinitionData::IDI_Inherited;
53506f32e7eSjoerg   }
53606f32e7eSjoerg 
53706f32e7eSjoerg   llvm_unreachable("unexpected InheritedDesignatedInitializers value");
53806f32e7eSjoerg }
53906f32e7eSjoerg 
getDesignatedInitializers(llvm::SmallVectorImpl<const ObjCMethodDecl * > & Methods) const54006f32e7eSjoerg void ObjCInterfaceDecl::getDesignatedInitializers(
54106f32e7eSjoerg     llvm::SmallVectorImpl<const ObjCMethodDecl *> &Methods) const {
54206f32e7eSjoerg   // Check for a complete definition and recover if not so.
54306f32e7eSjoerg   if (!isThisDeclarationADefinition())
54406f32e7eSjoerg     return;
54506f32e7eSjoerg   if (data().ExternallyCompleted)
54606f32e7eSjoerg     LoadExternalDefinition();
54706f32e7eSjoerg 
54806f32e7eSjoerg   const ObjCInterfaceDecl *IFace= findInterfaceWithDesignatedInitializers();
54906f32e7eSjoerg   if (!IFace)
55006f32e7eSjoerg     return;
55106f32e7eSjoerg 
55206f32e7eSjoerg   for (const auto *MD : IFace->instance_methods())
55306f32e7eSjoerg     if (MD->isThisDeclarationADesignatedInitializer())
55406f32e7eSjoerg       Methods.push_back(MD);
55506f32e7eSjoerg   for (const auto *Ext : IFace->visible_extensions()) {
55606f32e7eSjoerg     for (const auto *MD : Ext->instance_methods())
55706f32e7eSjoerg       if (MD->isThisDeclarationADesignatedInitializer())
55806f32e7eSjoerg         Methods.push_back(MD);
55906f32e7eSjoerg   }
56006f32e7eSjoerg }
56106f32e7eSjoerg 
isDesignatedInitializer(Selector Sel,const ObjCMethodDecl ** InitMethod) const56206f32e7eSjoerg bool ObjCInterfaceDecl::isDesignatedInitializer(Selector Sel,
56306f32e7eSjoerg                                       const ObjCMethodDecl **InitMethod) const {
56406f32e7eSjoerg   bool HasCompleteDef = isThisDeclarationADefinition();
56506f32e7eSjoerg   // During deserialization the data record for the ObjCInterfaceDecl could
56606f32e7eSjoerg   // be made invariant by reusing the canonical decl. Take this into account
56706f32e7eSjoerg   // when checking for the complete definition.
56806f32e7eSjoerg   if (!HasCompleteDef && getCanonicalDecl()->hasDefinition() &&
56906f32e7eSjoerg       getCanonicalDecl()->getDefinition() == getDefinition())
57006f32e7eSjoerg     HasCompleteDef = true;
57106f32e7eSjoerg 
57206f32e7eSjoerg   // Check for a complete definition and recover if not so.
57306f32e7eSjoerg   if (!HasCompleteDef)
57406f32e7eSjoerg     return false;
57506f32e7eSjoerg 
57606f32e7eSjoerg   if (data().ExternallyCompleted)
57706f32e7eSjoerg     LoadExternalDefinition();
57806f32e7eSjoerg 
57906f32e7eSjoerg   const ObjCInterfaceDecl *IFace= findInterfaceWithDesignatedInitializers();
58006f32e7eSjoerg   if (!IFace)
58106f32e7eSjoerg     return false;
58206f32e7eSjoerg 
58306f32e7eSjoerg   if (const ObjCMethodDecl *MD = IFace->getInstanceMethod(Sel)) {
58406f32e7eSjoerg     if (MD->isThisDeclarationADesignatedInitializer()) {
58506f32e7eSjoerg       if (InitMethod)
58606f32e7eSjoerg         *InitMethod = MD;
58706f32e7eSjoerg       return true;
58806f32e7eSjoerg     }
58906f32e7eSjoerg   }
59006f32e7eSjoerg   for (const auto *Ext : IFace->visible_extensions()) {
59106f32e7eSjoerg     if (const ObjCMethodDecl *MD = Ext->getInstanceMethod(Sel)) {
59206f32e7eSjoerg       if (MD->isThisDeclarationADesignatedInitializer()) {
59306f32e7eSjoerg         if (InitMethod)
59406f32e7eSjoerg           *InitMethod = MD;
59506f32e7eSjoerg         return true;
59606f32e7eSjoerg       }
59706f32e7eSjoerg     }
59806f32e7eSjoerg   }
59906f32e7eSjoerg   return false;
60006f32e7eSjoerg }
60106f32e7eSjoerg 
allocateDefinitionData()60206f32e7eSjoerg void ObjCInterfaceDecl::allocateDefinitionData() {
60306f32e7eSjoerg   assert(!hasDefinition() && "ObjC class already has a definition");
60406f32e7eSjoerg   Data.setPointer(new (getASTContext()) DefinitionData());
60506f32e7eSjoerg   Data.getPointer()->Definition = this;
60606f32e7eSjoerg 
60706f32e7eSjoerg   // Make the type point at the definition, now that we have one.
60806f32e7eSjoerg   if (TypeForDecl)
60906f32e7eSjoerg     cast<ObjCInterfaceType>(TypeForDecl)->Decl = this;
61006f32e7eSjoerg }
61106f32e7eSjoerg 
startDefinition()61206f32e7eSjoerg void ObjCInterfaceDecl::startDefinition() {
61306f32e7eSjoerg   allocateDefinitionData();
61406f32e7eSjoerg 
61506f32e7eSjoerg   // Update all of the declarations with a pointer to the definition.
61606f32e7eSjoerg   for (auto *RD : redecls()) {
61706f32e7eSjoerg     if (RD != this)
61806f32e7eSjoerg       RD->Data = Data;
61906f32e7eSjoerg   }
62006f32e7eSjoerg }
62106f32e7eSjoerg 
lookupInstanceVariable(IdentifierInfo * ID,ObjCInterfaceDecl * & clsDeclared)62206f32e7eSjoerg ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(IdentifierInfo *ID,
62306f32e7eSjoerg                                               ObjCInterfaceDecl *&clsDeclared) {
62406f32e7eSjoerg   // FIXME: Should make sure no callers ever do this.
62506f32e7eSjoerg   if (!hasDefinition())
62606f32e7eSjoerg     return nullptr;
62706f32e7eSjoerg 
62806f32e7eSjoerg   if (data().ExternallyCompleted)
62906f32e7eSjoerg     LoadExternalDefinition();
63006f32e7eSjoerg 
63106f32e7eSjoerg   ObjCInterfaceDecl* ClassDecl = this;
63206f32e7eSjoerg   while (ClassDecl != nullptr) {
63306f32e7eSjoerg     if (ObjCIvarDecl *I = ClassDecl->getIvarDecl(ID)) {
63406f32e7eSjoerg       clsDeclared = ClassDecl;
63506f32e7eSjoerg       return I;
63606f32e7eSjoerg     }
63706f32e7eSjoerg 
63806f32e7eSjoerg     for (const auto *Ext : ClassDecl->visible_extensions()) {
63906f32e7eSjoerg       if (ObjCIvarDecl *I = Ext->getIvarDecl(ID)) {
64006f32e7eSjoerg         clsDeclared = ClassDecl;
64106f32e7eSjoerg         return I;
64206f32e7eSjoerg       }
64306f32e7eSjoerg     }
64406f32e7eSjoerg 
64506f32e7eSjoerg     ClassDecl = ClassDecl->getSuperClass();
64606f32e7eSjoerg   }
64706f32e7eSjoerg   return nullptr;
64806f32e7eSjoerg }
64906f32e7eSjoerg 
65006f32e7eSjoerg /// lookupInheritedClass - This method returns ObjCInterfaceDecl * of the super
65106f32e7eSjoerg /// class whose name is passed as argument. If it is not one of the super classes
65206f32e7eSjoerg /// the it returns NULL.
lookupInheritedClass(const IdentifierInfo * ICName)65306f32e7eSjoerg ObjCInterfaceDecl *ObjCInterfaceDecl::lookupInheritedClass(
65406f32e7eSjoerg                                         const IdentifierInfo*ICName) {
65506f32e7eSjoerg   // FIXME: Should make sure no callers ever do this.
65606f32e7eSjoerg   if (!hasDefinition())
65706f32e7eSjoerg     return nullptr;
65806f32e7eSjoerg 
65906f32e7eSjoerg   if (data().ExternallyCompleted)
66006f32e7eSjoerg     LoadExternalDefinition();
66106f32e7eSjoerg 
66206f32e7eSjoerg   ObjCInterfaceDecl* ClassDecl = this;
66306f32e7eSjoerg   while (ClassDecl != nullptr) {
66406f32e7eSjoerg     if (ClassDecl->getIdentifier() == ICName)
66506f32e7eSjoerg       return ClassDecl;
66606f32e7eSjoerg     ClassDecl = ClassDecl->getSuperClass();
66706f32e7eSjoerg   }
66806f32e7eSjoerg   return nullptr;
66906f32e7eSjoerg }
67006f32e7eSjoerg 
67106f32e7eSjoerg ObjCProtocolDecl *
lookupNestedProtocol(IdentifierInfo * Name)67206f32e7eSjoerg ObjCInterfaceDecl::lookupNestedProtocol(IdentifierInfo *Name) {
67306f32e7eSjoerg   for (auto *P : all_referenced_protocols())
67406f32e7eSjoerg     if (P->lookupProtocolNamed(Name))
67506f32e7eSjoerg       return P;
67606f32e7eSjoerg   ObjCInterfaceDecl *SuperClass = getSuperClass();
67706f32e7eSjoerg   return SuperClass ? SuperClass->lookupNestedProtocol(Name) : nullptr;
67806f32e7eSjoerg }
67906f32e7eSjoerg 
68006f32e7eSjoerg /// lookupMethod - This method returns an instance/class method by looking in
68106f32e7eSjoerg /// the class, its categories, and its super classes (using a linear search).
68206f32e7eSjoerg /// When argument category "C" is specified, any implicit method found
68306f32e7eSjoerg /// in this category is ignored.
lookupMethod(Selector Sel,bool isInstance,bool shallowCategoryLookup,bool followSuper,const ObjCCategoryDecl * C) const68406f32e7eSjoerg ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel,
68506f32e7eSjoerg                                                 bool isInstance,
68606f32e7eSjoerg                                                 bool shallowCategoryLookup,
68706f32e7eSjoerg                                                 bool followSuper,
68806f32e7eSjoerg                                                 const ObjCCategoryDecl *C) const
68906f32e7eSjoerg {
69006f32e7eSjoerg   // FIXME: Should make sure no callers ever do this.
69106f32e7eSjoerg   if (!hasDefinition())
69206f32e7eSjoerg     return nullptr;
69306f32e7eSjoerg 
69406f32e7eSjoerg   const ObjCInterfaceDecl* ClassDecl = this;
69506f32e7eSjoerg   ObjCMethodDecl *MethodDecl = nullptr;
69606f32e7eSjoerg 
69706f32e7eSjoerg   if (data().ExternallyCompleted)
69806f32e7eSjoerg     LoadExternalDefinition();
69906f32e7eSjoerg 
70006f32e7eSjoerg   while (ClassDecl) {
70106f32e7eSjoerg     // 1. Look through primary class.
70206f32e7eSjoerg     if ((MethodDecl = ClassDecl->getMethod(Sel, isInstance)))
70306f32e7eSjoerg       return MethodDecl;
70406f32e7eSjoerg 
70506f32e7eSjoerg     // 2. Didn't find one yet - now look through categories.
70606f32e7eSjoerg     for (const auto *Cat : ClassDecl->visible_categories())
70706f32e7eSjoerg       if ((MethodDecl = Cat->getMethod(Sel, isInstance)))
70806f32e7eSjoerg         if (C != Cat || !MethodDecl->isImplicit())
70906f32e7eSjoerg           return MethodDecl;
71006f32e7eSjoerg 
71106f32e7eSjoerg     // 3. Didn't find one yet - look through primary class's protocols.
71206f32e7eSjoerg     for (const auto *I : ClassDecl->protocols())
71306f32e7eSjoerg       if ((MethodDecl = I->lookupMethod(Sel, isInstance)))
71406f32e7eSjoerg         return MethodDecl;
71506f32e7eSjoerg 
71606f32e7eSjoerg     // 4. Didn't find one yet - now look through categories' protocols
71706f32e7eSjoerg     if (!shallowCategoryLookup)
71806f32e7eSjoerg       for (const auto *Cat : ClassDecl->visible_categories()) {
71906f32e7eSjoerg         // Didn't find one yet - look through protocols.
72006f32e7eSjoerg         const ObjCList<ObjCProtocolDecl> &Protocols =
72106f32e7eSjoerg           Cat->getReferencedProtocols();
72206f32e7eSjoerg         for (auto *Protocol : Protocols)
72306f32e7eSjoerg           if ((MethodDecl = Protocol->lookupMethod(Sel, isInstance)))
72406f32e7eSjoerg             if (C != Cat || !MethodDecl->isImplicit())
72506f32e7eSjoerg               return MethodDecl;
72606f32e7eSjoerg       }
72706f32e7eSjoerg 
72806f32e7eSjoerg 
72906f32e7eSjoerg     if (!followSuper)
73006f32e7eSjoerg       return nullptr;
73106f32e7eSjoerg 
73206f32e7eSjoerg     // 5. Get to the super class (if any).
73306f32e7eSjoerg     ClassDecl = ClassDecl->getSuperClass();
73406f32e7eSjoerg   }
73506f32e7eSjoerg   return nullptr;
73606f32e7eSjoerg }
73706f32e7eSjoerg 
73806f32e7eSjoerg // Will search "local" class/category implementations for a method decl.
73906f32e7eSjoerg // If failed, then we search in class's root for an instance method.
74006f32e7eSjoerg // Returns 0 if no method is found.
lookupPrivateMethod(const Selector & Sel,bool Instance) const74106f32e7eSjoerg ObjCMethodDecl *ObjCInterfaceDecl::lookupPrivateMethod(
74206f32e7eSjoerg                                    const Selector &Sel,
74306f32e7eSjoerg                                    bool Instance) const {
74406f32e7eSjoerg   // FIXME: Should make sure no callers ever do this.
74506f32e7eSjoerg   if (!hasDefinition())
74606f32e7eSjoerg     return nullptr;
74706f32e7eSjoerg 
74806f32e7eSjoerg   if (data().ExternallyCompleted)
74906f32e7eSjoerg     LoadExternalDefinition();
75006f32e7eSjoerg 
75106f32e7eSjoerg   ObjCMethodDecl *Method = nullptr;
75206f32e7eSjoerg   if (ObjCImplementationDecl *ImpDecl = getImplementation())
75306f32e7eSjoerg     Method = Instance ? ImpDecl->getInstanceMethod(Sel)
75406f32e7eSjoerg                       : ImpDecl->getClassMethod(Sel);
75506f32e7eSjoerg 
75606f32e7eSjoerg   // Look through local category implementations associated with the class.
75706f32e7eSjoerg   if (!Method)
75806f32e7eSjoerg     Method = getCategoryMethod(Sel, Instance);
75906f32e7eSjoerg 
76006f32e7eSjoerg   // Before we give up, check if the selector is an instance method.
76106f32e7eSjoerg   // But only in the root. This matches gcc's behavior and what the
76206f32e7eSjoerg   // runtime expects.
76306f32e7eSjoerg   if (!Instance && !Method && !getSuperClass()) {
76406f32e7eSjoerg     Method = lookupInstanceMethod(Sel);
76506f32e7eSjoerg     // Look through local category implementations associated
76606f32e7eSjoerg     // with the root class.
76706f32e7eSjoerg     if (!Method)
76806f32e7eSjoerg       Method = lookupPrivateMethod(Sel, true);
76906f32e7eSjoerg   }
77006f32e7eSjoerg 
77106f32e7eSjoerg   if (!Method && getSuperClass())
77206f32e7eSjoerg     return getSuperClass()->lookupPrivateMethod(Sel, Instance);
77306f32e7eSjoerg   return Method;
77406f32e7eSjoerg }
77506f32e7eSjoerg 
77606f32e7eSjoerg //===----------------------------------------------------------------------===//
77706f32e7eSjoerg // ObjCMethodDecl
77806f32e7eSjoerg //===----------------------------------------------------------------------===//
77906f32e7eSjoerg 
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)780*13fbcb42Sjoerg ObjCMethodDecl::ObjCMethodDecl(
781*13fbcb42Sjoerg     SourceLocation beginLoc, SourceLocation endLoc, Selector SelInfo,
782*13fbcb42Sjoerg     QualType T, TypeSourceInfo *ReturnTInfo, DeclContext *contextDecl,
783*13fbcb42Sjoerg     bool isInstance, bool isVariadic, bool isPropertyAccessor,
784*13fbcb42Sjoerg     bool isSynthesizedAccessorStub, bool isImplicitlyDeclared, bool isDefined,
785*13fbcb42Sjoerg     ImplementationControl impControl, bool HasRelatedResultType)
78606f32e7eSjoerg     : NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo),
78706f32e7eSjoerg       DeclContext(ObjCMethod), MethodDeclType(T), ReturnTInfo(ReturnTInfo),
78806f32e7eSjoerg       DeclEndLoc(endLoc) {
78906f32e7eSjoerg 
79006f32e7eSjoerg   // Initialized the bits stored in DeclContext.
79106f32e7eSjoerg   ObjCMethodDeclBits.Family =
79206f32e7eSjoerg       static_cast<ObjCMethodFamily>(InvalidObjCMethodFamily);
79306f32e7eSjoerg   setInstanceMethod(isInstance);
79406f32e7eSjoerg   setVariadic(isVariadic);
79506f32e7eSjoerg   setPropertyAccessor(isPropertyAccessor);
796*13fbcb42Sjoerg   setSynthesizedAccessorStub(isSynthesizedAccessorStub);
79706f32e7eSjoerg   setDefined(isDefined);
79806f32e7eSjoerg   setIsRedeclaration(false);
79906f32e7eSjoerg   setHasRedeclaration(false);
80006f32e7eSjoerg   setDeclImplementation(impControl);
80106f32e7eSjoerg   setObjCDeclQualifier(OBJC_TQ_None);
80206f32e7eSjoerg   setRelatedResultType(HasRelatedResultType);
80306f32e7eSjoerg   setSelLocsKind(SelLoc_StandardNoSpace);
80406f32e7eSjoerg   setOverriding(false);
80506f32e7eSjoerg   setHasSkippedBody(false);
80606f32e7eSjoerg 
80706f32e7eSjoerg   setImplicit(isImplicitlyDeclared);
80806f32e7eSjoerg }
80906f32e7eSjoerg 
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)81006f32e7eSjoerg ObjCMethodDecl *ObjCMethodDecl::Create(
81106f32e7eSjoerg     ASTContext &C, SourceLocation beginLoc, SourceLocation endLoc,
81206f32e7eSjoerg     Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo,
81306f32e7eSjoerg     DeclContext *contextDecl, bool isInstance, bool isVariadic,
814*13fbcb42Sjoerg     bool isPropertyAccessor, bool isSynthesizedAccessorStub,
815*13fbcb42Sjoerg     bool isImplicitlyDeclared, bool isDefined, ImplementationControl impControl,
816*13fbcb42Sjoerg     bool HasRelatedResultType) {
81706f32e7eSjoerg   return new (C, contextDecl) ObjCMethodDecl(
81806f32e7eSjoerg       beginLoc, endLoc, SelInfo, T, ReturnTInfo, contextDecl, isInstance,
819*13fbcb42Sjoerg       isVariadic, isPropertyAccessor, isSynthesizedAccessorStub,
820*13fbcb42Sjoerg       isImplicitlyDeclared, isDefined, impControl, HasRelatedResultType);
82106f32e7eSjoerg }
82206f32e7eSjoerg 
CreateDeserialized(ASTContext & C,unsigned ID)82306f32e7eSjoerg ObjCMethodDecl *ObjCMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
82406f32e7eSjoerg   return new (C, ID) ObjCMethodDecl(SourceLocation(), SourceLocation(),
82506f32e7eSjoerg                                     Selector(), QualType(), nullptr, nullptr);
82606f32e7eSjoerg }
82706f32e7eSjoerg 
isDirectMethod() const828*13fbcb42Sjoerg bool ObjCMethodDecl::isDirectMethod() const {
829*13fbcb42Sjoerg   return hasAttr<ObjCDirectAttr>() &&
830*13fbcb42Sjoerg          !getASTContext().getLangOpts().ObjCDisableDirectMethodsForTesting;
831*13fbcb42Sjoerg }
832*13fbcb42Sjoerg 
isThisDeclarationADesignatedInitializer() const83306f32e7eSjoerg bool ObjCMethodDecl::isThisDeclarationADesignatedInitializer() const {
83406f32e7eSjoerg   return getMethodFamily() == OMF_init &&
83506f32e7eSjoerg       hasAttr<ObjCDesignatedInitializerAttr>();
83606f32e7eSjoerg }
83706f32e7eSjoerg 
definedInNSObject(const ASTContext & Ctx) const83806f32e7eSjoerg bool ObjCMethodDecl::definedInNSObject(const ASTContext &Ctx) const {
83906f32e7eSjoerg   if (const auto *PD = dyn_cast<const ObjCProtocolDecl>(getDeclContext()))
84006f32e7eSjoerg     return PD->getIdentifier() == Ctx.getNSObjectName();
84106f32e7eSjoerg   if (const auto *ID = dyn_cast<const ObjCInterfaceDecl>(getDeclContext()))
84206f32e7eSjoerg     return ID->getIdentifier() == Ctx.getNSObjectName();
84306f32e7eSjoerg   return false;
84406f32e7eSjoerg }
84506f32e7eSjoerg 
isDesignatedInitializerForTheInterface(const ObjCMethodDecl ** InitMethod) const84606f32e7eSjoerg bool ObjCMethodDecl::isDesignatedInitializerForTheInterface(
84706f32e7eSjoerg     const ObjCMethodDecl **InitMethod) const {
84806f32e7eSjoerg   if (getMethodFamily() != OMF_init)
84906f32e7eSjoerg     return false;
85006f32e7eSjoerg   const DeclContext *DC = getDeclContext();
85106f32e7eSjoerg   if (isa<ObjCProtocolDecl>(DC))
85206f32e7eSjoerg     return false;
85306f32e7eSjoerg   if (const ObjCInterfaceDecl *ID = getClassInterface())
85406f32e7eSjoerg     return ID->isDesignatedInitializer(getSelector(), InitMethod);
85506f32e7eSjoerg   return false;
85606f32e7eSjoerg }
85706f32e7eSjoerg 
getBody() const85806f32e7eSjoerg Stmt *ObjCMethodDecl::getBody() const {
85906f32e7eSjoerg   return Body.get(getASTContext().getExternalSource());
86006f32e7eSjoerg }
86106f32e7eSjoerg 
setAsRedeclaration(const ObjCMethodDecl * PrevMethod)86206f32e7eSjoerg void ObjCMethodDecl::setAsRedeclaration(const ObjCMethodDecl *PrevMethod) {
86306f32e7eSjoerg   assert(PrevMethod);
86406f32e7eSjoerg   getASTContext().setObjCMethodRedeclaration(PrevMethod, this);
86506f32e7eSjoerg   setIsRedeclaration(true);
86606f32e7eSjoerg   PrevMethod->setHasRedeclaration(true);
86706f32e7eSjoerg }
86806f32e7eSjoerg 
setParamsAndSelLocs(ASTContext & C,ArrayRef<ParmVarDecl * > Params,ArrayRef<SourceLocation> SelLocs)86906f32e7eSjoerg void ObjCMethodDecl::setParamsAndSelLocs(ASTContext &C,
87006f32e7eSjoerg                                          ArrayRef<ParmVarDecl*> Params,
87106f32e7eSjoerg                                          ArrayRef<SourceLocation> SelLocs) {
87206f32e7eSjoerg   ParamsAndSelLocs = nullptr;
87306f32e7eSjoerg   NumParams = Params.size();
87406f32e7eSjoerg   if (Params.empty() && SelLocs.empty())
87506f32e7eSjoerg     return;
87606f32e7eSjoerg 
87706f32e7eSjoerg   static_assert(alignof(ParmVarDecl *) >= alignof(SourceLocation),
87806f32e7eSjoerg                 "Alignment not sufficient for SourceLocation");
87906f32e7eSjoerg 
88006f32e7eSjoerg   unsigned Size = sizeof(ParmVarDecl *) * NumParams +
88106f32e7eSjoerg                   sizeof(SourceLocation) * SelLocs.size();
88206f32e7eSjoerg   ParamsAndSelLocs = C.Allocate(Size);
88306f32e7eSjoerg   std::copy(Params.begin(), Params.end(), getParams());
88406f32e7eSjoerg   std::copy(SelLocs.begin(), SelLocs.end(), getStoredSelLocs());
88506f32e7eSjoerg }
88606f32e7eSjoerg 
getSelectorLocs(SmallVectorImpl<SourceLocation> & SelLocs) const88706f32e7eSjoerg void ObjCMethodDecl::getSelectorLocs(
88806f32e7eSjoerg                                SmallVectorImpl<SourceLocation> &SelLocs) const {
88906f32e7eSjoerg   for (unsigned i = 0, e = getNumSelectorLocs(); i != e; ++i)
89006f32e7eSjoerg     SelLocs.push_back(getSelectorLoc(i));
89106f32e7eSjoerg }
89206f32e7eSjoerg 
setMethodParams(ASTContext & C,ArrayRef<ParmVarDecl * > Params,ArrayRef<SourceLocation> SelLocs)89306f32e7eSjoerg void ObjCMethodDecl::setMethodParams(ASTContext &C,
89406f32e7eSjoerg                                      ArrayRef<ParmVarDecl*> Params,
89506f32e7eSjoerg                                      ArrayRef<SourceLocation> SelLocs) {
89606f32e7eSjoerg   assert((!SelLocs.empty() || isImplicit()) &&
89706f32e7eSjoerg          "No selector locs for non-implicit method");
89806f32e7eSjoerg   if (isImplicit())
89906f32e7eSjoerg     return setParamsAndSelLocs(C, Params, llvm::None);
90006f32e7eSjoerg 
90106f32e7eSjoerg   setSelLocsKind(hasStandardSelectorLocs(getSelector(), SelLocs, Params,
90206f32e7eSjoerg                                         DeclEndLoc));
90306f32e7eSjoerg   if (getSelLocsKind() != SelLoc_NonStandard)
90406f32e7eSjoerg     return setParamsAndSelLocs(C, Params, llvm::None);
90506f32e7eSjoerg 
90606f32e7eSjoerg   setParamsAndSelLocs(C, Params, SelLocs);
90706f32e7eSjoerg }
90806f32e7eSjoerg 
90906f32e7eSjoerg /// A definition will return its interface declaration.
91006f32e7eSjoerg /// An interface declaration will return its definition.
91106f32e7eSjoerg /// Otherwise it will return itself.
getNextRedeclarationImpl()91206f32e7eSjoerg ObjCMethodDecl *ObjCMethodDecl::getNextRedeclarationImpl() {
91306f32e7eSjoerg   ASTContext &Ctx = getASTContext();
91406f32e7eSjoerg   ObjCMethodDecl *Redecl = nullptr;
91506f32e7eSjoerg   if (hasRedeclaration())
91606f32e7eSjoerg     Redecl = const_cast<ObjCMethodDecl*>(Ctx.getObjCMethodRedeclaration(this));
91706f32e7eSjoerg   if (Redecl)
91806f32e7eSjoerg     return Redecl;
91906f32e7eSjoerg 
92006f32e7eSjoerg   auto *CtxD = cast<Decl>(getDeclContext());
92106f32e7eSjoerg 
92206f32e7eSjoerg   if (!CtxD->isInvalidDecl()) {
92306f32e7eSjoerg     if (auto *IFD = dyn_cast<ObjCInterfaceDecl>(CtxD)) {
92406f32e7eSjoerg       if (ObjCImplementationDecl *ImplD = Ctx.getObjCImplementation(IFD))
92506f32e7eSjoerg         if (!ImplD->isInvalidDecl())
92606f32e7eSjoerg           Redecl = ImplD->getMethod(getSelector(), isInstanceMethod());
92706f32e7eSjoerg 
92806f32e7eSjoerg     } else if (auto *CD = dyn_cast<ObjCCategoryDecl>(CtxD)) {
92906f32e7eSjoerg       if (ObjCCategoryImplDecl *ImplD = Ctx.getObjCImplementation(CD))
93006f32e7eSjoerg         if (!ImplD->isInvalidDecl())
93106f32e7eSjoerg           Redecl = ImplD->getMethod(getSelector(), isInstanceMethod());
93206f32e7eSjoerg 
93306f32e7eSjoerg     } else if (auto *ImplD = dyn_cast<ObjCImplementationDecl>(CtxD)) {
93406f32e7eSjoerg       if (ObjCInterfaceDecl *IFD = ImplD->getClassInterface())
93506f32e7eSjoerg         if (!IFD->isInvalidDecl())
93606f32e7eSjoerg           Redecl = IFD->getMethod(getSelector(), isInstanceMethod());
93706f32e7eSjoerg 
93806f32e7eSjoerg     } else if (auto *CImplD = dyn_cast<ObjCCategoryImplDecl>(CtxD)) {
93906f32e7eSjoerg       if (ObjCCategoryDecl *CatD = CImplD->getCategoryDecl())
94006f32e7eSjoerg         if (!CatD->isInvalidDecl())
94106f32e7eSjoerg           Redecl = CatD->getMethod(getSelector(), isInstanceMethod());
94206f32e7eSjoerg     }
94306f32e7eSjoerg   }
94406f32e7eSjoerg 
94506f32e7eSjoerg   // Ensure that the discovered method redeclaration has a valid declaration
94606f32e7eSjoerg   // context. Used to prevent infinite loops when iterating redeclarations in
94706f32e7eSjoerg   // a partially invalid AST.
94806f32e7eSjoerg   if (Redecl && cast<Decl>(Redecl->getDeclContext())->isInvalidDecl())
94906f32e7eSjoerg     Redecl = nullptr;
95006f32e7eSjoerg 
95106f32e7eSjoerg   if (!Redecl && isRedeclaration()) {
95206f32e7eSjoerg     // This is the last redeclaration, go back to the first method.
95306f32e7eSjoerg     return cast<ObjCContainerDecl>(CtxD)->getMethod(getSelector(),
954*13fbcb42Sjoerg                                                     isInstanceMethod(),
955*13fbcb42Sjoerg                                                     /*AllowHidden=*/true);
95606f32e7eSjoerg   }
95706f32e7eSjoerg 
95806f32e7eSjoerg   return Redecl ? Redecl : this;
95906f32e7eSjoerg }
96006f32e7eSjoerg 
getCanonicalDecl()96106f32e7eSjoerg ObjCMethodDecl *ObjCMethodDecl::getCanonicalDecl() {
96206f32e7eSjoerg   auto *CtxD = cast<Decl>(getDeclContext());
963*13fbcb42Sjoerg   const auto &Sel = getSelector();
96406f32e7eSjoerg 
96506f32e7eSjoerg   if (auto *ImplD = dyn_cast<ObjCImplementationDecl>(CtxD)) {
966*13fbcb42Sjoerg     if (ObjCInterfaceDecl *IFD = ImplD->getClassInterface()) {
967*13fbcb42Sjoerg       // When the container is the ObjCImplementationDecl (the primary
968*13fbcb42Sjoerg       // @implementation), then the canonical Decl is either in
969*13fbcb42Sjoerg       // the class Interface, or in any of its extension.
970*13fbcb42Sjoerg       //
971*13fbcb42Sjoerg       // So when we don't find it in the ObjCInterfaceDecl,
972*13fbcb42Sjoerg       // sift through extensions too.
973*13fbcb42Sjoerg       if (ObjCMethodDecl *MD = IFD->getMethod(Sel, isInstanceMethod()))
97406f32e7eSjoerg         return MD;
975*13fbcb42Sjoerg       for (auto *Ext : IFD->known_extensions())
976*13fbcb42Sjoerg         if (ObjCMethodDecl *MD = Ext->getMethod(Sel, isInstanceMethod()))
977*13fbcb42Sjoerg           return MD;
978*13fbcb42Sjoerg     }
97906f32e7eSjoerg   } else if (auto *CImplD = dyn_cast<ObjCCategoryImplDecl>(CtxD)) {
98006f32e7eSjoerg     if (ObjCCategoryDecl *CatD = CImplD->getCategoryDecl())
981*13fbcb42Sjoerg       if (ObjCMethodDecl *MD = CatD->getMethod(Sel, isInstanceMethod()))
98206f32e7eSjoerg         return MD;
98306f32e7eSjoerg   }
98406f32e7eSjoerg 
98506f32e7eSjoerg   if (isRedeclaration()) {
98606f32e7eSjoerg     // It is possible that we have not done deserializing the ObjCMethod yet.
98706f32e7eSjoerg     ObjCMethodDecl *MD =
988*13fbcb42Sjoerg         cast<ObjCContainerDecl>(CtxD)->getMethod(Sel, isInstanceMethod(),
989*13fbcb42Sjoerg                                                  /*AllowHidden=*/true);
99006f32e7eSjoerg     return MD ? MD : this;
99106f32e7eSjoerg   }
99206f32e7eSjoerg 
99306f32e7eSjoerg   return this;
99406f32e7eSjoerg }
99506f32e7eSjoerg 
getEndLoc() const99606f32e7eSjoerg SourceLocation ObjCMethodDecl::getEndLoc() const {
99706f32e7eSjoerg   if (Stmt *Body = getBody())
99806f32e7eSjoerg     return Body->getEndLoc();
99906f32e7eSjoerg   return DeclEndLoc;
100006f32e7eSjoerg }
100106f32e7eSjoerg 
getMethodFamily() const100206f32e7eSjoerg ObjCMethodFamily ObjCMethodDecl::getMethodFamily() const {
100306f32e7eSjoerg   auto family = static_cast<ObjCMethodFamily>(ObjCMethodDeclBits.Family);
100406f32e7eSjoerg   if (family != static_cast<unsigned>(InvalidObjCMethodFamily))
100506f32e7eSjoerg     return family;
100606f32e7eSjoerg 
100706f32e7eSjoerg   // Check for an explicit attribute.
100806f32e7eSjoerg   if (const ObjCMethodFamilyAttr *attr = getAttr<ObjCMethodFamilyAttr>()) {
100906f32e7eSjoerg     // The unfortunate necessity of mapping between enums here is due
101006f32e7eSjoerg     // to the attributes framework.
101106f32e7eSjoerg     switch (attr->getFamily()) {
101206f32e7eSjoerg     case ObjCMethodFamilyAttr::OMF_None: family = OMF_None; break;
101306f32e7eSjoerg     case ObjCMethodFamilyAttr::OMF_alloc: family = OMF_alloc; break;
101406f32e7eSjoerg     case ObjCMethodFamilyAttr::OMF_copy: family = OMF_copy; break;
101506f32e7eSjoerg     case ObjCMethodFamilyAttr::OMF_init: family = OMF_init; break;
101606f32e7eSjoerg     case ObjCMethodFamilyAttr::OMF_mutableCopy: family = OMF_mutableCopy; break;
101706f32e7eSjoerg     case ObjCMethodFamilyAttr::OMF_new: family = OMF_new; break;
101806f32e7eSjoerg     }
101906f32e7eSjoerg     ObjCMethodDeclBits.Family = family;
102006f32e7eSjoerg     return family;
102106f32e7eSjoerg   }
102206f32e7eSjoerg 
102306f32e7eSjoerg   family = getSelector().getMethodFamily();
102406f32e7eSjoerg   switch (family) {
102506f32e7eSjoerg   case OMF_None: break;
102606f32e7eSjoerg 
102706f32e7eSjoerg   // init only has a conventional meaning for an instance method, and
102806f32e7eSjoerg   // it has to return an object.
102906f32e7eSjoerg   case OMF_init:
103006f32e7eSjoerg     if (!isInstanceMethod() || !getReturnType()->isObjCObjectPointerType())
103106f32e7eSjoerg       family = OMF_None;
103206f32e7eSjoerg     break;
103306f32e7eSjoerg 
103406f32e7eSjoerg   // alloc/copy/new have a conventional meaning for both class and
103506f32e7eSjoerg   // instance methods, but they require an object return.
103606f32e7eSjoerg   case OMF_alloc:
103706f32e7eSjoerg   case OMF_copy:
103806f32e7eSjoerg   case OMF_mutableCopy:
103906f32e7eSjoerg   case OMF_new:
104006f32e7eSjoerg     if (!getReturnType()->isObjCObjectPointerType())
104106f32e7eSjoerg       family = OMF_None;
104206f32e7eSjoerg     break;
104306f32e7eSjoerg 
104406f32e7eSjoerg   // These selectors have a conventional meaning only for instance methods.
104506f32e7eSjoerg   case OMF_dealloc:
104606f32e7eSjoerg   case OMF_finalize:
104706f32e7eSjoerg   case OMF_retain:
104806f32e7eSjoerg   case OMF_release:
104906f32e7eSjoerg   case OMF_autorelease:
105006f32e7eSjoerg   case OMF_retainCount:
105106f32e7eSjoerg   case OMF_self:
105206f32e7eSjoerg     if (!isInstanceMethod())
105306f32e7eSjoerg       family = OMF_None;
105406f32e7eSjoerg     break;
105506f32e7eSjoerg 
105606f32e7eSjoerg   case OMF_initialize:
105706f32e7eSjoerg     if (isInstanceMethod() || !getReturnType()->isVoidType())
105806f32e7eSjoerg       family = OMF_None;
105906f32e7eSjoerg     break;
106006f32e7eSjoerg 
106106f32e7eSjoerg   case OMF_performSelector:
106206f32e7eSjoerg     if (!isInstanceMethod() || !getReturnType()->isObjCIdType())
106306f32e7eSjoerg       family = OMF_None;
106406f32e7eSjoerg     else {
106506f32e7eSjoerg       unsigned noParams = param_size();
106606f32e7eSjoerg       if (noParams < 1 || noParams > 3)
106706f32e7eSjoerg         family = OMF_None;
106806f32e7eSjoerg       else {
106906f32e7eSjoerg         ObjCMethodDecl::param_type_iterator it = param_type_begin();
107006f32e7eSjoerg         QualType ArgT = (*it);
107106f32e7eSjoerg         if (!ArgT->isObjCSelType()) {
107206f32e7eSjoerg           family = OMF_None;
107306f32e7eSjoerg           break;
107406f32e7eSjoerg         }
107506f32e7eSjoerg         while (--noParams) {
107606f32e7eSjoerg           it++;
107706f32e7eSjoerg           ArgT = (*it);
107806f32e7eSjoerg           if (!ArgT->isObjCIdType()) {
107906f32e7eSjoerg             family = OMF_None;
108006f32e7eSjoerg             break;
108106f32e7eSjoerg           }
108206f32e7eSjoerg         }
108306f32e7eSjoerg       }
108406f32e7eSjoerg     }
108506f32e7eSjoerg     break;
108606f32e7eSjoerg 
108706f32e7eSjoerg   }
108806f32e7eSjoerg 
108906f32e7eSjoerg   // Cache the result.
109006f32e7eSjoerg   ObjCMethodDeclBits.Family = family;
109106f32e7eSjoerg   return family;
109206f32e7eSjoerg }
109306f32e7eSjoerg 
getSelfType(ASTContext & Context,const ObjCInterfaceDecl * OID,bool & selfIsPseudoStrong,bool & selfIsConsumed) const109406f32e7eSjoerg QualType ObjCMethodDecl::getSelfType(ASTContext &Context,
109506f32e7eSjoerg                                      const ObjCInterfaceDecl *OID,
109606f32e7eSjoerg                                      bool &selfIsPseudoStrong,
1097*13fbcb42Sjoerg                                      bool &selfIsConsumed) const {
109806f32e7eSjoerg   QualType selfTy;
109906f32e7eSjoerg   selfIsPseudoStrong = false;
110006f32e7eSjoerg   selfIsConsumed = false;
110106f32e7eSjoerg   if (isInstanceMethod()) {
110206f32e7eSjoerg     // There may be no interface context due to error in declaration
110306f32e7eSjoerg     // of the interface (which has been reported). Recover gracefully.
110406f32e7eSjoerg     if (OID) {
110506f32e7eSjoerg       selfTy = Context.getObjCInterfaceType(OID);
110606f32e7eSjoerg       selfTy = Context.getObjCObjectPointerType(selfTy);
110706f32e7eSjoerg     } else {
110806f32e7eSjoerg       selfTy = Context.getObjCIdType();
110906f32e7eSjoerg     }
111006f32e7eSjoerg   } else // we have a factory method.
111106f32e7eSjoerg     selfTy = Context.getObjCClassType();
111206f32e7eSjoerg 
111306f32e7eSjoerg   if (Context.getLangOpts().ObjCAutoRefCount) {
111406f32e7eSjoerg     if (isInstanceMethod()) {
111506f32e7eSjoerg       selfIsConsumed = hasAttr<NSConsumesSelfAttr>();
111606f32e7eSjoerg 
111706f32e7eSjoerg       // 'self' is always __strong.  It's actually pseudo-strong except
111806f32e7eSjoerg       // in init methods (or methods labeled ns_consumes_self), though.
111906f32e7eSjoerg       Qualifiers qs;
112006f32e7eSjoerg       qs.setObjCLifetime(Qualifiers::OCL_Strong);
112106f32e7eSjoerg       selfTy = Context.getQualifiedType(selfTy, qs);
112206f32e7eSjoerg 
112306f32e7eSjoerg       // In addition, 'self' is const unless this is an init method.
112406f32e7eSjoerg       if (getMethodFamily() != OMF_init && !selfIsConsumed) {
112506f32e7eSjoerg         selfTy = selfTy.withConst();
112606f32e7eSjoerg         selfIsPseudoStrong = true;
112706f32e7eSjoerg       }
112806f32e7eSjoerg     }
112906f32e7eSjoerg     else {
113006f32e7eSjoerg       assert(isClassMethod());
113106f32e7eSjoerg       // 'self' is always const in class methods.
113206f32e7eSjoerg       selfTy = selfTy.withConst();
113306f32e7eSjoerg       selfIsPseudoStrong = true;
113406f32e7eSjoerg     }
113506f32e7eSjoerg   }
113606f32e7eSjoerg   return selfTy;
113706f32e7eSjoerg }
113806f32e7eSjoerg 
createImplicitParams(ASTContext & Context,const ObjCInterfaceDecl * OID)113906f32e7eSjoerg void ObjCMethodDecl::createImplicitParams(ASTContext &Context,
114006f32e7eSjoerg                                           const ObjCInterfaceDecl *OID) {
114106f32e7eSjoerg   bool selfIsPseudoStrong, selfIsConsumed;
114206f32e7eSjoerg   QualType selfTy =
114306f32e7eSjoerg     getSelfType(Context, OID, selfIsPseudoStrong, selfIsConsumed);
114406f32e7eSjoerg   auto *Self = ImplicitParamDecl::Create(Context, this, SourceLocation(),
114506f32e7eSjoerg                                          &Context.Idents.get("self"), selfTy,
114606f32e7eSjoerg                                          ImplicitParamDecl::ObjCSelf);
114706f32e7eSjoerg   setSelfDecl(Self);
114806f32e7eSjoerg 
114906f32e7eSjoerg   if (selfIsConsumed)
115006f32e7eSjoerg     Self->addAttr(NSConsumedAttr::CreateImplicit(Context));
115106f32e7eSjoerg 
115206f32e7eSjoerg   if (selfIsPseudoStrong)
115306f32e7eSjoerg     Self->setARCPseudoStrong(true);
115406f32e7eSjoerg 
115506f32e7eSjoerg   setCmdDecl(ImplicitParamDecl::Create(
115606f32e7eSjoerg       Context, this, SourceLocation(), &Context.Idents.get("_cmd"),
115706f32e7eSjoerg       Context.getObjCSelType(), ImplicitParamDecl::ObjCCmd));
115806f32e7eSjoerg }
115906f32e7eSjoerg 
getClassInterface()116006f32e7eSjoerg ObjCInterfaceDecl *ObjCMethodDecl::getClassInterface() {
116106f32e7eSjoerg   if (auto *ID = dyn_cast<ObjCInterfaceDecl>(getDeclContext()))
116206f32e7eSjoerg     return ID;
116306f32e7eSjoerg   if (auto *CD = dyn_cast<ObjCCategoryDecl>(getDeclContext()))
116406f32e7eSjoerg     return CD->getClassInterface();
116506f32e7eSjoerg   if (auto *IMD = dyn_cast<ObjCImplDecl>(getDeclContext()))
116606f32e7eSjoerg     return IMD->getClassInterface();
116706f32e7eSjoerg   if (isa<ObjCProtocolDecl>(getDeclContext()))
116806f32e7eSjoerg     return nullptr;
116906f32e7eSjoerg   llvm_unreachable("unknown method context");
117006f32e7eSjoerg }
117106f32e7eSjoerg 
getCategory()1172*13fbcb42Sjoerg ObjCCategoryDecl *ObjCMethodDecl::getCategory() {
1173*13fbcb42Sjoerg   if (auto *CD = dyn_cast<ObjCCategoryDecl>(getDeclContext()))
1174*13fbcb42Sjoerg     return CD;
1175*13fbcb42Sjoerg   if (auto *IMD = dyn_cast<ObjCCategoryImplDecl>(getDeclContext()))
1176*13fbcb42Sjoerg     return IMD->getCategoryDecl();
1177*13fbcb42Sjoerg   return nullptr;
1178*13fbcb42Sjoerg }
1179*13fbcb42Sjoerg 
getReturnTypeSourceRange() const118006f32e7eSjoerg SourceRange ObjCMethodDecl::getReturnTypeSourceRange() const {
118106f32e7eSjoerg   const auto *TSI = getReturnTypeSourceInfo();
118206f32e7eSjoerg   if (TSI)
118306f32e7eSjoerg     return TSI->getTypeLoc().getSourceRange();
118406f32e7eSjoerg   return SourceRange();
118506f32e7eSjoerg }
118606f32e7eSjoerg 
getSendResultType() const118706f32e7eSjoerg QualType ObjCMethodDecl::getSendResultType() const {
118806f32e7eSjoerg   ASTContext &Ctx = getASTContext();
118906f32e7eSjoerg   return getReturnType().getNonLValueExprType(Ctx)
119006f32e7eSjoerg            .substObjCTypeArgs(Ctx, {}, ObjCSubstitutionContext::Result);
119106f32e7eSjoerg }
119206f32e7eSjoerg 
getSendResultType(QualType receiverType) const119306f32e7eSjoerg QualType ObjCMethodDecl::getSendResultType(QualType receiverType) const {
119406f32e7eSjoerg   // FIXME: Handle related result types here.
119506f32e7eSjoerg 
119606f32e7eSjoerg   return getReturnType().getNonLValueExprType(getASTContext())
119706f32e7eSjoerg            .substObjCMemberType(receiverType, getDeclContext(),
119806f32e7eSjoerg                                 ObjCSubstitutionContext::Result);
119906f32e7eSjoerg }
120006f32e7eSjoerg 
CollectOverriddenMethodsRecurse(const ObjCContainerDecl * Container,const ObjCMethodDecl * Method,SmallVectorImpl<const ObjCMethodDecl * > & Methods,bool MovedToSuper)120106f32e7eSjoerg static void CollectOverriddenMethodsRecurse(const ObjCContainerDecl *Container,
120206f32e7eSjoerg                                             const ObjCMethodDecl *Method,
120306f32e7eSjoerg                                SmallVectorImpl<const ObjCMethodDecl *> &Methods,
120406f32e7eSjoerg                                             bool MovedToSuper) {
120506f32e7eSjoerg   if (!Container)
120606f32e7eSjoerg     return;
120706f32e7eSjoerg 
120806f32e7eSjoerg   // In categories look for overridden methods from protocols. A method from
120906f32e7eSjoerg   // category is not "overridden" since it is considered as the "same" method
121006f32e7eSjoerg   // (same USR) as the one from the interface.
121106f32e7eSjoerg   if (const auto *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
121206f32e7eSjoerg     // Check whether we have a matching method at this category but only if we
121306f32e7eSjoerg     // are at the super class level.
121406f32e7eSjoerg     if (MovedToSuper)
121506f32e7eSjoerg       if (ObjCMethodDecl *
121606f32e7eSjoerg             Overridden = Container->getMethod(Method->getSelector(),
121706f32e7eSjoerg                                               Method->isInstanceMethod(),
121806f32e7eSjoerg                                               /*AllowHidden=*/true))
121906f32e7eSjoerg         if (Method != Overridden) {
122006f32e7eSjoerg           // We found an override at this category; there is no need to look
122106f32e7eSjoerg           // into its protocols.
122206f32e7eSjoerg           Methods.push_back(Overridden);
122306f32e7eSjoerg           return;
122406f32e7eSjoerg         }
122506f32e7eSjoerg 
122606f32e7eSjoerg     for (const auto *P : Category->protocols())
122706f32e7eSjoerg       CollectOverriddenMethodsRecurse(P, Method, Methods, MovedToSuper);
122806f32e7eSjoerg     return;
122906f32e7eSjoerg   }
123006f32e7eSjoerg 
123106f32e7eSjoerg   // Check whether we have a matching method at this level.
123206f32e7eSjoerg   if (const ObjCMethodDecl *
123306f32e7eSjoerg         Overridden = Container->getMethod(Method->getSelector(),
123406f32e7eSjoerg                                           Method->isInstanceMethod(),
123506f32e7eSjoerg                                           /*AllowHidden=*/true))
123606f32e7eSjoerg     if (Method != Overridden) {
123706f32e7eSjoerg       // We found an override at this level; there is no need to look
123806f32e7eSjoerg       // into other protocols or categories.
123906f32e7eSjoerg       Methods.push_back(Overridden);
124006f32e7eSjoerg       return;
124106f32e7eSjoerg     }
124206f32e7eSjoerg 
124306f32e7eSjoerg   if (const auto *Protocol = dyn_cast<ObjCProtocolDecl>(Container)){
124406f32e7eSjoerg     for (const auto *P : Protocol->protocols())
124506f32e7eSjoerg       CollectOverriddenMethodsRecurse(P, Method, Methods, MovedToSuper);
124606f32e7eSjoerg   }
124706f32e7eSjoerg 
124806f32e7eSjoerg   if (const auto *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
124906f32e7eSjoerg     for (const auto *P : Interface->protocols())
125006f32e7eSjoerg       CollectOverriddenMethodsRecurse(P, Method, Methods, MovedToSuper);
125106f32e7eSjoerg 
125206f32e7eSjoerg     for (const auto *Cat : Interface->known_categories())
125306f32e7eSjoerg       CollectOverriddenMethodsRecurse(Cat, Method, Methods, MovedToSuper);
125406f32e7eSjoerg 
125506f32e7eSjoerg     if (const ObjCInterfaceDecl *Super = Interface->getSuperClass())
125606f32e7eSjoerg       return CollectOverriddenMethodsRecurse(Super, Method, Methods,
125706f32e7eSjoerg                                              /*MovedToSuper=*/true);
125806f32e7eSjoerg   }
125906f32e7eSjoerg }
126006f32e7eSjoerg 
CollectOverriddenMethods(const ObjCContainerDecl * Container,const ObjCMethodDecl * Method,SmallVectorImpl<const ObjCMethodDecl * > & Methods)126106f32e7eSjoerg static inline void CollectOverriddenMethods(const ObjCContainerDecl *Container,
126206f32e7eSjoerg                                             const ObjCMethodDecl *Method,
126306f32e7eSjoerg                              SmallVectorImpl<const ObjCMethodDecl *> &Methods) {
126406f32e7eSjoerg   CollectOverriddenMethodsRecurse(Container, Method, Methods,
126506f32e7eSjoerg                                   /*MovedToSuper=*/false);
126606f32e7eSjoerg }
126706f32e7eSjoerg 
collectOverriddenMethodsSlow(const ObjCMethodDecl * Method,SmallVectorImpl<const ObjCMethodDecl * > & overridden)126806f32e7eSjoerg static void collectOverriddenMethodsSlow(const ObjCMethodDecl *Method,
126906f32e7eSjoerg                           SmallVectorImpl<const ObjCMethodDecl *> &overridden) {
127006f32e7eSjoerg   assert(Method->isOverriding());
127106f32e7eSjoerg 
127206f32e7eSjoerg   if (const auto *ProtD =
127306f32e7eSjoerg           dyn_cast<ObjCProtocolDecl>(Method->getDeclContext())) {
127406f32e7eSjoerg     CollectOverriddenMethods(ProtD, Method, overridden);
127506f32e7eSjoerg 
127606f32e7eSjoerg   } else if (const auto *IMD =
127706f32e7eSjoerg                  dyn_cast<ObjCImplDecl>(Method->getDeclContext())) {
127806f32e7eSjoerg     const ObjCInterfaceDecl *ID = IMD->getClassInterface();
127906f32e7eSjoerg     if (!ID)
128006f32e7eSjoerg       return;
128106f32e7eSjoerg     // Start searching for overridden methods using the method from the
128206f32e7eSjoerg     // interface as starting point.
128306f32e7eSjoerg     if (const ObjCMethodDecl *IFaceMeth = ID->getMethod(Method->getSelector(),
128406f32e7eSjoerg                                                     Method->isInstanceMethod(),
128506f32e7eSjoerg                                                     /*AllowHidden=*/true))
128606f32e7eSjoerg       Method = IFaceMeth;
128706f32e7eSjoerg     CollectOverriddenMethods(ID, Method, overridden);
128806f32e7eSjoerg 
128906f32e7eSjoerg   } else if (const auto *CatD =
129006f32e7eSjoerg                  dyn_cast<ObjCCategoryDecl>(Method->getDeclContext())) {
129106f32e7eSjoerg     const ObjCInterfaceDecl *ID = CatD->getClassInterface();
129206f32e7eSjoerg     if (!ID)
129306f32e7eSjoerg       return;
129406f32e7eSjoerg     // Start searching for overridden methods using the method from the
129506f32e7eSjoerg     // interface as starting point.
129606f32e7eSjoerg     if (const ObjCMethodDecl *IFaceMeth = ID->getMethod(Method->getSelector(),
129706f32e7eSjoerg                                                      Method->isInstanceMethod(),
129806f32e7eSjoerg                                                      /*AllowHidden=*/true))
129906f32e7eSjoerg       Method = IFaceMeth;
130006f32e7eSjoerg     CollectOverriddenMethods(ID, Method, overridden);
130106f32e7eSjoerg 
130206f32e7eSjoerg   } else {
130306f32e7eSjoerg     CollectOverriddenMethods(
130406f32e7eSjoerg                   dyn_cast_or_null<ObjCContainerDecl>(Method->getDeclContext()),
130506f32e7eSjoerg                   Method, overridden);
130606f32e7eSjoerg   }
130706f32e7eSjoerg }
130806f32e7eSjoerg 
getOverriddenMethods(SmallVectorImpl<const ObjCMethodDecl * > & Overridden) const130906f32e7eSjoerg void ObjCMethodDecl::getOverriddenMethods(
131006f32e7eSjoerg                     SmallVectorImpl<const ObjCMethodDecl *> &Overridden) const {
131106f32e7eSjoerg   const ObjCMethodDecl *Method = this;
131206f32e7eSjoerg 
131306f32e7eSjoerg   if (Method->isRedeclaration()) {
1314*13fbcb42Sjoerg     Method = cast<ObjCContainerDecl>(Method->getDeclContext())
1315*13fbcb42Sjoerg                  ->getMethod(Method->getSelector(), Method->isInstanceMethod(),
1316*13fbcb42Sjoerg                              /*AllowHidden=*/true);
131706f32e7eSjoerg   }
131806f32e7eSjoerg 
131906f32e7eSjoerg   if (Method->isOverriding()) {
132006f32e7eSjoerg     collectOverriddenMethodsSlow(Method, Overridden);
132106f32e7eSjoerg     assert(!Overridden.empty() &&
132206f32e7eSjoerg            "ObjCMethodDecl's overriding bit is not as expected");
132306f32e7eSjoerg   }
132406f32e7eSjoerg }
132506f32e7eSjoerg 
132606f32e7eSjoerg const ObjCPropertyDecl *
findPropertyDecl(bool CheckOverrides) const132706f32e7eSjoerg ObjCMethodDecl::findPropertyDecl(bool CheckOverrides) const {
132806f32e7eSjoerg   Selector Sel = getSelector();
132906f32e7eSjoerg   unsigned NumArgs = Sel.getNumArgs();
133006f32e7eSjoerg   if (NumArgs > 1)
133106f32e7eSjoerg     return nullptr;
133206f32e7eSjoerg 
133306f32e7eSjoerg   if (isPropertyAccessor()) {
133406f32e7eSjoerg     const auto *Container = cast<ObjCContainerDecl>(getParent());
1335*13fbcb42Sjoerg     // For accessor stubs, go back to the interface.
1336*13fbcb42Sjoerg     if (auto *ImplDecl = dyn_cast<ObjCImplDecl>(Container))
1337*13fbcb42Sjoerg       if (isSynthesizedAccessorStub())
1338*13fbcb42Sjoerg         Container = ImplDecl->getClassInterface();
1339*13fbcb42Sjoerg 
134006f32e7eSjoerg     bool IsGetter = (NumArgs == 0);
134106f32e7eSjoerg     bool IsInstance = isInstanceMethod();
134206f32e7eSjoerg 
134306f32e7eSjoerg     /// Local function that attempts to find a matching property within the
134406f32e7eSjoerg     /// given Objective-C container.
134506f32e7eSjoerg     auto findMatchingProperty =
134606f32e7eSjoerg       [&](const ObjCContainerDecl *Container) -> const ObjCPropertyDecl * {
134706f32e7eSjoerg       if (IsInstance) {
134806f32e7eSjoerg         for (const auto *I : Container->instance_properties()) {
134906f32e7eSjoerg           Selector NextSel = IsGetter ? I->getGetterName()
135006f32e7eSjoerg                                       : I->getSetterName();
135106f32e7eSjoerg           if (NextSel == Sel)
135206f32e7eSjoerg             return I;
135306f32e7eSjoerg         }
135406f32e7eSjoerg       } else {
135506f32e7eSjoerg         for (const auto *I : Container->class_properties()) {
135606f32e7eSjoerg           Selector NextSel = IsGetter ? I->getGetterName()
135706f32e7eSjoerg                                       : I->getSetterName();
135806f32e7eSjoerg           if (NextSel == Sel)
135906f32e7eSjoerg             return I;
136006f32e7eSjoerg         }
136106f32e7eSjoerg       }
136206f32e7eSjoerg 
136306f32e7eSjoerg       return nullptr;
136406f32e7eSjoerg     };
136506f32e7eSjoerg 
136606f32e7eSjoerg     // Look in the container we were given.
136706f32e7eSjoerg     if (const auto *Found = findMatchingProperty(Container))
136806f32e7eSjoerg       return Found;
136906f32e7eSjoerg 
137006f32e7eSjoerg     // If we're in a category or extension, look in the main class.
137106f32e7eSjoerg     const ObjCInterfaceDecl *ClassDecl = nullptr;
137206f32e7eSjoerg     if (const auto *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
137306f32e7eSjoerg       ClassDecl = Category->getClassInterface();
137406f32e7eSjoerg       if (const auto *Found = findMatchingProperty(ClassDecl))
137506f32e7eSjoerg         return Found;
137606f32e7eSjoerg     } else {
137706f32e7eSjoerg       // Determine whether the container is a class.
1378*13fbcb42Sjoerg       ClassDecl = cast<ObjCInterfaceDecl>(Container);
137906f32e7eSjoerg     }
1380*13fbcb42Sjoerg     assert(ClassDecl && "Failed to find main class");
138106f32e7eSjoerg 
138206f32e7eSjoerg     // If we have a class, check its visible extensions.
138306f32e7eSjoerg     for (const auto *Ext : ClassDecl->visible_extensions()) {
138406f32e7eSjoerg       if (Ext == Container)
138506f32e7eSjoerg         continue;
138606f32e7eSjoerg       if (const auto *Found = findMatchingProperty(Ext))
138706f32e7eSjoerg         return Found;
138806f32e7eSjoerg     }
1389*13fbcb42Sjoerg 
1390*13fbcb42Sjoerg     assert(isSynthesizedAccessorStub() && "expected an accessor stub");
1391*13fbcb42Sjoerg 
1392*13fbcb42Sjoerg     for (const auto *Cat : ClassDecl->known_categories()) {
1393*13fbcb42Sjoerg       if (Cat == Container)
1394*13fbcb42Sjoerg         continue;
1395*13fbcb42Sjoerg       if (const auto *Found = findMatchingProperty(Cat))
1396*13fbcb42Sjoerg         return Found;
139706f32e7eSjoerg     }
139806f32e7eSjoerg 
139906f32e7eSjoerg     llvm_unreachable("Marked as a property accessor but no property found!");
140006f32e7eSjoerg   }
140106f32e7eSjoerg 
140206f32e7eSjoerg   if (!CheckOverrides)
140306f32e7eSjoerg     return nullptr;
140406f32e7eSjoerg 
140506f32e7eSjoerg   using OverridesTy = SmallVector<const ObjCMethodDecl *, 8>;
140606f32e7eSjoerg 
140706f32e7eSjoerg   OverridesTy Overrides;
140806f32e7eSjoerg   getOverriddenMethods(Overrides);
140906f32e7eSjoerg   for (const auto *Override : Overrides)
141006f32e7eSjoerg     if (const ObjCPropertyDecl *Prop = Override->findPropertyDecl(false))
141106f32e7eSjoerg       return Prop;
141206f32e7eSjoerg 
141306f32e7eSjoerg   return nullptr;
141406f32e7eSjoerg }
141506f32e7eSjoerg 
141606f32e7eSjoerg //===----------------------------------------------------------------------===//
141706f32e7eSjoerg // ObjCTypeParamDecl
141806f32e7eSjoerg //===----------------------------------------------------------------------===//
141906f32e7eSjoerg 
anchor()142006f32e7eSjoerg void ObjCTypeParamDecl::anchor() {}
142106f32e7eSjoerg 
Create(ASTContext & ctx,DeclContext * dc,ObjCTypeParamVariance variance,SourceLocation varianceLoc,unsigned index,SourceLocation nameLoc,IdentifierInfo * name,SourceLocation colonLoc,TypeSourceInfo * boundInfo)142206f32e7eSjoerg ObjCTypeParamDecl *ObjCTypeParamDecl::Create(ASTContext &ctx, DeclContext *dc,
142306f32e7eSjoerg                                              ObjCTypeParamVariance variance,
142406f32e7eSjoerg                                              SourceLocation varianceLoc,
142506f32e7eSjoerg                                              unsigned index,
142606f32e7eSjoerg                                              SourceLocation nameLoc,
142706f32e7eSjoerg                                              IdentifierInfo *name,
142806f32e7eSjoerg                                              SourceLocation colonLoc,
142906f32e7eSjoerg                                              TypeSourceInfo *boundInfo) {
143006f32e7eSjoerg   auto *TPDecl =
143106f32e7eSjoerg     new (ctx, dc) ObjCTypeParamDecl(ctx, dc, variance, varianceLoc, index,
143206f32e7eSjoerg                                     nameLoc, name, colonLoc, boundInfo);
143306f32e7eSjoerg   QualType TPType = ctx.getObjCTypeParamType(TPDecl, {});
143406f32e7eSjoerg   TPDecl->setTypeForDecl(TPType.getTypePtr());
143506f32e7eSjoerg   return TPDecl;
143606f32e7eSjoerg }
143706f32e7eSjoerg 
CreateDeserialized(ASTContext & ctx,unsigned ID)143806f32e7eSjoerg ObjCTypeParamDecl *ObjCTypeParamDecl::CreateDeserialized(ASTContext &ctx,
143906f32e7eSjoerg                                                          unsigned ID) {
144006f32e7eSjoerg   return new (ctx, ID) ObjCTypeParamDecl(ctx, nullptr,
144106f32e7eSjoerg                                          ObjCTypeParamVariance::Invariant,
144206f32e7eSjoerg                                          SourceLocation(), 0, SourceLocation(),
144306f32e7eSjoerg                                          nullptr, SourceLocation(), nullptr);
144406f32e7eSjoerg }
144506f32e7eSjoerg 
getSourceRange() const144606f32e7eSjoerg SourceRange ObjCTypeParamDecl::getSourceRange() const {
144706f32e7eSjoerg   SourceLocation startLoc = VarianceLoc;
144806f32e7eSjoerg   if (startLoc.isInvalid())
144906f32e7eSjoerg     startLoc = getLocation();
145006f32e7eSjoerg 
145106f32e7eSjoerg   if (hasExplicitBound()) {
145206f32e7eSjoerg     return SourceRange(startLoc,
145306f32e7eSjoerg                        getTypeSourceInfo()->getTypeLoc().getEndLoc());
145406f32e7eSjoerg   }
145506f32e7eSjoerg 
145606f32e7eSjoerg   return SourceRange(startLoc);
145706f32e7eSjoerg }
145806f32e7eSjoerg 
145906f32e7eSjoerg //===----------------------------------------------------------------------===//
146006f32e7eSjoerg // ObjCTypeParamList
146106f32e7eSjoerg //===----------------------------------------------------------------------===//
ObjCTypeParamList(SourceLocation lAngleLoc,ArrayRef<ObjCTypeParamDecl * > typeParams,SourceLocation rAngleLoc)146206f32e7eSjoerg ObjCTypeParamList::ObjCTypeParamList(SourceLocation lAngleLoc,
146306f32e7eSjoerg                                      ArrayRef<ObjCTypeParamDecl *> typeParams,
146406f32e7eSjoerg                                      SourceLocation rAngleLoc)
1465*13fbcb42Sjoerg     : Brackets(lAngleLoc, rAngleLoc), NumParams(typeParams.size()) {
146606f32e7eSjoerg   std::copy(typeParams.begin(), typeParams.end(), begin());
146706f32e7eSjoerg }
146806f32e7eSjoerg 
create(ASTContext & ctx,SourceLocation lAngleLoc,ArrayRef<ObjCTypeParamDecl * > typeParams,SourceLocation rAngleLoc)146906f32e7eSjoerg ObjCTypeParamList *ObjCTypeParamList::create(
147006f32e7eSjoerg                      ASTContext &ctx,
147106f32e7eSjoerg                      SourceLocation lAngleLoc,
147206f32e7eSjoerg                      ArrayRef<ObjCTypeParamDecl *> typeParams,
147306f32e7eSjoerg                      SourceLocation rAngleLoc) {
147406f32e7eSjoerg   void *mem =
147506f32e7eSjoerg       ctx.Allocate(totalSizeToAlloc<ObjCTypeParamDecl *>(typeParams.size()),
147606f32e7eSjoerg                    alignof(ObjCTypeParamList));
147706f32e7eSjoerg   return new (mem) ObjCTypeParamList(lAngleLoc, typeParams, rAngleLoc);
147806f32e7eSjoerg }
147906f32e7eSjoerg 
gatherDefaultTypeArgs(SmallVectorImpl<QualType> & typeArgs) const148006f32e7eSjoerg void ObjCTypeParamList::gatherDefaultTypeArgs(
148106f32e7eSjoerg        SmallVectorImpl<QualType> &typeArgs) const {
148206f32e7eSjoerg   typeArgs.reserve(size());
148306f32e7eSjoerg   for (auto typeParam : *this)
148406f32e7eSjoerg     typeArgs.push_back(typeParam->getUnderlyingType());
148506f32e7eSjoerg }
148606f32e7eSjoerg 
148706f32e7eSjoerg //===----------------------------------------------------------------------===//
148806f32e7eSjoerg // ObjCInterfaceDecl
148906f32e7eSjoerg //===----------------------------------------------------------------------===//
149006f32e7eSjoerg 
Create(const ASTContext & C,DeclContext * DC,SourceLocation atLoc,IdentifierInfo * Id,ObjCTypeParamList * typeParamList,ObjCInterfaceDecl * PrevDecl,SourceLocation ClassLoc,bool isInternal)149106f32e7eSjoerg ObjCInterfaceDecl *ObjCInterfaceDecl::Create(const ASTContext &C,
149206f32e7eSjoerg                                              DeclContext *DC,
149306f32e7eSjoerg                                              SourceLocation atLoc,
149406f32e7eSjoerg                                              IdentifierInfo *Id,
149506f32e7eSjoerg                                              ObjCTypeParamList *typeParamList,
149606f32e7eSjoerg                                              ObjCInterfaceDecl *PrevDecl,
149706f32e7eSjoerg                                              SourceLocation ClassLoc,
149806f32e7eSjoerg                                              bool isInternal){
149906f32e7eSjoerg   auto *Result = new (C, DC)
150006f32e7eSjoerg       ObjCInterfaceDecl(C, DC, atLoc, Id, typeParamList, ClassLoc, PrevDecl,
150106f32e7eSjoerg                         isInternal);
150206f32e7eSjoerg   Result->Data.setInt(!C.getLangOpts().Modules);
150306f32e7eSjoerg   C.getObjCInterfaceType(Result, PrevDecl);
150406f32e7eSjoerg   return Result;
150506f32e7eSjoerg }
150606f32e7eSjoerg 
CreateDeserialized(const ASTContext & C,unsigned ID)150706f32e7eSjoerg ObjCInterfaceDecl *ObjCInterfaceDecl::CreateDeserialized(const ASTContext &C,
150806f32e7eSjoerg                                                          unsigned ID) {
150906f32e7eSjoerg   auto *Result = new (C, ID)
151006f32e7eSjoerg       ObjCInterfaceDecl(C, nullptr, SourceLocation(), nullptr, nullptr,
151106f32e7eSjoerg                         SourceLocation(), nullptr, false);
151206f32e7eSjoerg   Result->Data.setInt(!C.getLangOpts().Modules);
151306f32e7eSjoerg   return Result;
151406f32e7eSjoerg }
151506f32e7eSjoerg 
ObjCInterfaceDecl(const ASTContext & C,DeclContext * DC,SourceLocation AtLoc,IdentifierInfo * Id,ObjCTypeParamList * typeParamList,SourceLocation CLoc,ObjCInterfaceDecl * PrevDecl,bool IsInternal)151606f32e7eSjoerg ObjCInterfaceDecl::ObjCInterfaceDecl(const ASTContext &C, DeclContext *DC,
151706f32e7eSjoerg                                      SourceLocation AtLoc, IdentifierInfo *Id,
151806f32e7eSjoerg                                      ObjCTypeParamList *typeParamList,
151906f32e7eSjoerg                                      SourceLocation CLoc,
152006f32e7eSjoerg                                      ObjCInterfaceDecl *PrevDecl,
152106f32e7eSjoerg                                      bool IsInternal)
152206f32e7eSjoerg     : ObjCContainerDecl(ObjCInterface, DC, Id, CLoc, AtLoc),
152306f32e7eSjoerg       redeclarable_base(C) {
152406f32e7eSjoerg   setPreviousDecl(PrevDecl);
152506f32e7eSjoerg 
152606f32e7eSjoerg   // Copy the 'data' pointer over.
152706f32e7eSjoerg   if (PrevDecl)
152806f32e7eSjoerg     Data = PrevDecl->Data;
152906f32e7eSjoerg 
153006f32e7eSjoerg   setImplicit(IsInternal);
153106f32e7eSjoerg 
153206f32e7eSjoerg   setTypeParamList(typeParamList);
153306f32e7eSjoerg }
153406f32e7eSjoerg 
LoadExternalDefinition() const153506f32e7eSjoerg void ObjCInterfaceDecl::LoadExternalDefinition() const {
153606f32e7eSjoerg   assert(data().ExternallyCompleted && "Class is not externally completed");
153706f32e7eSjoerg   data().ExternallyCompleted = false;
153806f32e7eSjoerg   getASTContext().getExternalSource()->CompleteType(
153906f32e7eSjoerg                                         const_cast<ObjCInterfaceDecl *>(this));
154006f32e7eSjoerg }
154106f32e7eSjoerg 
setExternallyCompleted()154206f32e7eSjoerg void ObjCInterfaceDecl::setExternallyCompleted() {
154306f32e7eSjoerg   assert(getASTContext().getExternalSource() &&
154406f32e7eSjoerg          "Class can't be externally completed without an external source");
154506f32e7eSjoerg   assert(hasDefinition() &&
154606f32e7eSjoerg          "Forward declarations can't be externally completed");
154706f32e7eSjoerg   data().ExternallyCompleted = true;
154806f32e7eSjoerg }
154906f32e7eSjoerg 
setHasDesignatedInitializers()155006f32e7eSjoerg void ObjCInterfaceDecl::setHasDesignatedInitializers() {
155106f32e7eSjoerg   // Check for a complete definition and recover if not so.
155206f32e7eSjoerg   if (!isThisDeclarationADefinition())
155306f32e7eSjoerg     return;
155406f32e7eSjoerg   data().HasDesignatedInitializers = true;
155506f32e7eSjoerg }
155606f32e7eSjoerg 
hasDesignatedInitializers() const155706f32e7eSjoerg bool ObjCInterfaceDecl::hasDesignatedInitializers() const {
155806f32e7eSjoerg   // Check for a complete definition and recover if not so.
155906f32e7eSjoerg   if (!isThisDeclarationADefinition())
156006f32e7eSjoerg     return false;
156106f32e7eSjoerg   if (data().ExternallyCompleted)
156206f32e7eSjoerg     LoadExternalDefinition();
156306f32e7eSjoerg 
156406f32e7eSjoerg   return data().HasDesignatedInitializers;
156506f32e7eSjoerg }
156606f32e7eSjoerg 
156706f32e7eSjoerg StringRef
getObjCRuntimeNameAsString() const156806f32e7eSjoerg ObjCInterfaceDecl::getObjCRuntimeNameAsString() const {
156906f32e7eSjoerg   if (const auto *ObjCRTName = getAttr<ObjCRuntimeNameAttr>())
157006f32e7eSjoerg     return ObjCRTName->getMetadataName();
157106f32e7eSjoerg 
157206f32e7eSjoerg   return getName();
157306f32e7eSjoerg }
157406f32e7eSjoerg 
157506f32e7eSjoerg StringRef
getObjCRuntimeNameAsString() const157606f32e7eSjoerg ObjCImplementationDecl::getObjCRuntimeNameAsString() const {
157706f32e7eSjoerg   if (ObjCInterfaceDecl *ID =
157806f32e7eSjoerg       const_cast<ObjCImplementationDecl*>(this)->getClassInterface())
157906f32e7eSjoerg     return ID->getObjCRuntimeNameAsString();
158006f32e7eSjoerg 
158106f32e7eSjoerg   return getName();
158206f32e7eSjoerg }
158306f32e7eSjoerg 
getImplementation() const158406f32e7eSjoerg ObjCImplementationDecl *ObjCInterfaceDecl::getImplementation() const {
158506f32e7eSjoerg   if (const ObjCInterfaceDecl *Def = getDefinition()) {
158606f32e7eSjoerg     if (data().ExternallyCompleted)
158706f32e7eSjoerg       LoadExternalDefinition();
158806f32e7eSjoerg 
158906f32e7eSjoerg     return getASTContext().getObjCImplementation(
159006f32e7eSjoerg              const_cast<ObjCInterfaceDecl*>(Def));
159106f32e7eSjoerg   }
159206f32e7eSjoerg 
159306f32e7eSjoerg   // FIXME: Should make sure no callers ever do this.
159406f32e7eSjoerg   return nullptr;
159506f32e7eSjoerg }
159606f32e7eSjoerg 
setImplementation(ObjCImplementationDecl * ImplD)159706f32e7eSjoerg void ObjCInterfaceDecl::setImplementation(ObjCImplementationDecl *ImplD) {
159806f32e7eSjoerg   getASTContext().setObjCImplementation(getDefinition(), ImplD);
159906f32e7eSjoerg }
160006f32e7eSjoerg 
160106f32e7eSjoerg namespace {
160206f32e7eSjoerg 
160306f32e7eSjoerg struct SynthesizeIvarChunk {
160406f32e7eSjoerg   uint64_t Size;
160506f32e7eSjoerg   ObjCIvarDecl *Ivar;
160606f32e7eSjoerg 
SynthesizeIvarChunk__anon823593a80211::SynthesizeIvarChunk160706f32e7eSjoerg   SynthesizeIvarChunk(uint64_t size, ObjCIvarDecl *ivar)
160806f32e7eSjoerg       : Size(size), Ivar(ivar) {}
160906f32e7eSjoerg };
161006f32e7eSjoerg 
operator <(const SynthesizeIvarChunk & LHS,const SynthesizeIvarChunk & RHS)161106f32e7eSjoerg bool operator<(const SynthesizeIvarChunk & LHS,
161206f32e7eSjoerg                const SynthesizeIvarChunk &RHS) {
161306f32e7eSjoerg     return LHS.Size < RHS.Size;
161406f32e7eSjoerg }
161506f32e7eSjoerg 
161606f32e7eSjoerg } // namespace
161706f32e7eSjoerg 
161806f32e7eSjoerg /// all_declared_ivar_begin - return first ivar declared in this class,
161906f32e7eSjoerg /// its extensions and its implementation. Lazily build the list on first
162006f32e7eSjoerg /// access.
162106f32e7eSjoerg ///
162206f32e7eSjoerg /// Caveat: The list returned by this method reflects the current
162306f32e7eSjoerg /// state of the parser. The cache will be updated for every ivar
162406f32e7eSjoerg /// added by an extension or the implementation when they are
162506f32e7eSjoerg /// encountered.
162606f32e7eSjoerg /// See also ObjCIvarDecl::Create().
all_declared_ivar_begin()162706f32e7eSjoerg ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() {
162806f32e7eSjoerg   // FIXME: Should make sure no callers ever do this.
162906f32e7eSjoerg   if (!hasDefinition())
163006f32e7eSjoerg     return nullptr;
163106f32e7eSjoerg 
163206f32e7eSjoerg   ObjCIvarDecl *curIvar = nullptr;
163306f32e7eSjoerg   if (!data().IvarList) {
163406f32e7eSjoerg     if (!ivar_empty()) {
163506f32e7eSjoerg       ObjCInterfaceDecl::ivar_iterator I = ivar_begin(), E = ivar_end();
163606f32e7eSjoerg       data().IvarList = *I; ++I;
163706f32e7eSjoerg       for (curIvar = data().IvarList; I != E; curIvar = *I, ++I)
163806f32e7eSjoerg         curIvar->setNextIvar(*I);
163906f32e7eSjoerg     }
164006f32e7eSjoerg 
164106f32e7eSjoerg     for (const auto *Ext : known_extensions()) {
164206f32e7eSjoerg       if (!Ext->ivar_empty()) {
164306f32e7eSjoerg         ObjCCategoryDecl::ivar_iterator
164406f32e7eSjoerg           I = Ext->ivar_begin(),
164506f32e7eSjoerg           E = Ext->ivar_end();
164606f32e7eSjoerg         if (!data().IvarList) {
164706f32e7eSjoerg           data().IvarList = *I; ++I;
164806f32e7eSjoerg           curIvar = data().IvarList;
164906f32e7eSjoerg         }
165006f32e7eSjoerg         for ( ;I != E; curIvar = *I, ++I)
165106f32e7eSjoerg           curIvar->setNextIvar(*I);
165206f32e7eSjoerg       }
165306f32e7eSjoerg     }
165406f32e7eSjoerg     data().IvarListMissingImplementation = true;
165506f32e7eSjoerg   }
165606f32e7eSjoerg 
165706f32e7eSjoerg   // cached and complete!
165806f32e7eSjoerg   if (!data().IvarListMissingImplementation)
165906f32e7eSjoerg       return data().IvarList;
166006f32e7eSjoerg 
166106f32e7eSjoerg   if (ObjCImplementationDecl *ImplDecl = getImplementation()) {
166206f32e7eSjoerg     data().IvarListMissingImplementation = false;
166306f32e7eSjoerg     if (!ImplDecl->ivar_empty()) {
166406f32e7eSjoerg       SmallVector<SynthesizeIvarChunk, 16> layout;
166506f32e7eSjoerg       for (auto *IV : ImplDecl->ivars()) {
166606f32e7eSjoerg         if (IV->getSynthesize() && !IV->isInvalidDecl()) {
166706f32e7eSjoerg           layout.push_back(SynthesizeIvarChunk(
166806f32e7eSjoerg                              IV->getASTContext().getTypeSize(IV->getType()), IV));
166906f32e7eSjoerg           continue;
167006f32e7eSjoerg         }
167106f32e7eSjoerg         if (!data().IvarList)
167206f32e7eSjoerg           data().IvarList = IV;
167306f32e7eSjoerg         else
167406f32e7eSjoerg           curIvar->setNextIvar(IV);
167506f32e7eSjoerg         curIvar = IV;
167606f32e7eSjoerg       }
167706f32e7eSjoerg 
167806f32e7eSjoerg       if (!layout.empty()) {
167906f32e7eSjoerg         // Order synthesized ivars by their size.
168006f32e7eSjoerg         llvm::stable_sort(layout);
168106f32e7eSjoerg         unsigned Ix = 0, EIx = layout.size();
168206f32e7eSjoerg         if (!data().IvarList) {
168306f32e7eSjoerg           data().IvarList = layout[0].Ivar; Ix++;
168406f32e7eSjoerg           curIvar = data().IvarList;
168506f32e7eSjoerg         }
168606f32e7eSjoerg         for ( ; Ix != EIx; curIvar = layout[Ix].Ivar, Ix++)
168706f32e7eSjoerg           curIvar->setNextIvar(layout[Ix].Ivar);
168806f32e7eSjoerg       }
168906f32e7eSjoerg     }
169006f32e7eSjoerg   }
169106f32e7eSjoerg   return data().IvarList;
169206f32e7eSjoerg }
169306f32e7eSjoerg 
169406f32e7eSjoerg /// FindCategoryDeclaration - Finds category declaration in the list of
169506f32e7eSjoerg /// categories for this class and returns it. Name of the category is passed
169606f32e7eSjoerg /// in 'CategoryId'. If category not found, return 0;
169706f32e7eSjoerg ///
169806f32e7eSjoerg ObjCCategoryDecl *
FindCategoryDeclaration(IdentifierInfo * CategoryId) const169906f32e7eSjoerg ObjCInterfaceDecl::FindCategoryDeclaration(IdentifierInfo *CategoryId) const {
170006f32e7eSjoerg   // FIXME: Should make sure no callers ever do this.
170106f32e7eSjoerg   if (!hasDefinition())
170206f32e7eSjoerg     return nullptr;
170306f32e7eSjoerg 
170406f32e7eSjoerg   if (data().ExternallyCompleted)
170506f32e7eSjoerg     LoadExternalDefinition();
170606f32e7eSjoerg 
170706f32e7eSjoerg   for (auto *Cat : visible_categories())
170806f32e7eSjoerg     if (Cat->getIdentifier() == CategoryId)
170906f32e7eSjoerg       return Cat;
171006f32e7eSjoerg 
171106f32e7eSjoerg   return nullptr;
171206f32e7eSjoerg }
171306f32e7eSjoerg 
171406f32e7eSjoerg ObjCMethodDecl *
getCategoryInstanceMethod(Selector Sel) const171506f32e7eSjoerg ObjCInterfaceDecl::getCategoryInstanceMethod(Selector Sel) const {
171606f32e7eSjoerg   for (const auto *Cat : visible_categories()) {
171706f32e7eSjoerg     if (ObjCCategoryImplDecl *Impl = Cat->getImplementation())
171806f32e7eSjoerg       if (ObjCMethodDecl *MD = Impl->getInstanceMethod(Sel))
171906f32e7eSjoerg         return MD;
172006f32e7eSjoerg   }
172106f32e7eSjoerg 
172206f32e7eSjoerg   return nullptr;
172306f32e7eSjoerg }
172406f32e7eSjoerg 
getCategoryClassMethod(Selector Sel) const172506f32e7eSjoerg ObjCMethodDecl *ObjCInterfaceDecl::getCategoryClassMethod(Selector Sel) const {
172606f32e7eSjoerg   for (const auto *Cat : visible_categories()) {
172706f32e7eSjoerg     if (ObjCCategoryImplDecl *Impl = Cat->getImplementation())
172806f32e7eSjoerg       if (ObjCMethodDecl *MD = Impl->getClassMethod(Sel))
172906f32e7eSjoerg         return MD;
173006f32e7eSjoerg   }
173106f32e7eSjoerg 
173206f32e7eSjoerg   return nullptr;
173306f32e7eSjoerg }
173406f32e7eSjoerg 
173506f32e7eSjoerg /// ClassImplementsProtocol - Checks that 'lProto' protocol
173606f32e7eSjoerg /// has been implemented in IDecl class, its super class or categories (if
173706f32e7eSjoerg /// lookupCategory is true).
ClassImplementsProtocol(ObjCProtocolDecl * lProto,bool lookupCategory,bool RHSIsQualifiedID)173806f32e7eSjoerg bool ObjCInterfaceDecl::ClassImplementsProtocol(ObjCProtocolDecl *lProto,
173906f32e7eSjoerg                                     bool lookupCategory,
174006f32e7eSjoerg                                     bool RHSIsQualifiedID) {
174106f32e7eSjoerg   if (!hasDefinition())
174206f32e7eSjoerg     return false;
174306f32e7eSjoerg 
174406f32e7eSjoerg   ObjCInterfaceDecl *IDecl = this;
174506f32e7eSjoerg   // 1st, look up the class.
174606f32e7eSjoerg   for (auto *PI : IDecl->protocols()){
174706f32e7eSjoerg     if (getASTContext().ProtocolCompatibleWithProtocol(lProto, PI))
174806f32e7eSjoerg       return true;
174906f32e7eSjoerg     // This is dubious and is added to be compatible with gcc.  In gcc, it is
175006f32e7eSjoerg     // also allowed assigning a protocol-qualified 'id' type to a LHS object
175106f32e7eSjoerg     // when protocol in qualified LHS is in list of protocols in the rhs 'id'
175206f32e7eSjoerg     // object. This IMO, should be a bug.
175306f32e7eSjoerg     // FIXME: Treat this as an extension, and flag this as an error when GCC
175406f32e7eSjoerg     // extensions are not enabled.
175506f32e7eSjoerg     if (RHSIsQualifiedID &&
175606f32e7eSjoerg         getASTContext().ProtocolCompatibleWithProtocol(PI, lProto))
175706f32e7eSjoerg       return true;
175806f32e7eSjoerg   }
175906f32e7eSjoerg 
176006f32e7eSjoerg   // 2nd, look up the category.
176106f32e7eSjoerg   if (lookupCategory)
176206f32e7eSjoerg     for (const auto *Cat : visible_categories()) {
176306f32e7eSjoerg       for (auto *PI : Cat->protocols())
176406f32e7eSjoerg         if (getASTContext().ProtocolCompatibleWithProtocol(lProto, PI))
176506f32e7eSjoerg           return true;
176606f32e7eSjoerg     }
176706f32e7eSjoerg 
176806f32e7eSjoerg   // 3rd, look up the super class(s)
176906f32e7eSjoerg   if (IDecl->getSuperClass())
177006f32e7eSjoerg     return
177106f32e7eSjoerg   IDecl->getSuperClass()->ClassImplementsProtocol(lProto, lookupCategory,
177206f32e7eSjoerg                                                   RHSIsQualifiedID);
177306f32e7eSjoerg 
177406f32e7eSjoerg   return false;
177506f32e7eSjoerg }
177606f32e7eSjoerg 
177706f32e7eSjoerg //===----------------------------------------------------------------------===//
177806f32e7eSjoerg // ObjCIvarDecl
177906f32e7eSjoerg //===----------------------------------------------------------------------===//
178006f32e7eSjoerg 
anchor()178106f32e7eSjoerg void ObjCIvarDecl::anchor() {}
178206f32e7eSjoerg 
Create(ASTContext & C,ObjCContainerDecl * DC,SourceLocation StartLoc,SourceLocation IdLoc,IdentifierInfo * Id,QualType T,TypeSourceInfo * TInfo,AccessControl ac,Expr * BW,bool synthesized)178306f32e7eSjoerg ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC,
178406f32e7eSjoerg                                    SourceLocation StartLoc,
178506f32e7eSjoerg                                    SourceLocation IdLoc, IdentifierInfo *Id,
178606f32e7eSjoerg                                    QualType T, TypeSourceInfo *TInfo,
178706f32e7eSjoerg                                    AccessControl ac, Expr *BW,
178806f32e7eSjoerg                                    bool synthesized) {
178906f32e7eSjoerg   if (DC) {
179006f32e7eSjoerg     // Ivar's can only appear in interfaces, implementations (via synthesized
179106f32e7eSjoerg     // properties), and class extensions (via direct declaration, or synthesized
179206f32e7eSjoerg     // properties).
179306f32e7eSjoerg     //
179406f32e7eSjoerg     // FIXME: This should really be asserting this:
179506f32e7eSjoerg     //   (isa<ObjCCategoryDecl>(DC) &&
179606f32e7eSjoerg     //    cast<ObjCCategoryDecl>(DC)->IsClassExtension()))
179706f32e7eSjoerg     // but unfortunately we sometimes place ivars into non-class extension
179806f32e7eSjoerg     // categories on error. This breaks an AST invariant, and should not be
179906f32e7eSjoerg     // fixed.
180006f32e7eSjoerg     assert((isa<ObjCInterfaceDecl>(DC) || isa<ObjCImplementationDecl>(DC) ||
180106f32e7eSjoerg             isa<ObjCCategoryDecl>(DC)) &&
180206f32e7eSjoerg            "Invalid ivar decl context!");
180306f32e7eSjoerg     // Once a new ivar is created in any of class/class-extension/implementation
180406f32e7eSjoerg     // decl contexts, the previously built IvarList must be rebuilt.
180506f32e7eSjoerg     auto *ID = dyn_cast<ObjCInterfaceDecl>(DC);
180606f32e7eSjoerg     if (!ID) {
180706f32e7eSjoerg       if (auto *IM = dyn_cast<ObjCImplementationDecl>(DC))
180806f32e7eSjoerg         ID = IM->getClassInterface();
180906f32e7eSjoerg       else
181006f32e7eSjoerg         ID = cast<ObjCCategoryDecl>(DC)->getClassInterface();
181106f32e7eSjoerg     }
181206f32e7eSjoerg     ID->setIvarList(nullptr);
181306f32e7eSjoerg   }
181406f32e7eSjoerg 
181506f32e7eSjoerg   return new (C, DC) ObjCIvarDecl(DC, StartLoc, IdLoc, Id, T, TInfo, ac, BW,
181606f32e7eSjoerg                                   synthesized);
181706f32e7eSjoerg }
181806f32e7eSjoerg 
CreateDeserialized(ASTContext & C,unsigned ID)181906f32e7eSjoerg ObjCIvarDecl *ObjCIvarDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
182006f32e7eSjoerg   return new (C, ID) ObjCIvarDecl(nullptr, SourceLocation(), SourceLocation(),
182106f32e7eSjoerg                                   nullptr, QualType(), nullptr,
182206f32e7eSjoerg                                   ObjCIvarDecl::None, nullptr, false);
182306f32e7eSjoerg }
182406f32e7eSjoerg 
getContainingInterface() const182506f32e7eSjoerg const ObjCInterfaceDecl *ObjCIvarDecl::getContainingInterface() const {
182606f32e7eSjoerg   const auto *DC = cast<ObjCContainerDecl>(getDeclContext());
182706f32e7eSjoerg 
182806f32e7eSjoerg   switch (DC->getKind()) {
182906f32e7eSjoerg   default:
183006f32e7eSjoerg   case ObjCCategoryImpl:
183106f32e7eSjoerg   case ObjCProtocol:
183206f32e7eSjoerg     llvm_unreachable("invalid ivar container!");
183306f32e7eSjoerg 
183406f32e7eSjoerg     // Ivars can only appear in class extension categories.
183506f32e7eSjoerg   case ObjCCategory: {
183606f32e7eSjoerg     const auto *CD = cast<ObjCCategoryDecl>(DC);
183706f32e7eSjoerg     assert(CD->IsClassExtension() && "invalid container for ivar!");
183806f32e7eSjoerg     return CD->getClassInterface();
183906f32e7eSjoerg   }
184006f32e7eSjoerg 
184106f32e7eSjoerg   case ObjCImplementation:
184206f32e7eSjoerg     return cast<ObjCImplementationDecl>(DC)->getClassInterface();
184306f32e7eSjoerg 
184406f32e7eSjoerg   case ObjCInterface:
184506f32e7eSjoerg     return cast<ObjCInterfaceDecl>(DC);
184606f32e7eSjoerg   }
184706f32e7eSjoerg }
184806f32e7eSjoerg 
getUsageType(QualType objectType) const184906f32e7eSjoerg QualType ObjCIvarDecl::getUsageType(QualType objectType) const {
185006f32e7eSjoerg   return getType().substObjCMemberType(objectType, getDeclContext(),
185106f32e7eSjoerg                                        ObjCSubstitutionContext::Property);
185206f32e7eSjoerg }
185306f32e7eSjoerg 
185406f32e7eSjoerg //===----------------------------------------------------------------------===//
185506f32e7eSjoerg // ObjCAtDefsFieldDecl
185606f32e7eSjoerg //===----------------------------------------------------------------------===//
185706f32e7eSjoerg 
anchor()185806f32e7eSjoerg void ObjCAtDefsFieldDecl::anchor() {}
185906f32e7eSjoerg 
186006f32e7eSjoerg ObjCAtDefsFieldDecl
Create(ASTContext & C,DeclContext * DC,SourceLocation StartLoc,SourceLocation IdLoc,IdentifierInfo * Id,QualType T,Expr * BW)186106f32e7eSjoerg *ObjCAtDefsFieldDecl::Create(ASTContext &C, DeclContext *DC,
186206f32e7eSjoerg                              SourceLocation StartLoc,  SourceLocation IdLoc,
186306f32e7eSjoerg                              IdentifierInfo *Id, QualType T, Expr *BW) {
186406f32e7eSjoerg   return new (C, DC) ObjCAtDefsFieldDecl(DC, StartLoc, IdLoc, Id, T, BW);
186506f32e7eSjoerg }
186606f32e7eSjoerg 
CreateDeserialized(ASTContext & C,unsigned ID)186706f32e7eSjoerg ObjCAtDefsFieldDecl *ObjCAtDefsFieldDecl::CreateDeserialized(ASTContext &C,
186806f32e7eSjoerg                                                              unsigned ID) {
186906f32e7eSjoerg   return new (C, ID) ObjCAtDefsFieldDecl(nullptr, SourceLocation(),
187006f32e7eSjoerg                                          SourceLocation(), nullptr, QualType(),
187106f32e7eSjoerg                                          nullptr);
187206f32e7eSjoerg }
187306f32e7eSjoerg 
187406f32e7eSjoerg //===----------------------------------------------------------------------===//
187506f32e7eSjoerg // ObjCProtocolDecl
187606f32e7eSjoerg //===----------------------------------------------------------------------===//
187706f32e7eSjoerg 
anchor()187806f32e7eSjoerg void ObjCProtocolDecl::anchor() {}
187906f32e7eSjoerg 
ObjCProtocolDecl(ASTContext & C,DeclContext * DC,IdentifierInfo * Id,SourceLocation nameLoc,SourceLocation atStartLoc,ObjCProtocolDecl * PrevDecl)188006f32e7eSjoerg ObjCProtocolDecl::ObjCProtocolDecl(ASTContext &C, DeclContext *DC,
188106f32e7eSjoerg                                    IdentifierInfo *Id, SourceLocation nameLoc,
188206f32e7eSjoerg                                    SourceLocation atStartLoc,
188306f32e7eSjoerg                                    ObjCProtocolDecl *PrevDecl)
188406f32e7eSjoerg     : ObjCContainerDecl(ObjCProtocol, DC, Id, nameLoc, atStartLoc),
188506f32e7eSjoerg       redeclarable_base(C) {
188606f32e7eSjoerg   setPreviousDecl(PrevDecl);
188706f32e7eSjoerg   if (PrevDecl)
188806f32e7eSjoerg     Data = PrevDecl->Data;
188906f32e7eSjoerg }
189006f32e7eSjoerg 
Create(ASTContext & C,DeclContext * DC,IdentifierInfo * Id,SourceLocation nameLoc,SourceLocation atStartLoc,ObjCProtocolDecl * PrevDecl)189106f32e7eSjoerg ObjCProtocolDecl *ObjCProtocolDecl::Create(ASTContext &C, DeclContext *DC,
189206f32e7eSjoerg                                            IdentifierInfo *Id,
189306f32e7eSjoerg                                            SourceLocation nameLoc,
189406f32e7eSjoerg                                            SourceLocation atStartLoc,
189506f32e7eSjoerg                                            ObjCProtocolDecl *PrevDecl) {
189606f32e7eSjoerg   auto *Result =
189706f32e7eSjoerg       new (C, DC) ObjCProtocolDecl(C, DC, Id, nameLoc, atStartLoc, PrevDecl);
189806f32e7eSjoerg   Result->Data.setInt(!C.getLangOpts().Modules);
189906f32e7eSjoerg   return Result;
190006f32e7eSjoerg }
190106f32e7eSjoerg 
CreateDeserialized(ASTContext & C,unsigned ID)190206f32e7eSjoerg ObjCProtocolDecl *ObjCProtocolDecl::CreateDeserialized(ASTContext &C,
190306f32e7eSjoerg                                                        unsigned ID) {
190406f32e7eSjoerg   ObjCProtocolDecl *Result =
190506f32e7eSjoerg       new (C, ID) ObjCProtocolDecl(C, nullptr, nullptr, SourceLocation(),
190606f32e7eSjoerg                                    SourceLocation(), nullptr);
190706f32e7eSjoerg   Result->Data.setInt(!C.getLangOpts().Modules);
190806f32e7eSjoerg   return Result;
190906f32e7eSjoerg }
191006f32e7eSjoerg 
isNonRuntimeProtocol() const1911*13fbcb42Sjoerg bool ObjCProtocolDecl::isNonRuntimeProtocol() const {
1912*13fbcb42Sjoerg   return hasAttr<ObjCNonRuntimeProtocolAttr>();
1913*13fbcb42Sjoerg }
1914*13fbcb42Sjoerg 
getImpliedProtocols(llvm::DenseSet<const ObjCProtocolDecl * > & IPs) const1915*13fbcb42Sjoerg void ObjCProtocolDecl::getImpliedProtocols(
1916*13fbcb42Sjoerg     llvm::DenseSet<const ObjCProtocolDecl *> &IPs) const {
1917*13fbcb42Sjoerg   std::queue<const ObjCProtocolDecl *> WorkQueue;
1918*13fbcb42Sjoerg   WorkQueue.push(this);
1919*13fbcb42Sjoerg 
1920*13fbcb42Sjoerg   while (!WorkQueue.empty()) {
1921*13fbcb42Sjoerg     const auto *PD = WorkQueue.front();
1922*13fbcb42Sjoerg     WorkQueue.pop();
1923*13fbcb42Sjoerg     for (const auto *Parent : PD->protocols()) {
1924*13fbcb42Sjoerg       const auto *Can = Parent->getCanonicalDecl();
1925*13fbcb42Sjoerg       auto Result = IPs.insert(Can);
1926*13fbcb42Sjoerg       if (Result.second)
1927*13fbcb42Sjoerg         WorkQueue.push(Parent);
1928*13fbcb42Sjoerg     }
1929*13fbcb42Sjoerg   }
1930*13fbcb42Sjoerg }
1931*13fbcb42Sjoerg 
lookupProtocolNamed(IdentifierInfo * Name)193206f32e7eSjoerg ObjCProtocolDecl *ObjCProtocolDecl::lookupProtocolNamed(IdentifierInfo *Name) {
193306f32e7eSjoerg   ObjCProtocolDecl *PDecl = this;
193406f32e7eSjoerg 
193506f32e7eSjoerg   if (Name == getIdentifier())
193606f32e7eSjoerg     return PDecl;
193706f32e7eSjoerg 
193806f32e7eSjoerg   for (auto *I : protocols())
193906f32e7eSjoerg     if ((PDecl = I->lookupProtocolNamed(Name)))
194006f32e7eSjoerg       return PDecl;
194106f32e7eSjoerg 
194206f32e7eSjoerg   return nullptr;
194306f32e7eSjoerg }
194406f32e7eSjoerg 
194506f32e7eSjoerg // lookupMethod - Lookup a instance/class method in the protocol and protocols
194606f32e7eSjoerg // it inherited.
lookupMethod(Selector Sel,bool isInstance) const194706f32e7eSjoerg ObjCMethodDecl *ObjCProtocolDecl::lookupMethod(Selector Sel,
194806f32e7eSjoerg                                                bool isInstance) const {
194906f32e7eSjoerg   ObjCMethodDecl *MethodDecl = nullptr;
195006f32e7eSjoerg 
195106f32e7eSjoerg   // If there is no definition or the definition is hidden, we don't find
195206f32e7eSjoerg   // anything.
195306f32e7eSjoerg   const ObjCProtocolDecl *Def = getDefinition();
1954*13fbcb42Sjoerg   if (!Def || !Def->isUnconditionallyVisible())
195506f32e7eSjoerg     return nullptr;
195606f32e7eSjoerg 
195706f32e7eSjoerg   if ((MethodDecl = getMethod(Sel, isInstance)))
195806f32e7eSjoerg     return MethodDecl;
195906f32e7eSjoerg 
196006f32e7eSjoerg   for (const auto *I : protocols())
196106f32e7eSjoerg     if ((MethodDecl = I->lookupMethod(Sel, isInstance)))
196206f32e7eSjoerg       return MethodDecl;
196306f32e7eSjoerg   return nullptr;
196406f32e7eSjoerg }
196506f32e7eSjoerg 
allocateDefinitionData()196606f32e7eSjoerg void ObjCProtocolDecl::allocateDefinitionData() {
196706f32e7eSjoerg   assert(!Data.getPointer() && "Protocol already has a definition!");
196806f32e7eSjoerg   Data.setPointer(new (getASTContext()) DefinitionData);
196906f32e7eSjoerg   Data.getPointer()->Definition = this;
197006f32e7eSjoerg }
197106f32e7eSjoerg 
startDefinition()197206f32e7eSjoerg void ObjCProtocolDecl::startDefinition() {
197306f32e7eSjoerg   allocateDefinitionData();
197406f32e7eSjoerg 
197506f32e7eSjoerg   // Update all of the declarations with a pointer to the definition.
197606f32e7eSjoerg   for (auto *RD : redecls())
197706f32e7eSjoerg     RD->Data = this->Data;
197806f32e7eSjoerg }
197906f32e7eSjoerg 
collectPropertiesToImplement(PropertyMap & PM,PropertyDeclOrder & PO) const198006f32e7eSjoerg void ObjCProtocolDecl::collectPropertiesToImplement(PropertyMap &PM,
198106f32e7eSjoerg                                                     PropertyDeclOrder &PO) const {
198206f32e7eSjoerg   if (const ObjCProtocolDecl *PDecl = getDefinition()) {
198306f32e7eSjoerg     for (auto *Prop : PDecl->properties()) {
198406f32e7eSjoerg       // Insert into PM if not there already.
198506f32e7eSjoerg       PM.insert(std::make_pair(
198606f32e7eSjoerg           std::make_pair(Prop->getIdentifier(), Prop->isClassProperty()),
198706f32e7eSjoerg           Prop));
198806f32e7eSjoerg       PO.push_back(Prop);
198906f32e7eSjoerg     }
199006f32e7eSjoerg     // Scan through protocol's protocols.
199106f32e7eSjoerg     for (const auto *PI : PDecl->protocols())
199206f32e7eSjoerg       PI->collectPropertiesToImplement(PM, PO);
199306f32e7eSjoerg   }
199406f32e7eSjoerg }
199506f32e7eSjoerg 
collectInheritedProtocolProperties(const ObjCPropertyDecl * Property,ProtocolPropertySet & PS,PropertyDeclOrder & PO) const199606f32e7eSjoerg void ObjCProtocolDecl::collectInheritedProtocolProperties(
199706f32e7eSjoerg     const ObjCPropertyDecl *Property, ProtocolPropertySet &PS,
199806f32e7eSjoerg     PropertyDeclOrder &PO) const {
199906f32e7eSjoerg   if (const ObjCProtocolDecl *PDecl = getDefinition()) {
200006f32e7eSjoerg     if (!PS.insert(PDecl).second)
200106f32e7eSjoerg       return;
200206f32e7eSjoerg     for (auto *Prop : PDecl->properties()) {
200306f32e7eSjoerg       if (Prop == Property)
200406f32e7eSjoerg         continue;
200506f32e7eSjoerg       if (Prop->getIdentifier() == Property->getIdentifier()) {
200606f32e7eSjoerg         PO.push_back(Prop);
200706f32e7eSjoerg         return;
200806f32e7eSjoerg       }
200906f32e7eSjoerg     }
201006f32e7eSjoerg     // Scan through protocol's protocols which did not have a matching property.
201106f32e7eSjoerg     for (const auto *PI : PDecl->protocols())
201206f32e7eSjoerg       PI->collectInheritedProtocolProperties(Property, PS, PO);
201306f32e7eSjoerg   }
201406f32e7eSjoerg }
201506f32e7eSjoerg 
201606f32e7eSjoerg StringRef
getObjCRuntimeNameAsString() const201706f32e7eSjoerg ObjCProtocolDecl::getObjCRuntimeNameAsString() const {
201806f32e7eSjoerg   if (const auto *ObjCRTName = getAttr<ObjCRuntimeNameAttr>())
201906f32e7eSjoerg     return ObjCRTName->getMetadataName();
202006f32e7eSjoerg 
202106f32e7eSjoerg   return getName();
202206f32e7eSjoerg }
202306f32e7eSjoerg 
202406f32e7eSjoerg //===----------------------------------------------------------------------===//
202506f32e7eSjoerg // ObjCCategoryDecl
202606f32e7eSjoerg //===----------------------------------------------------------------------===//
202706f32e7eSjoerg 
anchor()202806f32e7eSjoerg void ObjCCategoryDecl::anchor() {}
202906f32e7eSjoerg 
ObjCCategoryDecl(DeclContext * DC,SourceLocation AtLoc,SourceLocation ClassNameLoc,SourceLocation CategoryNameLoc,IdentifierInfo * Id,ObjCInterfaceDecl * IDecl,ObjCTypeParamList * typeParamList,SourceLocation IvarLBraceLoc,SourceLocation IvarRBraceLoc)203006f32e7eSjoerg ObjCCategoryDecl::ObjCCategoryDecl(DeclContext *DC, SourceLocation AtLoc,
203106f32e7eSjoerg                                    SourceLocation ClassNameLoc,
203206f32e7eSjoerg                                    SourceLocation CategoryNameLoc,
203306f32e7eSjoerg                                    IdentifierInfo *Id, ObjCInterfaceDecl *IDecl,
203406f32e7eSjoerg                                    ObjCTypeParamList *typeParamList,
203506f32e7eSjoerg                                    SourceLocation IvarLBraceLoc,
203606f32e7eSjoerg                                    SourceLocation IvarRBraceLoc)
203706f32e7eSjoerg     : ObjCContainerDecl(ObjCCategory, DC, Id, ClassNameLoc, AtLoc),
203806f32e7eSjoerg       ClassInterface(IDecl), CategoryNameLoc(CategoryNameLoc),
203906f32e7eSjoerg       IvarLBraceLoc(IvarLBraceLoc), IvarRBraceLoc(IvarRBraceLoc) {
204006f32e7eSjoerg   setTypeParamList(typeParamList);
204106f32e7eSjoerg }
204206f32e7eSjoerg 
Create(ASTContext & C,DeclContext * DC,SourceLocation AtLoc,SourceLocation ClassNameLoc,SourceLocation CategoryNameLoc,IdentifierInfo * Id,ObjCInterfaceDecl * IDecl,ObjCTypeParamList * typeParamList,SourceLocation IvarLBraceLoc,SourceLocation IvarRBraceLoc)204306f32e7eSjoerg ObjCCategoryDecl *ObjCCategoryDecl::Create(ASTContext &C, DeclContext *DC,
204406f32e7eSjoerg                                            SourceLocation AtLoc,
204506f32e7eSjoerg                                            SourceLocation ClassNameLoc,
204606f32e7eSjoerg                                            SourceLocation CategoryNameLoc,
204706f32e7eSjoerg                                            IdentifierInfo *Id,
204806f32e7eSjoerg                                            ObjCInterfaceDecl *IDecl,
204906f32e7eSjoerg                                            ObjCTypeParamList *typeParamList,
205006f32e7eSjoerg                                            SourceLocation IvarLBraceLoc,
205106f32e7eSjoerg                                            SourceLocation IvarRBraceLoc) {
205206f32e7eSjoerg   auto *CatDecl =
205306f32e7eSjoerg       new (C, DC) ObjCCategoryDecl(DC, AtLoc, ClassNameLoc, CategoryNameLoc, Id,
205406f32e7eSjoerg                                    IDecl, typeParamList, IvarLBraceLoc,
205506f32e7eSjoerg                                    IvarRBraceLoc);
205606f32e7eSjoerg   if (IDecl) {
205706f32e7eSjoerg     // Link this category into its class's category list.
205806f32e7eSjoerg     CatDecl->NextClassCategory = IDecl->getCategoryListRaw();
205906f32e7eSjoerg     if (IDecl->hasDefinition()) {
206006f32e7eSjoerg       IDecl->setCategoryListRaw(CatDecl);
206106f32e7eSjoerg       if (ASTMutationListener *L = C.getASTMutationListener())
206206f32e7eSjoerg         L->AddedObjCCategoryToInterface(CatDecl, IDecl);
206306f32e7eSjoerg     }
206406f32e7eSjoerg   }
206506f32e7eSjoerg 
206606f32e7eSjoerg   return CatDecl;
206706f32e7eSjoerg }
206806f32e7eSjoerg 
CreateDeserialized(ASTContext & C,unsigned ID)206906f32e7eSjoerg ObjCCategoryDecl *ObjCCategoryDecl::CreateDeserialized(ASTContext &C,
207006f32e7eSjoerg                                                        unsigned ID) {
207106f32e7eSjoerg   return new (C, ID) ObjCCategoryDecl(nullptr, SourceLocation(),
207206f32e7eSjoerg                                       SourceLocation(), SourceLocation(),
207306f32e7eSjoerg                                       nullptr, nullptr, nullptr);
207406f32e7eSjoerg }
207506f32e7eSjoerg 
getImplementation() const207606f32e7eSjoerg ObjCCategoryImplDecl *ObjCCategoryDecl::getImplementation() const {
207706f32e7eSjoerg   return getASTContext().getObjCImplementation(
207806f32e7eSjoerg                                            const_cast<ObjCCategoryDecl*>(this));
207906f32e7eSjoerg }
208006f32e7eSjoerg 
setImplementation(ObjCCategoryImplDecl * ImplD)208106f32e7eSjoerg void ObjCCategoryDecl::setImplementation(ObjCCategoryImplDecl *ImplD) {
208206f32e7eSjoerg   getASTContext().setObjCImplementation(this, ImplD);
208306f32e7eSjoerg }
208406f32e7eSjoerg 
setTypeParamList(ObjCTypeParamList * TPL)208506f32e7eSjoerg void ObjCCategoryDecl::setTypeParamList(ObjCTypeParamList *TPL) {
208606f32e7eSjoerg   TypeParamList = TPL;
208706f32e7eSjoerg   if (!TPL)
208806f32e7eSjoerg     return;
208906f32e7eSjoerg   // Set the declaration context of each of the type parameters.
209006f32e7eSjoerg   for (auto *typeParam : *TypeParamList)
209106f32e7eSjoerg     typeParam->setDeclContext(this);
209206f32e7eSjoerg }
209306f32e7eSjoerg 
209406f32e7eSjoerg //===----------------------------------------------------------------------===//
209506f32e7eSjoerg // ObjCCategoryImplDecl
209606f32e7eSjoerg //===----------------------------------------------------------------------===//
209706f32e7eSjoerg 
anchor()209806f32e7eSjoerg void ObjCCategoryImplDecl::anchor() {}
209906f32e7eSjoerg 
210006f32e7eSjoerg ObjCCategoryImplDecl *
Create(ASTContext & C,DeclContext * DC,IdentifierInfo * Id,ObjCInterfaceDecl * ClassInterface,SourceLocation nameLoc,SourceLocation atStartLoc,SourceLocation CategoryNameLoc)210106f32e7eSjoerg ObjCCategoryImplDecl::Create(ASTContext &C, DeclContext *DC,
210206f32e7eSjoerg                              IdentifierInfo *Id,
210306f32e7eSjoerg                              ObjCInterfaceDecl *ClassInterface,
210406f32e7eSjoerg                              SourceLocation nameLoc,
210506f32e7eSjoerg                              SourceLocation atStartLoc,
210606f32e7eSjoerg                              SourceLocation CategoryNameLoc) {
210706f32e7eSjoerg   if (ClassInterface && ClassInterface->hasDefinition())
210806f32e7eSjoerg     ClassInterface = ClassInterface->getDefinition();
210906f32e7eSjoerg   return new (C, DC) ObjCCategoryImplDecl(DC, Id, ClassInterface, nameLoc,
211006f32e7eSjoerg                                           atStartLoc, CategoryNameLoc);
211106f32e7eSjoerg }
211206f32e7eSjoerg 
CreateDeserialized(ASTContext & C,unsigned ID)211306f32e7eSjoerg ObjCCategoryImplDecl *ObjCCategoryImplDecl::CreateDeserialized(ASTContext &C,
211406f32e7eSjoerg                                                                unsigned ID) {
211506f32e7eSjoerg   return new (C, ID) ObjCCategoryImplDecl(nullptr, nullptr, nullptr,
211606f32e7eSjoerg                                           SourceLocation(), SourceLocation(),
211706f32e7eSjoerg                                           SourceLocation());
211806f32e7eSjoerg }
211906f32e7eSjoerg 
getCategoryDecl() const212006f32e7eSjoerg ObjCCategoryDecl *ObjCCategoryImplDecl::getCategoryDecl() const {
212106f32e7eSjoerg   // The class interface might be NULL if we are working with invalid code.
212206f32e7eSjoerg   if (const ObjCInterfaceDecl *ID = getClassInterface())
212306f32e7eSjoerg     return ID->FindCategoryDeclaration(getIdentifier());
212406f32e7eSjoerg   return nullptr;
212506f32e7eSjoerg }
212606f32e7eSjoerg 
anchor()212706f32e7eSjoerg void ObjCImplDecl::anchor() {}
212806f32e7eSjoerg 
addPropertyImplementation(ObjCPropertyImplDecl * property)212906f32e7eSjoerg void ObjCImplDecl::addPropertyImplementation(ObjCPropertyImplDecl *property) {
213006f32e7eSjoerg   // FIXME: The context should be correct before we get here.
213106f32e7eSjoerg   property->setLexicalDeclContext(this);
213206f32e7eSjoerg   addDecl(property);
213306f32e7eSjoerg }
213406f32e7eSjoerg 
setClassInterface(ObjCInterfaceDecl * IFace)213506f32e7eSjoerg void ObjCImplDecl::setClassInterface(ObjCInterfaceDecl *IFace) {
213606f32e7eSjoerg   ASTContext &Ctx = getASTContext();
213706f32e7eSjoerg 
213806f32e7eSjoerg   if (auto *ImplD = dyn_cast_or_null<ObjCImplementationDecl>(this)) {
213906f32e7eSjoerg     if (IFace)
214006f32e7eSjoerg       Ctx.setObjCImplementation(IFace, ImplD);
214106f32e7eSjoerg 
214206f32e7eSjoerg   } else if (auto *ImplD = dyn_cast_or_null<ObjCCategoryImplDecl>(this)) {
214306f32e7eSjoerg     if (ObjCCategoryDecl *CD = IFace->FindCategoryDeclaration(getIdentifier()))
214406f32e7eSjoerg       Ctx.setObjCImplementation(CD, ImplD);
214506f32e7eSjoerg   }
214606f32e7eSjoerg 
214706f32e7eSjoerg   ClassInterface = IFace;
214806f32e7eSjoerg }
214906f32e7eSjoerg 
215006f32e7eSjoerg /// FindPropertyImplIvarDecl - This method lookup the ivar in the list of
215106f32e7eSjoerg /// properties implemented in this \@implementation block and returns
215206f32e7eSjoerg /// the implemented property that uses it.
215306f32e7eSjoerg ObjCPropertyImplDecl *ObjCImplDecl::
FindPropertyImplIvarDecl(IdentifierInfo * ivarId) const215406f32e7eSjoerg FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const {
215506f32e7eSjoerg   for (auto *PID : property_impls())
215606f32e7eSjoerg     if (PID->getPropertyIvarDecl() &&
215706f32e7eSjoerg         PID->getPropertyIvarDecl()->getIdentifier() == ivarId)
215806f32e7eSjoerg       return PID;
215906f32e7eSjoerg   return nullptr;
216006f32e7eSjoerg }
216106f32e7eSjoerg 
216206f32e7eSjoerg /// FindPropertyImplDecl - This method looks up a previous ObjCPropertyImplDecl
216306f32e7eSjoerg /// added to the list of those properties \@synthesized/\@dynamic in this
216406f32e7eSjoerg /// category \@implementation block.
216506f32e7eSjoerg ObjCPropertyImplDecl *ObjCImplDecl::
FindPropertyImplDecl(IdentifierInfo * Id,ObjCPropertyQueryKind QueryKind) const216606f32e7eSjoerg FindPropertyImplDecl(IdentifierInfo *Id,
216706f32e7eSjoerg                      ObjCPropertyQueryKind QueryKind) const {
216806f32e7eSjoerg   ObjCPropertyImplDecl *ClassPropImpl = nullptr;
216906f32e7eSjoerg   for (auto *PID : property_impls())
217006f32e7eSjoerg     // If queryKind is unknown, we return the instance property if one
217106f32e7eSjoerg     // exists; otherwise we return the class property.
217206f32e7eSjoerg     if (PID->getPropertyDecl()->getIdentifier() == Id) {
217306f32e7eSjoerg       if ((QueryKind == ObjCPropertyQueryKind::OBJC_PR_query_unknown &&
217406f32e7eSjoerg            !PID->getPropertyDecl()->isClassProperty()) ||
217506f32e7eSjoerg           (QueryKind == ObjCPropertyQueryKind::OBJC_PR_query_class &&
217606f32e7eSjoerg            PID->getPropertyDecl()->isClassProperty()) ||
217706f32e7eSjoerg           (QueryKind == ObjCPropertyQueryKind::OBJC_PR_query_instance &&
217806f32e7eSjoerg            !PID->getPropertyDecl()->isClassProperty()))
217906f32e7eSjoerg         return PID;
218006f32e7eSjoerg 
218106f32e7eSjoerg       if (PID->getPropertyDecl()->isClassProperty())
218206f32e7eSjoerg         ClassPropImpl = PID;
218306f32e7eSjoerg     }
218406f32e7eSjoerg 
218506f32e7eSjoerg   if (QueryKind == ObjCPropertyQueryKind::OBJC_PR_query_unknown)
218606f32e7eSjoerg     // We can't find the instance property, return the class property.
218706f32e7eSjoerg     return ClassPropImpl;
218806f32e7eSjoerg 
218906f32e7eSjoerg   return nullptr;
219006f32e7eSjoerg }
219106f32e7eSjoerg 
operator <<(raw_ostream & OS,const ObjCCategoryImplDecl & CID)219206f32e7eSjoerg raw_ostream &clang::operator<<(raw_ostream &OS,
219306f32e7eSjoerg                                const ObjCCategoryImplDecl &CID) {
219406f32e7eSjoerg   OS << CID.getName();
219506f32e7eSjoerg   return OS;
219606f32e7eSjoerg }
219706f32e7eSjoerg 
219806f32e7eSjoerg //===----------------------------------------------------------------------===//
219906f32e7eSjoerg // ObjCImplementationDecl
220006f32e7eSjoerg //===----------------------------------------------------------------------===//
220106f32e7eSjoerg 
anchor()220206f32e7eSjoerg void ObjCImplementationDecl::anchor() {}
220306f32e7eSjoerg 
220406f32e7eSjoerg ObjCImplementationDecl *
Create(ASTContext & C,DeclContext * DC,ObjCInterfaceDecl * ClassInterface,ObjCInterfaceDecl * SuperDecl,SourceLocation nameLoc,SourceLocation atStartLoc,SourceLocation superLoc,SourceLocation IvarLBraceLoc,SourceLocation IvarRBraceLoc)220506f32e7eSjoerg ObjCImplementationDecl::Create(ASTContext &C, DeclContext *DC,
220606f32e7eSjoerg                                ObjCInterfaceDecl *ClassInterface,
220706f32e7eSjoerg                                ObjCInterfaceDecl *SuperDecl,
220806f32e7eSjoerg                                SourceLocation nameLoc,
220906f32e7eSjoerg                                SourceLocation atStartLoc,
221006f32e7eSjoerg                                SourceLocation superLoc,
221106f32e7eSjoerg                                SourceLocation IvarLBraceLoc,
221206f32e7eSjoerg                                SourceLocation IvarRBraceLoc) {
221306f32e7eSjoerg   if (ClassInterface && ClassInterface->hasDefinition())
221406f32e7eSjoerg     ClassInterface = ClassInterface->getDefinition();
221506f32e7eSjoerg   return new (C, DC) ObjCImplementationDecl(DC, ClassInterface, SuperDecl,
221606f32e7eSjoerg                                             nameLoc, atStartLoc, superLoc,
221706f32e7eSjoerg                                             IvarLBraceLoc, IvarRBraceLoc);
221806f32e7eSjoerg }
221906f32e7eSjoerg 
222006f32e7eSjoerg ObjCImplementationDecl *
CreateDeserialized(ASTContext & C,unsigned ID)222106f32e7eSjoerg ObjCImplementationDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
222206f32e7eSjoerg   return new (C, ID) ObjCImplementationDecl(nullptr, nullptr, nullptr,
222306f32e7eSjoerg                                             SourceLocation(), SourceLocation());
222406f32e7eSjoerg }
222506f32e7eSjoerg 
setIvarInitializers(ASTContext & C,CXXCtorInitializer ** initializers,unsigned numInitializers)222606f32e7eSjoerg void ObjCImplementationDecl::setIvarInitializers(ASTContext &C,
222706f32e7eSjoerg                                              CXXCtorInitializer ** initializers,
222806f32e7eSjoerg                                                  unsigned numInitializers) {
222906f32e7eSjoerg   if (numInitializers > 0) {
223006f32e7eSjoerg     NumIvarInitializers = numInitializers;
223106f32e7eSjoerg     auto **ivarInitializers = new (C) CXXCtorInitializer*[NumIvarInitializers];
223206f32e7eSjoerg     memcpy(ivarInitializers, initializers,
223306f32e7eSjoerg            numInitializers * sizeof(CXXCtorInitializer*));
223406f32e7eSjoerg     IvarInitializers = ivarInitializers;
223506f32e7eSjoerg   }
223606f32e7eSjoerg }
223706f32e7eSjoerg 
223806f32e7eSjoerg ObjCImplementationDecl::init_const_iterator
init_begin() const223906f32e7eSjoerg ObjCImplementationDecl::init_begin() const {
224006f32e7eSjoerg   return IvarInitializers.get(getASTContext().getExternalSource());
224106f32e7eSjoerg }
224206f32e7eSjoerg 
operator <<(raw_ostream & OS,const ObjCImplementationDecl & ID)224306f32e7eSjoerg raw_ostream &clang::operator<<(raw_ostream &OS,
224406f32e7eSjoerg                                const ObjCImplementationDecl &ID) {
224506f32e7eSjoerg   OS << ID.getName();
224606f32e7eSjoerg   return OS;
224706f32e7eSjoerg }
224806f32e7eSjoerg 
224906f32e7eSjoerg //===----------------------------------------------------------------------===//
225006f32e7eSjoerg // ObjCCompatibleAliasDecl
225106f32e7eSjoerg //===----------------------------------------------------------------------===//
225206f32e7eSjoerg 
anchor()225306f32e7eSjoerg void ObjCCompatibleAliasDecl::anchor() {}
225406f32e7eSjoerg 
225506f32e7eSjoerg ObjCCompatibleAliasDecl *
Create(ASTContext & C,DeclContext * DC,SourceLocation L,IdentifierInfo * Id,ObjCInterfaceDecl * AliasedClass)225606f32e7eSjoerg ObjCCompatibleAliasDecl::Create(ASTContext &C, DeclContext *DC,
225706f32e7eSjoerg                                 SourceLocation L,
225806f32e7eSjoerg                                 IdentifierInfo *Id,
225906f32e7eSjoerg                                 ObjCInterfaceDecl* AliasedClass) {
226006f32e7eSjoerg   return new (C, DC) ObjCCompatibleAliasDecl(DC, L, Id, AliasedClass);
226106f32e7eSjoerg }
226206f32e7eSjoerg 
226306f32e7eSjoerg ObjCCompatibleAliasDecl *
CreateDeserialized(ASTContext & C,unsigned ID)226406f32e7eSjoerg ObjCCompatibleAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
226506f32e7eSjoerg   return new (C, ID) ObjCCompatibleAliasDecl(nullptr, SourceLocation(),
226606f32e7eSjoerg                                              nullptr, nullptr);
226706f32e7eSjoerg }
226806f32e7eSjoerg 
226906f32e7eSjoerg //===----------------------------------------------------------------------===//
227006f32e7eSjoerg // ObjCPropertyDecl
227106f32e7eSjoerg //===----------------------------------------------------------------------===//
227206f32e7eSjoerg 
anchor()227306f32e7eSjoerg void ObjCPropertyDecl::anchor() {}
227406f32e7eSjoerg 
Create(ASTContext & C,DeclContext * DC,SourceLocation L,IdentifierInfo * Id,SourceLocation AtLoc,SourceLocation LParenLoc,QualType T,TypeSourceInfo * TSI,PropertyControl propControl)227506f32e7eSjoerg ObjCPropertyDecl *ObjCPropertyDecl::Create(ASTContext &C, DeclContext *DC,
227606f32e7eSjoerg                                            SourceLocation L,
227706f32e7eSjoerg                                            IdentifierInfo *Id,
227806f32e7eSjoerg                                            SourceLocation AtLoc,
227906f32e7eSjoerg                                            SourceLocation LParenLoc,
228006f32e7eSjoerg                                            QualType T,
228106f32e7eSjoerg                                            TypeSourceInfo *TSI,
228206f32e7eSjoerg                                            PropertyControl propControl) {
228306f32e7eSjoerg   return new (C, DC) ObjCPropertyDecl(DC, L, Id, AtLoc, LParenLoc, T, TSI,
228406f32e7eSjoerg                                       propControl);
228506f32e7eSjoerg }
228606f32e7eSjoerg 
CreateDeserialized(ASTContext & C,unsigned ID)228706f32e7eSjoerg ObjCPropertyDecl *ObjCPropertyDecl::CreateDeserialized(ASTContext &C,
228806f32e7eSjoerg                                                        unsigned ID) {
228906f32e7eSjoerg   return new (C, ID) ObjCPropertyDecl(nullptr, SourceLocation(), nullptr,
229006f32e7eSjoerg                                       SourceLocation(), SourceLocation(),
229106f32e7eSjoerg                                       QualType(), nullptr, None);
229206f32e7eSjoerg }
229306f32e7eSjoerg 
getUsageType(QualType objectType) const229406f32e7eSjoerg QualType ObjCPropertyDecl::getUsageType(QualType objectType) const {
229506f32e7eSjoerg   return DeclType.substObjCMemberType(objectType, getDeclContext(),
229606f32e7eSjoerg                                       ObjCSubstitutionContext::Property);
229706f32e7eSjoerg }
229806f32e7eSjoerg 
isDirectProperty() const2299*13fbcb42Sjoerg bool ObjCPropertyDecl::isDirectProperty() const {
2300*13fbcb42Sjoerg   return (PropertyAttributes & ObjCPropertyAttribute::kind_direct) &&
2301*13fbcb42Sjoerg          !getASTContext().getLangOpts().ObjCDisableDirectMethodsForTesting;
2302*13fbcb42Sjoerg }
2303*13fbcb42Sjoerg 
230406f32e7eSjoerg //===----------------------------------------------------------------------===//
230506f32e7eSjoerg // ObjCPropertyImplDecl
230606f32e7eSjoerg //===----------------------------------------------------------------------===//
230706f32e7eSjoerg 
Create(ASTContext & C,DeclContext * DC,SourceLocation atLoc,SourceLocation L,ObjCPropertyDecl * property,Kind PK,ObjCIvarDecl * ivar,SourceLocation ivarLoc)230806f32e7eSjoerg ObjCPropertyImplDecl *ObjCPropertyImplDecl::Create(ASTContext &C,
230906f32e7eSjoerg                                                    DeclContext *DC,
231006f32e7eSjoerg                                                    SourceLocation atLoc,
231106f32e7eSjoerg                                                    SourceLocation L,
231206f32e7eSjoerg                                                    ObjCPropertyDecl *property,
231306f32e7eSjoerg                                                    Kind PK,
231406f32e7eSjoerg                                                    ObjCIvarDecl *ivar,
231506f32e7eSjoerg                                                    SourceLocation ivarLoc) {
231606f32e7eSjoerg   return new (C, DC) ObjCPropertyImplDecl(DC, atLoc, L, property, PK, ivar,
231706f32e7eSjoerg                                           ivarLoc);
231806f32e7eSjoerg }
231906f32e7eSjoerg 
CreateDeserialized(ASTContext & C,unsigned ID)232006f32e7eSjoerg ObjCPropertyImplDecl *ObjCPropertyImplDecl::CreateDeserialized(ASTContext &C,
232106f32e7eSjoerg                                                                unsigned ID) {
232206f32e7eSjoerg   return new (C, ID) ObjCPropertyImplDecl(nullptr, SourceLocation(),
232306f32e7eSjoerg                                           SourceLocation(), nullptr, Dynamic,
232406f32e7eSjoerg                                           nullptr, SourceLocation());
232506f32e7eSjoerg }
232606f32e7eSjoerg 
getSourceRange() const232706f32e7eSjoerg SourceRange ObjCPropertyImplDecl::getSourceRange() const {
232806f32e7eSjoerg   SourceLocation EndLoc = getLocation();
232906f32e7eSjoerg   if (IvarLoc.isValid())
233006f32e7eSjoerg     EndLoc = IvarLoc;
233106f32e7eSjoerg 
233206f32e7eSjoerg   return SourceRange(AtLoc, EndLoc);
233306f32e7eSjoerg }
2334