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> 36*e8d8bef9SDimitry 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 // Make the type point at the definition, now that we have one. 6080b57cec5SDimitry Andric if (TypeForDecl) 6090b57cec5SDimitry Andric cast<ObjCInterfaceType>(TypeForDecl)->Decl = this; 6100b57cec5SDimitry Andric } 6110b57cec5SDimitry Andric 6120b57cec5SDimitry Andric void ObjCInterfaceDecl::startDefinition() { 6130b57cec5SDimitry Andric allocateDefinitionData(); 6140b57cec5SDimitry Andric 6150b57cec5SDimitry Andric // Update all of the declarations with a pointer to the definition. 6160b57cec5SDimitry Andric for (auto *RD : redecls()) { 6170b57cec5SDimitry Andric if (RD != this) 6180b57cec5SDimitry Andric RD->Data = Data; 6190b57cec5SDimitry Andric } 6200b57cec5SDimitry Andric } 6210b57cec5SDimitry Andric 6220b57cec5SDimitry Andric ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(IdentifierInfo *ID, 6230b57cec5SDimitry Andric ObjCInterfaceDecl *&clsDeclared) { 6240b57cec5SDimitry Andric // FIXME: Should make sure no callers ever do this. 6250b57cec5SDimitry Andric if (!hasDefinition()) 6260b57cec5SDimitry Andric return nullptr; 6270b57cec5SDimitry Andric 6280b57cec5SDimitry Andric if (data().ExternallyCompleted) 6290b57cec5SDimitry Andric LoadExternalDefinition(); 6300b57cec5SDimitry Andric 6310b57cec5SDimitry Andric ObjCInterfaceDecl* ClassDecl = this; 6320b57cec5SDimitry Andric while (ClassDecl != nullptr) { 6330b57cec5SDimitry Andric if (ObjCIvarDecl *I = ClassDecl->getIvarDecl(ID)) { 6340b57cec5SDimitry Andric clsDeclared = ClassDecl; 6350b57cec5SDimitry Andric return I; 6360b57cec5SDimitry Andric } 6370b57cec5SDimitry Andric 6380b57cec5SDimitry Andric for (const auto *Ext : ClassDecl->visible_extensions()) { 6390b57cec5SDimitry Andric if (ObjCIvarDecl *I = Ext->getIvarDecl(ID)) { 6400b57cec5SDimitry Andric clsDeclared = ClassDecl; 6410b57cec5SDimitry Andric return I; 6420b57cec5SDimitry Andric } 6430b57cec5SDimitry Andric } 6440b57cec5SDimitry Andric 6450b57cec5SDimitry Andric ClassDecl = ClassDecl->getSuperClass(); 6460b57cec5SDimitry Andric } 6470b57cec5SDimitry Andric return nullptr; 6480b57cec5SDimitry Andric } 6490b57cec5SDimitry Andric 6500b57cec5SDimitry Andric /// lookupInheritedClass - This method returns ObjCInterfaceDecl * of the super 6510b57cec5SDimitry Andric /// class whose name is passed as argument. If it is not one of the super classes 6520b57cec5SDimitry Andric /// the it returns NULL. 6530b57cec5SDimitry Andric ObjCInterfaceDecl *ObjCInterfaceDecl::lookupInheritedClass( 6540b57cec5SDimitry Andric const IdentifierInfo*ICName) { 6550b57cec5SDimitry Andric // FIXME: Should make sure no callers ever do this. 6560b57cec5SDimitry Andric if (!hasDefinition()) 6570b57cec5SDimitry Andric return nullptr; 6580b57cec5SDimitry Andric 6590b57cec5SDimitry Andric if (data().ExternallyCompleted) 6600b57cec5SDimitry Andric LoadExternalDefinition(); 6610b57cec5SDimitry Andric 6620b57cec5SDimitry Andric ObjCInterfaceDecl* ClassDecl = this; 6630b57cec5SDimitry Andric while (ClassDecl != nullptr) { 6640b57cec5SDimitry Andric if (ClassDecl->getIdentifier() == ICName) 6650b57cec5SDimitry Andric return ClassDecl; 6660b57cec5SDimitry Andric ClassDecl = ClassDecl->getSuperClass(); 6670b57cec5SDimitry Andric } 6680b57cec5SDimitry Andric return nullptr; 6690b57cec5SDimitry Andric } 6700b57cec5SDimitry Andric 6710b57cec5SDimitry Andric ObjCProtocolDecl * 6720b57cec5SDimitry Andric ObjCInterfaceDecl::lookupNestedProtocol(IdentifierInfo *Name) { 6730b57cec5SDimitry Andric for (auto *P : all_referenced_protocols()) 6740b57cec5SDimitry Andric if (P->lookupProtocolNamed(Name)) 6750b57cec5SDimitry Andric return P; 6760b57cec5SDimitry Andric ObjCInterfaceDecl *SuperClass = getSuperClass(); 6770b57cec5SDimitry Andric return SuperClass ? SuperClass->lookupNestedProtocol(Name) : nullptr; 6780b57cec5SDimitry Andric } 6790b57cec5SDimitry Andric 6800b57cec5SDimitry Andric /// lookupMethod - This method returns an instance/class method by looking in 6810b57cec5SDimitry Andric /// the class, its categories, and its super classes (using a linear search). 6820b57cec5SDimitry Andric /// When argument category "C" is specified, any implicit method found 6830b57cec5SDimitry Andric /// in this category is ignored. 6840b57cec5SDimitry Andric ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel, 6850b57cec5SDimitry Andric bool isInstance, 6860b57cec5SDimitry Andric bool shallowCategoryLookup, 6870b57cec5SDimitry Andric bool followSuper, 6880b57cec5SDimitry Andric const ObjCCategoryDecl *C) const 6890b57cec5SDimitry Andric { 6900b57cec5SDimitry Andric // FIXME: Should make sure no callers ever do this. 6910b57cec5SDimitry Andric if (!hasDefinition()) 6920b57cec5SDimitry Andric return nullptr; 6930b57cec5SDimitry Andric 6940b57cec5SDimitry Andric const ObjCInterfaceDecl* ClassDecl = this; 6950b57cec5SDimitry Andric ObjCMethodDecl *MethodDecl = nullptr; 6960b57cec5SDimitry Andric 6970b57cec5SDimitry Andric if (data().ExternallyCompleted) 6980b57cec5SDimitry Andric LoadExternalDefinition(); 6990b57cec5SDimitry Andric 7000b57cec5SDimitry Andric while (ClassDecl) { 7010b57cec5SDimitry Andric // 1. Look through primary class. 7020b57cec5SDimitry Andric if ((MethodDecl = ClassDecl->getMethod(Sel, isInstance))) 7030b57cec5SDimitry Andric return MethodDecl; 7040b57cec5SDimitry Andric 7050b57cec5SDimitry Andric // 2. Didn't find one yet - now look through categories. 7060b57cec5SDimitry Andric for (const auto *Cat : ClassDecl->visible_categories()) 7070b57cec5SDimitry Andric if ((MethodDecl = Cat->getMethod(Sel, isInstance))) 7080b57cec5SDimitry Andric if (C != Cat || !MethodDecl->isImplicit()) 7090b57cec5SDimitry Andric return MethodDecl; 7100b57cec5SDimitry Andric 7110b57cec5SDimitry Andric // 3. Didn't find one yet - look through primary class's protocols. 7120b57cec5SDimitry Andric for (const auto *I : ClassDecl->protocols()) 7130b57cec5SDimitry Andric if ((MethodDecl = I->lookupMethod(Sel, isInstance))) 7140b57cec5SDimitry Andric return MethodDecl; 7150b57cec5SDimitry Andric 7160b57cec5SDimitry Andric // 4. Didn't find one yet - now look through categories' protocols 7170b57cec5SDimitry Andric if (!shallowCategoryLookup) 7180b57cec5SDimitry Andric for (const auto *Cat : ClassDecl->visible_categories()) { 7190b57cec5SDimitry Andric // Didn't find one yet - look through protocols. 7200b57cec5SDimitry Andric const ObjCList<ObjCProtocolDecl> &Protocols = 7210b57cec5SDimitry Andric Cat->getReferencedProtocols(); 7220b57cec5SDimitry Andric for (auto *Protocol : Protocols) 7230b57cec5SDimitry Andric if ((MethodDecl = Protocol->lookupMethod(Sel, isInstance))) 7240b57cec5SDimitry Andric if (C != Cat || !MethodDecl->isImplicit()) 7250b57cec5SDimitry Andric return MethodDecl; 7260b57cec5SDimitry Andric } 7270b57cec5SDimitry Andric 7280b57cec5SDimitry Andric 7290b57cec5SDimitry Andric if (!followSuper) 7300b57cec5SDimitry Andric return nullptr; 7310b57cec5SDimitry Andric 7320b57cec5SDimitry Andric // 5. Get to the super class (if any). 7330b57cec5SDimitry Andric ClassDecl = ClassDecl->getSuperClass(); 7340b57cec5SDimitry Andric } 7350b57cec5SDimitry Andric return nullptr; 7360b57cec5SDimitry Andric } 7370b57cec5SDimitry Andric 7380b57cec5SDimitry Andric // Will search "local" class/category implementations for a method decl. 7390b57cec5SDimitry Andric // If failed, then we search in class's root for an instance method. 7400b57cec5SDimitry Andric // Returns 0 if no method is found. 7410b57cec5SDimitry Andric ObjCMethodDecl *ObjCInterfaceDecl::lookupPrivateMethod( 7420b57cec5SDimitry Andric const Selector &Sel, 7430b57cec5SDimitry Andric bool Instance) const { 7440b57cec5SDimitry Andric // FIXME: Should make sure no callers ever do this. 7450b57cec5SDimitry Andric if (!hasDefinition()) 7460b57cec5SDimitry Andric return nullptr; 7470b57cec5SDimitry Andric 7480b57cec5SDimitry Andric if (data().ExternallyCompleted) 7490b57cec5SDimitry Andric LoadExternalDefinition(); 7500b57cec5SDimitry Andric 7510b57cec5SDimitry Andric ObjCMethodDecl *Method = nullptr; 7520b57cec5SDimitry Andric if (ObjCImplementationDecl *ImpDecl = getImplementation()) 7530b57cec5SDimitry Andric Method = Instance ? ImpDecl->getInstanceMethod(Sel) 7540b57cec5SDimitry Andric : ImpDecl->getClassMethod(Sel); 7550b57cec5SDimitry Andric 7560b57cec5SDimitry Andric // Look through local category implementations associated with the class. 7570b57cec5SDimitry Andric if (!Method) 7580b57cec5SDimitry Andric Method = getCategoryMethod(Sel, Instance); 7590b57cec5SDimitry Andric 7600b57cec5SDimitry Andric // Before we give up, check if the selector is an instance method. 7610b57cec5SDimitry Andric // But only in the root. This matches gcc's behavior and what the 7620b57cec5SDimitry Andric // runtime expects. 7630b57cec5SDimitry Andric if (!Instance && !Method && !getSuperClass()) { 7640b57cec5SDimitry Andric Method = lookupInstanceMethod(Sel); 7650b57cec5SDimitry Andric // Look through local category implementations associated 7660b57cec5SDimitry Andric // with the root class. 7670b57cec5SDimitry Andric if (!Method) 7680b57cec5SDimitry Andric Method = lookupPrivateMethod(Sel, true); 7690b57cec5SDimitry Andric } 7700b57cec5SDimitry Andric 7710b57cec5SDimitry Andric if (!Method && getSuperClass()) 7720b57cec5SDimitry Andric return getSuperClass()->lookupPrivateMethod(Sel, Instance); 7730b57cec5SDimitry Andric return Method; 7740b57cec5SDimitry Andric } 7750b57cec5SDimitry Andric 7760b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 7770b57cec5SDimitry Andric // ObjCMethodDecl 7780b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 7790b57cec5SDimitry Andric 780480093f4SDimitry Andric ObjCMethodDecl::ObjCMethodDecl( 781480093f4SDimitry Andric SourceLocation beginLoc, SourceLocation endLoc, Selector SelInfo, 782480093f4SDimitry Andric QualType T, TypeSourceInfo *ReturnTInfo, DeclContext *contextDecl, 783480093f4SDimitry Andric bool isInstance, bool isVariadic, bool isPropertyAccessor, 784480093f4SDimitry Andric bool isSynthesizedAccessorStub, bool isImplicitlyDeclared, bool isDefined, 785480093f4SDimitry Andric ImplementationControl impControl, bool HasRelatedResultType) 7860b57cec5SDimitry Andric : NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo), 7870b57cec5SDimitry Andric DeclContext(ObjCMethod), MethodDeclType(T), ReturnTInfo(ReturnTInfo), 7880b57cec5SDimitry Andric DeclEndLoc(endLoc) { 7890b57cec5SDimitry Andric 7900b57cec5SDimitry Andric // Initialized the bits stored in DeclContext. 7910b57cec5SDimitry Andric ObjCMethodDeclBits.Family = 7920b57cec5SDimitry Andric static_cast<ObjCMethodFamily>(InvalidObjCMethodFamily); 7930b57cec5SDimitry Andric setInstanceMethod(isInstance); 7940b57cec5SDimitry Andric setVariadic(isVariadic); 7950b57cec5SDimitry Andric setPropertyAccessor(isPropertyAccessor); 796480093f4SDimitry Andric setSynthesizedAccessorStub(isSynthesizedAccessorStub); 7970b57cec5SDimitry Andric setDefined(isDefined); 7980b57cec5SDimitry Andric setIsRedeclaration(false); 7990b57cec5SDimitry Andric setHasRedeclaration(false); 8000b57cec5SDimitry Andric setDeclImplementation(impControl); 8010b57cec5SDimitry Andric setObjCDeclQualifier(OBJC_TQ_None); 8020b57cec5SDimitry Andric setRelatedResultType(HasRelatedResultType); 8030b57cec5SDimitry Andric setSelLocsKind(SelLoc_StandardNoSpace); 8040b57cec5SDimitry Andric setOverriding(false); 8050b57cec5SDimitry Andric setHasSkippedBody(false); 8060b57cec5SDimitry Andric 8070b57cec5SDimitry Andric setImplicit(isImplicitlyDeclared); 8080b57cec5SDimitry Andric } 8090b57cec5SDimitry Andric 8100b57cec5SDimitry Andric ObjCMethodDecl *ObjCMethodDecl::Create( 8110b57cec5SDimitry Andric ASTContext &C, SourceLocation beginLoc, SourceLocation endLoc, 8120b57cec5SDimitry Andric Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo, 8130b57cec5SDimitry Andric DeclContext *contextDecl, bool isInstance, bool isVariadic, 814480093f4SDimitry Andric bool isPropertyAccessor, bool isSynthesizedAccessorStub, 815480093f4SDimitry Andric bool isImplicitlyDeclared, bool isDefined, ImplementationControl impControl, 816480093f4SDimitry Andric bool HasRelatedResultType) { 8170b57cec5SDimitry Andric return new (C, contextDecl) ObjCMethodDecl( 8180b57cec5SDimitry Andric beginLoc, endLoc, SelInfo, T, ReturnTInfo, contextDecl, isInstance, 819480093f4SDimitry Andric isVariadic, isPropertyAccessor, isSynthesizedAccessorStub, 820480093f4SDimitry Andric isImplicitlyDeclared, isDefined, impControl, HasRelatedResultType); 8210b57cec5SDimitry Andric } 8220b57cec5SDimitry Andric 8230b57cec5SDimitry Andric ObjCMethodDecl *ObjCMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) { 8240b57cec5SDimitry Andric return new (C, ID) ObjCMethodDecl(SourceLocation(), SourceLocation(), 8250b57cec5SDimitry Andric Selector(), QualType(), nullptr, nullptr); 8260b57cec5SDimitry Andric } 8270b57cec5SDimitry Andric 828480093f4SDimitry Andric bool ObjCMethodDecl::isDirectMethod() const { 829480093f4SDimitry Andric return hasAttr<ObjCDirectAttr>(); 830480093f4SDimitry Andric } 831480093f4SDimitry Andric 8320b57cec5SDimitry Andric bool ObjCMethodDecl::isThisDeclarationADesignatedInitializer() const { 8330b57cec5SDimitry Andric return getMethodFamily() == OMF_init && 8340b57cec5SDimitry Andric hasAttr<ObjCDesignatedInitializerAttr>(); 8350b57cec5SDimitry Andric } 8360b57cec5SDimitry Andric 8370b57cec5SDimitry Andric bool ObjCMethodDecl::definedInNSObject(const ASTContext &Ctx) const { 8380b57cec5SDimitry Andric if (const auto *PD = dyn_cast<const ObjCProtocolDecl>(getDeclContext())) 8390b57cec5SDimitry Andric return PD->getIdentifier() == Ctx.getNSObjectName(); 8400b57cec5SDimitry Andric if (const auto *ID = dyn_cast<const ObjCInterfaceDecl>(getDeclContext())) 8410b57cec5SDimitry Andric return ID->getIdentifier() == Ctx.getNSObjectName(); 8420b57cec5SDimitry Andric return false; 8430b57cec5SDimitry Andric } 8440b57cec5SDimitry Andric 8450b57cec5SDimitry Andric bool ObjCMethodDecl::isDesignatedInitializerForTheInterface( 8460b57cec5SDimitry Andric const ObjCMethodDecl **InitMethod) const { 8470b57cec5SDimitry Andric if (getMethodFamily() != OMF_init) 8480b57cec5SDimitry Andric return false; 8490b57cec5SDimitry Andric const DeclContext *DC = getDeclContext(); 8500b57cec5SDimitry Andric if (isa<ObjCProtocolDecl>(DC)) 8510b57cec5SDimitry Andric return false; 8520b57cec5SDimitry Andric if (const ObjCInterfaceDecl *ID = getClassInterface()) 8530b57cec5SDimitry Andric return ID->isDesignatedInitializer(getSelector(), InitMethod); 8540b57cec5SDimitry Andric return false; 8550b57cec5SDimitry Andric } 8560b57cec5SDimitry Andric 8570b57cec5SDimitry Andric Stmt *ObjCMethodDecl::getBody() const { 8580b57cec5SDimitry Andric return Body.get(getASTContext().getExternalSource()); 8590b57cec5SDimitry Andric } 8600b57cec5SDimitry Andric 8610b57cec5SDimitry Andric void ObjCMethodDecl::setAsRedeclaration(const ObjCMethodDecl *PrevMethod) { 8620b57cec5SDimitry Andric assert(PrevMethod); 8630b57cec5SDimitry Andric getASTContext().setObjCMethodRedeclaration(PrevMethod, this); 8640b57cec5SDimitry Andric setIsRedeclaration(true); 8650b57cec5SDimitry Andric PrevMethod->setHasRedeclaration(true); 8660b57cec5SDimitry Andric } 8670b57cec5SDimitry Andric 8680b57cec5SDimitry Andric void ObjCMethodDecl::setParamsAndSelLocs(ASTContext &C, 8690b57cec5SDimitry Andric ArrayRef<ParmVarDecl*> Params, 8700b57cec5SDimitry Andric ArrayRef<SourceLocation> SelLocs) { 8710b57cec5SDimitry Andric ParamsAndSelLocs = nullptr; 8720b57cec5SDimitry Andric NumParams = Params.size(); 8730b57cec5SDimitry Andric if (Params.empty() && SelLocs.empty()) 8740b57cec5SDimitry Andric return; 8750b57cec5SDimitry Andric 8760b57cec5SDimitry Andric static_assert(alignof(ParmVarDecl *) >= alignof(SourceLocation), 8770b57cec5SDimitry Andric "Alignment not sufficient for SourceLocation"); 8780b57cec5SDimitry Andric 8790b57cec5SDimitry Andric unsigned Size = sizeof(ParmVarDecl *) * NumParams + 8800b57cec5SDimitry Andric sizeof(SourceLocation) * SelLocs.size(); 8810b57cec5SDimitry Andric ParamsAndSelLocs = C.Allocate(Size); 8820b57cec5SDimitry Andric std::copy(Params.begin(), Params.end(), getParams()); 8830b57cec5SDimitry Andric std::copy(SelLocs.begin(), SelLocs.end(), getStoredSelLocs()); 8840b57cec5SDimitry Andric } 8850b57cec5SDimitry Andric 8860b57cec5SDimitry Andric void ObjCMethodDecl::getSelectorLocs( 8870b57cec5SDimitry Andric SmallVectorImpl<SourceLocation> &SelLocs) const { 8880b57cec5SDimitry Andric for (unsigned i = 0, e = getNumSelectorLocs(); i != e; ++i) 8890b57cec5SDimitry Andric SelLocs.push_back(getSelectorLoc(i)); 8900b57cec5SDimitry Andric } 8910b57cec5SDimitry Andric 8920b57cec5SDimitry Andric void ObjCMethodDecl::setMethodParams(ASTContext &C, 8930b57cec5SDimitry Andric ArrayRef<ParmVarDecl*> Params, 8940b57cec5SDimitry Andric ArrayRef<SourceLocation> SelLocs) { 8950b57cec5SDimitry Andric assert((!SelLocs.empty() || isImplicit()) && 8960b57cec5SDimitry Andric "No selector locs for non-implicit method"); 8970b57cec5SDimitry Andric if (isImplicit()) 8980b57cec5SDimitry Andric return setParamsAndSelLocs(C, Params, llvm::None); 8990b57cec5SDimitry Andric 9000b57cec5SDimitry Andric setSelLocsKind(hasStandardSelectorLocs(getSelector(), SelLocs, Params, 9010b57cec5SDimitry Andric DeclEndLoc)); 9020b57cec5SDimitry Andric if (getSelLocsKind() != SelLoc_NonStandard) 9030b57cec5SDimitry Andric return setParamsAndSelLocs(C, Params, llvm::None); 9040b57cec5SDimitry Andric 9050b57cec5SDimitry Andric setParamsAndSelLocs(C, Params, SelLocs); 9060b57cec5SDimitry Andric } 9070b57cec5SDimitry Andric 9080b57cec5SDimitry Andric /// A definition will return its interface declaration. 9090b57cec5SDimitry Andric /// An interface declaration will return its definition. 9100b57cec5SDimitry Andric /// Otherwise it will return itself. 9110b57cec5SDimitry Andric ObjCMethodDecl *ObjCMethodDecl::getNextRedeclarationImpl() { 9120b57cec5SDimitry Andric ASTContext &Ctx = getASTContext(); 9130b57cec5SDimitry Andric ObjCMethodDecl *Redecl = nullptr; 9140b57cec5SDimitry Andric if (hasRedeclaration()) 9150b57cec5SDimitry Andric Redecl = const_cast<ObjCMethodDecl*>(Ctx.getObjCMethodRedeclaration(this)); 9160b57cec5SDimitry Andric if (Redecl) 9170b57cec5SDimitry Andric return Redecl; 9180b57cec5SDimitry Andric 9190b57cec5SDimitry Andric auto *CtxD = cast<Decl>(getDeclContext()); 9200b57cec5SDimitry Andric 9210b57cec5SDimitry Andric if (!CtxD->isInvalidDecl()) { 9220b57cec5SDimitry Andric if (auto *IFD = dyn_cast<ObjCInterfaceDecl>(CtxD)) { 9230b57cec5SDimitry Andric if (ObjCImplementationDecl *ImplD = Ctx.getObjCImplementation(IFD)) 9240b57cec5SDimitry Andric if (!ImplD->isInvalidDecl()) 9250b57cec5SDimitry Andric Redecl = ImplD->getMethod(getSelector(), isInstanceMethod()); 9260b57cec5SDimitry Andric 9270b57cec5SDimitry Andric } else if (auto *CD = dyn_cast<ObjCCategoryDecl>(CtxD)) { 9280b57cec5SDimitry Andric if (ObjCCategoryImplDecl *ImplD = Ctx.getObjCImplementation(CD)) 9290b57cec5SDimitry Andric if (!ImplD->isInvalidDecl()) 9300b57cec5SDimitry Andric Redecl = ImplD->getMethod(getSelector(), isInstanceMethod()); 9310b57cec5SDimitry Andric 9320b57cec5SDimitry Andric } else if (auto *ImplD = dyn_cast<ObjCImplementationDecl>(CtxD)) { 9330b57cec5SDimitry Andric if (ObjCInterfaceDecl *IFD = ImplD->getClassInterface()) 9340b57cec5SDimitry Andric if (!IFD->isInvalidDecl()) 9350b57cec5SDimitry Andric Redecl = IFD->getMethod(getSelector(), isInstanceMethod()); 9360b57cec5SDimitry Andric 9370b57cec5SDimitry Andric } else if (auto *CImplD = dyn_cast<ObjCCategoryImplDecl>(CtxD)) { 9380b57cec5SDimitry Andric if (ObjCCategoryDecl *CatD = CImplD->getCategoryDecl()) 9390b57cec5SDimitry Andric if (!CatD->isInvalidDecl()) 9400b57cec5SDimitry Andric Redecl = CatD->getMethod(getSelector(), isInstanceMethod()); 9410b57cec5SDimitry Andric } 9420b57cec5SDimitry Andric } 9430b57cec5SDimitry Andric 9440b57cec5SDimitry Andric // Ensure that the discovered method redeclaration has a valid declaration 9450b57cec5SDimitry Andric // context. Used to prevent infinite loops when iterating redeclarations in 9460b57cec5SDimitry Andric // a partially invalid AST. 9470b57cec5SDimitry Andric if (Redecl && cast<Decl>(Redecl->getDeclContext())->isInvalidDecl()) 9480b57cec5SDimitry Andric Redecl = nullptr; 9490b57cec5SDimitry Andric 9500b57cec5SDimitry Andric if (!Redecl && isRedeclaration()) { 9510b57cec5SDimitry Andric // This is the last redeclaration, go back to the first method. 9520b57cec5SDimitry Andric return cast<ObjCContainerDecl>(CtxD)->getMethod(getSelector(), 953*e8d8bef9SDimitry Andric isInstanceMethod(), 954*e8d8bef9SDimitry Andric /*AllowHidden=*/true); 9550b57cec5SDimitry Andric } 9560b57cec5SDimitry Andric 9570b57cec5SDimitry Andric return Redecl ? Redecl : this; 9580b57cec5SDimitry Andric } 9590b57cec5SDimitry Andric 9600b57cec5SDimitry Andric ObjCMethodDecl *ObjCMethodDecl::getCanonicalDecl() { 9610b57cec5SDimitry Andric auto *CtxD = cast<Decl>(getDeclContext()); 962480093f4SDimitry Andric const auto &Sel = getSelector(); 9630b57cec5SDimitry Andric 9640b57cec5SDimitry Andric if (auto *ImplD = dyn_cast<ObjCImplementationDecl>(CtxD)) { 965480093f4SDimitry Andric if (ObjCInterfaceDecl *IFD = ImplD->getClassInterface()) { 966480093f4SDimitry Andric // When the container is the ObjCImplementationDecl (the primary 967480093f4SDimitry Andric // @implementation), then the canonical Decl is either in 968480093f4SDimitry Andric // the class Interface, or in any of its extension. 969480093f4SDimitry Andric // 970480093f4SDimitry Andric // So when we don't find it in the ObjCInterfaceDecl, 971480093f4SDimitry Andric // sift through extensions too. 972480093f4SDimitry Andric if (ObjCMethodDecl *MD = IFD->getMethod(Sel, isInstanceMethod())) 9730b57cec5SDimitry Andric return MD; 974480093f4SDimitry Andric for (auto *Ext : IFD->known_extensions()) 975480093f4SDimitry Andric if (ObjCMethodDecl *MD = Ext->getMethod(Sel, isInstanceMethod())) 976480093f4SDimitry Andric return MD; 977480093f4SDimitry Andric } 9780b57cec5SDimitry Andric } else if (auto *CImplD = dyn_cast<ObjCCategoryImplDecl>(CtxD)) { 9790b57cec5SDimitry Andric if (ObjCCategoryDecl *CatD = CImplD->getCategoryDecl()) 980480093f4SDimitry Andric if (ObjCMethodDecl *MD = CatD->getMethod(Sel, isInstanceMethod())) 9810b57cec5SDimitry Andric return MD; 9820b57cec5SDimitry Andric } 9830b57cec5SDimitry Andric 9840b57cec5SDimitry Andric if (isRedeclaration()) { 9850b57cec5SDimitry Andric // It is possible that we have not done deserializing the ObjCMethod yet. 9860b57cec5SDimitry Andric ObjCMethodDecl *MD = 987*e8d8bef9SDimitry Andric cast<ObjCContainerDecl>(CtxD)->getMethod(Sel, isInstanceMethod(), 988*e8d8bef9SDimitry Andric /*AllowHidden=*/true); 9890b57cec5SDimitry Andric return MD ? MD : this; 9900b57cec5SDimitry Andric } 9910b57cec5SDimitry Andric 9920b57cec5SDimitry Andric return this; 9930b57cec5SDimitry Andric } 9940b57cec5SDimitry Andric 9950b57cec5SDimitry Andric SourceLocation ObjCMethodDecl::getEndLoc() const { 9960b57cec5SDimitry Andric if (Stmt *Body = getBody()) 9970b57cec5SDimitry Andric return Body->getEndLoc(); 9980b57cec5SDimitry Andric return DeclEndLoc; 9990b57cec5SDimitry Andric } 10000b57cec5SDimitry Andric 10010b57cec5SDimitry Andric ObjCMethodFamily ObjCMethodDecl::getMethodFamily() const { 10020b57cec5SDimitry Andric auto family = static_cast<ObjCMethodFamily>(ObjCMethodDeclBits.Family); 10030b57cec5SDimitry Andric if (family != static_cast<unsigned>(InvalidObjCMethodFamily)) 10040b57cec5SDimitry Andric return family; 10050b57cec5SDimitry Andric 10060b57cec5SDimitry Andric // Check for an explicit attribute. 10070b57cec5SDimitry Andric if (const ObjCMethodFamilyAttr *attr = getAttr<ObjCMethodFamilyAttr>()) { 10080b57cec5SDimitry Andric // The unfortunate necessity of mapping between enums here is due 10090b57cec5SDimitry Andric // to the attributes framework. 10100b57cec5SDimitry Andric switch (attr->getFamily()) { 10110b57cec5SDimitry Andric case ObjCMethodFamilyAttr::OMF_None: family = OMF_None; break; 10120b57cec5SDimitry Andric case ObjCMethodFamilyAttr::OMF_alloc: family = OMF_alloc; break; 10130b57cec5SDimitry Andric case ObjCMethodFamilyAttr::OMF_copy: family = OMF_copy; break; 10140b57cec5SDimitry Andric case ObjCMethodFamilyAttr::OMF_init: family = OMF_init; break; 10150b57cec5SDimitry Andric case ObjCMethodFamilyAttr::OMF_mutableCopy: family = OMF_mutableCopy; break; 10160b57cec5SDimitry Andric case ObjCMethodFamilyAttr::OMF_new: family = OMF_new; break; 10170b57cec5SDimitry Andric } 10180b57cec5SDimitry Andric ObjCMethodDeclBits.Family = family; 10190b57cec5SDimitry Andric return family; 10200b57cec5SDimitry Andric } 10210b57cec5SDimitry Andric 10220b57cec5SDimitry Andric family = getSelector().getMethodFamily(); 10230b57cec5SDimitry Andric switch (family) { 10240b57cec5SDimitry Andric case OMF_None: break; 10250b57cec5SDimitry Andric 10260b57cec5SDimitry Andric // init only has a conventional meaning for an instance method, and 10270b57cec5SDimitry Andric // it has to return an object. 10280b57cec5SDimitry Andric case OMF_init: 10290b57cec5SDimitry Andric if (!isInstanceMethod() || !getReturnType()->isObjCObjectPointerType()) 10300b57cec5SDimitry Andric family = OMF_None; 10310b57cec5SDimitry Andric break; 10320b57cec5SDimitry Andric 10330b57cec5SDimitry Andric // alloc/copy/new have a conventional meaning for both class and 10340b57cec5SDimitry Andric // instance methods, but they require an object return. 10350b57cec5SDimitry Andric case OMF_alloc: 10360b57cec5SDimitry Andric case OMF_copy: 10370b57cec5SDimitry Andric case OMF_mutableCopy: 10380b57cec5SDimitry Andric case OMF_new: 10390b57cec5SDimitry Andric if (!getReturnType()->isObjCObjectPointerType()) 10400b57cec5SDimitry Andric family = OMF_None; 10410b57cec5SDimitry Andric break; 10420b57cec5SDimitry Andric 10430b57cec5SDimitry Andric // These selectors have a conventional meaning only for instance methods. 10440b57cec5SDimitry Andric case OMF_dealloc: 10450b57cec5SDimitry Andric case OMF_finalize: 10460b57cec5SDimitry Andric case OMF_retain: 10470b57cec5SDimitry Andric case OMF_release: 10480b57cec5SDimitry Andric case OMF_autorelease: 10490b57cec5SDimitry Andric case OMF_retainCount: 10500b57cec5SDimitry Andric case OMF_self: 10510b57cec5SDimitry Andric if (!isInstanceMethod()) 10520b57cec5SDimitry Andric family = OMF_None; 10530b57cec5SDimitry Andric break; 10540b57cec5SDimitry Andric 10550b57cec5SDimitry Andric case OMF_initialize: 10560b57cec5SDimitry Andric if (isInstanceMethod() || !getReturnType()->isVoidType()) 10570b57cec5SDimitry Andric family = OMF_None; 10580b57cec5SDimitry Andric break; 10590b57cec5SDimitry Andric 10600b57cec5SDimitry Andric case OMF_performSelector: 10610b57cec5SDimitry Andric if (!isInstanceMethod() || !getReturnType()->isObjCIdType()) 10620b57cec5SDimitry Andric family = OMF_None; 10630b57cec5SDimitry Andric else { 10640b57cec5SDimitry Andric unsigned noParams = param_size(); 10650b57cec5SDimitry Andric if (noParams < 1 || noParams > 3) 10660b57cec5SDimitry Andric family = OMF_None; 10670b57cec5SDimitry Andric else { 10680b57cec5SDimitry Andric ObjCMethodDecl::param_type_iterator it = param_type_begin(); 10690b57cec5SDimitry Andric QualType ArgT = (*it); 10700b57cec5SDimitry Andric if (!ArgT->isObjCSelType()) { 10710b57cec5SDimitry Andric family = OMF_None; 10720b57cec5SDimitry Andric break; 10730b57cec5SDimitry Andric } 10740b57cec5SDimitry Andric while (--noParams) { 10750b57cec5SDimitry Andric it++; 10760b57cec5SDimitry Andric ArgT = (*it); 10770b57cec5SDimitry Andric if (!ArgT->isObjCIdType()) { 10780b57cec5SDimitry Andric family = OMF_None; 10790b57cec5SDimitry Andric break; 10800b57cec5SDimitry Andric } 10810b57cec5SDimitry Andric } 10820b57cec5SDimitry Andric } 10830b57cec5SDimitry Andric } 10840b57cec5SDimitry Andric break; 10850b57cec5SDimitry Andric 10860b57cec5SDimitry Andric } 10870b57cec5SDimitry Andric 10880b57cec5SDimitry Andric // Cache the result. 10890b57cec5SDimitry Andric ObjCMethodDeclBits.Family = family; 10900b57cec5SDimitry Andric return family; 10910b57cec5SDimitry Andric } 10920b57cec5SDimitry Andric 10930b57cec5SDimitry Andric QualType ObjCMethodDecl::getSelfType(ASTContext &Context, 10940b57cec5SDimitry Andric const ObjCInterfaceDecl *OID, 10950b57cec5SDimitry Andric bool &selfIsPseudoStrong, 1096480093f4SDimitry Andric bool &selfIsConsumed) const { 10970b57cec5SDimitry Andric QualType selfTy; 10980b57cec5SDimitry Andric selfIsPseudoStrong = false; 10990b57cec5SDimitry Andric selfIsConsumed = false; 11000b57cec5SDimitry Andric if (isInstanceMethod()) { 11010b57cec5SDimitry Andric // There may be no interface context due to error in declaration 11020b57cec5SDimitry Andric // of the interface (which has been reported). Recover gracefully. 11030b57cec5SDimitry Andric if (OID) { 11040b57cec5SDimitry Andric selfTy = Context.getObjCInterfaceType(OID); 11050b57cec5SDimitry Andric selfTy = Context.getObjCObjectPointerType(selfTy); 11060b57cec5SDimitry Andric } else { 11070b57cec5SDimitry Andric selfTy = Context.getObjCIdType(); 11080b57cec5SDimitry Andric } 11090b57cec5SDimitry Andric } else // we have a factory method. 11100b57cec5SDimitry Andric selfTy = Context.getObjCClassType(); 11110b57cec5SDimitry Andric 11120b57cec5SDimitry Andric if (Context.getLangOpts().ObjCAutoRefCount) { 11130b57cec5SDimitry Andric if (isInstanceMethod()) { 11140b57cec5SDimitry Andric selfIsConsumed = hasAttr<NSConsumesSelfAttr>(); 11150b57cec5SDimitry Andric 11160b57cec5SDimitry Andric // 'self' is always __strong. It's actually pseudo-strong except 11170b57cec5SDimitry Andric // in init methods (or methods labeled ns_consumes_self), though. 11180b57cec5SDimitry Andric Qualifiers qs; 11190b57cec5SDimitry Andric qs.setObjCLifetime(Qualifiers::OCL_Strong); 11200b57cec5SDimitry Andric selfTy = Context.getQualifiedType(selfTy, qs); 11210b57cec5SDimitry Andric 11220b57cec5SDimitry Andric // In addition, 'self' is const unless this is an init method. 11230b57cec5SDimitry Andric if (getMethodFamily() != OMF_init && !selfIsConsumed) { 11240b57cec5SDimitry Andric selfTy = selfTy.withConst(); 11250b57cec5SDimitry Andric selfIsPseudoStrong = true; 11260b57cec5SDimitry Andric } 11270b57cec5SDimitry Andric } 11280b57cec5SDimitry Andric else { 11290b57cec5SDimitry Andric assert(isClassMethod()); 11300b57cec5SDimitry Andric // 'self' is always const in class methods. 11310b57cec5SDimitry Andric selfTy = selfTy.withConst(); 11320b57cec5SDimitry Andric selfIsPseudoStrong = true; 11330b57cec5SDimitry Andric } 11340b57cec5SDimitry Andric } 11350b57cec5SDimitry Andric return selfTy; 11360b57cec5SDimitry Andric } 11370b57cec5SDimitry Andric 11380b57cec5SDimitry Andric void ObjCMethodDecl::createImplicitParams(ASTContext &Context, 11390b57cec5SDimitry Andric const ObjCInterfaceDecl *OID) { 11400b57cec5SDimitry Andric bool selfIsPseudoStrong, selfIsConsumed; 11410b57cec5SDimitry Andric QualType selfTy = 11420b57cec5SDimitry Andric getSelfType(Context, OID, selfIsPseudoStrong, selfIsConsumed); 11430b57cec5SDimitry Andric auto *Self = ImplicitParamDecl::Create(Context, this, SourceLocation(), 11440b57cec5SDimitry Andric &Context.Idents.get("self"), selfTy, 11450b57cec5SDimitry Andric ImplicitParamDecl::ObjCSelf); 11460b57cec5SDimitry Andric setSelfDecl(Self); 11470b57cec5SDimitry Andric 11480b57cec5SDimitry Andric if (selfIsConsumed) 11490b57cec5SDimitry Andric Self->addAttr(NSConsumedAttr::CreateImplicit(Context)); 11500b57cec5SDimitry Andric 11510b57cec5SDimitry Andric if (selfIsPseudoStrong) 11520b57cec5SDimitry Andric Self->setARCPseudoStrong(true); 11530b57cec5SDimitry Andric 11540b57cec5SDimitry Andric setCmdDecl(ImplicitParamDecl::Create( 11550b57cec5SDimitry Andric Context, this, SourceLocation(), &Context.Idents.get("_cmd"), 11560b57cec5SDimitry Andric Context.getObjCSelType(), ImplicitParamDecl::ObjCCmd)); 11570b57cec5SDimitry Andric } 11580b57cec5SDimitry Andric 11590b57cec5SDimitry Andric ObjCInterfaceDecl *ObjCMethodDecl::getClassInterface() { 11600b57cec5SDimitry Andric if (auto *ID = dyn_cast<ObjCInterfaceDecl>(getDeclContext())) 11610b57cec5SDimitry Andric return ID; 11620b57cec5SDimitry Andric if (auto *CD = dyn_cast<ObjCCategoryDecl>(getDeclContext())) 11630b57cec5SDimitry Andric return CD->getClassInterface(); 11640b57cec5SDimitry Andric if (auto *IMD = dyn_cast<ObjCImplDecl>(getDeclContext())) 11650b57cec5SDimitry Andric return IMD->getClassInterface(); 11660b57cec5SDimitry Andric if (isa<ObjCProtocolDecl>(getDeclContext())) 11670b57cec5SDimitry Andric return nullptr; 11680b57cec5SDimitry Andric llvm_unreachable("unknown method context"); 11690b57cec5SDimitry Andric } 11700b57cec5SDimitry Andric 1171*e8d8bef9SDimitry Andric ObjCCategoryDecl *ObjCMethodDecl::getCategory() { 1172*e8d8bef9SDimitry Andric if (auto *CD = dyn_cast<ObjCCategoryDecl>(getDeclContext())) 1173*e8d8bef9SDimitry Andric return CD; 1174*e8d8bef9SDimitry Andric if (auto *IMD = dyn_cast<ObjCCategoryImplDecl>(getDeclContext())) 1175*e8d8bef9SDimitry Andric return IMD->getCategoryDecl(); 1176*e8d8bef9SDimitry Andric return nullptr; 1177*e8d8bef9SDimitry Andric } 1178*e8d8bef9SDimitry Andric 11790b57cec5SDimitry Andric SourceRange ObjCMethodDecl::getReturnTypeSourceRange() const { 11800b57cec5SDimitry Andric const auto *TSI = getReturnTypeSourceInfo(); 11810b57cec5SDimitry Andric if (TSI) 11820b57cec5SDimitry Andric return TSI->getTypeLoc().getSourceRange(); 11830b57cec5SDimitry Andric return SourceRange(); 11840b57cec5SDimitry Andric } 11850b57cec5SDimitry Andric 11860b57cec5SDimitry Andric QualType ObjCMethodDecl::getSendResultType() const { 11870b57cec5SDimitry Andric ASTContext &Ctx = getASTContext(); 11880b57cec5SDimitry Andric return getReturnType().getNonLValueExprType(Ctx) 11890b57cec5SDimitry Andric .substObjCTypeArgs(Ctx, {}, ObjCSubstitutionContext::Result); 11900b57cec5SDimitry Andric } 11910b57cec5SDimitry Andric 11920b57cec5SDimitry Andric QualType ObjCMethodDecl::getSendResultType(QualType receiverType) const { 11930b57cec5SDimitry Andric // FIXME: Handle related result types here. 11940b57cec5SDimitry Andric 11950b57cec5SDimitry Andric return getReturnType().getNonLValueExprType(getASTContext()) 11960b57cec5SDimitry Andric .substObjCMemberType(receiverType, getDeclContext(), 11970b57cec5SDimitry Andric ObjCSubstitutionContext::Result); 11980b57cec5SDimitry Andric } 11990b57cec5SDimitry Andric 12000b57cec5SDimitry Andric static void CollectOverriddenMethodsRecurse(const ObjCContainerDecl *Container, 12010b57cec5SDimitry Andric const ObjCMethodDecl *Method, 12020b57cec5SDimitry Andric SmallVectorImpl<const ObjCMethodDecl *> &Methods, 12030b57cec5SDimitry Andric bool MovedToSuper) { 12040b57cec5SDimitry Andric if (!Container) 12050b57cec5SDimitry Andric return; 12060b57cec5SDimitry Andric 12070b57cec5SDimitry Andric // In categories look for overridden methods from protocols. A method from 12080b57cec5SDimitry Andric // category is not "overridden" since it is considered as the "same" method 12090b57cec5SDimitry Andric // (same USR) as the one from the interface. 12100b57cec5SDimitry Andric if (const auto *Category = dyn_cast<ObjCCategoryDecl>(Container)) { 12110b57cec5SDimitry Andric // Check whether we have a matching method at this category but only if we 12120b57cec5SDimitry Andric // are at the super class level. 12130b57cec5SDimitry Andric if (MovedToSuper) 12140b57cec5SDimitry Andric if (ObjCMethodDecl * 12150b57cec5SDimitry Andric Overridden = Container->getMethod(Method->getSelector(), 12160b57cec5SDimitry Andric Method->isInstanceMethod(), 12170b57cec5SDimitry Andric /*AllowHidden=*/true)) 12180b57cec5SDimitry Andric if (Method != Overridden) { 12190b57cec5SDimitry Andric // We found an override at this category; there is no need to look 12200b57cec5SDimitry Andric // into its protocols. 12210b57cec5SDimitry Andric Methods.push_back(Overridden); 12220b57cec5SDimitry Andric return; 12230b57cec5SDimitry Andric } 12240b57cec5SDimitry Andric 12250b57cec5SDimitry Andric for (const auto *P : Category->protocols()) 12260b57cec5SDimitry Andric CollectOverriddenMethodsRecurse(P, Method, Methods, MovedToSuper); 12270b57cec5SDimitry Andric return; 12280b57cec5SDimitry Andric } 12290b57cec5SDimitry Andric 12300b57cec5SDimitry Andric // Check whether we have a matching method at this level. 12310b57cec5SDimitry Andric if (const ObjCMethodDecl * 12320b57cec5SDimitry Andric Overridden = Container->getMethod(Method->getSelector(), 12330b57cec5SDimitry Andric Method->isInstanceMethod(), 12340b57cec5SDimitry Andric /*AllowHidden=*/true)) 12350b57cec5SDimitry Andric if (Method != Overridden) { 12360b57cec5SDimitry Andric // We found an override at this level; there is no need to look 12370b57cec5SDimitry Andric // into other protocols or categories. 12380b57cec5SDimitry Andric Methods.push_back(Overridden); 12390b57cec5SDimitry Andric return; 12400b57cec5SDimitry Andric } 12410b57cec5SDimitry Andric 12420b57cec5SDimitry Andric if (const auto *Protocol = dyn_cast<ObjCProtocolDecl>(Container)){ 12430b57cec5SDimitry Andric for (const auto *P : Protocol->protocols()) 12440b57cec5SDimitry Andric CollectOverriddenMethodsRecurse(P, Method, Methods, MovedToSuper); 12450b57cec5SDimitry Andric } 12460b57cec5SDimitry Andric 12470b57cec5SDimitry Andric if (const auto *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) { 12480b57cec5SDimitry Andric for (const auto *P : Interface->protocols()) 12490b57cec5SDimitry Andric CollectOverriddenMethodsRecurse(P, Method, Methods, MovedToSuper); 12500b57cec5SDimitry Andric 12510b57cec5SDimitry Andric for (const auto *Cat : Interface->known_categories()) 12520b57cec5SDimitry Andric CollectOverriddenMethodsRecurse(Cat, Method, Methods, MovedToSuper); 12530b57cec5SDimitry Andric 12540b57cec5SDimitry Andric if (const ObjCInterfaceDecl *Super = Interface->getSuperClass()) 12550b57cec5SDimitry Andric return CollectOverriddenMethodsRecurse(Super, Method, Methods, 12560b57cec5SDimitry Andric /*MovedToSuper=*/true); 12570b57cec5SDimitry Andric } 12580b57cec5SDimitry Andric } 12590b57cec5SDimitry Andric 12600b57cec5SDimitry Andric static inline void CollectOverriddenMethods(const ObjCContainerDecl *Container, 12610b57cec5SDimitry Andric const ObjCMethodDecl *Method, 12620b57cec5SDimitry Andric SmallVectorImpl<const ObjCMethodDecl *> &Methods) { 12630b57cec5SDimitry Andric CollectOverriddenMethodsRecurse(Container, Method, Methods, 12640b57cec5SDimitry Andric /*MovedToSuper=*/false); 12650b57cec5SDimitry Andric } 12660b57cec5SDimitry Andric 12670b57cec5SDimitry Andric static void collectOverriddenMethodsSlow(const ObjCMethodDecl *Method, 12680b57cec5SDimitry Andric SmallVectorImpl<const ObjCMethodDecl *> &overridden) { 12690b57cec5SDimitry Andric assert(Method->isOverriding()); 12700b57cec5SDimitry Andric 12710b57cec5SDimitry Andric if (const auto *ProtD = 12720b57cec5SDimitry Andric dyn_cast<ObjCProtocolDecl>(Method->getDeclContext())) { 12730b57cec5SDimitry Andric CollectOverriddenMethods(ProtD, Method, overridden); 12740b57cec5SDimitry Andric 12750b57cec5SDimitry Andric } else if (const auto *IMD = 12760b57cec5SDimitry Andric dyn_cast<ObjCImplDecl>(Method->getDeclContext())) { 12770b57cec5SDimitry Andric const ObjCInterfaceDecl *ID = IMD->getClassInterface(); 12780b57cec5SDimitry Andric if (!ID) 12790b57cec5SDimitry Andric return; 12800b57cec5SDimitry Andric // Start searching for overridden methods using the method from the 12810b57cec5SDimitry Andric // interface as starting point. 12820b57cec5SDimitry Andric if (const ObjCMethodDecl *IFaceMeth = ID->getMethod(Method->getSelector(), 12830b57cec5SDimitry Andric Method->isInstanceMethod(), 12840b57cec5SDimitry Andric /*AllowHidden=*/true)) 12850b57cec5SDimitry Andric Method = IFaceMeth; 12860b57cec5SDimitry Andric CollectOverriddenMethods(ID, Method, overridden); 12870b57cec5SDimitry Andric 12880b57cec5SDimitry Andric } else if (const auto *CatD = 12890b57cec5SDimitry Andric dyn_cast<ObjCCategoryDecl>(Method->getDeclContext())) { 12900b57cec5SDimitry Andric const ObjCInterfaceDecl *ID = CatD->getClassInterface(); 12910b57cec5SDimitry Andric if (!ID) 12920b57cec5SDimitry Andric return; 12930b57cec5SDimitry Andric // Start searching for overridden methods using the method from the 12940b57cec5SDimitry Andric // interface as starting point. 12950b57cec5SDimitry Andric if (const ObjCMethodDecl *IFaceMeth = ID->getMethod(Method->getSelector(), 12960b57cec5SDimitry Andric Method->isInstanceMethod(), 12970b57cec5SDimitry Andric /*AllowHidden=*/true)) 12980b57cec5SDimitry Andric Method = IFaceMeth; 12990b57cec5SDimitry Andric CollectOverriddenMethods(ID, Method, overridden); 13000b57cec5SDimitry Andric 13010b57cec5SDimitry Andric } else { 13020b57cec5SDimitry Andric CollectOverriddenMethods( 13030b57cec5SDimitry Andric dyn_cast_or_null<ObjCContainerDecl>(Method->getDeclContext()), 13040b57cec5SDimitry Andric Method, overridden); 13050b57cec5SDimitry Andric } 13060b57cec5SDimitry Andric } 13070b57cec5SDimitry Andric 13080b57cec5SDimitry Andric void ObjCMethodDecl::getOverriddenMethods( 13090b57cec5SDimitry Andric SmallVectorImpl<const ObjCMethodDecl *> &Overridden) const { 13100b57cec5SDimitry Andric const ObjCMethodDecl *Method = this; 13110b57cec5SDimitry Andric 13120b57cec5SDimitry Andric if (Method->isRedeclaration()) { 1313*e8d8bef9SDimitry Andric Method = cast<ObjCContainerDecl>(Method->getDeclContext()) 1314*e8d8bef9SDimitry Andric ->getMethod(Method->getSelector(), Method->isInstanceMethod(), 1315*e8d8bef9SDimitry Andric /*AllowHidden=*/true); 13160b57cec5SDimitry Andric } 13170b57cec5SDimitry Andric 13180b57cec5SDimitry Andric if (Method->isOverriding()) { 13190b57cec5SDimitry Andric collectOverriddenMethodsSlow(Method, Overridden); 13200b57cec5SDimitry Andric assert(!Overridden.empty() && 13210b57cec5SDimitry Andric "ObjCMethodDecl's overriding bit is not as expected"); 13220b57cec5SDimitry Andric } 13230b57cec5SDimitry Andric } 13240b57cec5SDimitry Andric 13250b57cec5SDimitry Andric const ObjCPropertyDecl * 13260b57cec5SDimitry Andric ObjCMethodDecl::findPropertyDecl(bool CheckOverrides) const { 13270b57cec5SDimitry Andric Selector Sel = getSelector(); 13280b57cec5SDimitry Andric unsigned NumArgs = Sel.getNumArgs(); 13290b57cec5SDimitry Andric if (NumArgs > 1) 13300b57cec5SDimitry Andric return nullptr; 13310b57cec5SDimitry Andric 13320b57cec5SDimitry Andric if (isPropertyAccessor()) { 13330b57cec5SDimitry Andric const auto *Container = cast<ObjCContainerDecl>(getParent()); 1334480093f4SDimitry Andric // For accessor stubs, go back to the interface. 1335480093f4SDimitry Andric if (auto *ImplDecl = dyn_cast<ObjCImplDecl>(Container)) 1336480093f4SDimitry Andric if (isSynthesizedAccessorStub()) 1337480093f4SDimitry Andric Container = ImplDecl->getClassInterface(); 1338480093f4SDimitry Andric 13390b57cec5SDimitry Andric bool IsGetter = (NumArgs == 0); 13400b57cec5SDimitry Andric bool IsInstance = isInstanceMethod(); 13410b57cec5SDimitry Andric 13420b57cec5SDimitry Andric /// Local function that attempts to find a matching property within the 13430b57cec5SDimitry Andric /// given Objective-C container. 13440b57cec5SDimitry Andric auto findMatchingProperty = 13450b57cec5SDimitry Andric [&](const ObjCContainerDecl *Container) -> const ObjCPropertyDecl * { 13460b57cec5SDimitry Andric if (IsInstance) { 13470b57cec5SDimitry Andric for (const auto *I : Container->instance_properties()) { 13480b57cec5SDimitry Andric Selector NextSel = IsGetter ? I->getGetterName() 13490b57cec5SDimitry Andric : I->getSetterName(); 13500b57cec5SDimitry Andric if (NextSel == Sel) 13510b57cec5SDimitry Andric return I; 13520b57cec5SDimitry Andric } 13530b57cec5SDimitry Andric } else { 13540b57cec5SDimitry Andric for (const auto *I : Container->class_properties()) { 13550b57cec5SDimitry Andric Selector NextSel = IsGetter ? I->getGetterName() 13560b57cec5SDimitry Andric : I->getSetterName(); 13570b57cec5SDimitry Andric if (NextSel == Sel) 13580b57cec5SDimitry Andric return I; 13590b57cec5SDimitry Andric } 13600b57cec5SDimitry Andric } 13610b57cec5SDimitry Andric 13620b57cec5SDimitry Andric return nullptr; 13630b57cec5SDimitry Andric }; 13640b57cec5SDimitry Andric 13650b57cec5SDimitry Andric // Look in the container we were given. 13660b57cec5SDimitry Andric if (const auto *Found = findMatchingProperty(Container)) 13670b57cec5SDimitry Andric return Found; 13680b57cec5SDimitry Andric 13690b57cec5SDimitry Andric // If we're in a category or extension, look in the main class. 13700b57cec5SDimitry Andric const ObjCInterfaceDecl *ClassDecl = nullptr; 13710b57cec5SDimitry Andric if (const auto *Category = dyn_cast<ObjCCategoryDecl>(Container)) { 13720b57cec5SDimitry Andric ClassDecl = Category->getClassInterface(); 13730b57cec5SDimitry Andric if (const auto *Found = findMatchingProperty(ClassDecl)) 13740b57cec5SDimitry Andric return Found; 13750b57cec5SDimitry Andric } else { 13760b57cec5SDimitry Andric // Determine whether the container is a class. 13775ffd83dbSDimitry Andric ClassDecl = cast<ObjCInterfaceDecl>(Container); 13780b57cec5SDimitry Andric } 13795ffd83dbSDimitry Andric assert(ClassDecl && "Failed to find main class"); 13800b57cec5SDimitry Andric 13810b57cec5SDimitry Andric // If we have a class, check its visible extensions. 13820b57cec5SDimitry Andric for (const auto *Ext : ClassDecl->visible_extensions()) { 13830b57cec5SDimitry Andric if (Ext == Container) 13840b57cec5SDimitry Andric continue; 13850b57cec5SDimitry Andric if (const auto *Found = findMatchingProperty(Ext)) 13860b57cec5SDimitry Andric return Found; 13870b57cec5SDimitry Andric } 13880b57cec5SDimitry Andric 1389480093f4SDimitry Andric assert(isSynthesizedAccessorStub() && "expected an accessor stub"); 13905ffd83dbSDimitry Andric 1391480093f4SDimitry Andric for (const auto *Cat : ClassDecl->known_categories()) { 1392480093f4SDimitry Andric if (Cat == Container) 1393480093f4SDimitry Andric continue; 1394480093f4SDimitry Andric if (const auto *Found = findMatchingProperty(Cat)) 1395480093f4SDimitry Andric return Found; 1396480093f4SDimitry Andric } 1397480093f4SDimitry Andric 13980b57cec5SDimitry Andric llvm_unreachable("Marked as a property accessor but no property found!"); 13990b57cec5SDimitry Andric } 14000b57cec5SDimitry Andric 14010b57cec5SDimitry Andric if (!CheckOverrides) 14020b57cec5SDimitry Andric return nullptr; 14030b57cec5SDimitry Andric 14040b57cec5SDimitry Andric using OverridesTy = SmallVector<const ObjCMethodDecl *, 8>; 14050b57cec5SDimitry Andric 14060b57cec5SDimitry Andric OverridesTy Overrides; 14070b57cec5SDimitry Andric getOverriddenMethods(Overrides); 14080b57cec5SDimitry Andric for (const auto *Override : Overrides) 14090b57cec5SDimitry Andric if (const ObjCPropertyDecl *Prop = Override->findPropertyDecl(false)) 14100b57cec5SDimitry Andric return Prop; 14110b57cec5SDimitry Andric 14120b57cec5SDimitry Andric return nullptr; 14130b57cec5SDimitry Andric } 14140b57cec5SDimitry Andric 14150b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 14160b57cec5SDimitry Andric // ObjCTypeParamDecl 14170b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 14180b57cec5SDimitry Andric 14190b57cec5SDimitry Andric void ObjCTypeParamDecl::anchor() {} 14200b57cec5SDimitry Andric 14210b57cec5SDimitry Andric ObjCTypeParamDecl *ObjCTypeParamDecl::Create(ASTContext &ctx, DeclContext *dc, 14220b57cec5SDimitry Andric ObjCTypeParamVariance variance, 14230b57cec5SDimitry Andric SourceLocation varianceLoc, 14240b57cec5SDimitry Andric unsigned index, 14250b57cec5SDimitry Andric SourceLocation nameLoc, 14260b57cec5SDimitry Andric IdentifierInfo *name, 14270b57cec5SDimitry Andric SourceLocation colonLoc, 14280b57cec5SDimitry Andric TypeSourceInfo *boundInfo) { 14290b57cec5SDimitry Andric auto *TPDecl = 14300b57cec5SDimitry Andric new (ctx, dc) ObjCTypeParamDecl(ctx, dc, variance, varianceLoc, index, 14310b57cec5SDimitry Andric nameLoc, name, colonLoc, boundInfo); 14320b57cec5SDimitry Andric QualType TPType = ctx.getObjCTypeParamType(TPDecl, {}); 14330b57cec5SDimitry Andric TPDecl->setTypeForDecl(TPType.getTypePtr()); 14340b57cec5SDimitry Andric return TPDecl; 14350b57cec5SDimitry Andric } 14360b57cec5SDimitry Andric 14370b57cec5SDimitry Andric ObjCTypeParamDecl *ObjCTypeParamDecl::CreateDeserialized(ASTContext &ctx, 14380b57cec5SDimitry Andric unsigned ID) { 14390b57cec5SDimitry Andric return new (ctx, ID) ObjCTypeParamDecl(ctx, nullptr, 14400b57cec5SDimitry Andric ObjCTypeParamVariance::Invariant, 14410b57cec5SDimitry Andric SourceLocation(), 0, SourceLocation(), 14420b57cec5SDimitry Andric nullptr, SourceLocation(), nullptr); 14430b57cec5SDimitry Andric } 14440b57cec5SDimitry Andric 14450b57cec5SDimitry Andric SourceRange ObjCTypeParamDecl::getSourceRange() const { 14460b57cec5SDimitry Andric SourceLocation startLoc = VarianceLoc; 14470b57cec5SDimitry Andric if (startLoc.isInvalid()) 14480b57cec5SDimitry Andric startLoc = getLocation(); 14490b57cec5SDimitry Andric 14500b57cec5SDimitry Andric if (hasExplicitBound()) { 14510b57cec5SDimitry Andric return SourceRange(startLoc, 14520b57cec5SDimitry Andric getTypeSourceInfo()->getTypeLoc().getEndLoc()); 14530b57cec5SDimitry Andric } 14540b57cec5SDimitry Andric 14550b57cec5SDimitry Andric return SourceRange(startLoc); 14560b57cec5SDimitry Andric } 14570b57cec5SDimitry Andric 14580b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 14590b57cec5SDimitry Andric // ObjCTypeParamList 14600b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 14610b57cec5SDimitry Andric ObjCTypeParamList::ObjCTypeParamList(SourceLocation lAngleLoc, 14620b57cec5SDimitry Andric ArrayRef<ObjCTypeParamDecl *> typeParams, 14630b57cec5SDimitry Andric SourceLocation rAngleLoc) 1464*e8d8bef9SDimitry Andric : Brackets(lAngleLoc, rAngleLoc), NumParams(typeParams.size()) { 14650b57cec5SDimitry Andric std::copy(typeParams.begin(), typeParams.end(), begin()); 14660b57cec5SDimitry Andric } 14670b57cec5SDimitry Andric 14680b57cec5SDimitry Andric ObjCTypeParamList *ObjCTypeParamList::create( 14690b57cec5SDimitry Andric ASTContext &ctx, 14700b57cec5SDimitry Andric SourceLocation lAngleLoc, 14710b57cec5SDimitry Andric ArrayRef<ObjCTypeParamDecl *> typeParams, 14720b57cec5SDimitry Andric SourceLocation rAngleLoc) { 14730b57cec5SDimitry Andric void *mem = 14740b57cec5SDimitry Andric ctx.Allocate(totalSizeToAlloc<ObjCTypeParamDecl *>(typeParams.size()), 14750b57cec5SDimitry Andric alignof(ObjCTypeParamList)); 14760b57cec5SDimitry Andric return new (mem) ObjCTypeParamList(lAngleLoc, typeParams, rAngleLoc); 14770b57cec5SDimitry Andric } 14780b57cec5SDimitry Andric 14790b57cec5SDimitry Andric void ObjCTypeParamList::gatherDefaultTypeArgs( 14800b57cec5SDimitry Andric SmallVectorImpl<QualType> &typeArgs) const { 14810b57cec5SDimitry Andric typeArgs.reserve(size()); 14820b57cec5SDimitry Andric for (auto typeParam : *this) 14830b57cec5SDimitry Andric typeArgs.push_back(typeParam->getUnderlyingType()); 14840b57cec5SDimitry Andric } 14850b57cec5SDimitry Andric 14860b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 14870b57cec5SDimitry Andric // ObjCInterfaceDecl 14880b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 14890b57cec5SDimitry Andric 14900b57cec5SDimitry Andric ObjCInterfaceDecl *ObjCInterfaceDecl::Create(const ASTContext &C, 14910b57cec5SDimitry Andric DeclContext *DC, 14920b57cec5SDimitry Andric SourceLocation atLoc, 14930b57cec5SDimitry Andric IdentifierInfo *Id, 14940b57cec5SDimitry Andric ObjCTypeParamList *typeParamList, 14950b57cec5SDimitry Andric ObjCInterfaceDecl *PrevDecl, 14960b57cec5SDimitry Andric SourceLocation ClassLoc, 14970b57cec5SDimitry Andric bool isInternal){ 14980b57cec5SDimitry Andric auto *Result = new (C, DC) 14990b57cec5SDimitry Andric ObjCInterfaceDecl(C, DC, atLoc, Id, typeParamList, ClassLoc, PrevDecl, 15000b57cec5SDimitry Andric isInternal); 15010b57cec5SDimitry Andric Result->Data.setInt(!C.getLangOpts().Modules); 15020b57cec5SDimitry Andric C.getObjCInterfaceType(Result, PrevDecl); 15030b57cec5SDimitry Andric return Result; 15040b57cec5SDimitry Andric } 15050b57cec5SDimitry Andric 15060b57cec5SDimitry Andric ObjCInterfaceDecl *ObjCInterfaceDecl::CreateDeserialized(const ASTContext &C, 15070b57cec5SDimitry Andric unsigned ID) { 15080b57cec5SDimitry Andric auto *Result = new (C, ID) 15090b57cec5SDimitry Andric ObjCInterfaceDecl(C, nullptr, SourceLocation(), nullptr, nullptr, 15100b57cec5SDimitry Andric SourceLocation(), nullptr, false); 15110b57cec5SDimitry Andric Result->Data.setInt(!C.getLangOpts().Modules); 15120b57cec5SDimitry Andric return Result; 15130b57cec5SDimitry Andric } 15140b57cec5SDimitry Andric 15150b57cec5SDimitry Andric ObjCInterfaceDecl::ObjCInterfaceDecl(const ASTContext &C, DeclContext *DC, 15160b57cec5SDimitry Andric SourceLocation AtLoc, IdentifierInfo *Id, 15170b57cec5SDimitry Andric ObjCTypeParamList *typeParamList, 15180b57cec5SDimitry Andric SourceLocation CLoc, 15190b57cec5SDimitry Andric ObjCInterfaceDecl *PrevDecl, 15200b57cec5SDimitry Andric bool IsInternal) 15210b57cec5SDimitry Andric : ObjCContainerDecl(ObjCInterface, DC, Id, CLoc, AtLoc), 15220b57cec5SDimitry Andric redeclarable_base(C) { 15230b57cec5SDimitry Andric setPreviousDecl(PrevDecl); 15240b57cec5SDimitry Andric 15250b57cec5SDimitry Andric // Copy the 'data' pointer over. 15260b57cec5SDimitry Andric if (PrevDecl) 15270b57cec5SDimitry Andric Data = PrevDecl->Data; 15280b57cec5SDimitry Andric 15290b57cec5SDimitry Andric setImplicit(IsInternal); 15300b57cec5SDimitry Andric 15310b57cec5SDimitry Andric setTypeParamList(typeParamList); 15320b57cec5SDimitry Andric } 15330b57cec5SDimitry Andric 15340b57cec5SDimitry Andric void ObjCInterfaceDecl::LoadExternalDefinition() const { 15350b57cec5SDimitry Andric assert(data().ExternallyCompleted && "Class is not externally completed"); 15360b57cec5SDimitry Andric data().ExternallyCompleted = false; 15370b57cec5SDimitry Andric getASTContext().getExternalSource()->CompleteType( 15380b57cec5SDimitry Andric const_cast<ObjCInterfaceDecl *>(this)); 15390b57cec5SDimitry Andric } 15400b57cec5SDimitry Andric 15410b57cec5SDimitry Andric void ObjCInterfaceDecl::setExternallyCompleted() { 15420b57cec5SDimitry Andric assert(getASTContext().getExternalSource() && 15430b57cec5SDimitry Andric "Class can't be externally completed without an external source"); 15440b57cec5SDimitry Andric assert(hasDefinition() && 15450b57cec5SDimitry Andric "Forward declarations can't be externally completed"); 15460b57cec5SDimitry Andric data().ExternallyCompleted = true; 15470b57cec5SDimitry Andric } 15480b57cec5SDimitry Andric 15490b57cec5SDimitry Andric void ObjCInterfaceDecl::setHasDesignatedInitializers() { 15500b57cec5SDimitry Andric // Check for a complete definition and recover if not so. 15510b57cec5SDimitry Andric if (!isThisDeclarationADefinition()) 15520b57cec5SDimitry Andric return; 15530b57cec5SDimitry Andric data().HasDesignatedInitializers = true; 15540b57cec5SDimitry Andric } 15550b57cec5SDimitry Andric 15560b57cec5SDimitry Andric bool ObjCInterfaceDecl::hasDesignatedInitializers() const { 15570b57cec5SDimitry Andric // Check for a complete definition and recover if not so. 15580b57cec5SDimitry Andric if (!isThisDeclarationADefinition()) 15590b57cec5SDimitry Andric return false; 15600b57cec5SDimitry Andric if (data().ExternallyCompleted) 15610b57cec5SDimitry Andric LoadExternalDefinition(); 15620b57cec5SDimitry Andric 15630b57cec5SDimitry Andric return data().HasDesignatedInitializers; 15640b57cec5SDimitry Andric } 15650b57cec5SDimitry Andric 15660b57cec5SDimitry Andric StringRef 15670b57cec5SDimitry Andric ObjCInterfaceDecl::getObjCRuntimeNameAsString() const { 15680b57cec5SDimitry Andric if (const auto *ObjCRTName = getAttr<ObjCRuntimeNameAttr>()) 15690b57cec5SDimitry Andric return ObjCRTName->getMetadataName(); 15700b57cec5SDimitry Andric 15710b57cec5SDimitry Andric return getName(); 15720b57cec5SDimitry Andric } 15730b57cec5SDimitry Andric 15740b57cec5SDimitry Andric StringRef 15750b57cec5SDimitry Andric ObjCImplementationDecl::getObjCRuntimeNameAsString() const { 15760b57cec5SDimitry Andric if (ObjCInterfaceDecl *ID = 15770b57cec5SDimitry Andric const_cast<ObjCImplementationDecl*>(this)->getClassInterface()) 15780b57cec5SDimitry Andric return ID->getObjCRuntimeNameAsString(); 15790b57cec5SDimitry Andric 15800b57cec5SDimitry Andric return getName(); 15810b57cec5SDimitry Andric } 15820b57cec5SDimitry Andric 15830b57cec5SDimitry Andric ObjCImplementationDecl *ObjCInterfaceDecl::getImplementation() const { 15840b57cec5SDimitry Andric if (const ObjCInterfaceDecl *Def = getDefinition()) { 15850b57cec5SDimitry Andric if (data().ExternallyCompleted) 15860b57cec5SDimitry Andric LoadExternalDefinition(); 15870b57cec5SDimitry Andric 15880b57cec5SDimitry Andric return getASTContext().getObjCImplementation( 15890b57cec5SDimitry Andric const_cast<ObjCInterfaceDecl*>(Def)); 15900b57cec5SDimitry Andric } 15910b57cec5SDimitry Andric 15920b57cec5SDimitry Andric // FIXME: Should make sure no callers ever do this. 15930b57cec5SDimitry Andric return nullptr; 15940b57cec5SDimitry Andric } 15950b57cec5SDimitry Andric 15960b57cec5SDimitry Andric void ObjCInterfaceDecl::setImplementation(ObjCImplementationDecl *ImplD) { 15970b57cec5SDimitry Andric getASTContext().setObjCImplementation(getDefinition(), ImplD); 15980b57cec5SDimitry Andric } 15990b57cec5SDimitry Andric 16000b57cec5SDimitry Andric namespace { 16010b57cec5SDimitry Andric 16020b57cec5SDimitry Andric struct SynthesizeIvarChunk { 16030b57cec5SDimitry Andric uint64_t Size; 16040b57cec5SDimitry Andric ObjCIvarDecl *Ivar; 16050b57cec5SDimitry Andric 16060b57cec5SDimitry Andric SynthesizeIvarChunk(uint64_t size, ObjCIvarDecl *ivar) 16070b57cec5SDimitry Andric : Size(size), Ivar(ivar) {} 16080b57cec5SDimitry Andric }; 16090b57cec5SDimitry Andric 16100b57cec5SDimitry Andric bool operator<(const SynthesizeIvarChunk & LHS, 16110b57cec5SDimitry Andric const SynthesizeIvarChunk &RHS) { 16120b57cec5SDimitry Andric return LHS.Size < RHS.Size; 16130b57cec5SDimitry Andric } 16140b57cec5SDimitry Andric 16150b57cec5SDimitry Andric } // namespace 16160b57cec5SDimitry Andric 16170b57cec5SDimitry Andric /// all_declared_ivar_begin - return first ivar declared in this class, 16180b57cec5SDimitry Andric /// its extensions and its implementation. Lazily build the list on first 16190b57cec5SDimitry Andric /// access. 16200b57cec5SDimitry Andric /// 16210b57cec5SDimitry Andric /// Caveat: The list returned by this method reflects the current 16220b57cec5SDimitry Andric /// state of the parser. The cache will be updated for every ivar 16230b57cec5SDimitry Andric /// added by an extension or the implementation when they are 16240b57cec5SDimitry Andric /// encountered. 16250b57cec5SDimitry Andric /// See also ObjCIvarDecl::Create(). 16260b57cec5SDimitry Andric ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() { 16270b57cec5SDimitry Andric // FIXME: Should make sure no callers ever do this. 16280b57cec5SDimitry Andric if (!hasDefinition()) 16290b57cec5SDimitry Andric return nullptr; 16300b57cec5SDimitry Andric 16310b57cec5SDimitry Andric ObjCIvarDecl *curIvar = nullptr; 16320b57cec5SDimitry Andric if (!data().IvarList) { 16330b57cec5SDimitry Andric if (!ivar_empty()) { 16340b57cec5SDimitry Andric ObjCInterfaceDecl::ivar_iterator I = ivar_begin(), E = ivar_end(); 16350b57cec5SDimitry Andric data().IvarList = *I; ++I; 16360b57cec5SDimitry Andric for (curIvar = data().IvarList; I != E; curIvar = *I, ++I) 16370b57cec5SDimitry Andric curIvar->setNextIvar(*I); 16380b57cec5SDimitry Andric } 16390b57cec5SDimitry Andric 16400b57cec5SDimitry Andric for (const auto *Ext : known_extensions()) { 16410b57cec5SDimitry Andric if (!Ext->ivar_empty()) { 16420b57cec5SDimitry Andric ObjCCategoryDecl::ivar_iterator 16430b57cec5SDimitry Andric I = Ext->ivar_begin(), 16440b57cec5SDimitry Andric E = Ext->ivar_end(); 16450b57cec5SDimitry Andric if (!data().IvarList) { 16460b57cec5SDimitry Andric data().IvarList = *I; ++I; 16470b57cec5SDimitry Andric curIvar = data().IvarList; 16480b57cec5SDimitry Andric } 16490b57cec5SDimitry Andric for ( ;I != E; curIvar = *I, ++I) 16500b57cec5SDimitry Andric curIvar->setNextIvar(*I); 16510b57cec5SDimitry Andric } 16520b57cec5SDimitry Andric } 16530b57cec5SDimitry Andric data().IvarListMissingImplementation = true; 16540b57cec5SDimitry Andric } 16550b57cec5SDimitry Andric 16560b57cec5SDimitry Andric // cached and complete! 16570b57cec5SDimitry Andric if (!data().IvarListMissingImplementation) 16580b57cec5SDimitry Andric return data().IvarList; 16590b57cec5SDimitry Andric 16600b57cec5SDimitry Andric if (ObjCImplementationDecl *ImplDecl = getImplementation()) { 16610b57cec5SDimitry Andric data().IvarListMissingImplementation = false; 16620b57cec5SDimitry Andric if (!ImplDecl->ivar_empty()) { 16630b57cec5SDimitry Andric SmallVector<SynthesizeIvarChunk, 16> layout; 16640b57cec5SDimitry Andric for (auto *IV : ImplDecl->ivars()) { 16650b57cec5SDimitry Andric if (IV->getSynthesize() && !IV->isInvalidDecl()) { 16660b57cec5SDimitry Andric layout.push_back(SynthesizeIvarChunk( 16670b57cec5SDimitry Andric IV->getASTContext().getTypeSize(IV->getType()), IV)); 16680b57cec5SDimitry Andric continue; 16690b57cec5SDimitry Andric } 16700b57cec5SDimitry Andric if (!data().IvarList) 16710b57cec5SDimitry Andric data().IvarList = IV; 16720b57cec5SDimitry Andric else 16730b57cec5SDimitry Andric curIvar->setNextIvar(IV); 16740b57cec5SDimitry Andric curIvar = IV; 16750b57cec5SDimitry Andric } 16760b57cec5SDimitry Andric 16770b57cec5SDimitry Andric if (!layout.empty()) { 16780b57cec5SDimitry Andric // Order synthesized ivars by their size. 16790b57cec5SDimitry Andric llvm::stable_sort(layout); 16800b57cec5SDimitry Andric unsigned Ix = 0, EIx = layout.size(); 16810b57cec5SDimitry Andric if (!data().IvarList) { 16820b57cec5SDimitry Andric data().IvarList = layout[0].Ivar; Ix++; 16830b57cec5SDimitry Andric curIvar = data().IvarList; 16840b57cec5SDimitry Andric } 16850b57cec5SDimitry Andric for ( ; Ix != EIx; curIvar = layout[Ix].Ivar, Ix++) 16860b57cec5SDimitry Andric curIvar->setNextIvar(layout[Ix].Ivar); 16870b57cec5SDimitry Andric } 16880b57cec5SDimitry Andric } 16890b57cec5SDimitry Andric } 16900b57cec5SDimitry Andric return data().IvarList; 16910b57cec5SDimitry Andric } 16920b57cec5SDimitry Andric 16930b57cec5SDimitry Andric /// FindCategoryDeclaration - Finds category declaration in the list of 16940b57cec5SDimitry Andric /// categories for this class and returns it. Name of the category is passed 16950b57cec5SDimitry Andric /// in 'CategoryId'. If category not found, return 0; 16960b57cec5SDimitry Andric /// 16970b57cec5SDimitry Andric ObjCCategoryDecl * 16980b57cec5SDimitry Andric ObjCInterfaceDecl::FindCategoryDeclaration(IdentifierInfo *CategoryId) const { 16990b57cec5SDimitry Andric // FIXME: Should make sure no callers ever do this. 17000b57cec5SDimitry Andric if (!hasDefinition()) 17010b57cec5SDimitry Andric return nullptr; 17020b57cec5SDimitry Andric 17030b57cec5SDimitry Andric if (data().ExternallyCompleted) 17040b57cec5SDimitry Andric LoadExternalDefinition(); 17050b57cec5SDimitry Andric 17060b57cec5SDimitry Andric for (auto *Cat : visible_categories()) 17070b57cec5SDimitry Andric if (Cat->getIdentifier() == CategoryId) 17080b57cec5SDimitry Andric return Cat; 17090b57cec5SDimitry Andric 17100b57cec5SDimitry Andric return nullptr; 17110b57cec5SDimitry Andric } 17120b57cec5SDimitry Andric 17130b57cec5SDimitry Andric ObjCMethodDecl * 17140b57cec5SDimitry Andric ObjCInterfaceDecl::getCategoryInstanceMethod(Selector Sel) const { 17150b57cec5SDimitry Andric for (const auto *Cat : visible_categories()) { 17160b57cec5SDimitry Andric if (ObjCCategoryImplDecl *Impl = Cat->getImplementation()) 17170b57cec5SDimitry Andric if (ObjCMethodDecl *MD = Impl->getInstanceMethod(Sel)) 17180b57cec5SDimitry Andric return MD; 17190b57cec5SDimitry Andric } 17200b57cec5SDimitry Andric 17210b57cec5SDimitry Andric return nullptr; 17220b57cec5SDimitry Andric } 17230b57cec5SDimitry Andric 17240b57cec5SDimitry Andric ObjCMethodDecl *ObjCInterfaceDecl::getCategoryClassMethod(Selector Sel) const { 17250b57cec5SDimitry Andric for (const auto *Cat : visible_categories()) { 17260b57cec5SDimitry Andric if (ObjCCategoryImplDecl *Impl = Cat->getImplementation()) 17270b57cec5SDimitry Andric if (ObjCMethodDecl *MD = Impl->getClassMethod(Sel)) 17280b57cec5SDimitry Andric return MD; 17290b57cec5SDimitry Andric } 17300b57cec5SDimitry Andric 17310b57cec5SDimitry Andric return nullptr; 17320b57cec5SDimitry Andric } 17330b57cec5SDimitry Andric 17340b57cec5SDimitry Andric /// ClassImplementsProtocol - Checks that 'lProto' protocol 17350b57cec5SDimitry Andric /// has been implemented in IDecl class, its super class or categories (if 17360b57cec5SDimitry Andric /// lookupCategory is true). 17370b57cec5SDimitry Andric bool ObjCInterfaceDecl::ClassImplementsProtocol(ObjCProtocolDecl *lProto, 17380b57cec5SDimitry Andric bool lookupCategory, 17390b57cec5SDimitry Andric bool RHSIsQualifiedID) { 17400b57cec5SDimitry Andric if (!hasDefinition()) 17410b57cec5SDimitry Andric return false; 17420b57cec5SDimitry Andric 17430b57cec5SDimitry Andric ObjCInterfaceDecl *IDecl = this; 17440b57cec5SDimitry Andric // 1st, look up the class. 17450b57cec5SDimitry Andric for (auto *PI : IDecl->protocols()){ 17460b57cec5SDimitry Andric if (getASTContext().ProtocolCompatibleWithProtocol(lProto, PI)) 17470b57cec5SDimitry Andric return true; 17480b57cec5SDimitry Andric // This is dubious and is added to be compatible with gcc. In gcc, it is 17490b57cec5SDimitry Andric // also allowed assigning a protocol-qualified 'id' type to a LHS object 17500b57cec5SDimitry Andric // when protocol in qualified LHS is in list of protocols in the rhs 'id' 17510b57cec5SDimitry Andric // object. This IMO, should be a bug. 17520b57cec5SDimitry Andric // FIXME: Treat this as an extension, and flag this as an error when GCC 17530b57cec5SDimitry Andric // extensions are not enabled. 17540b57cec5SDimitry Andric if (RHSIsQualifiedID && 17550b57cec5SDimitry Andric getASTContext().ProtocolCompatibleWithProtocol(PI, lProto)) 17560b57cec5SDimitry Andric return true; 17570b57cec5SDimitry Andric } 17580b57cec5SDimitry Andric 17590b57cec5SDimitry Andric // 2nd, look up the category. 17600b57cec5SDimitry Andric if (lookupCategory) 17610b57cec5SDimitry Andric for (const auto *Cat : visible_categories()) { 17620b57cec5SDimitry Andric for (auto *PI : Cat->protocols()) 17630b57cec5SDimitry Andric if (getASTContext().ProtocolCompatibleWithProtocol(lProto, PI)) 17640b57cec5SDimitry Andric return true; 17650b57cec5SDimitry Andric } 17660b57cec5SDimitry Andric 17670b57cec5SDimitry Andric // 3rd, look up the super class(s) 17680b57cec5SDimitry Andric if (IDecl->getSuperClass()) 17690b57cec5SDimitry Andric return 17700b57cec5SDimitry Andric IDecl->getSuperClass()->ClassImplementsProtocol(lProto, lookupCategory, 17710b57cec5SDimitry Andric RHSIsQualifiedID); 17720b57cec5SDimitry Andric 17730b57cec5SDimitry Andric return false; 17740b57cec5SDimitry Andric } 17750b57cec5SDimitry Andric 17760b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 17770b57cec5SDimitry Andric // ObjCIvarDecl 17780b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 17790b57cec5SDimitry Andric 17800b57cec5SDimitry Andric void ObjCIvarDecl::anchor() {} 17810b57cec5SDimitry Andric 17820b57cec5SDimitry Andric ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC, 17830b57cec5SDimitry Andric SourceLocation StartLoc, 17840b57cec5SDimitry Andric SourceLocation IdLoc, IdentifierInfo *Id, 17850b57cec5SDimitry Andric QualType T, TypeSourceInfo *TInfo, 17860b57cec5SDimitry Andric AccessControl ac, Expr *BW, 17870b57cec5SDimitry Andric bool synthesized) { 17880b57cec5SDimitry Andric if (DC) { 17890b57cec5SDimitry Andric // Ivar's can only appear in interfaces, implementations (via synthesized 17900b57cec5SDimitry Andric // properties), and class extensions (via direct declaration, or synthesized 17910b57cec5SDimitry Andric // properties). 17920b57cec5SDimitry Andric // 17930b57cec5SDimitry Andric // FIXME: This should really be asserting this: 17940b57cec5SDimitry Andric // (isa<ObjCCategoryDecl>(DC) && 17950b57cec5SDimitry Andric // cast<ObjCCategoryDecl>(DC)->IsClassExtension())) 17960b57cec5SDimitry Andric // but unfortunately we sometimes place ivars into non-class extension 17970b57cec5SDimitry Andric // categories on error. This breaks an AST invariant, and should not be 17980b57cec5SDimitry Andric // fixed. 17990b57cec5SDimitry Andric assert((isa<ObjCInterfaceDecl>(DC) || isa<ObjCImplementationDecl>(DC) || 18000b57cec5SDimitry Andric isa<ObjCCategoryDecl>(DC)) && 18010b57cec5SDimitry Andric "Invalid ivar decl context!"); 18020b57cec5SDimitry Andric // Once a new ivar is created in any of class/class-extension/implementation 18030b57cec5SDimitry Andric // decl contexts, the previously built IvarList must be rebuilt. 18040b57cec5SDimitry Andric auto *ID = dyn_cast<ObjCInterfaceDecl>(DC); 18050b57cec5SDimitry Andric if (!ID) { 18060b57cec5SDimitry Andric if (auto *IM = dyn_cast<ObjCImplementationDecl>(DC)) 18070b57cec5SDimitry Andric ID = IM->getClassInterface(); 18080b57cec5SDimitry Andric else 18090b57cec5SDimitry Andric ID = cast<ObjCCategoryDecl>(DC)->getClassInterface(); 18100b57cec5SDimitry Andric } 18110b57cec5SDimitry Andric ID->setIvarList(nullptr); 18120b57cec5SDimitry Andric } 18130b57cec5SDimitry Andric 18140b57cec5SDimitry Andric return new (C, DC) ObjCIvarDecl(DC, StartLoc, IdLoc, Id, T, TInfo, ac, BW, 18150b57cec5SDimitry Andric synthesized); 18160b57cec5SDimitry Andric } 18170b57cec5SDimitry Andric 18180b57cec5SDimitry Andric ObjCIvarDecl *ObjCIvarDecl::CreateDeserialized(ASTContext &C, unsigned ID) { 18190b57cec5SDimitry Andric return new (C, ID) ObjCIvarDecl(nullptr, SourceLocation(), SourceLocation(), 18200b57cec5SDimitry Andric nullptr, QualType(), nullptr, 18210b57cec5SDimitry Andric ObjCIvarDecl::None, nullptr, false); 18220b57cec5SDimitry Andric } 18230b57cec5SDimitry Andric 18240b57cec5SDimitry Andric const ObjCInterfaceDecl *ObjCIvarDecl::getContainingInterface() const { 18250b57cec5SDimitry Andric const auto *DC = cast<ObjCContainerDecl>(getDeclContext()); 18260b57cec5SDimitry Andric 18270b57cec5SDimitry Andric switch (DC->getKind()) { 18280b57cec5SDimitry Andric default: 18290b57cec5SDimitry Andric case ObjCCategoryImpl: 18300b57cec5SDimitry Andric case ObjCProtocol: 18310b57cec5SDimitry Andric llvm_unreachable("invalid ivar container!"); 18320b57cec5SDimitry Andric 18330b57cec5SDimitry Andric // Ivars can only appear in class extension categories. 18340b57cec5SDimitry Andric case ObjCCategory: { 18350b57cec5SDimitry Andric const auto *CD = cast<ObjCCategoryDecl>(DC); 18360b57cec5SDimitry Andric assert(CD->IsClassExtension() && "invalid container for ivar!"); 18370b57cec5SDimitry Andric return CD->getClassInterface(); 18380b57cec5SDimitry Andric } 18390b57cec5SDimitry Andric 18400b57cec5SDimitry Andric case ObjCImplementation: 18410b57cec5SDimitry Andric return cast<ObjCImplementationDecl>(DC)->getClassInterface(); 18420b57cec5SDimitry Andric 18430b57cec5SDimitry Andric case ObjCInterface: 18440b57cec5SDimitry Andric return cast<ObjCInterfaceDecl>(DC); 18450b57cec5SDimitry Andric } 18460b57cec5SDimitry Andric } 18470b57cec5SDimitry Andric 18480b57cec5SDimitry Andric QualType ObjCIvarDecl::getUsageType(QualType objectType) const { 18490b57cec5SDimitry Andric return getType().substObjCMemberType(objectType, getDeclContext(), 18500b57cec5SDimitry Andric ObjCSubstitutionContext::Property); 18510b57cec5SDimitry Andric } 18520b57cec5SDimitry Andric 18530b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 18540b57cec5SDimitry Andric // ObjCAtDefsFieldDecl 18550b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 18560b57cec5SDimitry Andric 18570b57cec5SDimitry Andric void ObjCAtDefsFieldDecl::anchor() {} 18580b57cec5SDimitry Andric 18590b57cec5SDimitry Andric ObjCAtDefsFieldDecl 18600b57cec5SDimitry Andric *ObjCAtDefsFieldDecl::Create(ASTContext &C, DeclContext *DC, 18610b57cec5SDimitry Andric SourceLocation StartLoc, SourceLocation IdLoc, 18620b57cec5SDimitry Andric IdentifierInfo *Id, QualType T, Expr *BW) { 18630b57cec5SDimitry Andric return new (C, DC) ObjCAtDefsFieldDecl(DC, StartLoc, IdLoc, Id, T, BW); 18640b57cec5SDimitry Andric } 18650b57cec5SDimitry Andric 18660b57cec5SDimitry Andric ObjCAtDefsFieldDecl *ObjCAtDefsFieldDecl::CreateDeserialized(ASTContext &C, 18670b57cec5SDimitry Andric unsigned ID) { 18680b57cec5SDimitry Andric return new (C, ID) ObjCAtDefsFieldDecl(nullptr, SourceLocation(), 18690b57cec5SDimitry Andric SourceLocation(), nullptr, QualType(), 18700b57cec5SDimitry Andric nullptr); 18710b57cec5SDimitry Andric } 18720b57cec5SDimitry Andric 18730b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 18740b57cec5SDimitry Andric // ObjCProtocolDecl 18750b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 18760b57cec5SDimitry Andric 18770b57cec5SDimitry Andric void ObjCProtocolDecl::anchor() {} 18780b57cec5SDimitry Andric 18790b57cec5SDimitry Andric ObjCProtocolDecl::ObjCProtocolDecl(ASTContext &C, DeclContext *DC, 18800b57cec5SDimitry Andric IdentifierInfo *Id, SourceLocation nameLoc, 18810b57cec5SDimitry Andric SourceLocation atStartLoc, 18820b57cec5SDimitry Andric ObjCProtocolDecl *PrevDecl) 18830b57cec5SDimitry Andric : ObjCContainerDecl(ObjCProtocol, DC, Id, nameLoc, atStartLoc), 18840b57cec5SDimitry Andric redeclarable_base(C) { 18850b57cec5SDimitry Andric setPreviousDecl(PrevDecl); 18860b57cec5SDimitry Andric if (PrevDecl) 18870b57cec5SDimitry Andric Data = PrevDecl->Data; 18880b57cec5SDimitry Andric } 18890b57cec5SDimitry Andric 18900b57cec5SDimitry Andric ObjCProtocolDecl *ObjCProtocolDecl::Create(ASTContext &C, DeclContext *DC, 18910b57cec5SDimitry Andric IdentifierInfo *Id, 18920b57cec5SDimitry Andric SourceLocation nameLoc, 18930b57cec5SDimitry Andric SourceLocation atStartLoc, 18940b57cec5SDimitry Andric ObjCProtocolDecl *PrevDecl) { 18950b57cec5SDimitry Andric auto *Result = 18960b57cec5SDimitry Andric new (C, DC) ObjCProtocolDecl(C, DC, Id, nameLoc, atStartLoc, PrevDecl); 18970b57cec5SDimitry Andric Result->Data.setInt(!C.getLangOpts().Modules); 18980b57cec5SDimitry Andric return Result; 18990b57cec5SDimitry Andric } 19000b57cec5SDimitry Andric 19010b57cec5SDimitry Andric ObjCProtocolDecl *ObjCProtocolDecl::CreateDeserialized(ASTContext &C, 19020b57cec5SDimitry Andric unsigned ID) { 19030b57cec5SDimitry Andric ObjCProtocolDecl *Result = 19040b57cec5SDimitry Andric new (C, ID) ObjCProtocolDecl(C, nullptr, nullptr, SourceLocation(), 19050b57cec5SDimitry Andric SourceLocation(), nullptr); 19060b57cec5SDimitry Andric Result->Data.setInt(!C.getLangOpts().Modules); 19070b57cec5SDimitry Andric return Result; 19080b57cec5SDimitry Andric } 19090b57cec5SDimitry Andric 1910*e8d8bef9SDimitry Andric bool ObjCProtocolDecl::isNonRuntimeProtocol() const { 1911*e8d8bef9SDimitry Andric return hasAttr<ObjCNonRuntimeProtocolAttr>(); 1912*e8d8bef9SDimitry Andric } 1913*e8d8bef9SDimitry Andric 1914*e8d8bef9SDimitry Andric void ObjCProtocolDecl::getImpliedProtocols( 1915*e8d8bef9SDimitry Andric llvm::DenseSet<const ObjCProtocolDecl *> &IPs) const { 1916*e8d8bef9SDimitry Andric std::queue<const ObjCProtocolDecl *> WorkQueue; 1917*e8d8bef9SDimitry Andric WorkQueue.push(this); 1918*e8d8bef9SDimitry Andric 1919*e8d8bef9SDimitry Andric while (!WorkQueue.empty()) { 1920*e8d8bef9SDimitry Andric const auto *PD = WorkQueue.front(); 1921*e8d8bef9SDimitry Andric WorkQueue.pop(); 1922*e8d8bef9SDimitry Andric for (const auto *Parent : PD->protocols()) { 1923*e8d8bef9SDimitry Andric const auto *Can = Parent->getCanonicalDecl(); 1924*e8d8bef9SDimitry Andric auto Result = IPs.insert(Can); 1925*e8d8bef9SDimitry Andric if (Result.second) 1926*e8d8bef9SDimitry Andric WorkQueue.push(Parent); 1927*e8d8bef9SDimitry Andric } 1928*e8d8bef9SDimitry Andric } 1929*e8d8bef9SDimitry Andric } 1930*e8d8bef9SDimitry Andric 19310b57cec5SDimitry Andric ObjCProtocolDecl *ObjCProtocolDecl::lookupProtocolNamed(IdentifierInfo *Name) { 19320b57cec5SDimitry Andric ObjCProtocolDecl *PDecl = this; 19330b57cec5SDimitry Andric 19340b57cec5SDimitry Andric if (Name == getIdentifier()) 19350b57cec5SDimitry Andric return PDecl; 19360b57cec5SDimitry Andric 19370b57cec5SDimitry Andric for (auto *I : protocols()) 19380b57cec5SDimitry Andric if ((PDecl = I->lookupProtocolNamed(Name))) 19390b57cec5SDimitry Andric return PDecl; 19400b57cec5SDimitry Andric 19410b57cec5SDimitry Andric return nullptr; 19420b57cec5SDimitry Andric } 19430b57cec5SDimitry Andric 19440b57cec5SDimitry Andric // lookupMethod - Lookup a instance/class method in the protocol and protocols 19450b57cec5SDimitry Andric // it inherited. 19460b57cec5SDimitry Andric ObjCMethodDecl *ObjCProtocolDecl::lookupMethod(Selector Sel, 19470b57cec5SDimitry Andric bool isInstance) const { 19480b57cec5SDimitry Andric ObjCMethodDecl *MethodDecl = nullptr; 19490b57cec5SDimitry Andric 19500b57cec5SDimitry Andric // If there is no definition or the definition is hidden, we don't find 19510b57cec5SDimitry Andric // anything. 19520b57cec5SDimitry Andric const ObjCProtocolDecl *Def = getDefinition(); 19535ffd83dbSDimitry Andric if (!Def || !Def->isUnconditionallyVisible()) 19540b57cec5SDimitry Andric return nullptr; 19550b57cec5SDimitry Andric 19560b57cec5SDimitry Andric if ((MethodDecl = getMethod(Sel, isInstance))) 19570b57cec5SDimitry Andric return MethodDecl; 19580b57cec5SDimitry Andric 19590b57cec5SDimitry Andric for (const auto *I : protocols()) 19600b57cec5SDimitry Andric if ((MethodDecl = I->lookupMethod(Sel, isInstance))) 19610b57cec5SDimitry Andric return MethodDecl; 19620b57cec5SDimitry Andric return nullptr; 19630b57cec5SDimitry Andric } 19640b57cec5SDimitry Andric 19650b57cec5SDimitry Andric void ObjCProtocolDecl::allocateDefinitionData() { 19660b57cec5SDimitry Andric assert(!Data.getPointer() && "Protocol already has a definition!"); 19670b57cec5SDimitry Andric Data.setPointer(new (getASTContext()) DefinitionData); 19680b57cec5SDimitry Andric Data.getPointer()->Definition = this; 19690b57cec5SDimitry Andric } 19700b57cec5SDimitry Andric 19710b57cec5SDimitry Andric void ObjCProtocolDecl::startDefinition() { 19720b57cec5SDimitry Andric allocateDefinitionData(); 19730b57cec5SDimitry Andric 19740b57cec5SDimitry Andric // Update all of the declarations with a pointer to the definition. 19750b57cec5SDimitry Andric for (auto *RD : redecls()) 19760b57cec5SDimitry Andric RD->Data = this->Data; 19770b57cec5SDimitry Andric } 19780b57cec5SDimitry Andric 19790b57cec5SDimitry Andric void ObjCProtocolDecl::collectPropertiesToImplement(PropertyMap &PM, 19800b57cec5SDimitry Andric PropertyDeclOrder &PO) const { 19810b57cec5SDimitry Andric if (const ObjCProtocolDecl *PDecl = getDefinition()) { 19820b57cec5SDimitry Andric for (auto *Prop : PDecl->properties()) { 19830b57cec5SDimitry Andric // Insert into PM if not there already. 19840b57cec5SDimitry Andric PM.insert(std::make_pair( 19850b57cec5SDimitry Andric std::make_pair(Prop->getIdentifier(), Prop->isClassProperty()), 19860b57cec5SDimitry Andric Prop)); 19870b57cec5SDimitry Andric PO.push_back(Prop); 19880b57cec5SDimitry Andric } 19890b57cec5SDimitry Andric // Scan through protocol's protocols. 19900b57cec5SDimitry Andric for (const auto *PI : PDecl->protocols()) 19910b57cec5SDimitry Andric PI->collectPropertiesToImplement(PM, PO); 19920b57cec5SDimitry Andric } 19930b57cec5SDimitry Andric } 19940b57cec5SDimitry Andric 19950b57cec5SDimitry Andric void ObjCProtocolDecl::collectInheritedProtocolProperties( 19960b57cec5SDimitry Andric const ObjCPropertyDecl *Property, ProtocolPropertySet &PS, 19970b57cec5SDimitry Andric PropertyDeclOrder &PO) const { 19980b57cec5SDimitry Andric if (const ObjCProtocolDecl *PDecl = getDefinition()) { 19990b57cec5SDimitry Andric if (!PS.insert(PDecl).second) 20000b57cec5SDimitry Andric return; 20010b57cec5SDimitry Andric for (auto *Prop : PDecl->properties()) { 20020b57cec5SDimitry Andric if (Prop == Property) 20030b57cec5SDimitry Andric continue; 20040b57cec5SDimitry Andric if (Prop->getIdentifier() == Property->getIdentifier()) { 20050b57cec5SDimitry Andric PO.push_back(Prop); 20060b57cec5SDimitry Andric return; 20070b57cec5SDimitry Andric } 20080b57cec5SDimitry Andric } 20090b57cec5SDimitry Andric // Scan through protocol's protocols which did not have a matching property. 20100b57cec5SDimitry Andric for (const auto *PI : PDecl->protocols()) 20110b57cec5SDimitry Andric PI->collectInheritedProtocolProperties(Property, PS, PO); 20120b57cec5SDimitry Andric } 20130b57cec5SDimitry Andric } 20140b57cec5SDimitry Andric 20150b57cec5SDimitry Andric StringRef 20160b57cec5SDimitry Andric ObjCProtocolDecl::getObjCRuntimeNameAsString() const { 20170b57cec5SDimitry Andric if (const auto *ObjCRTName = getAttr<ObjCRuntimeNameAttr>()) 20180b57cec5SDimitry Andric return ObjCRTName->getMetadataName(); 20190b57cec5SDimitry Andric 20200b57cec5SDimitry Andric return getName(); 20210b57cec5SDimitry Andric } 20220b57cec5SDimitry Andric 20230b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 20240b57cec5SDimitry Andric // ObjCCategoryDecl 20250b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 20260b57cec5SDimitry Andric 20270b57cec5SDimitry Andric void ObjCCategoryDecl::anchor() {} 20280b57cec5SDimitry Andric 20290b57cec5SDimitry Andric ObjCCategoryDecl::ObjCCategoryDecl(DeclContext *DC, SourceLocation AtLoc, 20300b57cec5SDimitry Andric SourceLocation ClassNameLoc, 20310b57cec5SDimitry Andric SourceLocation CategoryNameLoc, 20320b57cec5SDimitry Andric IdentifierInfo *Id, ObjCInterfaceDecl *IDecl, 20330b57cec5SDimitry Andric ObjCTypeParamList *typeParamList, 20340b57cec5SDimitry Andric SourceLocation IvarLBraceLoc, 20350b57cec5SDimitry Andric SourceLocation IvarRBraceLoc) 20360b57cec5SDimitry Andric : ObjCContainerDecl(ObjCCategory, DC, Id, ClassNameLoc, AtLoc), 20370b57cec5SDimitry Andric ClassInterface(IDecl), CategoryNameLoc(CategoryNameLoc), 20380b57cec5SDimitry Andric IvarLBraceLoc(IvarLBraceLoc), IvarRBraceLoc(IvarRBraceLoc) { 20390b57cec5SDimitry Andric setTypeParamList(typeParamList); 20400b57cec5SDimitry Andric } 20410b57cec5SDimitry Andric 20420b57cec5SDimitry Andric ObjCCategoryDecl *ObjCCategoryDecl::Create(ASTContext &C, DeclContext *DC, 20430b57cec5SDimitry Andric SourceLocation AtLoc, 20440b57cec5SDimitry Andric SourceLocation ClassNameLoc, 20450b57cec5SDimitry Andric SourceLocation CategoryNameLoc, 20460b57cec5SDimitry Andric IdentifierInfo *Id, 20470b57cec5SDimitry Andric ObjCInterfaceDecl *IDecl, 20480b57cec5SDimitry Andric ObjCTypeParamList *typeParamList, 20490b57cec5SDimitry Andric SourceLocation IvarLBraceLoc, 20500b57cec5SDimitry Andric SourceLocation IvarRBraceLoc) { 20510b57cec5SDimitry Andric auto *CatDecl = 20520b57cec5SDimitry Andric new (C, DC) ObjCCategoryDecl(DC, AtLoc, ClassNameLoc, CategoryNameLoc, Id, 20530b57cec5SDimitry Andric IDecl, typeParamList, IvarLBraceLoc, 20540b57cec5SDimitry Andric IvarRBraceLoc); 20550b57cec5SDimitry Andric if (IDecl) { 20560b57cec5SDimitry Andric // Link this category into its class's category list. 20570b57cec5SDimitry Andric CatDecl->NextClassCategory = IDecl->getCategoryListRaw(); 20580b57cec5SDimitry Andric if (IDecl->hasDefinition()) { 20590b57cec5SDimitry Andric IDecl->setCategoryListRaw(CatDecl); 20600b57cec5SDimitry Andric if (ASTMutationListener *L = C.getASTMutationListener()) 20610b57cec5SDimitry Andric L->AddedObjCCategoryToInterface(CatDecl, IDecl); 20620b57cec5SDimitry Andric } 20630b57cec5SDimitry Andric } 20640b57cec5SDimitry Andric 20650b57cec5SDimitry Andric return CatDecl; 20660b57cec5SDimitry Andric } 20670b57cec5SDimitry Andric 20680b57cec5SDimitry Andric ObjCCategoryDecl *ObjCCategoryDecl::CreateDeserialized(ASTContext &C, 20690b57cec5SDimitry Andric unsigned ID) { 20700b57cec5SDimitry Andric return new (C, ID) ObjCCategoryDecl(nullptr, SourceLocation(), 20710b57cec5SDimitry Andric SourceLocation(), SourceLocation(), 20720b57cec5SDimitry Andric nullptr, nullptr, nullptr); 20730b57cec5SDimitry Andric } 20740b57cec5SDimitry Andric 20750b57cec5SDimitry Andric ObjCCategoryImplDecl *ObjCCategoryDecl::getImplementation() const { 20760b57cec5SDimitry Andric return getASTContext().getObjCImplementation( 20770b57cec5SDimitry Andric const_cast<ObjCCategoryDecl*>(this)); 20780b57cec5SDimitry Andric } 20790b57cec5SDimitry Andric 20800b57cec5SDimitry Andric void ObjCCategoryDecl::setImplementation(ObjCCategoryImplDecl *ImplD) { 20810b57cec5SDimitry Andric getASTContext().setObjCImplementation(this, ImplD); 20820b57cec5SDimitry Andric } 20830b57cec5SDimitry Andric 20840b57cec5SDimitry Andric void ObjCCategoryDecl::setTypeParamList(ObjCTypeParamList *TPL) { 20850b57cec5SDimitry Andric TypeParamList = TPL; 20860b57cec5SDimitry Andric if (!TPL) 20870b57cec5SDimitry Andric return; 20880b57cec5SDimitry Andric // Set the declaration context of each of the type parameters. 20890b57cec5SDimitry Andric for (auto *typeParam : *TypeParamList) 20900b57cec5SDimitry Andric typeParam->setDeclContext(this); 20910b57cec5SDimitry Andric } 20920b57cec5SDimitry Andric 20930b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 20940b57cec5SDimitry Andric // ObjCCategoryImplDecl 20950b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 20960b57cec5SDimitry Andric 20970b57cec5SDimitry Andric void ObjCCategoryImplDecl::anchor() {} 20980b57cec5SDimitry Andric 20990b57cec5SDimitry Andric ObjCCategoryImplDecl * 21000b57cec5SDimitry Andric ObjCCategoryImplDecl::Create(ASTContext &C, DeclContext *DC, 21010b57cec5SDimitry Andric IdentifierInfo *Id, 21020b57cec5SDimitry Andric ObjCInterfaceDecl *ClassInterface, 21030b57cec5SDimitry Andric SourceLocation nameLoc, 21040b57cec5SDimitry Andric SourceLocation atStartLoc, 21050b57cec5SDimitry Andric SourceLocation CategoryNameLoc) { 21060b57cec5SDimitry Andric if (ClassInterface && ClassInterface->hasDefinition()) 21070b57cec5SDimitry Andric ClassInterface = ClassInterface->getDefinition(); 21080b57cec5SDimitry Andric return new (C, DC) ObjCCategoryImplDecl(DC, Id, ClassInterface, nameLoc, 21090b57cec5SDimitry Andric atStartLoc, CategoryNameLoc); 21100b57cec5SDimitry Andric } 21110b57cec5SDimitry Andric 21120b57cec5SDimitry Andric ObjCCategoryImplDecl *ObjCCategoryImplDecl::CreateDeserialized(ASTContext &C, 21130b57cec5SDimitry Andric unsigned ID) { 21140b57cec5SDimitry Andric return new (C, ID) ObjCCategoryImplDecl(nullptr, nullptr, nullptr, 21150b57cec5SDimitry Andric SourceLocation(), SourceLocation(), 21160b57cec5SDimitry Andric SourceLocation()); 21170b57cec5SDimitry Andric } 21180b57cec5SDimitry Andric 21190b57cec5SDimitry Andric ObjCCategoryDecl *ObjCCategoryImplDecl::getCategoryDecl() const { 21200b57cec5SDimitry Andric // The class interface might be NULL if we are working with invalid code. 21210b57cec5SDimitry Andric if (const ObjCInterfaceDecl *ID = getClassInterface()) 21220b57cec5SDimitry Andric return ID->FindCategoryDeclaration(getIdentifier()); 21230b57cec5SDimitry Andric return nullptr; 21240b57cec5SDimitry Andric } 21250b57cec5SDimitry Andric 21260b57cec5SDimitry Andric void ObjCImplDecl::anchor() {} 21270b57cec5SDimitry Andric 21280b57cec5SDimitry Andric void ObjCImplDecl::addPropertyImplementation(ObjCPropertyImplDecl *property) { 21290b57cec5SDimitry Andric // FIXME: The context should be correct before we get here. 21300b57cec5SDimitry Andric property->setLexicalDeclContext(this); 21310b57cec5SDimitry Andric addDecl(property); 21320b57cec5SDimitry Andric } 21330b57cec5SDimitry Andric 21340b57cec5SDimitry Andric void ObjCImplDecl::setClassInterface(ObjCInterfaceDecl *IFace) { 21350b57cec5SDimitry Andric ASTContext &Ctx = getASTContext(); 21360b57cec5SDimitry Andric 21370b57cec5SDimitry Andric if (auto *ImplD = dyn_cast_or_null<ObjCImplementationDecl>(this)) { 21380b57cec5SDimitry Andric if (IFace) 21390b57cec5SDimitry Andric Ctx.setObjCImplementation(IFace, ImplD); 21400b57cec5SDimitry Andric 21410b57cec5SDimitry Andric } else if (auto *ImplD = dyn_cast_or_null<ObjCCategoryImplDecl>(this)) { 21420b57cec5SDimitry Andric if (ObjCCategoryDecl *CD = IFace->FindCategoryDeclaration(getIdentifier())) 21430b57cec5SDimitry Andric Ctx.setObjCImplementation(CD, ImplD); 21440b57cec5SDimitry Andric } 21450b57cec5SDimitry Andric 21460b57cec5SDimitry Andric ClassInterface = IFace; 21470b57cec5SDimitry Andric } 21480b57cec5SDimitry Andric 21490b57cec5SDimitry Andric /// FindPropertyImplIvarDecl - This method lookup the ivar in the list of 21500b57cec5SDimitry Andric /// properties implemented in this \@implementation block and returns 21510b57cec5SDimitry Andric /// the implemented property that uses it. 21520b57cec5SDimitry Andric ObjCPropertyImplDecl *ObjCImplDecl:: 21530b57cec5SDimitry Andric FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const { 21540b57cec5SDimitry Andric for (auto *PID : property_impls()) 21550b57cec5SDimitry Andric if (PID->getPropertyIvarDecl() && 21560b57cec5SDimitry Andric PID->getPropertyIvarDecl()->getIdentifier() == ivarId) 21570b57cec5SDimitry Andric return PID; 21580b57cec5SDimitry Andric return nullptr; 21590b57cec5SDimitry Andric } 21600b57cec5SDimitry Andric 21610b57cec5SDimitry Andric /// FindPropertyImplDecl - This method looks up a previous ObjCPropertyImplDecl 21620b57cec5SDimitry Andric /// added to the list of those properties \@synthesized/\@dynamic in this 21630b57cec5SDimitry Andric /// category \@implementation block. 21640b57cec5SDimitry Andric ObjCPropertyImplDecl *ObjCImplDecl:: 21650b57cec5SDimitry Andric FindPropertyImplDecl(IdentifierInfo *Id, 21660b57cec5SDimitry Andric ObjCPropertyQueryKind QueryKind) const { 21670b57cec5SDimitry Andric ObjCPropertyImplDecl *ClassPropImpl = nullptr; 21680b57cec5SDimitry Andric for (auto *PID : property_impls()) 21690b57cec5SDimitry Andric // If queryKind is unknown, we return the instance property if one 21700b57cec5SDimitry Andric // exists; otherwise we return the class property. 21710b57cec5SDimitry Andric if (PID->getPropertyDecl()->getIdentifier() == Id) { 21720b57cec5SDimitry Andric if ((QueryKind == ObjCPropertyQueryKind::OBJC_PR_query_unknown && 21730b57cec5SDimitry Andric !PID->getPropertyDecl()->isClassProperty()) || 21740b57cec5SDimitry Andric (QueryKind == ObjCPropertyQueryKind::OBJC_PR_query_class && 21750b57cec5SDimitry Andric PID->getPropertyDecl()->isClassProperty()) || 21760b57cec5SDimitry Andric (QueryKind == ObjCPropertyQueryKind::OBJC_PR_query_instance && 21770b57cec5SDimitry Andric !PID->getPropertyDecl()->isClassProperty())) 21780b57cec5SDimitry Andric return PID; 21790b57cec5SDimitry Andric 21800b57cec5SDimitry Andric if (PID->getPropertyDecl()->isClassProperty()) 21810b57cec5SDimitry Andric ClassPropImpl = PID; 21820b57cec5SDimitry Andric } 21830b57cec5SDimitry Andric 21840b57cec5SDimitry Andric if (QueryKind == ObjCPropertyQueryKind::OBJC_PR_query_unknown) 21850b57cec5SDimitry Andric // We can't find the instance property, return the class property. 21860b57cec5SDimitry Andric return ClassPropImpl; 21870b57cec5SDimitry Andric 21880b57cec5SDimitry Andric return nullptr; 21890b57cec5SDimitry Andric } 21900b57cec5SDimitry Andric 21910b57cec5SDimitry Andric raw_ostream &clang::operator<<(raw_ostream &OS, 21920b57cec5SDimitry Andric const ObjCCategoryImplDecl &CID) { 21930b57cec5SDimitry Andric OS << CID.getName(); 21940b57cec5SDimitry Andric return OS; 21950b57cec5SDimitry Andric } 21960b57cec5SDimitry Andric 21970b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 21980b57cec5SDimitry Andric // ObjCImplementationDecl 21990b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 22000b57cec5SDimitry Andric 22010b57cec5SDimitry Andric void ObjCImplementationDecl::anchor() {} 22020b57cec5SDimitry Andric 22030b57cec5SDimitry Andric ObjCImplementationDecl * 22040b57cec5SDimitry Andric ObjCImplementationDecl::Create(ASTContext &C, DeclContext *DC, 22050b57cec5SDimitry Andric ObjCInterfaceDecl *ClassInterface, 22060b57cec5SDimitry Andric ObjCInterfaceDecl *SuperDecl, 22070b57cec5SDimitry Andric SourceLocation nameLoc, 22080b57cec5SDimitry Andric SourceLocation atStartLoc, 22090b57cec5SDimitry Andric SourceLocation superLoc, 22100b57cec5SDimitry Andric SourceLocation IvarLBraceLoc, 22110b57cec5SDimitry Andric SourceLocation IvarRBraceLoc) { 22120b57cec5SDimitry Andric if (ClassInterface && ClassInterface->hasDefinition()) 22130b57cec5SDimitry Andric ClassInterface = ClassInterface->getDefinition(); 22140b57cec5SDimitry Andric return new (C, DC) ObjCImplementationDecl(DC, ClassInterface, SuperDecl, 22150b57cec5SDimitry Andric nameLoc, atStartLoc, superLoc, 22160b57cec5SDimitry Andric IvarLBraceLoc, IvarRBraceLoc); 22170b57cec5SDimitry Andric } 22180b57cec5SDimitry Andric 22190b57cec5SDimitry Andric ObjCImplementationDecl * 22200b57cec5SDimitry Andric ObjCImplementationDecl::CreateDeserialized(ASTContext &C, unsigned ID) { 22210b57cec5SDimitry Andric return new (C, ID) ObjCImplementationDecl(nullptr, nullptr, nullptr, 22220b57cec5SDimitry Andric SourceLocation(), SourceLocation()); 22230b57cec5SDimitry Andric } 22240b57cec5SDimitry Andric 22250b57cec5SDimitry Andric void ObjCImplementationDecl::setIvarInitializers(ASTContext &C, 22260b57cec5SDimitry Andric CXXCtorInitializer ** initializers, 22270b57cec5SDimitry Andric unsigned numInitializers) { 22280b57cec5SDimitry Andric if (numInitializers > 0) { 22290b57cec5SDimitry Andric NumIvarInitializers = numInitializers; 22300b57cec5SDimitry Andric auto **ivarInitializers = new (C) CXXCtorInitializer*[NumIvarInitializers]; 22310b57cec5SDimitry Andric memcpy(ivarInitializers, initializers, 22320b57cec5SDimitry Andric numInitializers * sizeof(CXXCtorInitializer*)); 22330b57cec5SDimitry Andric IvarInitializers = ivarInitializers; 22340b57cec5SDimitry Andric } 22350b57cec5SDimitry Andric } 22360b57cec5SDimitry Andric 22370b57cec5SDimitry Andric ObjCImplementationDecl::init_const_iterator 22380b57cec5SDimitry Andric ObjCImplementationDecl::init_begin() const { 22390b57cec5SDimitry Andric return IvarInitializers.get(getASTContext().getExternalSource()); 22400b57cec5SDimitry Andric } 22410b57cec5SDimitry Andric 22420b57cec5SDimitry Andric raw_ostream &clang::operator<<(raw_ostream &OS, 22430b57cec5SDimitry Andric const ObjCImplementationDecl &ID) { 22440b57cec5SDimitry Andric OS << ID.getName(); 22450b57cec5SDimitry Andric return OS; 22460b57cec5SDimitry Andric } 22470b57cec5SDimitry Andric 22480b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 22490b57cec5SDimitry Andric // ObjCCompatibleAliasDecl 22500b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 22510b57cec5SDimitry Andric 22520b57cec5SDimitry Andric void ObjCCompatibleAliasDecl::anchor() {} 22530b57cec5SDimitry Andric 22540b57cec5SDimitry Andric ObjCCompatibleAliasDecl * 22550b57cec5SDimitry Andric ObjCCompatibleAliasDecl::Create(ASTContext &C, DeclContext *DC, 22560b57cec5SDimitry Andric SourceLocation L, 22570b57cec5SDimitry Andric IdentifierInfo *Id, 22580b57cec5SDimitry Andric ObjCInterfaceDecl* AliasedClass) { 22590b57cec5SDimitry Andric return new (C, DC) ObjCCompatibleAliasDecl(DC, L, Id, AliasedClass); 22600b57cec5SDimitry Andric } 22610b57cec5SDimitry Andric 22620b57cec5SDimitry Andric ObjCCompatibleAliasDecl * 22630b57cec5SDimitry Andric ObjCCompatibleAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) { 22640b57cec5SDimitry Andric return new (C, ID) ObjCCompatibleAliasDecl(nullptr, SourceLocation(), 22650b57cec5SDimitry Andric nullptr, nullptr); 22660b57cec5SDimitry Andric } 22670b57cec5SDimitry Andric 22680b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 22690b57cec5SDimitry Andric // ObjCPropertyDecl 22700b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 22710b57cec5SDimitry Andric 22720b57cec5SDimitry Andric void ObjCPropertyDecl::anchor() {} 22730b57cec5SDimitry Andric 22740b57cec5SDimitry Andric ObjCPropertyDecl *ObjCPropertyDecl::Create(ASTContext &C, DeclContext *DC, 22750b57cec5SDimitry Andric SourceLocation L, 22760b57cec5SDimitry Andric IdentifierInfo *Id, 22770b57cec5SDimitry Andric SourceLocation AtLoc, 22780b57cec5SDimitry Andric SourceLocation LParenLoc, 22790b57cec5SDimitry Andric QualType T, 22800b57cec5SDimitry Andric TypeSourceInfo *TSI, 22810b57cec5SDimitry Andric PropertyControl propControl) { 22820b57cec5SDimitry Andric return new (C, DC) ObjCPropertyDecl(DC, L, Id, AtLoc, LParenLoc, T, TSI, 22830b57cec5SDimitry Andric propControl); 22840b57cec5SDimitry Andric } 22850b57cec5SDimitry Andric 22860b57cec5SDimitry Andric ObjCPropertyDecl *ObjCPropertyDecl::CreateDeserialized(ASTContext &C, 22870b57cec5SDimitry Andric unsigned ID) { 22880b57cec5SDimitry Andric return new (C, ID) ObjCPropertyDecl(nullptr, SourceLocation(), nullptr, 22890b57cec5SDimitry Andric SourceLocation(), SourceLocation(), 22900b57cec5SDimitry Andric QualType(), nullptr, None); 22910b57cec5SDimitry Andric } 22920b57cec5SDimitry Andric 22930b57cec5SDimitry Andric QualType ObjCPropertyDecl::getUsageType(QualType objectType) const { 22940b57cec5SDimitry Andric return DeclType.substObjCMemberType(objectType, getDeclContext(), 22950b57cec5SDimitry Andric ObjCSubstitutionContext::Property); 22960b57cec5SDimitry Andric } 22970b57cec5SDimitry Andric 22980b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 22990b57cec5SDimitry Andric // ObjCPropertyImplDecl 23000b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 23010b57cec5SDimitry Andric 23020b57cec5SDimitry Andric ObjCPropertyImplDecl *ObjCPropertyImplDecl::Create(ASTContext &C, 23030b57cec5SDimitry Andric DeclContext *DC, 23040b57cec5SDimitry Andric SourceLocation atLoc, 23050b57cec5SDimitry Andric SourceLocation L, 23060b57cec5SDimitry Andric ObjCPropertyDecl *property, 23070b57cec5SDimitry Andric Kind PK, 23080b57cec5SDimitry Andric ObjCIvarDecl *ivar, 23090b57cec5SDimitry Andric SourceLocation ivarLoc) { 23100b57cec5SDimitry Andric return new (C, DC) ObjCPropertyImplDecl(DC, atLoc, L, property, PK, ivar, 23110b57cec5SDimitry Andric ivarLoc); 23120b57cec5SDimitry Andric } 23130b57cec5SDimitry Andric 23140b57cec5SDimitry Andric ObjCPropertyImplDecl *ObjCPropertyImplDecl::CreateDeserialized(ASTContext &C, 23150b57cec5SDimitry Andric unsigned ID) { 23160b57cec5SDimitry Andric return new (C, ID) ObjCPropertyImplDecl(nullptr, SourceLocation(), 23170b57cec5SDimitry Andric SourceLocation(), nullptr, Dynamic, 23180b57cec5SDimitry Andric nullptr, SourceLocation()); 23190b57cec5SDimitry Andric } 23200b57cec5SDimitry Andric 23210b57cec5SDimitry Andric SourceRange ObjCPropertyImplDecl::getSourceRange() const { 23220b57cec5SDimitry Andric SourceLocation EndLoc = getLocation(); 23230b57cec5SDimitry Andric if (IvarLoc.isValid()) 23240b57cec5SDimitry Andric EndLoc = IvarLoc; 23250b57cec5SDimitry Andric 23260b57cec5SDimitry Andric return SourceRange(AtLoc, EndLoc); 23270b57cec5SDimitry Andric } 2328