xref: /llvm-project/clang/test/SemaObjCXX/properties.mm (revision 84a3aadf0f2483dde0acfc4e79f2a075a5f35bd1)
1// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -Wno-objc-root-class %s
2
3struct X {
4  void f() const;
5  ~X();
6};
7
8@interface A {
9  X x_;
10}
11
12- (const X&)x;
13- (void)setx:(const X&)other;
14@end
15
16@implementation A
17
18- (const X&)x { return x_; }
19- (void)setx:(const X&)other { x_ = other; }
20- (void)method {
21  self.x.f();
22}
23@end
24
25@interface Test2
26- (void) setY: (int) y;
27- (int) z;
28@end
29void test2(Test2 *a) {
30  auto y = a.y; // expected-error {{no getter method for read from property}}
31  auto z = a.z;
32}
33
34@interface Test3
35- (int) length;
36@end
37void test3(Test3 *t) {
38  char vla[t.length] = {}; // expected-error {{variable-sized object may not be initialized}} \
39                              expected-warning {{variable length arrays in C++ are a Clang extension}}
40  char *heaparray = new char[t.length];
41}
42
43namespace std {
44  template<typename T> void count();
45}
46
47@interface Test4
48- (X&) prop;
49@end
50
51void test4(Test4 *t) {
52  (void)const_cast<const X&>(t.prop);
53  (void)dynamic_cast<X&>(t.prop);
54  (void)reinterpret_cast<int&>(t.prop);
55}
56
57@interface Test5 {
58@public
59  int count;
60}
61@property int count;
62@end
63
64void test5(Test5* t5) {
65  if (t5.count < 2) { }
66  if (t5->count < 2) { }
67}
68
69
70@interface Test6
71+ (Class)class;
72- (Class)class;
73@end
74
75void test6(Test6 *t6) {
76  Class x = t6.class;
77  Class x2 = Test6.class;
78}
79
80template<typename T>
81void test6_template(T *t6) {
82  Class x = t6.class;
83}
84
85template void test6_template(Test6*);
86
87struct Test7PointerMaker {
88  operator char *() const;
89};
90@interface Test7
91- (char*) implicit_property;
92- (char) bad_implicit_property;
93- (Test7PointerMaker) implicit_struct_property;
94@property int *explicit_property;
95@property int bad_explicit_property;
96@property Test7PointerMaker explicit_struct_property;
97@end
98void test7(Test7 *ptr) {
99  delete ptr.implicit_property;
100  delete ptr.bad_implicit_property; // expected-error {{cannot delete expression of type 'char'}}
101  delete ptr.explicit_property;
102  delete ptr.bad_explicit_property; // expected-error {{cannot delete expression of type 'int'}}
103  delete ptr.implicit_struct_property;
104  delete ptr.explicit_struct_property;
105}
106
107// Make sure the returned value from property assignment is void,
108// because there isn't any other viable way to handle it for
109// non-trivial classes.
110class NonTrivial1 {
111public:
112	~NonTrivial1();
113};
114class NonTrivial2 {
115public:
116	NonTrivial2();
117	NonTrivial2(const NonTrivial2&);
118};
119@interface TestNonTrivial
120@property(assign, nonatomic) NonTrivial1 p1;
121@property(assign, nonatomic) NonTrivial2 p2;
122@end
123TestNonTrivial *TestNonTrivialObj;
124
125extern void* VoidType;
126extern decltype(TestNonTrivialObj.p1 = NonTrivial1())* VoidType;
127extern decltype(TestNonTrivialObj.p2 = NonTrivial2())* VoidType;
128
129namespace test9 {
130  struct CString {
131    const char *_data;
132    char operator[](int i) const { return _data[i]; }
133  };
134}
135@interface Test9
136@property test9::CString name;
137@end
138namespace test9 {
139  char test(Test9 *t) {
140    return t.name[0];
141  }
142}
143
144namespace test10 {
145  struct A { operator const char*(); };
146  struct B { operator const char*(); };
147}
148@interface Test10
149@property test10::A a;
150@property test10::B b;
151@property int index;
152@end
153namespace test10 {
154  void test(Test10 *t) {
155    (void) t.a[6];
156    (void) 6[t.b];
157    (void) "help"[t.index];
158    (void) t.index["help"];
159    (void) t.a[t.index];
160    (void) t.index[t.b];
161  }
162}
163
164@interface PropertyOfItself
165@property (readonly, nonatomic) PropertyOfItself x; // expected-error {{interface type cannot be statically allocated}}
166@end
167@implementation PropertyOfItself
168@synthesize x;
169@end
170
171struct CGSize {
172  double width;
173  double height;
174};
175typedef struct CGSize CGSize;
176
177struct CGRect {
178  CGSize origin;
179  CGSize size;
180};
181typedef struct CGRect CGRect;
182
183typedef CGRect NSRect;
184void HappySetFrame(NSRect frame) {}
185
186__attribute__((objc_root_class))
187@interface NSObject
188@property CGRect frame;
189@end
190
191@implementation NSObject
192- (void) nothing
193{
194	HappySetFrame({{0,0}, {13,14}});
195	[self setFrame: {{0,0}, {13,14}}];
196        self.frame = {{0,0}, {13,14}};
197        self.frame = (CGRect){{3,5}, {13,14}};
198}
199@end
200