From: Fariborz Jahanian Date: Fri, 10 Dec 2010 23:36:33 +0000 (+0000) Subject: Any property declared in a class extension might have user X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=88f5e9be350f4b107f8665183a6d441874e0fcc7;p=clang Any property declared in a class extension might have user declared setter or getter in current class extension or one of the other class extensions. Mark them as synthesized as property will be synthesized when property with same name is seen in the @implementation. This prevents bogus warning about unimplemented methods to be issued for these methods. Fixes // rdar://8747333 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@121597 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 57c1922292..a7014f6755 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -1522,8 +1522,29 @@ void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, // Compare protocol properties with those in category CompareProperties(C, C); - if (C->IsClassExtension()) - DiagnoseClassExtensionDupMethods(C, C->getClassInterface()); + if (C->IsClassExtension()) { + ObjCInterfaceDecl *CCPrimary = C->getClassInterface(); + DiagnoseClassExtensionDupMethods(C, CCPrimary); + for (ObjCContainerDecl::prop_iterator I = C->prop_begin(), + E = C->prop_end(); I != E; ++I) { + // Any property declared in a class extension might have user + // declared setter or getter in current class extension or one + // of the other class extensions. Mark them as synthesized as + // property will be synthesized when property with same name is + // seen in the @implementation. + for (const ObjCCategoryDecl *ClsExtDecl = + CCPrimary->getFirstClassExtension(); + ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension()) { + if (ObjCMethodDecl *GetterMethod = + ClsExtDecl->getInstanceMethod((*I)->getGetterName())) + GetterMethod->setSynthesized(true); + if (!(*I)->isReadOnly()) + if (ObjCMethodDecl *SetterMethod = + ClsExtDecl->getInstanceMethod((*I)->getSetterName())) + SetterMethod->setSynthesized(true); + } + } + } } if (ObjCContainerDecl *CDecl = dyn_cast(ClassDecl)) { if (CDecl->getIdentifier()) diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp index 9fc6853e46..aa934d8e9c 100644 --- a/lib/Sema/SemaObjCProperty.cpp +++ b/lib/Sema/SemaObjCProperty.cpp @@ -111,6 +111,7 @@ Sema::HandlePropertyInClassExtension(Scope *S, ObjCCategoryDecl *CDecl, // Create a new ObjCPropertyDecl with the DeclContext being // the class extension. + // FIXME. We should really be using CreatePropertyDecl for this. ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, DC, FD.D.getIdentifierLoc(), PropertyId, AtLoc, T); @@ -118,7 +119,9 @@ Sema::HandlePropertyInClassExtension(Scope *S, ObjCCategoryDecl *CDecl, PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly); if (Attributes & ObjCDeclSpec::DQ_PR_readwrite) PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite); - + // Set setter/getter selector name. Needed later. + PDecl->setGetterName(GetterSel); + PDecl->setSetterName(SetterSel); DC->addDecl(PDecl); // We need to look in the @interface to see if the @property was diff --git a/test/SemaObjC/property-in-class-extension.m b/test/SemaObjC/property-in-class-extension.m index af68a43f02..0f0c884015 100644 --- a/test/SemaObjC/property-in-class-extension.m +++ b/test/SemaObjC/property-in-class-extension.m @@ -12,4 +12,28 @@ void FUNC () { foo.bar = 0; // expected-error {{assigning to property with 'readonly' attribute not allowed}} } +// rdar://8747333 +@class NSObject; + +@interface rdar8747333 { +@private + NSObject *_bar; + NSObject *_baz; +} +- (NSObject *)baz; +@end + +@interface rdar8747333 () +- (NSObject *)bar; +@end + +@interface rdar8747333 () +@property (readwrite, assign) NSObject *bar; +@property (readwrite, assign) NSObject *baz; +@end + +@implementation rdar8747333 +@synthesize bar = _bar; +@synthesize baz = _baz; +@end