summaryrefslogtreecommitdiffstats
path: root/test/CodeGenObjC
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2012-03-06 20:05:56 +0000
committerTed Kremenek <kremenek@apple.com>2012-03-06 20:05:56 +0000
commitebcb57a8d298862c65043e88b2429591ab3c58d3 (patch)
treeadbe4e0a60340ec2858e4b8d74d7bb0f23887d67 /test/CodeGenObjC
parent9f86af897458b3b44e26b9e06a857f626f71a692 (diff)
Add clang support for new Objective-C literal syntax for NSDictionary, NSArray,
NSNumber, and boolean literals. This includes both Sema and Codegen support. Included is also support for new Objective-C container subscripting. My apologies for the large patch. It was very difficult to break apart. The patch introduces changes to the driver as well to cause clang to link in additional runtime support when needed to support the new language features. Docs are forthcoming to document the implementation and behavior of these features. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152137 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/CodeGenObjC')
-rw-r--r--test/CodeGenObjC/Inputs/literal-support.h35
-rw-r--r--test/CodeGenObjC/arc-literals.m121
-rw-r--r--test/CodeGenObjC/objc-arc-container-subscripting.m21
-rw-r--r--test/CodeGenObjC/objc-container-subscripting-1.m56
-rw-r--r--test/CodeGenObjC/objc-container-subscripting.m45
-rw-r--r--test/CodeGenObjC/objc-dictionary-literal.m25
-rw-r--r--test/CodeGenObjC/objc-literal-debugger-test.m16
-rw-r--r--test/CodeGenObjC/objc-literal-tests.m95
-rw-r--r--test/CodeGenObjC/optimized-setter.m33
9 files changed, 447 insertions, 0 deletions
diff --git a/test/CodeGenObjC/Inputs/literal-support.h b/test/CodeGenObjC/Inputs/literal-support.h
new file mode 100644
index 0000000000..5680a20c9f
--- /dev/null
+++ b/test/CodeGenObjC/Inputs/literal-support.h
@@ -0,0 +1,35 @@
+#ifndef OBJC_LITERAL_SUPPORT_H
+#define OBJC_LITERAL_SUPPORT_H
+
+typedef unsigned char BOOL;
+
+@interface NSNumber @end
+
+@interface NSNumber (NSNumberCreation)
++ (NSNumber *)numberWithChar:(char)value;
++ (NSNumber *)numberWithUnsignedChar:(unsigned char)value;
++ (NSNumber *)numberWithShort:(short)value;
++ (NSNumber *)numberWithUnsignedShort:(unsigned short)value;
++ (NSNumber *)numberWithInt:(int)value;
++ (NSNumber *)numberWithUnsignedInt:(unsigned int)value;
++ (NSNumber *)numberWithLong:(long)value;
++ (NSNumber *)numberWithUnsignedLong:(unsigned long)value;
++ (NSNumber *)numberWithLongLong:(long long)value;
++ (NSNumber *)numberWithUnsignedLongLong:(unsigned long long)value;
++ (NSNumber *)numberWithFloat:(float)value;
++ (NSNumber *)numberWithDouble:(double)value;
++ (NSNumber *)numberWithBool:(BOOL)value;
+@end
+
+@interface NSArray
+@end
+
+@interface NSArray (NSArrayCreation)
++ (id)arrayWithObjects:(const id [])objects count:(unsigned long)cnt;
+@end
+
+@interface NSDictionary
++ (id)dictionaryWithObjects:(const id [])objects forKeys:(const id [])keys count:(unsigned long)cnt;
+@end
+
+#endif // OBJC_LITERAL_SUPPORT_H
diff --git a/test/CodeGenObjC/arc-literals.m b/test/CodeGenObjC/arc-literals.m
new file mode 100644
index 0000000000..203c2ad1ee
--- /dev/null
+++ b/test/CodeGenObjC/arc-literals.m
@@ -0,0 +1,121 @@
+// RUN: %clang_cc1 -I %S/Inputs -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-optzns -o - %s | FileCheck %s
+
+#include "literal-support.h"
+
+// Check the various selector names we'll be using, in order.
+
+// CHECK: c"numberWithInt:\00"
+// CHECK: c"numberWithUnsignedInt:\00"
+// CHECK: c"numberWithUnsignedLongLong:\00"
+// CHECK: c"numberWithChar:\00"
+// CHECK: c"arrayWithObjects:count:\00"
+// CHECK: c"dictionaryWithObjects:forKeys:count:\00"
+// CHECK: c"prop\00"
+
+// CHECK: define void @test_numeric()
+void test_numeric() {
+ // CHECK: {{call.*objc_msgSend.*i32 17}}
+ // CHECK: call i8* @objc_retainAutoreleasedReturnValue
+ id ilit = @17;
+ // CHECK: {{call.*objc_msgSend.*i32 25}}
+ // CHECK: call i8* @objc_retainAutoreleasedReturnValue
+ id ulit = @25u;
+ // CHECK: {{call.*objc_msgSend.*i64 42}}
+ // CHECK: call i8* @objc_retainAutoreleasedReturnValue
+ id ulllit = @42ull;
+ // CHECK: {{call.*objc_msgSend.*i8 signext 97}}
+ // CHECK: call i8* @objc_retainAutoreleasedReturnValue
+ id charlit = @'a';
+ // CHECK: call void @objc_release
+ // CHECK: call void @objc_release
+ // CHECK: call void @objc_release
+ // CHECK: call void @objc_release
+ // CHECK-NEXT: ret void
+}
+
+// CHECK: define void @test_array
+void test_array(id a, id b) {
+ // Retaining parameters
+ // CHECK: call i8* @objc_retain(i8*
+ // CHECK: call i8* @objc_retain(i8*
+
+ // Constructing the array
+ // CHECK: getelementptr inbounds [2 x i8*]* [[OBJECTS:%[A-Za-z0-9]+]], i32 0, i32 0
+ // CHECK: store i8*
+ // CHECK: getelementptr inbounds [2 x i8*]* [[OBJECTS]], i32 0, i32 1
+ // CHECK: store i8*
+
+ // CHECK: {{call i8*.*objc_msgSend.*i64 2}}
+ // CHECK: call i8* @objc_retainAutoreleasedReturnValue
+ id arr = @[a, b];
+
+ // CHECK: call void @objc_release
+ // CHECK: call void @objc_release
+ // CHECK: call void @objc_release
+ // CHECK-NEXT: ret void
+}
+
+// CHECK: define void @test_dictionary
+void test_dictionary(id k1, id o1, id k2, id o2) {
+ // Retaining parameters
+ // CHECK: call i8* @objc_retain(i8*
+ // CHECK: call i8* @objc_retain(i8*
+ // CHECK: call i8* @objc_retain(i8*
+ // CHECK: call i8* @objc_retain(i8*
+
+ // Constructing the arrays
+ // CHECK: getelementptr inbounds [2 x i8*]* [[KEYS:%[A-Za-z0-9]+]], i32 0, i32 0
+ // CHECK: store i8*
+ // CHECK: getelementptr inbounds [2 x i8*]* [[OBJECTS:%[A-Za-z0-9]+]], i32 0, i32 0
+ // CHECK: store i8*
+ // CHECK: getelementptr inbounds [2 x i8*]* [[KEYS]], i32 0, i32 1
+ // CHECK: store i8*
+ // CHECK: getelementptr inbounds [2 x i8*]* [[OBJECTS]], i32 0, i32 1
+ // CHECK: store i8*
+
+ // Constructing the dictionary
+ // CHECK: {{call i8.*@objc_msgSend}}
+ // CHECK: call i8* @objc_retainAutoreleasedReturnValue
+ id dict = @{ k1 : o1, k2 : o2 };
+
+ // CHECK: call void @objc_release
+ // CHECK: call void @objc_release
+ // CHECK: call void @objc_release
+ // CHECK: call void @objc_release
+ // CHECK: call void @objc_release
+ // CHECK-NEXT: ret void
+}
+
+@interface A
+@end
+
+@interface B
+@property (retain) A* prop;
+@end
+
+// CHECK: define void @test_property
+void test_property(B *b) {
+ // Retain parameter
+ // CHECK: call i8* @objc_retain
+
+ // Invoke 'prop'
+ // CHECK: load i8** @"\01L_OBJC_SELECTOR_REFERENCES
+ // CHECK: {{call.*@objc_msgSend}}
+ // CHECK: call i8* @objc_retainAutoreleasedReturnValue
+
+ // Invoke arrayWithObjects:count:
+ // CHECK: load i8** @"\01L_OBJC_SELECTOR_REFERENCES
+ // CHECK: {{call.*objc_msgSend}}
+ // CHECK: call i8* @objc_retainAutoreleasedReturnValue
+ id arr = @[ b.prop ];
+
+ // Release b.prop
+ // CHECK: call void @objc_release
+
+ // Destroy arr
+ // CHECK: call void @objc_release
+
+ // Destroy b
+ // CHECK: call void @objc_release
+ // CHECK-NEXT: ret void
+}
diff --git a/test/CodeGenObjC/objc-arc-container-subscripting.m b/test/CodeGenObjC/objc-arc-container-subscripting.m
new file mode 100644
index 0000000000..892491630e
--- /dev/null
+++ b/test/CodeGenObjC/objc-arc-container-subscripting.m
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -fobjc-arc -emit-llvm -triple x86_64-apple-darwin -o - %s | FileCheck %s
+
+@interface NSMutableArray
+- (id)objectAtIndexedSubscript:(int)index;
+- (void)setObject:(id)object atIndexedSubscript:(int)index;
+@end
+
+id func() {
+ NSMutableArray *array;
+ array[3] = 0;
+ return array[3];
+}
+
+// CHECK: [[call:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend
+// CHECK: [[SIX:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[call]]) nounwind
+// CHECK: [[ARRAY:%.*]] = load %0**
+// CHECK: [[ARRAY_CASTED:%.*]] = bitcast{{.*}}[[ARRAY]] to i8*
+// CHECK: call void @objc_release(i8* [[ARRAY_CASTED]])
+// CHECK: [[EIGHT:%.*]] = call i8* @objc_autoreleaseReturnValue(i8* [[SIX]]) nounwind
+// CHECK: ret i8* [[EIGHT]]
+
diff --git a/test/CodeGenObjC/objc-container-subscripting-1.m b/test/CodeGenObjC/objc-container-subscripting-1.m
new file mode 100644
index 0000000000..91b7f468ea
--- /dev/null
+++ b/test/CodeGenObjC/objc-container-subscripting-1.m
@@ -0,0 +1,56 @@
+// RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin -o - %s | FileCheck %s
+
+typedef unsigned int size_t;
+@protocol P @end
+
+@interface NSMutableArray
+- (id)objectAtIndexedSubscript:(size_t)index;
+- (void)setObject:(id)object atIndexedSubscript:(size_t)index;
+@end
+
+@interface NSMutableDictionary
+- (id)objectForKeyedSubscript:(id)key;
+- (void)setObject:(id)object forKeyedSubscript:(id)key;
+@end
+
+int main() {
+ NSMutableArray *array;
+ id val;
+
+ id oldObject = array[10];
+// CHECK: [[ARR:%.*]] = load {{%.*}} [[array:%.*]], align 8
+// CHECK-NEXT: [[SEL:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_"
+// CHECK-NEXT: [[ARRC:%.*]] = bitcast {{%.*}} [[ARR]] to i8*
+// CHECK-NEXT: [[CALL:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*, i32)*)(i8* [[ARRC]], i8* [[SEL]], i32 10)
+// CHECK-NEXT: store i8* [[CALL]], i8** [[OLDOBJ:%.*]], align 8
+
+ val = (array[10] = oldObject);
+// CHECK: [[THREE:%.*]] = load {{%.*}} [[array:%.*]], align 8
+// CHECK-NEXT: [[FOUR:%.*]] = load i8** [[oldObject:%.*]], align 8
+// CHECK-NEXT: [[FIVE:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_2"
+// CHECK-NEXT: [[SIX:%.*]] = bitcast {{%.*}} [[THREE]] to i8*
+// CHECK-NEXT: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i8*, i32)*)(i8* [[SIX]], i8* [[FIVE]], i8* [[FOUR]], i32 10)
+// CHECK-NEXT: store i8* [[FOUR]], i8** [[val:%.*]]
+
+ NSMutableDictionary *dictionary;
+ id key;
+ id newObject;
+ oldObject = dictionary[key];
+// CHECK: [[SEVEN:%.*]] = load {{%.*}} [[DICTIONARY:%.*]], align 8
+// CHECK-NEXT: [[EIGHT:%.*]] = load i8** [[KEY:%.*]], align 8
+// CHECK-NEXT: [[TEN:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_4"
+// CHECK-NEXT: [[ELEVEN:%.*]] = bitcast {{%.*}} [[SEVEN]] to i8*
+// CHECK-NEXT: [[CALL1:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*, i8*)*)(i8* [[ELEVEN]], i8* [[TEN]], i8* [[EIGHT]])
+// CHECK-NEXT: store i8* [[CALL1]], i8** [[oldObject:%.*]], align 8
+
+
+ val = (dictionary[key] = newObject);
+// CHECK: [[TWELVE:%.*]] = load {{%.*}} [[DICTIONARY]], align 8
+// CHECK-NEXT: [[THIRTEEN:%.*]] = load i8** [[KEY]], align 8
+// CHECK-NEXT: [[FOURTEEN:%.*]] = load i8** [[NEWOBJECT:%.*]], align 8
+// CHECK-NEXT: [[SIXTEEN:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_6"
+// CHECK-NEXT: [[SEVENTEEN:%.*]] = bitcast {{%.*}} [[TWELVE]] to i8*
+// CHECK-NEXT: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i8*, i8*)*)(i8* [[SEVENTEEN]], i8* [[SIXTEEN]], i8* [[FOURTEEN]], i8* [[THIRTEEN]])
+// CHECK-NEXT: store i8* [[FOURTEEN]], i8** [[val:%.*]]
+}
+
diff --git a/test/CodeGenObjC/objc-container-subscripting.m b/test/CodeGenObjC/objc-container-subscripting.m
new file mode 100644
index 0000000000..fd8f8effac
--- /dev/null
+++ b/test/CodeGenObjC/objc-container-subscripting.m
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin %s -o /dev/null
+
+typedef unsigned int size_t;
+@protocol P @end
+
+@interface NSMutableArray
+#if __has_feature(objc_subscripting)
+- (id)objectAtIndexedSubscript:(size_t)index;
+- (void)setObject:(id)object atIndexedSubscript:(size_t)index;
+#endif
+@end
+
+#if __has_feature(objc_subscripting)
+@interface XNSMutableArray
+- (id)objectAtIndexedSubscript:(size_t)index;
+- (void)setObject:(id)object atIndexedSubscript:(size_t)index;
+#endif
+@end
+
+@interface NSMutableDictionary
+- (id)objectForKeyedSubscript:(id)key;
+- (void)setObject:(id)object forKeyedSubscript:(id)key;
+@end
+
+@class NSString;
+
+int main() {
+ NSMutableArray<P> * array;
+ id oldObject = array[10];
+
+ array[10] = oldObject;
+
+ id unknown_array;
+ oldObject = unknown_array[1];
+
+ unknown_array[1] = oldObject;
+
+ NSMutableDictionary *dictionary;
+ NSString *key;
+ id newObject;
+ oldObject = dictionary[key];
+ dictionary[key] = newObject; // replace oldObject with newObject
+
+}
+
diff --git a/test/CodeGenObjC/objc-dictionary-literal.m b/test/CodeGenObjC/objc-dictionary-literal.m
new file mode 100644
index 0000000000..b335582ed2
--- /dev/null
+++ b/test/CodeGenObjC/objc-dictionary-literal.m
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -x objective-c -triple x86_64-apple-darwin10 -fblocks -emit-llvm %s -o /dev/null
+// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -fblocks -emit-llvm %s -o /dev/null
+// rdar://10614657
+
+@interface NSNumber
++ (NSNumber *)numberWithChar:(char)value;
++ (NSNumber *)numberWithInt:(int)value;
+@end
+
+@protocol NSCopying @end
+typedef unsigned long NSUInteger;
+
+@interface NSDictionary
++ (id)dictionaryWithObjects:(const id [])objects forKeys:(const id <NSCopying> [])keys count:(NSUInteger)cnt;
+@end
+
+@interface NSString<NSCopying>
+@end
+
+int main() {
+ NSDictionary *dict = @{ @"name":@666 };
+ NSDictionary *dict1 = @{ @"name":@666 };
+ NSDictionary *dict2 = @{ @"name":@666 };
+ return 0;
+}
diff --git a/test/CodeGenObjC/objc-literal-debugger-test.m b/test/CodeGenObjC/objc-literal-debugger-test.m
new file mode 100644
index 0000000000..389ef2248a
--- /dev/null
+++ b/test/CodeGenObjC/objc-literal-debugger-test.m
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fdebugger-objc-literal -emit-llvm -o - %s | FileCheck %s
+
+int main() {
+ id l = @'a';
+ l = @'a';
+ l = @42;
+ l = @-42;
+ l = @42u;
+ l = @3.141592654f;
+ l = @__objc_yes;
+ l = @__objc_no;
+ l = @{ @"name":@666 };
+ l = @[ @"foo", @"bar" ];
+}
+
+// CHECK: declare i8* @objc_msgSend(i8*, i8*, ...) nonlazybind
diff --git a/test/CodeGenObjC/objc-literal-tests.m b/test/CodeGenObjC/objc-literal-tests.m
new file mode 100644
index 0000000000..c513d49611
--- /dev/null
+++ b/test/CodeGenObjC/objc-literal-tests.m
@@ -0,0 +1,95 @@
+// RUN: %clang_cc1 -x objective-c -triple x86_64-apple-darwin10 -fblocks -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -fblocks -emit-llvm %s -o - | FileCheck %s
+// rdar://10111397
+
+#if __has_feature(objc_bool)
+#define YES __objc_yes
+#define NO __objc_no
+#else
+#define YES ((BOOL)1)
+#define NO ((BOOL)0)
+#endif
+
+#if __LP64__ || (TARGET_OS_EMBEDDED && !TARGET_OS_IPHONE) || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64
+typedef unsigned long NSUInteger;
+typedef long NSInteger;
+#else
+typedef unsigned int NSUInteger;
+typedef int NSInteger;
+#endif
+typedef signed char BOOL;
+
+@interface NSNumber @end
+
+@interface NSNumber (NSNumberCreation)
+#if __has_feature(objc_array_literals)
++ (NSNumber *)numberWithChar:(char)value;
++ (NSNumber *)numberWithUnsignedChar:(unsigned char)value;
++ (NSNumber *)numberWithShort:(short)value;
++ (NSNumber *)numberWithUnsignedShort:(unsigned short)value;
++ (NSNumber *)numberWithInt:(int)value;
++ (NSNumber *)numberWithUnsignedInt:(unsigned int)value;
++ (NSNumber *)numberWithLong:(long)value;
++ (NSNumber *)numberWithUnsignedLong:(unsigned long)value;
++ (NSNumber *)numberWithLongLong:(long long)value;
++ (NSNumber *)numberWithUnsignedLongLong:(unsigned long long)value;
++ (NSNumber *)numberWithFloat:(float)value;
++ (NSNumber *)numberWithDouble:(double)value;
++ (NSNumber *)numberWithBool:(BOOL)value;
++ (NSNumber *)numberWithInteger:(NSInteger)value ;
++ (NSNumber *)numberWithUnsignedInteger:(NSUInteger)value ;
+#endif
+@end
+
+@interface NSDate
++ (NSDate *) date;
+@end
+
+#if __has_feature(objc_dictionary_literals)
+@interface NSDictionary
++ (id)dictionaryWithObjects:(const id [])objects forKeys:(const id [])keys count:(NSUInteger)cnt;
+@end
+#endif
+
+id NSUserName();
+
+// CHECK: define i32 @main() nounwind
+int main() {
+ // CHECK: call{{.*}}@objc_msgSend{{.*}}i8 signext 97
+ NSNumber *aNumber = @'a';
+ // CHECK: call{{.*}}@objc_msgSend{{.*}}i32 42
+ NSNumber *fortyTwo = @42;
+ // CHECK: call{{.*}}@objc_msgSend{{.*}}i32 -42
+ NSNumber *negativeFortyTwo = @-42;
+ // CHECK: call{{.*}}@objc_msgSend{{.*}}i32 42
+ NSNumber *positiveFortyTwo = @+42;
+ // CHECK: call{{.*}}@objc_msgSend{{.*}}i32 42
+ NSNumber *fortyTwoUnsigned = @42u;
+ // CHECK: call{{.*}}@objc_msgSend{{.*}}i64 42
+ NSNumber *fortyTwoLong = @42l;
+ // CHECK: call{{.*}}@objc_msgSend{{.*}}i64 42
+ NSNumber *fortyTwoLongLong = @42ll;
+ // CHECK: call{{.*}}@objc_msgSend{{.*}}float 0x400921FB60000000
+ NSNumber *piFloat = @3.141592654f;
+ // CHECK: call{{.*}}@objc_msgSend{{.*}}double 0x400921FB54411744
+ NSNumber *piDouble = @3.1415926535;
+ // CHECK: call{{.*}}@objc_msgSend{{.*}}i8 signext 1
+ NSNumber *yesNumber = @__objc_yes;
+ // CHECK: call{{.*}}@objc_msgSend{{.*}}i8 signext 0
+ NSNumber *noNumber = @__objc_no;
+ // CHECK: call{{.*}}@objc_msgSend{{.*}}i8 signext 1
+ NSNumber *yesNumber1 = @YES;
+ // CHECK: call{{.*}}@objc_msgSend{{.*}}i8 signext 0
+ NSNumber *noNumber1 = @NO;
+NSDictionary *dictionary = @{@"name" : NSUserName(),
+ @"date" : [NSDate date] };
+ return __objc_yes == __objc_no;
+}
+
+// rdar://10579122
+typedef BOOL (^foo)(void);
+extern void bar(foo a);
+
+void baz(void) {
+ bar(^(void) { return YES; });
+}
diff --git a/test/CodeGenObjC/optimized-setter.m b/test/CodeGenObjC/optimized-setter.m
new file mode 100644
index 0000000000..0e1b388595
--- /dev/null
+++ b/test/CodeGenObjC/optimized-setter.m
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 %s -emit-llvm -triple x86_64-apple-macosx10.8.0 -o - | FileCheck %s
+// rdar://10179974
+
+@interface I
+// void objc_setProperty_nonatomic(id self, SEL _cmd, id newValue, ptrdiff_t offset);
+// objc_setProperty(..., NO, NO)
+@property (nonatomic, retain) id nonatomicProperty;
+
+// void objc_setProperty_nonatomic_copy(id self, SEL _cmd, id newValue, ptrdiff_t offset);
+// objc_setProperty(..., NO, YES)
+@property (nonatomic, copy) id nonatomicPropertyCopy;
+
+// void objc_setProperty_atomic(id self, SEL _cmd, id newValue, ptrdiff_t offset);
+// objc_setProperty(..., YES, NO)
+@property (retain) id atomicProperty;
+
+// void objc_setProperty_atomic_copy(id self, SEL _cmd, id newValue, ptrdiff_t offset);
+// objc_setProperty(..., YES, YES)
+@property (copy) id atomicPropertyCopy;
+@end
+
+@implementation I
+@synthesize nonatomicProperty;
+@synthesize nonatomicPropertyCopy;
+@synthesize atomicProperty;
+@synthesize atomicPropertyCopy;
+@end
+
+// CHECK: call void @objc_setProperty_nonatomic
+// CHECK: call void @objc_setProperty_nonatomic_copy
+// CHECK: call void @objc_setProperty_atomic
+// CHECK: call void @objc_setProperty_atomic_copy
+