xref: /minix3/external/bsd/llvm/dist/clang/test/SemaObjCXX/arc-templates.mm (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1f4a2713aSLionel Sambuc// RUN: %clang_cc1 -fobjc-runtime-has-weak -fsyntax-only -fobjc-arc -verify -fblocks %s
2f4a2713aSLionel Sambuc
3f4a2713aSLionel Sambuc@interface A
4f4a2713aSLionel Sambuc@end
5f4a2713aSLionel Sambuc
6f4a2713aSLionel Sambuc@class NSString;
7f4a2713aSLionel Sambuc
8f4a2713aSLionel Sambuctemplate<typename T, typename U>
9f4a2713aSLionel Sambucstruct is_same {
10f4a2713aSLionel Sambuc  static const bool value = false;
11f4a2713aSLionel Sambuc};
12f4a2713aSLionel Sambuc
13f4a2713aSLionel Sambuctemplate<typename T>
14f4a2713aSLionel Sambucstruct is_same<T, T> {
15f4a2713aSLionel Sambuc  static const bool value = true;
16f4a2713aSLionel Sambuc};
17f4a2713aSLionel Sambuc
18f4a2713aSLionel Sambuc// Instantiation for reference/pointer types that will get lifetime
19f4a2713aSLionel Sambuc// adjustments.
20f4a2713aSLionel Sambuctemplate<typename T>
21f4a2713aSLionel Sambucstruct X0 {
22f4a2713aSLionel Sambuc  typedef T* pointer; // okay: ends up being strong.
23f4a2713aSLionel Sambuc  typedef T& reference; // okay: ends up being strong
24f4a2713aSLionel Sambuc};
25f4a2713aSLionel Sambuc
26f4a2713aSLionel Sambucvoid test_X0() {
27f4a2713aSLionel Sambuc  X0<id> x0id;
28f4a2713aSLionel Sambuc  X0<A*> x0a;
29f4a2713aSLionel Sambuc  X0<__strong A*> x0sa;
30f4a2713aSLionel Sambuc
31f4a2713aSLionel Sambuc  id __strong *ptr;
32f4a2713aSLionel Sambuc  id __strong val;
33f4a2713aSLionel Sambuc  X0<__strong id>::pointer &ptr_ref = ptr;
34f4a2713aSLionel Sambuc  X0<__strong id>::reference ref = val;
35f4a2713aSLionel Sambuc}
36f4a2713aSLionel Sambuc
37f4a2713aSLionel Sambucint check_infer_strong[is_same<id, __strong id>::value? 1 : -1];
38f4a2713aSLionel Sambuc
39f4a2713aSLionel Sambuc// Check template argument deduction (e.g., for specialization) using
40f4a2713aSLionel Sambuc// lifetime qualifiers.
41f4a2713aSLionel Sambuctemplate<typename T>
42f4a2713aSLionel Sambucstruct is_pointer_strong {
43f4a2713aSLionel Sambuc  static const bool value = false;
44f4a2713aSLionel Sambuc};
45f4a2713aSLionel Sambuc
46f4a2713aSLionel Sambuctemplate<typename T>
47f4a2713aSLionel Sambucstruct is_pointer_strong<__strong T*> {
48f4a2713aSLionel Sambuc  static const bool value = true;
49f4a2713aSLionel Sambuc};
50f4a2713aSLionel Sambuc
51f4a2713aSLionel Sambucint check_ptr_strong1[is_pointer_strong<__strong id*>::value? 1 : -1];
52f4a2713aSLionel Sambucint check_ptr_strong2[is_pointer_strong<__weak id*>::value? -1 : 1];
53f4a2713aSLionel Sambucint check_ptr_strong3[is_pointer_strong<__autoreleasing id*>::value? -1 : 1];
54f4a2713aSLionel Sambucint check_ptr_strong4[is_pointer_strong<__unsafe_unretained id*>::value? -1 : 1];
55f4a2713aSLionel Sambucint check_ptr_strong5[is_pointer_strong<id>::value? -1 : 1];
56f4a2713aSLionel Sambuc
57f4a2713aSLionel Sambuc// Check substitution into lifetime-qualified dependent types.
58f4a2713aSLionel Sambuctemplate<typename T>
59f4a2713aSLionel Sambucstruct make_strong_pointer {
60f4a2713aSLionel Sambuc  typedef __strong T *type;
61f4a2713aSLionel Sambuc};
62f4a2713aSLionel Sambuc
63f4a2713aSLionel Sambuctemplate<typename T>
64f4a2713aSLionel Sambucstruct make_strong_pointer<__weak T> {
65f4a2713aSLionel Sambuc  typedef __strong T *type;
66f4a2713aSLionel Sambuc};
67f4a2713aSLionel Sambuc
68f4a2713aSLionel Sambuctemplate<typename T>
69f4a2713aSLionel Sambucstruct make_strong_pointer<__autoreleasing T> {
70f4a2713aSLionel Sambuc  typedef __strong T *type;
71f4a2713aSLionel Sambuc};
72f4a2713aSLionel Sambuc
73f4a2713aSLionel Sambuctemplate<typename T>
74f4a2713aSLionel Sambucstruct make_strong_pointer<__unsafe_unretained T> {
75f4a2713aSLionel Sambuc  typedef __strong T *type;
76f4a2713aSLionel Sambuc};
77f4a2713aSLionel Sambuc
78f4a2713aSLionel Sambuc// Adding qualifiers
79f4a2713aSLionel Sambucint check_make_strong1[is_same<make_strong_pointer<id>::type, __strong id *>::value ? 1 : -1];
80f4a2713aSLionel Sambucint check_make_strong2[is_same<make_strong_pointer<A*>::type, A* __strong *>::value ? 1 : -1];
81f4a2713aSLionel Sambuc
82f4a2713aSLionel Sambuc// Adding redundant qualifiers
83f4a2713aSLionel Sambucint check_make_strong3[is_same<make_strong_pointer<__strong id>::type, __strong id *>::value ? 1 : -1];
84f4a2713aSLionel Sambucint check_make_strong4[is_same<make_strong_pointer<__strong A*>::type, A* __strong *>::value ? 1 : -1];
85f4a2713aSLionel Sambuc
86f4a2713aSLionel Sambuc// Adding nonsensical qualifiers.
87f4a2713aSLionel Sambucint check_make_strong5[is_same<make_strong_pointer<int>::type, int *>::value ? 1 : -1];
88f4a2713aSLionel Sambucint check_make_strong6[is_same<make_strong_pointer<__weak id>::type, __strong id *>::value ? 1 : -1];
89f4a2713aSLionel Sambuc
90f4a2713aSLionel Sambuctemplate<typename T>
91f4a2713aSLionel Sambucstruct make_weak {
92f4a2713aSLionel Sambuc  typedef __weak T type;
93f4a2713aSLionel Sambuc};
94f4a2713aSLionel Sambuc
95f4a2713aSLionel Sambucint check_make_weak0[is_same<make_weak<id>::type, __weak id>::value? 1 : -1];
96f4a2713aSLionel Sambucint check_make_weak1[is_same<make_weak<__strong id>::type, __weak id>::value? 1 : -1];
97f4a2713aSLionel Sambucint check_make_weak2[is_same<make_weak<__autoreleasing id>::type, __weak id>::value? 1 : -1];
98f4a2713aSLionel Sambuc
99f4a2713aSLionel Sambuctemplate<typename T>
100f4a2713aSLionel Sambucstruct make_weak_fail {
101f4a2713aSLionel Sambuc  typedef T T_type;
102f4a2713aSLionel Sambuc  typedef __weak T_type type; // expected-error{{the type 'T_type' (aka '__weak id') is already explicitly ownership-qualified}} \
103f4a2713aSLionel Sambuc  // expected-error{{the type 'T_type' (aka '__strong id') is already explicitly ownership-qualified}}
104f4a2713aSLionel Sambuc};
105f4a2713aSLionel Sambuc
106f4a2713aSLionel Sambucint check_make_weak_fail0[is_same<make_weak_fail<__weak id>::type, __weak id>::value? 1 : -1]; // expected-note{{in instantiation of template class 'make_weak_fail<__weak id>' requested here}}
107f4a2713aSLionel Sambuc
108f4a2713aSLionel Sambucint check_make_weak_fail1[is_same<make_weak_fail<id>::type, __weak id>::value? -1 : 1]; // expected-note{{in instantiation of template class 'make_weak_fail<id>' requested here}}
109f4a2713aSLionel Sambuc
110f4a2713aSLionel Sambuc// Check template argument deduction from function templates.
111f4a2713aSLionel Sambuctemplate<typename T> struct identity { };
112f4a2713aSLionel Sambuc
113f4a2713aSLionel Sambuctemplate<typename T> identity<T> accept_strong_ptr(__strong T*);
114f4a2713aSLionel Sambuctemplate<typename T> identity<T> accept_strong_ref(__strong T&);
115f4a2713aSLionel Sambuc
116f4a2713aSLionel Sambuctemplate<typename T> identity<T> accept_any_ptr(T*);
117f4a2713aSLionel Sambuctemplate<typename T> identity<T> accept_any_ref(T&);
118f4a2713aSLionel Sambuc
119f4a2713aSLionel Sambucvoid test_func_deduction_id() {
120f4a2713aSLionel Sambuc  __strong id *sip;
121f4a2713aSLionel Sambuc  __weak id *wip;
122f4a2713aSLionel Sambuc  __autoreleasing id *aip;
123f4a2713aSLionel Sambuc  __unsafe_unretained id *uip;
124f4a2713aSLionel Sambuc
125f4a2713aSLionel Sambuc  identity<id> res1 = accept_strong_ptr(sip);
126f4a2713aSLionel Sambuc  identity<__strong id> res2 = accept_any_ptr(sip);
127f4a2713aSLionel Sambuc
128f4a2713aSLionel Sambuc  __strong id si;
129f4a2713aSLionel Sambuc  __weak id wi;
130f4a2713aSLionel Sambuc  __autoreleasing id ai;
131f4a2713aSLionel Sambuc  __unsafe_unretained id ui;
132f4a2713aSLionel Sambuc  identity<id> res3 = accept_strong_ref(si);
133f4a2713aSLionel Sambuc  identity<__strong id> res4 = accept_any_ref(si);
134f4a2713aSLionel Sambuc  identity<__weak id> res5 = accept_any_ref(wi);
135f4a2713aSLionel Sambuc  identity<__autoreleasing id> res6 = accept_any_ref(ai);
136f4a2713aSLionel Sambuc  identity<__unsafe_unretained id> res7 = accept_any_ref(ui);
137f4a2713aSLionel Sambuc}
138f4a2713aSLionel Sambuc
139f4a2713aSLionel Sambucvoid test_func_deduction_A() {
140f4a2713aSLionel Sambuc  __strong A * *sip;
141f4a2713aSLionel Sambuc  __weak A * *wip;
142f4a2713aSLionel Sambuc  __autoreleasing A * *aip;
143f4a2713aSLionel Sambuc  __unsafe_unretained A * *uip;
144f4a2713aSLionel Sambuc
145f4a2713aSLionel Sambuc  identity<A *> res1 = accept_strong_ptr(sip);
146f4a2713aSLionel Sambuc  identity<__strong A *> res2 = accept_any_ptr(sip);
147f4a2713aSLionel Sambuc
148f4a2713aSLionel Sambuc  __strong A * si;
149f4a2713aSLionel Sambuc  __weak A * wi;
150f4a2713aSLionel Sambuc  __autoreleasing A * ai;
151f4a2713aSLionel Sambuc  __unsafe_unretained A * ui;
152f4a2713aSLionel Sambuc  identity<A *> res3 = accept_strong_ref(si);
153f4a2713aSLionel Sambuc  identity<__strong A *> res4 = accept_any_ref(si);
154f4a2713aSLionel Sambuc  identity<__weak A *> res5 = accept_any_ref(wi);
155f4a2713aSLionel Sambuc  identity<__autoreleasing A *> res6 = accept_any_ref(ai);
156f4a2713aSLionel Sambuc  identity<__unsafe_unretained A *> res7 = accept_any_ref(ui);
157f4a2713aSLionel Sambuc}
158f4a2713aSLionel Sambuc
159f4a2713aSLionel Sambuc// Test partial ordering (qualified vs. non-qualified).
160f4a2713aSLionel Sambuctemplate<typename T>
161f4a2713aSLionel Sambucstruct classify_pointer_pointer {
162f4a2713aSLionel Sambuc  static const unsigned value = 0;
163f4a2713aSLionel Sambuc};
164f4a2713aSLionel Sambuc
165f4a2713aSLionel Sambuctemplate<typename T>
166f4a2713aSLionel Sambucstruct classify_pointer_pointer<T*> {
167f4a2713aSLionel Sambuc  static const unsigned value = 1;
168f4a2713aSLionel Sambuc};
169f4a2713aSLionel Sambuc
170f4a2713aSLionel Sambuctemplate<typename T>
171f4a2713aSLionel Sambucstruct classify_pointer_pointer<__strong T*> {
172f4a2713aSLionel Sambuc  static const unsigned value = 2;
173f4a2713aSLionel Sambuc};
174f4a2713aSLionel Sambuc
175f4a2713aSLionel Sambuctemplate<typename T>
176f4a2713aSLionel Sambucstruct classify_pointer_pointer<__weak T*> {
177f4a2713aSLionel Sambuc  static const unsigned value = 3;
178f4a2713aSLionel Sambuc};
179f4a2713aSLionel Sambuc
180f4a2713aSLionel Sambuctemplate<typename T>
181f4a2713aSLionel Sambucstruct classify_pointer_pointer<T&> {
182f4a2713aSLionel Sambuc  static const unsigned value = 4;
183f4a2713aSLionel Sambuc};
184f4a2713aSLionel Sambuc
185f4a2713aSLionel Sambuctemplate<typename T>
186f4a2713aSLionel Sambucstruct classify_pointer_pointer<__strong T&> {
187f4a2713aSLionel Sambuc  static const unsigned value = 5;
188f4a2713aSLionel Sambuc};
189f4a2713aSLionel Sambuc
190f4a2713aSLionel Sambuctemplate<typename T>
191f4a2713aSLionel Sambucstruct classify_pointer_pointer<__weak T&> {
192f4a2713aSLionel Sambuc  static const unsigned value = 6;
193f4a2713aSLionel Sambuc};
194f4a2713aSLionel Sambuc
195f4a2713aSLionel Sambucint classify_ptr1[classify_pointer_pointer<int>::value == 0? 1 : -1];
196f4a2713aSLionel Sambucint classify_ptr2[classify_pointer_pointer<int *>::value == 1? 1 : -1];
197f4a2713aSLionel Sambucint classify_ptr3[classify_pointer_pointer<id __strong *>::value == 2? 1 : -1];
198f4a2713aSLionel Sambucint classify_ptr4[classify_pointer_pointer<id __weak *>::value == 3? 1 : -1];
199f4a2713aSLionel Sambucint classify_ptr5[classify_pointer_pointer<int&>::value == 4? 1 : -1];
200f4a2713aSLionel Sambucint classify_ptr6[classify_pointer_pointer<id __strong&>::value == 5? 1 : -1];
201f4a2713aSLionel Sambucint classify_ptr7[classify_pointer_pointer<id __weak&>::value == 6? 1 : -1];
202f4a2713aSLionel Sambucint classify_ptr8[classify_pointer_pointer<id __autoreleasing&>::value == 4? 1 : -1];
203f4a2713aSLionel Sambucint classify_ptr9[classify_pointer_pointer<id __unsafe_unretained&>::value == 4? 1 : -1];
204f4a2713aSLionel Sambucint classify_ptr10[classify_pointer_pointer<id __autoreleasing *>::value == 1? 1 : -1];
205f4a2713aSLionel Sambucint classify_ptr11[classify_pointer_pointer<id __unsafe_unretained *>::value == 1? 1 : -1];
206f4a2713aSLionel Sambucint classify_ptr12[classify_pointer_pointer<int *>::value == 1? 1 : -1];
207f4a2713aSLionel Sambucint classify_ptr13[classify_pointer_pointer<A * __strong *>::value == 2? 1 : -1];
208f4a2713aSLionel Sambucint classify_ptr14[classify_pointer_pointer<A * __weak *>::value == 3? 1 : -1];
209f4a2713aSLionel Sambucint classify_ptr15[classify_pointer_pointer<int&>::value == 4? 1 : -1];
210f4a2713aSLionel Sambucint classify_ptr16[classify_pointer_pointer<A * __strong&>::value == 5? 1 : -1];
211f4a2713aSLionel Sambucint classify_ptr17[classify_pointer_pointer<A * __weak&>::value == 6? 1 : -1];
212f4a2713aSLionel Sambucint classify_ptr18[classify_pointer_pointer<A * __autoreleasing&>::value == 4? 1 : -1];
213f4a2713aSLionel Sambucint classify_ptr19[classify_pointer_pointer<A * __unsafe_unretained&>::value == 4? 1 : -1];
214f4a2713aSLionel Sambucint classify_ptr20[classify_pointer_pointer<A * __autoreleasing *>::value == 1? 1 : -1];
215f4a2713aSLionel Sambucint classify_ptr21[classify_pointer_pointer<A * __unsafe_unretained *>::value == 1? 1 : -1];
216f4a2713aSLionel Sambuc
217f4a2713aSLionel Sambuctemplate<typename T> int& qual_vs_unqual_ptr(__strong T*);
218f4a2713aSLionel Sambuctemplate<typename T> double& qual_vs_unqual_ptr(__weak T*);
219f4a2713aSLionel Sambuctemplate<typename T> float& qual_vs_unqual_ptr(T*);
220f4a2713aSLionel Sambuctemplate<typename T> int& qual_vs_unqual_ref(__strong T&);
221f4a2713aSLionel Sambuctemplate<typename T> double& qual_vs_unqual_ref(__weak T&);
222f4a2713aSLionel Sambuctemplate<typename T> float& qual_vs_unqual_ref(T&);
223f4a2713aSLionel Sambuc
224f4a2713aSLionel Sambucvoid test_qual_vs_unqual_id() {
225f4a2713aSLionel Sambuc  __strong id *sip;
226f4a2713aSLionel Sambuc  __weak id *wip;
227f4a2713aSLionel Sambuc  __autoreleasing id *aip;
228f4a2713aSLionel Sambuc  __unsafe_unretained id *uip;
229f4a2713aSLionel Sambuc
230f4a2713aSLionel Sambuc  int &ir1 = qual_vs_unqual_ptr(sip);
231f4a2713aSLionel Sambuc  double &dr1 = qual_vs_unqual_ptr(wip);
232f4a2713aSLionel Sambuc  float &fr1 = qual_vs_unqual_ptr(aip);
233f4a2713aSLionel Sambuc  float &fr2 = qual_vs_unqual_ptr(uip);
234f4a2713aSLionel Sambuc
235f4a2713aSLionel Sambuc  int &ir2 = qual_vs_unqual_ref(*sip);
236f4a2713aSLionel Sambuc  double &dr2 = qual_vs_unqual_ref(*wip);
237f4a2713aSLionel Sambuc  float &fr3 = qual_vs_unqual_ref(*aip);
238f4a2713aSLionel Sambuc  float &fr4 = qual_vs_unqual_ref(*uip);
239f4a2713aSLionel Sambuc}
240f4a2713aSLionel Sambuc
241f4a2713aSLionel Sambucvoid test_qual_vs_unqual_a() {
242f4a2713aSLionel Sambuc  __strong A * *sap;
243f4a2713aSLionel Sambuc  __weak A * *wap;
244f4a2713aSLionel Sambuc  __autoreleasing A * *aap;
245f4a2713aSLionel Sambuc  __unsafe_unretained A * *uap;
246f4a2713aSLionel Sambuc
247f4a2713aSLionel Sambuc  int &ir1 = qual_vs_unqual_ptr(sap);
248f4a2713aSLionel Sambuc  double &dr1 = qual_vs_unqual_ptr(wap);
249f4a2713aSLionel Sambuc  float &fr1 = qual_vs_unqual_ptr(aap);
250f4a2713aSLionel Sambuc  float &fr2 = qual_vs_unqual_ptr(uap);
251f4a2713aSLionel Sambuc
252f4a2713aSLionel Sambuc  int &ir2 = qual_vs_unqual_ref(*sap);
253f4a2713aSLionel Sambuc  double &dr2 = qual_vs_unqual_ref(*wap);
254f4a2713aSLionel Sambuc  float &fr3 = qual_vs_unqual_ref(*aap);
255f4a2713aSLionel Sambuc  float &fr4 = qual_vs_unqual_ref(*uap);
256f4a2713aSLionel Sambuc}
257f4a2713aSLionel Sambuc
258f4a2713aSLionel Sambucnamespace rdar9828157 {
259f4a2713aSLionel Sambuc  // Template argument deduction involving lifetime qualifiers and
260f4a2713aSLionel Sambuc  // non-lifetime types.
261f4a2713aSLionel Sambuc  class A { };
262f4a2713aSLionel Sambuc
263f4a2713aSLionel Sambuc  template<typename T> float& f(T&);
264f4a2713aSLionel Sambuc  template<typename T> int& f(__strong T&);
265f4a2713aSLionel Sambuc  template<typename T> double& f(__weak T&);
266f4a2713aSLionel Sambuc
267f4a2713aSLionel Sambuc  void test_f(A* ap) {
268f4a2713aSLionel Sambuc    float &fr = (f)(ap);
269f4a2713aSLionel Sambuc  }
270f4a2713aSLionel Sambuc}
271f4a2713aSLionel Sambuc
272f4a2713aSLionel Sambucnamespace rdar10862386 {
273f4a2713aSLionel Sambuc  // More deduction with lifetime qualifiers.
274f4a2713aSLionel Sambuc  template <typename T>
275f4a2713aSLionel Sambuc  int testing(const T &) {
276f4a2713aSLionel Sambuc      return 1;
277f4a2713aSLionel Sambuc  }
278f4a2713aSLionel Sambuc
279f4a2713aSLionel Sambuc  void test() {
280f4a2713aSLionel Sambuc     testing(1);
281f4a2713aSLionel Sambuc      testing("hi");
282f4a2713aSLionel Sambuc      testing<NSString *>(@"hi");
283f4a2713aSLionel Sambuc      testing(@"hi");
284f4a2713aSLionel Sambuc }
285f4a2713aSLionel Sambuc}
286f4a2713aSLionel Sambuc
287f4a2713aSLionel Sambucnamespace rdar12367446 {
288f4a2713aSLionel Sambuc  template <class T> class A;
289f4a2713aSLionel Sambuc  template <class R> class A<R()> {};
290f4a2713aSLionel Sambuc
291f4a2713aSLionel Sambuc  void test() {
292f4a2713aSLionel Sambuc    A<id()> value;
293f4a2713aSLionel Sambuc  }
294f4a2713aSLionel Sambuc}
295f4a2713aSLionel Sambuc
296f4a2713aSLionel Sambucnamespace rdar14467941 {
297f4a2713aSLionel Sambuc  template<typename T> int &takePtr(const T &);
298f4a2713aSLionel Sambuc  template<typename T> float &takePtr(T * const &);
299f4a2713aSLionel Sambuc
300f4a2713aSLionel Sambuc  void testTakePtr(A *a) {
301f4a2713aSLionel Sambuc    float &fr1 = takePtr(a);
302f4a2713aSLionel Sambuc    float &fr2 = takePtr<A>(a);
303f4a2713aSLionel Sambuc  }
304f4a2713aSLionel Sambuc}
305*0a6a1f1dSLionel Sambuc
306*0a6a1f1dSLionel Sambucnamespace rdar15713945 {
307*0a6a1f1dSLionel Sambuc  template <class T> int &f(__strong T &);
308*0a6a1f1dSLionel Sambuc  template <class T> float &f(__weak T &);
309*0a6a1f1dSLionel Sambuc  template <class T> double &f(__unsafe_unretained T &);
310*0a6a1f1dSLionel Sambuc  template <class T> char &f(T &);
311*0a6a1f1dSLionel Sambuc
312*0a6a1f1dSLionel Sambuc  void foo() {
313*0a6a1f1dSLionel Sambuc    __strong NSString * const strong = 0;
314*0a6a1f1dSLionel Sambuc    int &ir = (f)(strong);
315*0a6a1f1dSLionel Sambuc    __weak NSString * const weak = 0;
316*0a6a1f1dSLionel Sambuc    float &fr = (f)(weak);
317*0a6a1f1dSLionel Sambuc    __unsafe_unretained NSString * const unsafe = 0;
318*0a6a1f1dSLionel Sambuc    double &dr = (f)(unsafe);
319*0a6a1f1dSLionel Sambuc  }
320*0a6a1f1dSLionel Sambuc}
321