Settled rule on warning on unimplemented property in

category implementation when some implementations
are missing in the primary class implementation.
(fixes radar 6505200).


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@94014 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Fariborz Jahanian 2010-01-20 19:36:21 +00:00
Родитель 3ea5cf8889
Коммит 3ad230eb62
5 изменённых файлов: 68 добавлений и 6 удалений

Просмотреть файл

@ -1840,6 +1840,9 @@ def err_illegal_super_cast : Error<
def warn_setter_getter_impl_required : Warning<
"property %0 requires method %1 to be defined - "
"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<
"implementation is here">;

Просмотреть файл

@ -1101,6 +1101,17 @@ void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl,
E = IDecl->protocol_end(); PI != E; ++PI)
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)) {
for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
E = PDecl->prop_end(); P != E; ++P) {
@ -1141,7 +1152,9 @@ void Sema::DiagnoseUnimplementedProperties(ObjCImplDecl* IMPDecl,
if (!InsMap.count(Prop->getGetterName())) {
Diag(Prop->getLocation(),
diag::warn_setter_getter_impl_required)
isa<ObjCCategoryDecl>(CDecl) ?
diag::warn_setter_getter_impl_required_in_category :
diag::warn_setter_getter_impl_required)
<< Prop->getDeclName() << Prop->getGetterName();
Diag(IMPDecl->getLocation(),
diag::note_property_impl_required);
@ -1149,6 +1162,8 @@ void Sema::DiagnoseUnimplementedProperties(ObjCImplDecl* IMPDecl,
if (!Prop->isReadOnly() && !InsMap.count(Prop->getSetterName())) {
Diag(Prop->getLocation(),
isa<ObjCCategoryDecl>(CDecl) ?
diag::warn_setter_getter_impl_required_in_category :
diag::warn_setter_getter_impl_required)
<< Prop->getDeclName() << Prop->getSetterName();
Diag(IMPDecl->getLocation(),
@ -1212,7 +1227,18 @@ void Sema::ImplMethodsVsClassMethods(ObjCImplDecl* IMPDecl,
E = C->protocol_end(); PI != E; ++PI)
CheckProtocolMethodDefs(IMPDecl->getLocation(), *PI, IncompleteImpl,
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
assert(false && "invalid ObjCContainerDecl type.");
}

Просмотреть файл

@ -4,7 +4,8 @@
@protocol MyProtocol
@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
@interface MyObject { float anotherFloat; }
@ -13,7 +14,7 @@
@interface MyObject (CAT) <MyProtocol>
@end
@implementation MyObject (CAT)
@implementation MyObject (CAT) // expected-note 2 {{implementation is here}}
@dynamic myFloat; // OK
@synthesize anotherFloat; // expected-error {{@synthesize not allowed in a category's implementation}}
@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
@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
@implementation I
@ -22,7 +23,7 @@
@synthesize name; // OK! property with same name as an accessible ivar of same name
@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}}
@dynamic bad; // expected-error {{property implementation must have its declaration in the category 'CAT'}}
@end