2008-03-16 08:19:01 +08:00
|
|
|
//===--- DeclObjC.cpp - ObjC Declaration AST Node Implementation ----------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements the Objective-C related Decl classes.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "clang/AST/DeclObjC.h"
|
|
|
|
#include "clang/AST/ASTContext.h"
|
2011-09-01 08:58:55 +08:00
|
|
|
#include "clang/AST/ASTMutationListener.h"
|
2012-12-01 23:09:41 +08:00
|
|
|
#include "clang/AST/Attr.h"
|
|
|
|
#include "clang/AST/Stmt.h"
|
2009-02-23 03:35:57 +08:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2012-09-28 03:45:11 +08:00
|
|
|
#include "llvm/ADT/SmallString.h"
|
2008-03-16 08:19:01 +08:00
|
|
|
using namespace clang;
|
|
|
|
|
2009-02-21 05:16:26 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// ObjCListBase
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-02-21 05:35:13 +08:00
|
|
|
void ObjCListBase::set(void *const* InList, unsigned Elts, ASTContext &Ctx) {
|
2010-07-26 02:17:45 +08:00
|
|
|
List = 0;
|
2009-02-21 05:16:26 +08:00
|
|
|
if (Elts == 0) return; // Setting to an empty list is a noop.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
|
2009-02-21 05:44:01 +08:00
|
|
|
List = new (Ctx) void*[Elts];
|
2009-02-21 05:16:26 +08:00
|
|
|
NumElts = Elts;
|
|
|
|
memcpy(List, InList, sizeof(void*)*Elts);
|
|
|
|
}
|
|
|
|
|
2010-01-16 23:02:53 +08:00
|
|
|
void ObjCProtocolList::set(ObjCProtocolDecl* const* InList, unsigned Elts,
|
|
|
|
const SourceLocation *Locs, ASTContext &Ctx) {
|
|
|
|
if (Elts == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
Locations = new (Ctx) SourceLocation[Elts];
|
|
|
|
memcpy(Locations, Locs, sizeof(SourceLocation) * Elts);
|
|
|
|
set(InList, Elts, Ctx);
|
|
|
|
}
|
|
|
|
|
2008-03-16 08:49:28 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2009-02-21 04:59:54 +08:00
|
|
|
// ObjCInterfaceDecl
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2011-12-20 10:48:34 +08:00
|
|
|
void ObjCContainerDecl::anchor() { }
|
|
|
|
|
2009-06-06 02:16:35 +08:00
|
|
|
/// getIvarDecl - This method looks up an ivar in this ContextDecl.
|
|
|
|
///
|
|
|
|
ObjCIvarDecl *
|
2009-06-30 10:36:12 +08:00
|
|
|
ObjCContainerDecl::getIvarDecl(IdentifierInfo *Id) const {
|
2012-12-19 08:45:41 +08:00
|
|
|
lookup_const_result R = lookup(Id);
|
|
|
|
for (lookup_const_iterator Ivar = R.begin(), IvarEnd = R.end();
|
|
|
|
Ivar != IvarEnd; ++Ivar) {
|
2009-06-06 02:16:35 +08:00
|
|
|
if (ObjCIvarDecl *ivar = dyn_cast<ObjCIvarDecl>(*Ivar))
|
|
|
|
return ivar;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-07-26 06:15:22 +08:00
|
|
|
// Get the local instance/class method declared in this interface.
|
2009-04-10 05:40:53 +08:00
|
|
|
ObjCMethodDecl *
|
2013-03-30 05:51:48 +08:00
|
|
|
ObjCContainerDecl::getMethod(Selector Sel, bool isInstance,
|
|
|
|
bool AllowHidden) const {
|
2013-01-17 08:38:46 +08:00
|
|
|
// If this context is a hidden protocol definition, don't find any
|
|
|
|
// methods there.
|
|
|
|
if (const ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(this)) {
|
|
|
|
if (const ObjCProtocolDecl *Def = Proto->getDefinition())
|
2013-03-30 05:51:48 +08:00
|
|
|
if (Def->isHidden() && !AllowHidden)
|
2013-01-17 08:38:46 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-02-23 03:35:57 +08:00
|
|
|
// Since instance & class methods can have the same name, the loop below
|
|
|
|
// ensures we get the correct method.
|
|
|
|
//
|
|
|
|
// @interface Whatever
|
|
|
|
// - (int) class_method;
|
|
|
|
// + (float) class_method;
|
|
|
|
// @end
|
|
|
|
//
|
2012-12-19 08:45:41 +08:00
|
|
|
lookup_const_result R = lookup(Sel);
|
|
|
|
for (lookup_const_iterator Meth = R.begin(), MethEnd = R.end();
|
|
|
|
Meth != MethEnd; ++Meth) {
|
2009-02-23 03:35:57 +08:00
|
|
|
ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth);
|
2009-07-26 06:15:22 +08:00
|
|
|
if (MD && MD->isInstanceMethod() == isInstance)
|
2009-02-23 03:35:57 +08:00
|
|
|
return MD;
|
|
|
|
}
|
2009-02-21 04:59:54 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-03-22 04:50:53 +08:00
|
|
|
/// HasUserDeclaredSetterMethod - This routine returns 'true' if a user declared setter
|
|
|
|
/// method was found in the class, its protocols, its super classes or categories.
|
|
|
|
/// It also returns 'true' if one of its categories has declared a 'readwrite' property.
|
|
|
|
/// This is because, user must provide a setter method for the category's 'readwrite'
|
|
|
|
/// property.
|
|
|
|
bool
|
|
|
|
ObjCContainerDecl::HasUserDeclaredSetterMethod(const ObjCPropertyDecl *Property) const {
|
|
|
|
Selector Sel = Property->getSetterName();
|
|
|
|
lookup_const_result R = lookup(Sel);
|
|
|
|
for (lookup_const_iterator Meth = R.begin(), MethEnd = R.end();
|
|
|
|
Meth != MethEnd; ++Meth) {
|
|
|
|
ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth);
|
|
|
|
if (MD && MD->isInstanceMethod() && !MD->isImplicit())
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(this)) {
|
|
|
|
// Also look into categories, including class extensions, looking
|
|
|
|
// for a user declared instance method.
|
|
|
|
for (ObjCInterfaceDecl::visible_categories_iterator
|
|
|
|
Cat = ID->visible_categories_begin(),
|
|
|
|
CatEnd = ID->visible_categories_end();
|
|
|
|
Cat != CatEnd;
|
|
|
|
++Cat) {
|
|
|
|
if (ObjCMethodDecl *MD = Cat->getInstanceMethod(Sel))
|
|
|
|
if (!MD->isImplicit())
|
|
|
|
return true;
|
|
|
|
if (Cat->IsClassExtension())
|
|
|
|
continue;
|
|
|
|
// Also search through the categories looking for a 'readwrite' declaration
|
|
|
|
// of this property. If one found, presumably a setter will be provided
|
|
|
|
// (properties declared in categories will not get auto-synthesized).
|
|
|
|
for (ObjCContainerDecl::prop_iterator P = Cat->prop_begin(),
|
|
|
|
E = Cat->prop_end(); P != E; ++P)
|
|
|
|
if (P->getIdentifier() == Property->getIdentifier()) {
|
|
|
|
if (P->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readwrite)
|
|
|
|
return true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Also look into protocols, for a user declared instance method.
|
|
|
|
for (ObjCInterfaceDecl::all_protocol_iterator P =
|
|
|
|
ID->all_referenced_protocol_begin(),
|
|
|
|
PE = ID->all_referenced_protocol_end(); P != PE; ++P) {
|
|
|
|
ObjCProtocolDecl *Proto = (*P);
|
|
|
|
if (Proto->HasUserDeclaredSetterMethod(Property))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
// And in its super class.
|
|
|
|
ObjCInterfaceDecl *OSC = ID->getSuperClass();
|
|
|
|
while (OSC) {
|
|
|
|
if (OSC->HasUserDeclaredSetterMethod(Property))
|
|
|
|
return true;
|
|
|
|
OSC = OSC->getSuperClass();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (const ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(this))
|
|
|
|
for (ObjCProtocolDecl::protocol_iterator PI = PD->protocol_begin(),
|
|
|
|
E = PD->protocol_end(); PI != E; ++PI) {
|
|
|
|
if ((*PI)->HasUserDeclaredSetterMethod(Property))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-03-16 04:11:46 +08:00
|
|
|
ObjCPropertyDecl *
|
2010-03-16 04:11:53 +08:00
|
|
|
ObjCPropertyDecl::findPropertyDecl(const DeclContext *DC,
|
2010-03-16 04:11:46 +08:00
|
|
|
IdentifierInfo *propertyID) {
|
2013-01-17 08:38:46 +08:00
|
|
|
// If this context is a hidden protocol definition, don't find any
|
|
|
|
// property.
|
|
|
|
if (const ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(DC)) {
|
|
|
|
if (const ObjCProtocolDecl *Def = Proto->getDefinition())
|
|
|
|
if (Def->isHidden())
|
|
|
|
return 0;
|
|
|
|
}
|
2010-03-16 04:11:46 +08:00
|
|
|
|
2012-12-19 08:45:41 +08:00
|
|
|
DeclContext::lookup_const_result R = DC->lookup(propertyID);
|
|
|
|
for (DeclContext::lookup_const_iterator I = R.begin(), E = R.end(); I != E;
|
|
|
|
++I)
|
2010-03-16 04:11:46 +08:00
|
|
|
if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(*I))
|
|
|
|
return PD;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-09-28 03:45:11 +08:00
|
|
|
IdentifierInfo *
|
|
|
|
ObjCPropertyDecl::getDefaultSynthIvarName(ASTContext &Ctx) const {
|
|
|
|
SmallString<128> ivarName;
|
|
|
|
{
|
|
|
|
llvm::raw_svector_ostream os(ivarName);
|
|
|
|
os << '_' << getIdentifier()->getName();
|
|
|
|
}
|
|
|
|
return &Ctx.Idents.get(ivarName.str());
|
|
|
|
}
|
|
|
|
|
2009-02-21 04:59:54 +08:00
|
|
|
/// FindPropertyDeclaration - Finds declaration of the property given its name
|
|
|
|
/// in 'PropertyId' and returns it. It returns 0, if not found.
|
|
|
|
ObjCPropertyDecl *
|
2009-06-30 10:36:12 +08:00
|
|
|
ObjCContainerDecl::FindPropertyDeclaration(IdentifierInfo *PropertyId) const {
|
2013-01-17 08:38:46 +08:00
|
|
|
// Don't find properties within hidden protocol definitions.
|
|
|
|
if (const ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(this)) {
|
|
|
|
if (const ObjCProtocolDecl *Def = Proto->getDefinition())
|
|
|
|
if (Def->isHidden())
|
|
|
|
return 0;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-03-16 04:11:53 +08:00
|
|
|
if (ObjCPropertyDecl *PD =
|
|
|
|
ObjCPropertyDecl::findPropertyDecl(cast<DeclContext>(this), PropertyId))
|
|
|
|
return PD;
|
|
|
|
|
|
|
|
switch (getKind()) {
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
case Decl::ObjCProtocol: {
|
|
|
|
const ObjCProtocolDecl *PID = cast<ObjCProtocolDecl>(this);
|
|
|
|
for (ObjCProtocolDecl::protocol_iterator I = PID->protocol_begin(),
|
|
|
|
E = PID->protocol_end(); I != E; ++I)
|
|
|
|
if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId))
|
2010-02-16 05:55:26 +08:00
|
|
|
return P;
|
2010-03-16 04:11:53 +08:00
|
|
|
break;
|
2009-02-21 04:59:54 +08:00
|
|
|
}
|
2010-03-16 04:11:53 +08:00
|
|
|
case Decl::ObjCInterface: {
|
|
|
|
const ObjCInterfaceDecl *OID = cast<ObjCInterfaceDecl>(this);
|
2013-01-17 07:00:23 +08:00
|
|
|
// Look through categories (but not extensions).
|
|
|
|
for (ObjCInterfaceDecl::visible_categories_iterator
|
|
|
|
Cat = OID->visible_categories_begin(),
|
|
|
|
CatEnd = OID->visible_categories_end();
|
|
|
|
Cat != CatEnd; ++Cat) {
|
2010-03-16 04:11:53 +08:00
|
|
|
if (!Cat->IsClassExtension())
|
|
|
|
if (ObjCPropertyDecl *P = Cat->FindPropertyDeclaration(PropertyId))
|
|
|
|
return P;
|
2013-01-17 07:00:23 +08:00
|
|
|
}
|
2010-03-16 04:11:53 +08:00
|
|
|
|
|
|
|
// Look through protocols.
|
2010-09-01 09:21:15 +08:00
|
|
|
for (ObjCInterfaceDecl::all_protocol_iterator
|
|
|
|
I = OID->all_referenced_protocol_begin(),
|
|
|
|
E = OID->all_referenced_protocol_end(); I != E; ++I)
|
2010-03-16 04:11:53 +08:00
|
|
|
if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId))
|
|
|
|
return P;
|
|
|
|
|
|
|
|
// Finally, check the super class.
|
|
|
|
if (const ObjCInterfaceDecl *superClass = OID->getSuperClass())
|
|
|
|
return superClass->FindPropertyDeclaration(PropertyId);
|
|
|
|
break;
|
2009-02-21 04:59:54 +08:00
|
|
|
}
|
2010-03-16 04:11:53 +08:00
|
|
|
case Decl::ObjCCategory: {
|
|
|
|
const ObjCCategoryDecl *OCD = cast<ObjCCategoryDecl>(this);
|
|
|
|
// Look through protocols.
|
|
|
|
if (!OCD->IsClassExtension())
|
|
|
|
for (ObjCCategoryDecl::protocol_iterator
|
|
|
|
I = OCD->protocol_begin(), E = OCD->protocol_end(); I != E; ++I)
|
2010-02-16 05:55:26 +08:00
|
|
|
if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId))
|
|
|
|
return P;
|
2010-03-16 04:11:53 +08:00
|
|
|
|
|
|
|
break;
|
2009-02-21 04:59:54 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-12-20 10:48:34 +08:00
|
|
|
void ObjCInterfaceDecl::anchor() { }
|
|
|
|
|
2009-11-03 06:45:15 +08:00
|
|
|
/// FindPropertyVisibleInPrimaryClass - Finds declaration of the property
|
|
|
|
/// with name 'PropertyId' in the primary class; including those in protocols
|
2010-03-16 04:30:07 +08:00
|
|
|
/// (direct or indirect) used by the primary class.
|
2009-11-03 06:45:15 +08:00
|
|
|
///
|
|
|
|
ObjCPropertyDecl *
|
2010-03-16 04:30:07 +08:00
|
|
|
ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass(
|
2009-11-03 06:45:15 +08:00
|
|
|
IdentifierInfo *PropertyId) const {
|
2011-12-15 13:27:12 +08:00
|
|
|
// FIXME: Should make sure no callers ever do this.
|
|
|
|
if (!hasDefinition())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (data().ExternallyCompleted)
|
2010-12-02 07:49:52 +08:00
|
|
|
LoadExternalDefinition();
|
|
|
|
|
2010-03-16 04:30:07 +08:00
|
|
|
if (ObjCPropertyDecl *PD =
|
|
|
|
ObjCPropertyDecl::findPropertyDecl(cast<DeclContext>(this), PropertyId))
|
|
|
|
return PD;
|
|
|
|
|
2009-11-03 06:45:15 +08:00
|
|
|
// Look through protocols.
|
2010-09-01 09:21:15 +08:00
|
|
|
for (ObjCInterfaceDecl::all_protocol_iterator
|
|
|
|
I = all_referenced_protocol_begin(),
|
|
|
|
E = all_referenced_protocol_end(); I != E; ++I)
|
2009-11-03 06:45:15 +08:00
|
|
|
if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId))
|
|
|
|
return P;
|
2010-03-16 04:30:07 +08:00
|
|
|
|
2009-11-03 06:45:15 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-02-15 06:33:34 +08:00
|
|
|
void ObjCInterfaceDecl::collectPropertiesToImplement(PropertyMap &PM,
|
|
|
|
PropertyDeclOrder &PO) const {
|
2012-10-19 03:17:53 +08:00
|
|
|
for (ObjCContainerDecl::prop_iterator P = prop_begin(),
|
|
|
|
E = prop_end(); P != E; ++P) {
|
|
|
|
ObjCPropertyDecl *Prop = *P;
|
|
|
|
PM[Prop->getIdentifier()] = Prop;
|
2013-02-15 06:33:34 +08:00
|
|
|
PO.push_back(Prop);
|
2012-10-19 03:17:53 +08:00
|
|
|
}
|
|
|
|
for (ObjCInterfaceDecl::all_protocol_iterator
|
|
|
|
PI = all_referenced_protocol_begin(),
|
|
|
|
E = all_referenced_protocol_end(); PI != E; ++PI)
|
2013-02-15 06:33:34 +08:00
|
|
|
(*PI)->collectPropertiesToImplement(PM, PO);
|
2012-10-31 09:18:22 +08:00
|
|
|
// Note, the properties declared only in class extensions are still copied
|
|
|
|
// into the main @interface's property list, and therefore we don't
|
|
|
|
// explicitly, have to search class extension properties.
|
2012-10-19 03:17:53 +08:00
|
|
|
}
|
|
|
|
|
2012-12-01 23:09:41 +08:00
|
|
|
bool ObjCInterfaceDecl::isArcWeakrefUnavailable() const {
|
|
|
|
const ObjCInterfaceDecl *Class = this;
|
|
|
|
while (Class) {
|
|
|
|
if (Class->hasAttr<ArcWeakrefUnavailableAttr>())
|
|
|
|
return true;
|
|
|
|
Class = Class->getSuperClass();
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
const ObjCInterfaceDecl *ObjCInterfaceDecl::isObjCRequiresPropertyDefs() const {
|
|
|
|
const ObjCInterfaceDecl *Class = this;
|
|
|
|
while (Class) {
|
|
|
|
if (Class->hasAttr<ObjCRequiresPropertyDefsAttr>())
|
|
|
|
return Class;
|
|
|
|
Class = Class->getSuperClass();
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-10-06 04:41:32 +08:00
|
|
|
void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
|
|
|
|
ObjCProtocolDecl *const* ExtList, unsigned ExtNum,
|
|
|
|
ASTContext &C)
|
|
|
|
{
|
2011-12-15 13:27:12 +08:00
|
|
|
if (data().ExternallyCompleted)
|
2010-12-02 07:49:52 +08:00
|
|
|
LoadExternalDefinition();
|
|
|
|
|
2011-12-15 13:27:12 +08:00
|
|
|
if (data().AllReferencedProtocols.empty() &&
|
|
|
|
data().ReferencedProtocols.empty()) {
|
|
|
|
data().AllReferencedProtocols.set(ExtList, ExtNum, C);
|
2009-10-06 04:41:32 +08:00
|
|
|
return;
|
|
|
|
}
|
2010-09-01 09:21:15 +08:00
|
|
|
|
2009-10-06 04:41:32 +08:00
|
|
|
// Check for duplicate protocol in class's protocol list.
|
2010-09-01 09:21:15 +08:00
|
|
|
// This is O(n*m). But it is extremely rare and number of protocols in
|
2009-10-06 04:41:32 +08:00
|
|
|
// class or its extension are very few.
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<ObjCProtocolDecl*, 8> ProtocolRefs;
|
2009-10-06 04:41:32 +08:00
|
|
|
for (unsigned i = 0; i < ExtNum; i++) {
|
|
|
|
bool protocolExists = false;
|
|
|
|
ObjCProtocolDecl *ProtoInExtension = ExtList[i];
|
2010-09-01 09:21:15 +08:00
|
|
|
for (all_protocol_iterator
|
|
|
|
p = all_referenced_protocol_begin(),
|
|
|
|
e = all_referenced_protocol_end(); p != e; ++p) {
|
2009-10-06 04:41:32 +08:00
|
|
|
ObjCProtocolDecl *Proto = (*p);
|
|
|
|
if (C.ProtocolCompatibleWithProtocol(ProtoInExtension, Proto)) {
|
|
|
|
protocolExists = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Do we want to warn on a protocol in extension class which
|
|
|
|
// already exist in the class? Probably not.
|
2010-09-01 09:21:15 +08:00
|
|
|
if (!protocolExists)
|
2009-10-06 04:41:32 +08:00
|
|
|
ProtocolRefs.push_back(ProtoInExtension);
|
|
|
|
}
|
2010-09-01 09:21:15 +08:00
|
|
|
|
2009-10-06 04:41:32 +08:00
|
|
|
if (ProtocolRefs.empty())
|
|
|
|
return;
|
2010-09-01 09:21:15 +08:00
|
|
|
|
2009-10-06 05:32:49 +08:00
|
|
|
// Merge ProtocolRefs into class's protocol list;
|
2010-09-01 09:21:15 +08:00
|
|
|
for (all_protocol_iterator p = all_referenced_protocol_begin(),
|
|
|
|
e = all_referenced_protocol_end(); p != e; ++p) {
|
2009-10-06 04:41:32 +08:00
|
|
|
ProtocolRefs.push_back(*p);
|
2010-01-16 23:02:53 +08:00
|
|
|
}
|
2010-09-01 09:21:15 +08:00
|
|
|
|
2011-12-15 13:27:12 +08:00
|
|
|
data().AllReferencedProtocols.set(ProtocolRefs.data(), ProtocolRefs.size(),C);
|
2009-10-06 04:41:32 +08:00
|
|
|
}
|
|
|
|
|
2013-12-05 15:07:03 +08:00
|
|
|
const ObjCInterfaceDecl *
|
|
|
|
ObjCInterfaceDecl::findInterfaceWithDesignatedInitializers() const {
|
2013-12-04 05:11:30 +08:00
|
|
|
const ObjCInterfaceDecl *IFace = this;
|
|
|
|
while (IFace) {
|
2013-12-05 15:07:03 +08:00
|
|
|
if (IFace->hasDesignatedInitializers())
|
|
|
|
return IFace;
|
|
|
|
if (!IFace->inheritsDesignatedInitializers())
|
2013-12-04 05:11:30 +08:00
|
|
|
break;
|
|
|
|
IFace = IFace->getSuperClass();
|
|
|
|
}
|
2013-12-05 15:07:03 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ObjCInterfaceDecl::inheritsDesignatedInitializers() const {
|
|
|
|
switch (data().InheritedDesignatedInitializers) {
|
|
|
|
case DefinitionData::IDI_Inherited:
|
|
|
|
return true;
|
|
|
|
case DefinitionData::IDI_NotInherited:
|
|
|
|
return false;
|
|
|
|
case DefinitionData::IDI_Unknown: {
|
|
|
|
bool isIntroducingInitializers = false;
|
|
|
|
for (instmeth_iterator I = instmeth_begin(),
|
|
|
|
E = instmeth_end(); I != E; ++I) {
|
|
|
|
const ObjCMethodDecl *MD = *I;
|
|
|
|
if (MD->getMethodFamily() == OMF_init && !MD->isOverriding()) {
|
|
|
|
isIntroducingInitializers = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// If the class introduced initializers we conservatively assume that we
|
|
|
|
// don't know if any of them is a designated initializer to avoid possible
|
|
|
|
// misleading warnings.
|
|
|
|
if (isIntroducingInitializers) {
|
|
|
|
data().InheritedDesignatedInitializers = DefinitionData::IDI_NotInherited;
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
data().InheritedDesignatedInitializers = DefinitionData::IDI_Inherited;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm_unreachable("unexpected InheritedDesignatedInitializers value");
|
|
|
|
}
|
|
|
|
|
|
|
|
void ObjCInterfaceDecl::getDesignatedInitializers(
|
|
|
|
llvm::SmallVectorImpl<const ObjCMethodDecl *> &Methods) const {
|
|
|
|
assert(hasDefinition());
|
|
|
|
if (data().ExternallyCompleted)
|
|
|
|
LoadExternalDefinition();
|
2013-12-04 05:11:30 +08:00
|
|
|
|
2013-12-05 15:07:03 +08:00
|
|
|
const ObjCInterfaceDecl *IFace= findInterfaceWithDesignatedInitializers();
|
2013-12-04 05:11:30 +08:00
|
|
|
if (!IFace)
|
|
|
|
return;
|
2013-12-05 15:07:03 +08:00
|
|
|
|
2013-12-04 05:11:30 +08:00
|
|
|
for (instmeth_iterator I = IFace->instmeth_begin(),
|
|
|
|
E = IFace->instmeth_end(); I != E; ++I) {
|
|
|
|
const ObjCMethodDecl *MD = *I;
|
2013-12-04 05:11:36 +08:00
|
|
|
if (MD->isThisDeclarationADesignatedInitializer())
|
2013-12-04 05:11:30 +08:00
|
|
|
Methods.push_back(MD);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-04 05:11:36 +08:00
|
|
|
bool ObjCInterfaceDecl::isDesignatedInitializer(Selector Sel,
|
|
|
|
const ObjCMethodDecl **InitMethod) const {
|
|
|
|
assert(hasDefinition());
|
|
|
|
if (data().ExternallyCompleted)
|
|
|
|
LoadExternalDefinition();
|
|
|
|
|
2013-12-05 15:07:03 +08:00
|
|
|
const ObjCInterfaceDecl *IFace= findInterfaceWithDesignatedInitializers();
|
2013-12-04 05:11:36 +08:00
|
|
|
if (!IFace)
|
|
|
|
return false;
|
|
|
|
|
2013-12-11 02:36:43 +08:00
|
|
|
if (const ObjCMethodDecl *MD = IFace->getMethod(Sel, /*isInstance=*/true)) {
|
2013-12-04 05:11:36 +08:00
|
|
|
if (MD->isThisDeclarationADesignatedInitializer()) {
|
|
|
|
if (InitMethod)
|
|
|
|
*InitMethod = MD;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-12-15 13:27:12 +08:00
|
|
|
void ObjCInterfaceDecl::allocateDefinitionData() {
|
|
|
|
assert(!hasDefinition() && "ObjC class already has a definition");
|
Ensure that type definitions present in just-loaded modules are
visible.
The basic problem here is that a given translation unit can use
forward declarations to form pointers to a given type, say,
class X;
X *x;
and then import a module that includes a definition of X:
import XDef;
We will then fail when attempting to access a member of X, e.g.,
x->method()
because the AST reader did not know to look for a default of a class
named X within the new module.
This implementation is a bit of a C-centric hack, because the only
definitions that can have this property are enums, structs, unions,
Objective-C classes, and Objective-C protocols, and all of those are
either visible at the top-level or can't be defined later. Hence, we
can use the out-of-date-ness of the name and the identifier-update
mechanism to force the update.
In C++, we will not be so lucky, and will need a more advanced
solution, because the definitions could be in namespaces defined in
two different modules, e.g.,
// module 1
namespace N { struct X; }
// module 2
namespace N { struct X { /* ... */ }; }
One possible implementation here is for C++ to extend the information
associated with each identifier table to include the declaration IDs
of any definitions associated with that name, regardless of
context. We would have to eagerly load those definitions.
llvm-svn: 174794
2013-02-09 09:35:03 +08:00
|
|
|
Data.setPointer(new (getASTContext()) DefinitionData());
|
|
|
|
Data.getPointer()->Definition = this;
|
2011-12-17 00:34:57 +08:00
|
|
|
|
|
|
|
// Make the type point at the definition, now that we have one.
|
|
|
|
if (TypeForDecl)
|
|
|
|
cast<ObjCInterfaceType>(TypeForDecl)->Decl = this;
|
2011-12-16 11:12:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void ObjCInterfaceDecl::startDefinition() {
|
|
|
|
allocateDefinitionData();
|
|
|
|
|
2011-12-16 02:03:09 +08:00
|
|
|
// Update all of the declarations with a pointer to the definition.
|
|
|
|
for (redecl_iterator RD = redecls_begin(), RDEnd = redecls_end();
|
|
|
|
RD != RDEnd; ++RD) {
|
|
|
|
if (*RD != this)
|
2011-12-16 02:17:27 +08:00
|
|
|
RD->Data = Data;
|
2011-12-16 02:03:09 +08:00
|
|
|
}
|
2011-11-13 05:07:46 +08:00
|
|
|
}
|
|
|
|
|
2009-06-30 10:36:12 +08:00
|
|
|
ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(IdentifierInfo *ID,
|
|
|
|
ObjCInterfaceDecl *&clsDeclared) {
|
2011-12-15 13:27:12 +08:00
|
|
|
// FIXME: Should make sure no callers ever do this.
|
|
|
|
if (!hasDefinition())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (data().ExternallyCompleted)
|
2011-10-19 10:25:16 +08:00
|
|
|
LoadExternalDefinition();
|
|
|
|
|
2009-02-21 04:59:54 +08:00
|
|
|
ObjCInterfaceDecl* ClassDecl = this;
|
|
|
|
while (ClassDecl != NULL) {
|
2009-06-30 10:36:12 +08:00
|
|
|
if (ObjCIvarDecl *I = ClassDecl->getIvarDecl(ID)) {
|
2009-06-06 02:16:35 +08:00
|
|
|
clsDeclared = ClassDecl;
|
|
|
|
return I;
|
2009-02-21 04:59:54 +08:00
|
|
|
}
|
2013-01-17 07:00:23 +08:00
|
|
|
|
|
|
|
for (ObjCInterfaceDecl::visible_extensions_iterator
|
|
|
|
Ext = ClassDecl->visible_extensions_begin(),
|
|
|
|
ExtEnd = ClassDecl->visible_extensions_end();
|
|
|
|
Ext != ExtEnd; ++Ext) {
|
|
|
|
if (ObjCIvarDecl *I = Ext->getIvarDecl(ID)) {
|
2010-02-23 09:26:30 +08:00
|
|
|
clsDeclared = ClassDecl;
|
|
|
|
return I;
|
|
|
|
}
|
2010-06-23 07:20:40 +08:00
|
|
|
}
|
2010-02-23 09:26:30 +08:00
|
|
|
|
2009-02-21 04:59:54 +08:00
|
|
|
ClassDecl = ClassDecl->getSuperClass();
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2009-05-23 01:12:32 +08:00
|
|
|
/// lookupInheritedClass - This method returns ObjCInterfaceDecl * of the super
|
|
|
|
/// class whose name is passed as argument. If it is not one of the super classes
|
|
|
|
/// the it returns NULL.
|
|
|
|
ObjCInterfaceDecl *ObjCInterfaceDecl::lookupInheritedClass(
|
|
|
|
const IdentifierInfo*ICName) {
|
2011-12-15 13:27:12 +08:00
|
|
|
// FIXME: Should make sure no callers ever do this.
|
|
|
|
if (!hasDefinition())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (data().ExternallyCompleted)
|
2011-10-19 10:25:16 +08:00
|
|
|
LoadExternalDefinition();
|
|
|
|
|
2009-05-23 01:12:32 +08:00
|
|
|
ObjCInterfaceDecl* ClassDecl = this;
|
|
|
|
while (ClassDecl != NULL) {
|
|
|
|
if (ClassDecl->getIdentifier() == ICName)
|
|
|
|
return ClassDecl;
|
|
|
|
ClassDecl = ClassDecl->getSuperClass();
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-07-11 05:30:22 +08:00
|
|
|
ObjCProtocolDecl *
|
|
|
|
ObjCInterfaceDecl::lookupNestedProtocol(IdentifierInfo *Name) {
|
|
|
|
for (ObjCInterfaceDecl::all_protocol_iterator P =
|
|
|
|
all_referenced_protocol_begin(), PE = all_referenced_protocol_end();
|
|
|
|
P != PE; ++P)
|
|
|
|
if ((*P)->lookupProtocolNamed(Name))
|
|
|
|
return (*P);
|
|
|
|
ObjCInterfaceDecl *SuperClass = getSuperClass();
|
|
|
|
return SuperClass ? SuperClass->lookupNestedProtocol(Name) : NULL;
|
|
|
|
}
|
|
|
|
|
2009-07-26 06:15:51 +08:00
|
|
|
/// lookupMethod - This method returns an instance/class method by looking in
|
2009-02-21 04:59:54 +08:00
|
|
|
/// the class, its categories, and its super classes (using a linear search).
|
2013-04-26 05:59:34 +08:00
|
|
|
/// When argument category "C" is specified, any implicit method found
|
|
|
|
/// in this category is ignored.
|
2012-04-06 06:14:12 +08:00
|
|
|
ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel,
|
2013-11-23 09:01:29 +08:00
|
|
|
bool isInstance,
|
|
|
|
bool shallowCategoryLookup,
|
|
|
|
bool followSuper,
|
2013-12-11 03:43:48 +08:00
|
|
|
const ObjCCategoryDecl *C) const
|
2013-11-23 09:01:29 +08:00
|
|
|
{
|
2011-12-15 13:27:12 +08:00
|
|
|
// FIXME: Should make sure no callers ever do this.
|
|
|
|
if (!hasDefinition())
|
|
|
|
return 0;
|
|
|
|
|
2009-07-26 06:15:51 +08:00
|
|
|
const ObjCInterfaceDecl* ClassDecl = this;
|
2009-02-21 04:59:54 +08:00
|
|
|
ObjCMethodDecl *MethodDecl = 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-15 13:27:12 +08:00
|
|
|
if (data().ExternallyCompleted)
|
2010-12-02 07:49:52 +08:00
|
|
|
LoadExternalDefinition();
|
|
|
|
|
2013-11-23 09:01:29 +08:00
|
|
|
while (ClassDecl) {
|
2009-07-26 06:15:51 +08:00
|
|
|
if ((MethodDecl = ClassDecl->getMethod(Sel, isInstance)))
|
2009-02-21 04:59:54 +08:00
|
|
|
return MethodDecl;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-21 04:59:54 +08:00
|
|
|
// Didn't find one yet - look through protocols.
|
2012-03-13 09:09:41 +08:00
|
|
|
for (ObjCInterfaceDecl::protocol_iterator I = ClassDecl->protocol_begin(),
|
|
|
|
E = ClassDecl->protocol_end();
|
|
|
|
I != E; ++I)
|
2009-07-26 06:15:51 +08:00
|
|
|
if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance)))
|
2009-02-21 04:59:54 +08:00
|
|
|
return MethodDecl;
|
2012-04-06 06:14:12 +08:00
|
|
|
|
|
|
|
// Didn't find one yet - now look through categories.
|
2013-04-26 05:59:34 +08:00
|
|
|
for (ObjCInterfaceDecl::visible_categories_iterator
|
|
|
|
Cat = ClassDecl->visible_categories_begin(),
|
|
|
|
CatEnd = ClassDecl->visible_categories_end();
|
|
|
|
Cat != CatEnd; ++Cat) {
|
|
|
|
if ((MethodDecl = Cat->getMethod(Sel, isInstance)))
|
|
|
|
if (C != (*Cat) || !MethodDecl->isImplicit())
|
2013-04-25 01:06:38 +08:00
|
|
|
return MethodDecl;
|
|
|
|
|
2013-04-26 05:59:34 +08:00
|
|
|
if (!shallowCategoryLookup) {
|
|
|
|
// Didn't find one yet - look through protocols.
|
|
|
|
const ObjCList<ObjCProtocolDecl> &Protocols =
|
|
|
|
Cat->getReferencedProtocols();
|
|
|
|
for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
|
|
|
|
E = Protocols.end(); I != E; ++I)
|
|
|
|
if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance)))
|
|
|
|
if (C != (*Cat) || !MethodDecl->isImplicit())
|
2013-04-25 01:06:38 +08:00
|
|
|
return MethodDecl;
|
2012-02-10 05:30:24 +08:00
|
|
|
}
|
2013-04-26 05:59:34 +08:00
|
|
|
}
|
2013-11-23 09:01:29 +08:00
|
|
|
|
|
|
|
if (!followSuper)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
// Get the super class (if any).
|
2009-02-21 04:59:54 +08:00
|
|
|
ClassDecl = ClassDecl->getSuperClass();
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-07-28 03:07:44 +08:00
|
|
|
// Will search "local" class/category implementations for a method decl.
|
|
|
|
// If failed, then we search in class's root for an instance method.
|
|
|
|
// Returns 0 if no method is found.
|
2010-12-04 07:37:08 +08:00
|
|
|
ObjCMethodDecl *ObjCInterfaceDecl::lookupPrivateMethod(
|
|
|
|
const Selector &Sel,
|
2012-07-31 04:31:21 +08:00
|
|
|
bool Instance) const {
|
2011-12-15 13:27:12 +08:00
|
|
|
// FIXME: Should make sure no callers ever do this.
|
|
|
|
if (!hasDefinition())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (data().ExternallyCompleted)
|
2011-10-19 10:25:16 +08:00
|
|
|
LoadExternalDefinition();
|
|
|
|
|
2009-10-02 07:46:04 +08:00
|
|
|
ObjCMethodDecl *Method = 0;
|
|
|
|
if (ObjCImplementationDecl *ImpDecl = getImplementation())
|
2010-12-04 07:37:08 +08:00
|
|
|
Method = Instance ? ImpDecl->getInstanceMethod(Sel)
|
|
|
|
: ImpDecl->getClassMethod(Sel);
|
2012-07-28 03:07:44 +08:00
|
|
|
|
|
|
|
// Look through local category implementations associated with the class.
|
|
|
|
if (!Method)
|
|
|
|
Method = Instance ? getCategoryInstanceMethod(Sel)
|
|
|
|
: getCategoryClassMethod(Sel);
|
|
|
|
|
|
|
|
// Before we give up, check if the selector is an instance method.
|
|
|
|
// But only in the root. This matches gcc's behavior and what the
|
|
|
|
// runtime expects.
|
|
|
|
if (!Instance && !Method && !getSuperClass()) {
|
|
|
|
Method = lookupInstanceMethod(Sel);
|
|
|
|
// Look through local category implementations associated
|
|
|
|
// with the root class.
|
|
|
|
if (!Method)
|
|
|
|
Method = lookupPrivateMethod(Sel, true);
|
|
|
|
}
|
|
|
|
|
2009-10-02 07:46:04 +08:00
|
|
|
if (!Method && getSuperClass())
|
2010-12-04 07:37:08 +08:00
|
|
|
return getSuperClass()->lookupPrivateMethod(Sel, Instance);
|
2009-10-02 07:46:04 +08:00
|
|
|
return Method;
|
|
|
|
}
|
2009-02-21 04:59:54 +08:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// ObjCMethodDecl
|
2008-03-16 08:49:28 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2008-04-04 14:12:32 +08:00
|
|
|
ObjCMethodDecl *ObjCMethodDecl::Create(ASTContext &C,
|
2009-09-09 23:08:12 +08:00
|
|
|
SourceLocation beginLoc,
|
2008-03-16 08:49:28 +08:00
|
|
|
SourceLocation endLoc,
|
|
|
|
Selector SelInfo, QualType T,
|
2010-03-08 22:59:44 +08:00
|
|
|
TypeSourceInfo *ResultTInfo,
|
2009-01-09 01:28:14 +08:00
|
|
|
DeclContext *contextDecl,
|
2008-08-21 02:02:42 +08:00
|
|
|
bool isInstance,
|
2008-03-16 08:49:28 +08:00
|
|
|
bool isVariadic,
|
2012-10-11 00:42:25 +08:00
|
|
|
bool isPropertyAccessor,
|
2011-08-18 03:25:08 +08:00
|
|
|
bool isImplicitlyDeclared,
|
2010-07-23 02:24:20 +08:00
|
|
|
bool isDefined,
|
2010-04-09 05:29:11 +08:00
|
|
|
ImplementationControl impControl,
|
2011-10-03 14:36:29 +08:00
|
|
|
bool HasRelatedResultType) {
|
2013-11-22 17:01:48 +08:00
|
|
|
return new (C, contextDecl) ObjCMethodDecl(
|
|
|
|
beginLoc, endLoc, SelInfo, T, ResultTInfo, contextDecl, isInstance,
|
|
|
|
isVariadic, isPropertyAccessor, isImplicitlyDeclared, isDefined,
|
|
|
|
impControl, HasRelatedResultType);
|
2008-03-16 09:15:50 +08:00
|
|
|
}
|
|
|
|
|
2012-01-06 05:55:30 +08:00
|
|
|
ObjCMethodDecl *ObjCMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
2013-11-22 17:01:48 +08:00
|
|
|
return new (C, ID) ObjCMethodDecl(SourceLocation(), SourceLocation(),
|
|
|
|
Selector(), QualType(), 0, 0);
|
2012-01-06 05:55:30 +08:00
|
|
|
}
|
|
|
|
|
2013-12-04 05:11:36 +08:00
|
|
|
bool ObjCMethodDecl::isThisDeclarationADesignatedInitializer() const {
|
|
|
|
return getMethodFamily() == OMF_init &&
|
|
|
|
hasAttr<ObjCDesignatedInitializerAttr>();
|
|
|
|
}
|
|
|
|
|
2013-12-04 05:11:43 +08:00
|
|
|
bool ObjCMethodDecl::isDesignatedInitializerForTheInterface(
|
|
|
|
const ObjCMethodDecl **InitMethod) const {
|
|
|
|
if (getMethodFamily() != OMF_init)
|
|
|
|
return false;
|
2013-12-04 05:11:36 +08:00
|
|
|
const DeclContext *DC = getDeclContext();
|
|
|
|
if (isa<ObjCProtocolDecl>(DC))
|
|
|
|
return false;
|
|
|
|
if (const ObjCInterfaceDecl *ID = getClassInterface())
|
2013-12-04 05:11:43 +08:00
|
|
|
return ID->isDesignatedInitializer(getSelector(), InitMethod);
|
2013-12-04 05:11:36 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-10-10 01:21:28 +08:00
|
|
|
Stmt *ObjCMethodDecl::getBody() const {
|
|
|
|
return Body.get(getASTContext().getExternalSource());
|
|
|
|
}
|
|
|
|
|
2011-10-14 16:02:31 +08:00
|
|
|
void ObjCMethodDecl::setAsRedeclaration(const ObjCMethodDecl *PrevMethod) {
|
|
|
|
assert(PrevMethod);
|
|
|
|
getASTContext().setObjCMethodRedeclaration(PrevMethod, this);
|
|
|
|
IsRedeclaration = true;
|
2011-10-15 01:41:52 +08:00
|
|
|
PrevMethod->HasRedeclaration = true;
|
2011-10-14 16:02:31 +08:00
|
|
|
}
|
|
|
|
|
2011-10-03 14:37:04 +08:00
|
|
|
void ObjCMethodDecl::setParamsAndSelLocs(ASTContext &C,
|
|
|
|
ArrayRef<ParmVarDecl*> Params,
|
|
|
|
ArrayRef<SourceLocation> SelLocs) {
|
|
|
|
ParamsAndSelLocs = 0;
|
|
|
|
NumParams = Params.size();
|
|
|
|
if (Params.empty() && SelLocs.empty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
unsigned Size = sizeof(ParmVarDecl *) * NumParams +
|
|
|
|
sizeof(SourceLocation) * SelLocs.size();
|
|
|
|
ParamsAndSelLocs = C.Allocate(Size);
|
|
|
|
std::copy(Params.begin(), Params.end(), getParams());
|
|
|
|
std::copy(SelLocs.begin(), SelLocs.end(), getStoredSelLocs());
|
|
|
|
}
|
|
|
|
|
|
|
|
void ObjCMethodDecl::getSelectorLocs(
|
|
|
|
SmallVectorImpl<SourceLocation> &SelLocs) const {
|
|
|
|
for (unsigned i = 0, e = getNumSelectorLocs(); i != e; ++i)
|
|
|
|
SelLocs.push_back(getSelectorLoc(i));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ObjCMethodDecl::setMethodParams(ASTContext &C,
|
|
|
|
ArrayRef<ParmVarDecl*> Params,
|
|
|
|
ArrayRef<SourceLocation> SelLocs) {
|
|
|
|
assert((!SelLocs.empty() || isImplicit()) &&
|
|
|
|
"No selector locs for non-implicit method");
|
|
|
|
if (isImplicit())
|
2013-05-05 08:41:58 +08:00
|
|
|
return setParamsAndSelLocs(C, Params, llvm::None);
|
2011-10-03 14:37:04 +08:00
|
|
|
|
2012-06-16 08:46:02 +08:00
|
|
|
SelLocsKind = hasStandardSelectorLocs(getSelector(), SelLocs, Params,
|
|
|
|
DeclEndLoc);
|
2011-10-03 14:37:04 +08:00
|
|
|
if (SelLocsKind != SelLoc_NonStandard)
|
2013-05-05 08:41:58 +08:00
|
|
|
return setParamsAndSelLocs(C, Params, llvm::None);
|
2011-10-03 14:37:04 +08:00
|
|
|
|
|
|
|
setParamsAndSelLocs(C, Params, SelLocs);
|
|
|
|
}
|
|
|
|
|
2009-07-21 08:06:36 +08:00
|
|
|
/// \brief A definition will return its interface declaration.
|
|
|
|
/// An interface declaration will return its definition.
|
|
|
|
/// Otherwise it will return itself.
|
|
|
|
ObjCMethodDecl *ObjCMethodDecl::getNextRedeclaration() {
|
|
|
|
ASTContext &Ctx = getASTContext();
|
2011-10-15 01:41:52 +08:00
|
|
|
ObjCMethodDecl *Redecl = 0;
|
|
|
|
if (HasRedeclaration)
|
|
|
|
Redecl = const_cast<ObjCMethodDecl*>(Ctx.getObjCMethodRedeclaration(this));
|
2011-10-14 14:48:06 +08:00
|
|
|
if (Redecl)
|
|
|
|
return Redecl;
|
|
|
|
|
2009-07-21 08:06:36 +08:00
|
|
|
Decl *CtxD = cast<Decl>(getDeclContext());
|
|
|
|
|
2013-05-31 02:53:21 +08:00
|
|
|
if (!CtxD->isInvalidDecl()) {
|
|
|
|
if (ObjCInterfaceDecl *IFD = dyn_cast<ObjCInterfaceDecl>(CtxD)) {
|
|
|
|
if (ObjCImplementationDecl *ImplD = Ctx.getObjCImplementation(IFD))
|
|
|
|
if (!ImplD->isInvalidDecl())
|
|
|
|
Redecl = ImplD->getMethod(getSelector(), isInstanceMethod());
|
|
|
|
|
|
|
|
} else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(CtxD)) {
|
|
|
|
if (ObjCCategoryImplDecl *ImplD = Ctx.getObjCImplementation(CD))
|
|
|
|
if (!ImplD->isInvalidDecl())
|
|
|
|
Redecl = ImplD->getMethod(getSelector(), isInstanceMethod());
|
|
|
|
|
|
|
|
} else if (ObjCImplementationDecl *ImplD =
|
|
|
|
dyn_cast<ObjCImplementationDecl>(CtxD)) {
|
|
|
|
if (ObjCInterfaceDecl *IFD = ImplD->getClassInterface())
|
|
|
|
if (!IFD->isInvalidDecl())
|
|
|
|
Redecl = IFD->getMethod(getSelector(), isInstanceMethod());
|
|
|
|
|
|
|
|
} else if (ObjCCategoryImplDecl *CImplD =
|
|
|
|
dyn_cast<ObjCCategoryImplDecl>(CtxD)) {
|
|
|
|
if (ObjCCategoryDecl *CatD = CImplD->getCategoryDecl())
|
|
|
|
if (!CatD->isInvalidDecl())
|
|
|
|
Redecl = CatD->getMethod(getSelector(), isInstanceMethod());
|
|
|
|
}
|
2009-07-21 08:06:36 +08:00
|
|
|
}
|
|
|
|
|
2011-10-14 16:02:31 +08:00
|
|
|
if (!Redecl && isRedeclaration()) {
|
|
|
|
// This is the last redeclaration, go back to the first method.
|
|
|
|
return cast<ObjCContainerDecl>(CtxD)->getMethod(getSelector(),
|
|
|
|
isInstanceMethod());
|
|
|
|
}
|
|
|
|
|
2009-07-21 08:06:36 +08:00
|
|
|
return Redecl ? Redecl : this;
|
|
|
|
}
|
|
|
|
|
2009-07-28 13:11:17 +08:00
|
|
|
ObjCMethodDecl *ObjCMethodDecl::getCanonicalDecl() {
|
|
|
|
Decl *CtxD = cast<Decl>(getDeclContext());
|
|
|
|
|
|
|
|
if (ObjCImplementationDecl *ImplD = dyn_cast<ObjCImplementationDecl>(CtxD)) {
|
|
|
|
if (ObjCInterfaceDecl *IFD = ImplD->getClassInterface())
|
|
|
|
if (ObjCMethodDecl *MD = IFD->getMethod(getSelector(),
|
|
|
|
isInstanceMethod()))
|
|
|
|
return MD;
|
|
|
|
|
|
|
|
} else if (ObjCCategoryImplDecl *CImplD =
|
|
|
|
dyn_cast<ObjCCategoryImplDecl>(CtxD)) {
|
2009-10-30 05:11:04 +08:00
|
|
|
if (ObjCCategoryDecl *CatD = CImplD->getCategoryDecl())
|
2009-07-28 13:11:17 +08:00
|
|
|
if (ObjCMethodDecl *MD = CatD->getMethod(getSelector(),
|
|
|
|
isInstanceMethod()))
|
|
|
|
return MD;
|
|
|
|
}
|
|
|
|
|
2011-10-18 03:48:09 +08:00
|
|
|
if (isRedeclaration())
|
|
|
|
return cast<ObjCContainerDecl>(CtxD)->getMethod(getSelector(),
|
|
|
|
isInstanceMethod());
|
|
|
|
|
2009-07-28 13:11:17 +08:00
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2012-06-16 08:46:02 +08:00
|
|
|
SourceLocation ObjCMethodDecl::getLocEnd() const {
|
|
|
|
if (Stmt *Body = getBody())
|
|
|
|
return Body->getLocEnd();
|
|
|
|
return DeclEndLoc;
|
|
|
|
}
|
|
|
|
|
2011-03-02 09:50:55 +08:00
|
|
|
ObjCMethodFamily ObjCMethodDecl::getMethodFamily() const {
|
|
|
|
ObjCMethodFamily family = static_cast<ObjCMethodFamily>(Family);
|
2011-03-03 05:01:41 +08:00
|
|
|
if (family != static_cast<unsigned>(InvalidObjCMethodFamily))
|
2011-03-02 09:50:55 +08:00
|
|
|
return family;
|
|
|
|
|
2011-03-02 19:33:24 +08:00
|
|
|
// Check for an explicit attribute.
|
|
|
|
if (const ObjCMethodFamilyAttr *attr = getAttr<ObjCMethodFamilyAttr>()) {
|
|
|
|
// The unfortunate necessity of mapping between enums here is due
|
|
|
|
// to the attributes framework.
|
|
|
|
switch (attr->getFamily()) {
|
|
|
|
case ObjCMethodFamilyAttr::OMF_None: family = OMF_None; break;
|
|
|
|
case ObjCMethodFamilyAttr::OMF_alloc: family = OMF_alloc; break;
|
|
|
|
case ObjCMethodFamilyAttr::OMF_copy: family = OMF_copy; break;
|
|
|
|
case ObjCMethodFamilyAttr::OMF_init: family = OMF_init; break;
|
|
|
|
case ObjCMethodFamilyAttr::OMF_mutableCopy: family = OMF_mutableCopy; break;
|
|
|
|
case ObjCMethodFamilyAttr::OMF_new: family = OMF_new; break;
|
|
|
|
}
|
|
|
|
Family = static_cast<unsigned>(family);
|
|
|
|
return family;
|
|
|
|
}
|
|
|
|
|
2011-03-02 09:50:55 +08:00
|
|
|
family = getSelector().getMethodFamily();
|
|
|
|
switch (family) {
|
|
|
|
case OMF_None: break;
|
|
|
|
|
|
|
|
// init only has a conventional meaning for an instance method, and
|
|
|
|
// it has to return an object.
|
|
|
|
case OMF_init:
|
|
|
|
if (!isInstanceMethod() || !getResultType()->isObjCObjectPointerType())
|
|
|
|
family = OMF_None;
|
|
|
|
break;
|
|
|
|
|
|
|
|
// alloc/copy/new have a conventional meaning for both class and
|
|
|
|
// instance methods, but they require an object return.
|
|
|
|
case OMF_alloc:
|
|
|
|
case OMF_copy:
|
|
|
|
case OMF_mutableCopy:
|
|
|
|
case OMF_new:
|
|
|
|
if (!getResultType()->isObjCObjectPointerType())
|
|
|
|
family = OMF_None;
|
|
|
|
break;
|
|
|
|
|
|
|
|
// These selectors have a conventional meaning only for instance methods.
|
|
|
|
case OMF_dealloc:
|
2011-08-29 06:35:17 +08:00
|
|
|
case OMF_finalize:
|
2011-03-02 09:50:55 +08:00
|
|
|
case OMF_retain:
|
|
|
|
case OMF_release:
|
|
|
|
case OMF_autorelease:
|
|
|
|
case OMF_retainCount:
|
2011-06-11 09:09:30 +08:00
|
|
|
case OMF_self:
|
2011-03-02 09:50:55 +08:00
|
|
|
if (!isInstanceMethod())
|
|
|
|
family = OMF_None;
|
|
|
|
break;
|
2011-07-06 06:38:59 +08:00
|
|
|
|
|
|
|
case OMF_performSelector:
|
|
|
|
if (!isInstanceMethod() ||
|
|
|
|
!getResultType()->isObjCIdType())
|
|
|
|
family = OMF_None;
|
|
|
|
else {
|
|
|
|
unsigned noParams = param_size();
|
|
|
|
if (noParams < 1 || noParams > 3)
|
|
|
|
family = OMF_None;
|
|
|
|
else {
|
2014-01-21 04:26:09 +08:00
|
|
|
ObjCMethodDecl::param_type_iterator it = arg_type_begin();
|
2011-07-06 06:38:59 +08:00
|
|
|
QualType ArgT = (*it);
|
|
|
|
if (!ArgT->isObjCSelType()) {
|
|
|
|
family = OMF_None;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
while (--noParams) {
|
|
|
|
it++;
|
|
|
|
ArgT = (*it);
|
|
|
|
if (!ArgT->isObjCIdType()) {
|
|
|
|
family = OMF_None;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2011-03-02 09:50:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Cache the result.
|
|
|
|
Family = static_cast<unsigned>(family);
|
|
|
|
return family;
|
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
void ObjCMethodDecl::createImplicitParams(ASTContext &Context,
|
2009-02-21 04:59:54 +08:00
|
|
|
const ObjCInterfaceDecl *OID) {
|
|
|
|
QualType selfTy;
|
|
|
|
if (isInstanceMethod()) {
|
|
|
|
// There may be no interface context due to error in declaration
|
|
|
|
// of the interface (which has been reported). Recover gracefully.
|
|
|
|
if (OID) {
|
2009-04-22 12:34:53 +08:00
|
|
|
selfTy = Context.getObjCInterfaceType(OID);
|
2009-07-11 07:34:53 +08:00
|
|
|
selfTy = Context.getObjCObjectPointerType(selfTy);
|
2009-02-21 04:59:54 +08:00
|
|
|
} else {
|
|
|
|
selfTy = Context.getObjCIdType();
|
|
|
|
}
|
|
|
|
} else // we have a factory method.
|
|
|
|
selfTy = Context.getObjCClassType();
|
|
|
|
|
2011-06-17 14:42:21 +08:00
|
|
|
bool selfIsPseudoStrong = false;
|
2011-06-16 07:02:42 +08:00
|
|
|
bool selfIsConsumed = false;
|
2011-11-15 05:59:25 +08:00
|
|
|
|
2012-03-11 15:00:24 +08:00
|
|
|
if (Context.getLangOpts().ObjCAutoRefCount) {
|
2011-11-15 05:59:25 +08:00
|
|
|
if (isInstanceMethod()) {
|
|
|
|
selfIsConsumed = hasAttr<NSConsumesSelfAttr>();
|
|
|
|
|
|
|
|
// 'self' is always __strong. It's actually pseudo-strong except
|
|
|
|
// in init methods (or methods labeled ns_consumes_self), though.
|
|
|
|
Qualifiers qs;
|
|
|
|
qs.setObjCLifetime(Qualifiers::OCL_Strong);
|
|
|
|
selfTy = Context.getQualifiedType(selfTy, qs);
|
|
|
|
|
|
|
|
// In addition, 'self' is const unless this is an init method.
|
|
|
|
if (getMethodFamily() != OMF_init && !selfIsConsumed) {
|
|
|
|
selfTy = selfTy.withConst();
|
|
|
|
selfIsPseudoStrong = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
assert(isClassMethod());
|
|
|
|
// 'self' is always const in class methods.
|
2011-06-16 07:02:42 +08:00
|
|
|
selfTy = selfTy.withConst();
|
2011-06-17 14:42:21 +08:00
|
|
|
selfIsPseudoStrong = true;
|
|
|
|
}
|
2011-06-16 07:02:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ImplicitParamDecl *self
|
|
|
|
= ImplicitParamDecl::Create(Context, this, SourceLocation(),
|
|
|
|
&Context.Idents.get("self"), selfTy);
|
|
|
|
setSelfDecl(self);
|
|
|
|
|
|
|
|
if (selfIsConsumed)
|
2014-01-16 21:03:14 +08:00
|
|
|
self->addAttr(NSConsumedAttr::CreateImplicit(Context));
|
2009-02-21 04:59:54 +08:00
|
|
|
|
2011-06-17 14:42:21 +08:00
|
|
|
if (selfIsPseudoStrong)
|
|
|
|
self->setARCPseudoStrong(true);
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
setCmdDecl(ImplicitParamDecl::Create(Context, this, SourceLocation(),
|
|
|
|
&Context.Idents.get("_cmd"),
|
2009-04-20 23:06:07 +08:00
|
|
|
Context.getObjCSelType()));
|
2009-02-21 04:59:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ObjCInterfaceDecl *ObjCMethodDecl::getClassInterface() {
|
|
|
|
if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(getDeclContext()))
|
|
|
|
return ID;
|
|
|
|
if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(getDeclContext()))
|
|
|
|
return CD->getClassInterface();
|
2009-07-28 13:10:52 +08:00
|
|
|
if (ObjCImplDecl *IMD = dyn_cast<ObjCImplDecl>(getDeclContext()))
|
2009-02-21 04:59:54 +08:00
|
|
|
return IMD->getClassInterface();
|
2009-07-28 13:10:52 +08:00
|
|
|
|
|
|
|
assert(!isa<ObjCProtocolDecl>(getDeclContext()) && "It's a protocol method");
|
2011-09-23 13:06:16 +08:00
|
|
|
llvm_unreachable("unknown method context");
|
2009-02-21 04:59:54 +08:00
|
|
|
}
|
|
|
|
|
2012-10-10 02:19:01 +08:00
|
|
|
static void CollectOverriddenMethodsRecurse(const ObjCContainerDecl *Container,
|
|
|
|
const ObjCMethodDecl *Method,
|
|
|
|
SmallVectorImpl<const ObjCMethodDecl *> &Methods,
|
|
|
|
bool MovedToSuper) {
|
|
|
|
if (!Container)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// In categories look for overriden methods from protocols. A method from
|
|
|
|
// category is not "overriden" since it is considered as the "same" method
|
|
|
|
// (same USR) as the one from the interface.
|
|
|
|
if (const ObjCCategoryDecl *
|
|
|
|
Category = dyn_cast<ObjCCategoryDecl>(Container)) {
|
|
|
|
// Check whether we have a matching method at this category but only if we
|
|
|
|
// are at the super class level.
|
|
|
|
if (MovedToSuper)
|
|
|
|
if (ObjCMethodDecl *
|
|
|
|
Overridden = Container->getMethod(Method->getSelector(),
|
2013-03-30 05:51:48 +08:00
|
|
|
Method->isInstanceMethod(),
|
|
|
|
/*AllowHidden=*/true))
|
2012-10-10 02:19:01 +08:00
|
|
|
if (Method != Overridden) {
|
|
|
|
// We found an override at this category; there is no need to look
|
|
|
|
// into its protocols.
|
|
|
|
Methods.push_back(Overridden);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(),
|
|
|
|
PEnd = Category->protocol_end();
|
|
|
|
P != PEnd; ++P)
|
|
|
|
CollectOverriddenMethodsRecurse(*P, Method, Methods, MovedToSuper);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check whether we have a matching method at this level.
|
|
|
|
if (const ObjCMethodDecl *
|
|
|
|
Overridden = Container->getMethod(Method->getSelector(),
|
2013-03-30 05:51:48 +08:00
|
|
|
Method->isInstanceMethod(),
|
|
|
|
/*AllowHidden=*/true))
|
2012-10-10 02:19:01 +08:00
|
|
|
if (Method != Overridden) {
|
|
|
|
// We found an override at this level; there is no need to look
|
|
|
|
// into other protocols or categories.
|
|
|
|
Methods.push_back(Overridden);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (const ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)){
|
|
|
|
for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(),
|
|
|
|
PEnd = Protocol->protocol_end();
|
|
|
|
P != PEnd; ++P)
|
|
|
|
CollectOverriddenMethodsRecurse(*P, Method, Methods, MovedToSuper);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (const ObjCInterfaceDecl *
|
|
|
|
Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
|
|
|
|
for (ObjCInterfaceDecl::protocol_iterator P = Interface->protocol_begin(),
|
|
|
|
PEnd = Interface->protocol_end();
|
|
|
|
P != PEnd; ++P)
|
|
|
|
CollectOverriddenMethodsRecurse(*P, Method, Methods, MovedToSuper);
|
|
|
|
|
2013-03-30 05:51:48 +08:00
|
|
|
for (ObjCInterfaceDecl::known_categories_iterator
|
|
|
|
Cat = Interface->known_categories_begin(),
|
|
|
|
CatEnd = Interface->known_categories_end();
|
2013-01-17 07:00:23 +08:00
|
|
|
Cat != CatEnd; ++Cat) {
|
|
|
|
CollectOverriddenMethodsRecurse(*Cat, Method, Methods,
|
2012-10-10 02:19:01 +08:00
|
|
|
MovedToSuper);
|
2013-01-17 07:00:23 +08:00
|
|
|
}
|
2012-10-10 02:19:01 +08:00
|
|
|
|
|
|
|
if (const ObjCInterfaceDecl *Super = Interface->getSuperClass())
|
|
|
|
return CollectOverriddenMethodsRecurse(Super, Method, Methods,
|
|
|
|
/*MovedToSuper=*/true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void CollectOverriddenMethods(const ObjCContainerDecl *Container,
|
|
|
|
const ObjCMethodDecl *Method,
|
|
|
|
SmallVectorImpl<const ObjCMethodDecl *> &Methods) {
|
|
|
|
CollectOverriddenMethodsRecurse(Container, Method, Methods,
|
|
|
|
/*MovedToSuper=*/false);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void collectOverriddenMethodsSlow(const ObjCMethodDecl *Method,
|
|
|
|
SmallVectorImpl<const ObjCMethodDecl *> &overridden) {
|
|
|
|
assert(Method->isOverriding());
|
|
|
|
|
|
|
|
if (const ObjCProtocolDecl *
|
|
|
|
ProtD = dyn_cast<ObjCProtocolDecl>(Method->getDeclContext())) {
|
|
|
|
CollectOverriddenMethods(ProtD, Method, overridden);
|
|
|
|
|
|
|
|
} else if (const ObjCImplDecl *
|
|
|
|
IMD = dyn_cast<ObjCImplDecl>(Method->getDeclContext())) {
|
|
|
|
const ObjCInterfaceDecl *ID = IMD->getClassInterface();
|
|
|
|
if (!ID)
|
|
|
|
return;
|
|
|
|
// Start searching for overridden methods using the method from the
|
|
|
|
// interface as starting point.
|
|
|
|
if (const ObjCMethodDecl *IFaceMeth = ID->getMethod(Method->getSelector(),
|
2013-03-30 05:51:48 +08:00
|
|
|
Method->isInstanceMethod(),
|
|
|
|
/*AllowHidden=*/true))
|
2012-10-10 02:19:01 +08:00
|
|
|
Method = IFaceMeth;
|
|
|
|
CollectOverriddenMethods(ID, Method, overridden);
|
|
|
|
|
|
|
|
} else if (const ObjCCategoryDecl *
|
|
|
|
CatD = dyn_cast<ObjCCategoryDecl>(Method->getDeclContext())) {
|
|
|
|
const ObjCInterfaceDecl *ID = CatD->getClassInterface();
|
|
|
|
if (!ID)
|
|
|
|
return;
|
|
|
|
// Start searching for overridden methods using the method from the
|
|
|
|
// interface as starting point.
|
|
|
|
if (const ObjCMethodDecl *IFaceMeth = ID->getMethod(Method->getSelector(),
|
2013-03-30 05:51:48 +08:00
|
|
|
Method->isInstanceMethod(),
|
|
|
|
/*AllowHidden=*/true))
|
2012-10-10 02:19:01 +08:00
|
|
|
Method = IFaceMeth;
|
|
|
|
CollectOverriddenMethods(ID, Method, overridden);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
CollectOverriddenMethods(
|
|
|
|
dyn_cast_or_null<ObjCContainerDecl>(Method->getDeclContext()),
|
|
|
|
Method, overridden);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ObjCMethodDecl::getOverriddenMethods(
|
|
|
|
SmallVectorImpl<const ObjCMethodDecl *> &Overridden) const {
|
|
|
|
const ObjCMethodDecl *Method = this;
|
|
|
|
|
|
|
|
if (Method->isRedeclaration()) {
|
|
|
|
Method = cast<ObjCContainerDecl>(Method->getDeclContext())->
|
|
|
|
getMethod(Method->getSelector(), Method->isInstanceMethod());
|
|
|
|
}
|
|
|
|
|
2013-04-17 08:09:08 +08:00
|
|
|
if (Method->isOverriding()) {
|
2012-10-10 02:19:01 +08:00
|
|
|
collectOverriddenMethodsSlow(Method, Overridden);
|
|
|
|
assert(!Overridden.empty() &&
|
|
|
|
"ObjCMethodDecl's overriding bit is not as expected");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-11 00:42:54 +08:00
|
|
|
const ObjCPropertyDecl *
|
|
|
|
ObjCMethodDecl::findPropertyDecl(bool CheckOverrides) const {
|
|
|
|
Selector Sel = getSelector();
|
|
|
|
unsigned NumArgs = Sel.getNumArgs();
|
|
|
|
if (NumArgs > 1)
|
|
|
|
return 0;
|
|
|
|
|
2012-10-12 00:02:02 +08:00
|
|
|
if (!isInstanceMethod() || getMethodFamily() != OMF_None)
|
2012-10-11 00:42:54 +08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (isPropertyAccessor()) {
|
|
|
|
const ObjCContainerDecl *Container = cast<ObjCContainerDecl>(getParent());
|
2013-01-12 08:28:34 +08:00
|
|
|
// If container is class extension, find its primary class.
|
|
|
|
if (const ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(Container))
|
|
|
|
if (CatDecl->IsClassExtension())
|
|
|
|
Container = CatDecl->getClassInterface();
|
|
|
|
|
2012-10-11 00:42:54 +08:00
|
|
|
bool IsGetter = (NumArgs == 0);
|
|
|
|
|
|
|
|
for (ObjCContainerDecl::prop_iterator I = Container->prop_begin(),
|
|
|
|
E = Container->prop_end();
|
|
|
|
I != E; ++I) {
|
|
|
|
Selector NextSel = IsGetter ? (*I)->getGetterName()
|
|
|
|
: (*I)->getSetterName();
|
|
|
|
if (NextSel == Sel)
|
|
|
|
return *I;
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm_unreachable("Marked as a property accessor but no property found!");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!CheckOverrides)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
typedef SmallVector<const ObjCMethodDecl *, 8> OverridesTy;
|
|
|
|
OverridesTy Overrides;
|
|
|
|
getOverriddenMethods(Overrides);
|
|
|
|
for (OverridesTy::const_iterator I = Overrides.begin(), E = Overrides.end();
|
|
|
|
I != E; ++I) {
|
|
|
|
if (const ObjCPropertyDecl *Prop = (*I)->findPropertyDecl(false))
|
|
|
|
return Prop;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2009-02-21 04:59:54 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// ObjCInterfaceDecl
|
|
|
|
//===----------------------------------------------------------------------===//
|
2009-02-20 14:03:09 +08:00
|
|
|
|
2012-01-18 02:09:05 +08:00
|
|
|
ObjCInterfaceDecl *ObjCInterfaceDecl::Create(const ASTContext &C,
|
2009-01-09 08:49:46 +08:00
|
|
|
DeclContext *DC,
|
2008-04-04 14:12:32 +08:00
|
|
|
SourceLocation atLoc,
|
2009-09-09 23:08:12 +08:00
|
|
|
IdentifierInfo *Id,
|
2011-12-16 11:12:41 +08:00
|
|
|
ObjCInterfaceDecl *PrevDecl,
|
2008-04-12 03:35:35 +08:00
|
|
|
SourceLocation ClassLoc,
|
2011-12-16 04:29:51 +08:00
|
|
|
bool isInternal){
|
2013-11-22 17:01:48 +08:00
|
|
|
ObjCInterfaceDecl *Result = new (C, DC)
|
|
|
|
ObjCInterfaceDecl(DC, atLoc, Id, ClassLoc, PrevDecl, isInternal);
|
Ensure that type definitions present in just-loaded modules are
visible.
The basic problem here is that a given translation unit can use
forward declarations to form pointers to a given type, say,
class X;
X *x;
and then import a module that includes a definition of X:
import XDef;
We will then fail when attempting to access a member of X, e.g.,
x->method()
because the AST reader did not know to look for a default of a class
named X within the new module.
This implementation is a bit of a C-centric hack, because the only
definitions that can have this property are enums, structs, unions,
Objective-C classes, and Objective-C protocols, and all of those are
either visible at the top-level or can't be defined later. Hence, we
can use the out-of-date-ness of the name and the identifier-update
mechanism to force the update.
In C++, we will not be so lucky, and will need a more advanced
solution, because the definitions could be in namespaces defined in
two different modules, e.g.,
// module 1
namespace N { struct X; }
// module 2
namespace N { struct X { /* ... */ }; }
One possible implementation here is for C++ to extend the information
associated with each identifier table to include the declaration IDs
of any definitions associated with that name, regardless of
context. We would have to eagerly load those definitions.
llvm-svn: 174794
2013-02-09 09:35:03 +08:00
|
|
|
Result->Data.setInt(!C.getLangOpts().Modules);
|
2011-12-16 11:12:41 +08:00
|
|
|
C.getObjCInterfaceType(Result, PrevDecl);
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2013-11-22 17:01:48 +08:00
|
|
|
ObjCInterfaceDecl *ObjCInterfaceDecl::CreateDeserialized(ASTContext &C,
|
2012-01-06 05:55:30 +08:00
|
|
|
unsigned ID) {
|
2013-11-22 17:01:48 +08:00
|
|
|
ObjCInterfaceDecl *Result = new (C, ID) ObjCInterfaceDecl(0, SourceLocation(),
|
|
|
|
0, SourceLocation(),
|
|
|
|
0, false);
|
Ensure that type definitions present in just-loaded modules are
visible.
The basic problem here is that a given translation unit can use
forward declarations to form pointers to a given type, say,
class X;
X *x;
and then import a module that includes a definition of X:
import XDef;
We will then fail when attempting to access a member of X, e.g.,
x->method()
because the AST reader did not know to look for a default of a class
named X within the new module.
This implementation is a bit of a C-centric hack, because the only
definitions that can have this property are enums, structs, unions,
Objective-C classes, and Objective-C protocols, and all of those are
either visible at the top-level or can't be defined later. Hence, we
can use the out-of-date-ness of the name and the identifier-update
mechanism to force the update.
In C++, we will not be so lucky, and will need a more advanced
solution, because the definitions could be in namespaces defined in
two different modules, e.g.,
// module 1
namespace N { struct X; }
// module 2
namespace N { struct X { /* ... */ }; }
One possible implementation here is for C++ to extend the information
associated with each identifier table to include the declaration IDs
of any definitions associated with that name, regardless of
context. We would have to eagerly load those definitions.
llvm-svn: 174794
2013-02-09 09:35:03 +08:00
|
|
|
Result->Data.setInt(!C.getLangOpts().Modules);
|
|
|
|
return Result;
|
2008-03-16 09:15:50 +08:00
|
|
|
}
|
2008-03-16 08:49:28 +08:00
|
|
|
|
2009-02-20 14:03:09 +08:00
|
|
|
ObjCInterfaceDecl::
|
|
|
|
ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
|
2011-12-17 06:37:11 +08:00
|
|
|
SourceLocation CLoc, ObjCInterfaceDecl *PrevDecl,
|
|
|
|
bool isInternal)
|
2011-10-04 12:48:02 +08:00
|
|
|
: ObjCContainerDecl(ObjCInterface, DC, Id, CLoc, atLoc),
|
2011-12-16 04:29:51 +08:00
|
|
|
TypeForDecl(0), Data()
|
2011-12-15 13:27:12 +08:00
|
|
|
{
|
2013-10-17 23:37:26 +08:00
|
|
|
setPreviousDecl(PrevDecl);
|
2011-12-17 06:37:11 +08:00
|
|
|
|
|
|
|
// Copy the 'data' pointer over.
|
|
|
|
if (PrevDecl)
|
|
|
|
Data = PrevDecl->Data;
|
|
|
|
|
2011-11-15 14:20:21 +08:00
|
|
|
setImplicit(isInternal);
|
2009-01-08 01:57:40 +08:00
|
|
|
}
|
|
|
|
|
2010-12-02 07:49:52 +08:00
|
|
|
void ObjCInterfaceDecl::LoadExternalDefinition() const {
|
2011-12-15 13:27:12 +08:00
|
|
|
assert(data().ExternallyCompleted && "Class is not externally completed");
|
|
|
|
data().ExternallyCompleted = false;
|
2010-12-02 07:49:52 +08:00
|
|
|
getASTContext().getExternalSource()->CompleteType(
|
|
|
|
const_cast<ObjCInterfaceDecl *>(this));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ObjCInterfaceDecl::setExternallyCompleted() {
|
|
|
|
assert(getASTContext().getExternalSource() &&
|
|
|
|
"Class can't be externally completed without an external source");
|
2011-12-15 13:27:12 +08:00
|
|
|
assert(hasDefinition() &&
|
2010-12-02 07:49:52 +08:00
|
|
|
"Forward declarations can't be externally completed");
|
2011-12-15 13:27:12 +08:00
|
|
|
data().ExternallyCompleted = true;
|
2010-12-02 07:49:52 +08:00
|
|
|
}
|
|
|
|
|
2013-12-04 05:11:30 +08:00
|
|
|
void ObjCInterfaceDecl::setHasDesignatedInitializers() {
|
|
|
|
assert(hasDefinition() && "Forward declarations can't contain methods");
|
|
|
|
data().HasDesignatedInitializers = true;
|
|
|
|
}
|
|
|
|
|
2013-12-04 05:11:49 +08:00
|
|
|
bool ObjCInterfaceDecl::hasDesignatedInitializers() const {
|
|
|
|
assert(hasDefinition() && "Forward declarations can't contain methods");
|
|
|
|
if (data().ExternallyCompleted)
|
|
|
|
LoadExternalDefinition();
|
|
|
|
|
|
|
|
return data().HasDesignatedInitializers;
|
|
|
|
}
|
|
|
|
|
2009-07-21 08:05:53 +08:00
|
|
|
ObjCImplementationDecl *ObjCInterfaceDecl::getImplementation() const {
|
2011-12-16 04:29:51 +08:00
|
|
|
if (const ObjCInterfaceDecl *Def = getDefinition()) {
|
|
|
|
if (data().ExternallyCompleted)
|
|
|
|
LoadExternalDefinition();
|
|
|
|
|
|
|
|
return getASTContext().getObjCImplementation(
|
|
|
|
const_cast<ObjCInterfaceDecl*>(Def));
|
|
|
|
}
|
|
|
|
|
2011-12-15 13:27:12 +08:00
|
|
|
// FIXME: Should make sure no callers ever do this.
|
2011-12-16 04:29:51 +08:00
|
|
|
return 0;
|
2009-07-21 08:05:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void ObjCInterfaceDecl::setImplementation(ObjCImplementationDecl *ImplD) {
|
2011-12-16 04:29:51 +08:00
|
|
|
getASTContext().setObjCImplementation(getDefinition(), ImplD);
|
2009-07-21 08:05:53 +08:00
|
|
|
}
|
|
|
|
|
2013-02-14 06:50:36 +08:00
|
|
|
namespace {
|
|
|
|
struct SynthesizeIvarChunk {
|
|
|
|
uint64_t Size;
|
|
|
|
ObjCIvarDecl *Ivar;
|
|
|
|
SynthesizeIvarChunk(uint64_t size, ObjCIvarDecl *ivar)
|
|
|
|
: Size(size), Ivar(ivar) {}
|
|
|
|
};
|
|
|
|
|
|
|
|
bool operator<(const SynthesizeIvarChunk & LHS,
|
|
|
|
const SynthesizeIvarChunk &RHS) {
|
|
|
|
return LHS.Size < RHS.Size;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-08-21 05:21:08 +08:00
|
|
|
/// all_declared_ivar_begin - return first ivar declared in this class,
|
|
|
|
/// its extensions and its implementation. Lazily build the list on first
|
|
|
|
/// access.
|
2013-03-07 06:03:30 +08:00
|
|
|
///
|
|
|
|
/// Caveat: The list returned by this method reflects the current
|
|
|
|
/// state of the parser. The cache will be updated for every ivar
|
|
|
|
/// added by an extension or the implementation when they are
|
|
|
|
/// encountered.
|
|
|
|
/// See also ObjCIvarDecl::Create().
|
2010-08-21 05:21:08 +08:00
|
|
|
ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() {
|
2011-12-15 13:27:12 +08:00
|
|
|
// FIXME: Should make sure no callers ever do this.
|
|
|
|
if (!hasDefinition())
|
|
|
|
return 0;
|
|
|
|
|
2010-08-21 05:21:08 +08:00
|
|
|
ObjCIvarDecl *curIvar = 0;
|
2013-03-07 06:03:30 +08:00
|
|
|
if (!data().IvarList) {
|
|
|
|
if (!ivar_empty()) {
|
|
|
|
ObjCInterfaceDecl::ivar_iterator I = ivar_begin(), E = ivar_end();
|
|
|
|
data().IvarList = *I; ++I;
|
|
|
|
for (curIvar = data().IvarList; I != E; curIvar = *I, ++I)
|
|
|
|
curIvar->setNextIvar(*I);
|
|
|
|
}
|
2013-01-17 07:00:23 +08:00
|
|
|
|
2013-03-07 06:03:30 +08:00
|
|
|
for (ObjCInterfaceDecl::known_extensions_iterator
|
|
|
|
Ext = known_extensions_begin(),
|
|
|
|
ExtEnd = known_extensions_end();
|
|
|
|
Ext != ExtEnd; ++Ext) {
|
|
|
|
if (!Ext->ivar_empty()) {
|
|
|
|
ObjCCategoryDecl::ivar_iterator
|
|
|
|
I = Ext->ivar_begin(),
|
|
|
|
E = Ext->ivar_end();
|
|
|
|
if (!data().IvarList) {
|
|
|
|
data().IvarList = *I; ++I;
|
|
|
|
curIvar = data().IvarList;
|
|
|
|
}
|
|
|
|
for ( ;I != E; curIvar = *I, ++I)
|
|
|
|
curIvar->setNextIvar(*I);
|
2010-08-21 05:21:08 +08:00
|
|
|
}
|
|
|
|
}
|
2013-03-07 06:03:30 +08:00
|
|
|
data().IvarListMissingImplementation = true;
|
2010-08-21 05:21:08 +08:00
|
|
|
}
|
2013-03-07 06:03:30 +08:00
|
|
|
|
|
|
|
// cached and complete!
|
|
|
|
if (!data().IvarListMissingImplementation)
|
|
|
|
return data().IvarList;
|
2010-08-21 05:21:08 +08:00
|
|
|
|
|
|
|
if (ObjCImplementationDecl *ImplDecl = getImplementation()) {
|
2013-03-07 06:03:30 +08:00
|
|
|
data().IvarListMissingImplementation = false;
|
2010-08-21 05:21:08 +08:00
|
|
|
if (!ImplDecl->ivar_empty()) {
|
2013-02-14 06:50:36 +08:00
|
|
|
SmallVector<SynthesizeIvarChunk, 16> layout;
|
|
|
|
for (ObjCImplementationDecl::ivar_iterator I = ImplDecl->ivar_begin(),
|
|
|
|
E = ImplDecl->ivar_end(); I != E; ++I) {
|
|
|
|
ObjCIvarDecl *IV = *I;
|
|
|
|
if (IV->getSynthesize() && !IV->isInvalidDecl()) {
|
|
|
|
layout.push_back(SynthesizeIvarChunk(
|
|
|
|
IV->getASTContext().getTypeSize(IV->getType()), IV));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!data().IvarList)
|
|
|
|
data().IvarList = *I;
|
|
|
|
else
|
|
|
|
curIvar->setNextIvar(*I);
|
|
|
|
curIvar = *I;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!layout.empty()) {
|
|
|
|
// Order synthesized ivars by their size.
|
|
|
|
std::stable_sort(layout.begin(), layout.end());
|
|
|
|
unsigned Ix = 0, EIx = layout.size();
|
|
|
|
if (!data().IvarList) {
|
|
|
|
data().IvarList = layout[0].Ivar; Ix++;
|
|
|
|
curIvar = data().IvarList;
|
|
|
|
}
|
|
|
|
for ( ; Ix != EIx; curIvar = layout[Ix].Ivar, Ix++)
|
|
|
|
curIvar->setNextIvar(layout[Ix].Ivar);
|
2010-08-21 05:21:08 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-12-15 13:27:12 +08:00
|
|
|
return data().IvarList;
|
2010-08-21 05:21:08 +08:00
|
|
|
}
|
2008-06-07 00:45:15 +08:00
|
|
|
|
2009-02-21 04:59:54 +08:00
|
|
|
/// FindCategoryDeclaration - Finds category declaration in the list of
|
|
|
|
/// categories for this class and returns it. Name of the category is passed
|
|
|
|
/// in 'CategoryId'. If category not found, return 0;
|
|
|
|
///
|
|
|
|
ObjCCategoryDecl *
|
|
|
|
ObjCInterfaceDecl::FindCategoryDeclaration(IdentifierInfo *CategoryId) const {
|
2012-03-03 03:14:29 +08:00
|
|
|
// FIXME: Should make sure no callers ever do this.
|
|
|
|
if (!hasDefinition())
|
|
|
|
return 0;
|
|
|
|
|
2011-12-15 13:27:12 +08:00
|
|
|
if (data().ExternallyCompleted)
|
2010-12-02 07:49:52 +08:00
|
|
|
LoadExternalDefinition();
|
|
|
|
|
2013-01-17 07:00:23 +08:00
|
|
|
for (visible_categories_iterator Cat = visible_categories_begin(),
|
|
|
|
CatEnd = visible_categories_end();
|
|
|
|
Cat != CatEnd;
|
|
|
|
++Cat) {
|
|
|
|
if (Cat->getIdentifier() == CategoryId)
|
|
|
|
return *Cat;
|
|
|
|
}
|
|
|
|
|
2009-02-21 04:59:54 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-07-21 08:06:20 +08:00
|
|
|
ObjCMethodDecl *
|
|
|
|
ObjCInterfaceDecl::getCategoryInstanceMethod(Selector Sel) const {
|
2013-01-17 07:00:23 +08:00
|
|
|
for (visible_categories_iterator Cat = visible_categories_begin(),
|
|
|
|
CatEnd = visible_categories_end();
|
|
|
|
Cat != CatEnd;
|
|
|
|
++Cat) {
|
|
|
|
if (ObjCCategoryImplDecl *Impl = Cat->getImplementation())
|
2009-07-21 08:06:20 +08:00
|
|
|
if (ObjCMethodDecl *MD = Impl->getInstanceMethod(Sel))
|
|
|
|
return MD;
|
2013-01-17 07:00:23 +08:00
|
|
|
}
|
|
|
|
|
2009-07-21 08:06:20 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
ObjCMethodDecl *ObjCInterfaceDecl::getCategoryClassMethod(Selector Sel) const {
|
2013-01-17 07:00:23 +08:00
|
|
|
for (visible_categories_iterator Cat = visible_categories_begin(),
|
|
|
|
CatEnd = visible_categories_end();
|
|
|
|
Cat != CatEnd;
|
|
|
|
++Cat) {
|
|
|
|
if (ObjCCategoryImplDecl *Impl = Cat->getImplementation())
|
2009-07-21 08:06:20 +08:00
|
|
|
if (ObjCMethodDecl *MD = Impl->getClassMethod(Sel))
|
|
|
|
return MD;
|
2013-01-17 07:00:23 +08:00
|
|
|
}
|
|
|
|
|
2009-07-21 08:06:20 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-08-12 06:02:25 +08:00
|
|
|
/// ClassImplementsProtocol - Checks that 'lProto' protocol
|
|
|
|
/// has been implemented in IDecl class, its super class or categories (if
|
|
|
|
/// lookupCategory is true).
|
|
|
|
bool ObjCInterfaceDecl::ClassImplementsProtocol(ObjCProtocolDecl *lProto,
|
|
|
|
bool lookupCategory,
|
|
|
|
bool RHSIsQualifiedID) {
|
2011-12-15 13:27:12 +08:00
|
|
|
if (!hasDefinition())
|
|
|
|
return false;
|
|
|
|
|
2009-08-12 06:02:25 +08:00
|
|
|
ObjCInterfaceDecl *IDecl = this;
|
|
|
|
// 1st, look up the class.
|
2012-03-13 09:09:41 +08:00
|
|
|
for (ObjCInterfaceDecl::protocol_iterator
|
|
|
|
PI = IDecl->protocol_begin(), E = IDecl->protocol_end(); PI != E; ++PI){
|
2009-08-12 06:02:25 +08:00
|
|
|
if (getASTContext().ProtocolCompatibleWithProtocol(lProto, *PI))
|
|
|
|
return true;
|
|
|
|
// This is dubious and is added to be compatible with gcc. In gcc, it is
|
|
|
|
// also allowed assigning a protocol-qualified 'id' type to a LHS object
|
|
|
|
// when protocol in qualified LHS is in list of protocols in the rhs 'id'
|
|
|
|
// object. This IMO, should be a bug.
|
|
|
|
// FIXME: Treat this as an extension, and flag this as an error when GCC
|
|
|
|
// extensions are not enabled.
|
2009-09-09 23:08:12 +08:00
|
|
|
if (RHSIsQualifiedID &&
|
2009-08-12 06:02:25 +08:00
|
|
|
getASTContext().ProtocolCompatibleWithProtocol(*PI, lProto))
|
|
|
|
return true;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-12 06:02:25 +08:00
|
|
|
// 2nd, look up the category.
|
|
|
|
if (lookupCategory)
|
2013-01-17 07:00:23 +08:00
|
|
|
for (visible_categories_iterator Cat = visible_categories_begin(),
|
|
|
|
CatEnd = visible_categories_end();
|
|
|
|
Cat != CatEnd;
|
|
|
|
++Cat) {
|
|
|
|
for (ObjCCategoryDecl::protocol_iterator PI = Cat->protocol_begin(),
|
|
|
|
E = Cat->protocol_end();
|
|
|
|
PI != E; ++PI)
|
2009-08-12 06:02:25 +08:00
|
|
|
if (getASTContext().ProtocolCompatibleWithProtocol(lProto, *PI))
|
|
|
|
return true;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-12 06:02:25 +08:00
|
|
|
// 3rd, look up the super class(s)
|
|
|
|
if (IDecl->getSuperClass())
|
|
|
|
return
|
|
|
|
IDecl->getSuperClass()->ClassImplementsProtocol(lProto, lookupCategory,
|
|
|
|
RHSIsQualifiedID);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-12 06:02:25 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-02-21 04:59:54 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// ObjCIvarDecl
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2011-12-20 10:48:34 +08:00
|
|
|
void ObjCIvarDecl::anchor() { }
|
|
|
|
|
2010-04-03 04:10:03 +08:00
|
|
|
ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC,
|
2011-03-08 16:55:46 +08:00
|
|
|
SourceLocation StartLoc,
|
|
|
|
SourceLocation IdLoc, IdentifierInfo *Id,
|
2009-12-07 10:54:59 +08:00
|
|
|
QualType T, TypeSourceInfo *TInfo,
|
2010-07-17 08:59:30 +08:00
|
|
|
AccessControl ac, Expr *BW,
|
2014-01-04 02:32:18 +08:00
|
|
|
bool synthesized) {
|
2010-04-03 04:10:03 +08:00
|
|
|
if (DC) {
|
|
|
|
// Ivar's can only appear in interfaces, implementations (via synthesized
|
|
|
|
// properties), and class extensions (via direct declaration, or synthesized
|
|
|
|
// properties).
|
|
|
|
//
|
|
|
|
// FIXME: This should really be asserting this:
|
|
|
|
// (isa<ObjCCategoryDecl>(DC) &&
|
|
|
|
// cast<ObjCCategoryDecl>(DC)->IsClassExtension()))
|
|
|
|
// but unfortunately we sometimes place ivars into non-class extension
|
|
|
|
// categories on error. This breaks an AST invariant, and should not be
|
|
|
|
// fixed.
|
|
|
|
assert((isa<ObjCInterfaceDecl>(DC) || isa<ObjCImplementationDecl>(DC) ||
|
|
|
|
isa<ObjCCategoryDecl>(DC)) &&
|
|
|
|
"Invalid ivar decl context!");
|
2010-08-21 05:21:08 +08:00
|
|
|
// Once a new ivar is created in any of class/class-extension/implementation
|
|
|
|
// decl contexts, the previously built IvarList must be rebuilt.
|
|
|
|
ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(DC);
|
|
|
|
if (!ID) {
|
2012-07-20 06:22:55 +08:00
|
|
|
if (ObjCImplementationDecl *IM = dyn_cast<ObjCImplementationDecl>(DC))
|
2010-08-21 05:21:08 +08:00
|
|
|
ID = IM->getClassInterface();
|
2012-07-20 06:22:55 +08:00
|
|
|
else
|
|
|
|
ID = cast<ObjCCategoryDecl>(DC)->getClassInterface();
|
2010-08-21 05:21:08 +08:00
|
|
|
}
|
|
|
|
ID->setIvarList(0);
|
2010-04-03 04:10:03 +08:00
|
|
|
}
|
|
|
|
|
2013-11-22 17:01:48 +08:00
|
|
|
return new (C, DC) ObjCIvarDecl(DC, StartLoc, IdLoc, Id, T, TInfo, ac, BW,
|
2014-01-04 02:32:18 +08:00
|
|
|
synthesized);
|
2008-03-16 08:49:28 +08:00
|
|
|
}
|
|
|
|
|
2012-01-06 05:55:30 +08:00
|
|
|
ObjCIvarDecl *ObjCIvarDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
2013-11-22 17:01:48 +08:00
|
|
|
return new (C, ID) ObjCIvarDecl(0, SourceLocation(), SourceLocation(), 0,
|
2014-01-04 02:32:18 +08:00
|
|
|
QualType(), 0, ObjCIvarDecl::None, 0, false);
|
2012-01-06 05:55:30 +08:00
|
|
|
}
|
|
|
|
|
2010-04-03 05:13:59 +08:00
|
|
|
const ObjCInterfaceDecl *ObjCIvarDecl::getContainingInterface() const {
|
|
|
|
const ObjCContainerDecl *DC = cast<ObjCContainerDecl>(getDeclContext());
|
|
|
|
|
|
|
|
switch (DC->getKind()) {
|
|
|
|
default:
|
|
|
|
case ObjCCategoryImpl:
|
|
|
|
case ObjCProtocol:
|
2011-09-23 13:06:16 +08:00
|
|
|
llvm_unreachable("invalid ivar container!");
|
2010-04-03 05:13:59 +08:00
|
|
|
|
|
|
|
// Ivars can only appear in class extension categories.
|
|
|
|
case ObjCCategory: {
|
|
|
|
const ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(DC);
|
|
|
|
assert(CD->IsClassExtension() && "invalid container for ivar!");
|
|
|
|
return CD->getClassInterface();
|
|
|
|
}
|
|
|
|
|
|
|
|
case ObjCImplementation:
|
|
|
|
return cast<ObjCImplementationDecl>(DC)->getClassInterface();
|
2008-08-20 11:26:33 +08:00
|
|
|
|
2010-04-03 05:13:59 +08:00
|
|
|
case ObjCInterface:
|
|
|
|
return cast<ObjCInterfaceDecl>(DC);
|
|
|
|
}
|
|
|
|
}
|
2009-02-21 04:59:54 +08:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// ObjCAtDefsFieldDecl
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2011-12-20 10:48:34 +08:00
|
|
|
void ObjCAtDefsFieldDecl::anchor() { }
|
|
|
|
|
2008-08-20 11:26:33 +08:00
|
|
|
ObjCAtDefsFieldDecl
|
2011-03-08 16:55:46 +08:00
|
|
|
*ObjCAtDefsFieldDecl::Create(ASTContext &C, DeclContext *DC,
|
|
|
|
SourceLocation StartLoc, SourceLocation IdLoc,
|
2008-08-20 11:26:33 +08:00
|
|
|
IdentifierInfo *Id, QualType T, Expr *BW) {
|
2013-11-22 17:01:48 +08:00
|
|
|
return new (C, DC) ObjCAtDefsFieldDecl(DC, StartLoc, IdLoc, Id, T, BW);
|
2008-08-20 11:26:33 +08:00
|
|
|
}
|
|
|
|
|
2013-11-22 17:01:48 +08:00
|
|
|
ObjCAtDefsFieldDecl *ObjCAtDefsFieldDecl::CreateDeserialized(ASTContext &C,
|
2012-01-06 05:55:30 +08:00
|
|
|
unsigned ID) {
|
2013-11-22 17:01:48 +08:00
|
|
|
return new (C, ID) ObjCAtDefsFieldDecl(0, SourceLocation(), SourceLocation(),
|
|
|
|
0, QualType(), 0);
|
2012-01-06 05:55:30 +08:00
|
|
|
}
|
|
|
|
|
2009-02-21 04:59:54 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// ObjCProtocolDecl
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2011-12-20 10:48:34 +08:00
|
|
|
void ObjCProtocolDecl::anchor() { }
|
|
|
|
|
2012-01-02 04:30:41 +08:00
|
|
|
ObjCProtocolDecl::ObjCProtocolDecl(DeclContext *DC, IdentifierInfo *Id,
|
|
|
|
SourceLocation nameLoc,
|
|
|
|
SourceLocation atStartLoc,
|
2012-01-02 06:06:18 +08:00
|
|
|
ObjCProtocolDecl *PrevDecl)
|
|
|
|
: ObjCContainerDecl(ObjCProtocol, DC, Id, nameLoc, atStartLoc), Data()
|
2012-01-02 04:30:41 +08:00
|
|
|
{
|
2013-10-17 23:37:26 +08:00
|
|
|
setPreviousDecl(PrevDecl);
|
2012-01-02 04:30:41 +08:00
|
|
|
if (PrevDecl)
|
|
|
|
Data = PrevDecl->Data;
|
|
|
|
}
|
|
|
|
|
2009-01-09 08:49:46 +08:00
|
|
|
ObjCProtocolDecl *ObjCProtocolDecl::Create(ASTContext &C, DeclContext *DC,
|
2011-10-04 12:48:02 +08:00
|
|
|
IdentifierInfo *Id,
|
|
|
|
SourceLocation nameLoc,
|
2011-10-18 03:48:06 +08:00
|
|
|
SourceLocation atStartLoc,
|
2012-01-02 06:06:18 +08:00
|
|
|
ObjCProtocolDecl *PrevDecl) {
|
2013-11-22 17:01:48 +08:00
|
|
|
ObjCProtocolDecl *Result =
|
|
|
|
new (C, DC) ObjCProtocolDecl(DC, Id, nameLoc, atStartLoc, PrevDecl);
|
Ensure that type definitions present in just-loaded modules are
visible.
The basic problem here is that a given translation unit can use
forward declarations to form pointers to a given type, say,
class X;
X *x;
and then import a module that includes a definition of X:
import XDef;
We will then fail when attempting to access a member of X, e.g.,
x->method()
because the AST reader did not know to look for a default of a class
named X within the new module.
This implementation is a bit of a C-centric hack, because the only
definitions that can have this property are enums, structs, unions,
Objective-C classes, and Objective-C protocols, and all of those are
either visible at the top-level or can't be defined later. Hence, we
can use the out-of-date-ness of the name and the identifier-update
mechanism to force the update.
In C++, we will not be so lucky, and will need a more advanced
solution, because the definitions could be in namespaces defined in
two different modules, e.g.,
// module 1
namespace N { struct X; }
// module 2
namespace N { struct X { /* ... */ }; }
One possible implementation here is for C++ to extend the information
associated with each identifier table to include the declaration IDs
of any definitions associated with that name, regardless of
context. We would have to eagerly load those definitions.
llvm-svn: 174794
2013-02-09 09:35:03 +08:00
|
|
|
Result->Data.setInt(!C.getLangOpts().Modules);
|
2012-01-02 04:30:41 +08:00
|
|
|
return Result;
|
2008-03-16 09:23:04 +08:00
|
|
|
}
|
|
|
|
|
2013-11-22 17:01:48 +08:00
|
|
|
ObjCProtocolDecl *ObjCProtocolDecl::CreateDeserialized(ASTContext &C,
|
2012-01-06 05:55:30 +08:00
|
|
|
unsigned ID) {
|
2013-11-22 17:01:48 +08:00
|
|
|
ObjCProtocolDecl *Result =
|
|
|
|
new (C, ID) ObjCProtocolDecl(0, 0, SourceLocation(), SourceLocation(), 0);
|
Ensure that type definitions present in just-loaded modules are
visible.
The basic problem here is that a given translation unit can use
forward declarations to form pointers to a given type, say,
class X;
X *x;
and then import a module that includes a definition of X:
import XDef;
We will then fail when attempting to access a member of X, e.g.,
x->method()
because the AST reader did not know to look for a default of a class
named X within the new module.
This implementation is a bit of a C-centric hack, because the only
definitions that can have this property are enums, structs, unions,
Objective-C classes, and Objective-C protocols, and all of those are
either visible at the top-level or can't be defined later. Hence, we
can use the out-of-date-ness of the name and the identifier-update
mechanism to force the update.
In C++, we will not be so lucky, and will need a more advanced
solution, because the definitions could be in namespaces defined in
two different modules, e.g.,
// module 1
namespace N { struct X; }
// module 2
namespace N { struct X { /* ... */ }; }
One possible implementation here is for C++ to extend the information
associated with each identifier table to include the declaration IDs
of any definitions associated with that name, regardless of
context. We would have to eagerly load those definitions.
llvm-svn: 174794
2013-02-09 09:35:03 +08:00
|
|
|
Result->Data.setInt(!C.getLangOpts().Modules);
|
|
|
|
return Result;
|
2012-01-06 05:55:30 +08:00
|
|
|
}
|
|
|
|
|
2009-03-02 00:12:44 +08:00
|
|
|
ObjCProtocolDecl *ObjCProtocolDecl::lookupProtocolNamed(IdentifierInfo *Name) {
|
|
|
|
ObjCProtocolDecl *PDecl = this;
|
|
|
|
|
|
|
|
if (Name == getIdentifier())
|
|
|
|
return PDecl;
|
|
|
|
|
|
|
|
for (protocol_iterator I = protocol_begin(), E = protocol_end(); I != E; ++I)
|
|
|
|
if ((PDecl = (*I)->lookupProtocolNamed(Name)))
|
|
|
|
return PDecl;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-03-02 00:12:44 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2009-07-26 06:15:38 +08:00
|
|
|
// lookupMethod - Lookup a instance/class method in the protocol and protocols
|
2009-02-21 04:59:54 +08:00
|
|
|
// it inherited.
|
2009-07-26 06:15:38 +08:00
|
|
|
ObjCMethodDecl *ObjCProtocolDecl::lookupMethod(Selector Sel,
|
|
|
|
bool isInstance) const {
|
2009-02-21 04:59:54 +08:00
|
|
|
ObjCMethodDecl *MethodDecl = NULL;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2013-01-17 08:38:46 +08:00
|
|
|
// If there is no definition or the definition is hidden, we don't find
|
|
|
|
// anything.
|
|
|
|
const ObjCProtocolDecl *Def = getDefinition();
|
|
|
|
if (!Def || Def->isHidden())
|
|
|
|
return NULL;
|
|
|
|
|
2009-07-26 06:15:38 +08:00
|
|
|
if ((MethodDecl = getMethod(Sel, isInstance)))
|
2009-02-21 04:59:54 +08:00
|
|
|
return MethodDecl;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-21 04:59:54 +08:00
|
|
|
for (protocol_iterator I = protocol_begin(), E = protocol_end(); I != E; ++I)
|
2009-07-26 06:15:38 +08:00
|
|
|
if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance)))
|
2009-02-21 04:59:54 +08:00
|
|
|
return MethodDecl;
|
|
|
|
return NULL;
|
|
|
|
}
|
2009-02-20 13:54:35 +08:00
|
|
|
|
2012-01-02 03:29:29 +08:00
|
|
|
void ObjCProtocolDecl::allocateDefinitionData() {
|
Ensure that type definitions present in just-loaded modules are
visible.
The basic problem here is that a given translation unit can use
forward declarations to form pointers to a given type, say,
class X;
X *x;
and then import a module that includes a definition of X:
import XDef;
We will then fail when attempting to access a member of X, e.g.,
x->method()
because the AST reader did not know to look for a default of a class
named X within the new module.
This implementation is a bit of a C-centric hack, because the only
definitions that can have this property are enums, structs, unions,
Objective-C classes, and Objective-C protocols, and all of those are
either visible at the top-level or can't be defined later. Hence, we
can use the out-of-date-ness of the name and the identifier-update
mechanism to force the update.
In C++, we will not be so lucky, and will need a more advanced
solution, because the definitions could be in namespaces defined in
two different modules, e.g.,
// module 1
namespace N { struct X; }
// module 2
namespace N { struct X { /* ... */ }; }
One possible implementation here is for C++ to extend the information
associated with each identifier table to include the declaration IDs
of any definitions associated with that name, regardless of
context. We would have to eagerly load those definitions.
llvm-svn: 174794
2013-02-09 09:35:03 +08:00
|
|
|
assert(!Data.getPointer() && "Protocol already has a definition!");
|
|
|
|
Data.setPointer(new (getASTContext()) DefinitionData);
|
|
|
|
Data.getPointer()->Definition = this;
|
2012-01-02 03:29:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void ObjCProtocolDecl::startDefinition() {
|
|
|
|
allocateDefinitionData();
|
2012-01-02 03:51:50 +08:00
|
|
|
|
|
|
|
// Update all of the declarations with a pointer to the definition.
|
|
|
|
for (redecl_iterator RD = redecls_begin(), RDEnd = redecls_end();
|
|
|
|
RD != RDEnd; ++RD)
|
|
|
|
RD->Data = this->Data;
|
2011-11-13 05:07:46 +08:00
|
|
|
}
|
|
|
|
|
2013-02-15 06:33:34 +08:00
|
|
|
void ObjCProtocolDecl::collectPropertiesToImplement(PropertyMap &PM,
|
|
|
|
PropertyDeclOrder &PO) const {
|
2013-01-08 05:31:08 +08:00
|
|
|
|
|
|
|
if (const ObjCProtocolDecl *PDecl = getDefinition()) {
|
|
|
|
for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
|
|
|
|
E = PDecl->prop_end(); P != E; ++P) {
|
|
|
|
ObjCPropertyDecl *Prop = *P;
|
|
|
|
// Insert into PM if not there already.
|
|
|
|
PM.insert(std::make_pair(Prop->getIdentifier(), Prop));
|
2013-02-15 06:33:34 +08:00
|
|
|
PO.push_back(Prop);
|
2013-01-08 05:31:08 +08:00
|
|
|
}
|
|
|
|
// Scan through protocol's protocols.
|
|
|
|
for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(),
|
|
|
|
E = PDecl->protocol_end(); PI != E; ++PI)
|
2013-02-15 06:33:34 +08:00
|
|
|
(*PI)->collectPropertiesToImplement(PM, PO);
|
2012-10-19 03:17:53 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-21 05:20:24 +08:00
|
|
|
|
|
|
|
void ObjCProtocolDecl::collectInheritedProtocolProperties(
|
|
|
|
const ObjCPropertyDecl *Property,
|
|
|
|
ProtocolPropertyMap &PM) const {
|
|
|
|
if (const ObjCProtocolDecl *PDecl = getDefinition()) {
|
|
|
|
bool MatchFound = false;
|
|
|
|
for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
|
|
|
|
E = PDecl->prop_end(); P != E; ++P) {
|
|
|
|
ObjCPropertyDecl *Prop = *P;
|
|
|
|
if (Prop == Property)
|
|
|
|
continue;
|
|
|
|
if (Prop->getIdentifier() == Property->getIdentifier()) {
|
|
|
|
PM[PDecl] = Prop;
|
|
|
|
MatchFound = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Scan through protocol's protocols which did not have a matching property.
|
|
|
|
if (!MatchFound)
|
|
|
|
for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(),
|
|
|
|
E = PDecl->protocol_end(); PI != E; ++PI)
|
|
|
|
(*PI)->collectInheritedProtocolProperties(Property, PM);
|
|
|
|
}
|
|
|
|
}
|
2012-10-19 03:17:53 +08:00
|
|
|
|
2009-02-21 04:59:54 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// ObjCCategoryDecl
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2011-12-20 10:48:34 +08:00
|
|
|
void ObjCCategoryDecl::anchor() { }
|
|
|
|
|
2009-01-09 08:49:46 +08:00
|
|
|
ObjCCategoryDecl *ObjCCategoryDecl::Create(ASTContext &C, DeclContext *DC,
|
2013-11-22 17:01:48 +08:00
|
|
|
SourceLocation AtLoc,
|
2010-01-17 00:38:58 +08:00
|
|
|
SourceLocation ClassNameLoc,
|
|
|
|
SourceLocation CategoryNameLoc,
|
2011-08-31 03:43:26 +08:00
|
|
|
IdentifierInfo *Id,
|
2012-02-21 04:09:20 +08:00
|
|
|
ObjCInterfaceDecl *IDecl,
|
|
|
|
SourceLocation IvarLBraceLoc,
|
|
|
|
SourceLocation IvarRBraceLoc) {
|
2013-11-22 17:01:48 +08:00
|
|
|
ObjCCategoryDecl *CatDecl =
|
|
|
|
new (C, DC) ObjCCategoryDecl(DC, AtLoc, ClassNameLoc, CategoryNameLoc, Id,
|
|
|
|
IDecl, IvarLBraceLoc, IvarRBraceLoc);
|
2011-08-31 03:43:26 +08:00
|
|
|
if (IDecl) {
|
|
|
|
// Link this category into its class's category list.
|
2013-01-17 07:00:23 +08:00
|
|
|
CatDecl->NextClassCategory = IDecl->getCategoryListRaw();
|
2011-12-15 13:27:12 +08:00
|
|
|
if (IDecl->hasDefinition()) {
|
2013-01-17 07:00:23 +08:00
|
|
|
IDecl->setCategoryListRaw(CatDecl);
|
2011-12-15 13:27:12 +08:00
|
|
|
if (ASTMutationListener *L = C.getASTMutationListener())
|
|
|
|
L->AddedObjCCategoryToInterface(CatDecl, IDecl);
|
|
|
|
}
|
2011-08-31 03:43:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return CatDecl;
|
|
|
|
}
|
|
|
|
|
2013-11-22 17:01:48 +08:00
|
|
|
ObjCCategoryDecl *ObjCCategoryDecl::CreateDeserialized(ASTContext &C,
|
2012-01-06 05:55:30 +08:00
|
|
|
unsigned ID) {
|
2013-11-22 17:01:48 +08:00
|
|
|
return new (C, ID) ObjCCategoryDecl(0, SourceLocation(), SourceLocation(),
|
|
|
|
SourceLocation(), 0, 0);
|
2008-03-17 04:34:23 +08:00
|
|
|
}
|
|
|
|
|
2009-07-21 08:05:53 +08:00
|
|
|
ObjCCategoryImplDecl *ObjCCategoryDecl::getImplementation() const {
|
|
|
|
return getASTContext().getObjCImplementation(
|
|
|
|
const_cast<ObjCCategoryDecl*>(this));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ObjCCategoryDecl::setImplementation(ObjCCategoryImplDecl *ImplD) {
|
|
|
|
getASTContext().setObjCImplementation(this, ImplD);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-02-21 04:59:54 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// ObjCCategoryImplDecl
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2011-12-20 10:48:34 +08:00
|
|
|
void ObjCCategoryImplDecl::anchor() { }
|
|
|
|
|
2008-03-17 04:53:07 +08:00
|
|
|
ObjCCategoryImplDecl *
|
2009-01-09 08:49:46 +08:00
|
|
|
ObjCCategoryImplDecl::Create(ASTContext &C, DeclContext *DC,
|
2011-10-04 12:48:02 +08:00
|
|
|
IdentifierInfo *Id,
|
|
|
|
ObjCInterfaceDecl *ClassInterface,
|
|
|
|
SourceLocation nameLoc,
|
2011-12-09 08:31:40 +08:00
|
|
|
SourceLocation atStartLoc,
|
|
|
|
SourceLocation CategoryNameLoc) {
|
2011-12-23 08:31:02 +08:00
|
|
|
if (ClassInterface && ClassInterface->hasDefinition())
|
|
|
|
ClassInterface = ClassInterface->getDefinition();
|
2013-11-22 17:01:48 +08:00
|
|
|
return new (C, DC) ObjCCategoryImplDecl(DC, Id, ClassInterface, nameLoc,
|
|
|
|
atStartLoc, CategoryNameLoc);
|
2008-03-17 04:53:07 +08:00
|
|
|
}
|
|
|
|
|
2012-01-06 05:55:30 +08:00
|
|
|
ObjCCategoryImplDecl *ObjCCategoryImplDecl::CreateDeserialized(ASTContext &C,
|
|
|
|
unsigned ID) {
|
2013-11-22 17:01:48 +08:00
|
|
|
return new (C, ID) ObjCCategoryImplDecl(0, 0, 0, SourceLocation(),
|
|
|
|
SourceLocation(), SourceLocation());
|
2012-01-06 05:55:30 +08:00
|
|
|
}
|
|
|
|
|
2009-10-30 05:11:04 +08:00
|
|
|
ObjCCategoryDecl *ObjCCategoryImplDecl::getCategoryDecl() const {
|
2010-03-20 04:39:03 +08:00
|
|
|
// The class interface might be NULL if we are working with invalid code.
|
|
|
|
if (const ObjCInterfaceDecl *ID = getClassInterface())
|
|
|
|
return ID->FindCategoryDeclaration(getIdentifier());
|
|
|
|
return 0;
|
2009-07-28 13:11:05 +08:00
|
|
|
}
|
|
|
|
|
2008-03-17 05:17:37 +08:00
|
|
|
|
2011-12-20 10:48:34 +08:00
|
|
|
void ObjCImplDecl::anchor() { }
|
|
|
|
|
2009-06-30 10:36:12 +08:00
|
|
|
void ObjCImplDecl::addPropertyImplementation(ObjCPropertyImplDecl *property) {
|
2009-04-23 10:42:49 +08:00
|
|
|
// FIXME: The context should be correct before we get here.
|
2009-04-23 09:02:12 +08:00
|
|
|
property->setLexicalDeclContext(this);
|
2009-06-30 10:36:12 +08:00
|
|
|
addDecl(property);
|
2009-04-23 09:02:12 +08:00
|
|
|
}
|
|
|
|
|
2009-07-21 08:05:53 +08:00
|
|
|
void ObjCImplDecl::setClassInterface(ObjCInterfaceDecl *IFace) {
|
|
|
|
ASTContext &Ctx = getASTContext();
|
|
|
|
|
|
|
|
if (ObjCImplementationDecl *ImplD
|
2009-07-21 15:56:29 +08:00
|
|
|
= dyn_cast_or_null<ObjCImplementationDecl>(this)) {
|
2009-07-21 08:05:53 +08:00
|
|
|
if (IFace)
|
|
|
|
Ctx.setObjCImplementation(IFace, ImplD);
|
|
|
|
|
2009-07-21 15:56:29 +08:00
|
|
|
} else if (ObjCCategoryImplDecl *ImplD =
|
2009-07-21 08:05:53 +08:00
|
|
|
dyn_cast_or_null<ObjCCategoryImplDecl>(this)) {
|
|
|
|
if (ObjCCategoryDecl *CD = IFace->FindCategoryDeclaration(getIdentifier()))
|
|
|
|
Ctx.setObjCImplementation(CD, ImplD);
|
|
|
|
}
|
|
|
|
|
|
|
|
ClassInterface = IFace;
|
|
|
|
}
|
|
|
|
|
2009-02-21 04:59:54 +08:00
|
|
|
/// FindPropertyImplIvarDecl - This method lookup the ivar in the list of
|
2013-03-13 01:43:00 +08:00
|
|
|
/// properties implemented in this \@implementation block and returns
|
2009-02-21 04:59:54 +08:00
|
|
|
/// the implemented property that uses it.
|
2008-12-14 06:20:28 +08:00
|
|
|
///
|
2009-03-01 02:42:10 +08:00
|
|
|
ObjCPropertyImplDecl *ObjCImplDecl::
|
2009-06-30 10:36:12 +08:00
|
|
|
FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const {
|
|
|
|
for (propimpl_iterator i = propimpl_begin(), e = propimpl_end(); i != e; ++i){
|
2012-06-07 04:45:41 +08:00
|
|
|
ObjCPropertyImplDecl *PID = *i;
|
2009-02-21 04:59:54 +08:00
|
|
|
if (PID->getPropertyIvarDecl() &&
|
|
|
|
PID->getPropertyIvarDecl()->getIdentifier() == ivarId)
|
|
|
|
return PID;
|
|
|
|
}
|
2009-01-09 01:28:14 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-02-21 04:59:54 +08:00
|
|
|
/// FindPropertyImplDecl - This method looks up a previous ObjCPropertyImplDecl
|
2012-06-16 06:30:14 +08:00
|
|
|
/// added to the list of those properties \@synthesized/\@dynamic in this
|
|
|
|
/// category \@implementation block.
|
2008-04-22 03:04:53 +08:00
|
|
|
///
|
2009-03-01 02:42:10 +08:00
|
|
|
ObjCPropertyImplDecl *ObjCImplDecl::
|
2009-06-30 10:36:12 +08:00
|
|
|
FindPropertyImplDecl(IdentifierInfo *Id) const {
|
|
|
|
for (propimpl_iterator i = propimpl_begin(), e = propimpl_end(); i != e; ++i){
|
2012-06-07 04:45:41 +08:00
|
|
|
ObjCPropertyImplDecl *PID = *i;
|
2009-02-21 04:59:54 +08:00
|
|
|
if (PID->getPropertyDecl()->getIdentifier() == Id)
|
|
|
|
return PID;
|
2009-01-20 02:16:19 +08:00
|
|
|
}
|
2008-04-22 03:04:53 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
raw_ostream &clang::operator<<(raw_ostream &OS,
|
2012-02-07 19:57:45 +08:00
|
|
|
const ObjCCategoryImplDecl &CID) {
|
|
|
|
OS << CID.getName();
|
2010-04-17 17:33:03 +08:00
|
|
|
return OS;
|
|
|
|
}
|
|
|
|
|
2009-02-21 04:59:54 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// ObjCImplementationDecl
|
|
|
|
//===----------------------------------------------------------------------===//
|
2008-03-16 08:19:01 +08:00
|
|
|
|
2011-12-20 10:48:34 +08:00
|
|
|
void ObjCImplementationDecl::anchor() { }
|
|
|
|
|
2009-02-21 04:59:54 +08:00
|
|
|
ObjCImplementationDecl *
|
2009-09-09 23:08:12 +08:00
|
|
|
ObjCImplementationDecl::Create(ASTContext &C, DeclContext *DC,
|
2009-02-21 04:59:54 +08:00
|
|
|
ObjCInterfaceDecl *ClassInterface,
|
2011-10-04 12:48:02 +08:00
|
|
|
ObjCInterfaceDecl *SuperDecl,
|
|
|
|
SourceLocation nameLoc,
|
2012-02-21 04:09:20 +08:00
|
|
|
SourceLocation atStartLoc,
|
2013-05-04 02:05:44 +08:00
|
|
|
SourceLocation superLoc,
|
2012-02-21 04:09:20 +08:00
|
|
|
SourceLocation IvarLBraceLoc,
|
|
|
|
SourceLocation IvarRBraceLoc) {
|
2011-12-23 08:31:02 +08:00
|
|
|
if (ClassInterface && ClassInterface->hasDefinition())
|
|
|
|
ClassInterface = ClassInterface->getDefinition();
|
2013-11-22 17:01:48 +08:00
|
|
|
return new (C, DC) ObjCImplementationDecl(DC, ClassInterface, SuperDecl,
|
|
|
|
nameLoc, atStartLoc, superLoc,
|
|
|
|
IvarLBraceLoc, IvarRBraceLoc);
|
2009-02-21 04:59:54 +08:00
|
|
|
}
|
2008-03-16 08:19:01 +08:00
|
|
|
|
2012-01-06 05:55:30 +08:00
|
|
|
ObjCImplementationDecl *
|
|
|
|
ObjCImplementationDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
2013-11-22 17:01:48 +08:00
|
|
|
return new (C, ID) ObjCImplementationDecl(0, 0, 0, SourceLocation(),
|
|
|
|
SourceLocation());
|
2012-01-06 05:55:30 +08:00
|
|
|
}
|
|
|
|
|
2011-07-22 12:15:06 +08:00
|
|
|
void ObjCImplementationDecl::setIvarInitializers(ASTContext &C,
|
|
|
|
CXXCtorInitializer ** initializers,
|
|
|
|
unsigned numInitializers) {
|
|
|
|
if (numInitializers > 0) {
|
|
|
|
NumIvarInitializers = numInitializers;
|
|
|
|
CXXCtorInitializer **ivarInitializers =
|
|
|
|
new (C) CXXCtorInitializer*[NumIvarInitializers];
|
|
|
|
memcpy(ivarInitializers, initializers,
|
|
|
|
numInitializers * sizeof(CXXCtorInitializer*));
|
|
|
|
IvarInitializers = ivarInitializers;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
raw_ostream &clang::operator<<(raw_ostream &OS,
|
2012-02-07 19:57:45 +08:00
|
|
|
const ObjCImplementationDecl &ID) {
|
|
|
|
OS << ID.getName();
|
2010-04-17 17:33:03 +08:00
|
|
|
return OS;
|
|
|
|
}
|
|
|
|
|
2009-02-21 04:59:54 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// ObjCCompatibleAliasDecl
|
|
|
|
//===----------------------------------------------------------------------===//
|
2008-03-16 08:19:01 +08:00
|
|
|
|
2011-12-20 10:48:34 +08:00
|
|
|
void ObjCCompatibleAliasDecl::anchor() { }
|
|
|
|
|
2009-02-21 04:59:54 +08:00
|
|
|
ObjCCompatibleAliasDecl *
|
|
|
|
ObjCCompatibleAliasDecl::Create(ASTContext &C, DeclContext *DC,
|
|
|
|
SourceLocation L,
|
2009-09-09 23:08:12 +08:00
|
|
|
IdentifierInfo *Id,
|
2009-02-21 04:59:54 +08:00
|
|
|
ObjCInterfaceDecl* AliasedClass) {
|
2013-11-22 17:01:48 +08:00
|
|
|
return new (C, DC) ObjCCompatibleAliasDecl(DC, L, Id, AliasedClass);
|
2008-03-16 08:19:01 +08:00
|
|
|
}
|
|
|
|
|
2012-01-06 05:55:30 +08:00
|
|
|
ObjCCompatibleAliasDecl *
|
|
|
|
ObjCCompatibleAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
2013-11-22 17:01:48 +08:00
|
|
|
return new (C, ID) ObjCCompatibleAliasDecl(0, SourceLocation(), 0, 0);
|
2012-01-06 05:55:30 +08:00
|
|
|
}
|
|
|
|
|
2009-02-21 04:59:54 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// ObjCPropertyDecl
|
|
|
|
//===----------------------------------------------------------------------===//
|
2008-03-16 08:19:01 +08:00
|
|
|
|
2011-12-20 10:48:34 +08:00
|
|
|
void ObjCPropertyDecl::anchor() { }
|
|
|
|
|
2009-02-21 04:59:54 +08:00
|
|
|
ObjCPropertyDecl *ObjCPropertyDecl::Create(ASTContext &C, DeclContext *DC,
|
|
|
|
SourceLocation L,
|
|
|
|
IdentifierInfo *Id,
|
2010-01-22 01:36:00 +08:00
|
|
|
SourceLocation AtLoc,
|
2012-03-01 06:18:55 +08:00
|
|
|
SourceLocation LParenLoc,
|
2010-06-05 04:50:08 +08:00
|
|
|
TypeSourceInfo *T,
|
2009-02-21 04:59:54 +08:00
|
|
|
PropertyControl propControl) {
|
2013-11-22 17:01:48 +08:00
|
|
|
return new (C, DC) ObjCPropertyDecl(DC, L, Id, AtLoc, LParenLoc, T);
|
2008-03-16 08:19:01 +08:00
|
|
|
}
|
|
|
|
|
2013-11-22 17:01:48 +08:00
|
|
|
ObjCPropertyDecl *ObjCPropertyDecl::CreateDeserialized(ASTContext &C,
|
2012-01-06 05:55:30 +08:00
|
|
|
unsigned ID) {
|
2013-11-22 17:01:48 +08:00
|
|
|
return new (C, ID) ObjCPropertyDecl(0, SourceLocation(), 0, SourceLocation(),
|
|
|
|
SourceLocation(), 0);
|
2012-01-06 05:55:30 +08:00
|
|
|
}
|
|
|
|
|
2009-02-21 04:59:54 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// ObjCPropertyImplDecl
|
|
|
|
//===----------------------------------------------------------------------===//
|
2008-03-17 09:19:02 +08:00
|
|
|
|
2008-04-23 08:06:01 +08:00
|
|
|
ObjCPropertyImplDecl *ObjCPropertyImplDecl::Create(ASTContext &C,
|
2009-01-09 08:49:46 +08:00
|
|
|
DeclContext *DC,
|
2008-04-23 08:06:01 +08:00
|
|
|
SourceLocation atLoc,
|
|
|
|
SourceLocation L,
|
|
|
|
ObjCPropertyDecl *property,
|
2008-08-26 12:47:31 +08:00
|
|
|
Kind PK,
|
2010-11-17 09:03:52 +08:00
|
|
|
ObjCIvarDecl *ivar,
|
|
|
|
SourceLocation ivarLoc) {
|
2013-11-22 17:01:48 +08:00
|
|
|
return new (C, DC) ObjCPropertyImplDecl(DC, atLoc, L, property, PK, ivar,
|
|
|
|
ivarLoc);
|
2008-04-23 08:06:01 +08:00
|
|
|
}
|
2008-03-17 09:19:02 +08:00
|
|
|
|
2013-11-22 17:01:48 +08:00
|
|
|
ObjCPropertyImplDecl *ObjCPropertyImplDecl::CreateDeserialized(ASTContext &C,
|
2012-01-06 05:55:30 +08:00
|
|
|
unsigned ID) {
|
2013-11-22 17:01:48 +08:00
|
|
|
return new (C, ID) ObjCPropertyImplDecl(0, SourceLocation(), SourceLocation(),
|
|
|
|
0, Dynamic, 0, SourceLocation());
|
2012-01-06 05:55:30 +08:00
|
|
|
}
|
|
|
|
|
2010-11-17 09:03:52 +08:00
|
|
|
SourceRange ObjCPropertyImplDecl::getSourceRange() const {
|
|
|
|
SourceLocation EndLoc = getLocation();
|
|
|
|
if (IvarLoc.isValid())
|
|
|
|
EndLoc = IvarLoc;
|
2008-04-04 14:12:32 +08:00
|
|
|
|
2010-11-17 09:03:52 +08:00
|
|
|
return SourceRange(AtLoc, EndLoc);
|
|
|
|
}
|