Stop back-patching 'readonly' Objective-C properties with 'readwrite' ones.
A 'readonly' Objective-C property declared in the primary class can
effectively be shadowed by a 'readwrite' property declared within an
extension of that class, so long as the types and attributes of the
two property declarations are compatible.
Previously, this functionality was implemented by back-patching the
original 'readonly' property to make it 'readwrite', destroying source
information and causing some hideously redundant, incorrect
code. Simplify the implementation to express how this should actually
be modeled: as a separate property declaration in the extension that
shadows (via the name lookup rules) the declaration in the primary
class. While here, correct some broken Fix-Its, eliminate a pile of
redundant code, clean up the ARC migrator's handling of properties
declared in extensions, and fix debug info's naming of methods that
come from categories.
A wonderous side effect of doing this write is that it eliminates the
"AddedObjCPropertyInClassExtension" method from the AST mutation
listener, which in turn eliminates the last place where we rewrite
entire declarations in a chained PCH file or a module file. This
change (which fixes rdar://problem/18475765) will allow us to
eliminate the rewritten-decls logic from the serialization library,
and fixes a crash (rdar://problem/23247794) illustrated by the
test/PCH/chain-categories.m example.
llvm-svn: 251874
diff --git a/clang/test/FixIt/atomic-property.m b/clang/test/FixIt/atomic-property.m
index 9ede7f1..84dd820 100644
--- a/clang/test/FixIt/atomic-property.m
+++ b/clang/test/FixIt/atomic-property.m
@@ -23,7 +23,7 @@
- (id) atomic_prop1 { return 0; }
@end
-// CHECK: {4:1-4:10}:"@property (nonatomic) "
-// CHECK: {9:1-9:12}:"@property (nonatomic"
-// CHECK: {13:1-13:12}:"@property (nonatomic, "
+// CHECK-DAG: {4:11-4:11}:"(nonatomic) "
+// CHECK-DAG: {9:12-9:12}:"nonatomic"
+// CHECK-DAG: {13:12-13:12}:"nonatomic, "
diff --git a/clang/test/Index/complete-kvc.m b/clang/test/Index/complete-kvc.m
index 62d98a9..336d41d 100644
--- a/clang/test/Index/complete-kvc.m
+++ b/clang/test/Index/complete-kvc.m
@@ -101,5 +101,5 @@
// RUN: c-index-test -code-completion-at=%s:52:8 %s | FileCheck -check-prefix=CHECK-CC3 %s
// CHECK-CC3: ObjCInstanceMethodDecl:{TypedText countOfIntProperty} (55)
-// CHECK-CC3-NEXT: ObjCInstanceMethodDecl:{TypedText intProperty} (40)
+// CHECK-CC3-NEXT: ObjCInstanceMethodDecl:{TypedText intProperty} (42)
// CHECK-CC3-NEXT: ObjCInstanceMethodDecl:{TypedText isIntProperty} (40)
diff --git a/clang/test/Modules/ModuleDebugInfo.m b/clang/test/Modules/ModuleDebugInfo.m
index b7dfb22..0974f38 100644
--- a/clang/test/Modules/ModuleDebugInfo.m
+++ b/clang/test/Modules/ModuleDebugInfo.m
@@ -33,7 +33,7 @@
// CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "InnerEnum"
// CHECK: !DISubprogram(name: "+[ObjCClass classMethod]"
// CHECK: !DISubprogram(name: "-[ObjCClass instanceMethodWithInt:]"
-// CHECK: !DISubprogram(name: "-[ categoryMethod]"
+// CHECK: !DISubprogram(name: "-[Category(Category) categoryMethod]"
// MODULE-CHECK: !DICompositeType(tag: DW_TAG_enumeration_type,
// MODULE-CHECK-SAME: scope: ![[MODULE:[0-9]+]],
diff --git a/clang/test/PCH/chain-categories.m b/clang/test/PCH/chain-categories.m
index 7836e09..dc57387 100644
--- a/clang/test/PCH/chain-categories.m
+++ b/clang/test/PCH/chain-categories.m
@@ -16,6 +16,10 @@
- (void)finalize;
@end
+@interface NSObject (Properties)
+@property (readonly,nonatomic) int intProp;
+@end
+
//===----------------------------------------------------------------------===//
#elif !defined(HEADER2)
#define HEADER2
@@ -34,6 +38,12 @@
-(void)extMeth;
@end
+@interface NSObject ()
+@property (readwrite,nonatomic) int intProp;
+@end
+
+@class NSObject;
+
//===----------------------------------------------------------------------===//
#else
//===----------------------------------------------------------------------===//
@@ -47,6 +57,9 @@
void test(NSObject *o) {
[o extMeth];
+
+ // Make sure the property is treated as read-write.
+ o.intProp = 17;
}
//===----------------------------------------------------------------------===//
diff --git a/clang/test/SemaObjC/atomoic-property-synnthesis-rules.m b/clang/test/SemaObjC/atomoic-property-synnthesis-rules.m
index b681558..c7fac7b 100644
--- a/clang/test/SemaObjC/atomoic-property-synnthesis-rules.m
+++ b/clang/test/SemaObjC/atomoic-property-synnthesis-rules.m
@@ -129,10 +129,8 @@
// read-only in class, read-write in class extension - might warn
@property(readonly) int GetSet_ReadWriteInExt;
-@property(readonly) int Get_ReadWriteInExt; // expected-note {{property declared here}} \
- // expected-note {{setter and getter must both be synthesized}}
-@property(readonly) int Set_ReadWriteInExt; // expected-note {{property declared here}} \
- // expected-note {{setter and getter must both be synthesized}}
+@property(readonly) int Get_ReadWriteInExt;
+@property(readonly) int Set_ReadWriteInExt;
@property(readonly) int None_ReadWriteInExt;
@property(nonatomic,readonly) int GetSet_Nonatomic_ReadWriteInExt;
@property(nonatomic,readonly) int Get_Nonatomic_ReadWriteInExt;
@@ -162,10 +160,8 @@
@property(nonatomic,readonly) int None_Nonatomic_ReadOnly_LateSynthesize;
@property(readonly) int GetSet_ReadWriteInExt_LateSynthesize;
-@property(readonly) int Get_ReadWriteInExt_LateSynthesize; // expected-note {{property declared here}} \
- // expected-note {{setter and getter must both be synthesized}}
-@property(readonly) int Set_ReadWriteInExt_LateSynthesize; // expected-note {{property declared here}} \
- // expected-note {{setter and getter must both be synthesized}}
+@property(readonly) int Get_ReadWriteInExt_LateSynthesize;
+@property(readonly) int Set_ReadWriteInExt_LateSynthesize;
@property(readonly) int None_ReadWriteInExt_LateSynthesize;
@property(nonatomic,readonly) int GetSet_Nonatomic_ReadWriteInExt_LateSynthesize;
@property(nonatomic,readonly) int Get_Nonatomic_ReadWriteInExt_LateSynthesize;
@@ -207,8 +203,10 @@
@interface Foo ()
@property(readwrite) int GetSet_ReadWriteInExt;
-@property(readwrite) int Get_ReadWriteInExt;
-@property(readwrite) int Set_ReadWriteInExt;
+@property(readwrite) int Get_ReadWriteInExt; // expected-note {{property declared here}} \
+ // expected-note {{setter and getter must both be synthesized}}
+@property(readwrite) int Set_ReadWriteInExt; // expected-note {{property declared here}} \
+ // expected-note {{setter and getter must both be synthesized}}
@property(readwrite) int None_ReadWriteInExt;
@property(nonatomic,readwrite) int GetSet_Nonatomic_ReadWriteInExt;
@property(nonatomic,readwrite) int Get_Nonatomic_ReadWriteInExt;
@@ -216,8 +214,10 @@
@property(nonatomic,readwrite) int None_Nonatomic_ReadWriteInExt;
@property(readwrite) int GetSet_ReadWriteInExt_LateSynthesize;
-@property(readwrite) int Get_ReadWriteInExt_LateSynthesize;
-@property(readwrite) int Set_ReadWriteInExt_LateSynthesize;
+@property(readwrite) int Get_ReadWriteInExt_LateSynthesize; // expected-note {{property declared here}} \
+ // expected-note {{setter and getter must both be synthesized}}
+@property(readwrite) int Set_ReadWriteInExt_LateSynthesize; // expected-note {{property declared here}} \
+ // expected-note {{setter and getter must both be synthesized}}
@property(readwrite) int None_ReadWriteInExt_LateSynthesize;
@property(nonatomic,readwrite) int GetSet_Nonatomic_ReadWriteInExt_LateSynthesize;
@property(nonatomic,readwrite) int Get_Nonatomic_ReadWriteInExt_LateSynthesize;
diff --git a/clang/test/SemaObjC/property-3.m b/clang/test/SemaObjC/property-3.m
index 3f82bcc..7c0ba57 100644
--- a/clang/test/SemaObjC/property-3.m
+++ b/clang/test/SemaObjC/property-3.m
@@ -29,5 +29,5 @@
@interface EKCalendar () <EKProtocolMutableCalendar>
@property (nonatomic, assign) BOOL allowReminders;
-@property (nonatomic, assign) BOOL allowNonatomicProperty; // expected-warning {{'atomic' attribute on property 'allowNonatomicProperty' does not match the property inherited from 'EKProtocolCalendar'}}
+@property (nonatomic, assign) BOOL allowNonatomicProperty; // expected-warning {{'atomic' attribute on property 'allowNonatomicProperty' does not match the property inherited from EKProtocolCalendar}}
@end
diff --git a/clang/test/SemaObjC/property-in-class-extension-1.m b/clang/test/SemaObjC/property-in-class-extension-1.m
index 6e9d476..8f5907b 100644
--- a/clang/test/SemaObjC/property-in-class-extension-1.m
+++ b/clang/test/SemaObjC/property-in-class-extension-1.m
@@ -10,7 +10,7 @@
@property (nonatomic, copy, readonly) NSString* matchingMemoryModel;
-@property (nonatomic, retain, readonly) NSString* addingNoNewMemoryModel;
+@property (atomic, retain, readonly) NSString* addingNoNewMemoryModel;
@property (readonly) NSString* none;
@property (readonly) NSString* none1;
@@ -50,10 +50,14 @@
// rdar://12214070
@interface radar12214070
@property (nonatomic, atomic, readonly) float propertyName; // expected-error {{property attributes 'atomic' and 'nonatomic' are mutually exclusive}}
+
+@property (nonatomic, readonly) float propertyName2; // expected-note {{property declared here}}
@end
@interface radar12214070 ()
@property (atomic, nonatomic, readonly, readwrite) float propertyName; // expected-error {{property attributes 'readonly' and 'readwrite' are mutually exclusive}} \
// expected-error {{property attributes 'atomic' and 'nonatomic' are mutually exclusive}}
+
+@property (atomic, readwrite) float propertyName2; // expected-warning {{'atomic' attribute on property 'propertyName2' does not match the property inherited from radar12214070}}
@end
diff --git a/clang/test/SemaObjCXX/property-invalid-type.mm b/clang/test/SemaObjCXX/property-invalid-type.mm
index 5b8a848..6482358 100644
--- a/clang/test/SemaObjCXX/property-invalid-type.mm
+++ b/clang/test/SemaObjCXX/property-invalid-type.mm
@@ -13,11 +13,11 @@
@synthesize response;
- (void) foo :(A*) a // expected-error {{expected a type}}
{
- self.response = a;
+ self.response = a; // expected-error{{assigning to 'int *' from incompatible type 'id'}}
}
@end
void foo(I *i)
{
- i.helper;
+ i.helper; // expected-warning{{property access result unused - getters should not be used for side effects}}
}