From cfa6a27f3cc5add888c6ac84dbcc45854cfd8666 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Tue, 29 Jun 2010 18:12:32 +0000 Subject: [PATCH] This patch fixes a bug whereby, clang skipped unimplemented property warning for properties coming from class's conformin protocol. It also simplifies the algorithm in the process. Fixes radar 8035776. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@107174 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/Sema.h | 11 +--- lib/Sema/SemaObjCProperty.cpp | 56 ++++++------------- .../super-class-protocol-conformance.m | 16 ++++++ 3 files changed, 36 insertions(+), 47 deletions(-) diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 325add7671..f93a9492b2 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -1573,16 +1573,9 @@ public: /// CollectImmediateProperties - This routine collects all properties in /// the class and its conforming protocols; but not those it its super class. void CollectImmediateProperties(ObjCContainerDecl *CDecl, - llvm::DenseMap& PropMap); + llvm::DenseMap& PropMap, + llvm::DenseMap& SuperPropMap); - /// ProtocolConformsToSuperClass - Returns true if class has a super class - /// and it, or its nested super class conforms to the protocol. - bool ProtocolConformsToSuperClass(const ObjCInterfaceDecl *IDecl, - const ObjCProtocolDecl *PDecl); - /// ProtocolConformsToProtocol - Returns true if 2nd Protocol (PDecl) is - /// qualified by the 1st. - bool ProtocolConformsToProtocol(const ObjCProtocolDecl *NestedProtocol, - const ObjCProtocolDecl *PDecl); /// LookupPropertyDecl - Looks up a property in the current class and all /// its protocols. diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp index a27d2a8a2f..44cd271753 100644 --- a/lib/Sema/SemaObjCProperty.cpp +++ b/lib/Sema/SemaObjCProperty.cpp @@ -778,7 +778,8 @@ bool Sema::isPropertyReadonly(ObjCPropertyDecl *PDecl, /// CollectImmediateProperties - This routine collects all properties in /// the class and its conforming protocols; but not those it its super class. void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl, - llvm::DenseMap& PropMap) { + llvm::DenseMap& PropMap, + llvm::DenseMap& SuperPropMap) { if (ObjCInterfaceDecl *IDecl = dyn_cast(CDecl)) { for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(), E = IDecl->prop_end(); P != E; ++P) { @@ -788,10 +789,7 @@ void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl, // scan through class's protocols. for (ObjCInterfaceDecl::protocol_iterator PI = IDecl->protocol_begin(), E = IDecl->protocol_end(); PI != E; ++PI) - // Exclude property for protocols which conform to class's super-class, - // as super-class has to implement the property. - if (!ProtocolConformsToSuperClass(IDecl, (*PI))) - CollectImmediateProperties((*PI), PropMap); + CollectImmediateProperties((*PI), PropMap, SuperPropMap); } if (ObjCCategoryDecl *CATDecl = dyn_cast(CDecl)) { if (!CATDecl->IsClassExtension()) @@ -803,20 +801,25 @@ void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl, // scan through class's protocols. for (ObjCInterfaceDecl::protocol_iterator PI = CATDecl->protocol_begin(), E = CATDecl->protocol_end(); PI != E; ++PI) - CollectImmediateProperties((*PI), PropMap); + CollectImmediateProperties((*PI), PropMap, SuperPropMap); } else if (ObjCProtocolDecl *PDecl = dyn_cast(CDecl)) { for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), E = PDecl->prop_end(); P != E; ++P) { ObjCPropertyDecl *Prop = (*P); - ObjCPropertyDecl *&PropEntry = PropMap[Prop->getIdentifier()]; - if (!PropEntry) - PropEntry = Prop; + ObjCPropertyDecl *PropertyFromSuper = SuperPropMap[Prop->getIdentifier()]; + // Exclude property for protocols which conform to class's super-class, + // as super-class has to implement the property. + if (!PropertyFromSuper || PropertyFromSuper != Prop) { + ObjCPropertyDecl *&PropEntry = PropMap[Prop->getIdentifier()]; + if (!PropEntry) + PropEntry = Prop; + } } // scan through protocol's protocols. for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(), E = PDecl->protocol_end(); PI != E; ++PI) - CollectImmediateProperties((*PI), PropMap); + CollectImmediateProperties((*PI), PropMap, SuperPropMap); } } @@ -861,33 +864,6 @@ static void CollectSuperClassPropertyImplementations(ObjCInterfaceDecl *CDecl, } } -/// ProtocolConformsToSuperClass - Returns true if class's given protocol -/// conforms to one of its super class's protocols. -bool Sema::ProtocolConformsToSuperClass(const ObjCInterfaceDecl *IDecl, - const ObjCProtocolDecl *PDecl) { - if (const ObjCInterfaceDecl *CDecl = IDecl->getSuperClass()) { - for (ObjCInterfaceDecl::protocol_iterator PI = CDecl->protocol_begin(), - E = CDecl->protocol_end(); PI != E; ++PI) { - if (ProtocolConformsToProtocol((*PI), PDecl)) - return true; - return ProtocolConformsToSuperClass(CDecl, PDecl); - } - } - return false; -} - -bool Sema::ProtocolConformsToProtocol(const ObjCProtocolDecl *NestedProtocol, - const ObjCProtocolDecl *PDecl) { - if (PDecl->getIdentifier() == NestedProtocol->getIdentifier()) - return true; - // scan through protocol's protocols. - for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(), - E = PDecl->protocol_end(); PI != E; ++PI) - if (ProtocolConformsToProtocol(NestedProtocol, (*PI))) - return true; - return false; -} - /// LookupPropertyDecl - Looks up a property in the current class and all /// its protocols. ObjCPropertyDecl *Sema::LookupPropertyDecl(const ObjCContainerDecl *CDecl, @@ -959,8 +935,12 @@ void Sema::DefaultSynthesizeProperties (Scope *S, ObjCImplDecl* IMPDecl, void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl, ObjCContainerDecl *CDecl, const llvm::DenseSet& InsMap) { + llvm::DenseMap SuperPropMap; + if (ObjCInterfaceDecl *IDecl = dyn_cast(CDecl)) + CollectSuperClassPropertyImplementations(IDecl, SuperPropMap); + llvm::DenseMap PropMap; - CollectImmediateProperties(CDecl, PropMap); + CollectImmediateProperties(CDecl, PropMap, SuperPropMap); if (PropMap.empty()) return; diff --git a/test/SemaObjC/super-class-protocol-conformance.m b/test/SemaObjC/super-class-protocol-conformance.m index ac8bc70a99..f555c3203d 100644 --- a/test/SemaObjC/super-class-protocol-conformance.m +++ b/test/SemaObjC/super-class-protocol-conformance.m @@ -45,3 +45,19 @@ @interface SubClass5 : SubClass4 @end @implementation SubClass5 @end // expected-note {{implementation is here}} + +// Radar 8035776 +@protocol SuperProtocol +@end + +@interface Super +@end + +@protocol ProtocolWithProperty +@property (readonly, assign) id invalidationBacktrace; // expected-warning {{property 'invalidationBacktrace' requires method 'invalidationBacktrace' to be defined}} +@end + +@interface INTF : Super +@end + +@implementation INTF @end // expected-note {{implementation is here}}