10b57cec5SDimitry Andric //===- DeclObjC.cpp - ObjC Declaration AST Node Implementation ------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements the Objective-C related Decl classes. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "clang/AST/DeclObjC.h" 140b57cec5SDimitry Andric #include "clang/AST/ASTContext.h" 150b57cec5SDimitry Andric #include "clang/AST/ASTMutationListener.h" 160b57cec5SDimitry Andric #include "clang/AST/Attr.h" 170b57cec5SDimitry Andric #include "clang/AST/Decl.h" 180b57cec5SDimitry Andric #include "clang/AST/DeclBase.h" 190b57cec5SDimitry Andric #include "clang/AST/Stmt.h" 200b57cec5SDimitry Andric #include "clang/AST/Type.h" 210b57cec5SDimitry Andric #include "clang/AST/TypeLoc.h" 220b57cec5SDimitry Andric #include "clang/Basic/IdentifierTable.h" 230b57cec5SDimitry Andric #include "clang/Basic/LLVM.h" 240b57cec5SDimitry Andric #include "clang/Basic/LangOptions.h" 250b57cec5SDimitry Andric #include "clang/Basic/SourceLocation.h" 260b57cec5SDimitry Andric #include "llvm/ADT/None.h" 270b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h" 280b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 290b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 300b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 310b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 320b57cec5SDimitry Andric #include <algorithm> 330b57cec5SDimitry Andric #include <cassert> 340b57cec5SDimitry Andric #include <cstdint> 350b57cec5SDimitry Andric #include <cstring> 36e8d8bef9SDimitry Andric #include <queue> 370b57cec5SDimitry Andric #include <utility> 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric using namespace clang; 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 420b57cec5SDimitry Andric // ObjCListBase 430b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric void ObjCListBase::set(void *const* InList, unsigned Elts, ASTContext &Ctx) { 460b57cec5SDimitry Andric List = nullptr; 470b57cec5SDimitry Andric if (Elts == 0) return; // Setting to an empty list is a noop. 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric List = new (Ctx) void*[Elts]; 500b57cec5SDimitry Andric NumElts = Elts; 510b57cec5SDimitry Andric memcpy(List, InList, sizeof(void*)*Elts); 520b57cec5SDimitry Andric } 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric void ObjCProtocolList::set(ObjCProtocolDecl* const* InList, unsigned Elts, 550b57cec5SDimitry Andric const SourceLocation *Locs, ASTContext &Ctx) { 560b57cec5SDimitry Andric if (Elts == 0) 570b57cec5SDimitry Andric return; 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric Locations = new (Ctx) SourceLocation[Elts]; 600b57cec5SDimitry Andric memcpy(Locations, Locs, sizeof(SourceLocation) * Elts); 610b57cec5SDimitry Andric set(InList, Elts, Ctx); 620b57cec5SDimitry Andric } 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 650b57cec5SDimitry Andric // ObjCInterfaceDecl 660b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric ObjCContainerDecl::ObjCContainerDecl(Kind DK, DeclContext *DC, 690b57cec5SDimitry Andric IdentifierInfo *Id, SourceLocation nameLoc, 700b57cec5SDimitry Andric SourceLocation atStartLoc) 710b57cec5SDimitry Andric : NamedDecl(DK, DC, nameLoc, Id), DeclContext(DK) { 720b57cec5SDimitry Andric setAtStartLoc(atStartLoc); 730b57cec5SDimitry Andric } 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric void ObjCContainerDecl::anchor() {} 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric /// getIvarDecl - This method looks up an ivar in this ContextDecl. 780b57cec5SDimitry Andric /// 790b57cec5SDimitry Andric ObjCIvarDecl * 800b57cec5SDimitry Andric ObjCContainerDecl::getIvarDecl(IdentifierInfo *Id) const { 810b57cec5SDimitry Andric lookup_result R = lookup(Id); 820b57cec5SDimitry Andric for (lookup_iterator Ivar = R.begin(), IvarEnd = R.end(); 830b57cec5SDimitry Andric Ivar != IvarEnd; ++Ivar) { 840b57cec5SDimitry Andric if (auto *ivar = dyn_cast<ObjCIvarDecl>(*Ivar)) 850b57cec5SDimitry Andric return ivar; 860b57cec5SDimitry Andric } 870b57cec5SDimitry Andric return nullptr; 880b57cec5SDimitry Andric } 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric // Get the local instance/class method declared in this interface. 910b57cec5SDimitry Andric ObjCMethodDecl * 920b57cec5SDimitry Andric ObjCContainerDecl::getMethod(Selector Sel, bool isInstance, 930b57cec5SDimitry Andric bool AllowHidden) const { 940b57cec5SDimitry Andric // If this context is a hidden protocol definition, don't find any 950b57cec5SDimitry Andric // methods there. 960b57cec5SDimitry Andric if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(this)) { 970b57cec5SDimitry Andric if (const ObjCProtocolDecl *Def = Proto->getDefinition()) 985ffd83dbSDimitry Andric if (!Def->isUnconditionallyVisible() && !AllowHidden) 990b57cec5SDimitry Andric return nullptr; 1000b57cec5SDimitry Andric } 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric // Since instance & class methods can have the same name, the loop below 1030b57cec5SDimitry Andric // ensures we get the correct method. 1040b57cec5SDimitry Andric // 1050b57cec5SDimitry Andric // @interface Whatever 1060b57cec5SDimitry Andric // - (int) class_method; 1070b57cec5SDimitry Andric // + (float) class_method; 1080b57cec5SDimitry Andric // @end 1090b57cec5SDimitry Andric lookup_result R = lookup(Sel); 1100b57cec5SDimitry Andric for (lookup_iterator Meth = R.begin(), MethEnd = R.end(); 1110b57cec5SDimitry Andric Meth != MethEnd; ++Meth) { 1120b57cec5SDimitry Andric auto *MD = dyn_cast<ObjCMethodDecl>(*Meth); 1130b57cec5SDimitry Andric if (MD && MD->isInstanceMethod() == isInstance) 1140b57cec5SDimitry Andric return MD; 1150b57cec5SDimitry Andric } 1160b57cec5SDimitry Andric return nullptr; 1170b57cec5SDimitry Andric } 1180b57cec5SDimitry Andric 1190b57cec5SDimitry Andric /// This routine returns 'true' if a user declared setter method was 1200b57cec5SDimitry Andric /// found in the class, its protocols, its super classes or categories. 1210b57cec5SDimitry Andric /// It also returns 'true' if one of its categories has declared a 'readwrite' 1220b57cec5SDimitry Andric /// property. This is because, user must provide a setter method for the 1230b57cec5SDimitry Andric /// category's 'readwrite' property. 1240b57cec5SDimitry Andric bool ObjCContainerDecl::HasUserDeclaredSetterMethod( 1250b57cec5SDimitry Andric const ObjCPropertyDecl *Property) const { 1260b57cec5SDimitry Andric Selector Sel = Property->getSetterName(); 1270b57cec5SDimitry Andric lookup_result R = lookup(Sel); 1280b57cec5SDimitry Andric for (lookup_iterator Meth = R.begin(), MethEnd = R.end(); 1290b57cec5SDimitry Andric Meth != MethEnd; ++Meth) { 1300b57cec5SDimitry Andric auto *MD = dyn_cast<ObjCMethodDecl>(*Meth); 1310b57cec5SDimitry Andric if (MD && MD->isInstanceMethod() && !MD->isImplicit()) 1320b57cec5SDimitry Andric return true; 1330b57cec5SDimitry Andric } 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(this)) { 1360b57cec5SDimitry Andric // Also look into categories, including class extensions, looking 1370b57cec5SDimitry Andric // for a user declared instance method. 1380b57cec5SDimitry Andric for (const auto *Cat : ID->visible_categories()) { 1390b57cec5SDimitry Andric if (ObjCMethodDecl *MD = Cat->getInstanceMethod(Sel)) 1400b57cec5SDimitry Andric if (!MD->isImplicit()) 1410b57cec5SDimitry Andric return true; 1420b57cec5SDimitry Andric if (Cat->IsClassExtension()) 1430b57cec5SDimitry Andric continue; 1440b57cec5SDimitry Andric // Also search through the categories looking for a 'readwrite' 1450b57cec5SDimitry Andric // declaration of this property. If one found, presumably a setter will 1460b57cec5SDimitry Andric // be provided (properties declared in categories will not get 1470b57cec5SDimitry Andric // auto-synthesized). 1480b57cec5SDimitry Andric for (const auto *P : Cat->properties()) 1490b57cec5SDimitry Andric if (P->getIdentifier() == Property->getIdentifier()) { 1505ffd83dbSDimitry Andric if (P->getPropertyAttributes() & 1515ffd83dbSDimitry Andric ObjCPropertyAttribute::kind_readwrite) 1520b57cec5SDimitry Andric return true; 1530b57cec5SDimitry Andric break; 1540b57cec5SDimitry Andric } 1550b57cec5SDimitry Andric } 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andric // Also look into protocols, for a user declared instance method. 1580b57cec5SDimitry Andric for (const auto *Proto : ID->all_referenced_protocols()) 1590b57cec5SDimitry Andric if (Proto->HasUserDeclaredSetterMethod(Property)) 1600b57cec5SDimitry Andric return true; 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric // And in its super class. 1630b57cec5SDimitry Andric ObjCInterfaceDecl *OSC = ID->getSuperClass(); 1640b57cec5SDimitry Andric while (OSC) { 1650b57cec5SDimitry Andric if (OSC->HasUserDeclaredSetterMethod(Property)) 1660b57cec5SDimitry Andric return true; 1670b57cec5SDimitry Andric OSC = OSC->getSuperClass(); 1680b57cec5SDimitry Andric } 1690b57cec5SDimitry Andric } 1700b57cec5SDimitry Andric if (const auto *PD = dyn_cast<ObjCProtocolDecl>(this)) 1710b57cec5SDimitry Andric for (const auto *PI : PD->protocols()) 1720b57cec5SDimitry Andric if (PI->HasUserDeclaredSetterMethod(Property)) 1730b57cec5SDimitry Andric return true; 1740b57cec5SDimitry Andric return false; 1750b57cec5SDimitry Andric } 1760b57cec5SDimitry Andric 1770b57cec5SDimitry Andric ObjCPropertyDecl * 1780b57cec5SDimitry Andric ObjCPropertyDecl::findPropertyDecl(const DeclContext *DC, 1790b57cec5SDimitry Andric const IdentifierInfo *propertyID, 1800b57cec5SDimitry Andric ObjCPropertyQueryKind queryKind) { 1810b57cec5SDimitry Andric // If this context is a hidden protocol definition, don't find any 1820b57cec5SDimitry Andric // property. 1830b57cec5SDimitry Andric if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(DC)) { 1840b57cec5SDimitry Andric if (const ObjCProtocolDecl *Def = Proto->getDefinition()) 1855ffd83dbSDimitry Andric if (!Def->isUnconditionallyVisible()) 1860b57cec5SDimitry Andric return nullptr; 1870b57cec5SDimitry Andric } 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andric // If context is class, then lookup property in its visible extensions. 1900b57cec5SDimitry Andric // This comes before property is looked up in primary class. 1910b57cec5SDimitry Andric if (auto *IDecl = dyn_cast<ObjCInterfaceDecl>(DC)) { 1920b57cec5SDimitry Andric for (const auto *Ext : IDecl->visible_extensions()) 1930b57cec5SDimitry Andric if (ObjCPropertyDecl *PD = ObjCPropertyDecl::findPropertyDecl(Ext, 1940b57cec5SDimitry Andric propertyID, 1950b57cec5SDimitry Andric queryKind)) 1960b57cec5SDimitry Andric return PD; 1970b57cec5SDimitry Andric } 1980b57cec5SDimitry Andric 1990b57cec5SDimitry Andric DeclContext::lookup_result R = DC->lookup(propertyID); 2000b57cec5SDimitry Andric ObjCPropertyDecl *classProp = nullptr; 2010b57cec5SDimitry Andric for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; 2020b57cec5SDimitry Andric ++I) 2030b57cec5SDimitry Andric if (auto *PD = dyn_cast<ObjCPropertyDecl>(*I)) { 2040b57cec5SDimitry Andric // If queryKind is unknown, we return the instance property if one 2050b57cec5SDimitry Andric // exists; otherwise we return the class property. 2060b57cec5SDimitry Andric if ((queryKind == ObjCPropertyQueryKind::OBJC_PR_query_unknown && 2070b57cec5SDimitry Andric !PD->isClassProperty()) || 2080b57cec5SDimitry Andric (queryKind == ObjCPropertyQueryKind::OBJC_PR_query_class && 2090b57cec5SDimitry Andric PD->isClassProperty()) || 2100b57cec5SDimitry Andric (queryKind == ObjCPropertyQueryKind::OBJC_PR_query_instance && 2110b57cec5SDimitry Andric !PD->isClassProperty())) 2120b57cec5SDimitry Andric return PD; 2130b57cec5SDimitry Andric 2140b57cec5SDimitry Andric if (PD->isClassProperty()) 2150b57cec5SDimitry Andric classProp = PD; 2160b57cec5SDimitry Andric } 2170b57cec5SDimitry Andric 2180b57cec5SDimitry Andric if (queryKind == ObjCPropertyQueryKind::OBJC_PR_query_unknown) 2190b57cec5SDimitry Andric // We can't find the instance property, return the class property. 2200b57cec5SDimitry Andric return classProp; 2210b57cec5SDimitry Andric 2220b57cec5SDimitry Andric return nullptr; 2230b57cec5SDimitry Andric } 2240b57cec5SDimitry Andric 2250b57cec5SDimitry Andric IdentifierInfo * 2260b57cec5SDimitry Andric ObjCPropertyDecl::getDefaultSynthIvarName(ASTContext &Ctx) const { 2270b57cec5SDimitry Andric SmallString<128> ivarName; 2280b57cec5SDimitry Andric { 2290b57cec5SDimitry Andric llvm::raw_svector_ostream os(ivarName); 2300b57cec5SDimitry Andric os << '_' << getIdentifier()->getName(); 2310b57cec5SDimitry Andric } 2320b57cec5SDimitry Andric return &Ctx.Idents.get(ivarName.str()); 2330b57cec5SDimitry Andric } 2340b57cec5SDimitry Andric 2350b57cec5SDimitry Andric /// FindPropertyDeclaration - Finds declaration of the property given its name 2360b57cec5SDimitry Andric /// in 'PropertyId' and returns it. It returns 0, if not found. 2370b57cec5SDimitry Andric ObjCPropertyDecl *ObjCContainerDecl::FindPropertyDeclaration( 2380b57cec5SDimitry Andric const IdentifierInfo *PropertyId, 2390b57cec5SDimitry Andric ObjCPropertyQueryKind QueryKind) const { 2400b57cec5SDimitry Andric // Don't find properties within hidden protocol definitions. 2410b57cec5SDimitry Andric if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(this)) { 2420b57cec5SDimitry Andric if (const ObjCProtocolDecl *Def = Proto->getDefinition()) 2435ffd83dbSDimitry Andric if (!Def->isUnconditionallyVisible()) 2440b57cec5SDimitry Andric return nullptr; 2450b57cec5SDimitry Andric } 2460b57cec5SDimitry Andric 2470b57cec5SDimitry Andric // Search the extensions of a class first; they override what's in 2480b57cec5SDimitry Andric // the class itself. 2490b57cec5SDimitry Andric if (const auto *ClassDecl = dyn_cast<ObjCInterfaceDecl>(this)) { 2500b57cec5SDimitry Andric for (const auto *Ext : ClassDecl->visible_extensions()) { 2510b57cec5SDimitry Andric if (auto *P = Ext->FindPropertyDeclaration(PropertyId, QueryKind)) 2520b57cec5SDimitry Andric return P; 2530b57cec5SDimitry Andric } 2540b57cec5SDimitry Andric } 2550b57cec5SDimitry Andric 2560b57cec5SDimitry Andric if (ObjCPropertyDecl *PD = 2570b57cec5SDimitry Andric ObjCPropertyDecl::findPropertyDecl(cast<DeclContext>(this), PropertyId, 2580b57cec5SDimitry Andric QueryKind)) 2590b57cec5SDimitry Andric return PD; 2600b57cec5SDimitry Andric 2610b57cec5SDimitry Andric switch (getKind()) { 2620b57cec5SDimitry Andric default: 2630b57cec5SDimitry Andric break; 2640b57cec5SDimitry Andric case Decl::ObjCProtocol: { 2650b57cec5SDimitry Andric const auto *PID = cast<ObjCProtocolDecl>(this); 2660b57cec5SDimitry Andric for (const auto *I : PID->protocols()) 2670b57cec5SDimitry Andric if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId, 2680b57cec5SDimitry Andric QueryKind)) 2690b57cec5SDimitry Andric return P; 2700b57cec5SDimitry Andric break; 2710b57cec5SDimitry Andric } 2720b57cec5SDimitry Andric case Decl::ObjCInterface: { 2730b57cec5SDimitry Andric const auto *OID = cast<ObjCInterfaceDecl>(this); 2740b57cec5SDimitry Andric // Look through categories (but not extensions; they were handled above). 2750b57cec5SDimitry Andric for (const auto *Cat : OID->visible_categories()) { 2760b57cec5SDimitry Andric if (!Cat->IsClassExtension()) 2770b57cec5SDimitry Andric if (ObjCPropertyDecl *P = Cat->FindPropertyDeclaration( 2780b57cec5SDimitry Andric PropertyId, QueryKind)) 2790b57cec5SDimitry Andric return P; 2800b57cec5SDimitry Andric } 2810b57cec5SDimitry Andric 2820b57cec5SDimitry Andric // Look through protocols. 2830b57cec5SDimitry Andric for (const auto *I : OID->all_referenced_protocols()) 2840b57cec5SDimitry Andric if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId, 2850b57cec5SDimitry Andric QueryKind)) 2860b57cec5SDimitry Andric return P; 2870b57cec5SDimitry Andric 2880b57cec5SDimitry Andric // Finally, check the super class. 2890b57cec5SDimitry Andric if (const ObjCInterfaceDecl *superClass = OID->getSuperClass()) 2900b57cec5SDimitry Andric return superClass->FindPropertyDeclaration(PropertyId, QueryKind); 2910b57cec5SDimitry Andric break; 2920b57cec5SDimitry Andric } 2930b57cec5SDimitry Andric case Decl::ObjCCategory: { 2940b57cec5SDimitry Andric const auto *OCD = cast<ObjCCategoryDecl>(this); 2950b57cec5SDimitry Andric // Look through protocols. 2960b57cec5SDimitry Andric if (!OCD->IsClassExtension()) 2970b57cec5SDimitry Andric for (const auto *I : OCD->protocols()) 2980b57cec5SDimitry Andric if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId, 2990b57cec5SDimitry Andric QueryKind)) 3000b57cec5SDimitry Andric return P; 3010b57cec5SDimitry Andric break; 3020b57cec5SDimitry Andric } 3030b57cec5SDimitry Andric } 3040b57cec5SDimitry Andric return nullptr; 3050b57cec5SDimitry Andric } 3060b57cec5SDimitry Andric 3070b57cec5SDimitry Andric void ObjCInterfaceDecl::anchor() {} 3080b57cec5SDimitry Andric 3090b57cec5SDimitry Andric ObjCTypeParamList *ObjCInterfaceDecl::getTypeParamList() const { 3100b57cec5SDimitry Andric // If this particular declaration has a type parameter list, return it. 3110b57cec5SDimitry Andric if (ObjCTypeParamList *written = getTypeParamListAsWritten()) 3120b57cec5SDimitry Andric return written; 3130b57cec5SDimitry Andric 3140b57cec5SDimitry Andric // If there is a definition, return its type parameter list. 3150b57cec5SDimitry Andric if (const ObjCInterfaceDecl *def = getDefinition()) 3160b57cec5SDimitry Andric return def->getTypeParamListAsWritten(); 3170b57cec5SDimitry Andric 3180b57cec5SDimitry Andric // Otherwise, look at previous declarations to determine whether any 3190b57cec5SDimitry Andric // of them has a type parameter list, skipping over those 3200b57cec5SDimitry Andric // declarations that do not. 3210b57cec5SDimitry Andric for (const ObjCInterfaceDecl *decl = getMostRecentDecl(); decl; 3220b57cec5SDimitry Andric decl = decl->getPreviousDecl()) { 3230b57cec5SDimitry Andric if (ObjCTypeParamList *written = decl->getTypeParamListAsWritten()) 3240b57cec5SDimitry Andric return written; 3250b57cec5SDimitry Andric } 3260b57cec5SDimitry Andric 3270b57cec5SDimitry Andric return nullptr; 3280b57cec5SDimitry Andric } 3290b57cec5SDimitry Andric 3300b57cec5SDimitry Andric void ObjCInterfaceDecl::setTypeParamList(ObjCTypeParamList *TPL) { 3310b57cec5SDimitry Andric TypeParamList = TPL; 3320b57cec5SDimitry Andric if (!TPL) 3330b57cec5SDimitry Andric return; 3340b57cec5SDimitry Andric // Set the declaration context of each of the type parameters. 3350b57cec5SDimitry Andric for (auto *typeParam : *TypeParamList) 3360b57cec5SDimitry Andric typeParam->setDeclContext(this); 3370b57cec5SDimitry Andric } 3380b57cec5SDimitry Andric 3390b57cec5SDimitry Andric ObjCInterfaceDecl *ObjCInterfaceDecl::getSuperClass() const { 3400b57cec5SDimitry Andric // FIXME: Should make sure no callers ever do this. 3410b57cec5SDimitry Andric if (!hasDefinition()) 3420b57cec5SDimitry Andric return nullptr; 3430b57cec5SDimitry Andric 3440b57cec5SDimitry Andric if (data().ExternallyCompleted) 3450b57cec5SDimitry Andric LoadExternalDefinition(); 3460b57cec5SDimitry Andric 3470b57cec5SDimitry Andric if (const ObjCObjectType *superType = getSuperClassType()) { 3480b57cec5SDimitry Andric if (ObjCInterfaceDecl *superDecl = superType->getInterface()) { 3490b57cec5SDimitry Andric if (ObjCInterfaceDecl *superDef = superDecl->getDefinition()) 3500b57cec5SDimitry Andric return superDef; 3510b57cec5SDimitry Andric 3520b57cec5SDimitry Andric return superDecl; 3530b57cec5SDimitry Andric } 3540b57cec5SDimitry Andric } 3550b57cec5SDimitry Andric 3560b57cec5SDimitry Andric return nullptr; 3570b57cec5SDimitry Andric } 3580b57cec5SDimitry Andric 3590b57cec5SDimitry Andric SourceLocation ObjCInterfaceDecl::getSuperClassLoc() const { 3600b57cec5SDimitry Andric if (TypeSourceInfo *superTInfo = getSuperClassTInfo()) 3610b57cec5SDimitry Andric return superTInfo->getTypeLoc().getBeginLoc(); 3620b57cec5SDimitry Andric 3630b57cec5SDimitry Andric return SourceLocation(); 3640b57cec5SDimitry Andric } 3650b57cec5SDimitry Andric 3660b57cec5SDimitry Andric /// FindPropertyVisibleInPrimaryClass - Finds declaration of the property 3670b57cec5SDimitry Andric /// with name 'PropertyId' in the primary class; including those in protocols 3680b57cec5SDimitry Andric /// (direct or indirect) used by the primary class. 3690b57cec5SDimitry Andric ObjCPropertyDecl * 3700b57cec5SDimitry Andric ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass( 3710b57cec5SDimitry Andric IdentifierInfo *PropertyId, 3720b57cec5SDimitry Andric ObjCPropertyQueryKind QueryKind) const { 3730b57cec5SDimitry Andric // FIXME: Should make sure no callers ever do this. 3740b57cec5SDimitry Andric if (!hasDefinition()) 3750b57cec5SDimitry Andric return nullptr; 3760b57cec5SDimitry Andric 3770b57cec5SDimitry Andric if (data().ExternallyCompleted) 3780b57cec5SDimitry Andric LoadExternalDefinition(); 3790b57cec5SDimitry Andric 3800b57cec5SDimitry Andric if (ObjCPropertyDecl *PD = 3810b57cec5SDimitry Andric ObjCPropertyDecl::findPropertyDecl(cast<DeclContext>(this), PropertyId, 3820b57cec5SDimitry Andric QueryKind)) 3830b57cec5SDimitry Andric return PD; 3840b57cec5SDimitry Andric 3850b57cec5SDimitry Andric // Look through protocols. 3860b57cec5SDimitry Andric for (const auto *I : all_referenced_protocols()) 3870b57cec5SDimitry Andric if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId, 3880b57cec5SDimitry Andric QueryKind)) 3890b57cec5SDimitry Andric return P; 3900b57cec5SDimitry Andric 3910b57cec5SDimitry Andric return nullptr; 3920b57cec5SDimitry Andric } 3930b57cec5SDimitry Andric 3940b57cec5SDimitry Andric void ObjCInterfaceDecl::collectPropertiesToImplement(PropertyMap &PM, 3950b57cec5SDimitry Andric PropertyDeclOrder &PO) const { 3960b57cec5SDimitry Andric for (auto *Prop : properties()) { 3970b57cec5SDimitry Andric PM[std::make_pair(Prop->getIdentifier(), Prop->isClassProperty())] = Prop; 3980b57cec5SDimitry Andric PO.push_back(Prop); 3990b57cec5SDimitry Andric } 4000b57cec5SDimitry Andric for (const auto *Ext : known_extensions()) { 4010b57cec5SDimitry Andric const ObjCCategoryDecl *ClassExt = Ext; 4020b57cec5SDimitry Andric for (auto *Prop : ClassExt->properties()) { 4030b57cec5SDimitry Andric PM[std::make_pair(Prop->getIdentifier(), Prop->isClassProperty())] = Prop; 4040b57cec5SDimitry Andric PO.push_back(Prop); 4050b57cec5SDimitry Andric } 4060b57cec5SDimitry Andric } 4070b57cec5SDimitry Andric for (const auto *PI : all_referenced_protocols()) 4080b57cec5SDimitry Andric PI->collectPropertiesToImplement(PM, PO); 4090b57cec5SDimitry Andric // Note, the properties declared only in class extensions are still copied 4100b57cec5SDimitry Andric // into the main @interface's property list, and therefore we don't 4110b57cec5SDimitry Andric // explicitly, have to search class extension properties. 4120b57cec5SDimitry Andric } 4130b57cec5SDimitry Andric 4140b57cec5SDimitry Andric bool ObjCInterfaceDecl::isArcWeakrefUnavailable() const { 4150b57cec5SDimitry Andric const ObjCInterfaceDecl *Class = this; 4160b57cec5SDimitry Andric while (Class) { 4170b57cec5SDimitry Andric if (Class->hasAttr<ArcWeakrefUnavailableAttr>()) 4180b57cec5SDimitry Andric return true; 4190b57cec5SDimitry Andric Class = Class->getSuperClass(); 4200b57cec5SDimitry Andric } 4210b57cec5SDimitry Andric return false; 4220b57cec5SDimitry Andric } 4230b57cec5SDimitry Andric 4240b57cec5SDimitry Andric const ObjCInterfaceDecl *ObjCInterfaceDecl::isObjCRequiresPropertyDefs() const { 4250b57cec5SDimitry Andric const ObjCInterfaceDecl *Class = this; 4260b57cec5SDimitry Andric while (Class) { 4270b57cec5SDimitry Andric if (Class->hasAttr<ObjCRequiresPropertyDefsAttr>()) 4280b57cec5SDimitry Andric return Class; 4290b57cec5SDimitry Andric Class = Class->getSuperClass(); 4300b57cec5SDimitry Andric } 4310b57cec5SDimitry Andric return nullptr; 4320b57cec5SDimitry Andric } 4330b57cec5SDimitry Andric 4340b57cec5SDimitry Andric void ObjCInterfaceDecl::mergeClassExtensionProtocolList( 4350b57cec5SDimitry Andric ObjCProtocolDecl *const* ExtList, unsigned ExtNum, 4360b57cec5SDimitry Andric ASTContext &C) { 4370b57cec5SDimitry Andric if (data().ExternallyCompleted) 4380b57cec5SDimitry Andric LoadExternalDefinition(); 4390b57cec5SDimitry Andric 4400b57cec5SDimitry Andric if (data().AllReferencedProtocols.empty() && 4410b57cec5SDimitry Andric data().ReferencedProtocols.empty()) { 4420b57cec5SDimitry Andric data().AllReferencedProtocols.set(ExtList, ExtNum, C); 4430b57cec5SDimitry Andric return; 4440b57cec5SDimitry Andric } 4450b57cec5SDimitry Andric 4460b57cec5SDimitry Andric // Check for duplicate protocol in class's protocol list. 4470b57cec5SDimitry Andric // This is O(n*m). But it is extremely rare and number of protocols in 4480b57cec5SDimitry Andric // class or its extension are very few. 4490b57cec5SDimitry Andric SmallVector<ObjCProtocolDecl *, 8> ProtocolRefs; 4500b57cec5SDimitry Andric for (unsigned i = 0; i < ExtNum; i++) { 4510b57cec5SDimitry Andric bool protocolExists = false; 4520b57cec5SDimitry Andric ObjCProtocolDecl *ProtoInExtension = ExtList[i]; 4530b57cec5SDimitry Andric for (auto *Proto : all_referenced_protocols()) { 4540b57cec5SDimitry Andric if (C.ProtocolCompatibleWithProtocol(ProtoInExtension, Proto)) { 4550b57cec5SDimitry Andric protocolExists = true; 4560b57cec5SDimitry Andric break; 4570b57cec5SDimitry Andric } 4580b57cec5SDimitry Andric } 4590b57cec5SDimitry Andric // Do we want to warn on a protocol in extension class which 4600b57cec5SDimitry Andric // already exist in the class? Probably not. 4610b57cec5SDimitry Andric if (!protocolExists) 4620b57cec5SDimitry Andric ProtocolRefs.push_back(ProtoInExtension); 4630b57cec5SDimitry Andric } 4640b57cec5SDimitry Andric 4650b57cec5SDimitry Andric if (ProtocolRefs.empty()) 4660b57cec5SDimitry Andric return; 4670b57cec5SDimitry Andric 4680b57cec5SDimitry Andric // Merge ProtocolRefs into class's protocol list; 4690b57cec5SDimitry Andric ProtocolRefs.append(all_referenced_protocol_begin(), 4700b57cec5SDimitry Andric all_referenced_protocol_end()); 4710b57cec5SDimitry Andric 4720b57cec5SDimitry Andric data().AllReferencedProtocols.set(ProtocolRefs.data(), ProtocolRefs.size(),C); 4730b57cec5SDimitry Andric } 4740b57cec5SDimitry Andric 4750b57cec5SDimitry Andric const ObjCInterfaceDecl * 4760b57cec5SDimitry Andric ObjCInterfaceDecl::findInterfaceWithDesignatedInitializers() const { 4770b57cec5SDimitry Andric const ObjCInterfaceDecl *IFace = this; 4780b57cec5SDimitry Andric while (IFace) { 4790b57cec5SDimitry Andric if (IFace->hasDesignatedInitializers()) 4800b57cec5SDimitry Andric return IFace; 4810b57cec5SDimitry Andric if (!IFace->inheritsDesignatedInitializers()) 4820b57cec5SDimitry Andric break; 4830b57cec5SDimitry Andric IFace = IFace->getSuperClass(); 4840b57cec5SDimitry Andric } 4850b57cec5SDimitry Andric return nullptr; 4860b57cec5SDimitry Andric } 4870b57cec5SDimitry Andric 4880b57cec5SDimitry Andric static bool isIntroducingInitializers(const ObjCInterfaceDecl *D) { 4890b57cec5SDimitry Andric for (const auto *MD : D->instance_methods()) { 4900b57cec5SDimitry Andric if (MD->getMethodFamily() == OMF_init && !MD->isOverriding()) 4910b57cec5SDimitry Andric return true; 4920b57cec5SDimitry Andric } 4930b57cec5SDimitry Andric for (const auto *Ext : D->visible_extensions()) { 4940b57cec5SDimitry Andric for (const auto *MD : Ext->instance_methods()) { 4950b57cec5SDimitry Andric if (MD->getMethodFamily() == OMF_init && !MD->isOverriding()) 4960b57cec5SDimitry Andric return true; 4970b57cec5SDimitry Andric } 4980b57cec5SDimitry Andric } 4990b57cec5SDimitry Andric if (const auto *ImplD = D->getImplementation()) { 5000b57cec5SDimitry Andric for (const auto *MD : ImplD->instance_methods()) { 5010b57cec5SDimitry Andric if (MD->getMethodFamily() == OMF_init && !MD->isOverriding()) 5020b57cec5SDimitry Andric return true; 5030b57cec5SDimitry Andric } 5040b57cec5SDimitry Andric } 5050b57cec5SDimitry Andric return false; 5060b57cec5SDimitry Andric } 5070b57cec5SDimitry Andric 5080b57cec5SDimitry Andric bool ObjCInterfaceDecl::inheritsDesignatedInitializers() const { 5090b57cec5SDimitry Andric switch (data().InheritedDesignatedInitializers) { 5100b57cec5SDimitry Andric case DefinitionData::IDI_Inherited: 5110b57cec5SDimitry Andric return true; 5120b57cec5SDimitry Andric case DefinitionData::IDI_NotInherited: 5130b57cec5SDimitry Andric return false; 5140b57cec5SDimitry Andric case DefinitionData::IDI_Unknown: 5150b57cec5SDimitry Andric // If the class introduced initializers we conservatively assume that we 5160b57cec5SDimitry Andric // don't know if any of them is a designated initializer to avoid possible 5170b57cec5SDimitry Andric // misleading warnings. 5180b57cec5SDimitry Andric if (isIntroducingInitializers(this)) { 5190b57cec5SDimitry Andric data().InheritedDesignatedInitializers = DefinitionData::IDI_NotInherited; 5200b57cec5SDimitry Andric } else { 5210b57cec5SDimitry Andric if (auto SuperD = getSuperClass()) { 5220b57cec5SDimitry Andric data().InheritedDesignatedInitializers = 5230b57cec5SDimitry Andric SuperD->declaresOrInheritsDesignatedInitializers() ? 5240b57cec5SDimitry Andric DefinitionData::IDI_Inherited : 5250b57cec5SDimitry Andric DefinitionData::IDI_NotInherited; 5260b57cec5SDimitry Andric } else { 5270b57cec5SDimitry Andric data().InheritedDesignatedInitializers = 5280b57cec5SDimitry Andric DefinitionData::IDI_NotInherited; 5290b57cec5SDimitry Andric } 5300b57cec5SDimitry Andric } 5310b57cec5SDimitry Andric assert(data().InheritedDesignatedInitializers 5320b57cec5SDimitry Andric != DefinitionData::IDI_Unknown); 5330b57cec5SDimitry Andric return data().InheritedDesignatedInitializers == 5340b57cec5SDimitry Andric DefinitionData::IDI_Inherited; 5350b57cec5SDimitry Andric } 5360b57cec5SDimitry Andric 5370b57cec5SDimitry Andric llvm_unreachable("unexpected InheritedDesignatedInitializers value"); 5380b57cec5SDimitry Andric } 5390b57cec5SDimitry Andric 5400b57cec5SDimitry Andric void ObjCInterfaceDecl::getDesignatedInitializers( 5410b57cec5SDimitry Andric llvm::SmallVectorImpl<const ObjCMethodDecl *> &Methods) const { 5420b57cec5SDimitry Andric // Check for a complete definition and recover if not so. 5430b57cec5SDimitry Andric if (!isThisDeclarationADefinition()) 5440b57cec5SDimitry Andric return; 5450b57cec5SDimitry Andric if (data().ExternallyCompleted) 5460b57cec5SDimitry Andric LoadExternalDefinition(); 5470b57cec5SDimitry Andric 5480b57cec5SDimitry Andric const ObjCInterfaceDecl *IFace= findInterfaceWithDesignatedInitializers(); 5490b57cec5SDimitry Andric if (!IFace) 5500b57cec5SDimitry Andric return; 5510b57cec5SDimitry Andric 5520b57cec5SDimitry Andric for (const auto *MD : IFace->instance_methods()) 5530b57cec5SDimitry Andric if (MD->isThisDeclarationADesignatedInitializer()) 5540b57cec5SDimitry Andric Methods.push_back(MD); 5550b57cec5SDimitry Andric for (const auto *Ext : IFace->visible_extensions()) { 5560b57cec5SDimitry Andric for (const auto *MD : Ext->instance_methods()) 5570b57cec5SDimitry Andric if (MD->isThisDeclarationADesignatedInitializer()) 5580b57cec5SDimitry Andric Methods.push_back(MD); 5590b57cec5SDimitry Andric } 5600b57cec5SDimitry Andric } 5610b57cec5SDimitry Andric 5620b57cec5SDimitry Andric bool ObjCInterfaceDecl::isDesignatedInitializer(Selector Sel, 5630b57cec5SDimitry Andric const ObjCMethodDecl **InitMethod) const { 5640b57cec5SDimitry Andric bool HasCompleteDef = isThisDeclarationADefinition(); 5650b57cec5SDimitry Andric // During deserialization the data record for the ObjCInterfaceDecl could 5660b57cec5SDimitry Andric // be made invariant by reusing the canonical decl. Take this into account 5670b57cec5SDimitry Andric // when checking for the complete definition. 5680b57cec5SDimitry Andric if (!HasCompleteDef && getCanonicalDecl()->hasDefinition() && 5690b57cec5SDimitry Andric getCanonicalDecl()->getDefinition() == getDefinition()) 5700b57cec5SDimitry Andric HasCompleteDef = true; 5710b57cec5SDimitry Andric 5720b57cec5SDimitry Andric // Check for a complete definition and recover if not so. 5730b57cec5SDimitry Andric if (!HasCompleteDef) 5740b57cec5SDimitry Andric return false; 5750b57cec5SDimitry Andric 5760b57cec5SDimitry Andric if (data().ExternallyCompleted) 5770b57cec5SDimitry Andric LoadExternalDefinition(); 5780b57cec5SDimitry Andric 5790b57cec5SDimitry Andric const ObjCInterfaceDecl *IFace= findInterfaceWithDesignatedInitializers(); 5800b57cec5SDimitry Andric if (!IFace) 5810b57cec5SDimitry Andric return false; 5820b57cec5SDimitry Andric 5830b57cec5SDimitry Andric if (const ObjCMethodDecl *MD = IFace->getInstanceMethod(Sel)) { 5840b57cec5SDimitry Andric if (MD->isThisDeclarationADesignatedInitializer()) { 5850b57cec5SDimitry Andric if (InitMethod) 5860b57cec5SDimitry Andric *InitMethod = MD; 5870b57cec5SDimitry Andric return true; 5880b57cec5SDimitry Andric } 5890b57cec5SDimitry Andric } 5900b57cec5SDimitry Andric for (const auto *Ext : IFace->visible_extensions()) { 5910b57cec5SDimitry Andric if (const ObjCMethodDecl *MD = Ext->getInstanceMethod(Sel)) { 5920b57cec5SDimitry Andric if (MD->isThisDeclarationADesignatedInitializer()) { 5930b57cec5SDimitry Andric if (InitMethod) 5940b57cec5SDimitry Andric *InitMethod = MD; 5950b57cec5SDimitry Andric return true; 5960b57cec5SDimitry Andric } 5970b57cec5SDimitry Andric } 5980b57cec5SDimitry Andric } 5990b57cec5SDimitry Andric return false; 6000b57cec5SDimitry Andric } 6010b57cec5SDimitry Andric 6020b57cec5SDimitry Andric void ObjCInterfaceDecl::allocateDefinitionData() { 6030b57cec5SDimitry Andric assert(!hasDefinition() && "ObjC class already has a definition"); 6040b57cec5SDimitry Andric Data.setPointer(new (getASTContext()) DefinitionData()); 6050b57cec5SDimitry Andric Data.getPointer()->Definition = this; 6060b57cec5SDimitry Andric } 6070b57cec5SDimitry Andric 6080b57cec5SDimitry Andric void ObjCInterfaceDecl::startDefinition() { 6090b57cec5SDimitry Andric allocateDefinitionData(); 6100b57cec5SDimitry Andric 6110b57cec5SDimitry Andric // Update all of the declarations with a pointer to the definition. 6120b57cec5SDimitry Andric for (auto *RD : redecls()) { 6130b57cec5SDimitry Andric if (RD != this) 6140b57cec5SDimitry Andric RD->Data = Data; 6150b57cec5SDimitry Andric } 6160b57cec5SDimitry Andric } 6170b57cec5SDimitry Andric 6180b57cec5SDimitry Andric ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(IdentifierInfo *ID, 6190b57cec5SDimitry Andric ObjCInterfaceDecl *&clsDeclared) { 6200b57cec5SDimitry Andric // FIXME: Should make sure no callers ever do this. 6210b57cec5SDimitry Andric if (!hasDefinition()) 6220b57cec5SDimitry Andric return nullptr; 6230b57cec5SDimitry Andric 6240b57cec5SDimitry Andric if (data().ExternallyCompleted) 6250b57cec5SDimitry Andric LoadExternalDefinition(); 6260b57cec5SDimitry Andric 6270b57cec5SDimitry Andric ObjCInterfaceDecl* ClassDecl = this; 6280b57cec5SDimitry Andric while (ClassDecl != nullptr) { 6290b57cec5SDimitry Andric if (ObjCIvarDecl *I = ClassDecl->getIvarDecl(ID)) { 6300b57cec5SDimitry Andric clsDeclared = ClassDecl; 6310b57cec5SDimitry Andric return I; 6320b57cec5SDimitry Andric } 6330b57cec5SDimitry Andric 6340b57cec5SDimitry Andric for (const auto *Ext : ClassDecl->visible_extensions()) { 6350b57cec5SDimitry Andric if (ObjCIvarDecl *I = Ext->getIvarDecl(ID)) { 6360b57cec5SDimitry Andric clsDeclared = ClassDecl; 6370b57cec5SDimitry Andric return I; 6380b57cec5SDimitry Andric } 6390b57cec5SDimitry Andric } 6400b57cec5SDimitry Andric 6410b57cec5SDimitry Andric ClassDecl = ClassDecl->getSuperClass(); 6420b57cec5SDimitry Andric } 6430b57cec5SDimitry Andric return nullptr; 6440b57cec5SDimitry Andric } 6450b57cec5SDimitry Andric 6460b57cec5SDimitry Andric /// lookupInheritedClass - This method returns ObjCInterfaceDecl * of the super 6470b57cec5SDimitry Andric /// class whose name is passed as argument. If it is not one of the super classes 6480b57cec5SDimitry Andric /// the it returns NULL. 6490b57cec5SDimitry Andric ObjCInterfaceDecl *ObjCInterfaceDecl::lookupInheritedClass( 6500b57cec5SDimitry Andric const IdentifierInfo*ICName) { 6510b57cec5SDimitry Andric // FIXME: Should make sure no callers ever do this. 6520b57cec5SDimitry Andric if (!hasDefinition()) 6530b57cec5SDimitry Andric return nullptr; 6540b57cec5SDimitry Andric 6550b57cec5SDimitry Andric if (data().ExternallyCompleted) 6560b57cec5SDimitry Andric LoadExternalDefinition(); 6570b57cec5SDimitry Andric 6580b57cec5SDimitry Andric ObjCInterfaceDecl* ClassDecl = this; 6590b57cec5SDimitry Andric while (ClassDecl != nullptr) { 6600b57cec5SDimitry Andric if (ClassDecl->getIdentifier() == ICName) 6610b57cec5SDimitry Andric return ClassDecl; 6620b57cec5SDimitry Andric ClassDecl = ClassDecl->getSuperClass(); 6630b57cec5SDimitry Andric } 6640b57cec5SDimitry Andric return nullptr; 6650b57cec5SDimitry Andric } 6660b57cec5SDimitry Andric 6670b57cec5SDimitry Andric ObjCProtocolDecl * 6680b57cec5SDimitry Andric ObjCInterfaceDecl::lookupNestedProtocol(IdentifierInfo *Name) { 6690b57cec5SDimitry Andric for (auto *P : all_referenced_protocols()) 6700b57cec5SDimitry Andric if (P->lookupProtocolNamed(Name)) 6710b57cec5SDimitry Andric return P; 6720b57cec5SDimitry Andric ObjCInterfaceDecl *SuperClass = getSuperClass(); 6730b57cec5SDimitry Andric return SuperClass ? SuperClass->lookupNestedProtocol(Name) : nullptr; 6740b57cec5SDimitry Andric } 6750b57cec5SDimitry Andric 6760b57cec5SDimitry Andric /// lookupMethod - This method returns an instance/class method by looking in 6770b57cec5SDimitry Andric /// the class, its categories, and its super classes (using a linear search). 6780b57cec5SDimitry Andric /// When argument category "C" is specified, any implicit method found 6790b57cec5SDimitry Andric /// in this category is ignored. 6800b57cec5SDimitry Andric ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel, 6810b57cec5SDimitry Andric bool isInstance, 6820b57cec5SDimitry Andric bool shallowCategoryLookup, 6830b57cec5SDimitry Andric bool followSuper, 6840b57cec5SDimitry Andric const ObjCCategoryDecl *C) const 6850b57cec5SDimitry Andric { 6860b57cec5SDimitry Andric // FIXME: Should make sure no callers ever do this. 6870b57cec5SDimitry Andric if (!hasDefinition()) 6880b57cec5SDimitry Andric return nullptr; 6890b57cec5SDimitry Andric 6900b57cec5SDimitry Andric const ObjCInterfaceDecl* ClassDecl = this; 6910b57cec5SDimitry Andric ObjCMethodDecl *MethodDecl = nullptr; 6920b57cec5SDimitry Andric 6930b57cec5SDimitry Andric if (data().ExternallyCompleted) 6940b57cec5SDimitry Andric LoadExternalDefinition(); 6950b57cec5SDimitry Andric 6960b57cec5SDimitry Andric while (ClassDecl) { 6970b57cec5SDimitry Andric // 1. Look through primary class. 6980b57cec5SDimitry Andric if ((MethodDecl = ClassDecl->getMethod(Sel, isInstance))) 6990b57cec5SDimitry Andric return MethodDecl; 7000b57cec5SDimitry Andric 7010b57cec5SDimitry Andric // 2. Didn't find one yet - now look through categories. 7020b57cec5SDimitry Andric for (const auto *Cat : ClassDecl->visible_categories()) 7030b57cec5SDimitry Andric if ((MethodDecl = Cat->getMethod(Sel, isInstance))) 7040b57cec5SDimitry Andric if (C != Cat || !MethodDecl->isImplicit()) 7050b57cec5SDimitry Andric return MethodDecl; 7060b57cec5SDimitry Andric 7070b57cec5SDimitry Andric // 3. Didn't find one yet - look through primary class's protocols. 7080b57cec5SDimitry Andric for (const auto *I : ClassDecl->protocols()) 7090b57cec5SDimitry Andric if ((MethodDecl = I->lookupMethod(Sel, isInstance))) 7100b57cec5SDimitry Andric return MethodDecl; 7110b57cec5SDimitry Andric 7120b57cec5SDimitry Andric // 4. Didn't find one yet - now look through categories' protocols 7130b57cec5SDimitry Andric if (!shallowCategoryLookup) 7140b57cec5SDimitry Andric for (const auto *Cat : ClassDecl->visible_categories()) { 7150b57cec5SDimitry Andric // Didn't find one yet - look through protocols. 7160b57cec5SDimitry Andric const ObjCList<ObjCProtocolDecl> &Protocols = 7170b57cec5SDimitry Andric Cat->getReferencedProtocols(); 7180b57cec5SDimitry Andric for (auto *Protocol : Protocols) 7190b57cec5SDimitry Andric if ((MethodDecl = Protocol->lookupMethod(Sel, isInstance))) 7200b57cec5SDimitry Andric if (C != Cat || !MethodDecl->isImplicit()) 7210b57cec5SDimitry Andric return MethodDecl; 7220b57cec5SDimitry Andric } 7230b57cec5SDimitry Andric 7240b57cec5SDimitry Andric 7250b57cec5SDimitry Andric if (!followSuper) 7260b57cec5SDimitry Andric return nullptr; 7270b57cec5SDimitry Andric 7280b57cec5SDimitry Andric // 5. Get to the super class (if any). 7290b57cec5SDimitry Andric ClassDecl = ClassDecl->getSuperClass(); 7300b57cec5SDimitry Andric } 7310b57cec5SDimitry Andric return nullptr; 7320b57cec5SDimitry Andric } 7330b57cec5SDimitry Andric 7340b57cec5SDimitry Andric // Will search "local" class/category implementations for a method decl. 7350b57cec5SDimitry Andric // If failed, then we search in class's root for an instance method. 7360b57cec5SDimitry Andric // Returns 0 if no method is found. 7370b57cec5SDimitry Andric ObjCMethodDecl *ObjCInterfaceDecl::lookupPrivateMethod( 7380b57cec5SDimitry Andric const Selector &Sel, 7390b57cec5SDimitry Andric bool Instance) const { 7400b57cec5SDimitry Andric // FIXME: Should make sure no callers ever do this. 7410b57cec5SDimitry Andric if (!hasDefinition()) 7420b57cec5SDimitry Andric return nullptr; 7430b57cec5SDimitry Andric 7440b57cec5SDimitry Andric if (data().ExternallyCompleted) 7450b57cec5SDimitry Andric LoadExternalDefinition(); 7460b57cec5SDimitry Andric 7470b57cec5SDimitry Andric ObjCMethodDecl *Method = nullptr; 7480b57cec5SDimitry Andric if (ObjCImplementationDecl *ImpDecl = getImplementation()) 7490b57cec5SDimitry Andric Method = Instance ? ImpDecl->getInstanceMethod(Sel) 7500b57cec5SDimitry Andric : ImpDecl->getClassMethod(Sel); 7510b57cec5SDimitry Andric 7520b57cec5SDimitry Andric // Look through local category implementations associated with the class. 7530b57cec5SDimitry Andric if (!Method) 7540b57cec5SDimitry Andric Method = getCategoryMethod(Sel, Instance); 7550b57cec5SDimitry Andric 7560b57cec5SDimitry Andric // Before we give up, check if the selector is an instance method. 7570b57cec5SDimitry Andric // But only in the root. This matches gcc's behavior and what the 7580b57cec5SDimitry Andric // runtime expects. 7590b57cec5SDimitry Andric if (!Instance && !Method && !getSuperClass()) { 7600b57cec5SDimitry Andric Method = lookupInstanceMethod(Sel); 7610b57cec5SDimitry Andric // Look through local category implementations associated 7620b57cec5SDimitry Andric // with the root class. 7630b57cec5SDimitry Andric if (!Method) 7640b57cec5SDimitry Andric Method = lookupPrivateMethod(Sel, true); 7650b57cec5SDimitry Andric } 7660b57cec5SDimitry Andric 7670b57cec5SDimitry Andric if (!Method && getSuperClass()) 7680b57cec5SDimitry Andric return getSuperClass()->lookupPrivateMethod(Sel, Instance); 7690b57cec5SDimitry Andric return Method; 7700b57cec5SDimitry Andric } 7710b57cec5SDimitry Andric 7720b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 7730b57cec5SDimitry Andric // ObjCMethodDecl 7740b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 7750b57cec5SDimitry Andric 776480093f4SDimitry Andric ObjCMethodDecl::ObjCMethodDecl( 777480093f4SDimitry Andric SourceLocation beginLoc, SourceLocation endLoc, Selector SelInfo, 778480093f4SDimitry Andric QualType T, TypeSourceInfo *ReturnTInfo, DeclContext *contextDecl, 779480093f4SDimitry Andric bool isInstance, bool isVariadic, bool isPropertyAccessor, 780480093f4SDimitry Andric bool isSynthesizedAccessorStub, bool isImplicitlyDeclared, bool isDefined, 781480093f4SDimitry Andric ImplementationControl impControl, bool HasRelatedResultType) 7820b57cec5SDimitry Andric : NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo), 7830b57cec5SDimitry Andric DeclContext(ObjCMethod), MethodDeclType(T), ReturnTInfo(ReturnTInfo), 7840b57cec5SDimitry Andric DeclEndLoc(endLoc) { 7850b57cec5SDimitry Andric 7860b57cec5SDimitry Andric // Initialized the bits stored in DeclContext. 7870b57cec5SDimitry Andric ObjCMethodDeclBits.Family = 7880b57cec5SDimitry Andric static_cast<ObjCMethodFamily>(InvalidObjCMethodFamily); 7890b57cec5SDimitry Andric setInstanceMethod(isInstance); 7900b57cec5SDimitry Andric setVariadic(isVariadic); 7910b57cec5SDimitry Andric setPropertyAccessor(isPropertyAccessor); 792480093f4SDimitry Andric setSynthesizedAccessorStub(isSynthesizedAccessorStub); 7930b57cec5SDimitry Andric setDefined(isDefined); 7940b57cec5SDimitry Andric setIsRedeclaration(false); 7950b57cec5SDimitry Andric setHasRedeclaration(false); 7960b57cec5SDimitry Andric setDeclImplementation(impControl); 7970b57cec5SDimitry Andric setObjCDeclQualifier(OBJC_TQ_None); 7980b57cec5SDimitry Andric setRelatedResultType(HasRelatedResultType); 7990b57cec5SDimitry Andric setSelLocsKind(SelLoc_StandardNoSpace); 8000b57cec5SDimitry Andric setOverriding(false); 8010b57cec5SDimitry Andric setHasSkippedBody(false); 8020b57cec5SDimitry Andric 8030b57cec5SDimitry Andric setImplicit(isImplicitlyDeclared); 8040b57cec5SDimitry Andric } 8050b57cec5SDimitry Andric 8060b57cec5SDimitry Andric ObjCMethodDecl *ObjCMethodDecl::Create( 8070b57cec5SDimitry Andric ASTContext &C, SourceLocation beginLoc, SourceLocation endLoc, 8080b57cec5SDimitry Andric Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo, 8090b57cec5SDimitry Andric DeclContext *contextDecl, bool isInstance, bool isVariadic, 810480093f4SDimitry Andric bool isPropertyAccessor, bool isSynthesizedAccessorStub, 811480093f4SDimitry Andric bool isImplicitlyDeclared, bool isDefined, ImplementationControl impControl, 812480093f4SDimitry Andric bool HasRelatedResultType) { 8130b57cec5SDimitry Andric return new (C, contextDecl) ObjCMethodDecl( 8140b57cec5SDimitry Andric beginLoc, endLoc, SelInfo, T, ReturnTInfo, contextDecl, isInstance, 815480093f4SDimitry Andric isVariadic, isPropertyAccessor, isSynthesizedAccessorStub, 816480093f4SDimitry Andric isImplicitlyDeclared, isDefined, impControl, HasRelatedResultType); 8170b57cec5SDimitry Andric } 8180b57cec5SDimitry Andric 8190b57cec5SDimitry Andric ObjCMethodDecl *ObjCMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) { 8200b57cec5SDimitry Andric return new (C, ID) ObjCMethodDecl(SourceLocation(), SourceLocation(), 8210b57cec5SDimitry Andric Selector(), QualType(), nullptr, nullptr); 8220b57cec5SDimitry Andric } 8230b57cec5SDimitry Andric 824480093f4SDimitry Andric bool ObjCMethodDecl::isDirectMethod() const { 825fe6060f1SDimitry Andric return hasAttr<ObjCDirectAttr>() && 826fe6060f1SDimitry Andric !getASTContext().getLangOpts().ObjCDisableDirectMethodsForTesting; 827480093f4SDimitry Andric } 828480093f4SDimitry Andric 8290b57cec5SDimitry Andric bool ObjCMethodDecl::isThisDeclarationADesignatedInitializer() const { 8300b57cec5SDimitry Andric return getMethodFamily() == OMF_init && 8310b57cec5SDimitry Andric hasAttr<ObjCDesignatedInitializerAttr>(); 8320b57cec5SDimitry Andric } 8330b57cec5SDimitry Andric 8340b57cec5SDimitry Andric bool ObjCMethodDecl::definedInNSObject(const ASTContext &Ctx) const { 8350b57cec5SDimitry Andric if (const auto *PD = dyn_cast<const ObjCProtocolDecl>(getDeclContext())) 8360b57cec5SDimitry Andric return PD->getIdentifier() == Ctx.getNSObjectName(); 8370b57cec5SDimitry Andric if (const auto *ID = dyn_cast<const ObjCInterfaceDecl>(getDeclContext())) 8380b57cec5SDimitry Andric return ID->getIdentifier() == Ctx.getNSObjectName(); 8390b57cec5SDimitry Andric return false; 8400b57cec5SDimitry Andric } 8410b57cec5SDimitry Andric 8420b57cec5SDimitry Andric bool ObjCMethodDecl::isDesignatedInitializerForTheInterface( 8430b57cec5SDimitry Andric const ObjCMethodDecl **InitMethod) const { 8440b57cec5SDimitry Andric if (getMethodFamily() != OMF_init) 8450b57cec5SDimitry Andric return false; 8460b57cec5SDimitry Andric const DeclContext *DC = getDeclContext(); 8470b57cec5SDimitry Andric if (isa<ObjCProtocolDecl>(DC)) 8480b57cec5SDimitry Andric return false; 8490b57cec5SDimitry Andric if (const ObjCInterfaceDecl *ID = getClassInterface()) 8500b57cec5SDimitry Andric return ID->isDesignatedInitializer(getSelector(), InitMethod); 8510b57cec5SDimitry Andric return false; 8520b57cec5SDimitry Andric } 8530b57cec5SDimitry Andric 854*349cc55cSDimitry Andric bool ObjCMethodDecl::hasParamDestroyedInCallee() const { 855*349cc55cSDimitry Andric for (auto param : parameters()) { 856*349cc55cSDimitry Andric if (param->isDestroyedInCallee()) 857*349cc55cSDimitry Andric return true; 858*349cc55cSDimitry Andric } 859*349cc55cSDimitry Andric return false; 860*349cc55cSDimitry Andric } 861*349cc55cSDimitry Andric 8620b57cec5SDimitry Andric Stmt *ObjCMethodDecl::getBody() const { 8630b57cec5SDimitry Andric return Body.get(getASTContext().getExternalSource()); 8640b57cec5SDimitry Andric } 8650b57cec5SDimitry Andric 8660b57cec5SDimitry Andric void ObjCMethodDecl::setAsRedeclaration(const ObjCMethodDecl *PrevMethod) { 8670b57cec5SDimitry Andric assert(PrevMethod); 8680b57cec5SDimitry Andric getASTContext().setObjCMethodRedeclaration(PrevMethod, this); 8690b57cec5SDimitry Andric setIsRedeclaration(true); 8700b57cec5SDimitry Andric PrevMethod->setHasRedeclaration(true); 8710b57cec5SDimitry Andric } 8720b57cec5SDimitry Andric 8730b57cec5SDimitry Andric void ObjCMethodDecl::setParamsAndSelLocs(ASTContext &C, 8740b57cec5SDimitry Andric ArrayRef<ParmVarDecl*> Params, 8750b57cec5SDimitry Andric ArrayRef<SourceLocation> SelLocs) { 8760b57cec5SDimitry Andric ParamsAndSelLocs = nullptr; 8770b57cec5SDimitry Andric NumParams = Params.size(); 8780b57cec5SDimitry Andric if (Params.empty() && SelLocs.empty()) 8790b57cec5SDimitry Andric return; 8800b57cec5SDimitry Andric 8810b57cec5SDimitry Andric static_assert(alignof(ParmVarDecl *) >= alignof(SourceLocation), 8820b57cec5SDimitry Andric "Alignment not sufficient for SourceLocation"); 8830b57cec5SDimitry Andric 8840b57cec5SDimitry Andric unsigned Size = sizeof(ParmVarDecl *) * NumParams + 8850b57cec5SDimitry Andric sizeof(SourceLocation) * SelLocs.size(); 8860b57cec5SDimitry Andric ParamsAndSelLocs = C.Allocate(Size); 8870b57cec5SDimitry Andric std::copy(Params.begin(), Params.end(), getParams()); 8880b57cec5SDimitry Andric std::copy(SelLocs.begin(), SelLocs.end(), getStoredSelLocs()); 8890b57cec5SDimitry Andric } 8900b57cec5SDimitry Andric 8910b57cec5SDimitry Andric void ObjCMethodDecl::getSelectorLocs( 8920b57cec5SDimitry Andric SmallVectorImpl<SourceLocation> &SelLocs) const { 8930b57cec5SDimitry Andric for (unsigned i = 0, e = getNumSelectorLocs(); i != e; ++i) 8940b57cec5SDimitry Andric SelLocs.push_back(getSelectorLoc(i)); 8950b57cec5SDimitry Andric } 8960b57cec5SDimitry Andric 8970b57cec5SDimitry Andric void ObjCMethodDecl::setMethodParams(ASTContext &C, 8980b57cec5SDimitry Andric ArrayRef<ParmVarDecl*> Params, 8990b57cec5SDimitry Andric ArrayRef<SourceLocation> SelLocs) { 9000b57cec5SDimitry Andric assert((!SelLocs.empty() || isImplicit()) && 9010b57cec5SDimitry Andric "No selector locs for non-implicit method"); 9020b57cec5SDimitry Andric if (isImplicit()) 9030b57cec5SDimitry Andric return setParamsAndSelLocs(C, Params, llvm::None); 9040b57cec5SDimitry Andric 9050b57cec5SDimitry Andric setSelLocsKind(hasStandardSelectorLocs(getSelector(), SelLocs, Params, 9060b57cec5SDimitry Andric DeclEndLoc)); 9070b57cec5SDimitry Andric if (getSelLocsKind() != SelLoc_NonStandard) 9080b57cec5SDimitry Andric return setParamsAndSelLocs(C, Params, llvm::None); 9090b57cec5SDimitry Andric 9100b57cec5SDimitry Andric setParamsAndSelLocs(C, Params, SelLocs); 9110b57cec5SDimitry Andric } 9120b57cec5SDimitry Andric 9130b57cec5SDimitry Andric /// A definition will return its interface declaration. 9140b57cec5SDimitry Andric /// An interface declaration will return its definition. 9150b57cec5SDimitry Andric /// Otherwise it will return itself. 9160b57cec5SDimitry Andric ObjCMethodDecl *ObjCMethodDecl::getNextRedeclarationImpl() { 9170b57cec5SDimitry Andric ASTContext &Ctx = getASTContext(); 9180b57cec5SDimitry Andric ObjCMethodDecl *Redecl = nullptr; 9190b57cec5SDimitry Andric if (hasRedeclaration()) 9200b57cec5SDimitry Andric Redecl = const_cast<ObjCMethodDecl*>(Ctx.getObjCMethodRedeclaration(this)); 9210b57cec5SDimitry Andric if (Redecl) 9220b57cec5SDimitry Andric return Redecl; 9230b57cec5SDimitry Andric 9240b57cec5SDimitry Andric auto *CtxD = cast<Decl>(getDeclContext()); 9250b57cec5SDimitry Andric 9260b57cec5SDimitry Andric if (!CtxD->isInvalidDecl()) { 9270b57cec5SDimitry Andric if (auto *IFD = dyn_cast<ObjCInterfaceDecl>(CtxD)) { 9280b57cec5SDimitry Andric if (ObjCImplementationDecl *ImplD = Ctx.getObjCImplementation(IFD)) 9290b57cec5SDimitry Andric if (!ImplD->isInvalidDecl()) 9300b57cec5SDimitry Andric Redecl = ImplD->getMethod(getSelector(), isInstanceMethod()); 9310b57cec5SDimitry Andric 9320b57cec5SDimitry Andric } else if (auto *CD = dyn_cast<ObjCCategoryDecl>(CtxD)) { 9330b57cec5SDimitry Andric if (ObjCCategoryImplDecl *ImplD = Ctx.getObjCImplementation(CD)) 9340b57cec5SDimitry Andric if (!ImplD->isInvalidDecl()) 9350b57cec5SDimitry Andric Redecl = ImplD->getMethod(getSelector(), isInstanceMethod()); 9360b57cec5SDimitry Andric 9370b57cec5SDimitry Andric } else if (auto *ImplD = dyn_cast<ObjCImplementationDecl>(CtxD)) { 9380b57cec5SDimitry Andric if (ObjCInterfaceDecl *IFD = ImplD->getClassInterface()) 9390b57cec5SDimitry Andric if (!IFD->isInvalidDecl()) 9400b57cec5SDimitry Andric Redecl = IFD->getMethod(getSelector(), isInstanceMethod()); 9410b57cec5SDimitry Andric 9420b57cec5SDimitry Andric } else if (auto *CImplD = dyn_cast<ObjCCategoryImplDecl>(CtxD)) { 9430b57cec5SDimitry Andric if (ObjCCategoryDecl *CatD = CImplD->getCategoryDecl()) 9440b57cec5SDimitry Andric if (!CatD->isInvalidDecl()) 9450b57cec5SDimitry Andric Redecl = CatD->getMethod(getSelector(), isInstanceMethod()); 9460b57cec5SDimitry Andric } 9470b57cec5SDimitry Andric } 9480b57cec5SDimitry Andric 9490b57cec5SDimitry Andric // Ensure that the discovered method redeclaration has a valid declaration 9500b57cec5SDimitry Andric // context. Used to prevent infinite loops when iterating redeclarations in 9510b57cec5SDimitry Andric // a partially invalid AST. 9520b57cec5SDimitry Andric if (Redecl && cast<Decl>(Redecl->getDeclContext())->isInvalidDecl()) 9530b57cec5SDimitry Andric Redecl = nullptr; 9540b57cec5SDimitry Andric 9550b57cec5SDimitry Andric if (!Redecl && isRedeclaration()) { 9560b57cec5SDimitry Andric // This is the last redeclaration, go back to the first method. 9570b57cec5SDimitry Andric return cast<ObjCContainerDecl>(CtxD)->getMethod(getSelector(), 958e8d8bef9SDimitry Andric isInstanceMethod(), 959e8d8bef9SDimitry Andric /*AllowHidden=*/true); 9600b57cec5SDimitry Andric } 9610b57cec5SDimitry Andric 9620b57cec5SDimitry Andric return Redecl ? Redecl : this; 9630b57cec5SDimitry Andric } 9640b57cec5SDimitry Andric 9650b57cec5SDimitry Andric ObjCMethodDecl *ObjCMethodDecl::getCanonicalDecl() { 9660b57cec5SDimitry Andric auto *CtxD = cast<Decl>(getDeclContext()); 967480093f4SDimitry Andric const auto &Sel = getSelector(); 9680b57cec5SDimitry Andric 9690b57cec5SDimitry Andric if (auto *ImplD = dyn_cast<ObjCImplementationDecl>(CtxD)) { 970480093f4SDimitry Andric if (ObjCInterfaceDecl *IFD = ImplD->getClassInterface()) { 971480093f4SDimitry Andric // When the container is the ObjCImplementationDecl (the primary 972480093f4SDimitry Andric // @implementation), then the canonical Decl is either in 973480093f4SDimitry Andric // the class Interface, or in any of its extension. 974480093f4SDimitry Andric // 975480093f4SDimitry Andric // So when we don't find it in the ObjCInterfaceDecl, 976480093f4SDimitry Andric // sift through extensions too. 977480093f4SDimitry Andric if (ObjCMethodDecl *MD = IFD->getMethod(Sel, isInstanceMethod())) 9780b57cec5SDimitry Andric return MD; 979480093f4SDimitry Andric for (auto *Ext : IFD->known_extensions()) 980480093f4SDimitry Andric if (ObjCMethodDecl *MD = Ext->getMethod(Sel, isInstanceMethod())) 981480093f4SDimitry Andric return MD; 982480093f4SDimitry Andric } 9830b57cec5SDimitry Andric } else if (auto *CImplD = dyn_cast<ObjCCategoryImplDecl>(CtxD)) { 9840b57cec5SDimitry Andric if (ObjCCategoryDecl *CatD = CImplD->getCategoryDecl()) 985480093f4SDimitry Andric if (ObjCMethodDecl *MD = CatD->getMethod(Sel, isInstanceMethod())) 9860b57cec5SDimitry Andric return MD; 9870b57cec5SDimitry Andric } 9880b57cec5SDimitry Andric 9890b57cec5SDimitry Andric if (isRedeclaration()) { 9900b57cec5SDimitry Andric // It is possible that we have not done deserializing the ObjCMethod yet. 9910b57cec5SDimitry Andric ObjCMethodDecl *MD = 992e8d8bef9SDimitry Andric cast<ObjCContainerDecl>(CtxD)->getMethod(Sel, isInstanceMethod(), 993e8d8bef9SDimitry Andric /*AllowHidden=*/true); 9940b57cec5SDimitry Andric return MD ? MD : this; 9950b57cec5SDimitry Andric } 9960b57cec5SDimitry Andric 9970b57cec5SDimitry Andric return this; 9980b57cec5SDimitry Andric } 9990b57cec5SDimitry Andric 10000b57cec5SDimitry Andric SourceLocation ObjCMethodDecl::getEndLoc() const { 10010b57cec5SDimitry Andric if (Stmt *Body = getBody()) 10020b57cec5SDimitry Andric return Body->getEndLoc(); 10030b57cec5SDimitry Andric return DeclEndLoc; 10040b57cec5SDimitry Andric } 10050b57cec5SDimitry Andric 10060b57cec5SDimitry Andric ObjCMethodFamily ObjCMethodDecl::getMethodFamily() const { 10070b57cec5SDimitry Andric auto family = static_cast<ObjCMethodFamily>(ObjCMethodDeclBits.Family); 10080b57cec5SDimitry Andric if (family != static_cast<unsigned>(InvalidObjCMethodFamily)) 10090b57cec5SDimitry Andric return family; 10100b57cec5SDimitry Andric 10110b57cec5SDimitry Andric // Check for an explicit attribute. 10120b57cec5SDimitry Andric if (const ObjCMethodFamilyAttr *attr = getAttr<ObjCMethodFamilyAttr>()) { 10130b57cec5SDimitry Andric // The unfortunate necessity of mapping between enums here is due 10140b57cec5SDimitry Andric // to the attributes framework. 10150b57cec5SDimitry Andric switch (attr->getFamily()) { 10160b57cec5SDimitry Andric case ObjCMethodFamilyAttr::OMF_None: family = OMF_None; break; 10170b57cec5SDimitry Andric case ObjCMethodFamilyAttr::OMF_alloc: family = OMF_alloc; break; 10180b57cec5SDimitry Andric case ObjCMethodFamilyAttr::OMF_copy: family = OMF_copy; break; 10190b57cec5SDimitry Andric case ObjCMethodFamilyAttr::OMF_init: family = OMF_init; break; 10200b57cec5SDimitry Andric case ObjCMethodFamilyAttr::OMF_mutableCopy: family = OMF_mutableCopy; break; 10210b57cec5SDimitry Andric case ObjCMethodFamilyAttr::OMF_new: family = OMF_new; break; 10220b57cec5SDimitry Andric } 10230b57cec5SDimitry Andric ObjCMethodDeclBits.Family = family; 10240b57cec5SDimitry Andric return family; 10250b57cec5SDimitry Andric } 10260b57cec5SDimitry Andric 10270b57cec5SDimitry Andric family = getSelector().getMethodFamily(); 10280b57cec5SDimitry Andric switch (family) { 10290b57cec5SDimitry Andric case OMF_None: break; 10300b57cec5SDimitry Andric 10310b57cec5SDimitry Andric // init only has a conventional meaning for an instance method, and 10320b57cec5SDimitry Andric // it has to return an object. 10330b57cec5SDimitry Andric case OMF_init: 10340b57cec5SDimitry Andric if (!isInstanceMethod() || !getReturnType()->isObjCObjectPointerType()) 10350b57cec5SDimitry Andric family = OMF_None; 10360b57cec5SDimitry Andric break; 10370b57cec5SDimitry Andric 10380b57cec5SDimitry Andric // alloc/copy/new have a conventional meaning for both class and 10390b57cec5SDimitry Andric // instance methods, but they require an object return. 10400b57cec5SDimitry Andric case OMF_alloc: 10410b57cec5SDimitry Andric case OMF_copy: 10420b57cec5SDimitry Andric case OMF_mutableCopy: 10430b57cec5SDimitry Andric case OMF_new: 10440b57cec5SDimitry Andric if (!getReturnType()->isObjCObjectPointerType()) 10450b57cec5SDimitry Andric family = OMF_None; 10460b57cec5SDimitry Andric break; 10470b57cec5SDimitry Andric 10480b57cec5SDimitry Andric // These selectors have a conventional meaning only for instance methods. 10490b57cec5SDimitry Andric case OMF_dealloc: 10500b57cec5SDimitry Andric case OMF_finalize: 10510b57cec5SDimitry Andric case OMF_retain: 10520b57cec5SDimitry Andric case OMF_release: 10530b57cec5SDimitry Andric case OMF_autorelease: 10540b57cec5SDimitry Andric case OMF_retainCount: 10550b57cec5SDimitry Andric case OMF_self: 10560b57cec5SDimitry Andric if (!isInstanceMethod()) 10570b57cec5SDimitry Andric family = OMF_None; 10580b57cec5SDimitry Andric break; 10590b57cec5SDimitry Andric 10600b57cec5SDimitry Andric case OMF_initialize: 10610b57cec5SDimitry Andric if (isInstanceMethod() || !getReturnType()->isVoidType()) 10620b57cec5SDimitry Andric family = OMF_None; 10630b57cec5SDimitry Andric break; 10640b57cec5SDimitry Andric 10650b57cec5SDimitry Andric case OMF_performSelector: 10660b57cec5SDimitry Andric if (!isInstanceMethod() || !getReturnType()->isObjCIdType()) 10670b57cec5SDimitry Andric family = OMF_None; 10680b57cec5SDimitry Andric else { 10690b57cec5SDimitry Andric unsigned noParams = param_size(); 10700b57cec5SDimitry Andric if (noParams < 1 || noParams > 3) 10710b57cec5SDimitry Andric family = OMF_None; 10720b57cec5SDimitry Andric else { 10730b57cec5SDimitry Andric ObjCMethodDecl::param_type_iterator it = param_type_begin(); 10740b57cec5SDimitry Andric QualType ArgT = (*it); 10750b57cec5SDimitry Andric if (!ArgT->isObjCSelType()) { 10760b57cec5SDimitry Andric family = OMF_None; 10770b57cec5SDimitry Andric break; 10780b57cec5SDimitry Andric } 10790b57cec5SDimitry Andric while (--noParams) { 10800b57cec5SDimitry Andric it++; 10810b57cec5SDimitry Andric ArgT = (*it); 10820b57cec5SDimitry Andric if (!ArgT->isObjCIdType()) { 10830b57cec5SDimitry Andric family = OMF_None; 10840b57cec5SDimitry Andric break; 10850b57cec5SDimitry Andric } 10860b57cec5SDimitry Andric } 10870b57cec5SDimitry Andric } 10880b57cec5SDimitry Andric } 10890b57cec5SDimitry Andric break; 10900b57cec5SDimitry Andric 10910b57cec5SDimitry Andric } 10920b57cec5SDimitry Andric 10930b57cec5SDimitry Andric // Cache the result. 10940b57cec5SDimitry Andric ObjCMethodDeclBits.Family = family; 10950b57cec5SDimitry Andric return family; 10960b57cec5SDimitry Andric } 10970b57cec5SDimitry Andric 10980b57cec5SDimitry Andric QualType ObjCMethodDecl::getSelfType(ASTContext &Context, 10990b57cec5SDimitry Andric const ObjCInterfaceDecl *OID, 11000b57cec5SDimitry Andric bool &selfIsPseudoStrong, 1101480093f4SDimitry Andric bool &selfIsConsumed) const { 11020b57cec5SDimitry Andric QualType selfTy; 11030b57cec5SDimitry Andric selfIsPseudoStrong = false; 11040b57cec5SDimitry Andric selfIsConsumed = false; 11050b57cec5SDimitry Andric if (isInstanceMethod()) { 11060b57cec5SDimitry Andric // There may be no interface context due to error in declaration 11070b57cec5SDimitry Andric // of the interface (which has been reported). Recover gracefully. 11080b57cec5SDimitry Andric if (OID) { 11090b57cec5SDimitry Andric selfTy = Context.getObjCInterfaceType(OID); 11100b57cec5SDimitry Andric selfTy = Context.getObjCObjectPointerType(selfTy); 11110b57cec5SDimitry Andric } else { 11120b57cec5SDimitry Andric selfTy = Context.getObjCIdType(); 11130b57cec5SDimitry Andric } 11140b57cec5SDimitry Andric } else // we have a factory method. 11150b57cec5SDimitry Andric selfTy = Context.getObjCClassType(); 11160b57cec5SDimitry Andric 11170b57cec5SDimitry Andric if (Context.getLangOpts().ObjCAutoRefCount) { 11180b57cec5SDimitry Andric if (isInstanceMethod()) { 11190b57cec5SDimitry Andric selfIsConsumed = hasAttr<NSConsumesSelfAttr>(); 11200b57cec5SDimitry Andric 11210b57cec5SDimitry Andric // 'self' is always __strong. It's actually pseudo-strong except 11220b57cec5SDimitry Andric // in init methods (or methods labeled ns_consumes_self), though. 11230b57cec5SDimitry Andric Qualifiers qs; 11240b57cec5SDimitry Andric qs.setObjCLifetime(Qualifiers::OCL_Strong); 11250b57cec5SDimitry Andric selfTy = Context.getQualifiedType(selfTy, qs); 11260b57cec5SDimitry Andric 11270b57cec5SDimitry Andric // In addition, 'self' is const unless this is an init method. 11280b57cec5SDimitry Andric if (getMethodFamily() != OMF_init && !selfIsConsumed) { 11290b57cec5SDimitry Andric selfTy = selfTy.withConst(); 11300b57cec5SDimitry Andric selfIsPseudoStrong = true; 11310b57cec5SDimitry Andric } 11320b57cec5SDimitry Andric } 11330b57cec5SDimitry Andric else { 11340b57cec5SDimitry Andric assert(isClassMethod()); 11350b57cec5SDimitry Andric // 'self' is always const in class methods. 11360b57cec5SDimitry Andric selfTy = selfTy.withConst(); 11370b57cec5SDimitry Andric selfIsPseudoStrong = true; 11380b57cec5SDimitry Andric } 11390b57cec5SDimitry Andric } 11400b57cec5SDimitry Andric return selfTy; 11410b57cec5SDimitry Andric } 11420b57cec5SDimitry Andric 11430b57cec5SDimitry Andric void ObjCMethodDecl::createImplicitParams(ASTContext &Context, 11440b57cec5SDimitry Andric const ObjCInterfaceDecl *OID) { 11450b57cec5SDimitry Andric bool selfIsPseudoStrong, selfIsConsumed; 11460b57cec5SDimitry Andric QualType selfTy = 11470b57cec5SDimitry Andric getSelfType(Context, OID, selfIsPseudoStrong, selfIsConsumed); 11480b57cec5SDimitry Andric auto *Self = ImplicitParamDecl::Create(Context, this, SourceLocation(), 11490b57cec5SDimitry Andric &Context.Idents.get("self"), selfTy, 11500b57cec5SDimitry Andric ImplicitParamDecl::ObjCSelf); 11510b57cec5SDimitry Andric setSelfDecl(Self); 11520b57cec5SDimitry Andric 11530b57cec5SDimitry Andric if (selfIsConsumed) 11540b57cec5SDimitry Andric Self->addAttr(NSConsumedAttr::CreateImplicit(Context)); 11550b57cec5SDimitry Andric 11560b57cec5SDimitry Andric if (selfIsPseudoStrong) 11570b57cec5SDimitry Andric Self->setARCPseudoStrong(true); 11580b57cec5SDimitry Andric 11590b57cec5SDimitry Andric setCmdDecl(ImplicitParamDecl::Create( 11600b57cec5SDimitry Andric Context, this, SourceLocation(), &Context.Idents.get("_cmd"), 11610b57cec5SDimitry Andric Context.getObjCSelType(), ImplicitParamDecl::ObjCCmd)); 11620b57cec5SDimitry Andric } 11630b57cec5SDimitry Andric 11640b57cec5SDimitry Andric ObjCInterfaceDecl *ObjCMethodDecl::getClassInterface() { 11650b57cec5SDimitry Andric if (auto *ID = dyn_cast<ObjCInterfaceDecl>(getDeclContext())) 11660b57cec5SDimitry Andric return ID; 11670b57cec5SDimitry Andric if (auto *CD = dyn_cast<ObjCCategoryDecl>(getDeclContext())) 11680b57cec5SDimitry Andric return CD->getClassInterface(); 11690b57cec5SDimitry Andric if (auto *IMD = dyn_cast<ObjCImplDecl>(getDeclContext())) 11700b57cec5SDimitry Andric return IMD->getClassInterface(); 11710b57cec5SDimitry Andric if (isa<ObjCProtocolDecl>(getDeclContext())) 11720b57cec5SDimitry Andric return nullptr; 11730b57cec5SDimitry Andric llvm_unreachable("unknown method context"); 11740b57cec5SDimitry Andric } 11750b57cec5SDimitry Andric 1176e8d8bef9SDimitry Andric ObjCCategoryDecl *ObjCMethodDecl::getCategory() { 1177e8d8bef9SDimitry Andric if (auto *CD = dyn_cast<ObjCCategoryDecl>(getDeclContext())) 1178e8d8bef9SDimitry Andric return CD; 1179e8d8bef9SDimitry Andric if (auto *IMD = dyn_cast<ObjCCategoryImplDecl>(getDeclContext())) 1180e8d8bef9SDimitry Andric return IMD->getCategoryDecl(); 1181e8d8bef9SDimitry Andric return nullptr; 1182e8d8bef9SDimitry Andric } 1183e8d8bef9SDimitry Andric 11840b57cec5SDimitry Andric SourceRange ObjCMethodDecl::getReturnTypeSourceRange() const { 11850b57cec5SDimitry Andric const auto *TSI = getReturnTypeSourceInfo(); 11860b57cec5SDimitry Andric if (TSI) 11870b57cec5SDimitry Andric return TSI->getTypeLoc().getSourceRange(); 11880b57cec5SDimitry Andric return SourceRange(); 11890b57cec5SDimitry Andric } 11900b57cec5SDimitry Andric 11910b57cec5SDimitry Andric QualType ObjCMethodDecl::getSendResultType() const { 11920b57cec5SDimitry Andric ASTContext &Ctx = getASTContext(); 11930b57cec5SDimitry Andric return getReturnType().getNonLValueExprType(Ctx) 11940b57cec5SDimitry Andric .substObjCTypeArgs(Ctx, {}, ObjCSubstitutionContext::Result); 11950b57cec5SDimitry Andric } 11960b57cec5SDimitry Andric 11970b57cec5SDimitry Andric QualType ObjCMethodDecl::getSendResultType(QualType receiverType) const { 11980b57cec5SDimitry Andric // FIXME: Handle related result types here. 11990b57cec5SDimitry Andric 12000b57cec5SDimitry Andric return getReturnType().getNonLValueExprType(getASTContext()) 12010b57cec5SDimitry Andric .substObjCMemberType(receiverType, getDeclContext(), 12020b57cec5SDimitry Andric ObjCSubstitutionContext::Result); 12030b57cec5SDimitry Andric } 12040b57cec5SDimitry Andric 12050b57cec5SDimitry Andric static void CollectOverriddenMethodsRecurse(const ObjCContainerDecl *Container, 12060b57cec5SDimitry Andric const ObjCMethodDecl *Method, 12070b57cec5SDimitry Andric SmallVectorImpl<const ObjCMethodDecl *> &Methods, 12080b57cec5SDimitry Andric bool MovedToSuper) { 12090b57cec5SDimitry Andric if (!Container) 12100b57cec5SDimitry Andric return; 12110b57cec5SDimitry Andric 12120b57cec5SDimitry Andric // In categories look for overridden methods from protocols. A method from 12130b57cec5SDimitry Andric // category is not "overridden" since it is considered as the "same" method 12140b57cec5SDimitry Andric // (same USR) as the one from the interface. 12150b57cec5SDimitry Andric if (const auto *Category = dyn_cast<ObjCCategoryDecl>(Container)) { 12160b57cec5SDimitry Andric // Check whether we have a matching method at this category but only if we 12170b57cec5SDimitry Andric // are at the super class level. 12180b57cec5SDimitry Andric if (MovedToSuper) 12190b57cec5SDimitry Andric if (ObjCMethodDecl * 12200b57cec5SDimitry Andric Overridden = Container->getMethod(Method->getSelector(), 12210b57cec5SDimitry Andric Method->isInstanceMethod(), 12220b57cec5SDimitry Andric /*AllowHidden=*/true)) 12230b57cec5SDimitry Andric if (Method != Overridden) { 12240b57cec5SDimitry Andric // We found an override at this category; there is no need to look 12250b57cec5SDimitry Andric // into its protocols. 12260b57cec5SDimitry Andric Methods.push_back(Overridden); 12270b57cec5SDimitry Andric return; 12280b57cec5SDimitry Andric } 12290b57cec5SDimitry Andric 12300b57cec5SDimitry Andric for (const auto *P : Category->protocols()) 12310b57cec5SDimitry Andric CollectOverriddenMethodsRecurse(P, Method, Methods, MovedToSuper); 12320b57cec5SDimitry Andric return; 12330b57cec5SDimitry Andric } 12340b57cec5SDimitry Andric 12350b57cec5SDimitry Andric // Check whether we have a matching method at this level. 12360b57cec5SDimitry Andric if (const ObjCMethodDecl * 12370b57cec5SDimitry Andric Overridden = Container->getMethod(Method->getSelector(), 12380b57cec5SDimitry Andric Method->isInstanceMethod(), 12390b57cec5SDimitry Andric /*AllowHidden=*/true)) 12400b57cec5SDimitry Andric if (Method != Overridden) { 12410b57cec5SDimitry Andric // We found an override at this level; there is no need to look 12420b57cec5SDimitry Andric // into other protocols or categories. 12430b57cec5SDimitry Andric Methods.push_back(Overridden); 12440b57cec5SDimitry Andric return; 12450b57cec5SDimitry Andric } 12460b57cec5SDimitry Andric 12470b57cec5SDimitry Andric if (const auto *Protocol = dyn_cast<ObjCProtocolDecl>(Container)){ 12480b57cec5SDimitry Andric for (const auto *P : Protocol->protocols()) 12490b57cec5SDimitry Andric CollectOverriddenMethodsRecurse(P, Method, Methods, MovedToSuper); 12500b57cec5SDimitry Andric } 12510b57cec5SDimitry Andric 12520b57cec5SDimitry Andric if (const auto *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) { 12530b57cec5SDimitry Andric for (const auto *P : Interface->protocols()) 12540b57cec5SDimitry Andric CollectOverriddenMethodsRecurse(P, Method, Methods, MovedToSuper); 12550b57cec5SDimitry Andric 12560b57cec5SDimitry Andric for (const auto *Cat : Interface->known_categories()) 12570b57cec5SDimitry Andric CollectOverriddenMethodsRecurse(Cat, Method, Methods, MovedToSuper); 12580b57cec5SDimitry Andric 12590b57cec5SDimitry Andric if (const ObjCInterfaceDecl *Super = Interface->getSuperClass()) 12600b57cec5SDimitry Andric return CollectOverriddenMethodsRecurse(Super, Method, Methods, 12610b57cec5SDimitry Andric /*MovedToSuper=*/true); 12620b57cec5SDimitry Andric } 12630b57cec5SDimitry Andric } 12640b57cec5SDimitry Andric 12650b57cec5SDimitry Andric static inline void CollectOverriddenMethods(const ObjCContainerDecl *Container, 12660b57cec5SDimitry Andric const ObjCMethodDecl *Method, 12670b57cec5SDimitry Andric SmallVectorImpl<const ObjCMethodDecl *> &Methods) { 12680b57cec5SDimitry Andric CollectOverriddenMethodsRecurse(Container, Method, Methods, 12690b57cec5SDimitry Andric /*MovedToSuper=*/false); 12700b57cec5SDimitry Andric } 12710b57cec5SDimitry Andric 12720b57cec5SDimitry Andric static void collectOverriddenMethodsSlow(const ObjCMethodDecl *Method, 12730b57cec5SDimitry Andric SmallVectorImpl<const ObjCMethodDecl *> &overridden) { 12740b57cec5SDimitry Andric assert(Method->isOverriding()); 12750b57cec5SDimitry Andric 12760b57cec5SDimitry Andric if (const auto *ProtD = 12770b57cec5SDimitry Andric dyn_cast<ObjCProtocolDecl>(Method->getDeclContext())) { 12780b57cec5SDimitry Andric CollectOverriddenMethods(ProtD, Method, overridden); 12790b57cec5SDimitry Andric 12800b57cec5SDimitry Andric } else if (const auto *IMD = 12810b57cec5SDimitry Andric dyn_cast<ObjCImplDecl>(Method->getDeclContext())) { 12820b57cec5SDimitry Andric const ObjCInterfaceDecl *ID = IMD->getClassInterface(); 12830b57cec5SDimitry Andric if (!ID) 12840b57cec5SDimitry Andric return; 12850b57cec5SDimitry Andric // Start searching for overridden methods using the method from the 12860b57cec5SDimitry Andric // interface as starting point. 12870b57cec5SDimitry Andric if (const ObjCMethodDecl *IFaceMeth = ID->getMethod(Method->getSelector(), 12880b57cec5SDimitry Andric Method->isInstanceMethod(), 12890b57cec5SDimitry Andric /*AllowHidden=*/true)) 12900b57cec5SDimitry Andric Method = IFaceMeth; 12910b57cec5SDimitry Andric CollectOverriddenMethods(ID, Method, overridden); 12920b57cec5SDimitry Andric 12930b57cec5SDimitry Andric } else if (const auto *CatD = 12940b57cec5SDimitry Andric dyn_cast<ObjCCategoryDecl>(Method->getDeclContext())) { 12950b57cec5SDimitry Andric const ObjCInterfaceDecl *ID = CatD->getClassInterface(); 12960b57cec5SDimitry Andric if (!ID) 12970b57cec5SDimitry Andric return; 12980b57cec5SDimitry Andric // Start searching for overridden methods using the method from the 12990b57cec5SDimitry Andric // interface as starting point. 13000b57cec5SDimitry Andric if (const ObjCMethodDecl *IFaceMeth = ID->getMethod(Method->getSelector(), 13010b57cec5SDimitry Andric Method->isInstanceMethod(), 13020b57cec5SDimitry Andric /*AllowHidden=*/true)) 13030b57cec5SDimitry Andric Method = IFaceMeth; 13040b57cec5SDimitry Andric CollectOverriddenMethods(ID, Method, overridden); 13050b57cec5SDimitry Andric 13060b57cec5SDimitry Andric } else { 13070b57cec5SDimitry Andric CollectOverriddenMethods( 13080b57cec5SDimitry Andric dyn_cast_or_null<ObjCContainerDecl>(Method->getDeclContext()), 13090b57cec5SDimitry Andric Method, overridden); 13100b57cec5SDimitry Andric } 13110b57cec5SDimitry Andric } 13120b57cec5SDimitry Andric 13130b57cec5SDimitry Andric void ObjCMethodDecl::getOverriddenMethods( 13140b57cec5SDimitry Andric SmallVectorImpl<const ObjCMethodDecl *> &Overridden) const { 13150b57cec5SDimitry Andric const ObjCMethodDecl *Method = this; 13160b57cec5SDimitry Andric 13170b57cec5SDimitry Andric if (Method->isRedeclaration()) { 1318e8d8bef9SDimitry Andric Method = cast<ObjCContainerDecl>(Method->getDeclContext()) 1319e8d8bef9SDimitry Andric ->getMethod(Method->getSelector(), Method->isInstanceMethod(), 1320e8d8bef9SDimitry Andric /*AllowHidden=*/true); 13210b57cec5SDimitry Andric } 13220b57cec5SDimitry Andric 13230b57cec5SDimitry Andric if (Method->isOverriding()) { 13240b57cec5SDimitry Andric collectOverriddenMethodsSlow(Method, Overridden); 13250b57cec5SDimitry Andric assert(!Overridden.empty() && 13260b57cec5SDimitry Andric "ObjCMethodDecl's overriding bit is not as expected"); 13270b57cec5SDimitry Andric } 13280b57cec5SDimitry Andric } 13290b57cec5SDimitry Andric 13300b57cec5SDimitry Andric const ObjCPropertyDecl * 13310b57cec5SDimitry Andric ObjCMethodDecl::findPropertyDecl(bool CheckOverrides) const { 13320b57cec5SDimitry Andric Selector Sel = getSelector(); 13330b57cec5SDimitry Andric unsigned NumArgs = Sel.getNumArgs(); 13340b57cec5SDimitry Andric if (NumArgs > 1) 13350b57cec5SDimitry Andric return nullptr; 13360b57cec5SDimitry Andric 13370b57cec5SDimitry Andric if (isPropertyAccessor()) { 13380b57cec5SDimitry Andric const auto *Container = cast<ObjCContainerDecl>(getParent()); 1339480093f4SDimitry Andric // For accessor stubs, go back to the interface. 1340480093f4SDimitry Andric if (auto *ImplDecl = dyn_cast<ObjCImplDecl>(Container)) 1341480093f4SDimitry Andric if (isSynthesizedAccessorStub()) 1342480093f4SDimitry Andric Container = ImplDecl->getClassInterface(); 1343480093f4SDimitry Andric 13440b57cec5SDimitry Andric bool IsGetter = (NumArgs == 0); 13450b57cec5SDimitry Andric bool IsInstance = isInstanceMethod(); 13460b57cec5SDimitry Andric 13470b57cec5SDimitry Andric /// Local function that attempts to find a matching property within the 13480b57cec5SDimitry Andric /// given Objective-C container. 13490b57cec5SDimitry Andric auto findMatchingProperty = 13500b57cec5SDimitry Andric [&](const ObjCContainerDecl *Container) -> const ObjCPropertyDecl * { 13510b57cec5SDimitry Andric if (IsInstance) { 13520b57cec5SDimitry Andric for (const auto *I : Container->instance_properties()) { 13530b57cec5SDimitry Andric Selector NextSel = IsGetter ? I->getGetterName() 13540b57cec5SDimitry Andric : I->getSetterName(); 13550b57cec5SDimitry Andric if (NextSel == Sel) 13560b57cec5SDimitry Andric return I; 13570b57cec5SDimitry Andric } 13580b57cec5SDimitry Andric } else { 13590b57cec5SDimitry Andric for (const auto *I : Container->class_properties()) { 13600b57cec5SDimitry Andric Selector NextSel = IsGetter ? I->getGetterName() 13610b57cec5SDimitry Andric : I->getSetterName(); 13620b57cec5SDimitry Andric if (NextSel == Sel) 13630b57cec5SDimitry Andric return I; 13640b57cec5SDimitry Andric } 13650b57cec5SDimitry Andric } 13660b57cec5SDimitry Andric 13670b57cec5SDimitry Andric return nullptr; 13680b57cec5SDimitry Andric }; 13690b57cec5SDimitry Andric 13700b57cec5SDimitry Andric // Look in the container we were given. 13710b57cec5SDimitry Andric if (const auto *Found = findMatchingProperty(Container)) 13720b57cec5SDimitry Andric return Found; 13730b57cec5SDimitry Andric 13740b57cec5SDimitry Andric // If we're in a category or extension, look in the main class. 13750b57cec5SDimitry Andric const ObjCInterfaceDecl *ClassDecl = nullptr; 13760b57cec5SDimitry Andric if (const auto *Category = dyn_cast<ObjCCategoryDecl>(Container)) { 13770b57cec5SDimitry Andric ClassDecl = Category->getClassInterface(); 13780b57cec5SDimitry Andric if (const auto *Found = findMatchingProperty(ClassDecl)) 13790b57cec5SDimitry Andric return Found; 13800b57cec5SDimitry Andric } else { 13810b57cec5SDimitry Andric // Determine whether the container is a class. 13825ffd83dbSDimitry Andric ClassDecl = cast<ObjCInterfaceDecl>(Container); 13830b57cec5SDimitry Andric } 13845ffd83dbSDimitry Andric assert(ClassDecl && "Failed to find main class"); 13850b57cec5SDimitry Andric 13860b57cec5SDimitry Andric // If we have a class, check its visible extensions. 13870b57cec5SDimitry Andric for (const auto *Ext : ClassDecl->visible_extensions()) { 13880b57cec5SDimitry Andric if (Ext == Container) 13890b57cec5SDimitry Andric continue; 13900b57cec5SDimitry Andric if (const auto *Found = findMatchingProperty(Ext)) 13910b57cec5SDimitry Andric return Found; 13920b57cec5SDimitry Andric } 13930b57cec5SDimitry Andric 1394480093f4SDimitry Andric assert(isSynthesizedAccessorStub() && "expected an accessor stub"); 13955ffd83dbSDimitry Andric 1396480093f4SDimitry Andric for (const auto *Cat : ClassDecl->known_categories()) { 1397480093f4SDimitry Andric if (Cat == Container) 1398480093f4SDimitry Andric continue; 1399480093f4SDimitry Andric if (const auto *Found = findMatchingProperty(Cat)) 1400480093f4SDimitry Andric return Found; 1401480093f4SDimitry Andric } 1402480093f4SDimitry Andric 14030b57cec5SDimitry Andric llvm_unreachable("Marked as a property accessor but no property found!"); 14040b57cec5SDimitry Andric } 14050b57cec5SDimitry Andric 14060b57cec5SDimitry Andric if (!CheckOverrides) 14070b57cec5SDimitry Andric return nullptr; 14080b57cec5SDimitry Andric 14090b57cec5SDimitry Andric using OverridesTy = SmallVector<const ObjCMethodDecl *, 8>; 14100b57cec5SDimitry Andric 14110b57cec5SDimitry Andric OverridesTy Overrides; 14120b57cec5SDimitry Andric getOverriddenMethods(Overrides); 14130b57cec5SDimitry Andric for (const auto *Override : Overrides) 14140b57cec5SDimitry Andric if (const ObjCPropertyDecl *Prop = Override->findPropertyDecl(false)) 14150b57cec5SDimitry Andric return Prop; 14160b57cec5SDimitry Andric 14170b57cec5SDimitry Andric return nullptr; 14180b57cec5SDimitry Andric } 14190b57cec5SDimitry Andric 14200b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 14210b57cec5SDimitry Andric // ObjCTypeParamDecl 14220b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 14230b57cec5SDimitry Andric 14240b57cec5SDimitry Andric void ObjCTypeParamDecl::anchor() {} 14250b57cec5SDimitry Andric 14260b57cec5SDimitry Andric ObjCTypeParamDecl *ObjCTypeParamDecl::Create(ASTContext &ctx, DeclContext *dc, 14270b57cec5SDimitry Andric ObjCTypeParamVariance variance, 14280b57cec5SDimitry Andric SourceLocation varianceLoc, 14290b57cec5SDimitry Andric unsigned index, 14300b57cec5SDimitry Andric SourceLocation nameLoc, 14310b57cec5SDimitry Andric IdentifierInfo *name, 14320b57cec5SDimitry Andric SourceLocation colonLoc, 14330b57cec5SDimitry Andric TypeSourceInfo *boundInfo) { 14340b57cec5SDimitry Andric auto *TPDecl = 14350b57cec5SDimitry Andric new (ctx, dc) ObjCTypeParamDecl(ctx, dc, variance, varianceLoc, index, 14360b57cec5SDimitry Andric nameLoc, name, colonLoc, boundInfo); 14370b57cec5SDimitry Andric QualType TPType = ctx.getObjCTypeParamType(TPDecl, {}); 14380b57cec5SDimitry Andric TPDecl->setTypeForDecl(TPType.getTypePtr()); 14390b57cec5SDimitry Andric return TPDecl; 14400b57cec5SDimitry Andric } 14410b57cec5SDimitry Andric 14420b57cec5SDimitry Andric ObjCTypeParamDecl *ObjCTypeParamDecl::CreateDeserialized(ASTContext &ctx, 14430b57cec5SDimitry Andric unsigned ID) { 14440b57cec5SDimitry Andric return new (ctx, ID) ObjCTypeParamDecl(ctx, nullptr, 14450b57cec5SDimitry Andric ObjCTypeParamVariance::Invariant, 14460b57cec5SDimitry Andric SourceLocation(), 0, SourceLocation(), 14470b57cec5SDimitry Andric nullptr, SourceLocation(), nullptr); 14480b57cec5SDimitry Andric } 14490b57cec5SDimitry Andric 14500b57cec5SDimitry Andric SourceRange ObjCTypeParamDecl::getSourceRange() const { 14510b57cec5SDimitry Andric SourceLocation startLoc = VarianceLoc; 14520b57cec5SDimitry Andric if (startLoc.isInvalid()) 14530b57cec5SDimitry Andric startLoc = getLocation(); 14540b57cec5SDimitry Andric 14550b57cec5SDimitry Andric if (hasExplicitBound()) { 14560b57cec5SDimitry Andric return SourceRange(startLoc, 14570b57cec5SDimitry Andric getTypeSourceInfo()->getTypeLoc().getEndLoc()); 14580b57cec5SDimitry Andric } 14590b57cec5SDimitry Andric 14600b57cec5SDimitry Andric return SourceRange(startLoc); 14610b57cec5SDimitry Andric } 14620b57cec5SDimitry Andric 14630b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 14640b57cec5SDimitry Andric // ObjCTypeParamList 14650b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 14660b57cec5SDimitry Andric ObjCTypeParamList::ObjCTypeParamList(SourceLocation lAngleLoc, 14670b57cec5SDimitry Andric ArrayRef<ObjCTypeParamDecl *> typeParams, 14680b57cec5SDimitry Andric SourceLocation rAngleLoc) 1469e8d8bef9SDimitry Andric : Brackets(lAngleLoc, rAngleLoc), NumParams(typeParams.size()) { 14700b57cec5SDimitry Andric std::copy(typeParams.begin(), typeParams.end(), begin()); 14710b57cec5SDimitry Andric } 14720b57cec5SDimitry Andric 14730b57cec5SDimitry Andric ObjCTypeParamList *ObjCTypeParamList::create( 14740b57cec5SDimitry Andric ASTContext &ctx, 14750b57cec5SDimitry Andric SourceLocation lAngleLoc, 14760b57cec5SDimitry Andric ArrayRef<ObjCTypeParamDecl *> typeParams, 14770b57cec5SDimitry Andric SourceLocation rAngleLoc) { 14780b57cec5SDimitry Andric void *mem = 14790b57cec5SDimitry Andric ctx.Allocate(totalSizeToAlloc<ObjCTypeParamDecl *>(typeParams.size()), 14800b57cec5SDimitry Andric alignof(ObjCTypeParamList)); 14810b57cec5SDimitry Andric return new (mem) ObjCTypeParamList(lAngleLoc, typeParams, rAngleLoc); 14820b57cec5SDimitry Andric } 14830b57cec5SDimitry Andric 14840b57cec5SDimitry Andric void ObjCTypeParamList::gatherDefaultTypeArgs( 14850b57cec5SDimitry Andric SmallVectorImpl<QualType> &typeArgs) const { 14860b57cec5SDimitry Andric typeArgs.reserve(size()); 14870b57cec5SDimitry Andric for (auto typeParam : *this) 14880b57cec5SDimitry Andric typeArgs.push_back(typeParam->getUnderlyingType()); 14890b57cec5SDimitry Andric } 14900b57cec5SDimitry Andric 14910b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 14920b57cec5SDimitry Andric // ObjCInterfaceDecl 14930b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 14940b57cec5SDimitry Andric 14950b57cec5SDimitry Andric ObjCInterfaceDecl *ObjCInterfaceDecl::Create(const ASTContext &C, 14960b57cec5SDimitry Andric DeclContext *DC, 14970b57cec5SDimitry Andric SourceLocation atLoc, 14980b57cec5SDimitry Andric IdentifierInfo *Id, 14990b57cec5SDimitry Andric ObjCTypeParamList *typeParamList, 15000b57cec5SDimitry Andric ObjCInterfaceDecl *PrevDecl, 15010b57cec5SDimitry Andric SourceLocation ClassLoc, 15020b57cec5SDimitry Andric bool isInternal){ 15030b57cec5SDimitry Andric auto *Result = new (C, DC) 15040b57cec5SDimitry Andric ObjCInterfaceDecl(C, DC, atLoc, Id, typeParamList, ClassLoc, PrevDecl, 15050b57cec5SDimitry Andric isInternal); 15060b57cec5SDimitry Andric Result->Data.setInt(!C.getLangOpts().Modules); 15070b57cec5SDimitry Andric C.getObjCInterfaceType(Result, PrevDecl); 15080b57cec5SDimitry Andric return Result; 15090b57cec5SDimitry Andric } 15100b57cec5SDimitry Andric 15110b57cec5SDimitry Andric ObjCInterfaceDecl *ObjCInterfaceDecl::CreateDeserialized(const ASTContext &C, 15120b57cec5SDimitry Andric unsigned ID) { 15130b57cec5SDimitry Andric auto *Result = new (C, ID) 15140b57cec5SDimitry Andric ObjCInterfaceDecl(C, nullptr, SourceLocation(), nullptr, nullptr, 15150b57cec5SDimitry Andric SourceLocation(), nullptr, false); 15160b57cec5SDimitry Andric Result->Data.setInt(!C.getLangOpts().Modules); 15170b57cec5SDimitry Andric return Result; 15180b57cec5SDimitry Andric } 15190b57cec5SDimitry Andric 15200b57cec5SDimitry Andric ObjCInterfaceDecl::ObjCInterfaceDecl(const ASTContext &C, DeclContext *DC, 15210b57cec5SDimitry Andric SourceLocation AtLoc, IdentifierInfo *Id, 15220b57cec5SDimitry Andric ObjCTypeParamList *typeParamList, 15230b57cec5SDimitry Andric SourceLocation CLoc, 15240b57cec5SDimitry Andric ObjCInterfaceDecl *PrevDecl, 15250b57cec5SDimitry Andric bool IsInternal) 15260b57cec5SDimitry Andric : ObjCContainerDecl(ObjCInterface, DC, Id, CLoc, AtLoc), 15270b57cec5SDimitry Andric redeclarable_base(C) { 15280b57cec5SDimitry Andric setPreviousDecl(PrevDecl); 15290b57cec5SDimitry Andric 15300b57cec5SDimitry Andric // Copy the 'data' pointer over. 15310b57cec5SDimitry Andric if (PrevDecl) 15320b57cec5SDimitry Andric Data = PrevDecl->Data; 15330b57cec5SDimitry Andric 15340b57cec5SDimitry Andric setImplicit(IsInternal); 15350b57cec5SDimitry Andric 15360b57cec5SDimitry Andric setTypeParamList(typeParamList); 15370b57cec5SDimitry Andric } 15380b57cec5SDimitry Andric 15390b57cec5SDimitry Andric void ObjCInterfaceDecl::LoadExternalDefinition() const { 15400b57cec5SDimitry Andric assert(data().ExternallyCompleted && "Class is not externally completed"); 15410b57cec5SDimitry Andric data().ExternallyCompleted = false; 15420b57cec5SDimitry Andric getASTContext().getExternalSource()->CompleteType( 15430b57cec5SDimitry Andric const_cast<ObjCInterfaceDecl *>(this)); 15440b57cec5SDimitry Andric } 15450b57cec5SDimitry Andric 15460b57cec5SDimitry Andric void ObjCInterfaceDecl::setExternallyCompleted() { 15470b57cec5SDimitry Andric assert(getASTContext().getExternalSource() && 15480b57cec5SDimitry Andric "Class can't be externally completed without an external source"); 15490b57cec5SDimitry Andric assert(hasDefinition() && 15500b57cec5SDimitry Andric "Forward declarations can't be externally completed"); 15510b57cec5SDimitry Andric data().ExternallyCompleted = true; 15520b57cec5SDimitry Andric } 15530b57cec5SDimitry Andric 15540b57cec5SDimitry Andric void ObjCInterfaceDecl::setHasDesignatedInitializers() { 15550b57cec5SDimitry Andric // Check for a complete definition and recover if not so. 15560b57cec5SDimitry Andric if (!isThisDeclarationADefinition()) 15570b57cec5SDimitry Andric return; 15580b57cec5SDimitry Andric data().HasDesignatedInitializers = true; 15590b57cec5SDimitry Andric } 15600b57cec5SDimitry Andric 15610b57cec5SDimitry Andric bool ObjCInterfaceDecl::hasDesignatedInitializers() const { 15620b57cec5SDimitry Andric // Check for a complete definition and recover if not so. 15630b57cec5SDimitry Andric if (!isThisDeclarationADefinition()) 15640b57cec5SDimitry Andric return false; 15650b57cec5SDimitry Andric if (data().ExternallyCompleted) 15660b57cec5SDimitry Andric LoadExternalDefinition(); 15670b57cec5SDimitry Andric 15680b57cec5SDimitry Andric return data().HasDesignatedInitializers; 15690b57cec5SDimitry Andric } 15700b57cec5SDimitry Andric 15710b57cec5SDimitry Andric StringRef 15720b57cec5SDimitry Andric ObjCInterfaceDecl::getObjCRuntimeNameAsString() const { 15730b57cec5SDimitry Andric if (const auto *ObjCRTName = getAttr<ObjCRuntimeNameAttr>()) 15740b57cec5SDimitry Andric return ObjCRTName->getMetadataName(); 15750b57cec5SDimitry Andric 15760b57cec5SDimitry Andric return getName(); 15770b57cec5SDimitry Andric } 15780b57cec5SDimitry Andric 15790b57cec5SDimitry Andric StringRef 15800b57cec5SDimitry Andric ObjCImplementationDecl::getObjCRuntimeNameAsString() const { 15810b57cec5SDimitry Andric if (ObjCInterfaceDecl *ID = 15820b57cec5SDimitry Andric const_cast<ObjCImplementationDecl*>(this)->getClassInterface()) 15830b57cec5SDimitry Andric return ID->getObjCRuntimeNameAsString(); 15840b57cec5SDimitry Andric 15850b57cec5SDimitry Andric return getName(); 15860b57cec5SDimitry Andric } 15870b57cec5SDimitry Andric 15880b57cec5SDimitry Andric ObjCImplementationDecl *ObjCInterfaceDecl::getImplementation() const { 15890b57cec5SDimitry Andric if (const ObjCInterfaceDecl *Def = getDefinition()) { 15900b57cec5SDimitry Andric if (data().ExternallyCompleted) 15910b57cec5SDimitry Andric LoadExternalDefinition(); 15920b57cec5SDimitry Andric 15930b57cec5SDimitry Andric return getASTContext().getObjCImplementation( 15940b57cec5SDimitry Andric const_cast<ObjCInterfaceDecl*>(Def)); 15950b57cec5SDimitry Andric } 15960b57cec5SDimitry Andric 15970b57cec5SDimitry Andric // FIXME: Should make sure no callers ever do this. 15980b57cec5SDimitry Andric return nullptr; 15990b57cec5SDimitry Andric } 16000b57cec5SDimitry Andric 16010b57cec5SDimitry Andric void ObjCInterfaceDecl::setImplementation(ObjCImplementationDecl *ImplD) { 16020b57cec5SDimitry Andric getASTContext().setObjCImplementation(getDefinition(), ImplD); 16030b57cec5SDimitry Andric } 16040b57cec5SDimitry Andric 16050b57cec5SDimitry Andric namespace { 16060b57cec5SDimitry Andric 16070b57cec5SDimitry Andric struct SynthesizeIvarChunk { 16080b57cec5SDimitry Andric uint64_t Size; 16090b57cec5SDimitry Andric ObjCIvarDecl *Ivar; 16100b57cec5SDimitry Andric 16110b57cec5SDimitry Andric SynthesizeIvarChunk(uint64_t size, ObjCIvarDecl *ivar) 16120b57cec5SDimitry Andric : Size(size), Ivar(ivar) {} 16130b57cec5SDimitry Andric }; 16140b57cec5SDimitry Andric 16150b57cec5SDimitry Andric bool operator<(const SynthesizeIvarChunk & LHS, 16160b57cec5SDimitry Andric const SynthesizeIvarChunk &RHS) { 16170b57cec5SDimitry Andric return LHS.Size < RHS.Size; 16180b57cec5SDimitry Andric } 16190b57cec5SDimitry Andric 16200b57cec5SDimitry Andric } // namespace 16210b57cec5SDimitry Andric 16220b57cec5SDimitry Andric /// all_declared_ivar_begin - return first ivar declared in this class, 16230b57cec5SDimitry Andric /// its extensions and its implementation. Lazily build the list on first 16240b57cec5SDimitry Andric /// access. 16250b57cec5SDimitry Andric /// 16260b57cec5SDimitry Andric /// Caveat: The list returned by this method reflects the current 16270b57cec5SDimitry Andric /// state of the parser. The cache will be updated for every ivar 16280b57cec5SDimitry Andric /// added by an extension or the implementation when they are 16290b57cec5SDimitry Andric /// encountered. 16300b57cec5SDimitry Andric /// See also ObjCIvarDecl::Create(). 16310b57cec5SDimitry Andric ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() { 16320b57cec5SDimitry Andric // FIXME: Should make sure no callers ever do this. 16330b57cec5SDimitry Andric if (!hasDefinition()) 16340b57cec5SDimitry Andric return nullptr; 16350b57cec5SDimitry Andric 16360b57cec5SDimitry Andric ObjCIvarDecl *curIvar = nullptr; 16370b57cec5SDimitry Andric if (!data().IvarList) { 16380b57cec5SDimitry Andric if (!ivar_empty()) { 16390b57cec5SDimitry Andric ObjCInterfaceDecl::ivar_iterator I = ivar_begin(), E = ivar_end(); 16400b57cec5SDimitry Andric data().IvarList = *I; ++I; 16410b57cec5SDimitry Andric for (curIvar = data().IvarList; I != E; curIvar = *I, ++I) 16420b57cec5SDimitry Andric curIvar->setNextIvar(*I); 16430b57cec5SDimitry Andric } 16440b57cec5SDimitry Andric 16450b57cec5SDimitry Andric for (const auto *Ext : known_extensions()) { 16460b57cec5SDimitry Andric if (!Ext->ivar_empty()) { 16470b57cec5SDimitry Andric ObjCCategoryDecl::ivar_iterator 16480b57cec5SDimitry Andric I = Ext->ivar_begin(), 16490b57cec5SDimitry Andric E = Ext->ivar_end(); 16500b57cec5SDimitry Andric if (!data().IvarList) { 16510b57cec5SDimitry Andric data().IvarList = *I; ++I; 16520b57cec5SDimitry Andric curIvar = data().IvarList; 16530b57cec5SDimitry Andric } 16540b57cec5SDimitry Andric for ( ;I != E; curIvar = *I, ++I) 16550b57cec5SDimitry Andric curIvar->setNextIvar(*I); 16560b57cec5SDimitry Andric } 16570b57cec5SDimitry Andric } 16580b57cec5SDimitry Andric data().IvarListMissingImplementation = true; 16590b57cec5SDimitry Andric } 16600b57cec5SDimitry Andric 16610b57cec5SDimitry Andric // cached and complete! 16620b57cec5SDimitry Andric if (!data().IvarListMissingImplementation) 16630b57cec5SDimitry Andric return data().IvarList; 16640b57cec5SDimitry Andric 16650b57cec5SDimitry Andric if (ObjCImplementationDecl *ImplDecl = getImplementation()) { 16660b57cec5SDimitry Andric data().IvarListMissingImplementation = false; 16670b57cec5SDimitry Andric if (!ImplDecl->ivar_empty()) { 16680b57cec5SDimitry Andric SmallVector<SynthesizeIvarChunk, 16> layout; 16690b57cec5SDimitry Andric for (auto *IV : ImplDecl->ivars()) { 16700b57cec5SDimitry Andric if (IV->getSynthesize() && !IV->isInvalidDecl()) { 16710b57cec5SDimitry Andric layout.push_back(SynthesizeIvarChunk( 16720b57cec5SDimitry Andric IV->getASTContext().getTypeSize(IV->getType()), IV)); 16730b57cec5SDimitry Andric continue; 16740b57cec5SDimitry Andric } 16750b57cec5SDimitry Andric if (!data().IvarList) 16760b57cec5SDimitry Andric data().IvarList = IV; 16770b57cec5SDimitry Andric else 16780b57cec5SDimitry Andric curIvar->setNextIvar(IV); 16790b57cec5SDimitry Andric curIvar = IV; 16800b57cec5SDimitry Andric } 16810b57cec5SDimitry Andric 16820b57cec5SDimitry Andric if (!layout.empty()) { 16830b57cec5SDimitry Andric // Order synthesized ivars by their size. 16840b57cec5SDimitry Andric llvm::stable_sort(layout); 16850b57cec5SDimitry Andric unsigned Ix = 0, EIx = layout.size(); 16860b57cec5SDimitry Andric if (!data().IvarList) { 16870b57cec5SDimitry Andric data().IvarList = layout[0].Ivar; Ix++; 16880b57cec5SDimitry Andric curIvar = data().IvarList; 16890b57cec5SDimitry Andric } 16900b57cec5SDimitry Andric for ( ; Ix != EIx; curIvar = layout[Ix].Ivar, Ix++) 16910b57cec5SDimitry Andric curIvar->setNextIvar(layout[Ix].Ivar); 16920b57cec5SDimitry Andric } 16930b57cec5SDimitry Andric } 16940b57cec5SDimitry Andric } 16950b57cec5SDimitry Andric return data().IvarList; 16960b57cec5SDimitry Andric } 16970b57cec5SDimitry Andric 16980b57cec5SDimitry Andric /// FindCategoryDeclaration - Finds category declaration in the list of 16990b57cec5SDimitry Andric /// categories for this class and returns it. Name of the category is passed 17000b57cec5SDimitry Andric /// in 'CategoryId'. If category not found, return 0; 17010b57cec5SDimitry Andric /// 17020b57cec5SDimitry Andric ObjCCategoryDecl * 17030b57cec5SDimitry Andric ObjCInterfaceDecl::FindCategoryDeclaration(IdentifierInfo *CategoryId) const { 17040b57cec5SDimitry Andric // FIXME: Should make sure no callers ever do this. 17050b57cec5SDimitry Andric if (!hasDefinition()) 17060b57cec5SDimitry Andric return nullptr; 17070b57cec5SDimitry Andric 17080b57cec5SDimitry Andric if (data().ExternallyCompleted) 17090b57cec5SDimitry Andric LoadExternalDefinition(); 17100b57cec5SDimitry Andric 17110b57cec5SDimitry Andric for (auto *Cat : visible_categories()) 17120b57cec5SDimitry Andric if (Cat->getIdentifier() == CategoryId) 17130b57cec5SDimitry Andric return Cat; 17140b57cec5SDimitry Andric 17150b57cec5SDimitry Andric return nullptr; 17160b57cec5SDimitry Andric } 17170b57cec5SDimitry Andric 17180b57cec5SDimitry Andric ObjCMethodDecl * 17190b57cec5SDimitry Andric ObjCInterfaceDecl::getCategoryInstanceMethod(Selector Sel) const { 17200b57cec5SDimitry Andric for (const auto *Cat : visible_categories()) { 17210b57cec5SDimitry Andric if (ObjCCategoryImplDecl *Impl = Cat->getImplementation()) 17220b57cec5SDimitry Andric if (ObjCMethodDecl *MD = Impl->getInstanceMethod(Sel)) 17230b57cec5SDimitry Andric return MD; 17240b57cec5SDimitry Andric } 17250b57cec5SDimitry Andric 17260b57cec5SDimitry Andric return nullptr; 17270b57cec5SDimitry Andric } 17280b57cec5SDimitry Andric 17290b57cec5SDimitry Andric ObjCMethodDecl *ObjCInterfaceDecl::getCategoryClassMethod(Selector Sel) const { 17300b57cec5SDimitry Andric for (const auto *Cat : visible_categories()) { 17310b57cec5SDimitry Andric if (ObjCCategoryImplDecl *Impl = Cat->getImplementation()) 17320b57cec5SDimitry Andric if (ObjCMethodDecl *MD = Impl->getClassMethod(Sel)) 17330b57cec5SDimitry Andric return MD; 17340b57cec5SDimitry Andric } 17350b57cec5SDimitry Andric 17360b57cec5SDimitry Andric return nullptr; 17370b57cec5SDimitry Andric } 17380b57cec5SDimitry Andric 17390b57cec5SDimitry Andric /// ClassImplementsProtocol - Checks that 'lProto' protocol 17400b57cec5SDimitry Andric /// has been implemented in IDecl class, its super class or categories (if 17410b57cec5SDimitry Andric /// lookupCategory is true). 17420b57cec5SDimitry Andric bool ObjCInterfaceDecl::ClassImplementsProtocol(ObjCProtocolDecl *lProto, 17430b57cec5SDimitry Andric bool lookupCategory, 17440b57cec5SDimitry Andric bool RHSIsQualifiedID) { 17450b57cec5SDimitry Andric if (!hasDefinition()) 17460b57cec5SDimitry Andric return false; 17470b57cec5SDimitry Andric 17480b57cec5SDimitry Andric ObjCInterfaceDecl *IDecl = this; 17490b57cec5SDimitry Andric // 1st, look up the class. 17500b57cec5SDimitry Andric for (auto *PI : IDecl->protocols()){ 17510b57cec5SDimitry Andric if (getASTContext().ProtocolCompatibleWithProtocol(lProto, PI)) 17520b57cec5SDimitry Andric return true; 17530b57cec5SDimitry Andric // This is dubious and is added to be compatible with gcc. In gcc, it is 17540b57cec5SDimitry Andric // also allowed assigning a protocol-qualified 'id' type to a LHS object 17550b57cec5SDimitry Andric // when protocol in qualified LHS is in list of protocols in the rhs 'id' 17560b57cec5SDimitry Andric // object. This IMO, should be a bug. 17570b57cec5SDimitry Andric // FIXME: Treat this as an extension, and flag this as an error when GCC 17580b57cec5SDimitry Andric // extensions are not enabled. 17590b57cec5SDimitry Andric if (RHSIsQualifiedID && 17600b57cec5SDimitry Andric getASTContext().ProtocolCompatibleWithProtocol(PI, lProto)) 17610b57cec5SDimitry Andric return true; 17620b57cec5SDimitry Andric } 17630b57cec5SDimitry Andric 17640b57cec5SDimitry Andric // 2nd, look up the category. 17650b57cec5SDimitry Andric if (lookupCategory) 17660b57cec5SDimitry Andric for (const auto *Cat : visible_categories()) { 17670b57cec5SDimitry Andric for (auto *PI : Cat->protocols()) 17680b57cec5SDimitry Andric if (getASTContext().ProtocolCompatibleWithProtocol(lProto, PI)) 17690b57cec5SDimitry Andric return true; 17700b57cec5SDimitry Andric } 17710b57cec5SDimitry Andric 17720b57cec5SDimitry Andric // 3rd, look up the super class(s) 17730b57cec5SDimitry Andric if (IDecl->getSuperClass()) 17740b57cec5SDimitry Andric return 17750b57cec5SDimitry Andric IDecl->getSuperClass()->ClassImplementsProtocol(lProto, lookupCategory, 17760b57cec5SDimitry Andric RHSIsQualifiedID); 17770b57cec5SDimitry Andric 17780b57cec5SDimitry Andric return false; 17790b57cec5SDimitry Andric } 17800b57cec5SDimitry Andric 17810b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 17820b57cec5SDimitry Andric // ObjCIvarDecl 17830b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 17840b57cec5SDimitry Andric 17850b57cec5SDimitry Andric void ObjCIvarDecl::anchor() {} 17860b57cec5SDimitry Andric 17870b57cec5SDimitry Andric ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC, 17880b57cec5SDimitry Andric SourceLocation StartLoc, 17890b57cec5SDimitry Andric SourceLocation IdLoc, IdentifierInfo *Id, 17900b57cec5SDimitry Andric QualType T, TypeSourceInfo *TInfo, 17910b57cec5SDimitry Andric AccessControl ac, Expr *BW, 17920b57cec5SDimitry Andric bool synthesized) { 17930b57cec5SDimitry Andric if (DC) { 17940b57cec5SDimitry Andric // Ivar's can only appear in interfaces, implementations (via synthesized 17950b57cec5SDimitry Andric // properties), and class extensions (via direct declaration, or synthesized 17960b57cec5SDimitry Andric // properties). 17970b57cec5SDimitry Andric // 17980b57cec5SDimitry Andric // FIXME: This should really be asserting this: 17990b57cec5SDimitry Andric // (isa<ObjCCategoryDecl>(DC) && 18000b57cec5SDimitry Andric // cast<ObjCCategoryDecl>(DC)->IsClassExtension())) 18010b57cec5SDimitry Andric // but unfortunately we sometimes place ivars into non-class extension 18020b57cec5SDimitry Andric // categories on error. This breaks an AST invariant, and should not be 18030b57cec5SDimitry Andric // fixed. 18040b57cec5SDimitry Andric assert((isa<ObjCInterfaceDecl>(DC) || isa<ObjCImplementationDecl>(DC) || 18050b57cec5SDimitry Andric isa<ObjCCategoryDecl>(DC)) && 18060b57cec5SDimitry Andric "Invalid ivar decl context!"); 18070b57cec5SDimitry Andric // Once a new ivar is created in any of class/class-extension/implementation 18080b57cec5SDimitry Andric // decl contexts, the previously built IvarList must be rebuilt. 18090b57cec5SDimitry Andric auto *ID = dyn_cast<ObjCInterfaceDecl>(DC); 18100b57cec5SDimitry Andric if (!ID) { 18110b57cec5SDimitry Andric if (auto *IM = dyn_cast<ObjCImplementationDecl>(DC)) 18120b57cec5SDimitry Andric ID = IM->getClassInterface(); 18130b57cec5SDimitry Andric else 18140b57cec5SDimitry Andric ID = cast<ObjCCategoryDecl>(DC)->getClassInterface(); 18150b57cec5SDimitry Andric } 18160b57cec5SDimitry Andric ID->setIvarList(nullptr); 18170b57cec5SDimitry Andric } 18180b57cec5SDimitry Andric 18190b57cec5SDimitry Andric return new (C, DC) ObjCIvarDecl(DC, StartLoc, IdLoc, Id, T, TInfo, ac, BW, 18200b57cec5SDimitry Andric synthesized); 18210b57cec5SDimitry Andric } 18220b57cec5SDimitry Andric 18230b57cec5SDimitry Andric ObjCIvarDecl *ObjCIvarDecl::CreateDeserialized(ASTContext &C, unsigned ID) { 18240b57cec5SDimitry Andric return new (C, ID) ObjCIvarDecl(nullptr, SourceLocation(), SourceLocation(), 18250b57cec5SDimitry Andric nullptr, QualType(), nullptr, 18260b57cec5SDimitry Andric ObjCIvarDecl::None, nullptr, false); 18270b57cec5SDimitry Andric } 18280b57cec5SDimitry Andric 18290b57cec5SDimitry Andric const ObjCInterfaceDecl *ObjCIvarDecl::getContainingInterface() const { 18300b57cec5SDimitry Andric const auto *DC = cast<ObjCContainerDecl>(getDeclContext()); 18310b57cec5SDimitry Andric 18320b57cec5SDimitry Andric switch (DC->getKind()) { 18330b57cec5SDimitry Andric default: 18340b57cec5SDimitry Andric case ObjCCategoryImpl: 18350b57cec5SDimitry Andric case ObjCProtocol: 18360b57cec5SDimitry Andric llvm_unreachable("invalid ivar container!"); 18370b57cec5SDimitry Andric 18380b57cec5SDimitry Andric // Ivars can only appear in class extension categories. 18390b57cec5SDimitry Andric case ObjCCategory: { 18400b57cec5SDimitry Andric const auto *CD = cast<ObjCCategoryDecl>(DC); 18410b57cec5SDimitry Andric assert(CD->IsClassExtension() && "invalid container for ivar!"); 18420b57cec5SDimitry Andric return CD->getClassInterface(); 18430b57cec5SDimitry Andric } 18440b57cec5SDimitry Andric 18450b57cec5SDimitry Andric case ObjCImplementation: 18460b57cec5SDimitry Andric return cast<ObjCImplementationDecl>(DC)->getClassInterface(); 18470b57cec5SDimitry Andric 18480b57cec5SDimitry Andric case ObjCInterface: 18490b57cec5SDimitry Andric return cast<ObjCInterfaceDecl>(DC); 18500b57cec5SDimitry Andric } 18510b57cec5SDimitry Andric } 18520b57cec5SDimitry Andric 18530b57cec5SDimitry Andric QualType ObjCIvarDecl::getUsageType(QualType objectType) const { 18540b57cec5SDimitry Andric return getType().substObjCMemberType(objectType, getDeclContext(), 18550b57cec5SDimitry Andric ObjCSubstitutionContext::Property); 18560b57cec5SDimitry Andric } 18570b57cec5SDimitry Andric 18580b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 18590b57cec5SDimitry Andric // ObjCAtDefsFieldDecl 18600b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 18610b57cec5SDimitry Andric 18620b57cec5SDimitry Andric void ObjCAtDefsFieldDecl::anchor() {} 18630b57cec5SDimitry Andric 18640b57cec5SDimitry Andric ObjCAtDefsFieldDecl 18650b57cec5SDimitry Andric *ObjCAtDefsFieldDecl::Create(ASTContext &C, DeclContext *DC, 18660b57cec5SDimitry Andric SourceLocation StartLoc, SourceLocation IdLoc, 18670b57cec5SDimitry Andric IdentifierInfo *Id, QualType T, Expr *BW) { 18680b57cec5SDimitry Andric return new (C, DC) ObjCAtDefsFieldDecl(DC, StartLoc, IdLoc, Id, T, BW); 18690b57cec5SDimitry Andric } 18700b57cec5SDimitry Andric 18710b57cec5SDimitry Andric ObjCAtDefsFieldDecl *ObjCAtDefsFieldDecl::CreateDeserialized(ASTContext &C, 18720b57cec5SDimitry Andric unsigned ID) { 18730b57cec5SDimitry Andric return new (C, ID) ObjCAtDefsFieldDecl(nullptr, SourceLocation(), 18740b57cec5SDimitry Andric SourceLocation(), nullptr, QualType(), 18750b57cec5SDimitry Andric nullptr); 18760b57cec5SDimitry Andric } 18770b57cec5SDimitry Andric 18780b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 18790b57cec5SDimitry Andric // ObjCProtocolDecl 18800b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 18810b57cec5SDimitry Andric 18820b57cec5SDimitry Andric void ObjCProtocolDecl::anchor() {} 18830b57cec5SDimitry Andric 18840b57cec5SDimitry Andric ObjCProtocolDecl::ObjCProtocolDecl(ASTContext &C, DeclContext *DC, 18850b57cec5SDimitry Andric IdentifierInfo *Id, SourceLocation nameLoc, 18860b57cec5SDimitry Andric SourceLocation atStartLoc, 18870b57cec5SDimitry Andric ObjCProtocolDecl *PrevDecl) 18880b57cec5SDimitry Andric : ObjCContainerDecl(ObjCProtocol, DC, Id, nameLoc, atStartLoc), 18890b57cec5SDimitry Andric redeclarable_base(C) { 18900b57cec5SDimitry Andric setPreviousDecl(PrevDecl); 18910b57cec5SDimitry Andric if (PrevDecl) 18920b57cec5SDimitry Andric Data = PrevDecl->Data; 18930b57cec5SDimitry Andric } 18940b57cec5SDimitry Andric 18950b57cec5SDimitry Andric ObjCProtocolDecl *ObjCProtocolDecl::Create(ASTContext &C, DeclContext *DC, 18960b57cec5SDimitry Andric IdentifierInfo *Id, 18970b57cec5SDimitry Andric SourceLocation nameLoc, 18980b57cec5SDimitry Andric SourceLocation atStartLoc, 18990b57cec5SDimitry Andric ObjCProtocolDecl *PrevDecl) { 19000b57cec5SDimitry Andric auto *Result = 19010b57cec5SDimitry Andric new (C, DC) ObjCProtocolDecl(C, DC, Id, nameLoc, atStartLoc, PrevDecl); 19020b57cec5SDimitry Andric Result->Data.setInt(!C.getLangOpts().Modules); 19030b57cec5SDimitry Andric return Result; 19040b57cec5SDimitry Andric } 19050b57cec5SDimitry Andric 19060b57cec5SDimitry Andric ObjCProtocolDecl *ObjCProtocolDecl::CreateDeserialized(ASTContext &C, 19070b57cec5SDimitry Andric unsigned ID) { 19080b57cec5SDimitry Andric ObjCProtocolDecl *Result = 19090b57cec5SDimitry Andric new (C, ID) ObjCProtocolDecl(C, nullptr, nullptr, SourceLocation(), 19100b57cec5SDimitry Andric SourceLocation(), nullptr); 19110b57cec5SDimitry Andric Result->Data.setInt(!C.getLangOpts().Modules); 19120b57cec5SDimitry Andric return Result; 19130b57cec5SDimitry Andric } 19140b57cec5SDimitry Andric 1915e8d8bef9SDimitry Andric bool ObjCProtocolDecl::isNonRuntimeProtocol() const { 1916e8d8bef9SDimitry Andric return hasAttr<ObjCNonRuntimeProtocolAttr>(); 1917e8d8bef9SDimitry Andric } 1918e8d8bef9SDimitry Andric 1919e8d8bef9SDimitry Andric void ObjCProtocolDecl::getImpliedProtocols( 1920e8d8bef9SDimitry Andric llvm::DenseSet<const ObjCProtocolDecl *> &IPs) const { 1921e8d8bef9SDimitry Andric std::queue<const ObjCProtocolDecl *> WorkQueue; 1922e8d8bef9SDimitry Andric WorkQueue.push(this); 1923e8d8bef9SDimitry Andric 1924e8d8bef9SDimitry Andric while (!WorkQueue.empty()) { 1925e8d8bef9SDimitry Andric const auto *PD = WorkQueue.front(); 1926e8d8bef9SDimitry Andric WorkQueue.pop(); 1927e8d8bef9SDimitry Andric for (const auto *Parent : PD->protocols()) { 1928e8d8bef9SDimitry Andric const auto *Can = Parent->getCanonicalDecl(); 1929e8d8bef9SDimitry Andric auto Result = IPs.insert(Can); 1930e8d8bef9SDimitry Andric if (Result.second) 1931e8d8bef9SDimitry Andric WorkQueue.push(Parent); 1932e8d8bef9SDimitry Andric } 1933e8d8bef9SDimitry Andric } 1934e8d8bef9SDimitry Andric } 1935e8d8bef9SDimitry Andric 19360b57cec5SDimitry Andric ObjCProtocolDecl *ObjCProtocolDecl::lookupProtocolNamed(IdentifierInfo *Name) { 19370b57cec5SDimitry Andric ObjCProtocolDecl *PDecl = this; 19380b57cec5SDimitry Andric 19390b57cec5SDimitry Andric if (Name == getIdentifier()) 19400b57cec5SDimitry Andric return PDecl; 19410b57cec5SDimitry Andric 19420b57cec5SDimitry Andric for (auto *I : protocols()) 19430b57cec5SDimitry Andric if ((PDecl = I->lookupProtocolNamed(Name))) 19440b57cec5SDimitry Andric return PDecl; 19450b57cec5SDimitry Andric 19460b57cec5SDimitry Andric return nullptr; 19470b57cec5SDimitry Andric } 19480b57cec5SDimitry Andric 19490b57cec5SDimitry Andric // lookupMethod - Lookup a instance/class method in the protocol and protocols 19500b57cec5SDimitry Andric // it inherited. 19510b57cec5SDimitry Andric ObjCMethodDecl *ObjCProtocolDecl::lookupMethod(Selector Sel, 19520b57cec5SDimitry Andric bool isInstance) const { 19530b57cec5SDimitry Andric ObjCMethodDecl *MethodDecl = nullptr; 19540b57cec5SDimitry Andric 19550b57cec5SDimitry Andric // If there is no definition or the definition is hidden, we don't find 19560b57cec5SDimitry Andric // anything. 19570b57cec5SDimitry Andric const ObjCProtocolDecl *Def = getDefinition(); 19585ffd83dbSDimitry Andric if (!Def || !Def->isUnconditionallyVisible()) 19590b57cec5SDimitry Andric return nullptr; 19600b57cec5SDimitry Andric 19610b57cec5SDimitry Andric if ((MethodDecl = getMethod(Sel, isInstance))) 19620b57cec5SDimitry Andric return MethodDecl; 19630b57cec5SDimitry Andric 19640b57cec5SDimitry Andric for (const auto *I : protocols()) 19650b57cec5SDimitry Andric if ((MethodDecl = I->lookupMethod(Sel, isInstance))) 19660b57cec5SDimitry Andric return MethodDecl; 19670b57cec5SDimitry Andric return nullptr; 19680b57cec5SDimitry Andric } 19690b57cec5SDimitry Andric 19700b57cec5SDimitry Andric void ObjCProtocolDecl::allocateDefinitionData() { 19710b57cec5SDimitry Andric assert(!Data.getPointer() && "Protocol already has a definition!"); 19720b57cec5SDimitry Andric Data.setPointer(new (getASTContext()) DefinitionData); 19730b57cec5SDimitry Andric Data.getPointer()->Definition = this; 19740b57cec5SDimitry Andric } 19750b57cec5SDimitry Andric 19760b57cec5SDimitry Andric void ObjCProtocolDecl::startDefinition() { 19770b57cec5SDimitry Andric allocateDefinitionData(); 19780b57cec5SDimitry Andric 19790b57cec5SDimitry Andric // Update all of the declarations with a pointer to the definition. 19800b57cec5SDimitry Andric for (auto *RD : redecls()) 19810b57cec5SDimitry Andric RD->Data = this->Data; 19820b57cec5SDimitry Andric } 19830b57cec5SDimitry Andric 19840b57cec5SDimitry Andric void ObjCProtocolDecl::collectPropertiesToImplement(PropertyMap &PM, 19850b57cec5SDimitry Andric PropertyDeclOrder &PO) const { 19860b57cec5SDimitry Andric if (const ObjCProtocolDecl *PDecl = getDefinition()) { 19870b57cec5SDimitry Andric for (auto *Prop : PDecl->properties()) { 19880b57cec5SDimitry Andric // Insert into PM if not there already. 19890b57cec5SDimitry Andric PM.insert(std::make_pair( 19900b57cec5SDimitry Andric std::make_pair(Prop->getIdentifier(), Prop->isClassProperty()), 19910b57cec5SDimitry Andric Prop)); 19920b57cec5SDimitry Andric PO.push_back(Prop); 19930b57cec5SDimitry Andric } 19940b57cec5SDimitry Andric // Scan through protocol's protocols. 19950b57cec5SDimitry Andric for (const auto *PI : PDecl->protocols()) 19960b57cec5SDimitry Andric PI->collectPropertiesToImplement(PM, PO); 19970b57cec5SDimitry Andric } 19980b57cec5SDimitry Andric } 19990b57cec5SDimitry Andric 20000b57cec5SDimitry Andric void ObjCProtocolDecl::collectInheritedProtocolProperties( 20010b57cec5SDimitry Andric const ObjCPropertyDecl *Property, ProtocolPropertySet &PS, 20020b57cec5SDimitry Andric PropertyDeclOrder &PO) const { 20030b57cec5SDimitry Andric if (const ObjCProtocolDecl *PDecl = getDefinition()) { 20040b57cec5SDimitry Andric if (!PS.insert(PDecl).second) 20050b57cec5SDimitry Andric return; 20060b57cec5SDimitry Andric for (auto *Prop : PDecl->properties()) { 20070b57cec5SDimitry Andric if (Prop == Property) 20080b57cec5SDimitry Andric continue; 20090b57cec5SDimitry Andric if (Prop->getIdentifier() == Property->getIdentifier()) { 20100b57cec5SDimitry Andric PO.push_back(Prop); 20110b57cec5SDimitry Andric return; 20120b57cec5SDimitry Andric } 20130b57cec5SDimitry Andric } 20140b57cec5SDimitry Andric // Scan through protocol's protocols which did not have a matching property. 20150b57cec5SDimitry Andric for (const auto *PI : PDecl->protocols()) 20160b57cec5SDimitry Andric PI->collectInheritedProtocolProperties(Property, PS, PO); 20170b57cec5SDimitry Andric } 20180b57cec5SDimitry Andric } 20190b57cec5SDimitry Andric 20200b57cec5SDimitry Andric StringRef 20210b57cec5SDimitry Andric ObjCProtocolDecl::getObjCRuntimeNameAsString() const { 20220b57cec5SDimitry Andric if (const auto *ObjCRTName = getAttr<ObjCRuntimeNameAttr>()) 20230b57cec5SDimitry Andric return ObjCRTName->getMetadataName(); 20240b57cec5SDimitry Andric 20250b57cec5SDimitry Andric return getName(); 20260b57cec5SDimitry Andric } 20270b57cec5SDimitry Andric 20280b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 20290b57cec5SDimitry Andric // ObjCCategoryDecl 20300b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 20310b57cec5SDimitry Andric 20320b57cec5SDimitry Andric void ObjCCategoryDecl::anchor() {} 20330b57cec5SDimitry Andric 20340b57cec5SDimitry Andric ObjCCategoryDecl::ObjCCategoryDecl(DeclContext *DC, SourceLocation AtLoc, 20350b57cec5SDimitry Andric SourceLocation ClassNameLoc, 20360b57cec5SDimitry Andric SourceLocation CategoryNameLoc, 20370b57cec5SDimitry Andric IdentifierInfo *Id, ObjCInterfaceDecl *IDecl, 20380b57cec5SDimitry Andric ObjCTypeParamList *typeParamList, 20390b57cec5SDimitry Andric SourceLocation IvarLBraceLoc, 20400b57cec5SDimitry Andric SourceLocation IvarRBraceLoc) 20410b57cec5SDimitry Andric : ObjCContainerDecl(ObjCCategory, DC, Id, ClassNameLoc, AtLoc), 20420b57cec5SDimitry Andric ClassInterface(IDecl), CategoryNameLoc(CategoryNameLoc), 20430b57cec5SDimitry Andric IvarLBraceLoc(IvarLBraceLoc), IvarRBraceLoc(IvarRBraceLoc) { 20440b57cec5SDimitry Andric setTypeParamList(typeParamList); 20450b57cec5SDimitry Andric } 20460b57cec5SDimitry Andric 20470b57cec5SDimitry Andric ObjCCategoryDecl *ObjCCategoryDecl::Create(ASTContext &C, DeclContext *DC, 20480b57cec5SDimitry Andric SourceLocation AtLoc, 20490b57cec5SDimitry Andric SourceLocation ClassNameLoc, 20500b57cec5SDimitry Andric SourceLocation CategoryNameLoc, 20510b57cec5SDimitry Andric IdentifierInfo *Id, 20520b57cec5SDimitry Andric ObjCInterfaceDecl *IDecl, 20530b57cec5SDimitry Andric ObjCTypeParamList *typeParamList, 20540b57cec5SDimitry Andric SourceLocation IvarLBraceLoc, 20550b57cec5SDimitry Andric SourceLocation IvarRBraceLoc) { 20560b57cec5SDimitry Andric auto *CatDecl = 20570b57cec5SDimitry Andric new (C, DC) ObjCCategoryDecl(DC, AtLoc, ClassNameLoc, CategoryNameLoc, Id, 20580b57cec5SDimitry Andric IDecl, typeParamList, IvarLBraceLoc, 20590b57cec5SDimitry Andric IvarRBraceLoc); 20600b57cec5SDimitry Andric if (IDecl) { 20610b57cec5SDimitry Andric // Link this category into its class's category list. 20620b57cec5SDimitry Andric CatDecl->NextClassCategory = IDecl->getCategoryListRaw(); 20630b57cec5SDimitry Andric if (IDecl->hasDefinition()) { 20640b57cec5SDimitry Andric IDecl->setCategoryListRaw(CatDecl); 20650b57cec5SDimitry Andric if (ASTMutationListener *L = C.getASTMutationListener()) 20660b57cec5SDimitry Andric L->AddedObjCCategoryToInterface(CatDecl, IDecl); 20670b57cec5SDimitry Andric } 20680b57cec5SDimitry Andric } 20690b57cec5SDimitry Andric 20700b57cec5SDimitry Andric return CatDecl; 20710b57cec5SDimitry Andric } 20720b57cec5SDimitry Andric 20730b57cec5SDimitry Andric ObjCCategoryDecl *ObjCCategoryDecl::CreateDeserialized(ASTContext &C, 20740b57cec5SDimitry Andric unsigned ID) { 20750b57cec5SDimitry Andric return new (C, ID) ObjCCategoryDecl(nullptr, SourceLocation(), 20760b57cec5SDimitry Andric SourceLocation(), SourceLocation(), 20770b57cec5SDimitry Andric nullptr, nullptr, nullptr); 20780b57cec5SDimitry Andric } 20790b57cec5SDimitry Andric 20800b57cec5SDimitry Andric ObjCCategoryImplDecl *ObjCCategoryDecl::getImplementation() const { 20810b57cec5SDimitry Andric return getASTContext().getObjCImplementation( 20820b57cec5SDimitry Andric const_cast<ObjCCategoryDecl*>(this)); 20830b57cec5SDimitry Andric } 20840b57cec5SDimitry Andric 20850b57cec5SDimitry Andric void ObjCCategoryDecl::setImplementation(ObjCCategoryImplDecl *ImplD) { 20860b57cec5SDimitry Andric getASTContext().setObjCImplementation(this, ImplD); 20870b57cec5SDimitry Andric } 20880b57cec5SDimitry Andric 20890b57cec5SDimitry Andric void ObjCCategoryDecl::setTypeParamList(ObjCTypeParamList *TPL) { 20900b57cec5SDimitry Andric TypeParamList = TPL; 20910b57cec5SDimitry Andric if (!TPL) 20920b57cec5SDimitry Andric return; 20930b57cec5SDimitry Andric // Set the declaration context of each of the type parameters. 20940b57cec5SDimitry Andric for (auto *typeParam : *TypeParamList) 20950b57cec5SDimitry Andric typeParam->setDeclContext(this); 20960b57cec5SDimitry Andric } 20970b57cec5SDimitry Andric 20980b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 20990b57cec5SDimitry Andric // ObjCCategoryImplDecl 21000b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 21010b57cec5SDimitry Andric 21020b57cec5SDimitry Andric void ObjCCategoryImplDecl::anchor() {} 21030b57cec5SDimitry Andric 21040b57cec5SDimitry Andric ObjCCategoryImplDecl * 21050b57cec5SDimitry Andric ObjCCategoryImplDecl::Create(ASTContext &C, DeclContext *DC, 21060b57cec5SDimitry Andric IdentifierInfo *Id, 21070b57cec5SDimitry Andric ObjCInterfaceDecl *ClassInterface, 21080b57cec5SDimitry Andric SourceLocation nameLoc, 21090b57cec5SDimitry Andric SourceLocation atStartLoc, 21100b57cec5SDimitry Andric SourceLocation CategoryNameLoc) { 21110b57cec5SDimitry Andric if (ClassInterface && ClassInterface->hasDefinition()) 21120b57cec5SDimitry Andric ClassInterface = ClassInterface->getDefinition(); 21130b57cec5SDimitry Andric return new (C, DC) ObjCCategoryImplDecl(DC, Id, ClassInterface, nameLoc, 21140b57cec5SDimitry Andric atStartLoc, CategoryNameLoc); 21150b57cec5SDimitry Andric } 21160b57cec5SDimitry Andric 21170b57cec5SDimitry Andric ObjCCategoryImplDecl *ObjCCategoryImplDecl::CreateDeserialized(ASTContext &C, 21180b57cec5SDimitry Andric unsigned ID) { 21190b57cec5SDimitry Andric return new (C, ID) ObjCCategoryImplDecl(nullptr, nullptr, nullptr, 21200b57cec5SDimitry Andric SourceLocation(), SourceLocation(), 21210b57cec5SDimitry Andric SourceLocation()); 21220b57cec5SDimitry Andric } 21230b57cec5SDimitry Andric 21240b57cec5SDimitry Andric ObjCCategoryDecl *ObjCCategoryImplDecl::getCategoryDecl() const { 21250b57cec5SDimitry Andric // The class interface might be NULL if we are working with invalid code. 21260b57cec5SDimitry Andric if (const ObjCInterfaceDecl *ID = getClassInterface()) 21270b57cec5SDimitry Andric return ID->FindCategoryDeclaration(getIdentifier()); 21280b57cec5SDimitry Andric return nullptr; 21290b57cec5SDimitry Andric } 21300b57cec5SDimitry Andric 21310b57cec5SDimitry Andric void ObjCImplDecl::anchor() {} 21320b57cec5SDimitry Andric 21330b57cec5SDimitry Andric void ObjCImplDecl::addPropertyImplementation(ObjCPropertyImplDecl *property) { 21340b57cec5SDimitry Andric // FIXME: The context should be correct before we get here. 21350b57cec5SDimitry Andric property->setLexicalDeclContext(this); 21360b57cec5SDimitry Andric addDecl(property); 21370b57cec5SDimitry Andric } 21380b57cec5SDimitry Andric 21390b57cec5SDimitry Andric void ObjCImplDecl::setClassInterface(ObjCInterfaceDecl *IFace) { 21400b57cec5SDimitry Andric ASTContext &Ctx = getASTContext(); 21410b57cec5SDimitry Andric 21420b57cec5SDimitry Andric if (auto *ImplD = dyn_cast_or_null<ObjCImplementationDecl>(this)) { 21430b57cec5SDimitry Andric if (IFace) 21440b57cec5SDimitry Andric Ctx.setObjCImplementation(IFace, ImplD); 21450b57cec5SDimitry Andric 21460b57cec5SDimitry Andric } else if (auto *ImplD = dyn_cast_or_null<ObjCCategoryImplDecl>(this)) { 21470b57cec5SDimitry Andric if (ObjCCategoryDecl *CD = IFace->FindCategoryDeclaration(getIdentifier())) 21480b57cec5SDimitry Andric Ctx.setObjCImplementation(CD, ImplD); 21490b57cec5SDimitry Andric } 21500b57cec5SDimitry Andric 21510b57cec5SDimitry Andric ClassInterface = IFace; 21520b57cec5SDimitry Andric } 21530b57cec5SDimitry Andric 21540b57cec5SDimitry Andric /// FindPropertyImplIvarDecl - This method lookup the ivar in the list of 21550b57cec5SDimitry Andric /// properties implemented in this \@implementation block and returns 21560b57cec5SDimitry Andric /// the implemented property that uses it. 21570b57cec5SDimitry Andric ObjCPropertyImplDecl *ObjCImplDecl:: 21580b57cec5SDimitry Andric FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const { 21590b57cec5SDimitry Andric for (auto *PID : property_impls()) 21600b57cec5SDimitry Andric if (PID->getPropertyIvarDecl() && 21610b57cec5SDimitry Andric PID->getPropertyIvarDecl()->getIdentifier() == ivarId) 21620b57cec5SDimitry Andric return PID; 21630b57cec5SDimitry Andric return nullptr; 21640b57cec5SDimitry Andric } 21650b57cec5SDimitry Andric 21660b57cec5SDimitry Andric /// FindPropertyImplDecl - This method looks up a previous ObjCPropertyImplDecl 21670b57cec5SDimitry Andric /// added to the list of those properties \@synthesized/\@dynamic in this 21680b57cec5SDimitry Andric /// category \@implementation block. 21690b57cec5SDimitry Andric ObjCPropertyImplDecl *ObjCImplDecl:: 21700b57cec5SDimitry Andric FindPropertyImplDecl(IdentifierInfo *Id, 21710b57cec5SDimitry Andric ObjCPropertyQueryKind QueryKind) const { 21720b57cec5SDimitry Andric ObjCPropertyImplDecl *ClassPropImpl = nullptr; 21730b57cec5SDimitry Andric for (auto *PID : property_impls()) 21740b57cec5SDimitry Andric // If queryKind is unknown, we return the instance property if one 21750b57cec5SDimitry Andric // exists; otherwise we return the class property. 21760b57cec5SDimitry Andric if (PID->getPropertyDecl()->getIdentifier() == Id) { 21770b57cec5SDimitry Andric if ((QueryKind == ObjCPropertyQueryKind::OBJC_PR_query_unknown && 21780b57cec5SDimitry Andric !PID->getPropertyDecl()->isClassProperty()) || 21790b57cec5SDimitry Andric (QueryKind == ObjCPropertyQueryKind::OBJC_PR_query_class && 21800b57cec5SDimitry Andric PID->getPropertyDecl()->isClassProperty()) || 21810b57cec5SDimitry Andric (QueryKind == ObjCPropertyQueryKind::OBJC_PR_query_instance && 21820b57cec5SDimitry Andric !PID->getPropertyDecl()->isClassProperty())) 21830b57cec5SDimitry Andric return PID; 21840b57cec5SDimitry Andric 21850b57cec5SDimitry Andric if (PID->getPropertyDecl()->isClassProperty()) 21860b57cec5SDimitry Andric ClassPropImpl = PID; 21870b57cec5SDimitry Andric } 21880b57cec5SDimitry Andric 21890b57cec5SDimitry Andric if (QueryKind == ObjCPropertyQueryKind::OBJC_PR_query_unknown) 21900b57cec5SDimitry Andric // We can't find the instance property, return the class property. 21910b57cec5SDimitry Andric return ClassPropImpl; 21920b57cec5SDimitry Andric 21930b57cec5SDimitry Andric return nullptr; 21940b57cec5SDimitry Andric } 21950b57cec5SDimitry Andric 21960b57cec5SDimitry Andric raw_ostream &clang::operator<<(raw_ostream &OS, 21970b57cec5SDimitry Andric const ObjCCategoryImplDecl &CID) { 21980b57cec5SDimitry Andric OS << CID.getName(); 21990b57cec5SDimitry Andric return OS; 22000b57cec5SDimitry Andric } 22010b57cec5SDimitry Andric 22020b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 22030b57cec5SDimitry Andric // ObjCImplementationDecl 22040b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 22050b57cec5SDimitry Andric 22060b57cec5SDimitry Andric void ObjCImplementationDecl::anchor() {} 22070b57cec5SDimitry Andric 22080b57cec5SDimitry Andric ObjCImplementationDecl * 22090b57cec5SDimitry Andric ObjCImplementationDecl::Create(ASTContext &C, DeclContext *DC, 22100b57cec5SDimitry Andric ObjCInterfaceDecl *ClassInterface, 22110b57cec5SDimitry Andric ObjCInterfaceDecl *SuperDecl, 22120b57cec5SDimitry Andric SourceLocation nameLoc, 22130b57cec5SDimitry Andric SourceLocation atStartLoc, 22140b57cec5SDimitry Andric SourceLocation superLoc, 22150b57cec5SDimitry Andric SourceLocation IvarLBraceLoc, 22160b57cec5SDimitry Andric SourceLocation IvarRBraceLoc) { 22170b57cec5SDimitry Andric if (ClassInterface && ClassInterface->hasDefinition()) 22180b57cec5SDimitry Andric ClassInterface = ClassInterface->getDefinition(); 22190b57cec5SDimitry Andric return new (C, DC) ObjCImplementationDecl(DC, ClassInterface, SuperDecl, 22200b57cec5SDimitry Andric nameLoc, atStartLoc, superLoc, 22210b57cec5SDimitry Andric IvarLBraceLoc, IvarRBraceLoc); 22220b57cec5SDimitry Andric } 22230b57cec5SDimitry Andric 22240b57cec5SDimitry Andric ObjCImplementationDecl * 22250b57cec5SDimitry Andric ObjCImplementationDecl::CreateDeserialized(ASTContext &C, unsigned ID) { 22260b57cec5SDimitry Andric return new (C, ID) ObjCImplementationDecl(nullptr, nullptr, nullptr, 22270b57cec5SDimitry Andric SourceLocation(), SourceLocation()); 22280b57cec5SDimitry Andric } 22290b57cec5SDimitry Andric 22300b57cec5SDimitry Andric void ObjCImplementationDecl::setIvarInitializers(ASTContext &C, 22310b57cec5SDimitry Andric CXXCtorInitializer ** initializers, 22320b57cec5SDimitry Andric unsigned numInitializers) { 22330b57cec5SDimitry Andric if (numInitializers > 0) { 22340b57cec5SDimitry Andric NumIvarInitializers = numInitializers; 22350b57cec5SDimitry Andric auto **ivarInitializers = new (C) CXXCtorInitializer*[NumIvarInitializers]; 22360b57cec5SDimitry Andric memcpy(ivarInitializers, initializers, 22370b57cec5SDimitry Andric numInitializers * sizeof(CXXCtorInitializer*)); 22380b57cec5SDimitry Andric IvarInitializers = ivarInitializers; 22390b57cec5SDimitry Andric } 22400b57cec5SDimitry Andric } 22410b57cec5SDimitry Andric 22420b57cec5SDimitry Andric ObjCImplementationDecl::init_const_iterator 22430b57cec5SDimitry Andric ObjCImplementationDecl::init_begin() const { 22440b57cec5SDimitry Andric return IvarInitializers.get(getASTContext().getExternalSource()); 22450b57cec5SDimitry Andric } 22460b57cec5SDimitry Andric 22470b57cec5SDimitry Andric raw_ostream &clang::operator<<(raw_ostream &OS, 22480b57cec5SDimitry Andric const ObjCImplementationDecl &ID) { 22490b57cec5SDimitry Andric OS << ID.getName(); 22500b57cec5SDimitry Andric return OS; 22510b57cec5SDimitry Andric } 22520b57cec5SDimitry Andric 22530b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 22540b57cec5SDimitry Andric // ObjCCompatibleAliasDecl 22550b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 22560b57cec5SDimitry Andric 22570b57cec5SDimitry Andric void ObjCCompatibleAliasDecl::anchor() {} 22580b57cec5SDimitry Andric 22590b57cec5SDimitry Andric ObjCCompatibleAliasDecl * 22600b57cec5SDimitry Andric ObjCCompatibleAliasDecl::Create(ASTContext &C, DeclContext *DC, 22610b57cec5SDimitry Andric SourceLocation L, 22620b57cec5SDimitry Andric IdentifierInfo *Id, 22630b57cec5SDimitry Andric ObjCInterfaceDecl* AliasedClass) { 22640b57cec5SDimitry Andric return new (C, DC) ObjCCompatibleAliasDecl(DC, L, Id, AliasedClass); 22650b57cec5SDimitry Andric } 22660b57cec5SDimitry Andric 22670b57cec5SDimitry Andric ObjCCompatibleAliasDecl * 22680b57cec5SDimitry Andric ObjCCompatibleAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) { 22690b57cec5SDimitry Andric return new (C, ID) ObjCCompatibleAliasDecl(nullptr, SourceLocation(), 22700b57cec5SDimitry Andric nullptr, nullptr); 22710b57cec5SDimitry Andric } 22720b57cec5SDimitry Andric 22730b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 22740b57cec5SDimitry Andric // ObjCPropertyDecl 22750b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 22760b57cec5SDimitry Andric 22770b57cec5SDimitry Andric void ObjCPropertyDecl::anchor() {} 22780b57cec5SDimitry Andric 22790b57cec5SDimitry Andric ObjCPropertyDecl *ObjCPropertyDecl::Create(ASTContext &C, DeclContext *DC, 22800b57cec5SDimitry Andric SourceLocation L, 22810b57cec5SDimitry Andric IdentifierInfo *Id, 22820b57cec5SDimitry Andric SourceLocation AtLoc, 22830b57cec5SDimitry Andric SourceLocation LParenLoc, 22840b57cec5SDimitry Andric QualType T, 22850b57cec5SDimitry Andric TypeSourceInfo *TSI, 22860b57cec5SDimitry Andric PropertyControl propControl) { 22870b57cec5SDimitry Andric return new (C, DC) ObjCPropertyDecl(DC, L, Id, AtLoc, LParenLoc, T, TSI, 22880b57cec5SDimitry Andric propControl); 22890b57cec5SDimitry Andric } 22900b57cec5SDimitry Andric 22910b57cec5SDimitry Andric ObjCPropertyDecl *ObjCPropertyDecl::CreateDeserialized(ASTContext &C, 22920b57cec5SDimitry Andric unsigned ID) { 22930b57cec5SDimitry Andric return new (C, ID) ObjCPropertyDecl(nullptr, SourceLocation(), nullptr, 22940b57cec5SDimitry Andric SourceLocation(), SourceLocation(), 22950b57cec5SDimitry Andric QualType(), nullptr, None); 22960b57cec5SDimitry Andric } 22970b57cec5SDimitry Andric 22980b57cec5SDimitry Andric QualType ObjCPropertyDecl::getUsageType(QualType objectType) const { 22990b57cec5SDimitry Andric return DeclType.substObjCMemberType(objectType, getDeclContext(), 23000b57cec5SDimitry Andric ObjCSubstitutionContext::Property); 23010b57cec5SDimitry Andric } 23020b57cec5SDimitry Andric 2303fe6060f1SDimitry Andric bool ObjCPropertyDecl::isDirectProperty() const { 2304fe6060f1SDimitry Andric return (PropertyAttributes & ObjCPropertyAttribute::kind_direct) && 2305fe6060f1SDimitry Andric !getASTContext().getLangOpts().ObjCDisableDirectMethodsForTesting; 2306fe6060f1SDimitry Andric } 2307fe6060f1SDimitry Andric 23080b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 23090b57cec5SDimitry Andric // ObjCPropertyImplDecl 23100b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 23110b57cec5SDimitry Andric 23120b57cec5SDimitry Andric ObjCPropertyImplDecl *ObjCPropertyImplDecl::Create(ASTContext &C, 23130b57cec5SDimitry Andric DeclContext *DC, 23140b57cec5SDimitry Andric SourceLocation atLoc, 23150b57cec5SDimitry Andric SourceLocation L, 23160b57cec5SDimitry Andric ObjCPropertyDecl *property, 23170b57cec5SDimitry Andric Kind PK, 23180b57cec5SDimitry Andric ObjCIvarDecl *ivar, 23190b57cec5SDimitry Andric SourceLocation ivarLoc) { 23200b57cec5SDimitry Andric return new (C, DC) ObjCPropertyImplDecl(DC, atLoc, L, property, PK, ivar, 23210b57cec5SDimitry Andric ivarLoc); 23220b57cec5SDimitry Andric } 23230b57cec5SDimitry Andric 23240b57cec5SDimitry Andric ObjCPropertyImplDecl *ObjCPropertyImplDecl::CreateDeserialized(ASTContext &C, 23250b57cec5SDimitry Andric unsigned ID) { 23260b57cec5SDimitry Andric return new (C, ID) ObjCPropertyImplDecl(nullptr, SourceLocation(), 23270b57cec5SDimitry Andric SourceLocation(), nullptr, Dynamic, 23280b57cec5SDimitry Andric nullptr, SourceLocation()); 23290b57cec5SDimitry Andric } 23300b57cec5SDimitry Andric 23310b57cec5SDimitry Andric SourceRange ObjCPropertyImplDecl::getSourceRange() const { 23320b57cec5SDimitry Andric SourceLocation EndLoc = getLocation(); 23330b57cec5SDimitry Andric if (IvarLoc.isValid()) 23340b57cec5SDimitry Andric EndLoc = IvarLoc; 23350b57cec5SDimitry Andric 23360b57cec5SDimitry Andric return SourceRange(AtLoc, EndLoc); 23370b57cec5SDimitry Andric } 2338