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
set(void * const * InList,unsigned Elts,ASTContext & Ctx)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
set(ObjCProtocolDecl * const * InList,unsigned Elts,const SourceLocation * Locs,ASTContext & Ctx)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
ObjCContainerDecl(Kind DK,DeclContext * DC,const IdentifierInfo * Id,SourceLocation nameLoc,SourceLocation atStartLoc)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
anchor()760b57cec5SDimitry Andric void ObjCContainerDecl::anchor() {}
770b57cec5SDimitry Andric
780b57cec5SDimitry Andric /// getIvarDecl - This method looks up an ivar in this ContextDecl.
790b57cec5SDimitry Andric ///
800b57cec5SDimitry Andric ObjCIvarDecl *
getIvarDecl(IdentifierInfo * Id) const810b57cec5SDimitry 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 *
getMethod(Selector Sel,bool isInstance,bool AllowHidden) const930b57cec5SDimitry 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.
HasUserDeclaredSetterMethod(const ObjCPropertyDecl * Property) const1250b57cec5SDimitry 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 *
findPropertyDecl(const DeclContext * DC,const IdentifierInfo * propertyID,ObjCPropertyQueryKind queryKind)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 *
getDefaultSynthIvarName(ASTContext & Ctx) const2270b57cec5SDimitry 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
getProperty(const IdentifierInfo * Id,bool IsInstance) const23604eeddc0SDimitry 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.
FindPropertyDeclaration(const IdentifierInfo * PropertyId,ObjCPropertyQueryKind QueryKind) const2500b57cec5SDimitry 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
anchor()3200b57cec5SDimitry Andric void ObjCInterfaceDecl::anchor() {}
3210b57cec5SDimitry Andric
getTypeParamList() const3220b57cec5SDimitry 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
setTypeParamList(ObjCTypeParamList * TPL)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
getSuperClass() const3520b57cec5SDimitry 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
getSuperClassLoc() const3720b57cec5SDimitry 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.
FindPropertyVisibleInPrimaryClass(const IdentifierInfo * PropertyId,ObjCPropertyQueryKind QueryKind) const382*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
collectPropertiesToImplement(PropertyMap & PM) const405bdd1243dSDimitry 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
isArcWeakrefUnavailable() const4220b57cec5SDimitry 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
isObjCRequiresPropertyDefs() const4320b57cec5SDimitry 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
mergeClassExtensionProtocolList(ObjCProtocolDecl * const * ExtList,unsigned ExtNum,ASTContext & C)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 *
findInterfaceWithDesignatedInitializers() const4840b57cec5SDimitry 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
isIntroducingInitializers(const ObjCInterfaceDecl * D)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
inheritsDesignatedInitializers() const5160b57cec5SDimitry 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
getDesignatedInitializers(llvm::SmallVectorImpl<const ObjCMethodDecl * > & Methods) const5480b57cec5SDimitry 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
isDesignatedInitializer(Selector Sel,const ObjCMethodDecl ** InitMethod) const5700b57cec5SDimitry 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
allocateDefinitionData()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
startDefinition()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
startDuplicateDefinitionForComparison()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
mergeDuplicateDefinitionWithCommon(const ObjCInterfaceDecl * Definition)632bdd1243dSDimitry Andric void ObjCInterfaceDecl::mergeDuplicateDefinitionWithCommon(
633bdd1243dSDimitry Andric const ObjCInterfaceDecl *Definition) {
634bdd1243dSDimitry Andric Data = Definition->Data;
635bdd1243dSDimitry Andric }
636bdd1243dSDimitry Andric
lookupInstanceVariable(IdentifierInfo * ID,ObjCInterfaceDecl * & clsDeclared)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.
lookupInheritedClass(const IdentifierInfo * ICName)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 *
lookupNestedProtocol(IdentifierInfo * Name)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.
lookupMethod(Selector Sel,bool isInstance,bool shallowCategoryLookup,bool followSuper,const ObjCCategoryDecl * C) const6990b57cec5SDimitry 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.
lookupPrivateMethod(const Selector & Sel,bool Instance) const7560b57cec5SDimitry 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
getODRHash()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
hasODRHash() const807bdd1243dSDimitry Andric bool ObjCInterfaceDecl::hasODRHash() const {
808bdd1243dSDimitry Andric if (!hasDefinition())
809bdd1243dSDimitry Andric return false;
810bdd1243dSDimitry Andric return data().HasODRHash;
811bdd1243dSDimitry Andric }
812bdd1243dSDimitry Andric
setHasODRHash(bool HasHash)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
ObjCMethodDecl(SourceLocation beginLoc,SourceLocation endLoc,Selector SelInfo,QualType T,TypeSourceInfo * ReturnTInfo,DeclContext * contextDecl,bool isInstance,bool isVariadic,bool isPropertyAccessor,bool isSynthesizedAccessorStub,bool isImplicitlyDeclared,bool isDefined,ObjCImplementationControl impControl,bool HasRelatedResultType)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
Create(ASTContext & C,SourceLocation beginLoc,SourceLocation endLoc,Selector SelInfo,QualType T,TypeSourceInfo * ReturnTInfo,DeclContext * contextDecl,bool isInstance,bool isVariadic,bool isPropertyAccessor,bool isSynthesizedAccessorStub,bool isImplicitlyDeclared,bool isDefined,ObjCImplementationControl impControl,bool HasRelatedResultType)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
CreateDeserialized(ASTContext & C,GlobalDeclID ID)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
isDirectMethod() const871480093f4SDimitry Andric bool ObjCMethodDecl::isDirectMethod() const {
872fe6060f1SDimitry Andric return hasAttr<ObjCDirectAttr>() &&
873fe6060f1SDimitry Andric !getASTContext().getLangOpts().ObjCDisableDirectMethodsForTesting;
874480093f4SDimitry Andric }
875480093f4SDimitry Andric
isThisDeclarationADesignatedInitializer() const8760b57cec5SDimitry Andric bool ObjCMethodDecl::isThisDeclarationADesignatedInitializer() const {
8770b57cec5SDimitry Andric return getMethodFamily() == OMF_init &&
8780b57cec5SDimitry Andric hasAttr<ObjCDesignatedInitializerAttr>();
8790b57cec5SDimitry Andric }
8800b57cec5SDimitry Andric
definedInNSObject(const ASTContext & Ctx) const8810b57cec5SDimitry 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
isDesignatedInitializerForTheInterface(const ObjCMethodDecl ** InitMethod) const8890b57cec5SDimitry 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
hasParamDestroyedInCallee() const901349cc55cSDimitry 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
getBody() const9090b57cec5SDimitry Andric Stmt *ObjCMethodDecl::getBody() const {
9100b57cec5SDimitry Andric return Body.get(getASTContext().getExternalSource());
9110b57cec5SDimitry Andric }
9120b57cec5SDimitry Andric
setAsRedeclaration(const ObjCMethodDecl * PrevMethod)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
setParamsAndSelLocs(ASTContext & C,ArrayRef<ParmVarDecl * > Params,ArrayRef<SourceLocation> SelLocs)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
getSelectorLocs(SmallVectorImpl<SourceLocation> & SelLocs) const9380b57cec5SDimitry 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
setMethodParams(ASTContext & C,ArrayRef<ParmVarDecl * > Params,ArrayRef<SourceLocation> SelLocs)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.
getNextRedeclarationImpl()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
getCanonicalDecl()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
getEndLoc() const10470b57cec5SDimitry Andric SourceLocation ObjCMethodDecl::getEndLoc() const {
10480b57cec5SDimitry Andric if (Stmt *Body = getBody())
10490b57cec5SDimitry Andric return Body->getEndLoc();
10500b57cec5SDimitry Andric return DeclEndLoc;
10510b57cec5SDimitry Andric }
10520b57cec5SDimitry Andric
getMethodFamily() const10530b57cec5SDimitry 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
getSelfType(ASTContext & Context,const ObjCInterfaceDecl * OID,bool & selfIsPseudoStrong,bool & selfIsConsumed) const11450b57cec5SDimitry 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
createImplicitParams(ASTContext & Context,const ObjCInterfaceDecl * OID)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
getClassInterface()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
getCategory()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
getReturnTypeSourceRange() const12310b57cec5SDimitry 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
getSendResultType() const12380b57cec5SDimitry 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
getSendResultType(QualType receiverType) const12440b57cec5SDimitry 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
CollectOverriddenMethodsRecurse(const ObjCContainerDecl * Container,const ObjCMethodDecl * Method,SmallVectorImpl<const ObjCMethodDecl * > & Methods,bool MovedToSuper)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
CollectOverriddenMethods(const ObjCContainerDecl * Container,const ObjCMethodDecl * Method,SmallVectorImpl<const ObjCMethodDecl * > & Methods)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
collectOverriddenMethodsSlow(const ObjCMethodDecl * Method,SmallVectorImpl<const ObjCMethodDecl * > & overridden)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
getOverriddenMethods(SmallVectorImpl<const ObjCMethodDecl * > & Overridden) const13600b57cec5SDimitry 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 *
findPropertyDecl(bool CheckOverrides) const13780b57cec5SDimitry 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
anchor()14710b57cec5SDimitry Andric void ObjCTypeParamDecl::anchor() {}
14720b57cec5SDimitry Andric
Create(ASTContext & ctx,DeclContext * dc,ObjCTypeParamVariance variance,SourceLocation varianceLoc,unsigned index,SourceLocation nameLoc,IdentifierInfo * name,SourceLocation colonLoc,TypeSourceInfo * boundInfo)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
CreateDeserialized(ASTContext & ctx,GlobalDeclID ID)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
getSourceRange() const14970b57cec5SDimitry 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 //===----------------------------------------------------------------------===//
ObjCTypeParamList(SourceLocation lAngleLoc,ArrayRef<ObjCTypeParamDecl * > typeParams,SourceLocation rAngleLoc)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
create(ASTContext & ctx,SourceLocation lAngleLoc,ArrayRef<ObjCTypeParamDecl * > typeParams,SourceLocation rAngleLoc)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
gatherDefaultTypeArgs(SmallVectorImpl<QualType> & typeArgs) const15310b57cec5SDimitry 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
Create(const ASTContext & C,DeclContext * DC,SourceLocation atLoc,const IdentifierInfo * Id,ObjCTypeParamList * typeParamList,ObjCInterfaceDecl * PrevDecl,SourceLocation ClassLoc,bool isInternal)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
CreateDeserialized(const ASTContext & C,GlobalDeclID ID)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
ObjCInterfaceDecl(const ASTContext & C,DeclContext * DC,SourceLocation AtLoc,const IdentifierInfo * Id,ObjCTypeParamList * typeParamList,SourceLocation CLoc,ObjCInterfaceDecl * PrevDecl,bool IsInternal)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
LoadExternalDefinition() const15800b57cec5SDimitry 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
setExternallyCompleted()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
setHasDesignatedInitializers()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
hasDesignatedInitializers() const16020b57cec5SDimitry 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
getObjCRuntimeNameAsString() const16130b57cec5SDimitry 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
getObjCRuntimeNameAsString() const16210b57cec5SDimitry 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
getImplementation() const16290b57cec5SDimitry 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
setImplementation(ObjCImplementationDecl * ImplD)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
SynthesizeIvarChunk__anon43dd50270211::SynthesizeIvarChunk16520b57cec5SDimitry Andric SynthesizeIvarChunk(uint64_t size, ObjCIvarDecl *ivar)
16530b57cec5SDimitry Andric : Size(size), Ivar(ivar) {}
16540b57cec5SDimitry Andric };
16550b57cec5SDimitry Andric
operator <(const SynthesizeIvarChunk & LHS,const SynthesizeIvarChunk & RHS)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().
all_declared_ivar_begin()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 ///
FindCategoryDeclaration(const IdentifierInfo * CategoryId) const1748*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 *
getCategoryInstanceMethod(Selector Sel) const17650b57cec5SDimitry 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
getCategoryClassMethod(Selector Sel) const17750b57cec5SDimitry 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).
ClassImplementsProtocol(ObjCProtocolDecl * lProto,bool lookupCategory,bool RHSIsQualifiedID)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
anchor()18310b57cec5SDimitry Andric void ObjCIvarDecl::anchor() {}
18320b57cec5SDimitry Andric
Create(ASTContext & C,ObjCContainerDecl * DC,SourceLocation StartLoc,SourceLocation IdLoc,const IdentifierInfo * Id,QualType T,TypeSourceInfo * TInfo,AccessControl ac,Expr * BW,bool synthesized)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
CreateDeserialized(ASTContext & C,GlobalDeclID ID)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
getContainingInterface()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
getUsageType(QualType objectType) const18990b57cec5SDimitry 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
anchor()19080b57cec5SDimitry Andric void ObjCAtDefsFieldDecl::anchor() {}
19090b57cec5SDimitry Andric
19100b57cec5SDimitry Andric ObjCAtDefsFieldDecl
Create(ASTContext & C,DeclContext * DC,SourceLocation StartLoc,SourceLocation IdLoc,IdentifierInfo * Id,QualType T,Expr * BW)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
CreateDeserialized(ASTContext & C,GlobalDeclID ID)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
anchor()19280b57cec5SDimitry Andric void ObjCProtocolDecl::anchor() {}
19290b57cec5SDimitry Andric
ObjCProtocolDecl(ASTContext & C,DeclContext * DC,IdentifierInfo * Id,SourceLocation nameLoc,SourceLocation atStartLoc,ObjCProtocolDecl * PrevDecl)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
Create(ASTContext & C,DeclContext * DC,IdentifierInfo * Id,SourceLocation nameLoc,SourceLocation atStartLoc,ObjCProtocolDecl * PrevDecl)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
CreateDeserialized(ASTContext & C,GlobalDeclID ID)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
isNonRuntimeProtocol() const1961e8d8bef9SDimitry Andric bool ObjCProtocolDecl::isNonRuntimeProtocol() const {
1962e8d8bef9SDimitry Andric return hasAttr<ObjCNonRuntimeProtocolAttr>();
1963e8d8bef9SDimitry Andric }
1964e8d8bef9SDimitry Andric
getImpliedProtocols(llvm::DenseSet<const ObjCProtocolDecl * > & IPs) const1965e8d8bef9SDimitry 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
lookupProtocolNamed(IdentifierInfo * Name)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.
lookupMethod(Selector Sel,bool isInstance) const19970b57cec5SDimitry 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
allocateDefinitionData()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
startDefinition()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
startDuplicateDefinitionForComparison()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
mergeDuplicateDefinitionWithCommon(const ObjCProtocolDecl * Definition)2037bdd1243dSDimitry Andric void ObjCProtocolDecl::mergeDuplicateDefinitionWithCommon(
2038bdd1243dSDimitry Andric const ObjCProtocolDecl *Definition) {
2039bdd1243dSDimitry Andric Data = Definition->Data;
2040bdd1243dSDimitry Andric }
2041bdd1243dSDimitry Andric
collectPropertiesToImplement(PropertyMap & PM) const2042bdd1243dSDimitry 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
collectInheritedProtocolProperties(const ObjCPropertyDecl * Property,ProtocolPropertySet & PS,PropertyDeclOrder & PO) const20560b57cec5SDimitry 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
getObjCRuntimeNameAsString() const20770b57cec5SDimitry 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
getODRHash()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
hasODRHash() const2100bdd1243dSDimitry Andric bool ObjCProtocolDecl::hasODRHash() const {
2101bdd1243dSDimitry Andric if (!hasDefinition())
2102bdd1243dSDimitry Andric return false;
2103bdd1243dSDimitry Andric return data().HasODRHash;
2104bdd1243dSDimitry Andric }
2105bdd1243dSDimitry Andric
setHasODRHash(bool HasHash)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
anchor()21150b57cec5SDimitry Andric void ObjCCategoryDecl::anchor() {}
21160b57cec5SDimitry Andric
ObjCCategoryDecl(DeclContext * DC,SourceLocation AtLoc,SourceLocation ClassNameLoc,SourceLocation CategoryNameLoc,const IdentifierInfo * Id,ObjCInterfaceDecl * IDecl,ObjCTypeParamList * typeParamList,SourceLocation IvarLBraceLoc,SourceLocation IvarRBraceLoc)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
Create(ASTContext & C,DeclContext * DC,SourceLocation AtLoc,SourceLocation ClassNameLoc,SourceLocation CategoryNameLoc,const IdentifierInfo * Id,ObjCInterfaceDecl * IDecl,ObjCTypeParamList * typeParamList,SourceLocation IvarLBraceLoc,SourceLocation IvarRBraceLoc)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
CreateDeserialized(ASTContext & C,GlobalDeclID ID)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
getImplementation() const21580b57cec5SDimitry Andric ObjCCategoryImplDecl *ObjCCategoryDecl::getImplementation() const {
21590b57cec5SDimitry Andric return getASTContext().getObjCImplementation(
21600b57cec5SDimitry Andric const_cast<ObjCCategoryDecl*>(this));
21610b57cec5SDimitry Andric }
21620b57cec5SDimitry Andric
setImplementation(ObjCCategoryImplDecl * ImplD)21630b57cec5SDimitry Andric void ObjCCategoryDecl::setImplementation(ObjCCategoryImplDecl *ImplD) {
21640b57cec5SDimitry Andric getASTContext().setObjCImplementation(this, ImplD);
21650b57cec5SDimitry Andric }
21660b57cec5SDimitry Andric
setTypeParamList(ObjCTypeParamList * TPL)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
anchor()21800b57cec5SDimitry Andric void ObjCCategoryImplDecl::anchor() {}
21810b57cec5SDimitry Andric
Create(ASTContext & C,DeclContext * DC,const IdentifierInfo * Id,ObjCInterfaceDecl * ClassInterface,SourceLocation nameLoc,SourceLocation atStartLoc,SourceLocation CategoryNameLoc)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 *
CreateDeserialized(ASTContext & C,GlobalDeclID ID)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
getCategoryDecl() const21990b57cec5SDimitry 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
anchor()22060b57cec5SDimitry Andric void ObjCImplDecl::anchor() {}
22070b57cec5SDimitry Andric
addPropertyImplementation(ObjCPropertyImplDecl * property)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
setClassInterface(ObjCInterfaceDecl * IFace)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::
FindPropertyImplIvarDecl(IdentifierInfo * ivarId) const22330b57cec5SDimitry 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::
FindPropertyImplDecl(IdentifierInfo * Id,ObjCPropertyQueryKind QueryKind) const22450b57cec5SDimitry 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
operator <<(raw_ostream & OS,const ObjCCategoryImplDecl & CID)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
anchor()22810b57cec5SDimitry Andric void ObjCImplementationDecl::anchor() {}
22820b57cec5SDimitry Andric
22830b57cec5SDimitry Andric ObjCImplementationDecl *
Create(ASTContext & C,DeclContext * DC,ObjCInterfaceDecl * ClassInterface,ObjCInterfaceDecl * SuperDecl,SourceLocation nameLoc,SourceLocation atStartLoc,SourceLocation superLoc,SourceLocation IvarLBraceLoc,SourceLocation IvarRBraceLoc)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 *
CreateDeserialized(ASTContext & C,GlobalDeclID ID)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
setIvarInitializers(ASTContext & C,CXXCtorInitializer ** initializers,unsigned numInitializers)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
init_begin() const23180b57cec5SDimitry Andric ObjCImplementationDecl::init_begin() const {
23190b57cec5SDimitry Andric return IvarInitializers.get(getASTContext().getExternalSource());
23200b57cec5SDimitry Andric }
23210b57cec5SDimitry Andric
operator <<(raw_ostream & OS,const ObjCImplementationDecl & ID)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
anchor()23320b57cec5SDimitry Andric void ObjCCompatibleAliasDecl::anchor() {}
23330b57cec5SDimitry Andric
23340b57cec5SDimitry Andric ObjCCompatibleAliasDecl *
Create(ASTContext & C,DeclContext * DC,SourceLocation L,IdentifierInfo * Id,ObjCInterfaceDecl * AliasedClass)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 *
CreateDeserialized(ASTContext & C,GlobalDeclID ID)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
anchor()23520b57cec5SDimitry Andric void ObjCPropertyDecl::anchor() {}
23530b57cec5SDimitry Andric
2354*0fca6ea1SDimitry Andric ObjCPropertyDecl *
Create(ASTContext & C,DeclContext * DC,SourceLocation L,const IdentifierInfo * Id,SourceLocation AtLoc,SourceLocation LParenLoc,QualType T,TypeSourceInfo * TSI,PropertyControl propControl)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
CreateDeserialized(ASTContext & C,GlobalDeclID ID)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
getUsageType(QualType objectType) const23700b57cec5SDimitry Andric QualType ObjCPropertyDecl::getUsageType(QualType objectType) const {
23710b57cec5SDimitry Andric return DeclType.substObjCMemberType(objectType, getDeclContext(),
23720b57cec5SDimitry Andric ObjCSubstitutionContext::Property);
23730b57cec5SDimitry Andric }
23740b57cec5SDimitry Andric
isDirectProperty() const2375fe6060f1SDimitry 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
Create(ASTContext & C,DeclContext * DC,SourceLocation atLoc,SourceLocation L,ObjCPropertyDecl * property,Kind PK,ObjCIvarDecl * ivar,SourceLocation ivarLoc)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 *
CreateDeserialized(ASTContext & C,GlobalDeclID ID)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
getSourceRange() const24030b57cec5SDimitry 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