diff options
-rw-r--r-- | lib/Sema/SemaDeclObjC.cpp | 25 | ||||
-rw-r--r-- | lib/Sema/SemaObjCProperty.cpp | 5 | ||||
-rw-r--r-- | test/SemaObjC/property-in-class-extension.m | 24 |
3 files changed, 51 insertions, 3 deletions
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<ObjCContainerDecl>(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 |