From 339798eae1eb61c50ca68766ed028c0a16d0a284 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Mon, 5 Oct 2009 20:41:32 +0000 Subject: [PATCH] Patch to implement Protocols on class extensions. Protocols on class extensions don't work git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@83322 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/DeclObjC.h | 5 +++ lib/AST/DeclObjC.cpp | 41 +++++++++++++++++++ lib/Sema/SemaDeclObjC.cpp | 11 ++++- test/CodeGenObjC/protocol-in-extended-class.m | 29 +++++++++++++ 4 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 test/CodeGenObjC/protocol-in-extended-class.m diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index fec2607fac..2b12bb5c1b 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -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); } diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index 4185ac1682..e978a5b60f 100644 --- a/lib/AST/DeclObjC.cpp +++ b/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 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/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index c11b4e0666..51651ab4bb 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/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); diff --git a/test/CodeGenObjC/protocol-in-extended-class.m b/test/CodeGenObjC/protocol-in-extended-class.m new file mode 100644 index 0000000000..87bda46fae --- /dev/null +++ b/test/CodeGenObjC/protocol-in-extended-class.m @@ -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 { +} +-(void) Meth; +@end + +@interface ItDoesntWork() +@end + +@implementation ItDoesntWork +-(void) Meth { + ItDoesntWork *p = 0; + } +@end + +// CHECK-LP64: l_OBJC_PROTOCOL_$_ExtendedProtocol: + +// CHECK-LP32: L_OBJC_PROTOCOL_ExtendedProtocol: -- 2.40.0