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