- Remove getInstanceMethods/getClassMethods API on ObjcInterfaceDecl, ObjcProtocolDecl, and ObjcCategoryDecl. These methods are replaced by the respective iterators on each class.

- Add getInstanceMethodForSelector to ObjcInterfaceDecl, ObjcProtocolDecl, and ObjcCatgoryDecl. This hook will do a "shallow" lookup. This is a convenience method that reducing some of the iterator usage.
- Various changes to convert all clients to the above API's...
 

llvm-svn: 45046
This commit is contained in:
Steve Naroff 2007-12-14 23:37:57 +00:00
parent 85e45f278c
commit 3ce37a6b8e
4 changed files with 327 additions and 280 deletions

View File

@ -409,36 +409,24 @@ ObjcIvarDecl *ObjcInterfaceDecl::lookupInstanceVariable(
/// the class, its categories, and its super classes (using a linear search).
ObjcMethodDecl *ObjcInterfaceDecl::lookupInstanceMethod(Selector &Sel) {
ObjcInterfaceDecl* ClassDecl = this;
ObjcMethodDecl *MethodDecl = 0;
while (ClassDecl != NULL) {
ObjcMethodDecl **methods = ClassDecl->getInstanceMethods();
int methodCount = ClassDecl->getNumInstanceMethods();
for (int i = 0; i < methodCount; ++i) {
if (methods[i]->getSelector() == Sel) {
return methods[i];
}
}
if ((MethodDecl = ClassDecl->getInstanceMethodForSelector(Sel)))
return MethodDecl;
// Didn't find one yet - look through protocols.
ObjcProtocolDecl **protocols = ClassDecl->getReferencedProtocols();
int numProtocols = ClassDecl->getNumIntfRefProtocols();
for (int pIdx = 0; pIdx < numProtocols; pIdx++) {
ObjcMethodDecl **methods = protocols[pIdx]->getInstanceMethods();
int methodCount = protocols[pIdx]->getNumInstanceMethods();
for (int i = 0; i < methodCount; ++i) {
if (methods[i]->getSelector() == Sel) {
return methods[i];
}
}
if ((MethodDecl = protocols[pIdx]->getInstanceMethodForSelector(Sel)))
return MethodDecl;
}
// Didn't find one yet - now look through categories.
ObjcCategoryDecl *CatDecl = ClassDecl->getCategoryList();
while (CatDecl) {
ObjcMethodDecl **methods = CatDecl->getInstanceMethods();
int methodCount = CatDecl->getNumInstanceMethods();
for (int i = 0; i < methodCount; ++i) {
if (methods[i]->getSelector() == Sel) {
return methods[i];
}
}
if ((MethodDecl = CatDecl->getInstanceMethodForSelector(Sel)))
return MethodDecl;
CatDecl = CatDecl->getNextClassCategory();
}
ClassDecl = ClassDecl->getSuperClass();
@ -450,36 +438,24 @@ ObjcMethodDecl *ObjcInterfaceDecl::lookupInstanceMethod(Selector &Sel) {
// class, its categories, and its super classes (using a linear search).
ObjcMethodDecl *ObjcInterfaceDecl::lookupClassMethod(Selector &Sel) {
ObjcInterfaceDecl* ClassDecl = this;
ObjcMethodDecl *MethodDecl = 0;
while (ClassDecl != NULL) {
ObjcMethodDecl **methods = ClassDecl->getClassMethods();
int methodCount = ClassDecl->getNumClassMethods();
for (int i = 0; i < methodCount; ++i) {
if (methods[i]->getSelector() == Sel) {
return methods[i];
}
}
if ((MethodDecl = ClassDecl->getClassMethodForSelector(Sel)))
return MethodDecl;
// Didn't find one yet - look through protocols.
ObjcProtocolDecl **protocols = ClassDecl->getReferencedProtocols();
int numProtocols = ClassDecl->getNumIntfRefProtocols();
for (int pIdx = 0; pIdx < numProtocols; pIdx++) {
ObjcMethodDecl **methods = protocols[pIdx]->getClassMethods();
int methodCount = protocols[pIdx]->getNumClassMethods();
for (int i = 0; i < methodCount; ++i) {
if (methods[i]->getSelector() == Sel) {
return methods[i];
}
}
if ((MethodDecl = protocols[pIdx]->getClassMethodForSelector(Sel)))
return MethodDecl;
}
// Didn't find one yet - now look through categories.
ObjcCategoryDecl *CatDecl = ClassDecl->getCategoryList();
while (CatDecl) {
ObjcMethodDecl **methods = CatDecl->getClassMethods();
int methodCount = CatDecl->getNumClassMethods();
for (int i = 0; i < methodCount; ++i) {
if (methods[i]->getSelector() == Sel) {
return methods[i];
}
}
if ((MethodDecl = CatDecl->getClassMethodForSelector(Sel)))
return MethodDecl;
CatDecl = CatDecl->getNextClassCategory();
}
ClassDecl = ClassDecl->getSuperClass();
@ -532,19 +508,17 @@ ObjcMethodDecl *ObjcCategoryImplDecl::lookupClassMethod(Selector &Sel) {
// lookupInstanceMethod - Lookup a instance method in the protocol and protocols
// it inherited.
ObjcMethodDecl *ObjcProtocolDecl::lookupInstanceMethod(Selector &Sel) {
ObjcMethodDecl *const*methods = getInstanceMethods();
int methodCount = getNumInstanceMethods();
for (int i = 0; i < methodCount; ++i) {
if (methods[i]->getSelector() == Sel) {
return methods[i];
}
}
ObjcMethodDecl *MethodDecl = NULL;
if ((MethodDecl = getInstanceMethodForSelector(Sel)))
return MethodDecl;
if (getNumReferencedProtocols() > 0) {
ObjcProtocolDecl **RefPDecl = getReferencedProtocols();
for (int i = 0; i < getNumReferencedProtocols(); i++) {
if (ObjcMethodDecl *Method = RefPDecl[i]->lookupInstanceMethod(Sel))
return Method;
if ((MethodDecl = RefPDecl[i]->getInstanceMethodForSelector(Sel)))
return MethodDecl;
}
}
return NULL;
@ -553,20 +527,33 @@ ObjcMethodDecl *ObjcProtocolDecl::lookupInstanceMethod(Selector &Sel) {
// lookupInstanceMethod - Lookup a class method in the protocol and protocols
// it inherited.
ObjcMethodDecl *ObjcProtocolDecl::lookupClassMethod(Selector &Sel) {
ObjcMethodDecl *const*methods = getClassMethods();
int methodCount = getNumClassMethods();
for (int i = 0; i < methodCount; ++i) {
if (methods[i]->getSelector() == Sel) {
return methods[i];
}
}
ObjcMethodDecl *MethodDecl = NULL;
if ((MethodDecl = getClassMethodForSelector(Sel)))
return MethodDecl;
if (getNumReferencedProtocols() > 0) {
ObjcProtocolDecl **RefPDecl = getReferencedProtocols();
for (int i = 0; i < getNumReferencedProtocols(); i++) {
if (ObjcMethodDecl *Method = RefPDecl[i]->lookupClassMethod(Sel))
return Method;
if ((MethodDecl = RefPDecl[i]->getClassMethodForSelector(Sel)))
return MethodDecl;
}
}
return NULL;
}
ObjcInterfaceDecl *const ObjcMethodDecl::getClassInterface() const {
if (ObjcInterfaceDecl *ID = dyn_cast<ObjcInterfaceDecl>(MethodContext))
return ID;
if (ObjcCategoryDecl *CD = dyn_cast<ObjcCategoryDecl>(MethodContext))
return CD->getClassInterface();
if (ObjcImplementationDecl *IMD =
dyn_cast<ObjcImplementationDecl>(MethodContext))
return IMD->getClassInterface();
if (ObjcCategoryImplDecl *CID =
dyn_cast<ObjcCategoryImplDecl>(MethodContext))
return CID->getClassInterface();
assert(false && "unknown method context");
return 0;
}

View File

@ -144,7 +144,7 @@ namespace {
void RewriteCategoryDecl(ObjcCategoryDecl *Dcl);
void RewriteProtocolDecl(ObjcProtocolDecl *Dcl);
void RewriteForwardProtocolDecl(ObjcForwardProtocolDecl *Dcl);
void RewriteMethodDeclarations(int nMethods, ObjcMethodDecl **Methods);
void RewriteMethodDeclaration(ObjcMethodDecl *Method);
void RewriteProperties(int nProperties, ObjcPropertyDecl **Properties);
void RewriteFunctionDecl(FunctionDecl *FD);
void RewriteObjcQualifiedInterfaceTypes(Decl *Dcl);
@ -398,18 +398,15 @@ void RewriteTest::RewriteForwardClassDecl(ObjcClassDecl *ClassDecl) {
typedefString.c_str(), typedefString.size());
}
void RewriteTest::RewriteMethodDeclarations(int nMethods, ObjcMethodDecl **Methods) {
for (int i = 0; i < nMethods; i++) {
ObjcMethodDecl *Method = Methods[i];
SourceLocation LocStart = Method->getLocStart();
SourceLocation LocEnd = Method->getLocEnd();
void RewriteTest::RewriteMethodDeclaration(ObjcMethodDecl *Method) {
SourceLocation LocStart = Method->getLocStart();
SourceLocation LocEnd = Method->getLocEnd();
if (SM->getLineNumber(LocEnd) > SM->getLineNumber(LocStart)) {
Rewrite.InsertText(LocStart, "/* ", 3);
Rewrite.ReplaceText(LocEnd, 1, ";*/ ", 4);
} else {
Rewrite.InsertText(LocStart, "// ", 3);
}
if (SM->getLineNumber(LocEnd) > SM->getLineNumber(LocStart)) {
Rewrite.InsertText(LocStart, "/* ", 3);
Rewrite.ReplaceText(LocEnd, 1, ";*/ ", 4);
} else {
Rewrite.InsertText(LocStart, "// ", 3);
}
}
@ -431,10 +428,13 @@ void RewriteTest::RewriteCategoryDecl(ObjcCategoryDecl *CatDecl) {
// FIXME: handle category headers that are declared across multiple lines.
Rewrite.ReplaceText(LocStart, 0, "// ", 3);
RewriteMethodDeclarations(CatDecl->getNumInstanceMethods(),
CatDecl->getInstanceMethods());
RewriteMethodDeclarations(CatDecl->getNumClassMethods(),
CatDecl->getClassMethods());
for (ObjcCategoryDecl::instmeth_iterator I = CatDecl->instmeth_begin(),
E = CatDecl->instmeth_end(); I != E; ++I)
RewriteMethodDeclaration(*I);
for (ObjcCategoryDecl::classmeth_iterator I = CatDecl->classmeth_begin(),
E = CatDecl->classmeth_end(); I != E; ++I)
RewriteMethodDeclaration(*I);
// Lastly, comment out the @end.
Rewrite.ReplaceText(CatDecl->getAtEndLoc(), 0, "// ", 3);
}
@ -447,10 +447,13 @@ void RewriteTest::RewriteProtocolDecl(ObjcProtocolDecl *PDecl) {
// FIXME: handle protocol headers that are declared across multiple lines.
Rewrite.ReplaceText(LocStart, 0, "// ", 3);
RewriteMethodDeclarations(PDecl->getNumInstanceMethods(),
PDecl->getInstanceMethods());
RewriteMethodDeclarations(PDecl->getNumClassMethods(),
PDecl->getClassMethods());
for (ObjcProtocolDecl::instmeth_iterator I = PDecl->instmeth_begin(),
E = PDecl->instmeth_end(); I != E; ++I)
RewriteMethodDeclaration(*I);
for (ObjcProtocolDecl::classmeth_iterator I = PDecl->classmeth_begin(),
E = PDecl->classmeth_end(); I != E; ++I)
RewriteMethodDeclaration(*I);
// Lastly, comment out the @end.
SourceLocation LocEnd = PDecl->getAtEndLoc();
Rewrite.ReplaceText(LocEnd, 0, "// ", 3);
@ -619,11 +622,13 @@ void RewriteTest::RewriteInterfaceDecl(ObjcInterfaceDecl *ClassDecl) {
RewriteProperties(ClassDecl->getNumPropertyDecl(),
ClassDecl->getPropertyDecl());
RewriteMethodDeclarations(ClassDecl->getNumInstanceMethods(),
ClassDecl->getInstanceMethods());
RewriteMethodDeclarations(ClassDecl->getNumClassMethods(),
ClassDecl->getClassMethods());
for (ObjcInterfaceDecl::instmeth_iterator I = ClassDecl->instmeth_begin(),
E = ClassDecl->instmeth_end(); I != E; ++I)
RewriteMethodDeclaration(*I);
for (ObjcInterfaceDecl::classmeth_iterator I = ClassDecl->classmeth_begin(),
E = ClassDecl->classmeth_end(); I != E; ++I)
RewriteMethodDeclaration(*I);
// Lastly, comment out the @end.
Rewrite.ReplaceText(ClassDecl->getAtEndLoc(), 0, "// ", 3);
}
@ -1843,31 +1848,27 @@ void RewriteTest::RewriteObjcProtocolsMetaData(ObjcProtocolDecl **Protocols,
objc_protocol_methods = true;
}
// Output instance methods declared in this protocol.
int NumMethods = PDecl->getNumInstanceMethods();
if (NumMethods > 0) {
int NumMethods = PDecl->getNumInstanceMethods();
if(NumMethods > 0) {
Result += "\nstatic struct _objc_protocol_method_list "
"_OBJC_PROTOCOL_INSTANCE_METHODS_";
Result += PDecl->getName();
Result += " __attribute__ ((section (\"__OBJC, __cat_inst_meth\")))= "
"{\n\t" + utostr(NumMethods) + "\n";
ObjcMethodDecl **Methods = PDecl->getInstanceMethods();
Result += "\t,{{(SEL)\"";
Result += Methods[0]->getSelector().getName().c_str();
Result += "\", \"\"}\n";
for (int i = 1; i < NumMethods; i++) {
Result += "\t ,{(SEL)\"";
Result += Methods[i]->getSelector().getName().c_str();
std::string MethodTypeString;
Context->getObjcEncodingForMethodDecl(Methods[i], MethodTypeString);
Result += "\", \"";
Result += MethodTypeString;
Result += "\"}\n";
}
Result += "\t }\n};\n";
}
// Output instance methods declared in this protocol.
for (ObjcProtocolDecl::instmeth_iterator I = PDecl->instmeth_begin(),
E = PDecl->instmeth_end(); I != E; ++I) {
Result += "\t ,{(SEL)\"";
Result += (*I)->getSelector().getName().c_str();
std::string MethodTypeString;
Context->getObjcEncodingForMethodDecl((*I), MethodTypeString);
Result += "\", \"";
Result += MethodTypeString;
Result += "\"}\n";
}
Result += "\t }\n};\n";
}
// Output class methods declared in this protocol.
NumMethods = PDecl->getNumClassMethods();
@ -1880,16 +1881,13 @@ void RewriteTest::RewriteObjcProtocolsMetaData(ObjcProtocolDecl **Protocols,
Result += utostr(NumMethods);
Result += "\n";
ObjcMethodDecl **Methods = PDecl->getClassMethods();
Result += "\t,{{(SEL)\"";
Result += Methods[0]->getSelector().getName().c_str();
Result += "\", \"\"}\n";
for (int i = 1; i < NumMethods; i++) {
// Output instance methods declared in this protocol.
for (ObjcProtocolDecl::classmeth_iterator I = PDecl->classmeth_begin(),
E = PDecl->classmeth_end(); I != E; ++I) {
Result += "\t ,{(SEL)\"";
Result += Methods[i]->getSelector().getName().c_str();
Result += (*I)->getSelector().getName().c_str();
std::string MethodTypeString;
Context->getObjcEncodingForMethodDecl(Methods[i], MethodTypeString);
Context->getObjcEncodingForMethodDecl((*I), MethodTypeString);
Result += "\", \"";
Result += MethodTypeString;
Result += "\"}\n";
@ -1936,14 +1934,14 @@ void RewriteTest::RewriteObjcProtocolsMetaData(ObjcProtocolDecl **Protocols,
"{\n\t0, \"";
Result += PDecl->getName();
Result += "\", 0, ";
if (PDecl->getInstanceMethods() > 0) {
if (PDecl->getNumInstanceMethods() > 0) {
Result += "&_OBJC_PROTOCOL_INSTANCE_METHODS_";
Result += PDecl->getName();
Result += ", ";
}
else
Result += "0, ";
if (PDecl->getClassMethods() > 0) {
if (PDecl->getNumClassMethods() > 0) {
Result += "&_OBJC_PROTOCOL_CLASS_METHODS_";
Result += PDecl->getName();
Result += "\n";

View File

@ -452,25 +452,27 @@ void Sema::CheckProtocolMethodDefs(ObjcProtocolDecl *PDecl,
const llvm::DenseSet<Selector> &InsMap,
const llvm::DenseSet<Selector> &ClsMap) {
// check unimplemented instance methods.
ObjcMethodDecl** methods = PDecl->getInstanceMethods();
for (int j = 0; j < PDecl->getNumInstanceMethods(); j++) {
if (!InsMap.count(methods[j]->getSelector()) &&
methods[j]->getImplementationControl() != ObjcMethodDecl::Optional) {
Diag(methods[j]->getLocation(), diag::warn_undef_method_impl,
methods[j]->getSelector().getName());
for (ObjcProtocolDecl::instmeth_iterator I = PDecl->instmeth_begin(),
E = PDecl->instmeth_end(); I != E; ++I) {
ObjcMethodDecl *method = *I;
if (!InsMap.count(method->getSelector()) &&
method->getImplementationControl() != ObjcMethodDecl::Optional) {
Diag(method->getLocation(), diag::warn_undef_method_impl,
method->getSelector().getName());
IncompleteImpl = true;
}
}
// check unimplemented class methods
methods = PDecl->getClassMethods();
for (int j = 0; j < PDecl->getNumClassMethods(); j++)
if (!ClsMap.count(methods[j]->getSelector()) &&
methods[j]->getImplementationControl() != ObjcMethodDecl::Optional) {
Diag(methods[j]->getLocation(), diag::warn_undef_method_impl,
methods[j]->getSelector().getName());
for (ObjcProtocolDecl::classmeth_iterator I = PDecl->classmeth_begin(),
E = PDecl->classmeth_end(); I != E; ++I) {
ObjcMethodDecl *method = *I;
if (!ClsMap.count(method->getSelector()) &&
method->getImplementationControl() != ObjcMethodDecl::Optional) {
Diag(method->getLocation(), diag::warn_undef_method_impl,
method->getSelector().getName());
IncompleteImpl = true;
}
}
// Check on this protocols's referenced protocols, recursively
ObjcProtocolDecl** RefPDecl = PDecl->getReferencedProtocols();
for (int i = 0; i < PDecl->getNumReferencedProtocols(); i++)
@ -533,11 +535,11 @@ void Sema::ImplCategoryMethodsVsIntfMethods(ObjcCategoryImplDecl *CatImplDecl,
InsMap.insert((*I)->getSelector());
bool IncompleteImpl = false;
ObjcMethodDecl *const* methods = CatClassDecl->getInstanceMethods();
for (int j = 0; j < CatClassDecl->getNumInstanceMethods(); j++)
if (!InsMap.count(methods[j]->getSelector())) {
Diag(methods[j]->getLocation(), diag::warn_undef_method_impl,
methods[j]->getSelector().getName());
for (ObjcCategoryDecl::instmeth_iterator I = CatClassDecl->instmeth_begin(),
E = CatClassDecl->instmeth_end(); I != E; ++I)
if (!InsMap.count((*I)->getSelector())) {
Diag((*I)->getLocation(), diag::warn_undef_method_impl,
(*I)->getSelector().getName());
IncompleteImpl = true;
}
llvm::DenseSet<Selector> ClsMap;
@ -548,11 +550,11 @@ void Sema::ImplCategoryMethodsVsIntfMethods(ObjcCategoryImplDecl *CatImplDecl,
I != E; ++I)
ClsMap.insert((*I)->getSelector());
methods = CatClassDecl->getClassMethods();
for (int j = 0; j < CatClassDecl->getNumClassMethods(); j++)
if (!ClsMap.count(methods[j]->getSelector())) {
Diag(methods[j]->getLocation(), diag::warn_undef_method_impl,
methods[j]->getSelector().getName());
for (ObjcCategoryDecl::classmeth_iterator I = CatClassDecl->classmeth_begin(),
E = CatClassDecl->classmeth_end(); I != E; ++I)
if (!ClsMap.count((*I)->getSelector())) {
Diag((*I)->getLocation(), diag::warn_undef_method_impl,
(*I)->getSelector().getName());
IncompleteImpl = true;
}

View File

@ -27,6 +27,125 @@ class ObjcMethodDecl;
class ObjcProtocolDecl;
class ObjcCategoryDecl;
class ObjcPropertyDecl;
/// ObjcMethodDecl - Represents an instance or class method declaration.
/// ObjC methods can be declared within 4 contexts: class interfaces,
/// categories, protocols, and class implementations. While C++ member
/// functions leverage C syntax, Objective-C method syntax is modeled after
/// Smalltalk (using colons to specify argument types/expressions).
/// Here are some brief examples:
///
/// Setter/getter instance methods:
/// - (void)setMenu:(NSMenu *)menu;
/// - (NSMenu *)menu;
///
/// Instance method that takes 2 NSView arguments:
/// - (void)replaceSubview:(NSView *)oldView with:(NSView *)newView;
///
/// Getter class method:
/// + (NSMenu *)defaultMenu;
///
/// A selector represents a unique name for a method. The selector names for
/// the above methods are setMenu:, menu, replaceSubview:with:, and defaultMenu.
///
class ObjcMethodDecl : public Decl {
public:
enum ImplementationControl { None, Required, Optional };
private:
/// Bitfields must be first fields in this class so they pack with those
/// declared in class Decl.
/// instance (true) or class (false) method.
bool IsInstance : 1;
bool IsVariadic : 1;
/// @required/@optional
ImplementationControl DeclImplementation : 2;
/// in, inout, etc.
ObjcDeclQualifier objcDeclQualifier : 6;
// Context this method is declared in.
NamedDecl *MethodContext;
// A unigue name for this method.
Selector SelName;
// Type of this method.
QualType MethodDeclType;
/// ParamInfo - new[]'d array of pointers to VarDecls for the formal
/// parameters of this Method. This is null if there are no formals.
ParmVarDecl **ParamInfo;
int NumMethodParams; // -1 if no parameters
/// List of attributes for this method declaration.
AttributeList *MethodAttrs;
SourceLocation EndLoc; // the location of the ';' or '{'.
// The following are only used for method definitions, null otherwise.
// FIXME: space savings opportunity, consider a sub-class.
Stmt *Body;
ParmVarDecl *SelfDecl;
public:
ObjcMethodDecl(SourceLocation beginLoc, SourceLocation endLoc,
Selector SelInfo, QualType T,
Decl *contextDecl,
ParmVarDecl **paramInfo = 0, int numParams=-1,
AttributeList *M = 0, bool isInstance = true,
bool isVariadic = false,
ImplementationControl impControl = None,
Decl *PrevDecl = 0)
: Decl(ObjcMethod, beginLoc),
IsInstance(isInstance), IsVariadic(isVariadic),
DeclImplementation(impControl), objcDeclQualifier(OBJC_TQ_None),
MethodContext(static_cast<NamedDecl*>(contextDecl)),
SelName(SelInfo), MethodDeclType(T),
ParamInfo(paramInfo), NumMethodParams(numParams),
MethodAttrs(M), EndLoc(endLoc), Body(0), SelfDecl(0) {}
virtual ~ObjcMethodDecl();
ObjcDeclQualifier getObjcDeclQualifier() const { return objcDeclQualifier; }
void setObjcDeclQualifier(ObjcDeclQualifier QV) { objcDeclQualifier = QV; }
// Location information, modeled after the Stmt API.
SourceLocation getLocStart() const { return getLocation(); }
SourceLocation getLocEnd() const { return EndLoc; }
NamedDecl *getMethodContext() const { return MethodContext; }
ObjcInterfaceDecl *const getClassInterface() const;
Selector getSelector() const { return SelName; }
QualType getResultType() const { return MethodDeclType; }
int getNumParams() const { return NumMethodParams; }
ParmVarDecl *getParamDecl(int i) const {
assert(i < getNumParams() && "Illegal param #");
return ParamInfo[i];
}
void setMethodParams(ParmVarDecl **NewParamInfo, unsigned NumParams);
AttributeList *getMethodAttrs() const {return MethodAttrs;}
bool isInstance() const { return IsInstance; }
bool isVariadic() const { return IsVariadic; }
// Related to protocols declared in @protocol
void setDeclImplementation(ImplementationControl ic) {
DeclImplementation = ic;
}
ImplementationControl getImplementationControl() const {
return DeclImplementation;
}
Stmt *const getBody() const { return Body; }
void setBody(Stmt *B) { Body = B; }
ParmVarDecl *const getSelfDecl() const { return SelfDecl; }
void setSelfDecl(ParmVarDecl *PVD) { SelfDecl = PVD; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return D->getKind() == ObjcMethod; }
static bool classof(const ObjcMethodDecl *D) { return true; }
};
/// ObjcInterfaceDecl - Represents an ObjC class declaration. For example:
///
@ -118,10 +237,7 @@ public:
ivar_iterator ivar_begin() const { return Ivars; }
ivar_iterator ivar_end() const { return Ivars + ivar_size();}
ObjcMethodDecl** getInstanceMethods() const { return InstanceMethods; }
int getNumInstanceMethods() const { return NumInstanceMethods; }
ObjcMethodDecl** getClassMethods() const { return ClassMethods; }
int getNumClassMethods() const { return NumClassMethods; }
typedef ObjcMethodDecl * const * instmeth_iterator;
@ -160,6 +276,28 @@ public:
}
ObjcIvarDecl *lookupInstanceVariable(IdentifierInfo *ivarName,
ObjcInterfaceDecl *&clsDeclared);
// Get the local instance method declared in this interface.
ObjcMethodDecl *getInstanceMethodForSelector(Selector &Sel) {
for (instmeth_iterator I = instmeth_begin(), E = instmeth_end();
I != E; ++I) {
if ((*I)->getSelector() == Sel)
return *I;
}
return 0;
}
// Get the local class method declared in this interface.
ObjcMethodDecl *getClassMethodForSelector(Selector &Sel) {
for (classmeth_iterator I = classmeth_begin(), E = classmeth_end();
I != E; ++I) {
if ((*I)->getSelector() == Sel)
return *I;
}
return 0;
}
// Lookup the instance method. First, we search locally. If a method isn't
// found, we look through the reference protocols. Lastly, we look categories
// defined for this class.
ObjcMethodDecl *lookupInstanceMethod(Selector &Sel);
ObjcMethodDecl *lookupClassMethod(Selector &Sel);
@ -291,12 +429,39 @@ public:
return ReferencedProtocols;
}
int getNumReferencedProtocols() const { return NumReferencedProtocols; }
ObjcMethodDecl** getInstanceMethods() const { return InstanceMethods; }
int getNumInstanceMethods() const { return NumInstanceMethods; }
ObjcMethodDecl** getClassMethods() const { return ClassMethods; }
int getNumClassMethods() const { return NumClassMethods; }
typedef ObjcMethodDecl * const * instmeth_iterator;
instmeth_iterator instmeth_begin() const { return InstanceMethods; }
instmeth_iterator instmeth_end() const {
return InstanceMethods+(NumInstanceMethods == -1 ? 0 : NumInstanceMethods);
}
typedef ObjcMethodDecl * const * classmeth_iterator;
classmeth_iterator classmeth_begin() const { return ClassMethods; }
classmeth_iterator classmeth_end() const {
return ClassMethods+(NumClassMethods == -1 ? 0 : NumClassMethods);
}
// Get the local instance method declared in this interface.
ObjcMethodDecl *getInstanceMethodForSelector(Selector &Sel) {
for (instmeth_iterator I = instmeth_begin(), E = instmeth_end();
I != E; ++I) {
if ((*I)->getSelector() == Sel)
return *I;
}
return 0;
}
// Get the local class method declared in this interface.
ObjcMethodDecl *getClassMethodForSelector(Selector &Sel) {
for (classmeth_iterator I = classmeth_begin(), E = classmeth_end();
I != E; ++I) {
if ((*I)->getSelector() == Sel)
return *I;
}
return 0;
}
ObjcMethodDecl *lookupInstanceMethod(Selector &Sel);
ObjcMethodDecl *lookupClassMethod(Selector &Sel);
@ -452,12 +617,39 @@ public:
return ReferencedProtocols;
}
int getNumReferencedProtocols() const { return NumReferencedProtocols; }
ObjcMethodDecl **getInstanceMethods() const { return InstanceMethods; }
int getNumInstanceMethods() const { return NumInstanceMethods; }
ObjcMethodDecl **getClassMethods() const { return ClassMethods; }
int getNumClassMethods() const { return NumClassMethods; }
typedef ObjcMethodDecl * const * instmeth_iterator;
instmeth_iterator instmeth_begin() const { return InstanceMethods; }
instmeth_iterator instmeth_end() const {
return InstanceMethods+(NumInstanceMethods == -1 ? 0 : NumInstanceMethods);
}
typedef ObjcMethodDecl * const * classmeth_iterator;
classmeth_iterator classmeth_begin() const { return ClassMethods; }
classmeth_iterator classmeth_end() const {
return ClassMethods+(NumClassMethods == -1 ? 0 : NumClassMethods);
}
// Get the local instance method declared in this interface.
ObjcMethodDecl *getInstanceMethodForSelector(Selector &Sel) {
for (instmeth_iterator I = instmeth_begin(), E = instmeth_end();
I != E; ++I) {
if ((*I)->getSelector() == Sel)
return *I;
}
return 0;
}
// Get the local class method declared in this interface.
ObjcMethodDecl *getClassMethodForSelector(Selector &Sel) {
for (classmeth_iterator I = classmeth_begin(), E = classmeth_end();
I != E; ++I) {
if ((*I)->getSelector() == Sel)
return *I;
}
return 0;
}
void addMethods(ObjcMethodDecl **insMethods, unsigned numInsMembers,
ObjcMethodDecl **clsMethods, unsigned numClsMembers,
@ -629,138 +821,6 @@ public:
static bool classof(const ObjcImplementationDecl *D) { return true; }
};
/// ObjcMethodDecl - Represents an instance or class method declaration.
/// ObjC methods can be declared within 4 contexts: class interfaces,
/// categories, protocols, and class implementations. While C++ member
/// functions leverage C syntax, Objective-C method syntax is modeled after
/// Smalltalk (using colons to specify argument types/expressions).
/// Here are some brief examples:
///
/// Setter/getter instance methods:
/// - (void)setMenu:(NSMenu *)menu;
/// - (NSMenu *)menu;
///
/// Instance method that takes 2 NSView arguments:
/// - (void)replaceSubview:(NSView *)oldView with:(NSView *)newView;
///
/// Getter class method:
/// + (NSMenu *)defaultMenu;
///
/// A selector represents a unique name for a method. The selector names for
/// the above methods are setMenu:, menu, replaceSubview:with:, and defaultMenu.
///
class ObjcMethodDecl : public Decl {
public:
enum ImplementationControl { None, Required, Optional };
private:
/// Bitfields must be first fields in this class so they pack with those
/// declared in class Decl.
/// instance (true) or class (false) method.
bool IsInstance : 1;
bool IsVariadic : 1;
/// @required/@optional
ImplementationControl DeclImplementation : 2;
/// in, inout, etc.
ObjcDeclQualifier objcDeclQualifier : 6;
// Context this method is declared in.
NamedDecl *MethodContext;
// A unigue name for this method.
Selector SelName;
// Type of this method.
QualType MethodDeclType;
/// ParamInfo - new[]'d array of pointers to VarDecls for the formal
/// parameters of this Method. This is null if there are no formals.
ParmVarDecl **ParamInfo;
int NumMethodParams; // -1 if no parameters
/// List of attributes for this method declaration.
AttributeList *MethodAttrs;
SourceLocation EndLoc; // the location of the ';' or '{'.
// The following are only used for method definitions, null otherwise.
// FIXME: space savings opportunity, consider a sub-class.
Stmt *Body;
ParmVarDecl *SelfDecl;
public:
ObjcMethodDecl(SourceLocation beginLoc, SourceLocation endLoc,
Selector SelInfo, QualType T,
Decl *contextDecl,
ParmVarDecl **paramInfo = 0, int numParams=-1,
AttributeList *M = 0, bool isInstance = true,
bool isVariadic = false,
ImplementationControl impControl = None,
Decl *PrevDecl = 0)
: Decl(ObjcMethod, beginLoc),
IsInstance(isInstance), IsVariadic(isVariadic),
DeclImplementation(impControl), objcDeclQualifier(OBJC_TQ_None),
MethodContext(static_cast<NamedDecl*>(contextDecl)),
SelName(SelInfo), MethodDeclType(T),
ParamInfo(paramInfo), NumMethodParams(numParams),
MethodAttrs(M), EndLoc(endLoc), Body(0), SelfDecl(0) {}
virtual ~ObjcMethodDecl();
ObjcDeclQualifier getObjcDeclQualifier() const { return objcDeclQualifier; }
void setObjcDeclQualifier(ObjcDeclQualifier QV) { objcDeclQualifier = QV; }
// Location information, modeled after the Stmt API.
SourceLocation getLocStart() const { return getLocation(); }
SourceLocation getLocEnd() const { return EndLoc; }
NamedDecl *getMethodContext() const { return MethodContext; }
ObjcInterfaceDecl *const getClassInterface() const {
if (ObjcInterfaceDecl *ID = dyn_cast<ObjcInterfaceDecl>(MethodContext))
return ID;
if (ObjcCategoryDecl *CD = dyn_cast<ObjcCategoryDecl>(MethodContext))
return CD->getClassInterface();
if (ObjcImplementationDecl *IMD =
dyn_cast<ObjcImplementationDecl>(MethodContext))
return IMD->getClassInterface();
if (ObjcCategoryImplDecl *CID =
dyn_cast<ObjcCategoryImplDecl>(MethodContext))
return CID->getClassInterface();
assert(false && "unknown method context");
return 0;
}
Selector getSelector() const { return SelName; }
QualType getResultType() const { return MethodDeclType; }
int getNumParams() const { return NumMethodParams; }
ParmVarDecl *getParamDecl(int i) const {
assert(i < getNumParams() && "Illegal param #");
return ParamInfo[i];
}
void setMethodParams(ParmVarDecl **NewParamInfo, unsigned NumParams);
AttributeList *getMethodAttrs() const {return MethodAttrs;}
bool isInstance() const { return IsInstance; }
bool isVariadic() const { return IsVariadic; }
// Related to protocols declared in @protocol
void setDeclImplementation(ImplementationControl ic) {
DeclImplementation = ic;
}
ImplementationControl getImplementationControl() const {
return DeclImplementation;
}
Stmt *const getBody() const { return Body; }
void setBody(Stmt *B) { Body = B; }
ParmVarDecl *const getSelfDecl() const { return SelfDecl; }
void setSelfDecl(ParmVarDecl *PVD) { SelfDecl = PVD; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return D->getKind() == ObjcMethod; }
static bool classof(const ObjcMethodDecl *D) { return true; }
};
/// ObjcCompatibleAliasDecl - Represents alias of a class. This alias is
/// declared as @compatibility_alias alias class.
class ObjcCompatibleAliasDecl : public ScopedDecl {