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