Do not issue warning on unimplemented property in the class, if it

conforms to a protocol as one of its super classes does. This is because
conforming super class will implement the property. This implements 
new warning rules for unimplemented properties (radar 7884086).

llvm-svn: 102919
This commit is contained in:
Fariborz Jahanian 2010-05-03 15:49:20 +00:00
parent f93cb3bacb
commit 58f11d6245
4 changed files with 89 additions and 3 deletions

View File

@ -1539,6 +1539,15 @@ public:
/// the class and its conforming protocols; but not those it its super class.
void CollectImmediateProperties(ObjCContainerDecl *CDecl,
llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap);
/// 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.

View File

@ -719,7 +719,10 @@ 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)
CollectImmediateProperties((*PI), PropMap);
// 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);
}
if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) {
if (!CATDecl->IsClassExtension())
@ -748,6 +751,33 @@ void Sema::CollectImmediateProperties(ObjCContainerDecl *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,

View File

@ -85,14 +85,14 @@
@interface TopClass <TopProtocol>
{
id myString; // expected-note {{previously declared 'myString' here}}
id myString;
}
@end
@interface SubClass : TopClass <TopProtocol>
@end
@implementation SubClass @end // expected-error {{property 'myString' attempting to use ivar 'myString' declared in super class 'TopClass'}}
@implementation SubClass @end
// rdar: // 7920807
@interface C @end

View File

@ -0,0 +1,47 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
// rdar: // 7884086
@interface NSObject @end
@protocol TopProtocol
@property (readonly) id myString; // expected-warning {{property 'myString' requires method 'myString' to be defined}}
@end
@protocol SubProtocol <TopProtocol>
@end
@interface TopClass : NSObject <TopProtocol> {}
@end
@interface SubClass : TopClass <SubProtocol> {}
@end
@interface SubClass1 : TopClass {}
@end
@implementation SubClass1 @end // Test1 - No Warning
@implementation TopClass // expected-note {{implementation is here}}
@end
@implementation SubClass // Test3 - No Warning
@end
@interface SubClass2 : TopClass<TopProtocol>
@end
@implementation SubClass2 @end // Test 4 - No Warning
@interface SubClass3 : TopClass<SubProtocol> @end
@implementation SubClass3 @end // Test 5 - No Warning
@interface SubClass4 : SubClass3 @end
@implementation SubClass4 @end // Test 5 - No Warning
@protocol NewProtocol
@property (readonly) id myNewString; // expected-warning {{property 'myNewString' requires method 'myNewString' to be defined}}
@end
@interface SubClass5 : SubClass4 <NewProtocol> @end
@implementation SubClass5 @end // expected-note {{implementation is here}}