diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2009-10-05 20:41:32 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2009-10-05 20:41:32 +0000 |
commit | 092cd6e624b5348841acbbe64a99e3d4330b785a (patch) | |
tree | 8e23516823eb5924a485dac139cfbfc36b1572b0 /clang/lib | |
parent | 1b7035da6f79e1eed8fad4d38151c9a00cc716f1 (diff) | |
download | bcm5719-llvm-092cd6e624b5348841acbbe64a99e3d4330b785a.tar.gz bcm5719-llvm-092cd6e624b5348841acbbe64a99e3d4330b785a.zip |
Patch to implement Protocols on class extensions.
<rdar://problem/7269631> Protocols on class extensions don't work
llvm-svn: 83322
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/DeclObjC.cpp | 41 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclObjC.cpp | 11 |
2 files changed, 50 insertions, 2 deletions
diff --git a/clang/lib/AST/DeclObjC.cpp b/clang/lib/AST/DeclObjC.cpp index 4185ac16828..e978a5b60fa 100644 --- a/clang/lib/AST/DeclObjC.cpp +++ b/clang/lib/AST/DeclObjC.cpp @@ -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; diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index c11b4e06667..51651ab4bba 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -588,8 +588,15 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc, CDecl->insertNextClassCategory(); if (NumProtoRefs) { - CDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs,Context); - CDecl->setLocEnd(EndProtoLoc); + // 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); |