aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Sema/SemaDeclObjC.cpp25
-rw-r--r--lib/Sema/SemaObjCProperty.cpp5
-rw-r--r--test/SemaObjC/property-in-class-extension.m24
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