forked from OSchip/llvm-project
ObjectiveC Class Properties: warn if a class property accessor is mistakenly an
instance method. When diagnosing unimplemented class property, make sure we emit a warning when we only see an instance method with the right selector. Also warn when we only see a class method for an instance property. rdar://26141719 llvm-svn: 269968
This commit is contained in:
parent
8beed747ce
commit
08ce73470c
|
@ -1763,19 +1763,23 @@ void Sema::DefaultSynthesizeProperties(Scope *S, Decl *D) {
|
|||
DefaultSynthesizeProperties(S, IC, IDecl);
|
||||
}
|
||||
|
||||
static void DiagnoseUnimplementedAccessor(Sema &S,
|
||||
ObjCInterfaceDecl *PrimaryClass,
|
||||
Selector Method,
|
||||
ObjCImplDecl* IMPDecl,
|
||||
ObjCContainerDecl *CDecl,
|
||||
ObjCCategoryDecl *C,
|
||||
ObjCPropertyDecl *Prop,
|
||||
Sema::SelectorSet &SMap) {
|
||||
static void DiagnoseUnimplementedAccessor(
|
||||
Sema &S, ObjCInterfaceDecl *PrimaryClass, Selector Method,
|
||||
ObjCImplDecl *IMPDecl, ObjCContainerDecl *CDecl, ObjCCategoryDecl *C,
|
||||
ObjCPropertyDecl *Prop,
|
||||
llvm::SmallPtrSet<const ObjCMethodDecl *, 8> &SMap) {
|
||||
// Check to see if we have a corresponding selector in SMap and with the
|
||||
// right method type.
|
||||
auto I = std::find_if(SMap.begin(), SMap.end(),
|
||||
[&](const ObjCMethodDecl *x) {
|
||||
return x->getSelector() == Method &&
|
||||
x->isClassMethod() == Prop->isClassProperty();
|
||||
});
|
||||
// When reporting on missing property setter/getter implementation in
|
||||
// categories, do not report when they are declared in primary class,
|
||||
// class's protocol, or one of it super classes. This is because,
|
||||
// the class is going to implement them.
|
||||
if (!SMap.count(Method) &&
|
||||
if (I == SMap.end() &&
|
||||
(PrimaryClass == nullptr ||
|
||||
!PrimaryClass->lookupPropertyAccessor(Method, C,
|
||||
Prop->isClassProperty()))) {
|
||||
|
@ -1867,10 +1871,10 @@ void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl,
|
|||
for (const auto *I : IMPDecl->property_impls())
|
||||
PropImplMap.insert(I->getPropertyDecl());
|
||||
|
||||
SelectorSet InsMap;
|
||||
llvm::SmallPtrSet<const ObjCMethodDecl *, 8> InsMap;
|
||||
// Collect property accessors implemented in current implementation.
|
||||
for (const auto *I : IMPDecl->methods())
|
||||
InsMap.insert(I->getSelector());
|
||||
InsMap.insert(I);
|
||||
|
||||
ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl);
|
||||
ObjCInterfaceDecl *PrimaryClass = nullptr;
|
||||
|
@ -1882,7 +1886,7 @@ void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl,
|
|||
// setter/getter is implemented in category's primary class
|
||||
// implementation.
|
||||
for (const auto *I : IMP->methods())
|
||||
InsMap.insert(I->getSelector());
|
||||
InsMap.insert(I);
|
||||
}
|
||||
|
||||
for (ObjCContainerDecl::PropertyMap::iterator
|
||||
|
|
|
@ -43,3 +43,16 @@ void message_id(id me) {
|
|||
void message_class(Class me) {
|
||||
[me c2];
|
||||
}
|
||||
|
||||
@interface NSObject
|
||||
@end
|
||||
|
||||
@interface MyClass : NSObject
|
||||
@property(class, readonly) int classProp; // expected-note {{property declared here}}
|
||||
@end
|
||||
|
||||
@implementation MyClass // expected-warning {{class property 'classProp' requires method 'classProp' to be defined}}
|
||||
- (int)classProp { // Oops, mistakenly made this an instance method.
|
||||
return 8;
|
||||
}
|
||||
@end
|
||||
|
|
Loading…
Reference in New Issue