1// TEST_CONFIG CC=clang
2
3#include "test.h"
4#include <objc/runtime.h>
5#include <objc/objc-internal.h>
6#import <Foundation/NSObject.h>
7
8class SerialNumber {
9    size_t _number;
10public:
11    SerialNumber() : _number(42) {}
12    SerialNumber(const SerialNumber &number) : _number(number._number + 1) {}
13    SerialNumber &operator=(const SerialNumber &number) { _number = number._number + 1; return *this; }
14
15    int operator==(const SerialNumber &number) { return _number == number._number; }
16    int operator!=(const SerialNumber &number) { return _number != number._number; }
17};
18
19@interface TestAtomicProperty : NSObject {
20    SerialNumber number;
21}
22@property(atomic) SerialNumber number;
23@end
24
25@implementation TestAtomicProperty
26
27#if 1 // with new enough compiler, this will be synthesized automatically.
28
29extern void objc_copyCppObjectAtomic(void *dest, const void *src, void (*copyHelper) (void *dest, const void *source));
30
31static void copySerialNumber(void *d, const void *s) {
32    SerialNumber *dest = (SerialNumber *)d;
33    const SerialNumber *src = (const SerialNumber *)s;
34    dest->operator=(*src);
35}
36
37- (SerialNumber)number {
38    SerialNumber result;
39    objc_copyCppObjectAtomic(&result, &number, copySerialNumber);
40    return result;
41}
42
43- (void)setNumber:(SerialNumber)aNumber {
44    objc_copyCppObjectAtomic(&number, &aNumber, copySerialNumber);
45}
46
47+(void)initialize {
48    testwarn("rdar://6137845 compiler should synthesize calls to objc_copyCppObjectAtomic");
49}
50
51#else
52@synthesize number;
53#endif    
54
55@end
56
57int main()
58{
59    PUSH_POOL {
60        SerialNumber number;
61        TestAtomicProperty *test = [TestAtomicProperty new];
62        test.number = number;
63        testassert(test.number != number);
64    } POP_POOL;
65
66    succeed(__FILE__);
67}
68