diff --git a/clang/AST/Decl.cpp b/clang/AST/Decl.cpp index 711b3257ec85..385a82944a55 100644 --- a/clang/AST/Decl.cpp +++ b/clang/AST/Decl.cpp @@ -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(MethodContext)) + return ID; + if (ObjcCategoryDecl *CD = dyn_cast(MethodContext)) + return CD->getClassInterface(); + if (ObjcImplementationDecl *IMD = + dyn_cast(MethodContext)) + return IMD->getClassInterface(); + if (ObjcCategoryImplDecl *CID = + dyn_cast(MethodContext)) + return CID->getClassInterface(); + assert(false && "unknown method context"); + return 0; +} diff --git a/clang/Driver/RewriteTest.cpp b/clang/Driver/RewriteTest.cpp index 7392016021e1..780fbc555ebd 100644 --- a/clang/Driver/RewriteTest.cpp +++ b/clang/Driver/RewriteTest.cpp @@ -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"; diff --git a/clang/Sema/SemaDeclObjC.cpp b/clang/Sema/SemaDeclObjC.cpp index b2cad375f8a8..d520c4f357cd 100644 --- a/clang/Sema/SemaDeclObjC.cpp +++ b/clang/Sema/SemaDeclObjC.cpp @@ -452,25 +452,27 @@ void Sema::CheckProtocolMethodDefs(ObjcProtocolDecl *PDecl, const llvm::DenseSet &InsMap, const llvm::DenseSet &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 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; } diff --git a/clang/include/clang/AST/DeclObjC.h b/clang/include/clang/AST/DeclObjC.h index 64cfb7e5bea9..40023c60eab8 100644 --- a/clang/include/clang/AST/DeclObjC.h +++ b/clang/include/clang/AST/DeclObjC.h @@ -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(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(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(MethodContext)) - return ID; - if (ObjcCategoryDecl *CD = dyn_cast(MethodContext)) - return CD->getClassInterface(); - if (ObjcImplementationDecl *IMD = - dyn_cast(MethodContext)) - return IMD->getClassInterface(); - if (ObjcCategoryImplDecl *CID = - dyn_cast(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 {