Patch to implement required warnings for unimplemented

properties imported frfom protocol. Fixes radar 7544809.

llvm-svn: 93965
This commit is contained in:
Fariborz Jahanian 2010-01-20 01:51:55 +00:00
parent 1bcb2631e6
commit 98609b3a07
4 changed files with 103 additions and 41 deletions

View File

@ -1278,9 +1278,6 @@ public:
const llvm::DenseSet<Selector> &InsMap,
const llvm::DenseSet<Selector> &ClsMap,
ObjCInterfaceDecl *IDecl);
void CheckPropertyImplementation(ObjCImplDecl* IMPDecl,
ObjCInterfaceDecl *CDecl);
/// CheckImplementationIvars - This routine checks if the instance variables
/// listed in the implelementation match those listed in the interface.
@ -1294,6 +1291,17 @@ public:
ObjCContainerDecl* IDecl,
bool IncompleteImpl = false);
/// DiagnoseUnimplementedProperties - This routine warns on those properties
/// which must be implemented by this implementation.
void DiagnoseUnimplementedProperties(ObjCImplDecl* IMPDecl,
ObjCContainerDecl *CDecl,
const llvm::DenseSet<Selector>& InsMap);
/// 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<IdentifierInfo *, ObjCPropertyDecl*>& PropMap);
/// AtomicPropertySetterGetterRules - This routine enforces the rule (via
/// warning) when atomic property has one but not the other user-declared
/// setter or getter.

View File

@ -1086,11 +1086,75 @@ void Sema::MatchAllMethodDeclarations(const llvm::DenseSet<Selector> &InsMap,
}
}
/// CheckPropertyImplementation - Check that all required properties are
/// synthesized in class's implementation. This includes properties
/// declared in current class and in class's protocols (direct or indirect).
void Sema::CheckPropertyImplementation(ObjCImplDecl* IMPDecl,
ObjCInterfaceDecl *CDecl) {
/// 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<IdentifierInfo *, ObjCPropertyDecl*>& PropMap) {
if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) {
for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(),
E = IDecl->prop_end(); P != E; ++P) {
ObjCPropertyDecl *Prop = (*P);
PropMap[Prop->getIdentifier()] = Prop;
}
// scan through class's protocols.
for (ObjCInterfaceDecl::protocol_iterator PI = IDecl->protocol_begin(),
E = IDecl->protocol_end(); PI != E; ++PI)
CollectImmediateProperties((*PI), PropMap);
}
else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(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;
}
// scan through protocol's protocols.
for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(),
E = PDecl->protocol_end(); PI != E; ++PI)
CollectImmediateProperties((*PI), PropMap);
}
}
void Sema::DiagnoseUnimplementedProperties(ObjCImplDecl* IMPDecl,
ObjCContainerDecl *CDecl,
const llvm::DenseSet<Selector>& InsMap) {
llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> PropMap;
CollectImmediateProperties(CDecl, PropMap);
for (llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>::iterator
P = PropMap.begin(), E = PropMap.end(); P != E; ++P) {
ObjCPropertyDecl *Prop = P->second;
if (Prop->isInvalidDecl() ||
Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional)
continue;
ObjCPropertyImplDecl *PI = 0;
// Is there a matching propery synthesize/dynamic?
for (ObjCImplDecl::propimpl_iterator
I = IMPDecl->propimpl_begin(),
EI = IMPDecl->propimpl_end(); I != EI; ++I)
if ((*I)->getPropertyDecl() == Prop) {
PI = (*I);
break;
}
if (PI)
continue;
if (!InsMap.count(Prop->getGetterName())) {
Diag(Prop->getLocation(),
diag::warn_setter_getter_impl_required)
<< Prop->getDeclName() << Prop->getGetterName();
Diag(IMPDecl->getLocation(),
diag::note_property_impl_required);
}
if (!Prop->isReadOnly() && !InsMap.count(Prop->getSetterName())) {
Diag(Prop->getLocation(),
diag::warn_setter_getter_impl_required)
<< Prop->getDeclName() << Prop->getSetterName();
Diag(IMPDecl->getLocation(),
diag::note_property_impl_required);
}
}
}
void Sema::ImplMethodsVsClassMethods(ObjCImplDecl* IMPDecl,
@ -1107,39 +1171,8 @@ void Sema::ImplMethodsVsClassMethods(ObjCImplDecl* IMPDecl,
// an implementation or 2) there is a @synthesize/@dynamic implementation
// of the property in the @implementation.
if (isa<ObjCInterfaceDecl>(CDecl))
for (ObjCContainerDecl::prop_iterator P = CDecl->prop_begin(),
E = CDecl->prop_end(); P != E; ++P) {
ObjCPropertyDecl *Prop = (*P);
if (Prop->isInvalidDecl())
continue;
ObjCPropertyImplDecl *PI = 0;
// Is there a matching propery synthesize/dynamic?
for (ObjCImplDecl::propimpl_iterator
I = IMPDecl->propimpl_begin(),
EI = IMPDecl->propimpl_end(); I != EI; ++I)
if ((*I)->getPropertyDecl() == Prop) {
PI = (*I);
break;
}
if (PI)
continue;
if (!InsMap.count(Prop->getGetterName())) {
Diag(Prop->getLocation(),
diag::warn_setter_getter_impl_required)
<< Prop->getDeclName() << Prop->getGetterName();
Diag(IMPDecl->getLocation(),
diag::note_property_impl_required);
}
if (!Prop->isReadOnly() && !InsMap.count(Prop->getSetterName())) {
Diag(Prop->getLocation(),
diag::warn_setter_getter_impl_required)
<< Prop->getDeclName() << Prop->getSetterName();
Diag(IMPDecl->getLocation(),
diag::note_property_impl_required);
}
}
DiagnoseUnimplementedProperties(IMPDecl, CDecl, InsMap);
llvm::DenseSet<Selector> ClsMap;
for (ObjCImplementationDecl::classmeth_iterator
I = IMPDecl->classmeth_begin(),

View File

@ -12,6 +12,7 @@ void test() {
}
@protocol P1
@optional
@property int *sprop; // expected-note{{'sprop' declared here}}
@end

View File

@ -0,0 +1,20 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
@protocol PROTOCOL0
@required
@property float MyProperty0; // expected-warning {{property 'MyProperty0' requires method 'MyProperty0' to be defined }} \
// expected-warning {{property 'MyProperty0' requires method 'setMyProperty0:' to be defined}}
@end
@protocol PROTOCOL<PROTOCOL0>
@required
@property float MyProperty; // expected-warning {{property 'MyProperty' requires method 'MyProperty' to be defined}} \
// expected-warning {{property 'MyProperty' requires method 'setMyProperty:' to be defined}}
@optional
@property float OptMyProperty;
@end
@interface I <PROTOCOL>
@end
@implementation I @end // expected-note 4 {{implementation is here}}