1 // RUN: %clang_cc1 -fobjc-runtime-has-weak -fsyntax-only -fobjc-arc -verify -fblocks -std=c++11 %s 2 3 #define CONSUMED __attribute__((ns_consumed)) 4 #define PRODUCED __attribute__((ns_returns_retained)) 5 6 @interface A 7 @end 8 9 @class NSString; 10 11 template<typename T, typename U> 12 struct is_same { 13 static const bool value = false; 14 }; 15 16 template<typename T> 17 struct is_same<T, T> { 18 static const bool value = true; 19 }; 20 21 // Instantiation for reference/pointer types that will get lifetime 22 // adjustments. 23 template<typename T> 24 struct X0 { 25 typedef T* pointer; // okay: ends up being strong. 26 typedef T& reference; // okay: ends up being strong 27 }; 28 29 void test_X0() { 30 X0<id> x0id; 31 X0<A*> x0a; 32 X0<__strong A*> x0sa; 33 34 id __strong *ptr; 35 id __strong val; 36 X0<__strong id>::pointer &ptr_ref = ptr; 37 X0<__strong id>::reference ref = val; 38 } 39 40 int check_infer_strong[is_same<id, __strong id>::value? 1 : -1]; 41 42 // Check template argument deduction (e.g., for specialization) using 43 // lifetime qualifiers. 44 template<typename T> 45 struct is_pointer_strong { 46 static const bool value = false; 47 }; 48 49 template<typename T> 50 struct is_pointer_strong<__strong T*> { 51 static const bool value = true; 52 }; 53 54 int check_ptr_strong1[is_pointer_strong<__strong id*>::value? 1 : -1]; 55 int check_ptr_strong2[is_pointer_strong<__weak id*>::value? -1 : 1]; 56 int check_ptr_strong3[is_pointer_strong<__autoreleasing id*>::value? -1 : 1]; 57 int check_ptr_strong4[is_pointer_strong<__unsafe_unretained id*>::value? -1 : 1]; 58 int check_ptr_strong5[is_pointer_strong<id>::value? -1 : 1]; 59 60 // Check substitution into lifetime-qualified dependent types. 61 template<typename T> 62 struct make_strong_pointer { 63 typedef __strong T *type; 64 }; 65 66 template<typename T> 67 struct make_strong_pointer<__weak T> { 68 typedef __strong T *type; 69 }; 70 71 template<typename T> 72 struct make_strong_pointer<__autoreleasing T> { 73 typedef __strong T *type; 74 }; 75 76 template<typename T> 77 struct make_strong_pointer<__unsafe_unretained T> { 78 typedef __strong T *type; 79 }; 80 81 // Adding qualifiers 82 int check_make_strong1[is_same<make_strong_pointer<id>::type, __strong id *>::value ? 1 : -1]; 83 int check_make_strong2[is_same<make_strong_pointer<A*>::type, A* __strong *>::value ? 1 : -1]; 84 85 // Adding redundant qualifiers 86 int check_make_strong3[is_same<make_strong_pointer<__strong id>::type, __strong id *>::value ? 1 : -1]; 87 int check_make_strong4[is_same<make_strong_pointer<__strong A*>::type, A* __strong *>::value ? 1 : -1]; 88 89 // Adding nonsensical qualifiers. 90 int check_make_strong5[is_same<make_strong_pointer<int>::type, int *>::value ? 1 : -1]; 91 int check_make_strong6[is_same<make_strong_pointer<__weak id>::type, __strong id *>::value ? 1 : -1]; 92 93 template<typename T> 94 struct make_weak { 95 typedef __weak T type; 96 }; 97 98 int check_make_weak0[is_same<make_weak<id>::type, __weak id>::value? 1 : -1]; 99 int check_make_weak1[is_same<make_weak<__strong id>::type, __weak id>::value? 1 : -1]; 100 int check_make_weak2[is_same<make_weak<__autoreleasing id>::type, __weak id>::value? 1 : -1]; 101 102 template<typename T> 103 struct make_weak_fail { 104 typedef T T_type; 105 typedef __weak T_type type; // expected-error{{the type 'T_type' (aka '__weak id') is already explicitly ownership-qualified}} \ 106 // expected-error{{the type 'T_type' (aka '__strong id') is already explicitly ownership-qualified}} 107 }; 108 109 int 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}} 110 111 int 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}} 112 113 // Check template argument deduction from function templates. 114 template<typename T> struct identity { }; 115 116 template<typename T> identity<T> accept_strong_ptr(__strong T*); 117 template<typename T> identity<T> accept_strong_ref(__strong T&); 118 119 template<typename T> identity<T> accept_any_ptr(T*); 120 template<typename T> identity<T> accept_any_ref(T&); 121 122 void test_func_deduction_id() { 123 __strong id *sip; 124 __weak id *wip; 125 __autoreleasing id *aip; 126 __unsafe_unretained id *uip; 127 128 identity<id> res1 = accept_strong_ptr(sip); 129 identity<__strong id> res2 = accept_any_ptr(sip); 130 131 __strong id si; 132 __weak id wi; 133 __autoreleasing id ai; 134 __unsafe_unretained id ui; 135 identity<id> res3 = accept_strong_ref(si); 136 identity<__strong id> res4 = accept_any_ref(si); 137 identity<__weak id> res5 = accept_any_ref(wi); 138 identity<__autoreleasing id> res6 = accept_any_ref(ai); 139 identity<__unsafe_unretained id> res7 = accept_any_ref(ui); 140 } 141 142 void test_func_deduction_A() { 143 __strong A * *sip; 144 __weak A * *wip; 145 __autoreleasing A * *aip; 146 __unsafe_unretained A * *uip; 147 148 identity<A *> res1 = accept_strong_ptr(sip); 149 identity<__strong A *> res2 = accept_any_ptr(sip); 150 151 __strong A * si; 152 __weak A * wi; 153 __autoreleasing A * ai; 154 __unsafe_unretained A * ui; 155 identity<A *> res3 = accept_strong_ref(si); 156 identity<__strong A *> res4 = accept_any_ref(si); 157 identity<__weak A *> res5 = accept_any_ref(wi); 158 identity<__autoreleasing A *> res6 = accept_any_ref(ai); 159 identity<__unsafe_unretained A *> res7 = accept_any_ref(ui); 160 } 161 162 // Test partial ordering (qualified vs. non-qualified). 163 template<typename T> 164 struct classify_pointer_pointer { 165 static const unsigned value = 0; 166 }; 167 168 template<typename T> 169 struct classify_pointer_pointer<T*> { 170 static const unsigned value = 1; 171 }; 172 173 template<typename T> 174 struct classify_pointer_pointer<__strong T*> { 175 static const unsigned value = 2; 176 }; 177 178 template<typename T> 179 struct classify_pointer_pointer<__weak T*> { 180 static const unsigned value = 3; 181 }; 182 183 template<typename T> 184 struct classify_pointer_pointer<T&> { 185 static const unsigned value = 4; 186 }; 187 188 template<typename T> 189 struct classify_pointer_pointer<__strong T&> { 190 static const unsigned value = 5; 191 }; 192 193 template<typename T> 194 struct classify_pointer_pointer<__weak T&> { 195 static const unsigned value = 6; 196 }; 197 198 int classify_ptr1[classify_pointer_pointer<int>::value == 0? 1 : -1]; 199 int classify_ptr2[classify_pointer_pointer<int *>::value == 1? 1 : -1]; 200 int classify_ptr3[classify_pointer_pointer<id __strong *>::value == 2? 1 : -1]; 201 int classify_ptr4[classify_pointer_pointer<id __weak *>::value == 3? 1 : -1]; 202 int classify_ptr5[classify_pointer_pointer<int&>::value == 4? 1 : -1]; 203 int classify_ptr6[classify_pointer_pointer<id __strong&>::value == 5? 1 : -1]; 204 int classify_ptr7[classify_pointer_pointer<id __weak&>::value == 6? 1 : -1]; 205 int classify_ptr8[classify_pointer_pointer<id __autoreleasing&>::value == 4? 1 : -1]; 206 int classify_ptr9[classify_pointer_pointer<id __unsafe_unretained&>::value == 4? 1 : -1]; 207 int classify_ptr10[classify_pointer_pointer<id __autoreleasing *>::value == 1? 1 : -1]; 208 int classify_ptr11[classify_pointer_pointer<id __unsafe_unretained *>::value == 1? 1 : -1]; 209 int classify_ptr12[classify_pointer_pointer<int *>::value == 1? 1 : -1]; 210 int classify_ptr13[classify_pointer_pointer<A * __strong *>::value == 2? 1 : -1]; 211 int classify_ptr14[classify_pointer_pointer<A * __weak *>::value == 3? 1 : -1]; 212 int classify_ptr15[classify_pointer_pointer<int&>::value == 4? 1 : -1]; 213 int classify_ptr16[classify_pointer_pointer<A * __strong&>::value == 5? 1 : -1]; 214 int classify_ptr17[classify_pointer_pointer<A * __weak&>::value == 6? 1 : -1]; 215 int classify_ptr18[classify_pointer_pointer<A * __autoreleasing&>::value == 4? 1 : -1]; 216 int classify_ptr19[classify_pointer_pointer<A * __unsafe_unretained&>::value == 4? 1 : -1]; 217 int classify_ptr20[classify_pointer_pointer<A * __autoreleasing *>::value == 1? 1 : -1]; 218 int classify_ptr21[classify_pointer_pointer<A * __unsafe_unretained *>::value == 1? 1 : -1]; 219 220 template<typename T> int& qual_vs_unqual_ptr(__strong T*); 221 template<typename T> double& qual_vs_unqual_ptr(__weak T*); 222 template<typename T> float& qual_vs_unqual_ptr(T*); 223 template<typename T> int& qual_vs_unqual_ref(__strong T&); 224 template<typename T> double& qual_vs_unqual_ref(__weak T&); 225 template<typename T> float& qual_vs_unqual_ref(T&); 226 227 void test_qual_vs_unqual_id() { 228 __strong id *sip; 229 __weak id *wip; 230 __autoreleasing id *aip; 231 __unsafe_unretained id *uip; 232 233 int &ir1 = qual_vs_unqual_ptr(sip); 234 double &dr1 = qual_vs_unqual_ptr(wip); 235 float &fr1 = qual_vs_unqual_ptr(aip); 236 float &fr2 = qual_vs_unqual_ptr(uip); 237 238 int &ir2 = qual_vs_unqual_ref(*sip); 239 double &dr2 = qual_vs_unqual_ref(*wip); 240 float &fr3 = qual_vs_unqual_ref(*aip); 241 float &fr4 = qual_vs_unqual_ref(*uip); 242 } 243 244 void test_qual_vs_unqual_a() { 245 __strong A * *sap; 246 __weak A * *wap; 247 __autoreleasing A * *aap; 248 __unsafe_unretained A * *uap; 249 250 int &ir1 = qual_vs_unqual_ptr(sap); 251 double &dr1 = qual_vs_unqual_ptr(wap); 252 float &fr1 = qual_vs_unqual_ptr(aap); 253 float &fr2 = qual_vs_unqual_ptr(uap); 254 255 int &ir2 = qual_vs_unqual_ref(*sap); 256 double &dr2 = qual_vs_unqual_ref(*wap); 257 float &fr3 = qual_vs_unqual_ref(*aap); 258 float &fr4 = qual_vs_unqual_ref(*uap); 259 } 260 261 namespace rdar9828157 { 262 // Template argument deduction involving lifetime qualifiers and 263 // non-lifetime types. 264 class A { }; 265 266 template<typename T> float& f(T&); 267 template<typename T> int& f(__strong T&); 268 template<typename T> double& f(__weak T&); 269 270 void test_f(A* ap) { 271 float &fr = (f)(ap); 272 } 273 } 274 275 namespace rdar10862386 { 276 // More deduction with lifetime qualifiers. 277 template <typename T> 278 int testing(const T &) { 279 return 1; 280 } 281 282 void test() { 283 testing(1); 284 testing("hi"); 285 testing<NSString *>(@"hi"); 286 testing(@"hi"); 287 } 288 } 289 290 namespace rdar12367446 { 291 template <class T> class A; 292 template <class R> class A<R()> {}; 293 294 void test() { 295 A<id()> value; 296 } 297 } 298 299 namespace rdar14467941 { 300 template<typename T> int &takePtr(const T &); 301 template<typename T> float &takePtr(T * const &); 302 303 void testTakePtr(A *a) { 304 float &fr1 = takePtr(a); 305 float &fr2 = takePtr<A>(a); 306 } 307 } 308 309 namespace rdar15713945 { 310 template <class T> int &f(__strong T &); 311 template <class T> float &f(__weak T &); 312 template <class T> double &f(__unsafe_unretained T &); 313 template <class T> char &f(T &); 314 315 void foo() { 316 __strong NSString * const strong = 0; 317 int &ir = (f)(strong); 318 __weak NSString * const weak = 0; 319 float &fr = (f)(weak); 320 __unsafe_unretained NSString * const unsafe = 0; 321 double &dr = (f)(unsafe); 322 } 323 } 324 325 namespace consumed { 326 void take_yes_no(void (&)(id CONSUMED, id)); // expected-note 2 {{candidate function not viable}} 327 void take_no_yes(void (&)(id, CONSUMED id)); // expected-note 2 {{candidate function not viable}} 328 void take_yes_yes(void (&)(CONSUMED id, CONSUMED id)); // expected-note 2 {{candidate function not viable}} 329 330 template <class... As> void consumes_first(id CONSUMED, As...); 331 void test1() { 332 take_yes_no(consumes_first<id>); 333 take_no_yes(consumes_first<id>); // expected-error {{no matching function}} 334 take_yes_yes(consumes_first<id>); // expected-error {{no matching function}} 335 } 336 337 template <class... As> void consumes_rest(id, CONSUMED As...); 338 void test2() { 339 take_yes_no(consumes_rest<id>); // expected-error {{no matching function}} 340 take_no_yes(consumes_rest<id>); 341 take_yes_yes(consumes_rest<id>); // expected-error {{no matching function}} 342 } 343 344 template <class T, class U> void consumes_two(CONSUMED T, CONSUMED U); 345 void test3() { 346 take_yes_no(consumes_two); // expected-error {{no matching function}} 347 take_no_yes(consumes_two); // expected-error {{no matching function}} 348 take_yes_yes(consumes_two); 349 } 350 } 351 352 namespace consumed_nested { 353 void take_yes_no(void (&)(id CONSUMED, id)); // expected-note 4 {{candidate function not viable}} 354 void take_no_yes(void (&)(id, CONSUMED id)); // expected-note 4 {{candidate function not viable}} 355 void take_yes_yes(void (&)(CONSUMED id, CONSUMED id)); // expected-note 4 {{candidate function not viable}} 356 357 template <unsigned N> struct consumes_first { 358 template <class... As> static void fn(id CONSUMED, As...); 359 }; 360 void test1() { 361 take_yes_no(consumes_first<1>::fn<id>); 362 take_no_yes(consumes_first<2>::fn<id>); // expected-error {{no matching function}} 363 take_yes_yes(consumes_first<3>::fn<id>); // expected-error {{no matching function}} 364 take_yes_no(consumes_first<4>::fn); 365 take_no_yes(consumes_first<5>::fn); // expected-error {{no matching function}} 366 take_yes_yes(consumes_first<6>::fn); // expected-error {{no matching function}} 367 } 368 369 template <unsigned N> struct consumes_rest { 370 template <class... As> static void fn(id, CONSUMED As...); 371 }; 372 void test2() { 373 take_yes_no(consumes_rest<1>::fn<id>); // expected-error {{no matching function}} 374 take_no_yes(consumes_rest<2>::fn<id>); 375 take_yes_yes(consumes_rest<3>::fn<id>); // expected-error {{no matching function}} 376 take_yes_no(consumes_rest<4>::fn<id>); // expected-error {{no matching function}} 377 take_no_yes(consumes_rest<5>::fn<id>); 378 take_yes_yes(consumes_rest<6>::fn<id>); // expected-error {{no matching function}} 379 } 380 381 template <unsigned N> struct consumes_two { 382 template <class T, class U> static void fn(CONSUMED T, CONSUMED U); 383 }; 384 void test3() { 385 take_yes_no(consumes_two<1>::fn<id, id>); // expected-error {{no matching function}} 386 take_no_yes(consumes_two<2>::fn<id, id>); // expected-error {{no matching function}} 387 take_yes_yes(consumes_two<3>::fn<id, id>); 388 take_yes_no(consumes_two<1>::fn); // expected-error {{no matching function}} 389 take_no_yes(consumes_two<2>::fn); // expected-error {{no matching function}} 390 take_yes_yes(consumes_two<3>::fn); 391 } 392 } 393 394 namespace produced { 395 void take_yes(PRODUCED id (&)()); // expected-note 2 {{candidate function not viable}} 396 void take_no(id (&)()); // expected-note 2 {{candidate function not viable}} 397 398 template <class T> T non_produces1(); 399 template <class T> T non_produces2(); 400 template <class T> T non_produces3(); 401 template <class T> T non_produces4(); 402 void test1() { 403 take_yes(non_produces1<id>); // expected-error {{no matching function}} 404 take_yes(non_produces2); // expected-error {{no matching function}} 405 take_no(non_produces3<id>); 406 take_no(non_produces4); 407 } 408 409 template <class T> PRODUCED T produces1(); 410 template <class T> PRODUCED T produces2(); 411 template <class T> PRODUCED T produces3(); 412 template <class T> PRODUCED T produces4(); 413 void test2() { 414 take_yes(produces1<id>); 415 take_yes(produces2); 416 take_no(produces3<id>); // expected-error {{no matching function}} 417 take_no(produces4); // expected-error {{no matching function}} 418 } 419 } 420 421 namespace produced_nested { 422 void take_yes(PRODUCED id (&)()); // expected-note 2 {{candidate function not viable}} 423 void take_no(id (&)()); // expected-note 2 {{candidate function not viable}} 424 425 template <unsigned N> struct non_produces { 426 template <class T> static T fn(); 427 }; 428 void test1() { 429 take_yes(non_produces<1>::fn<id>); // expected-error {{no matching function}} 430 take_yes(non_produces<2>::fn); // expected-error {{no matching function}} 431 take_no(non_produces<3>::fn<id>); 432 take_no(non_produces<4>::fn); 433 } 434 435 template <unsigned N> struct produces { 436 template <class T> static PRODUCED T fn(); 437 }; 438 void test2() { 439 take_yes(produces<1>::fn<id>); 440 take_yes(produces<2>::fn); 441 take_no(produces<3>::fn<id>); // expected-error {{no matching function}} 442 take_no(produces<4>::fn); // expected-error {{no matching function}} 443 } 444 } 445 446 namespace instantiate_consumed { 447 template <class T> void take(CONSUMED T t) {} // expected-note {{candidate template ignored: substitution failure [with T = int]: ns_consumed attribute only applies to Objective-C object parameters}} 448 void test() { 449 take((id) 0); 450 take((int) 0); // expected-error {{no matching function for call to 'take'}} 451 } 452 } 453