Patch to implement Protocols on class extensions.

<rdar://problem/7269631> Protocols on class extensions don't work

llvm-svn: 83322
This commit is contained in:
Fariborz Jahanian 2009-10-05 20:41:32 +00:00
parent 1b7035da6f
commit 092cd6e624
4 changed files with 84 additions and 2 deletions

View File

@ -469,6 +469,11 @@ public:
ReferencedProtocols.set(List, Num, C);
}
/// mergeClassExtensionProtocolList - Merge class extension's protocol list
/// into the protocol list for this class.
void mergeClassExtensionProtocolList(ObjCProtocolDecl *const* List, unsigned Num,
ASTContext &C);
void setIVarList(ObjCIvarDecl * const *List, unsigned Num, ASTContext &C) {
IVars.set(List, Num, C);
}

View File

@ -118,6 +118,47 @@ ObjCContainerDecl::FindPropertyDeclaration(IdentifierInfo *PropertyId) const {
return 0;
}
void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
ObjCProtocolDecl *const* ExtList, unsigned ExtNum,
ASTContext &C)
{
if (ReferencedProtocols.empty()) {
ReferencedProtocols.set(ExtList, ExtNum, C);
return;
}
// Check for duplicate protocol in class's protocol list.
// This is (O)2. But it is extremely rare and number of protocols in
// class or its extension are very few.
llvm::SmallVector<ObjCProtocolDecl*, 8> ProtocolRefs;
for (unsigned i = 0; i < ExtNum; i++) {
bool protocolExists = false;
ObjCProtocolDecl *ProtoInExtension = ExtList[i];
for (protocol_iterator p = protocol_begin(), e = protocol_end();
p != e; p++) {
ObjCProtocolDecl *Proto = (*p);
if (C.ProtocolCompatibleWithProtocol(ProtoInExtension, Proto)) {
protocolExists = true;
break;
}
}
// Do we want to warn on a protocol in extension class which
// already exist in the class? Probably not.
if (!protocolExists)
ProtocolRefs.push_back(ProtoInExtension);
}
if (ProtocolRefs.empty())
return;
for (protocol_iterator p = protocol_begin(), e = protocol_end();
p != e; p++)
ProtocolRefs.push_back(*p);
ReferencedProtocols.Destroy(C);
unsigned NumProtoRefs = ProtocolRefs.size();
setProtocolList((ObjCProtocolDecl**)&ProtocolRefs[0], NumProtoRefs, C);
// Merge ProtocolRefs into class's protocol list;
}
ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(IdentifierInfo *ID,
ObjCInterfaceDecl *&clsDeclared) {
ObjCInterfaceDecl* ClassDecl = this;

View File

@ -588,9 +588,16 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
CDecl->insertNextClassCategory();
if (NumProtoRefs) {
CDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs,Context);
// Protocols in the class extension belong to the class.
if (!CDecl->getIdentifier())
IDecl->mergeClassExtensionProtocolList((ObjCProtocolDecl**)ProtoRefs,
NumProtoRefs,Context);
else {
CDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs,
Context);
CDecl->setLocEnd(EndProtoLoc);
}
}
CheckObjCDeclScope(CDecl);
return DeclPtrTy::make(CDecl);

View File

@ -0,0 +1,29 @@
// RUN: clang-cc -triple x86_64-apple-darwin10 -S %s -o %t-64.s &&
// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s &&
// RUN: clang-cc -triple i386-apple-darwin -S %s -o %t-32.s &&
// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s &&
// RUN: true
@protocol MyProtocol
@end
@protocol ExtendedProtocol
@end
@interface ItDoesntWork<MyProtocol> {
}
-(void) Meth;
@end
@interface ItDoesntWork() <MyProtocol, ExtendedProtocol>
@end
@implementation ItDoesntWork
-(void) Meth {
ItDoesntWork <MyProtocol, ExtendedProtocol> *p = 0;
}
@end
// CHECK-LP64: l_OBJC_PROTOCOL_$_ExtendedProtocol:
// CHECK-LP32: L_OBJC_PROTOCOL_ExtendedProtocol: