introduce a new ObjCList templated class and start moving

various objc lists over to it.  First up, the protocol list 
on ObjCInterfaceDecl.

llvm-svn: 53856
This commit is contained in:
Chris Lattner 2008-07-21 18:19:38 +00:00
parent b47772535b
commit d004505b74
7 changed files with 101 additions and 66 deletions

View File

@ -248,18 +248,16 @@ void DeclPrinter::PrintObjCInterfaceDecl(ObjCInterfaceDecl *OID) {
Out << "@interface " << I; Out << "@interface " << I;
// Protocols? // Protocols?
int count = OID->getNumIntfRefProtocols(); const ObjCList<ObjCProtocolDecl> &Protocols = OID->getReferencedProtocols();
if (!Protocols.empty()) {
if (count > 0) { for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
ObjCProtocolDecl **refProtocols = OID->getReferencedProtocols(); E = Protocols.end(); I != E; ++I)
for (int i = 0; i < count; i++) Out << (I == Protocols.begin() ? '<' : ',') << (*I)->getName();
Out << (i == 0 ? '<' : ',') << refProtocols[i]->getName();
} }
if (count > 0) if (!Protocols.empty())
Out << ">\n"; Out << ">";
else Out << '\n';
Out << '\n';
if (OID->ivar_size() > 0) { if (OID->ivar_size() > 0) {
Out << '{'; Out << '{';

View File

@ -217,7 +217,7 @@ namespace {
const char *ClassName, const char *ClassName,
std::string &Result); std::string &Result);
void RewriteObjCProtocolsMetaData(ObjCProtocolDecl **Protocols, void RewriteObjCProtocolsMetaData(ObjCProtocolDecl *const*Protocols,
int NumProtocols, int NumProtocols,
const char *prefix, const char *prefix,
const char *ClassName, const char *ClassName,
@ -2364,7 +2364,7 @@ void RewriteObjC::SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl,
const char *endHeader = SM->getCharacterData(L); const char *endHeader = SM->getCharacterData(L);
endHeader += Lexer::MeasureTokenLength(L, *SM); endHeader += Lexer::MeasureTokenLength(L, *SM);
if (CDecl->getNumIntfRefProtocols()) { if (!CDecl->getReferencedProtocols().empty()) {
// advance to the end of the referenced protocols. // advance to the end of the referenced protocols.
while (endHeader < cursor && *endHeader != '>') endHeader++; while (endHeader < cursor && *endHeader != '>') endHeader++;
endHeader++; endHeader++;
@ -2508,7 +2508,7 @@ void RewriteObjC::RewriteObjCMethodsMetaData(instmeth_iterator MethodBegin,
} }
/// RewriteObjCProtocolsMetaData - Rewrite protocols meta-data. /// RewriteObjCProtocolsMetaData - Rewrite protocols meta-data.
void RewriteObjC::RewriteObjCProtocolsMetaData(ObjCProtocolDecl **Protocols, void RewriteObjC::RewriteObjCProtocolsMetaData(ObjCProtocolDecl*const*Protocols,
int NumProtocols, int NumProtocols,
const char *prefix, const char *prefix,
const char *ClassName, const char *ClassName,
@ -2899,8 +2899,8 @@ void RewriteObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
false, "", IDecl->getName(), Result); false, "", IDecl->getName(), Result);
// Protocols referenced in class declaration? // Protocols referenced in class declaration?
RewriteObjCProtocolsMetaData(CDecl->getReferencedProtocols(), RewriteObjCProtocolsMetaData(CDecl->getReferencedProtocols().begin(),
CDecl->getNumIntfRefProtocols(), CDecl->getReferencedProtocols().size(),
"CLASS", CDecl->getName(), Result); "CLASS", CDecl->getName(), Result);
@ -2977,7 +2977,7 @@ void RewriteObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
} }
else else
Result += ", 0\n"; Result += ", 0\n";
if (CDecl->getNumIntfRefProtocols() > 0) { if (!CDecl->getReferencedProtocols().empty()) {
Result += "\t,0, (struct _objc_protocol_list *)&_OBJC_CLASS_PROTOCOLS_"; Result += "\t,0, (struct _objc_protocol_list *)&_OBJC_CLASS_PROTOCOLS_";
Result += CDecl->getName(); Result += CDecl->getName();
Result += ",0,0\n"; Result += ",0,0\n";
@ -3030,7 +3030,7 @@ void RewriteObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
} }
else else
Result += ",0,0"; Result += ",0,0";
if (CDecl->getNumIntfRefProtocols() > 0) { if (!CDecl->getReferencedProtocols().empty()) {
Result += ", (struct _objc_protocol_list*)&_OBJC_CLASS_PROTOCOLS_"; Result += ", (struct _objc_protocol_list*)&_OBJC_CLASS_PROTOCOLS_";
Result += CDecl->getName(); Result += CDecl->getName();
Result += ", 0,0\n"; Result += ", 0,0\n";

View File

@ -28,6 +28,48 @@ class ObjCProtocolDecl;
class ObjCCategoryDecl; class ObjCCategoryDecl;
class ObjCPropertyDecl; class ObjCPropertyDecl;
class ObjCPropertyImplDecl; 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 <typename T>
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. /// ObjCMethodDecl - Represents an instance or class method declaration.
/// ObjC methods can be declared within 4 contexts: class interfaces, /// ObjC methods can be declared within 4 contexts: class interfaces,
@ -227,8 +269,7 @@ class ObjCInterfaceDecl : public NamedDecl, public DeclContext {
ObjCInterfaceDecl *SuperClass; ObjCInterfaceDecl *SuperClass;
/// Protocols referenced in interface header declaration /// Protocols referenced in interface header declaration
ObjCProtocolDecl **ReferencedProtocols; // Null if none ObjCList<ObjCProtocolDecl> ReferencedProtocols;
unsigned NumReferencedProtocols; // 0 if none
/// Ivars/NumIvars - This is a new[]'d array of pointers to Decls. /// Ivars/NumIvars - This is a new[]'d array of pointers to Decls.
ObjCIvarDecl **Ivars; // Null if not defined. ObjCIvarDecl **Ivars; // Null if not defined.
@ -261,8 +302,7 @@ class ObjCInterfaceDecl : public NamedDecl, public DeclContext {
SourceLocation CLoc, bool FD, bool isInternal) SourceLocation CLoc, bool FD, bool isInternal)
: NamedDecl(ObjCInterface, atLoc, Id), DeclContext(ObjCInterface), : NamedDecl(ObjCInterface, atLoc, Id), DeclContext(ObjCInterface),
TypeForDecl(0), SuperClass(0), TypeForDecl(0), SuperClass(0),
ReferencedProtocols(0), NumReferencedProtocols(0), Ivars(0), Ivars(0), NumIvars(0),
NumIvars(0),
InstanceMethods(0), NumInstanceMethods(0), InstanceMethods(0), NumInstanceMethods(0),
ClassMethods(0), NumClassMethods(0), ClassMethods(0), NumClassMethods(0),
CategoryList(0), PropertyDecl(0), NumPropertyDecl(0), CategoryList(0), PropertyDecl(0), NumPropertyDecl(0),
@ -283,21 +323,17 @@ public:
SourceLocation ClassLoc = SourceLocation(), SourceLocation ClassLoc = SourceLocation(),
bool ForwardDecl = false, bool ForwardDecl = false,
bool isInternal = false); bool isInternal = false);
const ObjCList<ObjCProtocolDecl> &getReferencedProtocols() const {
ObjCProtocolDecl **getReferencedProtocols() const {
return ReferencedProtocols; return ReferencedProtocols;
} }
unsigned getNumIntfRefProtocols() const { return NumReferencedProtocols; }
ObjCPropertyDecl *FindPropertyDeclaration(IdentifierInfo *PropertyId) const; ObjCPropertyDecl *FindPropertyDeclaration(IdentifierInfo *PropertyId) const;
ObjCCategoryDecl *FindCategoryDeclaration(IdentifierInfo *CategoryId) const; ObjCCategoryDecl *FindCategoryDeclaration(IdentifierInfo *CategoryId) const;
ObjCIvarDecl *FindIvarDeclaration(IdentifierInfo *IvarId) const; ObjCIvarDecl *FindIvarDeclaration(IdentifierInfo *IvarId) const;
typedef ObjCProtocolDecl * const * protocol_iterator; typedef ObjCList<ObjCProtocolDecl>::iterator protocol_iterator;
protocol_iterator protocol_begin() const { return ReferencedProtocols; } protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();}
protocol_iterator protocol_end() const { protocol_iterator protocol_end() const { return ReferencedProtocols.end(); }
return ReferencedProtocols+NumReferencedProtocols;
}
typedef ObjCIvarDecl * const *ivar_iterator; typedef ObjCIvarDecl * const *ivar_iterator;
ivar_iterator ivar_begin() const { return Ivars; } ivar_iterator ivar_begin() const { return Ivars; }
@ -323,7 +359,9 @@ public:
/// addReferencedProtocols - Set the list of protocols that this interface /// addReferencedProtocols - Set the list of protocols that this interface
/// implements. /// implements.
void addReferencedProtocols(ObjCProtocolDecl **OID, unsigned numRefProtos); void addReferencedProtocols(ObjCProtocolDecl * const *OID, unsigned NumRPs) {
ReferencedProtocols.set(OID, NumRPs);
}
void addInstanceVariablesToClass(ObjCIvarDecl **ivars, unsigned numIvars, void addInstanceVariablesToClass(ObjCIvarDecl **ivars, unsigned numIvars,
SourceLocation RBracLoc); SourceLocation RBracLoc);

View File

@ -280,18 +280,6 @@ ObjCIvarDecl *
return 0; 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 /// ObjCAddInstanceVariablesToClass - Inserts instance variables
/// into ObjCInterfaceDecl's fields. /// into ObjCInterfaceDecl's fields.
/// ///
@ -539,12 +527,13 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupInstanceMethod(Selector Sel) {
return MethodDecl; return MethodDecl;
// Didn't find one yet - look through protocols. // Didn't find one yet - look through protocols.
ObjCProtocolDecl **protocols = ClassDecl->getReferencedProtocols(); const ObjCList<ObjCProtocolDecl> &Protocols =
int numProtocols = ClassDecl->getNumIntfRefProtocols(); ClassDecl->getReferencedProtocols();
for (int pIdx = 0; pIdx < numProtocols; pIdx++) { for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
if ((MethodDecl = protocols[pIdx]->getInstanceMethod(Sel))) E = Protocols.end(); I != E; ++I)
if ((MethodDecl = (*I)->getInstanceMethod(Sel)))
return MethodDecl; return MethodDecl;
}
// Didn't find one yet - now look through categories. // Didn't find one yet - now look through categories.
ObjCCategoryDecl *CatDecl = ClassDecl->getCategoryList(); ObjCCategoryDecl *CatDecl = ClassDecl->getCategoryList();
while (CatDecl) { while (CatDecl) {
@ -568,10 +557,12 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupClassMethod(Selector Sel) {
return MethodDecl; return MethodDecl;
// Didn't find one yet - look through protocols. // Didn't find one yet - look through protocols.
ObjCProtocolDecl **protocols = ClassDecl->getReferencedProtocols(); const ObjCList<ObjCProtocolDecl> &Protocols =
int numProtocols = ClassDecl->getNumIntfRefProtocols(); ClassDecl->getReferencedProtocols();
for (int pIdx = 0; pIdx < numProtocols; pIdx++) {
if ((MethodDecl = protocols[pIdx]->getClassMethod(Sel))) for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
E = Protocols.end(); I != E; ++I) {
if ((MethodDecl = (*I)->getClassMethod(Sel)))
return MethodDecl; return MethodDecl;
} }
// Didn't find one yet - now look through categories. // Didn't find one yet - now look through categories.

View File

@ -415,9 +415,11 @@ void CodeGenModule::EmitObjCCategoryImpl(const ObjCCategoryImplDecl *OCD) {
// Collect the names of referenced protocols // Collect the names of referenced protocols
llvm::SmallVector<std::string, 16> Protocols; llvm::SmallVector<std::string, 16> Protocols;
ObjCInterfaceDecl * ClassDecl = (ObjCInterfaceDecl*)OCD->getClassInterface(); const ObjCInterfaceDecl *ClassDecl = OCD->getClassInterface();
for (unsigned i=0 ; i<ClassDecl->getNumIntfRefProtocols() ; i++) const ObjCList<ObjCProtocolDecl> &Protos =ClassDecl->getReferencedProtocols();
Protocols.push_back(ClassDecl->getReferencedProtocols()[i]->getName()); for (ObjCList<ObjCProtocolDecl>::iterator I = Protos.begin(),
E = Protos.end(); I != E; ++I)
Protocols.push_back((*I)->getName());
// Generate the category // Generate the category
Runtime->GenerateCategory(OCD->getClassInterface()->getName(), Runtime->GenerateCategory(OCD->getClassInterface()->getName(),
@ -495,8 +497,10 @@ void CodeGenModule::EmitObjCClassImplementation(
} }
// Collect the names of referenced protocols // Collect the names of referenced protocols
llvm::SmallVector<std::string, 16> Protocols; llvm::SmallVector<std::string, 16> Protocols;
for (unsigned i = 0, e = ClassDecl->getNumIntfRefProtocols() ; i < e ; i++) const ObjCList<ObjCProtocolDecl> &Protos =ClassDecl->getReferencedProtocols();
Protocols.push_back(ClassDecl->getReferencedProtocols()[i]->getName()); for (ObjCList<ObjCProtocolDecl>::iterator I = Protos.begin(),
E = Protos.end(); I != E; ++I)
Protocols.push_back((*I)->getName());
// Generate the category // Generate the category
Runtime->GenerateClass(ClassName, SCName, instanceSize, IvarNames, IvarTypes, Runtime->GenerateClass(ClassName, SCName, instanceSize, IvarNames, IvarTypes,

View File

@ -653,9 +653,11 @@ void Sema::ImplMethodsVsClassMethods(ObjCImplementationDecl* IMPDecl,
// Check the protocol list for unimplemented methods in the @implementation // Check the protocol list for unimplemented methods in the @implementation
// class. // class.
ObjCProtocolDecl** protocols = IDecl->getReferencedProtocols(); const ObjCList<ObjCProtocolDecl> &Protocols =
for (unsigned i = 0; i < IDecl->getNumIntfRefProtocols(); i++) IDecl->getReferencedProtocols();
CheckProtocolMethodDefs(IMPDecl->getLocation(), protocols[i], for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
E = Protocols.end(); I != E; ++I)
CheckProtocolMethodDefs(IMPDecl->getLocation(), *I,
IncompleteImpl, InsMap, ClsMap); IncompleteImpl, InsMap, ClsMap);
} }

View File

@ -375,9 +375,12 @@ static bool ClassImplementsProtocol(ObjCProtocolDecl *lProto,
bool RHSIsQualifiedID = false) { bool RHSIsQualifiedID = false) {
// 1st, look up the class. // 1st, look up the class.
ObjCProtocolDecl **protoList = IDecl->getReferencedProtocols(); const ObjCList<ObjCProtocolDecl> &Protocols =
for (unsigned i = 0; i < IDecl->getNumIntfRefProtocols(); i++) { IDecl->getReferencedProtocols();
if (ProtocolCompatibleWithProtocol(lProto, protoList[i]))
for (ObjCList<ObjCProtocolDecl>::iterator PI = Protocols.begin(),
E = Protocols.end(); PI != E; ++PI) {
if (ProtocolCompatibleWithProtocol(lProto, *PI))
return true; return true;
// This is dubious and is added to be compatible with gcc. // This is dubious and is added to be compatible with gcc.
// In gcc, it is also allowed assigning a protocol-qualified 'id' // 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. // 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 // FIXME: Treat this as an extension, and flag this as an error when
// GCC extensions are not enabled. // GCC extensions are not enabled.
else if (RHSIsQualifiedID && if (RHSIsQualifiedID && ProtocolCompatibleWithProtocol(*PI, lProto))
ProtocolCompatibleWithProtocol(protoList[i], lProto))
return true; return true;
} }
@ -394,7 +396,7 @@ static bool ClassImplementsProtocol(ObjCProtocolDecl *lProto,
if (lookupCategory) if (lookupCategory)
for (ObjCCategoryDecl *CDecl = IDecl->getCategoryList(); CDecl; for (ObjCCategoryDecl *CDecl = IDecl->getCategoryList(); CDecl;
CDecl = CDecl->getNextClassCategory()) { CDecl = CDecl->getNextClassCategory()) {
protoList = CDecl->getReferencedProtocols(); ObjCProtocolDecl **protoList = CDecl->getReferencedProtocols();
for (unsigned i = 0; i < CDecl->getNumReferencedProtocols(); i++) { for (unsigned i = 0; i < CDecl->getNumReferencedProtocols(); i++) {
if (ProtocolCompatibleWithProtocol(lProto, protoList[i])) if (ProtocolCompatibleWithProtocol(lProto, protoList[i]))
return true; return true;