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" 19bdd1243dSDimitry Andric #include "clang/AST/ODRHash.h" 200b57cec5SDimitry Andric #include "clang/AST/Stmt.h" 210b57cec5SDimitry Andric #include "clang/AST/Type.h" 220b57cec5SDimitry Andric #include "clang/AST/TypeLoc.h" 230b57cec5SDimitry Andric #include "clang/Basic/IdentifierTable.h" 240b57cec5SDimitry Andric #include "clang/Basic/LLVM.h" 250b57cec5SDimitry Andric #include "clang/Basic/LangOptions.h" 260b57cec5SDimitry Andric #include "clang/Basic/SourceLocation.h" 270b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h" 280b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 290b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 300b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 310b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 320b57cec5SDimitry Andric #include <algorithm> 330b57cec5SDimitry Andric #include <cassert> 340b57cec5SDimitry Andric #include <cstdint> 350b57cec5SDimitry Andric #include <cstring> 36e8d8bef9SDimitry Andric #include <queue> 370b57cec5SDimitry Andric #include <utility> 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric using namespace clang; 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 420b57cec5SDimitry Andric // ObjCListBase 430b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric void ObjCListBase::set(void *const* InList, unsigned Elts, ASTContext &Ctx) { 460b57cec5SDimitry Andric List = nullptr; 470b57cec5SDimitry Andric if (Elts == 0) return; // Setting to an empty list is a noop. 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric List = new (Ctx) void*[Elts]; 500b57cec5SDimitry Andric NumElts = Elts; 510b57cec5SDimitry Andric memcpy(List, InList, sizeof(void*)*Elts); 520b57cec5SDimitry Andric } 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric void ObjCProtocolList::set(ObjCProtocolDecl* const* InList, unsigned Elts, 550b57cec5SDimitry Andric const SourceLocation *Locs, ASTContext &Ctx) { 560b57cec5SDimitry Andric if (Elts == 0) 570b57cec5SDimitry Andric return; 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric Locations = new (Ctx) SourceLocation[Elts]; 600b57cec5SDimitry Andric memcpy(Locations, Locs, sizeof(SourceLocation) * Elts); 610b57cec5SDimitry Andric set(InList, Elts, Ctx); 620b57cec5SDimitry Andric } 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 650b57cec5SDimitry Andric // ObjCInterfaceDecl 660b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric ObjCContainerDecl::ObjCContainerDecl(Kind DK, DeclContext *DC, 69*0fca6ea1SDimitry Andric const IdentifierInfo *Id, 70*0fca6ea1SDimitry Andric SourceLocation nameLoc, 710b57cec5SDimitry Andric SourceLocation atStartLoc) 720b57cec5SDimitry Andric : NamedDecl(DK, DC, nameLoc, Id), DeclContext(DK) { 730b57cec5SDimitry Andric setAtStartLoc(atStartLoc); 740b57cec5SDimitry Andric } 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric void ObjCContainerDecl::anchor() {} 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric /// getIvarDecl - This method looks up an ivar in this ContextDecl. 790b57cec5SDimitry Andric /// 800b57cec5SDimitry Andric ObjCIvarDecl * 810b57cec5SDimitry Andric ObjCContainerDecl::getIvarDecl(IdentifierInfo *Id) const { 820b57cec5SDimitry Andric lookup_result R = lookup(Id); 830b57cec5SDimitry Andric for (lookup_iterator Ivar = R.begin(), IvarEnd = R.end(); 840b57cec5SDimitry Andric Ivar != IvarEnd; ++Ivar) { 850b57cec5SDimitry Andric if (auto *ivar = dyn_cast<ObjCIvarDecl>(*Ivar)) 860b57cec5SDimitry Andric return ivar; 870b57cec5SDimitry Andric } 880b57cec5SDimitry Andric return nullptr; 890b57cec5SDimitry Andric } 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric // Get the local instance/class method declared in this interface. 920b57cec5SDimitry Andric ObjCMethodDecl * 930b57cec5SDimitry Andric ObjCContainerDecl::getMethod(Selector Sel, bool isInstance, 940b57cec5SDimitry Andric bool AllowHidden) const { 950b57cec5SDimitry Andric // If this context is a hidden protocol definition, don't find any 960b57cec5SDimitry Andric // methods there. 970b57cec5SDimitry Andric if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(this)) { 980b57cec5SDimitry Andric if (const ObjCProtocolDecl *Def = Proto->getDefinition()) 995ffd83dbSDimitry Andric if (!Def->isUnconditionallyVisible() && !AllowHidden) 1000b57cec5SDimitry Andric return nullptr; 1010b57cec5SDimitry Andric } 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric // Since instance & class methods can have the same name, the loop below 1040b57cec5SDimitry Andric // ensures we get the correct method. 1050b57cec5SDimitry Andric // 1060b57cec5SDimitry Andric // @interface Whatever 1070b57cec5SDimitry Andric // - (int) class_method; 1080b57cec5SDimitry Andric // + (float) class_method; 1090b57cec5SDimitry Andric // @end 1100b57cec5SDimitry Andric lookup_result R = lookup(Sel); 1110b57cec5SDimitry Andric for (lookup_iterator Meth = R.begin(), MethEnd = R.end(); 1120b57cec5SDimitry Andric Meth != MethEnd; ++Meth) { 1130b57cec5SDimitry Andric auto *MD = dyn_cast<ObjCMethodDecl>(*Meth); 1140b57cec5SDimitry Andric if (MD && MD->isInstanceMethod() == isInstance) 1150b57cec5SDimitry Andric return MD; 1160b57cec5SDimitry Andric } 1170b57cec5SDimitry Andric return nullptr; 1180b57cec5SDimitry Andric } 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric /// This routine returns 'true' if a user declared setter method was 1210b57cec5SDimitry Andric /// found in the class, its protocols, its super classes or categories. 1220b57cec5SDimitry Andric /// It also returns 'true' if one of its categories has declared a 'readwrite' 1230b57cec5SDimitry Andric /// property. This is because, user must provide a setter method for the 1240b57cec5SDimitry Andric /// category's 'readwrite' property. 1250b57cec5SDimitry Andric bool ObjCContainerDecl::HasUserDeclaredSetterMethod( 1260b57cec5SDimitry Andric const ObjCPropertyDecl *Property) const { 1270b57cec5SDimitry Andric Selector Sel = Property->getSetterName(); 1280b57cec5SDimitry Andric lookup_result R = lookup(Sel); 1290b57cec5SDimitry Andric for (lookup_iterator Meth = R.begin(), MethEnd = R.end(); 1300b57cec5SDimitry Andric Meth != MethEnd; ++Meth) { 1310b57cec5SDimitry Andric auto *MD = dyn_cast<ObjCMethodDecl>(*Meth); 1320b57cec5SDimitry Andric if (MD && MD->isInstanceMethod() && !MD->isImplicit()) 1330b57cec5SDimitry Andric return true; 1340b57cec5SDimitry Andric } 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(this)) { 1370b57cec5SDimitry Andric // Also look into categories, including class extensions, looking 1380b57cec5SDimitry Andric // for a user declared instance method. 1390b57cec5SDimitry Andric for (const auto *Cat : ID->visible_categories()) { 1400b57cec5SDimitry Andric if (ObjCMethodDecl *MD = Cat->getInstanceMethod(Sel)) 1410b57cec5SDimitry Andric if (!MD->isImplicit()) 1420b57cec5SDimitry Andric return true; 1430b57cec5SDimitry Andric if (Cat->IsClassExtension()) 1440b57cec5SDimitry Andric continue; 1450b57cec5SDimitry Andric // Also search through the categories looking for a 'readwrite' 1460b57cec5SDimitry Andric // declaration of this property. If one found, presumably a setter will 1470b57cec5SDimitry Andric // be provided (properties declared in categories will not get 1480b57cec5SDimitry Andric // auto-synthesized). 1490b57cec5SDimitry Andric for (const auto *P : Cat->properties()) 1500b57cec5SDimitry Andric if (P->getIdentifier() == Property->getIdentifier()) { 1515ffd83dbSDimitry Andric if (P->getPropertyAttributes() & 1525ffd83dbSDimitry Andric ObjCPropertyAttribute::kind_readwrite) 1530b57cec5SDimitry Andric return true; 1540b57cec5SDimitry Andric break; 1550b57cec5SDimitry Andric } 1560b57cec5SDimitry Andric } 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andric // Also look into protocols, for a user declared instance method. 1590b57cec5SDimitry Andric for (const auto *Proto : ID->all_referenced_protocols()) 1600b57cec5SDimitry Andric if (Proto->HasUserDeclaredSetterMethod(Property)) 1610b57cec5SDimitry Andric return true; 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andric // And in its super class. 1640b57cec5SDimitry Andric ObjCInterfaceDecl *OSC = ID->getSuperClass(); 1650b57cec5SDimitry Andric while (OSC) { 1660b57cec5SDimitry Andric if (OSC->HasUserDeclaredSetterMethod(Property)) 1670b57cec5SDimitry Andric return true; 1680b57cec5SDimitry Andric OSC = OSC->getSuperClass(); 1690b57cec5SDimitry Andric } 1700b57cec5SDimitry Andric } 1710b57cec5SDimitry Andric if (const auto *PD = dyn_cast<ObjCProtocolDecl>(this)) 1720b57cec5SDimitry Andric for (const auto *PI : PD->protocols()) 1730b57cec5SDimitry Andric if (PI->HasUserDeclaredSetterMethod(Property)) 1740b57cec5SDimitry Andric return true; 1750b57cec5SDimitry Andric return false; 1760b57cec5SDimitry Andric } 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric ObjCPropertyDecl * 1790b57cec5SDimitry Andric ObjCPropertyDecl::findPropertyDecl(const DeclContext *DC, 1800b57cec5SDimitry Andric const IdentifierInfo *propertyID, 1810b57cec5SDimitry Andric ObjCPropertyQueryKind queryKind) { 1820b57cec5SDimitry Andric // If this context is a hidden protocol definition, don't find any 1830b57cec5SDimitry Andric // property. 1840b57cec5SDimitry Andric if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(DC)) { 1850b57cec5SDimitry Andric if (const ObjCProtocolDecl *Def = Proto->getDefinition()) 1865ffd83dbSDimitry Andric if (!Def->isUnconditionallyVisible()) 1870b57cec5SDimitry Andric return nullptr; 1880b57cec5SDimitry Andric } 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric // If context is class, then lookup property in its visible extensions. 1910b57cec5SDimitry Andric // This comes before property is looked up in primary class. 1920b57cec5SDimitry Andric if (auto *IDecl = dyn_cast<ObjCInterfaceDecl>(DC)) { 1930b57cec5SDimitry Andric for (const auto *Ext : IDecl->visible_extensions()) 1940b57cec5SDimitry Andric if (ObjCPropertyDecl *PD = ObjCPropertyDecl::findPropertyDecl(Ext, 1950b57cec5SDimitry Andric propertyID, 1960b57cec5SDimitry Andric queryKind)) 1970b57cec5SDimitry Andric return PD; 1980b57cec5SDimitry Andric } 1990b57cec5SDimitry Andric 2000b57cec5SDimitry Andric DeclContext::lookup_result R = DC->lookup(propertyID); 2010b57cec5SDimitry Andric ObjCPropertyDecl *classProp = nullptr; 2020b57cec5SDimitry Andric for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; 2030b57cec5SDimitry Andric ++I) 2040b57cec5SDimitry Andric if (auto *PD = dyn_cast<ObjCPropertyDecl>(*I)) { 2050b57cec5SDimitry Andric // If queryKind is unknown, we return the instance property if one 2060b57cec5SDimitry Andric // exists; otherwise we return the class property. 2070b57cec5SDimitry Andric if ((queryKind == ObjCPropertyQueryKind::OBJC_PR_query_unknown && 2080b57cec5SDimitry Andric !PD->isClassProperty()) || 2090b57cec5SDimitry Andric (queryKind == ObjCPropertyQueryKind::OBJC_PR_query_class && 2100b57cec5SDimitry Andric PD->isClassProperty()) || 2110b57cec5SDimitry Andric (queryKind == ObjCPropertyQueryKind::OBJC_PR_query_instance && 2120b57cec5SDimitry Andric !PD->isClassProperty())) 2130b57cec5SDimitry Andric return PD; 2140b57cec5SDimitry Andric 2150b57cec5SDimitry Andric if (PD->isClassProperty()) 2160b57cec5SDimitry Andric classProp = PD; 2170b57cec5SDimitry Andric } 2180b57cec5SDimitry Andric 2190b57cec5SDimitry Andric if (queryKind == ObjCPropertyQueryKind::OBJC_PR_query_unknown) 2200b57cec5SDimitry Andric // We can't find the instance property, return the class property. 2210b57cec5SDimitry Andric return classProp; 2220b57cec5SDimitry Andric 2230b57cec5SDimitry Andric return nullptr; 2240b57cec5SDimitry Andric } 2250b57cec5SDimitry Andric 2260b57cec5SDimitry Andric IdentifierInfo * 2270b57cec5SDimitry Andric ObjCPropertyDecl::getDefaultSynthIvarName(ASTContext &Ctx) const { 2280b57cec5SDimitry Andric SmallString<128> ivarName; 2290b57cec5SDimitry Andric { 2300b57cec5SDimitry Andric llvm::raw_svector_ostream os(ivarName); 2310b57cec5SDimitry Andric os << '_' << getIdentifier()->getName(); 2320b57cec5SDimitry Andric } 2330b57cec5SDimitry Andric return &Ctx.Idents.get(ivarName.str()); 2340b57cec5SDimitry Andric } 2350b57cec5SDimitry Andric 23604eeddc0SDimitry Andric ObjCPropertyDecl *ObjCContainerDecl::getProperty(const IdentifierInfo *Id, 23704eeddc0SDimitry Andric bool IsInstance) const { 23804eeddc0SDimitry Andric for (auto *LookupResult : lookup(Id)) { 23904eeddc0SDimitry Andric if (auto *Prop = dyn_cast<ObjCPropertyDecl>(LookupResult)) { 24004eeddc0SDimitry Andric if (Prop->isInstanceProperty() == IsInstance) { 24104eeddc0SDimitry Andric return Prop; 24204eeddc0SDimitry Andric } 24304eeddc0SDimitry Andric } 24404eeddc0SDimitry Andric } 24504eeddc0SDimitry Andric return nullptr; 24604eeddc0SDimitry Andric } 24704eeddc0SDimitry Andric 2480b57cec5SDimitry Andric /// FindPropertyDeclaration - Finds declaration of the property given its name 2490b57cec5SDimitry Andric /// in 'PropertyId' and returns it. It returns 0, if not found. 2500b57cec5SDimitry Andric ObjCPropertyDecl *ObjCContainerDecl::FindPropertyDeclaration( 2510b57cec5SDimitry Andric const IdentifierInfo *PropertyId, 2520b57cec5SDimitry Andric ObjCPropertyQueryKind QueryKind) const { 2530b57cec5SDimitry Andric // Don't find properties within hidden protocol definitions. 2540b57cec5SDimitry Andric if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(this)) { 2550b57cec5SDimitry Andric if (const ObjCProtocolDecl *Def = Proto->getDefinition()) 2565ffd83dbSDimitry Andric if (!Def->isUnconditionallyVisible()) 2570b57cec5SDimitry Andric return nullptr; 2580b57cec5SDimitry Andric } 2590b57cec5SDimitry Andric 2600b57cec5SDimitry Andric // Search the extensions of a class first; they override what's in 2610b57cec5SDimitry Andric // the class itself. 2620b57cec5SDimitry Andric if (const auto *ClassDecl = dyn_cast<ObjCInterfaceDecl>(this)) { 2630b57cec5SDimitry Andric for (const auto *Ext : ClassDecl->visible_extensions()) { 2640b57cec5SDimitry Andric if (auto *P = Ext->FindPropertyDeclaration(PropertyId, QueryKind)) 2650b57cec5SDimitry Andric return P; 2660b57cec5SDimitry Andric } 2670b57cec5SDimitry Andric } 2680b57cec5SDimitry Andric 2690b57cec5SDimitry Andric if (ObjCPropertyDecl *PD = 2700b57cec5SDimitry Andric ObjCPropertyDecl::findPropertyDecl(cast<DeclContext>(this), PropertyId, 2710b57cec5SDimitry Andric QueryKind)) 2720b57cec5SDimitry Andric return PD; 2730b57cec5SDimitry Andric 2740b57cec5SDimitry Andric switch (getKind()) { 2750b57cec5SDimitry Andric default: 2760b57cec5SDimitry Andric break; 2770b57cec5SDimitry Andric case Decl::ObjCProtocol: { 2780b57cec5SDimitry Andric const auto *PID = cast<ObjCProtocolDecl>(this); 2790b57cec5SDimitry Andric for (const auto *I : PID->protocols()) 2800b57cec5SDimitry Andric if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId, 2810b57cec5SDimitry Andric QueryKind)) 2820b57cec5SDimitry Andric return P; 2830b57cec5SDimitry Andric break; 2840b57cec5SDimitry Andric } 2850b57cec5SDimitry Andric case Decl::ObjCInterface: { 2860b57cec5SDimitry Andric const auto *OID = cast<ObjCInterfaceDecl>(this); 2870b57cec5SDimitry Andric // Look through categories (but not extensions; they were handled above). 2880b57cec5SDimitry Andric for (const auto *Cat : OID->visible_categories()) { 2890b57cec5SDimitry Andric if (!Cat->IsClassExtension()) 2900b57cec5SDimitry Andric if (ObjCPropertyDecl *P = Cat->FindPropertyDeclaration( 2910b57cec5SDimitry Andric PropertyId, QueryKind)) 2920b57cec5SDimitry Andric return P; 2930b57cec5SDimitry Andric } 2940b57cec5SDimitry Andric 2950b57cec5SDimitry Andric // Look through protocols. 2960b57cec5SDimitry Andric for (const auto *I : OID->all_referenced_protocols()) 2970b57cec5SDimitry Andric if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId, 2980b57cec5SDimitry Andric QueryKind)) 2990b57cec5SDimitry Andric return P; 3000b57cec5SDimitry Andric 3010b57cec5SDimitry Andric // Finally, check the super class. 3020b57cec5SDimitry Andric if (const ObjCInterfaceDecl *superClass = OID->getSuperClass()) 3030b57cec5SDimitry Andric return superClass->FindPropertyDeclaration(PropertyId, QueryKind); 3040b57cec5SDimitry Andric break; 3050b57cec5SDimitry Andric } 3060b57cec5SDimitry Andric case Decl::ObjCCategory: { 3070b57cec5SDimitry Andric const auto *OCD = cast<ObjCCategoryDecl>(this); 3080b57cec5SDimitry Andric // Look through protocols. 3090b57cec5SDimitry Andric if (!OCD->IsClassExtension()) 3100b57cec5SDimitry Andric for (const auto *I : OCD->protocols()) 3110b57cec5SDimitry Andric if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId, 3120b57cec5SDimitry Andric QueryKind)) 3130b57cec5SDimitry Andric return P; 3140b57cec5SDimitry Andric break; 3150b57cec5SDimitry Andric } 3160b57cec5SDimitry Andric } 3170b57cec5SDimitry Andric return nullptr; 3180b57cec5SDimitry Andric } 3190b57cec5SDimitry Andric 3200b57cec5SDimitry Andric void ObjCInterfaceDecl::anchor() {} 3210b57cec5SDimitry Andric 3220b57cec5SDimitry Andric ObjCTypeParamList *ObjCInterfaceDecl::getTypeParamList() const { 3230b57cec5SDimitry Andric // If this particular declaration has a type parameter list, return it. 3240b57cec5SDimitry Andric if (ObjCTypeParamList *written = getTypeParamListAsWritten()) 3250b57cec5SDimitry Andric return written; 3260b57cec5SDimitry Andric 3270b57cec5SDimitry Andric // If there is a definition, return its type parameter list. 3280b57cec5SDimitry Andric if (const ObjCInterfaceDecl *def = getDefinition()) 3290b57cec5SDimitry Andric return def->getTypeParamListAsWritten(); 3300b57cec5SDimitry Andric 3310b57cec5SDimitry Andric // Otherwise, look at previous declarations to determine whether any 3320b57cec5SDimitry Andric // of them has a type parameter list, skipping over those 3330b57cec5SDimitry Andric // declarations that do not. 3340b57cec5SDimitry Andric for (const ObjCInterfaceDecl *decl = getMostRecentDecl(); decl; 3350b57cec5SDimitry Andric decl = decl->getPreviousDecl()) { 3360b57cec5SDimitry Andric if (ObjCTypeParamList *written = decl->getTypeParamListAsWritten()) 3370b57cec5SDimitry Andric return written; 3380b57cec5SDimitry Andric } 3390b57cec5SDimitry Andric 3400b57cec5SDimitry Andric return nullptr; 3410b57cec5SDimitry Andric } 3420b57cec5SDimitry Andric 3430b57cec5SDimitry Andric void ObjCInterfaceDecl::setTypeParamList(ObjCTypeParamList *TPL) { 3440b57cec5SDimitry Andric TypeParamList = TPL; 3450b57cec5SDimitry Andric if (!TPL) 3460b57cec5SDimitry Andric return; 3470b57cec5SDimitry Andric // Set the declaration context of each of the type parameters. 3480b57cec5SDimitry Andric for (auto *typeParam : *TypeParamList) 3490b57cec5SDimitry Andric typeParam->setDeclContext(this); 3500b57cec5SDimitry Andric } 3510b57cec5SDimitry Andric 3520b57cec5SDimitry Andric ObjCInterfaceDecl *ObjCInterfaceDecl::getSuperClass() const { 3530b57cec5SDimitry Andric // FIXME: Should make sure no callers ever do this. 3540b57cec5SDimitry Andric if (!hasDefinition()) 3550b57cec5SDimitry Andric return nullptr; 3560b57cec5SDimitry Andric 3570b57cec5SDimitry Andric if (data().ExternallyCompleted) 3580b57cec5SDimitry Andric LoadExternalDefinition(); 3590b57cec5SDimitry Andric 3600b57cec5SDimitry Andric if (const ObjCObjectType *superType = getSuperClassType()) { 3610b57cec5SDimitry Andric if (ObjCInterfaceDecl *superDecl = superType->getInterface()) { 3620b57cec5SDimitry Andric if (ObjCInterfaceDecl *superDef = superDecl->getDefinition()) 3630b57cec5SDimitry Andric return superDef; 3640b57cec5SDimitry Andric 3650b57cec5SDimitry Andric return superDecl; 3660b57cec5SDimitry Andric } 3670b57cec5SDimitry Andric } 3680b57cec5SDimitry Andric 3690b57cec5SDimitry Andric return nullptr; 3700b57cec5SDimitry Andric } 3710b57cec5SDimitry Andric 3720b57cec5SDimitry Andric SourceLocation ObjCInterfaceDecl::getSuperClassLoc() const { 3730b57cec5SDimitry Andric if (TypeSourceInfo *superTInfo = getSuperClassTInfo()) 3740b57cec5SDimitry Andric return superTInfo->getTypeLoc().getBeginLoc(); 3750b57cec5SDimitry Andric 3760b57cec5SDimitry Andric return SourceLocation(); 3770b57cec5SDimitry Andric } 3780b57cec5SDimitry Andric 3790b57cec5SDimitry Andric /// FindPropertyVisibleInPrimaryClass - Finds declaration of the property 3800b57cec5SDimitry Andric /// with name 'PropertyId' in the primary class; including those in protocols 3810b57cec5SDimitry Andric /// (direct or indirect) used by the primary class. 382*0fca6ea1SDimitry Andric ObjCPropertyDecl *ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass( 383*0fca6ea1SDimitry Andric const IdentifierInfo *PropertyId, ObjCPropertyQueryKind QueryKind) const { 3840b57cec5SDimitry Andric // FIXME: Should make sure no callers ever do this. 3850b57cec5SDimitry Andric if (!hasDefinition()) 3860b57cec5SDimitry Andric return nullptr; 3870b57cec5SDimitry Andric 3880b57cec5SDimitry Andric if (data().ExternallyCompleted) 3890b57cec5SDimitry Andric LoadExternalDefinition(); 3900b57cec5SDimitry Andric 3910b57cec5SDimitry Andric if (ObjCPropertyDecl *PD = 3920b57cec5SDimitry Andric ObjCPropertyDecl::findPropertyDecl(cast<DeclContext>(this), PropertyId, 3930b57cec5SDimitry Andric QueryKind)) 3940b57cec5SDimitry Andric return PD; 3950b57cec5SDimitry Andric 3960b57cec5SDimitry Andric // Look through protocols. 3970b57cec5SDimitry Andric for (const auto *I : all_referenced_protocols()) 3980b57cec5SDimitry Andric if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId, 3990b57cec5SDimitry Andric QueryKind)) 4000b57cec5SDimitry Andric return P; 4010b57cec5SDimitry Andric 4020b57cec5SDimitry Andric return nullptr; 4030b57cec5SDimitry Andric } 4040b57cec5SDimitry Andric 405bdd1243dSDimitry Andric void ObjCInterfaceDecl::collectPropertiesToImplement(PropertyMap &PM) const { 4060b57cec5SDimitry Andric for (auto *Prop : properties()) { 4070b57cec5SDimitry Andric PM[std::make_pair(Prop->getIdentifier(), Prop->isClassProperty())] = Prop; 4080b57cec5SDimitry Andric } 4090b57cec5SDimitry Andric for (const auto *Ext : known_extensions()) { 4100b57cec5SDimitry Andric const ObjCCategoryDecl *ClassExt = Ext; 4110b57cec5SDimitry Andric for (auto *Prop : ClassExt->properties()) { 4120b57cec5SDimitry Andric PM[std::make_pair(Prop->getIdentifier(), Prop->isClassProperty())] = Prop; 4130b57cec5SDimitry Andric } 4140b57cec5SDimitry Andric } 4150b57cec5SDimitry Andric for (const auto *PI : all_referenced_protocols()) 416bdd1243dSDimitry Andric PI->collectPropertiesToImplement(PM); 4170b57cec5SDimitry Andric // Note, the properties declared only in class extensions are still copied 4180b57cec5SDimitry Andric // into the main @interface's property list, and therefore we don't 4190b57cec5SDimitry Andric // explicitly, have to search class extension properties. 4200b57cec5SDimitry Andric } 4210b57cec5SDimitry Andric 4220b57cec5SDimitry Andric bool ObjCInterfaceDecl::isArcWeakrefUnavailable() const { 4230b57cec5SDimitry Andric const ObjCInterfaceDecl *Class = this; 4240b57cec5SDimitry Andric while (Class) { 4250b57cec5SDimitry Andric if (Class->hasAttr<ArcWeakrefUnavailableAttr>()) 4260b57cec5SDimitry Andric return true; 4270b57cec5SDimitry Andric Class = Class->getSuperClass(); 4280b57cec5SDimitry Andric } 4290b57cec5SDimitry Andric return false; 4300b57cec5SDimitry Andric } 4310b57cec5SDimitry Andric 4320b57cec5SDimitry Andric const ObjCInterfaceDecl *ObjCInterfaceDecl::isObjCRequiresPropertyDefs() const { 4330b57cec5SDimitry Andric const ObjCInterfaceDecl *Class = this; 4340b57cec5SDimitry Andric while (Class) { 4350b57cec5SDimitry Andric if (Class->hasAttr<ObjCRequiresPropertyDefsAttr>()) 4360b57cec5SDimitry Andric return Class; 4370b57cec5SDimitry Andric Class = Class->getSuperClass(); 4380b57cec5SDimitry Andric } 4390b57cec5SDimitry Andric return nullptr; 4400b57cec5SDimitry Andric } 4410b57cec5SDimitry Andric 4420b57cec5SDimitry Andric void ObjCInterfaceDecl::mergeClassExtensionProtocolList( 4430b57cec5SDimitry Andric ObjCProtocolDecl *const* ExtList, unsigned ExtNum, 4440b57cec5SDimitry Andric ASTContext &C) { 4450b57cec5SDimitry Andric if (data().ExternallyCompleted) 4460b57cec5SDimitry Andric LoadExternalDefinition(); 4470b57cec5SDimitry Andric 4480b57cec5SDimitry Andric if (data().AllReferencedProtocols.empty() && 4490b57cec5SDimitry Andric data().ReferencedProtocols.empty()) { 4500b57cec5SDimitry Andric data().AllReferencedProtocols.set(ExtList, ExtNum, C); 4510b57cec5SDimitry Andric return; 4520b57cec5SDimitry Andric } 4530b57cec5SDimitry Andric 4540b57cec5SDimitry Andric // Check for duplicate protocol in class's protocol list. 4550b57cec5SDimitry Andric // This is O(n*m). But it is extremely rare and number of protocols in 4560b57cec5SDimitry Andric // class or its extension are very few. 4570b57cec5SDimitry Andric SmallVector<ObjCProtocolDecl *, 8> ProtocolRefs; 4580b57cec5SDimitry Andric for (unsigned i = 0; i < ExtNum; i++) { 4590b57cec5SDimitry Andric bool protocolExists = false; 4600b57cec5SDimitry Andric ObjCProtocolDecl *ProtoInExtension = ExtList[i]; 4610b57cec5SDimitry Andric for (auto *Proto : all_referenced_protocols()) { 4620b57cec5SDimitry Andric if (C.ProtocolCompatibleWithProtocol(ProtoInExtension, Proto)) { 4630b57cec5SDimitry Andric protocolExists = true; 4640b57cec5SDimitry Andric break; 4650b57cec5SDimitry Andric } 4660b57cec5SDimitry Andric } 4670b57cec5SDimitry Andric // Do we want to warn on a protocol in extension class which 4680b57cec5SDimitry Andric // already exist in the class? Probably not. 4690b57cec5SDimitry Andric if (!protocolExists) 4700b57cec5SDimitry Andric ProtocolRefs.push_back(ProtoInExtension); 4710b57cec5SDimitry Andric } 4720b57cec5SDimitry Andric 4730b57cec5SDimitry Andric if (ProtocolRefs.empty()) 4740b57cec5SDimitry Andric return; 4750b57cec5SDimitry Andric 4760b57cec5SDimitry Andric // Merge ProtocolRefs into class's protocol list; 4770b57cec5SDimitry Andric ProtocolRefs.append(all_referenced_protocol_begin(), 4780b57cec5SDimitry Andric all_referenced_protocol_end()); 4790b57cec5SDimitry Andric 4800b57cec5SDimitry Andric data().AllReferencedProtocols.set(ProtocolRefs.data(), ProtocolRefs.size(),C); 4810b57cec5SDimitry Andric } 4820b57cec5SDimitry Andric 4830b57cec5SDimitry Andric const ObjCInterfaceDecl * 4840b57cec5SDimitry Andric ObjCInterfaceDecl::findInterfaceWithDesignatedInitializers() const { 4850b57cec5SDimitry Andric const ObjCInterfaceDecl *IFace = this; 4860b57cec5SDimitry Andric while (IFace) { 4870b57cec5SDimitry Andric if (IFace->hasDesignatedInitializers()) 4880b57cec5SDimitry Andric return IFace; 4890b57cec5SDimitry Andric if (!IFace->inheritsDesignatedInitializers()) 4900b57cec5SDimitry Andric break; 4910b57cec5SDimitry Andric IFace = IFace->getSuperClass(); 4920b57cec5SDimitry Andric } 4930b57cec5SDimitry Andric return nullptr; 4940b57cec5SDimitry Andric } 4950b57cec5SDimitry Andric 4960b57cec5SDimitry Andric static bool isIntroducingInitializers(const ObjCInterfaceDecl *D) { 4970b57cec5SDimitry Andric for (const auto *MD : D->instance_methods()) { 4980b57cec5SDimitry Andric if (MD->getMethodFamily() == OMF_init && !MD->isOverriding()) 4990b57cec5SDimitry Andric return true; 5000b57cec5SDimitry Andric } 5010b57cec5SDimitry Andric for (const auto *Ext : D->visible_extensions()) { 5020b57cec5SDimitry Andric for (const auto *MD : Ext->instance_methods()) { 5030b57cec5SDimitry Andric if (MD->getMethodFamily() == OMF_init && !MD->isOverriding()) 5040b57cec5SDimitry Andric return true; 5050b57cec5SDimitry Andric } 5060b57cec5SDimitry Andric } 5070b57cec5SDimitry Andric if (const auto *ImplD = D->getImplementation()) { 5080b57cec5SDimitry Andric for (const auto *MD : ImplD->instance_methods()) { 5090b57cec5SDimitry Andric if (MD->getMethodFamily() == OMF_init && !MD->isOverriding()) 5100b57cec5SDimitry Andric return true; 5110b57cec5SDimitry Andric } 5120b57cec5SDimitry Andric } 5130b57cec5SDimitry Andric return false; 5140b57cec5SDimitry Andric } 5150b57cec5SDimitry Andric 5160b57cec5SDimitry Andric bool ObjCInterfaceDecl::inheritsDesignatedInitializers() const { 5170b57cec5SDimitry Andric switch (data().InheritedDesignatedInitializers) { 5180b57cec5SDimitry Andric case DefinitionData::IDI_Inherited: 5190b57cec5SDimitry Andric return true; 5200b57cec5SDimitry Andric case DefinitionData::IDI_NotInherited: 5210b57cec5SDimitry Andric return false; 5220b57cec5SDimitry Andric case DefinitionData::IDI_Unknown: 5230b57cec5SDimitry Andric // If the class introduced initializers we conservatively assume that we 5240b57cec5SDimitry Andric // don't know if any of them is a designated initializer to avoid possible 5250b57cec5SDimitry Andric // misleading warnings. 5260b57cec5SDimitry Andric if (isIntroducingInitializers(this)) { 5270b57cec5SDimitry Andric data().InheritedDesignatedInitializers = DefinitionData::IDI_NotInherited; 5280b57cec5SDimitry Andric } else { 5290b57cec5SDimitry Andric if (auto SuperD = getSuperClass()) { 5300b57cec5SDimitry Andric data().InheritedDesignatedInitializers = 5310b57cec5SDimitry Andric SuperD->declaresOrInheritsDesignatedInitializers() ? 5320b57cec5SDimitry Andric DefinitionData::IDI_Inherited : 5330b57cec5SDimitry Andric DefinitionData::IDI_NotInherited; 5340b57cec5SDimitry Andric } else { 5350b57cec5SDimitry Andric data().InheritedDesignatedInitializers = 5360b57cec5SDimitry Andric DefinitionData::IDI_NotInherited; 5370b57cec5SDimitry Andric } 5380b57cec5SDimitry Andric } 5390b57cec5SDimitry Andric assert(data().InheritedDesignatedInitializers 5400b57cec5SDimitry Andric != DefinitionData::IDI_Unknown); 5410b57cec5SDimitry Andric return data().InheritedDesignatedInitializers == 5420b57cec5SDimitry Andric DefinitionData::IDI_Inherited; 5430b57cec5SDimitry Andric } 5440b57cec5SDimitry Andric 5450b57cec5SDimitry Andric llvm_unreachable("unexpected InheritedDesignatedInitializers value"); 5460b57cec5SDimitry Andric } 5470b57cec5SDimitry Andric 5480b57cec5SDimitry Andric void ObjCInterfaceDecl::getDesignatedInitializers( 5490b57cec5SDimitry Andric llvm::SmallVectorImpl<const ObjCMethodDecl *> &Methods) const { 5500b57cec5SDimitry Andric // Check for a complete definition and recover if not so. 5510b57cec5SDimitry Andric if (!isThisDeclarationADefinition()) 5520b57cec5SDimitry Andric return; 5530b57cec5SDimitry Andric if (data().ExternallyCompleted) 5540b57cec5SDimitry Andric LoadExternalDefinition(); 5550b57cec5SDimitry Andric 5560b57cec5SDimitry Andric const ObjCInterfaceDecl *IFace= findInterfaceWithDesignatedInitializers(); 5570b57cec5SDimitry Andric if (!IFace) 5580b57cec5SDimitry Andric return; 5590b57cec5SDimitry Andric 5600b57cec5SDimitry Andric for (const auto *MD : IFace->instance_methods()) 5610b57cec5SDimitry Andric if (MD->isThisDeclarationADesignatedInitializer()) 5620b57cec5SDimitry Andric Methods.push_back(MD); 5630b57cec5SDimitry Andric for (const auto *Ext : IFace->visible_extensions()) { 5640b57cec5SDimitry Andric for (const auto *MD : Ext->instance_methods()) 5650b57cec5SDimitry Andric if (MD->isThisDeclarationADesignatedInitializer()) 5660b57cec5SDimitry Andric Methods.push_back(MD); 5670b57cec5SDimitry Andric } 5680b57cec5SDimitry Andric } 5690b57cec5SDimitry Andric 5700b57cec5SDimitry Andric bool ObjCInterfaceDecl::isDesignatedInitializer(Selector Sel, 5710b57cec5SDimitry Andric const ObjCMethodDecl **InitMethod) const { 5720b57cec5SDimitry Andric bool HasCompleteDef = isThisDeclarationADefinition(); 5730b57cec5SDimitry Andric // During deserialization the data record for the ObjCInterfaceDecl could 5740b57cec5SDimitry Andric // be made invariant by reusing the canonical decl. Take this into account 5750b57cec5SDimitry Andric // when checking for the complete definition. 5760b57cec5SDimitry Andric if (!HasCompleteDef && getCanonicalDecl()->hasDefinition() && 5770b57cec5SDimitry Andric getCanonicalDecl()->getDefinition() == getDefinition()) 5780b57cec5SDimitry Andric HasCompleteDef = true; 5790b57cec5SDimitry Andric 5800b57cec5SDimitry Andric // Check for a complete definition and recover if not so. 5810b57cec5SDimitry Andric if (!HasCompleteDef) 5820b57cec5SDimitry Andric return false; 5830b57cec5SDimitry Andric 5840b57cec5SDimitry Andric if (data().ExternallyCompleted) 5850b57cec5SDimitry Andric LoadExternalDefinition(); 5860b57cec5SDimitry Andric 5870b57cec5SDimitry Andric const ObjCInterfaceDecl *IFace= findInterfaceWithDesignatedInitializers(); 5880b57cec5SDimitry Andric if (!IFace) 5890b57cec5SDimitry Andric return false; 5900b57cec5SDimitry Andric 5910b57cec5SDimitry Andric if (const ObjCMethodDecl *MD = IFace->getInstanceMethod(Sel)) { 5920b57cec5SDimitry Andric if (MD->isThisDeclarationADesignatedInitializer()) { 5930b57cec5SDimitry Andric if (InitMethod) 5940b57cec5SDimitry Andric *InitMethod = MD; 5950b57cec5SDimitry Andric return true; 5960b57cec5SDimitry Andric } 5970b57cec5SDimitry Andric } 5980b57cec5SDimitry Andric for (const auto *Ext : IFace->visible_extensions()) { 5990b57cec5SDimitry Andric if (const ObjCMethodDecl *MD = Ext->getInstanceMethod(Sel)) { 6000b57cec5SDimitry Andric if (MD->isThisDeclarationADesignatedInitializer()) { 6010b57cec5SDimitry Andric if (InitMethod) 6020b57cec5SDimitry Andric *InitMethod = MD; 6030b57cec5SDimitry Andric return true; 6040b57cec5SDimitry Andric } 6050b57cec5SDimitry Andric } 6060b57cec5SDimitry Andric } 6070b57cec5SDimitry Andric return false; 6080b57cec5SDimitry Andric } 6090b57cec5SDimitry Andric 6100b57cec5SDimitry Andric void ObjCInterfaceDecl::allocateDefinitionData() { 6110b57cec5SDimitry Andric assert(!hasDefinition() && "ObjC class already has a definition"); 6120b57cec5SDimitry Andric Data.setPointer(new (getASTContext()) DefinitionData()); 6130b57cec5SDimitry Andric Data.getPointer()->Definition = this; 6140b57cec5SDimitry Andric } 6150b57cec5SDimitry Andric 6160b57cec5SDimitry Andric void ObjCInterfaceDecl::startDefinition() { 6170b57cec5SDimitry Andric allocateDefinitionData(); 6180b57cec5SDimitry Andric 6190b57cec5SDimitry Andric // Update all of the declarations with a pointer to the definition. 6200b57cec5SDimitry Andric for (auto *RD : redecls()) { 6210b57cec5SDimitry Andric if (RD != this) 6220b57cec5SDimitry Andric RD->Data = Data; 6230b57cec5SDimitry Andric } 6240b57cec5SDimitry Andric } 6250b57cec5SDimitry Andric 626bdd1243dSDimitry Andric void ObjCInterfaceDecl::startDuplicateDefinitionForComparison() { 627bdd1243dSDimitry Andric Data.setPointer(nullptr); 628bdd1243dSDimitry Andric allocateDefinitionData(); 629bdd1243dSDimitry Andric // Don't propagate data to other redeclarations. 630bdd1243dSDimitry Andric } 631bdd1243dSDimitry Andric 632bdd1243dSDimitry Andric void ObjCInterfaceDecl::mergeDuplicateDefinitionWithCommon( 633bdd1243dSDimitry Andric const ObjCInterfaceDecl *Definition) { 634bdd1243dSDimitry Andric Data = Definition->Data; 635bdd1243dSDimitry Andric } 636bdd1243dSDimitry Andric 6370b57cec5SDimitry Andric ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(IdentifierInfo *ID, 6380b57cec5SDimitry Andric ObjCInterfaceDecl *&clsDeclared) { 6390b57cec5SDimitry Andric // FIXME: Should make sure no callers ever do this. 6400b57cec5SDimitry Andric if (!hasDefinition()) 6410b57cec5SDimitry Andric return nullptr; 6420b57cec5SDimitry Andric 6430b57cec5SDimitry Andric if (data().ExternallyCompleted) 6440b57cec5SDimitry Andric LoadExternalDefinition(); 6450b57cec5SDimitry Andric 6460b57cec5SDimitry Andric ObjCInterfaceDecl* ClassDecl = this; 6470b57cec5SDimitry Andric while (ClassDecl != nullptr) { 6480b57cec5SDimitry Andric if (ObjCIvarDecl *I = ClassDecl->getIvarDecl(ID)) { 6490b57cec5SDimitry Andric clsDeclared = ClassDecl; 6500b57cec5SDimitry Andric return I; 6510b57cec5SDimitry Andric } 6520b57cec5SDimitry Andric 6530b57cec5SDimitry Andric for (const auto *Ext : ClassDecl->visible_extensions()) { 6540b57cec5SDimitry Andric if (ObjCIvarDecl *I = Ext->getIvarDecl(ID)) { 6550b57cec5SDimitry Andric clsDeclared = ClassDecl; 6560b57cec5SDimitry Andric return I; 6570b57cec5SDimitry Andric } 6580b57cec5SDimitry Andric } 6590b57cec5SDimitry Andric 6600b57cec5SDimitry Andric ClassDecl = ClassDecl->getSuperClass(); 6610b57cec5SDimitry Andric } 6620b57cec5SDimitry Andric return nullptr; 6630b57cec5SDimitry Andric } 6640b57cec5SDimitry Andric 6650b57cec5SDimitry Andric /// lookupInheritedClass - This method returns ObjCInterfaceDecl * of the super 6660b57cec5SDimitry Andric /// class whose name is passed as argument. If it is not one of the super classes 6670b57cec5SDimitry Andric /// the it returns NULL. 6680b57cec5SDimitry Andric ObjCInterfaceDecl *ObjCInterfaceDecl::lookupInheritedClass( 6690b57cec5SDimitry Andric const IdentifierInfo*ICName) { 6700b57cec5SDimitry Andric // FIXME: Should make sure no callers ever do this. 6710b57cec5SDimitry Andric if (!hasDefinition()) 6720b57cec5SDimitry Andric return nullptr; 6730b57cec5SDimitry Andric 6740b57cec5SDimitry Andric if (data().ExternallyCompleted) 6750b57cec5SDimitry Andric LoadExternalDefinition(); 6760b57cec5SDimitry Andric 6770b57cec5SDimitry Andric ObjCInterfaceDecl* ClassDecl = this; 6780b57cec5SDimitry Andric while (ClassDecl != nullptr) { 6790b57cec5SDimitry Andric if (ClassDecl->getIdentifier() == ICName) 6800b57cec5SDimitry Andric return ClassDecl; 6810b57cec5SDimitry Andric ClassDecl = ClassDecl->getSuperClass(); 6820b57cec5SDimitry Andric } 6830b57cec5SDimitry Andric return nullptr; 6840b57cec5SDimitry Andric } 6850b57cec5SDimitry Andric 6860b57cec5SDimitry Andric ObjCProtocolDecl * 6870b57cec5SDimitry Andric ObjCInterfaceDecl::lookupNestedProtocol(IdentifierInfo *Name) { 6880b57cec5SDimitry Andric for (auto *P : all_referenced_protocols()) 6890b57cec5SDimitry Andric if (P->lookupProtocolNamed(Name)) 6900b57cec5SDimitry Andric return P; 6910b57cec5SDimitry Andric ObjCInterfaceDecl *SuperClass = getSuperClass(); 6920b57cec5SDimitry Andric return SuperClass ? SuperClass->lookupNestedProtocol(Name) : nullptr; 6930b57cec5SDimitry Andric } 6940b57cec5SDimitry Andric 6950b57cec5SDimitry Andric /// lookupMethod - This method returns an instance/class method by looking in 6960b57cec5SDimitry Andric /// the class, its categories, and its super classes (using a linear search). 6970b57cec5SDimitry Andric /// When argument category "C" is specified, any implicit method found 6980b57cec5SDimitry Andric /// in this category is ignored. 6990b57cec5SDimitry Andric ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel, 7000b57cec5SDimitry Andric bool isInstance, 7010b57cec5SDimitry Andric bool shallowCategoryLookup, 7020b57cec5SDimitry Andric bool followSuper, 7030b57cec5SDimitry Andric const ObjCCategoryDecl *C) const 7040b57cec5SDimitry Andric { 7050b57cec5SDimitry Andric // FIXME: Should make sure no callers ever do this. 7060b57cec5SDimitry Andric if (!hasDefinition()) 7070b57cec5SDimitry Andric return nullptr; 7080b57cec5SDimitry Andric 7090b57cec5SDimitry Andric const ObjCInterfaceDecl* ClassDecl = this; 7100b57cec5SDimitry Andric ObjCMethodDecl *MethodDecl = nullptr; 7110b57cec5SDimitry Andric 7120b57cec5SDimitry Andric if (data().ExternallyCompleted) 7130b57cec5SDimitry Andric LoadExternalDefinition(); 7140b57cec5SDimitry Andric 7150b57cec5SDimitry Andric while (ClassDecl) { 7160b57cec5SDimitry Andric // 1. Look through primary class. 7170b57cec5SDimitry Andric if ((MethodDecl = ClassDecl->getMethod(Sel, isInstance))) 7180b57cec5SDimitry Andric return MethodDecl; 7190b57cec5SDimitry Andric 7200b57cec5SDimitry Andric // 2. Didn't find one yet - now look through categories. 7210b57cec5SDimitry Andric for (const auto *Cat : ClassDecl->visible_categories()) 7220b57cec5SDimitry Andric if ((MethodDecl = Cat->getMethod(Sel, isInstance))) 7230b57cec5SDimitry Andric if (C != Cat || !MethodDecl->isImplicit()) 7240b57cec5SDimitry Andric return MethodDecl; 7250b57cec5SDimitry Andric 7260b57cec5SDimitry Andric // 3. Didn't find one yet - look through primary class's protocols. 7270b57cec5SDimitry Andric for (const auto *I : ClassDecl->protocols()) 7280b57cec5SDimitry Andric if ((MethodDecl = I->lookupMethod(Sel, isInstance))) 7290b57cec5SDimitry Andric return MethodDecl; 7300b57cec5SDimitry Andric 7310b57cec5SDimitry Andric // 4. Didn't find one yet - now look through categories' protocols 7320b57cec5SDimitry Andric if (!shallowCategoryLookup) 7330b57cec5SDimitry Andric for (const auto *Cat : ClassDecl->visible_categories()) { 7340b57cec5SDimitry Andric // Didn't find one yet - look through protocols. 7350b57cec5SDimitry Andric const ObjCList<ObjCProtocolDecl> &Protocols = 7360b57cec5SDimitry Andric Cat->getReferencedProtocols(); 7370b57cec5SDimitry Andric for (auto *Protocol : Protocols) 7380b57cec5SDimitry Andric if ((MethodDecl = Protocol->lookupMethod(Sel, isInstance))) 7390b57cec5SDimitry Andric if (C != Cat || !MethodDecl->isImplicit()) 7400b57cec5SDimitry Andric return MethodDecl; 7410b57cec5SDimitry Andric } 7420b57cec5SDimitry Andric 7430b57cec5SDimitry Andric 7440b57cec5SDimitry Andric if (!followSuper) 7450b57cec5SDimitry Andric return nullptr; 7460b57cec5SDimitry Andric 7470b57cec5SDimitry Andric // 5. Get to the super class (if any). 7480b57cec5SDimitry Andric ClassDecl = ClassDecl->getSuperClass(); 7490b57cec5SDimitry Andric } 7500b57cec5SDimitry Andric return nullptr; 7510b57cec5SDimitry Andric } 7520b57cec5SDimitry Andric 7530b57cec5SDimitry Andric // Will search "local" class/category implementations for a method decl. 7540b57cec5SDimitry Andric // If failed, then we search in class's root for an instance method. 7550b57cec5SDimitry Andric // Returns 0 if no method is found. 7560b57cec5SDimitry Andric ObjCMethodDecl *ObjCInterfaceDecl::lookupPrivateMethod( 7570b57cec5SDimitry Andric const Selector &Sel, 7580b57cec5SDimitry Andric bool Instance) const { 7590b57cec5SDimitry Andric // FIXME: Should make sure no callers ever do this. 7600b57cec5SDimitry Andric if (!hasDefinition()) 7610b57cec5SDimitry Andric return nullptr; 7620b57cec5SDimitry Andric 7630b57cec5SDimitry Andric if (data().ExternallyCompleted) 7640b57cec5SDimitry Andric LoadExternalDefinition(); 7650b57cec5SDimitry Andric 7660b57cec5SDimitry Andric ObjCMethodDecl *Method = nullptr; 7670b57cec5SDimitry Andric if (ObjCImplementationDecl *ImpDecl = getImplementation()) 7680b57cec5SDimitry Andric Method = Instance ? ImpDecl->getInstanceMethod(Sel) 7690b57cec5SDimitry Andric : ImpDecl->getClassMethod(Sel); 7700b57cec5SDimitry Andric 7710b57cec5SDimitry Andric // Look through local category implementations associated with the class. 7720b57cec5SDimitry Andric if (!Method) 7730b57cec5SDimitry Andric Method = getCategoryMethod(Sel, Instance); 7740b57cec5SDimitry Andric 7750b57cec5SDimitry Andric // Before we give up, check if the selector is an instance method. 7760b57cec5SDimitry Andric // But only in the root. This matches gcc's behavior and what the 7770b57cec5SDimitry Andric // runtime expects. 7780b57cec5SDimitry Andric if (!Instance && !Method && !getSuperClass()) { 7790b57cec5SDimitry Andric Method = lookupInstanceMethod(Sel); 7800b57cec5SDimitry Andric // Look through local category implementations associated 7810b57cec5SDimitry Andric // with the root class. 7820b57cec5SDimitry Andric if (!Method) 7830b57cec5SDimitry Andric Method = lookupPrivateMethod(Sel, true); 7840b57cec5SDimitry Andric } 7850b57cec5SDimitry Andric 7860b57cec5SDimitry Andric if (!Method && getSuperClass()) 7870b57cec5SDimitry Andric return getSuperClass()->lookupPrivateMethod(Sel, Instance); 7880b57cec5SDimitry Andric return Method; 7890b57cec5SDimitry Andric } 7900b57cec5SDimitry Andric 791bdd1243dSDimitry Andric unsigned ObjCInterfaceDecl::getODRHash() { 792bdd1243dSDimitry Andric assert(hasDefinition() && "ODRHash only for records with definitions"); 793bdd1243dSDimitry Andric 794bdd1243dSDimitry Andric // Previously calculated hash is stored in DefinitionData. 795bdd1243dSDimitry Andric if (hasODRHash()) 796bdd1243dSDimitry Andric return data().ODRHash; 797bdd1243dSDimitry Andric 798bdd1243dSDimitry Andric // Only calculate hash on first call of getODRHash per record. 799bdd1243dSDimitry Andric ODRHash Hasher; 800bdd1243dSDimitry Andric Hasher.AddObjCInterfaceDecl(getDefinition()); 801bdd1243dSDimitry Andric data().ODRHash = Hasher.CalculateHash(); 802bdd1243dSDimitry Andric setHasODRHash(true); 803bdd1243dSDimitry Andric 804bdd1243dSDimitry Andric return data().ODRHash; 805bdd1243dSDimitry Andric } 806bdd1243dSDimitry Andric 807bdd1243dSDimitry Andric bool ObjCInterfaceDecl::hasODRHash() const { 808bdd1243dSDimitry Andric if (!hasDefinition()) 809bdd1243dSDimitry Andric return false; 810bdd1243dSDimitry Andric return data().HasODRHash; 811bdd1243dSDimitry Andric } 812bdd1243dSDimitry Andric 813bdd1243dSDimitry Andric void ObjCInterfaceDecl::setHasODRHash(bool HasHash) { 814bdd1243dSDimitry Andric assert(hasDefinition() && "Cannot set ODRHash without definition"); 815bdd1243dSDimitry Andric data().HasODRHash = HasHash; 816bdd1243dSDimitry Andric } 817bdd1243dSDimitry Andric 8180b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8190b57cec5SDimitry Andric // ObjCMethodDecl 8200b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8210b57cec5SDimitry Andric 822480093f4SDimitry Andric ObjCMethodDecl::ObjCMethodDecl( 823480093f4SDimitry Andric SourceLocation beginLoc, SourceLocation endLoc, Selector SelInfo, 824480093f4SDimitry Andric QualType T, TypeSourceInfo *ReturnTInfo, DeclContext *contextDecl, 825480093f4SDimitry Andric bool isInstance, bool isVariadic, bool isPropertyAccessor, 826480093f4SDimitry Andric bool isSynthesizedAccessorStub, bool isImplicitlyDeclared, bool isDefined, 8275f757f3fSDimitry Andric ObjCImplementationControl impControl, bool HasRelatedResultType) 8280b57cec5SDimitry Andric : NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo), 8290b57cec5SDimitry Andric DeclContext(ObjCMethod), MethodDeclType(T), ReturnTInfo(ReturnTInfo), 8300b57cec5SDimitry Andric DeclEndLoc(endLoc) { 8310b57cec5SDimitry Andric 8320b57cec5SDimitry Andric // Initialized the bits stored in DeclContext. 8330b57cec5SDimitry Andric ObjCMethodDeclBits.Family = 8340b57cec5SDimitry Andric static_cast<ObjCMethodFamily>(InvalidObjCMethodFamily); 8350b57cec5SDimitry Andric setInstanceMethod(isInstance); 8360b57cec5SDimitry Andric setVariadic(isVariadic); 8370b57cec5SDimitry Andric setPropertyAccessor(isPropertyAccessor); 838480093f4SDimitry Andric setSynthesizedAccessorStub(isSynthesizedAccessorStub); 8390b57cec5SDimitry Andric setDefined(isDefined); 8400b57cec5SDimitry Andric setIsRedeclaration(false); 8410b57cec5SDimitry Andric setHasRedeclaration(false); 8420b57cec5SDimitry Andric setDeclImplementation(impControl); 8430b57cec5SDimitry Andric setObjCDeclQualifier(OBJC_TQ_None); 8440b57cec5SDimitry Andric setRelatedResultType(HasRelatedResultType); 8450b57cec5SDimitry Andric setSelLocsKind(SelLoc_StandardNoSpace); 8460b57cec5SDimitry Andric setOverriding(false); 8470b57cec5SDimitry Andric setHasSkippedBody(false); 8480b57cec5SDimitry Andric 8490b57cec5SDimitry Andric setImplicit(isImplicitlyDeclared); 8500b57cec5SDimitry Andric } 8510b57cec5SDimitry Andric 8520b57cec5SDimitry Andric ObjCMethodDecl *ObjCMethodDecl::Create( 8530b57cec5SDimitry Andric ASTContext &C, SourceLocation beginLoc, SourceLocation endLoc, 8540b57cec5SDimitry Andric Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo, 8550b57cec5SDimitry Andric DeclContext *contextDecl, bool isInstance, bool isVariadic, 856480093f4SDimitry Andric bool isPropertyAccessor, bool isSynthesizedAccessorStub, 8575f757f3fSDimitry Andric bool isImplicitlyDeclared, bool isDefined, 8585f757f3fSDimitry Andric ObjCImplementationControl impControl, bool HasRelatedResultType) { 8590b57cec5SDimitry Andric return new (C, contextDecl) ObjCMethodDecl( 8600b57cec5SDimitry Andric beginLoc, endLoc, SelInfo, T, ReturnTInfo, contextDecl, isInstance, 861480093f4SDimitry Andric isVariadic, isPropertyAccessor, isSynthesizedAccessorStub, 862480093f4SDimitry Andric isImplicitlyDeclared, isDefined, impControl, HasRelatedResultType); 8630b57cec5SDimitry Andric } 8640b57cec5SDimitry Andric 865*0fca6ea1SDimitry Andric ObjCMethodDecl *ObjCMethodDecl::CreateDeserialized(ASTContext &C, 866*0fca6ea1SDimitry Andric GlobalDeclID ID) { 8670b57cec5SDimitry Andric return new (C, ID) ObjCMethodDecl(SourceLocation(), SourceLocation(), 8680b57cec5SDimitry Andric Selector(), QualType(), nullptr, nullptr); 8690b57cec5SDimitry Andric } 8700b57cec5SDimitry Andric 871480093f4SDimitry Andric bool ObjCMethodDecl::isDirectMethod() const { 872fe6060f1SDimitry Andric return hasAttr<ObjCDirectAttr>() && 873fe6060f1SDimitry Andric !getASTContext().getLangOpts().ObjCDisableDirectMethodsForTesting; 874480093f4SDimitry Andric } 875480093f4SDimitry Andric 8760b57cec5SDimitry Andric bool ObjCMethodDecl::isThisDeclarationADesignatedInitializer() const { 8770b57cec5SDimitry Andric return getMethodFamily() == OMF_init && 8780b57cec5SDimitry Andric hasAttr<ObjCDesignatedInitializerAttr>(); 8790b57cec5SDimitry Andric } 8800b57cec5SDimitry Andric 8810b57cec5SDimitry Andric bool ObjCMethodDecl::definedInNSObject(const ASTContext &Ctx) const { 8820b57cec5SDimitry Andric if (const auto *PD = dyn_cast<const ObjCProtocolDecl>(getDeclContext())) 8830b57cec5SDimitry Andric return PD->getIdentifier() == Ctx.getNSObjectName(); 8840b57cec5SDimitry Andric if (const auto *ID = dyn_cast<const ObjCInterfaceDecl>(getDeclContext())) 8850b57cec5SDimitry Andric return ID->getIdentifier() == Ctx.getNSObjectName(); 8860b57cec5SDimitry Andric return false; 8870b57cec5SDimitry Andric } 8880b57cec5SDimitry Andric 8890b57cec5SDimitry Andric bool ObjCMethodDecl::isDesignatedInitializerForTheInterface( 8900b57cec5SDimitry Andric const ObjCMethodDecl **InitMethod) const { 8910b57cec5SDimitry Andric if (getMethodFamily() != OMF_init) 8920b57cec5SDimitry Andric return false; 8930b57cec5SDimitry Andric const DeclContext *DC = getDeclContext(); 8940b57cec5SDimitry Andric if (isa<ObjCProtocolDecl>(DC)) 8950b57cec5SDimitry Andric return false; 8960b57cec5SDimitry Andric if (const ObjCInterfaceDecl *ID = getClassInterface()) 8970b57cec5SDimitry Andric return ID->isDesignatedInitializer(getSelector(), InitMethod); 8980b57cec5SDimitry Andric return false; 8990b57cec5SDimitry Andric } 9000b57cec5SDimitry Andric 901349cc55cSDimitry Andric bool ObjCMethodDecl::hasParamDestroyedInCallee() const { 902bdd1243dSDimitry Andric for (auto *param : parameters()) { 903349cc55cSDimitry Andric if (param->isDestroyedInCallee()) 904349cc55cSDimitry Andric return true; 905349cc55cSDimitry Andric } 906349cc55cSDimitry Andric return false; 907349cc55cSDimitry Andric } 908349cc55cSDimitry Andric 9090b57cec5SDimitry Andric Stmt *ObjCMethodDecl::getBody() const { 9100b57cec5SDimitry Andric return Body.get(getASTContext().getExternalSource()); 9110b57cec5SDimitry Andric } 9120b57cec5SDimitry Andric 9130b57cec5SDimitry Andric void ObjCMethodDecl::setAsRedeclaration(const ObjCMethodDecl *PrevMethod) { 9140b57cec5SDimitry Andric assert(PrevMethod); 9150b57cec5SDimitry Andric getASTContext().setObjCMethodRedeclaration(PrevMethod, this); 9160b57cec5SDimitry Andric setIsRedeclaration(true); 9170b57cec5SDimitry Andric PrevMethod->setHasRedeclaration(true); 9180b57cec5SDimitry Andric } 9190b57cec5SDimitry Andric 9200b57cec5SDimitry Andric void ObjCMethodDecl::setParamsAndSelLocs(ASTContext &C, 9210b57cec5SDimitry Andric ArrayRef<ParmVarDecl*> Params, 9220b57cec5SDimitry Andric ArrayRef<SourceLocation> SelLocs) { 9230b57cec5SDimitry Andric ParamsAndSelLocs = nullptr; 9240b57cec5SDimitry Andric NumParams = Params.size(); 9250b57cec5SDimitry Andric if (Params.empty() && SelLocs.empty()) 9260b57cec5SDimitry Andric return; 9270b57cec5SDimitry Andric 9280b57cec5SDimitry Andric static_assert(alignof(ParmVarDecl *) >= alignof(SourceLocation), 9290b57cec5SDimitry Andric "Alignment not sufficient for SourceLocation"); 9300b57cec5SDimitry Andric 9310b57cec5SDimitry Andric unsigned Size = sizeof(ParmVarDecl *) * NumParams + 9320b57cec5SDimitry Andric sizeof(SourceLocation) * SelLocs.size(); 9330b57cec5SDimitry Andric ParamsAndSelLocs = C.Allocate(Size); 9345f757f3fSDimitry Andric std::uninitialized_copy(Params.begin(), Params.end(), getParams()); 9355f757f3fSDimitry Andric std::uninitialized_copy(SelLocs.begin(), SelLocs.end(), getStoredSelLocs()); 9360b57cec5SDimitry Andric } 9370b57cec5SDimitry Andric 9380b57cec5SDimitry Andric void ObjCMethodDecl::getSelectorLocs( 9390b57cec5SDimitry Andric SmallVectorImpl<SourceLocation> &SelLocs) const { 9400b57cec5SDimitry Andric for (unsigned i = 0, e = getNumSelectorLocs(); i != e; ++i) 9410b57cec5SDimitry Andric SelLocs.push_back(getSelectorLoc(i)); 9420b57cec5SDimitry Andric } 9430b57cec5SDimitry Andric 9440b57cec5SDimitry Andric void ObjCMethodDecl::setMethodParams(ASTContext &C, 9450b57cec5SDimitry Andric ArrayRef<ParmVarDecl*> Params, 9460b57cec5SDimitry Andric ArrayRef<SourceLocation> SelLocs) { 9470b57cec5SDimitry Andric assert((!SelLocs.empty() || isImplicit()) && 9480b57cec5SDimitry Andric "No selector locs for non-implicit method"); 9490b57cec5SDimitry Andric if (isImplicit()) 950bdd1243dSDimitry Andric return setParamsAndSelLocs(C, Params, std::nullopt); 9510b57cec5SDimitry Andric 9520b57cec5SDimitry Andric setSelLocsKind(hasStandardSelectorLocs(getSelector(), SelLocs, Params, 9530b57cec5SDimitry Andric DeclEndLoc)); 9540b57cec5SDimitry Andric if (getSelLocsKind() != SelLoc_NonStandard) 955bdd1243dSDimitry Andric return setParamsAndSelLocs(C, Params, std::nullopt); 9560b57cec5SDimitry Andric 9570b57cec5SDimitry Andric setParamsAndSelLocs(C, Params, SelLocs); 9580b57cec5SDimitry Andric } 9590b57cec5SDimitry Andric 9600b57cec5SDimitry Andric /// A definition will return its interface declaration. 9610b57cec5SDimitry Andric /// An interface declaration will return its definition. 9620b57cec5SDimitry Andric /// Otherwise it will return itself. 9630b57cec5SDimitry Andric ObjCMethodDecl *ObjCMethodDecl::getNextRedeclarationImpl() { 9640b57cec5SDimitry Andric ASTContext &Ctx = getASTContext(); 9650b57cec5SDimitry Andric ObjCMethodDecl *Redecl = nullptr; 9660b57cec5SDimitry Andric if (hasRedeclaration()) 9670b57cec5SDimitry Andric Redecl = const_cast<ObjCMethodDecl*>(Ctx.getObjCMethodRedeclaration(this)); 9680b57cec5SDimitry Andric if (Redecl) 9690b57cec5SDimitry Andric return Redecl; 9700b57cec5SDimitry Andric 9710b57cec5SDimitry Andric auto *CtxD = cast<Decl>(getDeclContext()); 9720b57cec5SDimitry Andric 9730b57cec5SDimitry Andric if (!CtxD->isInvalidDecl()) { 9740b57cec5SDimitry Andric if (auto *IFD = dyn_cast<ObjCInterfaceDecl>(CtxD)) { 9750b57cec5SDimitry Andric if (ObjCImplementationDecl *ImplD = Ctx.getObjCImplementation(IFD)) 9760b57cec5SDimitry Andric if (!ImplD->isInvalidDecl()) 9770b57cec5SDimitry Andric Redecl = ImplD->getMethod(getSelector(), isInstanceMethod()); 9780b57cec5SDimitry Andric 9790b57cec5SDimitry Andric } else if (auto *CD = dyn_cast<ObjCCategoryDecl>(CtxD)) { 9800b57cec5SDimitry Andric if (ObjCCategoryImplDecl *ImplD = Ctx.getObjCImplementation(CD)) 9810b57cec5SDimitry Andric if (!ImplD->isInvalidDecl()) 9820b57cec5SDimitry Andric Redecl = ImplD->getMethod(getSelector(), isInstanceMethod()); 9830b57cec5SDimitry Andric 9840b57cec5SDimitry Andric } else if (auto *ImplD = dyn_cast<ObjCImplementationDecl>(CtxD)) { 9850b57cec5SDimitry Andric if (ObjCInterfaceDecl *IFD = ImplD->getClassInterface()) 9860b57cec5SDimitry Andric if (!IFD->isInvalidDecl()) 9870b57cec5SDimitry Andric Redecl = IFD->getMethod(getSelector(), isInstanceMethod()); 9880b57cec5SDimitry Andric 9890b57cec5SDimitry Andric } else if (auto *CImplD = dyn_cast<ObjCCategoryImplDecl>(CtxD)) { 9900b57cec5SDimitry Andric if (ObjCCategoryDecl *CatD = CImplD->getCategoryDecl()) 9910b57cec5SDimitry Andric if (!CatD->isInvalidDecl()) 9920b57cec5SDimitry Andric Redecl = CatD->getMethod(getSelector(), isInstanceMethod()); 9930b57cec5SDimitry Andric } 9940b57cec5SDimitry Andric } 9950b57cec5SDimitry Andric 9960b57cec5SDimitry Andric // Ensure that the discovered method redeclaration has a valid declaration 9970b57cec5SDimitry Andric // context. Used to prevent infinite loops when iterating redeclarations in 9980b57cec5SDimitry Andric // a partially invalid AST. 9990b57cec5SDimitry Andric if (Redecl && cast<Decl>(Redecl->getDeclContext())->isInvalidDecl()) 10000b57cec5SDimitry Andric Redecl = nullptr; 10010b57cec5SDimitry Andric 10020b57cec5SDimitry Andric if (!Redecl && isRedeclaration()) { 10030b57cec5SDimitry Andric // This is the last redeclaration, go back to the first method. 10040b57cec5SDimitry Andric return cast<ObjCContainerDecl>(CtxD)->getMethod(getSelector(), 1005e8d8bef9SDimitry Andric isInstanceMethod(), 1006e8d8bef9SDimitry Andric /*AllowHidden=*/true); 10070b57cec5SDimitry Andric } 10080b57cec5SDimitry Andric 10090b57cec5SDimitry Andric return Redecl ? Redecl : this; 10100b57cec5SDimitry Andric } 10110b57cec5SDimitry Andric 10120b57cec5SDimitry Andric ObjCMethodDecl *ObjCMethodDecl::getCanonicalDecl() { 10130b57cec5SDimitry Andric auto *CtxD = cast<Decl>(getDeclContext()); 1014480093f4SDimitry Andric const auto &Sel = getSelector(); 10150b57cec5SDimitry Andric 10160b57cec5SDimitry Andric if (auto *ImplD = dyn_cast<ObjCImplementationDecl>(CtxD)) { 1017480093f4SDimitry Andric if (ObjCInterfaceDecl *IFD = ImplD->getClassInterface()) { 1018480093f4SDimitry Andric // When the container is the ObjCImplementationDecl (the primary 1019480093f4SDimitry Andric // @implementation), then the canonical Decl is either in 1020480093f4SDimitry Andric // the class Interface, or in any of its extension. 1021480093f4SDimitry Andric // 1022480093f4SDimitry Andric // So when we don't find it in the ObjCInterfaceDecl, 1023480093f4SDimitry Andric // sift through extensions too. 1024480093f4SDimitry Andric if (ObjCMethodDecl *MD = IFD->getMethod(Sel, isInstanceMethod())) 10250b57cec5SDimitry Andric return MD; 1026480093f4SDimitry Andric for (auto *Ext : IFD->known_extensions()) 1027480093f4SDimitry Andric if (ObjCMethodDecl *MD = Ext->getMethod(Sel, isInstanceMethod())) 1028480093f4SDimitry Andric return MD; 1029480093f4SDimitry Andric } 10300b57cec5SDimitry Andric } else if (auto *CImplD = dyn_cast<ObjCCategoryImplDecl>(CtxD)) { 10310b57cec5SDimitry Andric if (ObjCCategoryDecl *CatD = CImplD->getCategoryDecl()) 1032480093f4SDimitry Andric if (ObjCMethodDecl *MD = CatD->getMethod(Sel, isInstanceMethod())) 10330b57cec5SDimitry Andric return MD; 10340b57cec5SDimitry Andric } 10350b57cec5SDimitry Andric 10360b57cec5SDimitry Andric if (isRedeclaration()) { 10370b57cec5SDimitry Andric // It is possible that we have not done deserializing the ObjCMethod yet. 10380b57cec5SDimitry Andric ObjCMethodDecl *MD = 1039e8d8bef9SDimitry Andric cast<ObjCContainerDecl>(CtxD)->getMethod(Sel, isInstanceMethod(), 1040e8d8bef9SDimitry Andric /*AllowHidden=*/true); 10410b57cec5SDimitry Andric return MD ? MD : this; 10420b57cec5SDimitry Andric } 10430b57cec5SDimitry Andric 10440b57cec5SDimitry Andric return this; 10450b57cec5SDimitry Andric } 10460b57cec5SDimitry Andric 10470b57cec5SDimitry Andric SourceLocation ObjCMethodDecl::getEndLoc() const { 10480b57cec5SDimitry Andric if (Stmt *Body = getBody()) 10490b57cec5SDimitry Andric return Body->getEndLoc(); 10500b57cec5SDimitry Andric return DeclEndLoc; 10510b57cec5SDimitry Andric } 10520b57cec5SDimitry Andric 10530b57cec5SDimitry Andric ObjCMethodFamily ObjCMethodDecl::getMethodFamily() const { 10540b57cec5SDimitry Andric auto family = static_cast<ObjCMethodFamily>(ObjCMethodDeclBits.Family); 10550b57cec5SDimitry Andric if (family != static_cast<unsigned>(InvalidObjCMethodFamily)) 10560b57cec5SDimitry Andric return family; 10570b57cec5SDimitry Andric 10580b57cec5SDimitry Andric // Check for an explicit attribute. 10590b57cec5SDimitry Andric if (const ObjCMethodFamilyAttr *attr = getAttr<ObjCMethodFamilyAttr>()) { 10600b57cec5SDimitry Andric // The unfortunate necessity of mapping between enums here is due 10610b57cec5SDimitry Andric // to the attributes framework. 10620b57cec5SDimitry Andric switch (attr->getFamily()) { 10630b57cec5SDimitry Andric case ObjCMethodFamilyAttr::OMF_None: family = OMF_None; break; 10640b57cec5SDimitry Andric case ObjCMethodFamilyAttr::OMF_alloc: family = OMF_alloc; break; 10650b57cec5SDimitry Andric case ObjCMethodFamilyAttr::OMF_copy: family = OMF_copy; break; 10660b57cec5SDimitry Andric case ObjCMethodFamilyAttr::OMF_init: family = OMF_init; break; 10670b57cec5SDimitry Andric case ObjCMethodFamilyAttr::OMF_mutableCopy: family = OMF_mutableCopy; break; 10680b57cec5SDimitry Andric case ObjCMethodFamilyAttr::OMF_new: family = OMF_new; break; 10690b57cec5SDimitry Andric } 10700b57cec5SDimitry Andric ObjCMethodDeclBits.Family = family; 10710b57cec5SDimitry Andric return family; 10720b57cec5SDimitry Andric } 10730b57cec5SDimitry Andric 10740b57cec5SDimitry Andric family = getSelector().getMethodFamily(); 10750b57cec5SDimitry Andric switch (family) { 10760b57cec5SDimitry Andric case OMF_None: break; 10770b57cec5SDimitry Andric 10780b57cec5SDimitry Andric // init only has a conventional meaning for an instance method, and 10790b57cec5SDimitry Andric // it has to return an object. 10800b57cec5SDimitry Andric case OMF_init: 10810b57cec5SDimitry Andric if (!isInstanceMethod() || !getReturnType()->isObjCObjectPointerType()) 10820b57cec5SDimitry Andric family = OMF_None; 10830b57cec5SDimitry Andric break; 10840b57cec5SDimitry Andric 10850b57cec5SDimitry Andric // alloc/copy/new have a conventional meaning for both class and 10860b57cec5SDimitry Andric // instance methods, but they require an object return. 10870b57cec5SDimitry Andric case OMF_alloc: 10880b57cec5SDimitry Andric case OMF_copy: 10890b57cec5SDimitry Andric case OMF_mutableCopy: 10900b57cec5SDimitry Andric case OMF_new: 10910b57cec5SDimitry Andric if (!getReturnType()->isObjCObjectPointerType()) 10920b57cec5SDimitry Andric family = OMF_None; 10930b57cec5SDimitry Andric break; 10940b57cec5SDimitry Andric 10950b57cec5SDimitry Andric // These selectors have a conventional meaning only for instance methods. 10960b57cec5SDimitry Andric case OMF_dealloc: 10970b57cec5SDimitry Andric case OMF_finalize: 10980b57cec5SDimitry Andric case OMF_retain: 10990b57cec5SDimitry Andric case OMF_release: 11000b57cec5SDimitry Andric case OMF_autorelease: 11010b57cec5SDimitry Andric case OMF_retainCount: 11020b57cec5SDimitry Andric case OMF_self: 11030b57cec5SDimitry Andric if (!isInstanceMethod()) 11040b57cec5SDimitry Andric family = OMF_None; 11050b57cec5SDimitry Andric break; 11060b57cec5SDimitry Andric 11070b57cec5SDimitry Andric case OMF_initialize: 11080b57cec5SDimitry Andric if (isInstanceMethod() || !getReturnType()->isVoidType()) 11090b57cec5SDimitry Andric family = OMF_None; 11100b57cec5SDimitry Andric break; 11110b57cec5SDimitry Andric 11120b57cec5SDimitry Andric case OMF_performSelector: 11130b57cec5SDimitry Andric if (!isInstanceMethod() || !getReturnType()->isObjCIdType()) 11140b57cec5SDimitry Andric family = OMF_None; 11150b57cec5SDimitry Andric else { 11160b57cec5SDimitry Andric unsigned noParams = param_size(); 11170b57cec5SDimitry Andric if (noParams < 1 || noParams > 3) 11180b57cec5SDimitry Andric family = OMF_None; 11190b57cec5SDimitry Andric else { 11200b57cec5SDimitry Andric ObjCMethodDecl::param_type_iterator it = param_type_begin(); 11210b57cec5SDimitry Andric QualType ArgT = (*it); 11220b57cec5SDimitry Andric if (!ArgT->isObjCSelType()) { 11230b57cec5SDimitry Andric family = OMF_None; 11240b57cec5SDimitry Andric break; 11250b57cec5SDimitry Andric } 11260b57cec5SDimitry Andric while (--noParams) { 11270b57cec5SDimitry Andric it++; 11280b57cec5SDimitry Andric ArgT = (*it); 11290b57cec5SDimitry Andric if (!ArgT->isObjCIdType()) { 11300b57cec5SDimitry Andric family = OMF_None; 11310b57cec5SDimitry Andric break; 11320b57cec5SDimitry Andric } 11330b57cec5SDimitry Andric } 11340b57cec5SDimitry Andric } 11350b57cec5SDimitry Andric } 11360b57cec5SDimitry Andric break; 11370b57cec5SDimitry Andric 11380b57cec5SDimitry Andric } 11390b57cec5SDimitry Andric 11400b57cec5SDimitry Andric // Cache the result. 11410b57cec5SDimitry Andric ObjCMethodDeclBits.Family = family; 11420b57cec5SDimitry Andric return family; 11430b57cec5SDimitry Andric } 11440b57cec5SDimitry Andric 11450b57cec5SDimitry Andric QualType ObjCMethodDecl::getSelfType(ASTContext &Context, 11460b57cec5SDimitry Andric const ObjCInterfaceDecl *OID, 11470b57cec5SDimitry Andric bool &selfIsPseudoStrong, 1148480093f4SDimitry Andric bool &selfIsConsumed) const { 11490b57cec5SDimitry Andric QualType selfTy; 11500b57cec5SDimitry Andric selfIsPseudoStrong = false; 11510b57cec5SDimitry Andric selfIsConsumed = false; 11520b57cec5SDimitry Andric if (isInstanceMethod()) { 11530b57cec5SDimitry Andric // There may be no interface context due to error in declaration 11540b57cec5SDimitry Andric // of the interface (which has been reported). Recover gracefully. 11550b57cec5SDimitry Andric if (OID) { 11560b57cec5SDimitry Andric selfTy = Context.getObjCInterfaceType(OID); 11570b57cec5SDimitry Andric selfTy = Context.getObjCObjectPointerType(selfTy); 11580b57cec5SDimitry Andric } else { 11590b57cec5SDimitry Andric selfTy = Context.getObjCIdType(); 11600b57cec5SDimitry Andric } 11610b57cec5SDimitry Andric } else // we have a factory method. 11620b57cec5SDimitry Andric selfTy = Context.getObjCClassType(); 11630b57cec5SDimitry Andric 11640b57cec5SDimitry Andric if (Context.getLangOpts().ObjCAutoRefCount) { 11650b57cec5SDimitry Andric if (isInstanceMethod()) { 11660b57cec5SDimitry Andric selfIsConsumed = hasAttr<NSConsumesSelfAttr>(); 11670b57cec5SDimitry Andric 11680b57cec5SDimitry Andric // 'self' is always __strong. It's actually pseudo-strong except 11690b57cec5SDimitry Andric // in init methods (or methods labeled ns_consumes_self), though. 11700b57cec5SDimitry Andric Qualifiers qs; 11710b57cec5SDimitry Andric qs.setObjCLifetime(Qualifiers::OCL_Strong); 11720b57cec5SDimitry Andric selfTy = Context.getQualifiedType(selfTy, qs); 11730b57cec5SDimitry Andric 11740b57cec5SDimitry Andric // In addition, 'self' is const unless this is an init method. 11750b57cec5SDimitry Andric if (getMethodFamily() != OMF_init && !selfIsConsumed) { 11760b57cec5SDimitry Andric selfTy = selfTy.withConst(); 11770b57cec5SDimitry Andric selfIsPseudoStrong = true; 11780b57cec5SDimitry Andric } 11790b57cec5SDimitry Andric } 11800b57cec5SDimitry Andric else { 11810b57cec5SDimitry Andric assert(isClassMethod()); 11820b57cec5SDimitry Andric // 'self' is always const in class methods. 11830b57cec5SDimitry Andric selfTy = selfTy.withConst(); 11840b57cec5SDimitry Andric selfIsPseudoStrong = true; 11850b57cec5SDimitry Andric } 11860b57cec5SDimitry Andric } 11870b57cec5SDimitry Andric return selfTy; 11880b57cec5SDimitry Andric } 11890b57cec5SDimitry Andric 11900b57cec5SDimitry Andric void ObjCMethodDecl::createImplicitParams(ASTContext &Context, 11910b57cec5SDimitry Andric const ObjCInterfaceDecl *OID) { 11920b57cec5SDimitry Andric bool selfIsPseudoStrong, selfIsConsumed; 11930b57cec5SDimitry Andric QualType selfTy = 11940b57cec5SDimitry Andric getSelfType(Context, OID, selfIsPseudoStrong, selfIsConsumed); 11950b57cec5SDimitry Andric auto *Self = ImplicitParamDecl::Create(Context, this, SourceLocation(), 11960b57cec5SDimitry Andric &Context.Idents.get("self"), selfTy, 11975f757f3fSDimitry Andric ImplicitParamKind::ObjCSelf); 11980b57cec5SDimitry Andric setSelfDecl(Self); 11990b57cec5SDimitry Andric 12000b57cec5SDimitry Andric if (selfIsConsumed) 12010b57cec5SDimitry Andric Self->addAttr(NSConsumedAttr::CreateImplicit(Context)); 12020b57cec5SDimitry Andric 12030b57cec5SDimitry Andric if (selfIsPseudoStrong) 12040b57cec5SDimitry Andric Self->setARCPseudoStrong(true); 12050b57cec5SDimitry Andric 12060b57cec5SDimitry Andric setCmdDecl(ImplicitParamDecl::Create( 12070b57cec5SDimitry Andric Context, this, SourceLocation(), &Context.Idents.get("_cmd"), 12085f757f3fSDimitry Andric Context.getObjCSelType(), ImplicitParamKind::ObjCCmd)); 12090b57cec5SDimitry Andric } 12100b57cec5SDimitry Andric 12110b57cec5SDimitry Andric ObjCInterfaceDecl *ObjCMethodDecl::getClassInterface() { 12120b57cec5SDimitry Andric if (auto *ID = dyn_cast<ObjCInterfaceDecl>(getDeclContext())) 12130b57cec5SDimitry Andric return ID; 12140b57cec5SDimitry Andric if (auto *CD = dyn_cast<ObjCCategoryDecl>(getDeclContext())) 12150b57cec5SDimitry Andric return CD->getClassInterface(); 12160b57cec5SDimitry Andric if (auto *IMD = dyn_cast<ObjCImplDecl>(getDeclContext())) 12170b57cec5SDimitry Andric return IMD->getClassInterface(); 12180b57cec5SDimitry Andric if (isa<ObjCProtocolDecl>(getDeclContext())) 12190b57cec5SDimitry Andric return nullptr; 12200b57cec5SDimitry Andric llvm_unreachable("unknown method context"); 12210b57cec5SDimitry Andric } 12220b57cec5SDimitry Andric 1223e8d8bef9SDimitry Andric ObjCCategoryDecl *ObjCMethodDecl::getCategory() { 1224e8d8bef9SDimitry Andric if (auto *CD = dyn_cast<ObjCCategoryDecl>(getDeclContext())) 1225e8d8bef9SDimitry Andric return CD; 1226e8d8bef9SDimitry Andric if (auto *IMD = dyn_cast<ObjCCategoryImplDecl>(getDeclContext())) 1227e8d8bef9SDimitry Andric return IMD->getCategoryDecl(); 1228e8d8bef9SDimitry Andric return nullptr; 1229e8d8bef9SDimitry Andric } 1230e8d8bef9SDimitry Andric 12310b57cec5SDimitry Andric SourceRange ObjCMethodDecl::getReturnTypeSourceRange() const { 12320b57cec5SDimitry Andric const auto *TSI = getReturnTypeSourceInfo(); 12330b57cec5SDimitry Andric if (TSI) 12340b57cec5SDimitry Andric return TSI->getTypeLoc().getSourceRange(); 12350b57cec5SDimitry Andric return SourceRange(); 12360b57cec5SDimitry Andric } 12370b57cec5SDimitry Andric 12380b57cec5SDimitry Andric QualType ObjCMethodDecl::getSendResultType() const { 12390b57cec5SDimitry Andric ASTContext &Ctx = getASTContext(); 12400b57cec5SDimitry Andric return getReturnType().getNonLValueExprType(Ctx) 12410b57cec5SDimitry Andric .substObjCTypeArgs(Ctx, {}, ObjCSubstitutionContext::Result); 12420b57cec5SDimitry Andric } 12430b57cec5SDimitry Andric 12440b57cec5SDimitry Andric QualType ObjCMethodDecl::getSendResultType(QualType receiverType) const { 12450b57cec5SDimitry Andric // FIXME: Handle related result types here. 12460b57cec5SDimitry Andric 12470b57cec5SDimitry Andric return getReturnType().getNonLValueExprType(getASTContext()) 12480b57cec5SDimitry Andric .substObjCMemberType(receiverType, getDeclContext(), 12490b57cec5SDimitry Andric ObjCSubstitutionContext::Result); 12500b57cec5SDimitry Andric } 12510b57cec5SDimitry Andric 12520b57cec5SDimitry Andric static void CollectOverriddenMethodsRecurse(const ObjCContainerDecl *Container, 12530b57cec5SDimitry Andric const ObjCMethodDecl *Method, 12540b57cec5SDimitry Andric SmallVectorImpl<const ObjCMethodDecl *> &Methods, 12550b57cec5SDimitry Andric bool MovedToSuper) { 12560b57cec5SDimitry Andric if (!Container) 12570b57cec5SDimitry Andric return; 12580b57cec5SDimitry Andric 12590b57cec5SDimitry Andric // In categories look for overridden methods from protocols. A method from 12600b57cec5SDimitry Andric // category is not "overridden" since it is considered as the "same" method 12610b57cec5SDimitry Andric // (same USR) as the one from the interface. 12620b57cec5SDimitry Andric if (const auto *Category = dyn_cast<ObjCCategoryDecl>(Container)) { 12630b57cec5SDimitry Andric // Check whether we have a matching method at this category but only if we 12640b57cec5SDimitry Andric // are at the super class level. 12650b57cec5SDimitry Andric if (MovedToSuper) 12660b57cec5SDimitry Andric if (ObjCMethodDecl * 12670b57cec5SDimitry Andric Overridden = Container->getMethod(Method->getSelector(), 12680b57cec5SDimitry Andric Method->isInstanceMethod(), 12690b57cec5SDimitry Andric /*AllowHidden=*/true)) 12700b57cec5SDimitry Andric if (Method != Overridden) { 12710b57cec5SDimitry Andric // We found an override at this category; there is no need to look 12720b57cec5SDimitry Andric // into its protocols. 12730b57cec5SDimitry Andric Methods.push_back(Overridden); 12740b57cec5SDimitry Andric return; 12750b57cec5SDimitry Andric } 12760b57cec5SDimitry Andric 12770b57cec5SDimitry Andric for (const auto *P : Category->protocols()) 12780b57cec5SDimitry Andric CollectOverriddenMethodsRecurse(P, Method, Methods, MovedToSuper); 12790b57cec5SDimitry Andric return; 12800b57cec5SDimitry Andric } 12810b57cec5SDimitry Andric 12820b57cec5SDimitry Andric // Check whether we have a matching method at this level. 12830b57cec5SDimitry Andric if (const ObjCMethodDecl * 12840b57cec5SDimitry Andric Overridden = Container->getMethod(Method->getSelector(), 12850b57cec5SDimitry Andric Method->isInstanceMethod(), 12860b57cec5SDimitry Andric /*AllowHidden=*/true)) 12870b57cec5SDimitry Andric if (Method != Overridden) { 12880b57cec5SDimitry Andric // We found an override at this level; there is no need to look 12890b57cec5SDimitry Andric // into other protocols or categories. 12900b57cec5SDimitry Andric Methods.push_back(Overridden); 12910b57cec5SDimitry Andric return; 12920b57cec5SDimitry Andric } 12930b57cec5SDimitry Andric 12940b57cec5SDimitry Andric if (const auto *Protocol = dyn_cast<ObjCProtocolDecl>(Container)){ 12950b57cec5SDimitry Andric for (const auto *P : Protocol->protocols()) 12960b57cec5SDimitry Andric CollectOverriddenMethodsRecurse(P, Method, Methods, MovedToSuper); 12970b57cec5SDimitry Andric } 12980b57cec5SDimitry Andric 12990b57cec5SDimitry Andric if (const auto *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) { 13000b57cec5SDimitry Andric for (const auto *P : Interface->protocols()) 13010b57cec5SDimitry Andric CollectOverriddenMethodsRecurse(P, Method, Methods, MovedToSuper); 13020b57cec5SDimitry Andric 13030b57cec5SDimitry Andric for (const auto *Cat : Interface->known_categories()) 13040b57cec5SDimitry Andric CollectOverriddenMethodsRecurse(Cat, Method, Methods, MovedToSuper); 13050b57cec5SDimitry Andric 13060b57cec5SDimitry Andric if (const ObjCInterfaceDecl *Super = Interface->getSuperClass()) 13070b57cec5SDimitry Andric return CollectOverriddenMethodsRecurse(Super, Method, Methods, 13080b57cec5SDimitry Andric /*MovedToSuper=*/true); 13090b57cec5SDimitry Andric } 13100b57cec5SDimitry Andric } 13110b57cec5SDimitry Andric 13120b57cec5SDimitry Andric static inline void CollectOverriddenMethods(const ObjCContainerDecl *Container, 13130b57cec5SDimitry Andric const ObjCMethodDecl *Method, 13140b57cec5SDimitry Andric SmallVectorImpl<const ObjCMethodDecl *> &Methods) { 13150b57cec5SDimitry Andric CollectOverriddenMethodsRecurse(Container, Method, Methods, 13160b57cec5SDimitry Andric /*MovedToSuper=*/false); 13170b57cec5SDimitry Andric } 13180b57cec5SDimitry Andric 13190b57cec5SDimitry Andric static void collectOverriddenMethodsSlow(const ObjCMethodDecl *Method, 13200b57cec5SDimitry Andric SmallVectorImpl<const ObjCMethodDecl *> &overridden) { 13210b57cec5SDimitry Andric assert(Method->isOverriding()); 13220b57cec5SDimitry Andric 13230b57cec5SDimitry Andric if (const auto *ProtD = 13240b57cec5SDimitry Andric dyn_cast<ObjCProtocolDecl>(Method->getDeclContext())) { 13250b57cec5SDimitry Andric CollectOverriddenMethods(ProtD, Method, overridden); 13260b57cec5SDimitry Andric 13270b57cec5SDimitry Andric } else if (const auto *IMD = 13280b57cec5SDimitry Andric dyn_cast<ObjCImplDecl>(Method->getDeclContext())) { 13290b57cec5SDimitry Andric const ObjCInterfaceDecl *ID = IMD->getClassInterface(); 13300b57cec5SDimitry Andric if (!ID) 13310b57cec5SDimitry Andric return; 13320b57cec5SDimitry Andric // Start searching for overridden methods using the method from the 13330b57cec5SDimitry Andric // interface as starting point. 13340b57cec5SDimitry Andric if (const ObjCMethodDecl *IFaceMeth = ID->getMethod(Method->getSelector(), 13350b57cec5SDimitry Andric Method->isInstanceMethod(), 13360b57cec5SDimitry Andric /*AllowHidden=*/true)) 13370b57cec5SDimitry Andric Method = IFaceMeth; 13380b57cec5SDimitry Andric CollectOverriddenMethods(ID, Method, overridden); 13390b57cec5SDimitry Andric 13400b57cec5SDimitry Andric } else if (const auto *CatD = 13410b57cec5SDimitry Andric dyn_cast<ObjCCategoryDecl>(Method->getDeclContext())) { 13420b57cec5SDimitry Andric const ObjCInterfaceDecl *ID = CatD->getClassInterface(); 13430b57cec5SDimitry Andric if (!ID) 13440b57cec5SDimitry Andric return; 13450b57cec5SDimitry Andric // Start searching for overridden methods using the method from the 13460b57cec5SDimitry Andric // interface as starting point. 13470b57cec5SDimitry Andric if (const ObjCMethodDecl *IFaceMeth = ID->getMethod(Method->getSelector(), 13480b57cec5SDimitry Andric Method->isInstanceMethod(), 13490b57cec5SDimitry Andric /*AllowHidden=*/true)) 13500b57cec5SDimitry Andric Method = IFaceMeth; 13510b57cec5SDimitry Andric CollectOverriddenMethods(ID, Method, overridden); 13520b57cec5SDimitry Andric 13530b57cec5SDimitry Andric } else { 13540b57cec5SDimitry Andric CollectOverriddenMethods( 13550b57cec5SDimitry Andric dyn_cast_or_null<ObjCContainerDecl>(Method->getDeclContext()), 13560b57cec5SDimitry Andric Method, overridden); 13570b57cec5SDimitry Andric } 13580b57cec5SDimitry Andric } 13590b57cec5SDimitry Andric 13600b57cec5SDimitry Andric void ObjCMethodDecl::getOverriddenMethods( 13610b57cec5SDimitry Andric SmallVectorImpl<const ObjCMethodDecl *> &Overridden) const { 13620b57cec5SDimitry Andric const ObjCMethodDecl *Method = this; 13630b57cec5SDimitry Andric 13640b57cec5SDimitry Andric if (Method->isRedeclaration()) { 1365e8d8bef9SDimitry Andric Method = cast<ObjCContainerDecl>(Method->getDeclContext()) 1366e8d8bef9SDimitry Andric ->getMethod(Method->getSelector(), Method->isInstanceMethod(), 1367e8d8bef9SDimitry Andric /*AllowHidden=*/true); 13680b57cec5SDimitry Andric } 13690b57cec5SDimitry Andric 13700b57cec5SDimitry Andric if (Method->isOverriding()) { 13710b57cec5SDimitry Andric collectOverriddenMethodsSlow(Method, Overridden); 13720b57cec5SDimitry Andric assert(!Overridden.empty() && 13730b57cec5SDimitry Andric "ObjCMethodDecl's overriding bit is not as expected"); 13740b57cec5SDimitry Andric } 13750b57cec5SDimitry Andric } 13760b57cec5SDimitry Andric 13770b57cec5SDimitry Andric const ObjCPropertyDecl * 13780b57cec5SDimitry Andric ObjCMethodDecl::findPropertyDecl(bool CheckOverrides) const { 13790b57cec5SDimitry Andric Selector Sel = getSelector(); 13800b57cec5SDimitry Andric unsigned NumArgs = Sel.getNumArgs(); 13810b57cec5SDimitry Andric if (NumArgs > 1) 13820b57cec5SDimitry Andric return nullptr; 13830b57cec5SDimitry Andric 13840b57cec5SDimitry Andric if (isPropertyAccessor()) { 13850b57cec5SDimitry Andric const auto *Container = cast<ObjCContainerDecl>(getParent()); 1386480093f4SDimitry Andric // For accessor stubs, go back to the interface. 1387480093f4SDimitry Andric if (auto *ImplDecl = dyn_cast<ObjCImplDecl>(Container)) 1388480093f4SDimitry Andric if (isSynthesizedAccessorStub()) 1389480093f4SDimitry Andric Container = ImplDecl->getClassInterface(); 1390480093f4SDimitry Andric 13910b57cec5SDimitry Andric bool IsGetter = (NumArgs == 0); 13920b57cec5SDimitry Andric bool IsInstance = isInstanceMethod(); 13930b57cec5SDimitry Andric 13940b57cec5SDimitry Andric /// Local function that attempts to find a matching property within the 13950b57cec5SDimitry Andric /// given Objective-C container. 13960b57cec5SDimitry Andric auto findMatchingProperty = 13970b57cec5SDimitry Andric [&](const ObjCContainerDecl *Container) -> const ObjCPropertyDecl * { 13980b57cec5SDimitry Andric if (IsInstance) { 13990b57cec5SDimitry Andric for (const auto *I : Container->instance_properties()) { 14000b57cec5SDimitry Andric Selector NextSel = IsGetter ? I->getGetterName() 14010b57cec5SDimitry Andric : I->getSetterName(); 14020b57cec5SDimitry Andric if (NextSel == Sel) 14030b57cec5SDimitry Andric return I; 14040b57cec5SDimitry Andric } 14050b57cec5SDimitry Andric } else { 14060b57cec5SDimitry Andric for (const auto *I : Container->class_properties()) { 14070b57cec5SDimitry Andric Selector NextSel = IsGetter ? I->getGetterName() 14080b57cec5SDimitry Andric : I->getSetterName(); 14090b57cec5SDimitry Andric if (NextSel == Sel) 14100b57cec5SDimitry Andric return I; 14110b57cec5SDimitry Andric } 14120b57cec5SDimitry Andric } 14130b57cec5SDimitry Andric 14140b57cec5SDimitry Andric return nullptr; 14150b57cec5SDimitry Andric }; 14160b57cec5SDimitry Andric 14170b57cec5SDimitry Andric // Look in the container we were given. 14180b57cec5SDimitry Andric if (const auto *Found = findMatchingProperty(Container)) 14190b57cec5SDimitry Andric return Found; 14200b57cec5SDimitry Andric 14210b57cec5SDimitry Andric // If we're in a category or extension, look in the main class. 14220b57cec5SDimitry Andric const ObjCInterfaceDecl *ClassDecl = nullptr; 14230b57cec5SDimitry Andric if (const auto *Category = dyn_cast<ObjCCategoryDecl>(Container)) { 14240b57cec5SDimitry Andric ClassDecl = Category->getClassInterface(); 14250b57cec5SDimitry Andric if (const auto *Found = findMatchingProperty(ClassDecl)) 14260b57cec5SDimitry Andric return Found; 14270b57cec5SDimitry Andric } else { 14280b57cec5SDimitry Andric // Determine whether the container is a class. 14295ffd83dbSDimitry Andric ClassDecl = cast<ObjCInterfaceDecl>(Container); 14300b57cec5SDimitry Andric } 14315ffd83dbSDimitry Andric assert(ClassDecl && "Failed to find main class"); 14320b57cec5SDimitry Andric 14330b57cec5SDimitry Andric // If we have a class, check its visible extensions. 14340b57cec5SDimitry Andric for (const auto *Ext : ClassDecl->visible_extensions()) { 14350b57cec5SDimitry Andric if (Ext == Container) 14360b57cec5SDimitry Andric continue; 14370b57cec5SDimitry Andric if (const auto *Found = findMatchingProperty(Ext)) 14380b57cec5SDimitry Andric return Found; 14390b57cec5SDimitry Andric } 14400b57cec5SDimitry Andric 1441480093f4SDimitry Andric assert(isSynthesizedAccessorStub() && "expected an accessor stub"); 14425ffd83dbSDimitry Andric 1443480093f4SDimitry Andric for (const auto *Cat : ClassDecl->known_categories()) { 1444480093f4SDimitry Andric if (Cat == Container) 1445480093f4SDimitry Andric continue; 1446480093f4SDimitry Andric if (const auto *Found = findMatchingProperty(Cat)) 1447480093f4SDimitry Andric return Found; 1448480093f4SDimitry Andric } 1449480093f4SDimitry Andric 14500b57cec5SDimitry Andric llvm_unreachable("Marked as a property accessor but no property found!"); 14510b57cec5SDimitry Andric } 14520b57cec5SDimitry Andric 14530b57cec5SDimitry Andric if (!CheckOverrides) 14540b57cec5SDimitry Andric return nullptr; 14550b57cec5SDimitry Andric 14560b57cec5SDimitry Andric using OverridesTy = SmallVector<const ObjCMethodDecl *, 8>; 14570b57cec5SDimitry Andric 14580b57cec5SDimitry Andric OverridesTy Overrides; 14590b57cec5SDimitry Andric getOverriddenMethods(Overrides); 14600b57cec5SDimitry Andric for (const auto *Override : Overrides) 14610b57cec5SDimitry Andric if (const ObjCPropertyDecl *Prop = Override->findPropertyDecl(false)) 14620b57cec5SDimitry Andric return Prop; 14630b57cec5SDimitry Andric 14640b57cec5SDimitry Andric return nullptr; 14650b57cec5SDimitry Andric } 14660b57cec5SDimitry Andric 14670b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 14680b57cec5SDimitry Andric // ObjCTypeParamDecl 14690b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 14700b57cec5SDimitry Andric 14710b57cec5SDimitry Andric void ObjCTypeParamDecl::anchor() {} 14720b57cec5SDimitry Andric 14730b57cec5SDimitry Andric ObjCTypeParamDecl *ObjCTypeParamDecl::Create(ASTContext &ctx, DeclContext *dc, 14740b57cec5SDimitry Andric ObjCTypeParamVariance variance, 14750b57cec5SDimitry Andric SourceLocation varianceLoc, 14760b57cec5SDimitry Andric unsigned index, 14770b57cec5SDimitry Andric SourceLocation nameLoc, 14780b57cec5SDimitry Andric IdentifierInfo *name, 14790b57cec5SDimitry Andric SourceLocation colonLoc, 14800b57cec5SDimitry Andric TypeSourceInfo *boundInfo) { 14810b57cec5SDimitry Andric auto *TPDecl = 14820b57cec5SDimitry Andric new (ctx, dc) ObjCTypeParamDecl(ctx, dc, variance, varianceLoc, index, 14830b57cec5SDimitry Andric nameLoc, name, colonLoc, boundInfo); 14840b57cec5SDimitry Andric QualType TPType = ctx.getObjCTypeParamType(TPDecl, {}); 14850b57cec5SDimitry Andric TPDecl->setTypeForDecl(TPType.getTypePtr()); 14860b57cec5SDimitry Andric return TPDecl; 14870b57cec5SDimitry Andric } 14880b57cec5SDimitry Andric 14890b57cec5SDimitry Andric ObjCTypeParamDecl *ObjCTypeParamDecl::CreateDeserialized(ASTContext &ctx, 1490*0fca6ea1SDimitry Andric GlobalDeclID ID) { 14910b57cec5SDimitry Andric return new (ctx, ID) ObjCTypeParamDecl(ctx, nullptr, 14920b57cec5SDimitry Andric ObjCTypeParamVariance::Invariant, 14930b57cec5SDimitry Andric SourceLocation(), 0, SourceLocation(), 14940b57cec5SDimitry Andric nullptr, SourceLocation(), nullptr); 14950b57cec5SDimitry Andric } 14960b57cec5SDimitry Andric 14970b57cec5SDimitry Andric SourceRange ObjCTypeParamDecl::getSourceRange() const { 14980b57cec5SDimitry Andric SourceLocation startLoc = VarianceLoc; 14990b57cec5SDimitry Andric if (startLoc.isInvalid()) 15000b57cec5SDimitry Andric startLoc = getLocation(); 15010b57cec5SDimitry Andric 15020b57cec5SDimitry Andric if (hasExplicitBound()) { 15030b57cec5SDimitry Andric return SourceRange(startLoc, 15040b57cec5SDimitry Andric getTypeSourceInfo()->getTypeLoc().getEndLoc()); 15050b57cec5SDimitry Andric } 15060b57cec5SDimitry Andric 15070b57cec5SDimitry Andric return SourceRange(startLoc); 15080b57cec5SDimitry Andric } 15090b57cec5SDimitry Andric 15100b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 15110b57cec5SDimitry Andric // ObjCTypeParamList 15120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 15130b57cec5SDimitry Andric ObjCTypeParamList::ObjCTypeParamList(SourceLocation lAngleLoc, 15140b57cec5SDimitry Andric ArrayRef<ObjCTypeParamDecl *> typeParams, 15150b57cec5SDimitry Andric SourceLocation rAngleLoc) 1516e8d8bef9SDimitry Andric : Brackets(lAngleLoc, rAngleLoc), NumParams(typeParams.size()) { 15170b57cec5SDimitry Andric std::copy(typeParams.begin(), typeParams.end(), begin()); 15180b57cec5SDimitry Andric } 15190b57cec5SDimitry Andric 15200b57cec5SDimitry Andric ObjCTypeParamList *ObjCTypeParamList::create( 15210b57cec5SDimitry Andric ASTContext &ctx, 15220b57cec5SDimitry Andric SourceLocation lAngleLoc, 15230b57cec5SDimitry Andric ArrayRef<ObjCTypeParamDecl *> typeParams, 15240b57cec5SDimitry Andric SourceLocation rAngleLoc) { 15250b57cec5SDimitry Andric void *mem = 15260b57cec5SDimitry Andric ctx.Allocate(totalSizeToAlloc<ObjCTypeParamDecl *>(typeParams.size()), 15270b57cec5SDimitry Andric alignof(ObjCTypeParamList)); 15280b57cec5SDimitry Andric return new (mem) ObjCTypeParamList(lAngleLoc, typeParams, rAngleLoc); 15290b57cec5SDimitry Andric } 15300b57cec5SDimitry Andric 15310b57cec5SDimitry Andric void ObjCTypeParamList::gatherDefaultTypeArgs( 15320b57cec5SDimitry Andric SmallVectorImpl<QualType> &typeArgs) const { 15330b57cec5SDimitry Andric typeArgs.reserve(size()); 1534bdd1243dSDimitry Andric for (auto *typeParam : *this) 15350b57cec5SDimitry Andric typeArgs.push_back(typeParam->getUnderlyingType()); 15360b57cec5SDimitry Andric } 15370b57cec5SDimitry Andric 15380b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 15390b57cec5SDimitry Andric // ObjCInterfaceDecl 15400b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 15410b57cec5SDimitry Andric 1542*0fca6ea1SDimitry Andric ObjCInterfaceDecl *ObjCInterfaceDecl::Create( 1543*0fca6ea1SDimitry Andric const ASTContext &C, DeclContext *DC, SourceLocation atLoc, 1544*0fca6ea1SDimitry Andric const IdentifierInfo *Id, ObjCTypeParamList *typeParamList, 1545*0fca6ea1SDimitry Andric ObjCInterfaceDecl *PrevDecl, SourceLocation ClassLoc, bool isInternal) { 15460b57cec5SDimitry Andric auto *Result = new (C, DC) 15470b57cec5SDimitry Andric ObjCInterfaceDecl(C, DC, atLoc, Id, typeParamList, ClassLoc, PrevDecl, 15480b57cec5SDimitry Andric isInternal); 15490b57cec5SDimitry Andric Result->Data.setInt(!C.getLangOpts().Modules); 15500b57cec5SDimitry Andric C.getObjCInterfaceType(Result, PrevDecl); 15510b57cec5SDimitry Andric return Result; 15520b57cec5SDimitry Andric } 15530b57cec5SDimitry Andric 15540b57cec5SDimitry Andric ObjCInterfaceDecl *ObjCInterfaceDecl::CreateDeserialized(const ASTContext &C, 1555*0fca6ea1SDimitry Andric GlobalDeclID ID) { 15560b57cec5SDimitry Andric auto *Result = new (C, ID) 15570b57cec5SDimitry Andric ObjCInterfaceDecl(C, nullptr, SourceLocation(), nullptr, nullptr, 15580b57cec5SDimitry Andric SourceLocation(), nullptr, false); 15590b57cec5SDimitry Andric Result->Data.setInt(!C.getLangOpts().Modules); 15600b57cec5SDimitry Andric return Result; 15610b57cec5SDimitry Andric } 15620b57cec5SDimitry Andric 1563*0fca6ea1SDimitry Andric ObjCInterfaceDecl::ObjCInterfaceDecl( 1564*0fca6ea1SDimitry Andric const ASTContext &C, DeclContext *DC, SourceLocation AtLoc, 1565*0fca6ea1SDimitry Andric const IdentifierInfo *Id, ObjCTypeParamList *typeParamList, 1566*0fca6ea1SDimitry Andric SourceLocation CLoc, ObjCInterfaceDecl *PrevDecl, bool IsInternal) 15670b57cec5SDimitry Andric : ObjCContainerDecl(ObjCInterface, DC, Id, CLoc, AtLoc), 15680b57cec5SDimitry Andric redeclarable_base(C) { 15690b57cec5SDimitry Andric setPreviousDecl(PrevDecl); 15700b57cec5SDimitry Andric 15710b57cec5SDimitry Andric // Copy the 'data' pointer over. 15720b57cec5SDimitry Andric if (PrevDecl) 15730b57cec5SDimitry Andric Data = PrevDecl->Data; 15740b57cec5SDimitry Andric 15750b57cec5SDimitry Andric setImplicit(IsInternal); 15760b57cec5SDimitry Andric 15770b57cec5SDimitry Andric setTypeParamList(typeParamList); 15780b57cec5SDimitry Andric } 15790b57cec5SDimitry Andric 15800b57cec5SDimitry Andric void ObjCInterfaceDecl::LoadExternalDefinition() const { 15810b57cec5SDimitry Andric assert(data().ExternallyCompleted && "Class is not externally completed"); 15820b57cec5SDimitry Andric data().ExternallyCompleted = false; 15830b57cec5SDimitry Andric getASTContext().getExternalSource()->CompleteType( 15840b57cec5SDimitry Andric const_cast<ObjCInterfaceDecl *>(this)); 15850b57cec5SDimitry Andric } 15860b57cec5SDimitry Andric 15870b57cec5SDimitry Andric void ObjCInterfaceDecl::setExternallyCompleted() { 15880b57cec5SDimitry Andric assert(getASTContext().getExternalSource() && 15890b57cec5SDimitry Andric "Class can't be externally completed without an external source"); 15900b57cec5SDimitry Andric assert(hasDefinition() && 15910b57cec5SDimitry Andric "Forward declarations can't be externally completed"); 15920b57cec5SDimitry Andric data().ExternallyCompleted = true; 15930b57cec5SDimitry Andric } 15940b57cec5SDimitry Andric 15950b57cec5SDimitry Andric void ObjCInterfaceDecl::setHasDesignatedInitializers() { 15960b57cec5SDimitry Andric // Check for a complete definition and recover if not so. 15970b57cec5SDimitry Andric if (!isThisDeclarationADefinition()) 15980b57cec5SDimitry Andric return; 15990b57cec5SDimitry Andric data().HasDesignatedInitializers = true; 16000b57cec5SDimitry Andric } 16010b57cec5SDimitry Andric 16020b57cec5SDimitry Andric bool ObjCInterfaceDecl::hasDesignatedInitializers() const { 16030b57cec5SDimitry Andric // Check for a complete definition and recover if not so. 16040b57cec5SDimitry Andric if (!isThisDeclarationADefinition()) 16050b57cec5SDimitry Andric return false; 16060b57cec5SDimitry Andric if (data().ExternallyCompleted) 16070b57cec5SDimitry Andric LoadExternalDefinition(); 16080b57cec5SDimitry Andric 16090b57cec5SDimitry Andric return data().HasDesignatedInitializers; 16100b57cec5SDimitry Andric } 16110b57cec5SDimitry Andric 16120b57cec5SDimitry Andric StringRef 16130b57cec5SDimitry Andric ObjCInterfaceDecl::getObjCRuntimeNameAsString() const { 16140b57cec5SDimitry Andric if (const auto *ObjCRTName = getAttr<ObjCRuntimeNameAttr>()) 16150b57cec5SDimitry Andric return ObjCRTName->getMetadataName(); 16160b57cec5SDimitry Andric 16170b57cec5SDimitry Andric return getName(); 16180b57cec5SDimitry Andric } 16190b57cec5SDimitry Andric 16200b57cec5SDimitry Andric StringRef 16210b57cec5SDimitry Andric ObjCImplementationDecl::getObjCRuntimeNameAsString() const { 16220b57cec5SDimitry Andric if (ObjCInterfaceDecl *ID = 16230b57cec5SDimitry Andric const_cast<ObjCImplementationDecl*>(this)->getClassInterface()) 16240b57cec5SDimitry Andric return ID->getObjCRuntimeNameAsString(); 16250b57cec5SDimitry Andric 16260b57cec5SDimitry Andric return getName(); 16270b57cec5SDimitry Andric } 16280b57cec5SDimitry Andric 16290b57cec5SDimitry Andric ObjCImplementationDecl *ObjCInterfaceDecl::getImplementation() const { 16300b57cec5SDimitry Andric if (const ObjCInterfaceDecl *Def = getDefinition()) { 16310b57cec5SDimitry Andric if (data().ExternallyCompleted) 16320b57cec5SDimitry Andric LoadExternalDefinition(); 16330b57cec5SDimitry Andric 16340b57cec5SDimitry Andric return getASTContext().getObjCImplementation( 16350b57cec5SDimitry Andric const_cast<ObjCInterfaceDecl*>(Def)); 16360b57cec5SDimitry Andric } 16370b57cec5SDimitry Andric 16380b57cec5SDimitry Andric // FIXME: Should make sure no callers ever do this. 16390b57cec5SDimitry Andric return nullptr; 16400b57cec5SDimitry Andric } 16410b57cec5SDimitry Andric 16420b57cec5SDimitry Andric void ObjCInterfaceDecl::setImplementation(ObjCImplementationDecl *ImplD) { 16430b57cec5SDimitry Andric getASTContext().setObjCImplementation(getDefinition(), ImplD); 16440b57cec5SDimitry Andric } 16450b57cec5SDimitry Andric 16460b57cec5SDimitry Andric namespace { 16470b57cec5SDimitry Andric 16480b57cec5SDimitry Andric struct SynthesizeIvarChunk { 16490b57cec5SDimitry Andric uint64_t Size; 16500b57cec5SDimitry Andric ObjCIvarDecl *Ivar; 16510b57cec5SDimitry Andric 16520b57cec5SDimitry Andric SynthesizeIvarChunk(uint64_t size, ObjCIvarDecl *ivar) 16530b57cec5SDimitry Andric : Size(size), Ivar(ivar) {} 16540b57cec5SDimitry Andric }; 16550b57cec5SDimitry Andric 16560b57cec5SDimitry Andric bool operator<(const SynthesizeIvarChunk & LHS, 16570b57cec5SDimitry Andric const SynthesizeIvarChunk &RHS) { 16580b57cec5SDimitry Andric return LHS.Size < RHS.Size; 16590b57cec5SDimitry Andric } 16600b57cec5SDimitry Andric 16610b57cec5SDimitry Andric } // namespace 16620b57cec5SDimitry Andric 16630b57cec5SDimitry Andric /// all_declared_ivar_begin - return first ivar declared in this class, 16640b57cec5SDimitry Andric /// its extensions and its implementation. Lazily build the list on first 16650b57cec5SDimitry Andric /// access. 16660b57cec5SDimitry Andric /// 16670b57cec5SDimitry Andric /// Caveat: The list returned by this method reflects the current 16680b57cec5SDimitry Andric /// state of the parser. The cache will be updated for every ivar 16690b57cec5SDimitry Andric /// added by an extension or the implementation when they are 16700b57cec5SDimitry Andric /// encountered. 16710b57cec5SDimitry Andric /// See also ObjCIvarDecl::Create(). 16720b57cec5SDimitry Andric ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() { 16730b57cec5SDimitry Andric // FIXME: Should make sure no callers ever do this. 16740b57cec5SDimitry Andric if (!hasDefinition()) 16750b57cec5SDimitry Andric return nullptr; 16760b57cec5SDimitry Andric 16770b57cec5SDimitry Andric ObjCIvarDecl *curIvar = nullptr; 16780b57cec5SDimitry Andric if (!data().IvarList) { 167981ad6265SDimitry Andric // Force ivar deserialization upfront, before building IvarList. 168081ad6265SDimitry Andric (void)ivar_empty(); 168181ad6265SDimitry Andric for (const auto *Ext : known_extensions()) { 168281ad6265SDimitry Andric (void)Ext->ivar_empty(); 168381ad6265SDimitry Andric } 16840b57cec5SDimitry Andric if (!ivar_empty()) { 16850b57cec5SDimitry Andric ObjCInterfaceDecl::ivar_iterator I = ivar_begin(), E = ivar_end(); 16860b57cec5SDimitry Andric data().IvarList = *I; ++I; 16870b57cec5SDimitry Andric for (curIvar = data().IvarList; I != E; curIvar = *I, ++I) 16880b57cec5SDimitry Andric curIvar->setNextIvar(*I); 16890b57cec5SDimitry Andric } 16900b57cec5SDimitry Andric 16910b57cec5SDimitry Andric for (const auto *Ext : known_extensions()) { 16920b57cec5SDimitry Andric if (!Ext->ivar_empty()) { 16930b57cec5SDimitry Andric ObjCCategoryDecl::ivar_iterator 16940b57cec5SDimitry Andric I = Ext->ivar_begin(), 16950b57cec5SDimitry Andric E = Ext->ivar_end(); 16960b57cec5SDimitry Andric if (!data().IvarList) { 16970b57cec5SDimitry Andric data().IvarList = *I; ++I; 16980b57cec5SDimitry Andric curIvar = data().IvarList; 16990b57cec5SDimitry Andric } 17000b57cec5SDimitry Andric for ( ;I != E; curIvar = *I, ++I) 17010b57cec5SDimitry Andric curIvar->setNextIvar(*I); 17020b57cec5SDimitry Andric } 17030b57cec5SDimitry Andric } 17040b57cec5SDimitry Andric data().IvarListMissingImplementation = true; 17050b57cec5SDimitry Andric } 17060b57cec5SDimitry Andric 17070b57cec5SDimitry Andric // cached and complete! 17080b57cec5SDimitry Andric if (!data().IvarListMissingImplementation) 17090b57cec5SDimitry Andric return data().IvarList; 17100b57cec5SDimitry Andric 17110b57cec5SDimitry Andric if (ObjCImplementationDecl *ImplDecl = getImplementation()) { 17120b57cec5SDimitry Andric data().IvarListMissingImplementation = false; 17130b57cec5SDimitry Andric if (!ImplDecl->ivar_empty()) { 17140b57cec5SDimitry Andric SmallVector<SynthesizeIvarChunk, 16> layout; 17150b57cec5SDimitry Andric for (auto *IV : ImplDecl->ivars()) { 17160b57cec5SDimitry Andric if (IV->getSynthesize() && !IV->isInvalidDecl()) { 17170b57cec5SDimitry Andric layout.push_back(SynthesizeIvarChunk( 17180b57cec5SDimitry Andric IV->getASTContext().getTypeSize(IV->getType()), IV)); 17190b57cec5SDimitry Andric continue; 17200b57cec5SDimitry Andric } 17210b57cec5SDimitry Andric if (!data().IvarList) 17220b57cec5SDimitry Andric data().IvarList = IV; 17230b57cec5SDimitry Andric else 17240b57cec5SDimitry Andric curIvar->setNextIvar(IV); 17250b57cec5SDimitry Andric curIvar = IV; 17260b57cec5SDimitry Andric } 17270b57cec5SDimitry Andric 17280b57cec5SDimitry Andric if (!layout.empty()) { 17290b57cec5SDimitry Andric // Order synthesized ivars by their size. 17300b57cec5SDimitry Andric llvm::stable_sort(layout); 17310b57cec5SDimitry Andric unsigned Ix = 0, EIx = layout.size(); 17320b57cec5SDimitry Andric if (!data().IvarList) { 17330b57cec5SDimitry Andric data().IvarList = layout[0].Ivar; Ix++; 17340b57cec5SDimitry Andric curIvar = data().IvarList; 17350b57cec5SDimitry Andric } 17360b57cec5SDimitry Andric for ( ; Ix != EIx; curIvar = layout[Ix].Ivar, Ix++) 17370b57cec5SDimitry Andric curIvar->setNextIvar(layout[Ix].Ivar); 17380b57cec5SDimitry Andric } 17390b57cec5SDimitry Andric } 17400b57cec5SDimitry Andric } 17410b57cec5SDimitry Andric return data().IvarList; 17420b57cec5SDimitry Andric } 17430b57cec5SDimitry Andric 17440b57cec5SDimitry Andric /// FindCategoryDeclaration - Finds category declaration in the list of 17450b57cec5SDimitry Andric /// categories for this class and returns it. Name of the category is passed 17460b57cec5SDimitry Andric /// in 'CategoryId'. If category not found, return 0; 17470b57cec5SDimitry Andric /// 1748*0fca6ea1SDimitry Andric ObjCCategoryDecl *ObjCInterfaceDecl::FindCategoryDeclaration( 1749*0fca6ea1SDimitry Andric const IdentifierInfo *CategoryId) const { 17500b57cec5SDimitry Andric // FIXME: Should make sure no callers ever do this. 17510b57cec5SDimitry Andric if (!hasDefinition()) 17520b57cec5SDimitry Andric return nullptr; 17530b57cec5SDimitry Andric 17540b57cec5SDimitry Andric if (data().ExternallyCompleted) 17550b57cec5SDimitry Andric LoadExternalDefinition(); 17560b57cec5SDimitry Andric 17570b57cec5SDimitry Andric for (auto *Cat : visible_categories()) 17580b57cec5SDimitry Andric if (Cat->getIdentifier() == CategoryId) 17590b57cec5SDimitry Andric return Cat; 17600b57cec5SDimitry Andric 17610b57cec5SDimitry Andric return nullptr; 17620b57cec5SDimitry Andric } 17630b57cec5SDimitry Andric 17640b57cec5SDimitry Andric ObjCMethodDecl * 17650b57cec5SDimitry Andric ObjCInterfaceDecl::getCategoryInstanceMethod(Selector Sel) const { 17660b57cec5SDimitry Andric for (const auto *Cat : visible_categories()) { 17670b57cec5SDimitry Andric if (ObjCCategoryImplDecl *Impl = Cat->getImplementation()) 17680b57cec5SDimitry Andric if (ObjCMethodDecl *MD = Impl->getInstanceMethod(Sel)) 17690b57cec5SDimitry Andric return MD; 17700b57cec5SDimitry Andric } 17710b57cec5SDimitry Andric 17720b57cec5SDimitry Andric return nullptr; 17730b57cec5SDimitry Andric } 17740b57cec5SDimitry Andric 17750b57cec5SDimitry Andric ObjCMethodDecl *ObjCInterfaceDecl::getCategoryClassMethod(Selector Sel) const { 17760b57cec5SDimitry Andric for (const auto *Cat : visible_categories()) { 17770b57cec5SDimitry Andric if (ObjCCategoryImplDecl *Impl = Cat->getImplementation()) 17780b57cec5SDimitry Andric if (ObjCMethodDecl *MD = Impl->getClassMethod(Sel)) 17790b57cec5SDimitry Andric return MD; 17800b57cec5SDimitry Andric } 17810b57cec5SDimitry Andric 17820b57cec5SDimitry Andric return nullptr; 17830b57cec5SDimitry Andric } 17840b57cec5SDimitry Andric 17850b57cec5SDimitry Andric /// ClassImplementsProtocol - Checks that 'lProto' protocol 17860b57cec5SDimitry Andric /// has been implemented in IDecl class, its super class or categories (if 17870b57cec5SDimitry Andric /// lookupCategory is true). 17880b57cec5SDimitry Andric bool ObjCInterfaceDecl::ClassImplementsProtocol(ObjCProtocolDecl *lProto, 17890b57cec5SDimitry Andric bool lookupCategory, 17900b57cec5SDimitry Andric bool RHSIsQualifiedID) { 17910b57cec5SDimitry Andric if (!hasDefinition()) 17920b57cec5SDimitry Andric return false; 17930b57cec5SDimitry Andric 17940b57cec5SDimitry Andric ObjCInterfaceDecl *IDecl = this; 17950b57cec5SDimitry Andric // 1st, look up the class. 17960b57cec5SDimitry Andric for (auto *PI : IDecl->protocols()){ 17970b57cec5SDimitry Andric if (getASTContext().ProtocolCompatibleWithProtocol(lProto, PI)) 17980b57cec5SDimitry Andric return true; 17990b57cec5SDimitry Andric // This is dubious and is added to be compatible with gcc. In gcc, it is 18000b57cec5SDimitry Andric // also allowed assigning a protocol-qualified 'id' type to a LHS object 18010b57cec5SDimitry Andric // when protocol in qualified LHS is in list of protocols in the rhs 'id' 18020b57cec5SDimitry Andric // object. This IMO, should be a bug. 18030b57cec5SDimitry Andric // FIXME: Treat this as an extension, and flag this as an error when GCC 18040b57cec5SDimitry Andric // extensions are not enabled. 18050b57cec5SDimitry Andric if (RHSIsQualifiedID && 18060b57cec5SDimitry Andric getASTContext().ProtocolCompatibleWithProtocol(PI, lProto)) 18070b57cec5SDimitry Andric return true; 18080b57cec5SDimitry Andric } 18090b57cec5SDimitry Andric 18100b57cec5SDimitry Andric // 2nd, look up the category. 18110b57cec5SDimitry Andric if (lookupCategory) 18120b57cec5SDimitry Andric for (const auto *Cat : visible_categories()) { 18130b57cec5SDimitry Andric for (auto *PI : Cat->protocols()) 18140b57cec5SDimitry Andric if (getASTContext().ProtocolCompatibleWithProtocol(lProto, PI)) 18150b57cec5SDimitry Andric return true; 18160b57cec5SDimitry Andric } 18170b57cec5SDimitry Andric 18180b57cec5SDimitry Andric // 3rd, look up the super class(s) 18190b57cec5SDimitry Andric if (IDecl->getSuperClass()) 18200b57cec5SDimitry Andric return 18210b57cec5SDimitry Andric IDecl->getSuperClass()->ClassImplementsProtocol(lProto, lookupCategory, 18220b57cec5SDimitry Andric RHSIsQualifiedID); 18230b57cec5SDimitry Andric 18240b57cec5SDimitry Andric return false; 18250b57cec5SDimitry Andric } 18260b57cec5SDimitry Andric 18270b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 18280b57cec5SDimitry Andric // ObjCIvarDecl 18290b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 18300b57cec5SDimitry Andric 18310b57cec5SDimitry Andric void ObjCIvarDecl::anchor() {} 18320b57cec5SDimitry Andric 18330b57cec5SDimitry Andric ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC, 18340b57cec5SDimitry Andric SourceLocation StartLoc, 1835*0fca6ea1SDimitry Andric SourceLocation IdLoc, 1836*0fca6ea1SDimitry Andric const IdentifierInfo *Id, QualType T, 1837*0fca6ea1SDimitry Andric TypeSourceInfo *TInfo, AccessControl ac, 1838*0fca6ea1SDimitry Andric Expr *BW, bool synthesized) { 18390b57cec5SDimitry Andric if (DC) { 18400b57cec5SDimitry Andric // Ivar's can only appear in interfaces, implementations (via synthesized 18410b57cec5SDimitry Andric // properties), and class extensions (via direct declaration, or synthesized 18420b57cec5SDimitry Andric // properties). 18430b57cec5SDimitry Andric // 18440b57cec5SDimitry Andric // FIXME: This should really be asserting this: 18450b57cec5SDimitry Andric // (isa<ObjCCategoryDecl>(DC) && 18460b57cec5SDimitry Andric // cast<ObjCCategoryDecl>(DC)->IsClassExtension())) 18470b57cec5SDimitry Andric // but unfortunately we sometimes place ivars into non-class extension 18480b57cec5SDimitry Andric // categories on error. This breaks an AST invariant, and should not be 18490b57cec5SDimitry Andric // fixed. 18500b57cec5SDimitry Andric assert((isa<ObjCInterfaceDecl>(DC) || isa<ObjCImplementationDecl>(DC) || 18510b57cec5SDimitry Andric isa<ObjCCategoryDecl>(DC)) && 18520b57cec5SDimitry Andric "Invalid ivar decl context!"); 18530b57cec5SDimitry Andric // Once a new ivar is created in any of class/class-extension/implementation 18540b57cec5SDimitry Andric // decl contexts, the previously built IvarList must be rebuilt. 18550b57cec5SDimitry Andric auto *ID = dyn_cast<ObjCInterfaceDecl>(DC); 18560b57cec5SDimitry Andric if (!ID) { 18570b57cec5SDimitry Andric if (auto *IM = dyn_cast<ObjCImplementationDecl>(DC)) 18580b57cec5SDimitry Andric ID = IM->getClassInterface(); 18590b57cec5SDimitry Andric else 18600b57cec5SDimitry Andric ID = cast<ObjCCategoryDecl>(DC)->getClassInterface(); 18610b57cec5SDimitry Andric } 18620b57cec5SDimitry Andric ID->setIvarList(nullptr); 18630b57cec5SDimitry Andric } 18640b57cec5SDimitry Andric 18650b57cec5SDimitry Andric return new (C, DC) ObjCIvarDecl(DC, StartLoc, IdLoc, Id, T, TInfo, ac, BW, 18660b57cec5SDimitry Andric synthesized); 18670b57cec5SDimitry Andric } 18680b57cec5SDimitry Andric 1869*0fca6ea1SDimitry Andric ObjCIvarDecl *ObjCIvarDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) { 18700b57cec5SDimitry Andric return new (C, ID) ObjCIvarDecl(nullptr, SourceLocation(), SourceLocation(), 18710b57cec5SDimitry Andric nullptr, QualType(), nullptr, 18720b57cec5SDimitry Andric ObjCIvarDecl::None, nullptr, false); 18730b57cec5SDimitry Andric } 18740b57cec5SDimitry Andric 187581ad6265SDimitry Andric ObjCInterfaceDecl *ObjCIvarDecl::getContainingInterface() { 187681ad6265SDimitry Andric auto *DC = cast<ObjCContainerDecl>(getDeclContext()); 18770b57cec5SDimitry Andric 18780b57cec5SDimitry Andric switch (DC->getKind()) { 18790b57cec5SDimitry Andric default: 18800b57cec5SDimitry Andric case ObjCCategoryImpl: 18810b57cec5SDimitry Andric case ObjCProtocol: 18820b57cec5SDimitry Andric llvm_unreachable("invalid ivar container!"); 18830b57cec5SDimitry Andric 18840b57cec5SDimitry Andric // Ivars can only appear in class extension categories. 18850b57cec5SDimitry Andric case ObjCCategory: { 188681ad6265SDimitry Andric auto *CD = cast<ObjCCategoryDecl>(DC); 18870b57cec5SDimitry Andric assert(CD->IsClassExtension() && "invalid container for ivar!"); 18880b57cec5SDimitry Andric return CD->getClassInterface(); 18890b57cec5SDimitry Andric } 18900b57cec5SDimitry Andric 18910b57cec5SDimitry Andric case ObjCImplementation: 18920b57cec5SDimitry Andric return cast<ObjCImplementationDecl>(DC)->getClassInterface(); 18930b57cec5SDimitry Andric 18940b57cec5SDimitry Andric case ObjCInterface: 18950b57cec5SDimitry Andric return cast<ObjCInterfaceDecl>(DC); 18960b57cec5SDimitry Andric } 18970b57cec5SDimitry Andric } 18980b57cec5SDimitry Andric 18990b57cec5SDimitry Andric QualType ObjCIvarDecl::getUsageType(QualType objectType) const { 19000b57cec5SDimitry Andric return getType().substObjCMemberType(objectType, getDeclContext(), 19010b57cec5SDimitry Andric ObjCSubstitutionContext::Property); 19020b57cec5SDimitry Andric } 19030b57cec5SDimitry Andric 19040b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 19050b57cec5SDimitry Andric // ObjCAtDefsFieldDecl 19060b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 19070b57cec5SDimitry Andric 19080b57cec5SDimitry Andric void ObjCAtDefsFieldDecl::anchor() {} 19090b57cec5SDimitry Andric 19100b57cec5SDimitry Andric ObjCAtDefsFieldDecl 19110b57cec5SDimitry Andric *ObjCAtDefsFieldDecl::Create(ASTContext &C, DeclContext *DC, 19120b57cec5SDimitry Andric SourceLocation StartLoc, SourceLocation IdLoc, 19130b57cec5SDimitry Andric IdentifierInfo *Id, QualType T, Expr *BW) { 19140b57cec5SDimitry Andric return new (C, DC) ObjCAtDefsFieldDecl(DC, StartLoc, IdLoc, Id, T, BW); 19150b57cec5SDimitry Andric } 19160b57cec5SDimitry Andric 19170b57cec5SDimitry Andric ObjCAtDefsFieldDecl *ObjCAtDefsFieldDecl::CreateDeserialized(ASTContext &C, 1918*0fca6ea1SDimitry Andric GlobalDeclID ID) { 19190b57cec5SDimitry Andric return new (C, ID) ObjCAtDefsFieldDecl(nullptr, SourceLocation(), 19200b57cec5SDimitry Andric SourceLocation(), nullptr, QualType(), 19210b57cec5SDimitry Andric nullptr); 19220b57cec5SDimitry Andric } 19230b57cec5SDimitry Andric 19240b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 19250b57cec5SDimitry Andric // ObjCProtocolDecl 19260b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 19270b57cec5SDimitry Andric 19280b57cec5SDimitry Andric void ObjCProtocolDecl::anchor() {} 19290b57cec5SDimitry Andric 19300b57cec5SDimitry Andric ObjCProtocolDecl::ObjCProtocolDecl(ASTContext &C, DeclContext *DC, 19310b57cec5SDimitry Andric IdentifierInfo *Id, SourceLocation nameLoc, 19320b57cec5SDimitry Andric SourceLocation atStartLoc, 19330b57cec5SDimitry Andric ObjCProtocolDecl *PrevDecl) 19340b57cec5SDimitry Andric : ObjCContainerDecl(ObjCProtocol, DC, Id, nameLoc, atStartLoc), 19350b57cec5SDimitry Andric redeclarable_base(C) { 19360b57cec5SDimitry Andric setPreviousDecl(PrevDecl); 19370b57cec5SDimitry Andric if (PrevDecl) 19380b57cec5SDimitry Andric Data = PrevDecl->Data; 19390b57cec5SDimitry Andric } 19400b57cec5SDimitry Andric 19410b57cec5SDimitry Andric ObjCProtocolDecl *ObjCProtocolDecl::Create(ASTContext &C, DeclContext *DC, 19420b57cec5SDimitry Andric IdentifierInfo *Id, 19430b57cec5SDimitry Andric SourceLocation nameLoc, 19440b57cec5SDimitry Andric SourceLocation atStartLoc, 19450b57cec5SDimitry Andric ObjCProtocolDecl *PrevDecl) { 19460b57cec5SDimitry Andric auto *Result = 19470b57cec5SDimitry Andric new (C, DC) ObjCProtocolDecl(C, DC, Id, nameLoc, atStartLoc, PrevDecl); 19480b57cec5SDimitry Andric Result->Data.setInt(!C.getLangOpts().Modules); 19490b57cec5SDimitry Andric return Result; 19500b57cec5SDimitry Andric } 19510b57cec5SDimitry Andric 19520b57cec5SDimitry Andric ObjCProtocolDecl *ObjCProtocolDecl::CreateDeserialized(ASTContext &C, 1953*0fca6ea1SDimitry Andric GlobalDeclID ID) { 19540b57cec5SDimitry Andric ObjCProtocolDecl *Result = 19550b57cec5SDimitry Andric new (C, ID) ObjCProtocolDecl(C, nullptr, nullptr, SourceLocation(), 19560b57cec5SDimitry Andric SourceLocation(), nullptr); 19570b57cec5SDimitry Andric Result->Data.setInt(!C.getLangOpts().Modules); 19580b57cec5SDimitry Andric return Result; 19590b57cec5SDimitry Andric } 19600b57cec5SDimitry Andric 1961e8d8bef9SDimitry Andric bool ObjCProtocolDecl::isNonRuntimeProtocol() const { 1962e8d8bef9SDimitry Andric return hasAttr<ObjCNonRuntimeProtocolAttr>(); 1963e8d8bef9SDimitry Andric } 1964e8d8bef9SDimitry Andric 1965e8d8bef9SDimitry Andric void ObjCProtocolDecl::getImpliedProtocols( 1966e8d8bef9SDimitry Andric llvm::DenseSet<const ObjCProtocolDecl *> &IPs) const { 1967e8d8bef9SDimitry Andric std::queue<const ObjCProtocolDecl *> WorkQueue; 1968e8d8bef9SDimitry Andric WorkQueue.push(this); 1969e8d8bef9SDimitry Andric 1970e8d8bef9SDimitry Andric while (!WorkQueue.empty()) { 1971e8d8bef9SDimitry Andric const auto *PD = WorkQueue.front(); 1972e8d8bef9SDimitry Andric WorkQueue.pop(); 1973e8d8bef9SDimitry Andric for (const auto *Parent : PD->protocols()) { 1974e8d8bef9SDimitry Andric const auto *Can = Parent->getCanonicalDecl(); 1975e8d8bef9SDimitry Andric auto Result = IPs.insert(Can); 1976e8d8bef9SDimitry Andric if (Result.second) 1977e8d8bef9SDimitry Andric WorkQueue.push(Parent); 1978e8d8bef9SDimitry Andric } 1979e8d8bef9SDimitry Andric } 1980e8d8bef9SDimitry Andric } 1981e8d8bef9SDimitry Andric 19820b57cec5SDimitry Andric ObjCProtocolDecl *ObjCProtocolDecl::lookupProtocolNamed(IdentifierInfo *Name) { 19830b57cec5SDimitry Andric ObjCProtocolDecl *PDecl = this; 19840b57cec5SDimitry Andric 19850b57cec5SDimitry Andric if (Name == getIdentifier()) 19860b57cec5SDimitry Andric return PDecl; 19870b57cec5SDimitry Andric 19880b57cec5SDimitry Andric for (auto *I : protocols()) 19890b57cec5SDimitry Andric if ((PDecl = I->lookupProtocolNamed(Name))) 19900b57cec5SDimitry Andric return PDecl; 19910b57cec5SDimitry Andric 19920b57cec5SDimitry Andric return nullptr; 19930b57cec5SDimitry Andric } 19940b57cec5SDimitry Andric 19950b57cec5SDimitry Andric // lookupMethod - Lookup a instance/class method in the protocol and protocols 19960b57cec5SDimitry Andric // it inherited. 19970b57cec5SDimitry Andric ObjCMethodDecl *ObjCProtocolDecl::lookupMethod(Selector Sel, 19980b57cec5SDimitry Andric bool isInstance) const { 19990b57cec5SDimitry Andric ObjCMethodDecl *MethodDecl = nullptr; 20000b57cec5SDimitry Andric 20010b57cec5SDimitry Andric // If there is no definition or the definition is hidden, we don't find 20020b57cec5SDimitry Andric // anything. 20030b57cec5SDimitry Andric const ObjCProtocolDecl *Def = getDefinition(); 20045ffd83dbSDimitry Andric if (!Def || !Def->isUnconditionallyVisible()) 20050b57cec5SDimitry Andric return nullptr; 20060b57cec5SDimitry Andric 20070b57cec5SDimitry Andric if ((MethodDecl = getMethod(Sel, isInstance))) 20080b57cec5SDimitry Andric return MethodDecl; 20090b57cec5SDimitry Andric 20100b57cec5SDimitry Andric for (const auto *I : protocols()) 20110b57cec5SDimitry Andric if ((MethodDecl = I->lookupMethod(Sel, isInstance))) 20120b57cec5SDimitry Andric return MethodDecl; 20130b57cec5SDimitry Andric return nullptr; 20140b57cec5SDimitry Andric } 20150b57cec5SDimitry Andric 20160b57cec5SDimitry Andric void ObjCProtocolDecl::allocateDefinitionData() { 20170b57cec5SDimitry Andric assert(!Data.getPointer() && "Protocol already has a definition!"); 20180b57cec5SDimitry Andric Data.setPointer(new (getASTContext()) DefinitionData); 20190b57cec5SDimitry Andric Data.getPointer()->Definition = this; 2020bdd1243dSDimitry Andric Data.getPointer()->HasODRHash = false; 20210b57cec5SDimitry Andric } 20220b57cec5SDimitry Andric 20230b57cec5SDimitry Andric void ObjCProtocolDecl::startDefinition() { 20240b57cec5SDimitry Andric allocateDefinitionData(); 20250b57cec5SDimitry Andric 20260b57cec5SDimitry Andric // Update all of the declarations with a pointer to the definition. 20270b57cec5SDimitry Andric for (auto *RD : redecls()) 20280b57cec5SDimitry Andric RD->Data = this->Data; 20290b57cec5SDimitry Andric } 20300b57cec5SDimitry Andric 2031bdd1243dSDimitry Andric void ObjCProtocolDecl::startDuplicateDefinitionForComparison() { 2032bdd1243dSDimitry Andric Data.setPointer(nullptr); 2033bdd1243dSDimitry Andric allocateDefinitionData(); 2034bdd1243dSDimitry Andric // Don't propagate data to other redeclarations. 2035bdd1243dSDimitry Andric } 2036bdd1243dSDimitry Andric 2037bdd1243dSDimitry Andric void ObjCProtocolDecl::mergeDuplicateDefinitionWithCommon( 2038bdd1243dSDimitry Andric const ObjCProtocolDecl *Definition) { 2039bdd1243dSDimitry Andric Data = Definition->Data; 2040bdd1243dSDimitry Andric } 2041bdd1243dSDimitry Andric 2042bdd1243dSDimitry Andric void ObjCProtocolDecl::collectPropertiesToImplement(PropertyMap &PM) const { 20430b57cec5SDimitry Andric if (const ObjCProtocolDecl *PDecl = getDefinition()) { 20440b57cec5SDimitry Andric for (auto *Prop : PDecl->properties()) { 20450b57cec5SDimitry Andric // Insert into PM if not there already. 20460b57cec5SDimitry Andric PM.insert(std::make_pair( 20470b57cec5SDimitry Andric std::make_pair(Prop->getIdentifier(), Prop->isClassProperty()), 20480b57cec5SDimitry Andric Prop)); 20490b57cec5SDimitry Andric } 20500b57cec5SDimitry Andric // Scan through protocol's protocols. 20510b57cec5SDimitry Andric for (const auto *PI : PDecl->protocols()) 2052bdd1243dSDimitry Andric PI->collectPropertiesToImplement(PM); 20530b57cec5SDimitry Andric } 20540b57cec5SDimitry Andric } 20550b57cec5SDimitry Andric 20560b57cec5SDimitry Andric void ObjCProtocolDecl::collectInheritedProtocolProperties( 20570b57cec5SDimitry Andric const ObjCPropertyDecl *Property, ProtocolPropertySet &PS, 20580b57cec5SDimitry Andric PropertyDeclOrder &PO) const { 20590b57cec5SDimitry Andric if (const ObjCProtocolDecl *PDecl = getDefinition()) { 20600b57cec5SDimitry Andric if (!PS.insert(PDecl).second) 20610b57cec5SDimitry Andric return; 20620b57cec5SDimitry Andric for (auto *Prop : PDecl->properties()) { 20630b57cec5SDimitry Andric if (Prop == Property) 20640b57cec5SDimitry Andric continue; 20650b57cec5SDimitry Andric if (Prop->getIdentifier() == Property->getIdentifier()) { 20660b57cec5SDimitry Andric PO.push_back(Prop); 20670b57cec5SDimitry Andric return; 20680b57cec5SDimitry Andric } 20690b57cec5SDimitry Andric } 20700b57cec5SDimitry Andric // Scan through protocol's protocols which did not have a matching property. 20710b57cec5SDimitry Andric for (const auto *PI : PDecl->protocols()) 20720b57cec5SDimitry Andric PI->collectInheritedProtocolProperties(Property, PS, PO); 20730b57cec5SDimitry Andric } 20740b57cec5SDimitry Andric } 20750b57cec5SDimitry Andric 20760b57cec5SDimitry Andric StringRef 20770b57cec5SDimitry Andric ObjCProtocolDecl::getObjCRuntimeNameAsString() const { 20780b57cec5SDimitry Andric if (const auto *ObjCRTName = getAttr<ObjCRuntimeNameAttr>()) 20790b57cec5SDimitry Andric return ObjCRTName->getMetadataName(); 20800b57cec5SDimitry Andric 20810b57cec5SDimitry Andric return getName(); 20820b57cec5SDimitry Andric } 20830b57cec5SDimitry Andric 2084bdd1243dSDimitry Andric unsigned ObjCProtocolDecl::getODRHash() { 2085bdd1243dSDimitry Andric assert(hasDefinition() && "ODRHash only for records with definitions"); 2086bdd1243dSDimitry Andric 2087bdd1243dSDimitry Andric // Previously calculated hash is stored in DefinitionData. 2088bdd1243dSDimitry Andric if (hasODRHash()) 2089bdd1243dSDimitry Andric return data().ODRHash; 2090bdd1243dSDimitry Andric 2091bdd1243dSDimitry Andric // Only calculate hash on first call of getODRHash per record. 2092bdd1243dSDimitry Andric ODRHash Hasher; 2093bdd1243dSDimitry Andric Hasher.AddObjCProtocolDecl(getDefinition()); 2094bdd1243dSDimitry Andric data().ODRHash = Hasher.CalculateHash(); 2095bdd1243dSDimitry Andric setHasODRHash(true); 2096bdd1243dSDimitry Andric 2097bdd1243dSDimitry Andric return data().ODRHash; 2098bdd1243dSDimitry Andric } 2099bdd1243dSDimitry Andric 2100bdd1243dSDimitry Andric bool ObjCProtocolDecl::hasODRHash() const { 2101bdd1243dSDimitry Andric if (!hasDefinition()) 2102bdd1243dSDimitry Andric return false; 2103bdd1243dSDimitry Andric return data().HasODRHash; 2104bdd1243dSDimitry Andric } 2105bdd1243dSDimitry Andric 2106bdd1243dSDimitry Andric void ObjCProtocolDecl::setHasODRHash(bool HasHash) { 2107bdd1243dSDimitry Andric assert(hasDefinition() && "Cannot set ODRHash without definition"); 2108bdd1243dSDimitry Andric data().HasODRHash = HasHash; 2109bdd1243dSDimitry Andric } 2110bdd1243dSDimitry Andric 21110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 21120b57cec5SDimitry Andric // ObjCCategoryDecl 21130b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 21140b57cec5SDimitry Andric 21150b57cec5SDimitry Andric void ObjCCategoryDecl::anchor() {} 21160b57cec5SDimitry Andric 2117*0fca6ea1SDimitry Andric ObjCCategoryDecl::ObjCCategoryDecl( 2118*0fca6ea1SDimitry Andric DeclContext *DC, SourceLocation AtLoc, SourceLocation ClassNameLoc, 2119*0fca6ea1SDimitry Andric SourceLocation CategoryNameLoc, const IdentifierInfo *Id, 2120*0fca6ea1SDimitry Andric ObjCInterfaceDecl *IDecl, ObjCTypeParamList *typeParamList, 2121*0fca6ea1SDimitry Andric SourceLocation IvarLBraceLoc, SourceLocation IvarRBraceLoc) 21220b57cec5SDimitry Andric : ObjCContainerDecl(ObjCCategory, DC, Id, ClassNameLoc, AtLoc), 21230b57cec5SDimitry Andric ClassInterface(IDecl), CategoryNameLoc(CategoryNameLoc), 21240b57cec5SDimitry Andric IvarLBraceLoc(IvarLBraceLoc), IvarRBraceLoc(IvarRBraceLoc) { 21250b57cec5SDimitry Andric setTypeParamList(typeParamList); 21260b57cec5SDimitry Andric } 21270b57cec5SDimitry Andric 2128*0fca6ea1SDimitry Andric ObjCCategoryDecl *ObjCCategoryDecl::Create( 2129*0fca6ea1SDimitry Andric ASTContext &C, DeclContext *DC, SourceLocation AtLoc, 2130*0fca6ea1SDimitry Andric SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc, 2131*0fca6ea1SDimitry Andric const IdentifierInfo *Id, ObjCInterfaceDecl *IDecl, 2132*0fca6ea1SDimitry Andric ObjCTypeParamList *typeParamList, SourceLocation IvarLBraceLoc, 21330b57cec5SDimitry Andric SourceLocation IvarRBraceLoc) { 21340b57cec5SDimitry Andric auto *CatDecl = 21350b57cec5SDimitry Andric new (C, DC) ObjCCategoryDecl(DC, AtLoc, ClassNameLoc, CategoryNameLoc, Id, 21360b57cec5SDimitry Andric IDecl, typeParamList, IvarLBraceLoc, 21370b57cec5SDimitry Andric IvarRBraceLoc); 21380b57cec5SDimitry Andric if (IDecl) { 21390b57cec5SDimitry Andric // Link this category into its class's category list. 21400b57cec5SDimitry Andric CatDecl->NextClassCategory = IDecl->getCategoryListRaw(); 21410b57cec5SDimitry Andric if (IDecl->hasDefinition()) { 21420b57cec5SDimitry Andric IDecl->setCategoryListRaw(CatDecl); 21430b57cec5SDimitry Andric if (ASTMutationListener *L = C.getASTMutationListener()) 21440b57cec5SDimitry Andric L->AddedObjCCategoryToInterface(CatDecl, IDecl); 21450b57cec5SDimitry Andric } 21460b57cec5SDimitry Andric } 21470b57cec5SDimitry Andric 21480b57cec5SDimitry Andric return CatDecl; 21490b57cec5SDimitry Andric } 21500b57cec5SDimitry Andric 21510b57cec5SDimitry Andric ObjCCategoryDecl *ObjCCategoryDecl::CreateDeserialized(ASTContext &C, 2152*0fca6ea1SDimitry Andric GlobalDeclID ID) { 21530b57cec5SDimitry Andric return new (C, ID) ObjCCategoryDecl(nullptr, SourceLocation(), 21540b57cec5SDimitry Andric SourceLocation(), SourceLocation(), 21550b57cec5SDimitry Andric nullptr, nullptr, nullptr); 21560b57cec5SDimitry Andric } 21570b57cec5SDimitry Andric 21580b57cec5SDimitry Andric ObjCCategoryImplDecl *ObjCCategoryDecl::getImplementation() const { 21590b57cec5SDimitry Andric return getASTContext().getObjCImplementation( 21600b57cec5SDimitry Andric const_cast<ObjCCategoryDecl*>(this)); 21610b57cec5SDimitry Andric } 21620b57cec5SDimitry Andric 21630b57cec5SDimitry Andric void ObjCCategoryDecl::setImplementation(ObjCCategoryImplDecl *ImplD) { 21640b57cec5SDimitry Andric getASTContext().setObjCImplementation(this, ImplD); 21650b57cec5SDimitry Andric } 21660b57cec5SDimitry Andric 21670b57cec5SDimitry Andric void ObjCCategoryDecl::setTypeParamList(ObjCTypeParamList *TPL) { 21680b57cec5SDimitry Andric TypeParamList = TPL; 21690b57cec5SDimitry Andric if (!TPL) 21700b57cec5SDimitry Andric return; 21710b57cec5SDimitry Andric // Set the declaration context of each of the type parameters. 21720b57cec5SDimitry Andric for (auto *typeParam : *TypeParamList) 21730b57cec5SDimitry Andric typeParam->setDeclContext(this); 21740b57cec5SDimitry Andric } 21750b57cec5SDimitry Andric 21760b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 21770b57cec5SDimitry Andric // ObjCCategoryImplDecl 21780b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 21790b57cec5SDimitry Andric 21800b57cec5SDimitry Andric void ObjCCategoryImplDecl::anchor() {} 21810b57cec5SDimitry Andric 2182*0fca6ea1SDimitry Andric ObjCCategoryImplDecl *ObjCCategoryImplDecl::Create( 2183*0fca6ea1SDimitry Andric ASTContext &C, DeclContext *DC, const IdentifierInfo *Id, 2184*0fca6ea1SDimitry Andric ObjCInterfaceDecl *ClassInterface, SourceLocation nameLoc, 2185*0fca6ea1SDimitry Andric SourceLocation atStartLoc, SourceLocation CategoryNameLoc) { 21860b57cec5SDimitry Andric if (ClassInterface && ClassInterface->hasDefinition()) 21870b57cec5SDimitry Andric ClassInterface = ClassInterface->getDefinition(); 21880b57cec5SDimitry Andric return new (C, DC) ObjCCategoryImplDecl(DC, Id, ClassInterface, nameLoc, 21890b57cec5SDimitry Andric atStartLoc, CategoryNameLoc); 21900b57cec5SDimitry Andric } 21910b57cec5SDimitry Andric 2192*0fca6ea1SDimitry Andric ObjCCategoryImplDecl * 2193*0fca6ea1SDimitry Andric ObjCCategoryImplDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) { 21940b57cec5SDimitry Andric return new (C, ID) ObjCCategoryImplDecl(nullptr, nullptr, nullptr, 21950b57cec5SDimitry Andric SourceLocation(), SourceLocation(), 21960b57cec5SDimitry Andric SourceLocation()); 21970b57cec5SDimitry Andric } 21980b57cec5SDimitry Andric 21990b57cec5SDimitry Andric ObjCCategoryDecl *ObjCCategoryImplDecl::getCategoryDecl() const { 22000b57cec5SDimitry Andric // The class interface might be NULL if we are working with invalid code. 22010b57cec5SDimitry Andric if (const ObjCInterfaceDecl *ID = getClassInterface()) 22020b57cec5SDimitry Andric return ID->FindCategoryDeclaration(getIdentifier()); 22030b57cec5SDimitry Andric return nullptr; 22040b57cec5SDimitry Andric } 22050b57cec5SDimitry Andric 22060b57cec5SDimitry Andric void ObjCImplDecl::anchor() {} 22070b57cec5SDimitry Andric 22080b57cec5SDimitry Andric void ObjCImplDecl::addPropertyImplementation(ObjCPropertyImplDecl *property) { 22090b57cec5SDimitry Andric // FIXME: The context should be correct before we get here. 22100b57cec5SDimitry Andric property->setLexicalDeclContext(this); 22110b57cec5SDimitry Andric addDecl(property); 22120b57cec5SDimitry Andric } 22130b57cec5SDimitry Andric 22140b57cec5SDimitry Andric void ObjCImplDecl::setClassInterface(ObjCInterfaceDecl *IFace) { 22150b57cec5SDimitry Andric ASTContext &Ctx = getASTContext(); 22160b57cec5SDimitry Andric 22170b57cec5SDimitry Andric if (auto *ImplD = dyn_cast_or_null<ObjCImplementationDecl>(this)) { 22180b57cec5SDimitry Andric if (IFace) 22190b57cec5SDimitry Andric Ctx.setObjCImplementation(IFace, ImplD); 22200b57cec5SDimitry Andric 22210b57cec5SDimitry Andric } else if (auto *ImplD = dyn_cast_or_null<ObjCCategoryImplDecl>(this)) { 22220b57cec5SDimitry Andric if (ObjCCategoryDecl *CD = IFace->FindCategoryDeclaration(getIdentifier())) 22230b57cec5SDimitry Andric Ctx.setObjCImplementation(CD, ImplD); 22240b57cec5SDimitry Andric } 22250b57cec5SDimitry Andric 22260b57cec5SDimitry Andric ClassInterface = IFace; 22270b57cec5SDimitry Andric } 22280b57cec5SDimitry Andric 22290b57cec5SDimitry Andric /// FindPropertyImplIvarDecl - This method lookup the ivar in the list of 22300b57cec5SDimitry Andric /// properties implemented in this \@implementation block and returns 22310b57cec5SDimitry Andric /// the implemented property that uses it. 22320b57cec5SDimitry Andric ObjCPropertyImplDecl *ObjCImplDecl:: 22330b57cec5SDimitry Andric FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const { 22340b57cec5SDimitry Andric for (auto *PID : property_impls()) 22350b57cec5SDimitry Andric if (PID->getPropertyIvarDecl() && 22360b57cec5SDimitry Andric PID->getPropertyIvarDecl()->getIdentifier() == ivarId) 22370b57cec5SDimitry Andric return PID; 22380b57cec5SDimitry Andric return nullptr; 22390b57cec5SDimitry Andric } 22400b57cec5SDimitry Andric 22410b57cec5SDimitry Andric /// FindPropertyImplDecl - This method looks up a previous ObjCPropertyImplDecl 22420b57cec5SDimitry Andric /// added to the list of those properties \@synthesized/\@dynamic in this 22430b57cec5SDimitry Andric /// category \@implementation block. 22440b57cec5SDimitry Andric ObjCPropertyImplDecl *ObjCImplDecl:: 22450b57cec5SDimitry Andric FindPropertyImplDecl(IdentifierInfo *Id, 22460b57cec5SDimitry Andric ObjCPropertyQueryKind QueryKind) const { 22470b57cec5SDimitry Andric ObjCPropertyImplDecl *ClassPropImpl = nullptr; 22480b57cec5SDimitry Andric for (auto *PID : property_impls()) 22490b57cec5SDimitry Andric // If queryKind is unknown, we return the instance property if one 22500b57cec5SDimitry Andric // exists; otherwise we return the class property. 22510b57cec5SDimitry Andric if (PID->getPropertyDecl()->getIdentifier() == Id) { 22520b57cec5SDimitry Andric if ((QueryKind == ObjCPropertyQueryKind::OBJC_PR_query_unknown && 22530b57cec5SDimitry Andric !PID->getPropertyDecl()->isClassProperty()) || 22540b57cec5SDimitry Andric (QueryKind == ObjCPropertyQueryKind::OBJC_PR_query_class && 22550b57cec5SDimitry Andric PID->getPropertyDecl()->isClassProperty()) || 22560b57cec5SDimitry Andric (QueryKind == ObjCPropertyQueryKind::OBJC_PR_query_instance && 22570b57cec5SDimitry Andric !PID->getPropertyDecl()->isClassProperty())) 22580b57cec5SDimitry Andric return PID; 22590b57cec5SDimitry Andric 22600b57cec5SDimitry Andric if (PID->getPropertyDecl()->isClassProperty()) 22610b57cec5SDimitry Andric ClassPropImpl = PID; 22620b57cec5SDimitry Andric } 22630b57cec5SDimitry Andric 22640b57cec5SDimitry Andric if (QueryKind == ObjCPropertyQueryKind::OBJC_PR_query_unknown) 22650b57cec5SDimitry Andric // We can't find the instance property, return the class property. 22660b57cec5SDimitry Andric return ClassPropImpl; 22670b57cec5SDimitry Andric 22680b57cec5SDimitry Andric return nullptr; 22690b57cec5SDimitry Andric } 22700b57cec5SDimitry Andric 22710b57cec5SDimitry Andric raw_ostream &clang::operator<<(raw_ostream &OS, 22720b57cec5SDimitry Andric const ObjCCategoryImplDecl &CID) { 22730b57cec5SDimitry Andric OS << CID.getName(); 22740b57cec5SDimitry Andric return OS; 22750b57cec5SDimitry Andric } 22760b57cec5SDimitry Andric 22770b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 22780b57cec5SDimitry Andric // ObjCImplementationDecl 22790b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 22800b57cec5SDimitry Andric 22810b57cec5SDimitry Andric void ObjCImplementationDecl::anchor() {} 22820b57cec5SDimitry Andric 22830b57cec5SDimitry Andric ObjCImplementationDecl * 22840b57cec5SDimitry Andric ObjCImplementationDecl::Create(ASTContext &C, DeclContext *DC, 22850b57cec5SDimitry Andric ObjCInterfaceDecl *ClassInterface, 22860b57cec5SDimitry Andric ObjCInterfaceDecl *SuperDecl, 22870b57cec5SDimitry Andric SourceLocation nameLoc, 22880b57cec5SDimitry Andric SourceLocation atStartLoc, 22890b57cec5SDimitry Andric SourceLocation superLoc, 22900b57cec5SDimitry Andric SourceLocation IvarLBraceLoc, 22910b57cec5SDimitry Andric SourceLocation IvarRBraceLoc) { 22920b57cec5SDimitry Andric if (ClassInterface && ClassInterface->hasDefinition()) 22930b57cec5SDimitry Andric ClassInterface = ClassInterface->getDefinition(); 22940b57cec5SDimitry Andric return new (C, DC) ObjCImplementationDecl(DC, ClassInterface, SuperDecl, 22950b57cec5SDimitry Andric nameLoc, atStartLoc, superLoc, 22960b57cec5SDimitry Andric IvarLBraceLoc, IvarRBraceLoc); 22970b57cec5SDimitry Andric } 22980b57cec5SDimitry Andric 22990b57cec5SDimitry Andric ObjCImplementationDecl * 2300*0fca6ea1SDimitry Andric ObjCImplementationDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) { 23010b57cec5SDimitry Andric return new (C, ID) ObjCImplementationDecl(nullptr, nullptr, nullptr, 23020b57cec5SDimitry Andric SourceLocation(), SourceLocation()); 23030b57cec5SDimitry Andric } 23040b57cec5SDimitry Andric 23050b57cec5SDimitry Andric void ObjCImplementationDecl::setIvarInitializers(ASTContext &C, 23060b57cec5SDimitry Andric CXXCtorInitializer ** initializers, 23070b57cec5SDimitry Andric unsigned numInitializers) { 23080b57cec5SDimitry Andric if (numInitializers > 0) { 23090b57cec5SDimitry Andric NumIvarInitializers = numInitializers; 23100b57cec5SDimitry Andric auto **ivarInitializers = new (C) CXXCtorInitializer*[NumIvarInitializers]; 23110b57cec5SDimitry Andric memcpy(ivarInitializers, initializers, 23120b57cec5SDimitry Andric numInitializers * sizeof(CXXCtorInitializer*)); 23130b57cec5SDimitry Andric IvarInitializers = ivarInitializers; 23140b57cec5SDimitry Andric } 23150b57cec5SDimitry Andric } 23160b57cec5SDimitry Andric 23170b57cec5SDimitry Andric ObjCImplementationDecl::init_const_iterator 23180b57cec5SDimitry Andric ObjCImplementationDecl::init_begin() const { 23190b57cec5SDimitry Andric return IvarInitializers.get(getASTContext().getExternalSource()); 23200b57cec5SDimitry Andric } 23210b57cec5SDimitry Andric 23220b57cec5SDimitry Andric raw_ostream &clang::operator<<(raw_ostream &OS, 23230b57cec5SDimitry Andric const ObjCImplementationDecl &ID) { 23240b57cec5SDimitry Andric OS << ID.getName(); 23250b57cec5SDimitry Andric return OS; 23260b57cec5SDimitry Andric } 23270b57cec5SDimitry Andric 23280b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 23290b57cec5SDimitry Andric // ObjCCompatibleAliasDecl 23300b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 23310b57cec5SDimitry Andric 23320b57cec5SDimitry Andric void ObjCCompatibleAliasDecl::anchor() {} 23330b57cec5SDimitry Andric 23340b57cec5SDimitry Andric ObjCCompatibleAliasDecl * 23350b57cec5SDimitry Andric ObjCCompatibleAliasDecl::Create(ASTContext &C, DeclContext *DC, 23360b57cec5SDimitry Andric SourceLocation L, 23370b57cec5SDimitry Andric IdentifierInfo *Id, 23380b57cec5SDimitry Andric ObjCInterfaceDecl* AliasedClass) { 23390b57cec5SDimitry Andric return new (C, DC) ObjCCompatibleAliasDecl(DC, L, Id, AliasedClass); 23400b57cec5SDimitry Andric } 23410b57cec5SDimitry Andric 23420b57cec5SDimitry Andric ObjCCompatibleAliasDecl * 2343*0fca6ea1SDimitry Andric ObjCCompatibleAliasDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) { 23440b57cec5SDimitry Andric return new (C, ID) ObjCCompatibleAliasDecl(nullptr, SourceLocation(), 23450b57cec5SDimitry Andric nullptr, nullptr); 23460b57cec5SDimitry Andric } 23470b57cec5SDimitry Andric 23480b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 23490b57cec5SDimitry Andric // ObjCPropertyDecl 23500b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 23510b57cec5SDimitry Andric 23520b57cec5SDimitry Andric void ObjCPropertyDecl::anchor() {} 23530b57cec5SDimitry Andric 2354*0fca6ea1SDimitry Andric ObjCPropertyDecl * 2355*0fca6ea1SDimitry Andric ObjCPropertyDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, 2356*0fca6ea1SDimitry Andric const IdentifierInfo *Id, SourceLocation AtLoc, 2357*0fca6ea1SDimitry Andric SourceLocation LParenLoc, QualType T, 2358*0fca6ea1SDimitry Andric TypeSourceInfo *TSI, PropertyControl propControl) { 23590b57cec5SDimitry Andric return new (C, DC) ObjCPropertyDecl(DC, L, Id, AtLoc, LParenLoc, T, TSI, 23600b57cec5SDimitry Andric propControl); 23610b57cec5SDimitry Andric } 23620b57cec5SDimitry Andric 23630b57cec5SDimitry Andric ObjCPropertyDecl *ObjCPropertyDecl::CreateDeserialized(ASTContext &C, 2364*0fca6ea1SDimitry Andric GlobalDeclID ID) { 23650b57cec5SDimitry Andric return new (C, ID) ObjCPropertyDecl(nullptr, SourceLocation(), nullptr, 23660b57cec5SDimitry Andric SourceLocation(), SourceLocation(), 23670b57cec5SDimitry Andric QualType(), nullptr, None); 23680b57cec5SDimitry Andric } 23690b57cec5SDimitry Andric 23700b57cec5SDimitry Andric QualType ObjCPropertyDecl::getUsageType(QualType objectType) const { 23710b57cec5SDimitry Andric return DeclType.substObjCMemberType(objectType, getDeclContext(), 23720b57cec5SDimitry Andric ObjCSubstitutionContext::Property); 23730b57cec5SDimitry Andric } 23740b57cec5SDimitry Andric 2375fe6060f1SDimitry Andric bool ObjCPropertyDecl::isDirectProperty() const { 2376fe6060f1SDimitry Andric return (PropertyAttributes & ObjCPropertyAttribute::kind_direct) && 2377fe6060f1SDimitry Andric !getASTContext().getLangOpts().ObjCDisableDirectMethodsForTesting; 2378fe6060f1SDimitry Andric } 2379fe6060f1SDimitry Andric 23800b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 23810b57cec5SDimitry Andric // ObjCPropertyImplDecl 23820b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 23830b57cec5SDimitry Andric 23840b57cec5SDimitry Andric ObjCPropertyImplDecl *ObjCPropertyImplDecl::Create(ASTContext &C, 23850b57cec5SDimitry Andric DeclContext *DC, 23860b57cec5SDimitry Andric SourceLocation atLoc, 23870b57cec5SDimitry Andric SourceLocation L, 23880b57cec5SDimitry Andric ObjCPropertyDecl *property, 23890b57cec5SDimitry Andric Kind PK, 23900b57cec5SDimitry Andric ObjCIvarDecl *ivar, 23910b57cec5SDimitry Andric SourceLocation ivarLoc) { 23920b57cec5SDimitry Andric return new (C, DC) ObjCPropertyImplDecl(DC, atLoc, L, property, PK, ivar, 23930b57cec5SDimitry Andric ivarLoc); 23940b57cec5SDimitry Andric } 23950b57cec5SDimitry Andric 2396*0fca6ea1SDimitry Andric ObjCPropertyImplDecl * 2397*0fca6ea1SDimitry Andric ObjCPropertyImplDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) { 23980b57cec5SDimitry Andric return new (C, ID) ObjCPropertyImplDecl(nullptr, SourceLocation(), 23990b57cec5SDimitry Andric SourceLocation(), nullptr, Dynamic, 24000b57cec5SDimitry Andric nullptr, SourceLocation()); 24010b57cec5SDimitry Andric } 24020b57cec5SDimitry Andric 24030b57cec5SDimitry Andric SourceRange ObjCPropertyImplDecl::getSourceRange() const { 24040b57cec5SDimitry Andric SourceLocation EndLoc = getLocation(); 24050b57cec5SDimitry Andric if (IvarLoc.isValid()) 24060b57cec5SDimitry Andric EndLoc = IvarLoc; 24070b57cec5SDimitry Andric 24080b57cec5SDimitry Andric return SourceRange(AtLoc, EndLoc); 24090b57cec5SDimitry Andric } 2410