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