From: Chris Lattner Date: Mon, 21 Jul 2008 18:19:38 +0000 (+0000) Subject: introduce a new ObjCList templated class and start moving X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3db6cae19c236fe2cef343c90105ce7cca7de965;p=clang introduce a new ObjCList templated class and start moving various objc lists over to it. First up, the protocol list on ObjCInterfaceDecl. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@53856 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/Driver/ASTConsumers.cpp b/Driver/ASTConsumers.cpp index 4e909fc908..efeb9be892 100644 --- a/Driver/ASTConsumers.cpp +++ b/Driver/ASTConsumers.cpp @@ -248,18 +248,16 @@ void DeclPrinter::PrintObjCInterfaceDecl(ObjCInterfaceDecl *OID) { Out << "@interface " << I; // Protocols? - int count = OID->getNumIntfRefProtocols(); - - if (count > 0) { - ObjCProtocolDecl **refProtocols = OID->getReferencedProtocols(); - for (int i = 0; i < count; i++) - Out << (i == 0 ? '<' : ',') << refProtocols[i]->getName(); + const ObjCList &Protocols = OID->getReferencedProtocols(); + if (!Protocols.empty()) { + for (ObjCList::iterator I = Protocols.begin(), + E = Protocols.end(); I != E; ++I) + Out << (I == Protocols.begin() ? '<' : ',') << (*I)->getName(); } - if (count > 0) - Out << ">\n"; - else - Out << '\n'; + if (!Protocols.empty()) + Out << ">"; + Out << '\n'; if (OID->ivar_size() > 0) { Out << '{'; diff --git a/Driver/RewriteObjC.cpp b/Driver/RewriteObjC.cpp index 80b5784bdf..7bc414c9e7 100644 --- a/Driver/RewriteObjC.cpp +++ b/Driver/RewriteObjC.cpp @@ -217,7 +217,7 @@ namespace { const char *ClassName, std::string &Result); - void RewriteObjCProtocolsMetaData(ObjCProtocolDecl **Protocols, + void RewriteObjCProtocolsMetaData(ObjCProtocolDecl *const*Protocols, int NumProtocols, const char *prefix, const char *ClassName, @@ -2364,7 +2364,7 @@ void RewriteObjC::SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl, const char *endHeader = SM->getCharacterData(L); endHeader += Lexer::MeasureTokenLength(L, *SM); - if (CDecl->getNumIntfRefProtocols()) { + if (!CDecl->getReferencedProtocols().empty()) { // advance to the end of the referenced protocols. while (endHeader < cursor && *endHeader != '>') endHeader++; endHeader++; @@ -2508,7 +2508,7 @@ void RewriteObjC::RewriteObjCMethodsMetaData(instmeth_iterator MethodBegin, } /// RewriteObjCProtocolsMetaData - Rewrite protocols meta-data. -void RewriteObjC::RewriteObjCProtocolsMetaData(ObjCProtocolDecl **Protocols, +void RewriteObjC::RewriteObjCProtocolsMetaData(ObjCProtocolDecl*const*Protocols, int NumProtocols, const char *prefix, const char *ClassName, @@ -2899,8 +2899,8 @@ void RewriteObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, false, "", IDecl->getName(), Result); // Protocols referenced in class declaration? - RewriteObjCProtocolsMetaData(CDecl->getReferencedProtocols(), - CDecl->getNumIntfRefProtocols(), + RewriteObjCProtocolsMetaData(CDecl->getReferencedProtocols().begin(), + CDecl->getReferencedProtocols().size(), "CLASS", CDecl->getName(), Result); @@ -2977,7 +2977,7 @@ void RewriteObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, } else Result += ", 0\n"; - if (CDecl->getNumIntfRefProtocols() > 0) { + if (!CDecl->getReferencedProtocols().empty()) { Result += "\t,0, (struct _objc_protocol_list *)&_OBJC_CLASS_PROTOCOLS_"; Result += CDecl->getName(); Result += ",0,0\n"; @@ -3030,7 +3030,7 @@ void RewriteObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, } else Result += ",0,0"; - if (CDecl->getNumIntfRefProtocols() > 0) { + if (!CDecl->getReferencedProtocols().empty()) { Result += ", (struct _objc_protocol_list*)&_OBJC_CLASS_PROTOCOLS_"; Result += CDecl->getName(); Result += ", 0,0\n"; diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 5f216cf00a..d35ae178d1 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -28,6 +28,48 @@ class ObjCProtocolDecl; class ObjCCategoryDecl; class ObjCPropertyDecl; class ObjCPropertyImplDecl; + + +/// ObjCList - This is a simple template class used to hold various lists of +/// decls etc, which is heavily used by the ObjC front-end. This only use case +/// this supports is setting the list all at once and then reading elements out +/// of it. +template +class ObjCList { + /// List is a new[]'d array of pointers to objects that are not owned by this + /// list. + T **List; + unsigned NumElts; + + void operator=(const ObjCList &); // DO NOT IMPLEMENT + ObjCList(const ObjCList&); // DO NOT IMPLEMENT +public: + ObjCList() : List(0), NumElts(0) {} + ~ObjCList() { + delete[] List; + } + + void set(T* const* InList, unsigned Elts) { + assert(List == 0 && "Elements already set!"); + List = new T*[Elts]; + NumElts = Elts; + memcpy(List, InList, sizeof(T*)*Elts); + } + + typedef T* const * iterator; + iterator begin() const { return List; } + iterator end() const { return List+NumElts; } + + unsigned size() const { return NumElts; } + bool empty() const { return NumElts == 0; } + + T* get(unsigned idx) const { + assert(idx < NumElts && "Invalid access"); + return List[idx]; + } +}; + + /// ObjCMethodDecl - Represents an instance or class method declaration. /// ObjC methods can be declared within 4 contexts: class interfaces, @@ -227,8 +269,7 @@ class ObjCInterfaceDecl : public NamedDecl, public DeclContext { ObjCInterfaceDecl *SuperClass; /// Protocols referenced in interface header declaration - ObjCProtocolDecl **ReferencedProtocols; // Null if none - unsigned NumReferencedProtocols; // 0 if none + ObjCList ReferencedProtocols; /// Ivars/NumIvars - This is a new[]'d array of pointers to Decls. ObjCIvarDecl **Ivars; // Null if not defined. @@ -261,8 +302,7 @@ class ObjCInterfaceDecl : public NamedDecl, public DeclContext { SourceLocation CLoc, bool FD, bool isInternal) : NamedDecl(ObjCInterface, atLoc, Id), DeclContext(ObjCInterface), TypeForDecl(0), SuperClass(0), - ReferencedProtocols(0), NumReferencedProtocols(0), Ivars(0), - NumIvars(0), + Ivars(0), NumIvars(0), InstanceMethods(0), NumInstanceMethods(0), ClassMethods(0), NumClassMethods(0), CategoryList(0), PropertyDecl(0), NumPropertyDecl(0), @@ -283,21 +323,17 @@ public: SourceLocation ClassLoc = SourceLocation(), bool ForwardDecl = false, bool isInternal = false); - - ObjCProtocolDecl **getReferencedProtocols() const { + const ObjCList &getReferencedProtocols() const { return ReferencedProtocols; } - unsigned getNumIntfRefProtocols() const { return NumReferencedProtocols; } ObjCPropertyDecl *FindPropertyDeclaration(IdentifierInfo *PropertyId) const; ObjCCategoryDecl *FindCategoryDeclaration(IdentifierInfo *CategoryId) const; ObjCIvarDecl *FindIvarDeclaration(IdentifierInfo *IvarId) const; - - typedef ObjCProtocolDecl * const * protocol_iterator; - protocol_iterator protocol_begin() const { return ReferencedProtocols; } - protocol_iterator protocol_end() const { - return ReferencedProtocols+NumReferencedProtocols; - } + + typedef ObjCList::iterator protocol_iterator; + protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();} + protocol_iterator protocol_end() const { return ReferencedProtocols.end(); } typedef ObjCIvarDecl * const *ivar_iterator; ivar_iterator ivar_begin() const { return Ivars; } @@ -323,7 +359,9 @@ public: /// addReferencedProtocols - Set the list of protocols that this interface /// implements. - void addReferencedProtocols(ObjCProtocolDecl **OID, unsigned numRefProtos); + void addReferencedProtocols(ObjCProtocolDecl * const *OID, unsigned NumRPs) { + ReferencedProtocols.set(OID, NumRPs); + } void addInstanceVariablesToClass(ObjCIvarDecl **ivars, unsigned numIvars, SourceLocation RBracLoc); diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index 5da762e1fb..7b28b10f91 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -280,18 +280,6 @@ ObjCIvarDecl * return 0; } -/// addReferencedProtocols - Set the list of protocols that this interface -/// implements. -void ObjCInterfaceDecl::addReferencedProtocols(ObjCProtocolDecl **OID, - unsigned numRefProtos) { - assert(NumReferencedProtocols == 0 && "refproto already set!"); - NumReferencedProtocols = numRefProtos; - if (numRefProtos) { - ReferencedProtocols = new ObjCProtocolDecl*[numRefProtos]; - memcpy(ReferencedProtocols, OID, numRefProtos*sizeof(ObjCProtocolDecl*)); - } -} - /// ObjCAddInstanceVariablesToClass - Inserts instance variables /// into ObjCInterfaceDecl's fields. /// @@ -539,12 +527,13 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupInstanceMethod(Selector 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++) { - if ((MethodDecl = protocols[pIdx]->getInstanceMethod(Sel))) + const ObjCList &Protocols = + ClassDecl->getReferencedProtocols(); + for (ObjCList::iterator I = Protocols.begin(), + E = Protocols.end(); I != E; ++I) + if ((MethodDecl = (*I)->getInstanceMethod(Sel))) return MethodDecl; - } + // Didn't find one yet - now look through categories. ObjCCategoryDecl *CatDecl = ClassDecl->getCategoryList(); while (CatDecl) { @@ -568,10 +557,12 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupClassMethod(Selector 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++) { - if ((MethodDecl = protocols[pIdx]->getClassMethod(Sel))) + const ObjCList &Protocols = + ClassDecl->getReferencedProtocols(); + + for (ObjCList::iterator I = Protocols.begin(), + E = Protocols.end(); I != E; ++I) { + if ((MethodDecl = (*I)->getClassMethod(Sel))) return MethodDecl; } // Didn't find one yet - now look through categories. diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 20afc5eb12..b9c15427c3 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -415,9 +415,11 @@ void CodeGenModule::EmitObjCCategoryImpl(const ObjCCategoryImplDecl *OCD) { // Collect the names of referenced protocols llvm::SmallVector Protocols; - ObjCInterfaceDecl * ClassDecl = (ObjCInterfaceDecl*)OCD->getClassInterface(); - for (unsigned i=0 ; igetNumIntfRefProtocols() ; i++) - Protocols.push_back(ClassDecl->getReferencedProtocols()[i]->getName()); + const ObjCInterfaceDecl *ClassDecl = OCD->getClassInterface(); + const ObjCList &Protos =ClassDecl->getReferencedProtocols(); + for (ObjCList::iterator I = Protos.begin(), + E = Protos.end(); I != E; ++I) + Protocols.push_back((*I)->getName()); // Generate the category Runtime->GenerateCategory(OCD->getClassInterface()->getName(), @@ -495,8 +497,10 @@ void CodeGenModule::EmitObjCClassImplementation( } // Collect the names of referenced protocols llvm::SmallVector Protocols; - for (unsigned i = 0, e = ClassDecl->getNumIntfRefProtocols() ; i < e ; i++) - Protocols.push_back(ClassDecl->getReferencedProtocols()[i]->getName()); + const ObjCList &Protos =ClassDecl->getReferencedProtocols(); + for (ObjCList::iterator I = Protos.begin(), + E = Protos.end(); I != E; ++I) + Protocols.push_back((*I)->getName()); // Generate the category Runtime->GenerateClass(ClassName, SCName, instanceSize, IvarNames, IvarTypes, diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index ad40cbe845..5188740af6 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -653,9 +653,11 @@ void Sema::ImplMethodsVsClassMethods(ObjCImplementationDecl* IMPDecl, // Check the protocol list for unimplemented methods in the @implementation // class. - ObjCProtocolDecl** protocols = IDecl->getReferencedProtocols(); - for (unsigned i = 0; i < IDecl->getNumIntfRefProtocols(); i++) - CheckProtocolMethodDefs(IMPDecl->getLocation(), protocols[i], + const ObjCList &Protocols = + IDecl->getReferencedProtocols(); + for (ObjCList::iterator I = Protocols.begin(), + E = Protocols.end(); I != E; ++I) + CheckProtocolMethodDefs(IMPDecl->getLocation(), *I, IncompleteImpl, InsMap, ClsMap); } diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 56a1f812b1..6d19b87446 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -375,9 +375,12 @@ static bool ClassImplementsProtocol(ObjCProtocolDecl *lProto, bool RHSIsQualifiedID = false) { // 1st, look up the class. - ObjCProtocolDecl **protoList = IDecl->getReferencedProtocols(); - for (unsigned i = 0; i < IDecl->getNumIntfRefProtocols(); i++) { - if (ProtocolCompatibleWithProtocol(lProto, protoList[i])) + const ObjCList &Protocols = + IDecl->getReferencedProtocols(); + + for (ObjCList::iterator PI = Protocols.begin(), + E = Protocols.end(); PI != E; ++PI) { + if (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' @@ -385,8 +388,7 @@ static bool ClassImplementsProtocol(ObjCProtocolDecl *lProto, // 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. - else if (RHSIsQualifiedID && - ProtocolCompatibleWithProtocol(protoList[i], lProto)) + if (RHSIsQualifiedID && ProtocolCompatibleWithProtocol(*PI, lProto)) return true; } @@ -394,7 +396,7 @@ static bool ClassImplementsProtocol(ObjCProtocolDecl *lProto, if (lookupCategory) for (ObjCCategoryDecl *CDecl = IDecl->getCategoryList(); CDecl; CDecl = CDecl->getNextClassCategory()) { - protoList = CDecl->getReferencedProtocols(); + ObjCProtocolDecl **protoList = CDecl->getReferencedProtocols(); for (unsigned i = 0; i < CDecl->getNumReferencedProtocols(); i++) { if (ProtocolCompatibleWithProtocol(lProto, protoList[i])) return true;