forked from OSchip/llvm-project
Settled rule on warning on unimplemented property in
category implementation when some implementations are missing in the primary class implementation. (fixes radar 6505200). llvm-svn: 94014
This commit is contained in:
parent
af362f014d
commit
4f8a57112f
|
@ -1840,6 +1840,9 @@ def err_illegal_super_cast : Error<
|
||||||
def warn_setter_getter_impl_required : Warning<
|
def warn_setter_getter_impl_required : Warning<
|
||||||
"property %0 requires method %1 to be defined - "
|
"property %0 requires method %1 to be defined - "
|
||||||
"use @synthesize, @dynamic or provide a method implementation">;
|
"use @synthesize, @dynamic or provide a method implementation">;
|
||||||
|
def warn_setter_getter_impl_required_in_category : Warning<
|
||||||
|
"property %0 requires method %1 to be defined - "
|
||||||
|
"use @dynamic or provide a method implementation in category">;
|
||||||
def note_property_impl_required : Note<
|
def note_property_impl_required : Note<
|
||||||
"implementation is here">;
|
"implementation is here">;
|
||||||
|
|
||||||
|
|
|
@ -1101,6 +1101,17 @@ void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl,
|
||||||
E = IDecl->protocol_end(); PI != E; ++PI)
|
E = IDecl->protocol_end(); PI != E; ++PI)
|
||||||
CollectImmediateProperties((*PI), PropMap);
|
CollectImmediateProperties((*PI), PropMap);
|
||||||
}
|
}
|
||||||
|
if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) {
|
||||||
|
for (ObjCContainerDecl::prop_iterator P = CATDecl->prop_begin(),
|
||||||
|
E = CATDecl->prop_end(); P != E; ++P) {
|
||||||
|
ObjCPropertyDecl *Prop = (*P);
|
||||||
|
PropMap[Prop->getIdentifier()] = Prop;
|
||||||
|
}
|
||||||
|
// scan through class's protocols.
|
||||||
|
for (ObjCInterfaceDecl::protocol_iterator PI = CATDecl->protocol_begin(),
|
||||||
|
E = CATDecl->protocol_end(); PI != E; ++PI)
|
||||||
|
CollectImmediateProperties((*PI), PropMap);
|
||||||
|
}
|
||||||
else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) {
|
else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) {
|
||||||
for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
|
for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
|
||||||
E = PDecl->prop_end(); P != E; ++P) {
|
E = PDecl->prop_end(); P != E; ++P) {
|
||||||
|
@ -1141,6 +1152,8 @@ void Sema::DiagnoseUnimplementedProperties(ObjCImplDecl* IMPDecl,
|
||||||
|
|
||||||
if (!InsMap.count(Prop->getGetterName())) {
|
if (!InsMap.count(Prop->getGetterName())) {
|
||||||
Diag(Prop->getLocation(),
|
Diag(Prop->getLocation(),
|
||||||
|
isa<ObjCCategoryDecl>(CDecl) ?
|
||||||
|
diag::warn_setter_getter_impl_required_in_category :
|
||||||
diag::warn_setter_getter_impl_required)
|
diag::warn_setter_getter_impl_required)
|
||||||
<< Prop->getDeclName() << Prop->getGetterName();
|
<< Prop->getDeclName() << Prop->getGetterName();
|
||||||
Diag(IMPDecl->getLocation(),
|
Diag(IMPDecl->getLocation(),
|
||||||
|
@ -1149,6 +1162,8 @@ void Sema::DiagnoseUnimplementedProperties(ObjCImplDecl* IMPDecl,
|
||||||
|
|
||||||
if (!Prop->isReadOnly() && !InsMap.count(Prop->getSetterName())) {
|
if (!Prop->isReadOnly() && !InsMap.count(Prop->getSetterName())) {
|
||||||
Diag(Prop->getLocation(),
|
Diag(Prop->getLocation(),
|
||||||
|
isa<ObjCCategoryDecl>(CDecl) ?
|
||||||
|
diag::warn_setter_getter_impl_required_in_category :
|
||||||
diag::warn_setter_getter_impl_required)
|
diag::warn_setter_getter_impl_required)
|
||||||
<< Prop->getDeclName() << Prop->getSetterName();
|
<< Prop->getDeclName() << Prop->getSetterName();
|
||||||
Diag(IMPDecl->getLocation(),
|
Diag(IMPDecl->getLocation(),
|
||||||
|
@ -1212,6 +1227,17 @@ void Sema::ImplMethodsVsClassMethods(ObjCImplDecl* IMPDecl,
|
||||||
E = C->protocol_end(); PI != E; ++PI)
|
E = C->protocol_end(); PI != E; ++PI)
|
||||||
CheckProtocolMethodDefs(IMPDecl->getLocation(), *PI, IncompleteImpl,
|
CheckProtocolMethodDefs(IMPDecl->getLocation(), *PI, IncompleteImpl,
|
||||||
InsMap, ClsMap, C->getClassInterface());
|
InsMap, ClsMap, C->getClassInterface());
|
||||||
|
// Report unimplemented properties in the category as well.
|
||||||
|
// When reporting on missing setter/getters, do not report when
|
||||||
|
// setter/getter is implemented in category's primary class
|
||||||
|
// implementation.
|
||||||
|
if (ObjCInterfaceDecl *ID = C->getClassInterface())
|
||||||
|
if (ObjCImplDecl *IMP = ID->getImplementation()) {
|
||||||
|
for (ObjCImplementationDecl::instmeth_iterator
|
||||||
|
I = IMP->instmeth_begin(), E = IMP->instmeth_end(); I!=E; ++I)
|
||||||
|
InsMap.insert((*I)->getSelector());
|
||||||
|
}
|
||||||
|
DiagnoseUnimplementedProperties(IMPDecl, CDecl, InsMap);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
assert(false && "invalid ObjCContainerDecl type.");
|
assert(false && "invalid ObjCContainerDecl type.");
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
|
|
||||||
@protocol MyProtocol
|
@protocol MyProtocol
|
||||||
@property float myFloat;
|
@property float myFloat;
|
||||||
@property float anotherFloat;
|
@property float anotherFloat; // expected-warning {{property 'anotherFloat' requires method 'anotherFloat' to be defined - use @dynamic}} \
|
||||||
|
// expected-warning {{property 'anotherFloat' requires method 'setAnotherFloat:' to be defined }}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface MyObject { float anotherFloat; }
|
@interface MyObject { float anotherFloat; }
|
||||||
|
@ -13,7 +14,7 @@
|
||||||
@interface MyObject (CAT) <MyProtocol>
|
@interface MyObject (CAT) <MyProtocol>
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation MyObject (CAT)
|
@implementation MyObject (CAT) // expected-note 2 {{implementation is here}}
|
||||||
@dynamic myFloat; // OK
|
@dynamic myFloat; // OK
|
||||||
@synthesize anotherFloat; // expected-error {{@synthesize not allowed in a category's implementation}}
|
@synthesize anotherFloat; // expected-error {{@synthesize not allowed in a category's implementation}}
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||||
|
|
||||||
|
/* This test is for categories which don't implement the accessors but some accessors are
|
||||||
|
implemented in their base class implementation. In this case,no warning must be issued.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@interface MyClass
|
||||||
|
{
|
||||||
|
int _foo;
|
||||||
|
}
|
||||||
|
@property(readonly) int foo;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation MyClass
|
||||||
|
- (int) foo { return _foo; }
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface MyClass (private)
|
||||||
|
@property(readwrite) int foo;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation MyClass (private)
|
||||||
|
- (void) setFoo:(int)foo { _foo = foo; }
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface MyClass (public)
|
||||||
|
@property(readwrite) int foo; // expected-warning {{property 'foo' requires method 'setFoo:' to be defined }}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation MyClass (public)// expected-note {{implementation is here}}
|
||||||
|
@end
|
|
@ -11,7 +11,8 @@
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface I(CAT)
|
@interface I(CAT)
|
||||||
@property int d1;
|
@property int d1; // expected-warning {{property 'd1' requires method 'd1' to be defined }} \
|
||||||
|
// expected-warning {{property 'd1' requires method 'setD1:' to be defined }}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation I
|
@implementation I
|
||||||
|
@ -22,7 +23,7 @@
|
||||||
@synthesize name; // OK! property with same name as an accessible ivar of same name
|
@synthesize name; // OK! property with same name as an accessible ivar of same name
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation I(CAT)
|
@implementation I(CAT) // expected-note 2 {{implementation is here}}
|
||||||
@synthesize d1; // expected-error {{@synthesize not allowed in a category's implementation}}
|
@synthesize d1; // expected-error {{@synthesize not allowed in a category's implementation}}
|
||||||
@dynamic bad; // expected-error {{property implementation must have its declaration in the category 'CAT'}}
|
@dynamic bad; // expected-error {{property implementation must have its declaration in the category 'CAT'}}
|
||||||
@end
|
@end
|
||||||
|
|
Loading…
Reference in New Issue