From: Steve Naroff Date: Mon, 12 Nov 2007 22:05:31 +0000 (+0000) Subject: Add category method definitions incrementally, removing a FIXME (like we do for class... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e1e6c0d5c79c0ee7ed62fef47a19aa7ecef40db4;p=clang Add category method definitions incrementally, removing a FIXME (like we do for class implementations). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@44027 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/AST/Decl.cpp b/AST/Decl.cpp index b09960eab1..b7f85e9a53 100644 --- a/AST/Decl.cpp +++ b/AST/Decl.cpp @@ -388,26 +388,6 @@ void ObjcCategoryDecl::addMethods(ObjcMethodDecl **insMethods, AtEndLoc = endLoc; } -/// addMethods - Insert instance and methods declarations into -/// ObjcCategoryImplDecl's CatInsMethods and CatClsMethods fields. -/// -void ObjcCategoryImplDecl::addMethods(ObjcMethodDecl **insMethods, - unsigned numInsMembers, - ObjcMethodDecl **clsMethods, - unsigned numClsMembers, - SourceLocation AtEndLoc) { - NumInstanceMethods = numInsMembers; - if (numInsMembers) { - InstanceMethods = new ObjcMethodDecl*[numInsMembers]; - memcpy(InstanceMethods, insMethods, numInsMembers*sizeof(ObjcMethodDecl*)); - } - NumClassMethods = numClsMembers; - if (numClsMembers) { - ClassMethods = new ObjcMethodDecl*[numClsMembers]; - memcpy(ClassMethods, clsMethods, numClsMembers*sizeof(ObjcMethodDecl*)); - } -} - ObjcIvarDecl *ObjcInterfaceDecl::lookupInstanceVariable( IdentifierInfo *ID, ObjcInterfaceDecl *&clsDeclared) { ObjcInterfaceDecl* ClassDecl = this; @@ -535,3 +515,30 @@ ObjcMethodDecl *ObjcImplementationDecl::lookupClassMethod(Selector &Sel) { return NULL; } +// lookupInstanceMethod - This method returns an instance method by looking in +// the class implementation. Unlike interfaces, we don't look outside the +// implementation. +ObjcMethodDecl *ObjcCategoryImplDecl::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]; + } + } + return NULL; +} + +// lookupClassMethod - This method returns an instance method by looking in +// the class implementation. Unlike interfaces, we don't look outside the +// implementation. +ObjcMethodDecl *ObjcCategoryImplDecl::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]; + } + } + return NULL; +} diff --git a/Sema/SemaDecl.cpp b/Sema/SemaDecl.cpp index cd47b94c19..65488cafa7 100644 --- a/Sema/SemaDecl.cpp +++ b/Sema/SemaDecl.cpp @@ -1522,7 +1522,7 @@ void Sema::ImplCategoryMethodsVsIntfMethods(ObjcCategoryImplDecl *CatImplDecl, llvm::DenseSet InsMap; // Check and see if instance methods in category interface have been // implemented in its implementation class. - ObjcMethodDecl **methods = CatImplDecl->getInstanceMethods(); + ObjcMethodDecl *const*methods = CatImplDecl->getInstanceMethods(); for (int i=0; i < CatImplDecl->getNumInstanceMethods(); i++) InsMap.insert(methods[i]->getSelector()); @@ -2070,8 +2070,7 @@ void Sema::ActOnAtEnd(SourceLocation AtEndLoc, DeclTy *classDecl, ImplMethodsVsClassMethods(IC, IDecl); } else { ObjcCategoryImplDecl* CatImplClass = cast(ClassDecl); - CatImplClass->addMethods(&insMethods[0], insMethods.size(), - &clsMethods[0], clsMethods.size(), AtEndLoc); + CatImplClass->setLocEnd(AtEndLoc); ObjcInterfaceDecl* IDecl = CatImplClass->getClassInterface(); // Find category interface decl and then check that all methods declared // in this interface is implemented in the category @implementation. @@ -2143,13 +2142,14 @@ Sema::DeclTy *Sema::ActOnMethodDeclaration( Decl *CDecl = static_cast(ClassDecl); ObjcInterfaceDecl *IDecl = 0; ObjcImplementationDecl *ImpDecl = 0; + ObjcCategoryImplDecl *CatImpDecl = 0; if (isa(CDecl)) IDecl = cast(CDecl); else if (isa(CDecl)) IDecl = cast(CDecl)->getClassInterface(); // FIXME: what is this? (talk to fariborz) else if ((ImpDecl = dyn_cast(CDecl))) IDecl = ImpDecl->getClassInterface(); // FIXME: what is this? (talk to fariborz) - else if (isa(CDecl)) + else if ((CatImpDecl = dyn_cast(CDecl))) IDecl = cast(CDecl)->getClassInterface(); // FIXME: what is this? (talk to fariborz) ObjcMethodDecl* ObjcMethod = new ObjcMethodDecl(MethodLoc, EndLoc, Sel, @@ -2163,13 +2163,12 @@ Sema::DeclTy *Sema::ActOnMethodDeclaration( ObjcMethod->setMethodParams(&Params[0], Sel.getNumArgs()); ObjcMethod->setObjcDeclQualifier( CvtQTToAstBitMask(ReturnQT.getObjcDeclQualifier())); + const ObjcMethodDecl *PrevMethod = 0; + // For implementations (which can be very "coarse grain"), we add the + // method now. This allows the AST to implement lookup methods that work + // incrementally (without waiting until we parse the @end). It also allows + // us to flag multiple declaration errors as they occur. if (ImpDecl) { - // For implementations (which can be very "coarse grain"), we add the - // method now. This allows the AST to implement lookup methods that work - // incrementally (without waiting until we parse the @end). It also allows - // us to flag multiple declaration errors as they occur. - // FIXME: still need to do this for ObjcCategoryImplDecl. - const ObjcMethodDecl *PrevMethod = 0; if (MethodType == tok::minus) { PrevMethod = ImpDecl->lookupInstanceMethod(Sel); ImpDecl->addInstanceMethod(ObjcMethod); @@ -2177,13 +2176,21 @@ Sema::DeclTy *Sema::ActOnMethodDeclaration( PrevMethod = ImpDecl->lookupClassMethod(Sel); ImpDecl->addClassMethod(ObjcMethod); } - if (PrevMethod) { - // You can never have two method definitions with the same name. - Diag(ObjcMethod->getLocation(), diag::error_duplicate_method_decl, - ObjcMethod->getSelector().getName()); - Diag(PrevMethod->getLocation(), diag::err_previous_declaration); - } + } else if (CatImpDecl) { + if (MethodType == tok::minus) { + PrevMethod = CatImpDecl->lookupInstanceMethod(Sel); + CatImpDecl->addInstanceMethod(ObjcMethod); + } else { + PrevMethod = CatImpDecl->lookupClassMethod(Sel); + CatImpDecl->addClassMethod(ObjcMethod); + } } + if (PrevMethod) { + // You can never have two method definitions with the same name. + Diag(ObjcMethod->getLocation(), diag::error_duplicate_method_decl, + ObjcMethod->getSelector().getName()); + Diag(PrevMethod->getLocation(), diag::err_previous_declaration); + } return ObjcMethod; } diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index db40ba904b..9320c60d25 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -572,36 +572,47 @@ class ObjcCategoryImplDecl : public NamedDecl { /// Class interface for this category implementation ObjcInterfaceDecl *ClassInterface; - /// category instance methods being implemented - ObjcMethodDecl **InstanceMethods; // Null if category is not implementing any - int NumInstanceMethods; // -1 if category is not implementing any - - /// category class methods being implemented - ObjcMethodDecl **ClassMethods; // Null if category is not implementing any - int NumClassMethods; // -1 if category is not implementing any + /// implemented instance methods + llvm::SmallVector InstanceMethods; - public: + /// implemented class methods + llvm::SmallVector ClassMethods; + + SourceLocation EndLoc; +public: ObjcCategoryImplDecl(SourceLocation L, IdentifierInfo *Id, ObjcInterfaceDecl *classInterface) : NamedDecl(ObjcCategoryImpl, L, Id), - ClassInterface(classInterface), - InstanceMethods(0), NumInstanceMethods(-1), - ClassMethods(0), NumClassMethods(-1) {} + ClassInterface(classInterface) {} - ObjcInterfaceDecl *getClassInterface() const { - return ClassInterface; - } - - ObjcMethodDecl **getInstanceMethods() const { return InstanceMethods; } - int getNumInstanceMethods() const { return NumInstanceMethods; } - - ObjcMethodDecl **getClassMethods() const { return ClassMethods; } - int getNumClassMethods() const { return NumClassMethods; } + ObjcInterfaceDecl *getClassInterface() const { return ClassInterface; } - void addMethods(ObjcMethodDecl **insMethods, unsigned numInsMembers, - ObjcMethodDecl **clsMethods, unsigned numClsMembers, - SourceLocation AtEndLoc); + // FIXME: Figure out how to remove the const pointer below. + ObjcMethodDecl *const*getInstanceMethods() const { + return &InstanceMethods[0]; + } + int getNumInstanceMethods() const { return InstanceMethods.size(); } + // FIXME: Figure out how to remove the const pointer below. + ObjcMethodDecl *const*getClassMethods() const { + return &ClassMethods[0]; + } + int getNumClassMethods() const { return ClassMethods.size(); } + + void addInstanceMethod(ObjcMethodDecl *method) { + InstanceMethods.push_back(method); + } + void addClassMethod(ObjcMethodDecl *method) { + ClassMethods.push_back(method); + } + ObjcMethodDecl *lookupInstanceMethod(Selector &Sel); + ObjcMethodDecl *lookupClassMethod(Selector &Sel); + + // Location information, modeled after the Stmt API. + SourceLocation getLocStart() const { return getLocation(); } + SourceLocation getLocEnd() const { return EndLoc; } + void setLocEnd(SourceLocation LE) { EndLoc = LE; }; + static bool classof(const Decl *D) { return D->getKind() == ObjcCategoryImpl;} static bool classof(const ObjcCategoryImplDecl *D) { return true; } };