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 11template<typename T, typename U> 12struct is_same { 13 static const bool value = false; 14}; 15 16template<typename T> 17struct is_same<T, T> { 18 static const bool value = true; 19}; 20 21// Instantiation for reference/pointer types that will get lifetime 22// adjustments. 23template<typename T> 24struct X0 { 25 typedef T* pointer; // okay: ends up being strong. 26 typedef T& reference; // okay: ends up being strong 27}; 28 29void 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 40int 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. 44template<typename T> 45struct is_pointer_strong { 46 static const bool value = false; 47}; 48 49template<typename T> 50struct is_pointer_strong<__strong T*> { 51 static const bool value = true; 52}; 53 54int check_ptr_strong1[is_pointer_strong<__strong id*>::value? 1 : -1]; 55int check_ptr_strong2[is_pointer_strong<__weak id*>::value? -1 : 1]; 56int check_ptr_strong3[is_pointer_strong<__autoreleasing id*>::value? -1 : 1]; 57int check_ptr_strong4[is_pointer_strong<__unsafe_unretained id*>::value? -1 : 1]; 58int check_ptr_strong5[is_pointer_strong<id>::value? -1 : 1]; 59 60// Check substitution into lifetime-qualified dependent types. 61template<typename T> 62struct make_strong_pointer { 63 typedef __strong T *type; 64}; 65 66template<typename T> 67struct make_strong_pointer<__weak T> { 68 typedef __strong T *type; 69}; 70 71template<typename T> 72struct make_strong_pointer<__autoreleasing T> { 73 typedef __strong T *type; 74}; 75 76template<typename T> 77struct make_strong_pointer<__unsafe_unretained T> { 78 typedef __strong T *type; 79}; 80 81// Adding qualifiers 82int check_make_strong1[is_same<make_strong_pointer<id>::type, __strong id *>::value ? 1 : -1]; 83int check_make_strong2[is_same<make_strong_pointer<A*>::type, A* __strong *>::value ? 1 : -1]; 84 85// Adding redundant qualifiers 86int check_make_strong3[is_same<make_strong_pointer<__strong id>::type, __strong id *>::value ? 1 : -1]; 87int check_make_strong4[is_same<make_strong_pointer<__strong A*>::type, A* __strong *>::value ? 1 : -1]; 88 89// Adding nonsensical qualifiers. 90int check_make_strong5[is_same<make_strong_pointer<int>::type, int *>::value ? 1 : -1]; 91int check_make_strong6[is_same<make_strong_pointer<__weak id>::type, __strong id *>::value ? 1 : -1]; 92 93template<typename T> 94struct make_weak { 95 typedef __weak T type; 96}; 97 98int check_make_weak0[is_same<make_weak<id>::type, __weak id>::value? 1 : -1]; 99int check_make_weak1[is_same<make_weak<__strong id>::type, __weak id>::value? 1 : -1]; 100int check_make_weak2[is_same<make_weak<__autoreleasing id>::type, __weak id>::value? 1 : -1]; 101 102template<typename T> 103struct make_weak_fail { 104 typedef T T_type; 105 typedef __weak T_type type; // expected-error{{the type 'make_weak_fail<__weak id>::T_type' (aka '__weak id') is already explicitly ownership-qualified}} \ 106 // expected-error{{the type 'make_weak_fail<id>::T_type' (aka '__strong id') is already explicitly ownership-qualified}} 107}; 108 109int 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 111int 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. 114template<typename T> struct identity { }; 115 116template<typename T> identity<T> accept_strong_ptr(__strong T*); 117template<typename T> identity<T> accept_strong_ref(__strong T&); 118 119template<typename T> identity<T> accept_any_ptr(T*); 120template<typename T> identity<T> accept_any_ref(T&); 121 122void 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 142void 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). 163template<typename T> 164struct classify_pointer_pointer { 165 static const unsigned value = 0; 166}; 167 168template<typename T> 169struct classify_pointer_pointer<T*> { 170 static const unsigned value = 1; 171}; 172 173template<typename T> 174struct classify_pointer_pointer<__strong T*> { 175 static const unsigned value = 2; 176}; 177 178template<typename T> 179struct classify_pointer_pointer<__weak T*> { 180 static const unsigned value = 3; 181}; 182 183template<typename T> 184struct classify_pointer_pointer<T&> { 185 static const unsigned value = 4; 186}; 187 188template<typename T> 189struct classify_pointer_pointer<__strong T&> { 190 static const unsigned value = 5; 191}; 192 193template<typename T> 194struct classify_pointer_pointer<__weak T&> { 195 static const unsigned value = 6; 196}; 197 198int classify_ptr1[classify_pointer_pointer<int>::value == 0? 1 : -1]; 199int classify_ptr2[classify_pointer_pointer<int *>::value == 1? 1 : -1]; 200int classify_ptr3[classify_pointer_pointer<id __strong *>::value == 2? 1 : -1]; 201int classify_ptr4[classify_pointer_pointer<id __weak *>::value == 3? 1 : -1]; 202int classify_ptr5[classify_pointer_pointer<int&>::value == 4? 1 : -1]; 203int classify_ptr6[classify_pointer_pointer<id __strong&>::value == 5? 1 : -1]; 204int classify_ptr7[classify_pointer_pointer<id __weak&>::value == 6? 1 : -1]; 205int classify_ptr8[classify_pointer_pointer<id __autoreleasing&>::value == 4? 1 : -1]; 206int classify_ptr9[classify_pointer_pointer<id __unsafe_unretained&>::value == 4? 1 : -1]; 207int classify_ptr10[classify_pointer_pointer<id __autoreleasing *>::value == 1? 1 : -1]; 208int classify_ptr11[classify_pointer_pointer<id __unsafe_unretained *>::value == 1? 1 : -1]; 209int classify_ptr12[classify_pointer_pointer<int *>::value == 1? 1 : -1]; 210int classify_ptr13[classify_pointer_pointer<A * __strong *>::value == 2? 1 : -1]; 211int classify_ptr14[classify_pointer_pointer<A * __weak *>::value == 3? 1 : -1]; 212int classify_ptr15[classify_pointer_pointer<int&>::value == 4? 1 : -1]; 213int classify_ptr16[classify_pointer_pointer<A * __strong&>::value == 5? 1 : -1]; 214int classify_ptr17[classify_pointer_pointer<A * __weak&>::value == 6? 1 : -1]; 215int classify_ptr18[classify_pointer_pointer<A * __autoreleasing&>::value == 4? 1 : -1]; 216int classify_ptr19[classify_pointer_pointer<A * __unsafe_unretained&>::value == 4? 1 : -1]; 217int classify_ptr20[classify_pointer_pointer<A * __autoreleasing *>::value == 1? 1 : -1]; 218int classify_ptr21[classify_pointer_pointer<A * __unsafe_unretained *>::value == 1? 1 : -1]; 219 220template<typename T> int& qual_vs_unqual_ptr(__strong T*); 221template<typename T> double& qual_vs_unqual_ptr(__weak T*); 222template<typename T> float& qual_vs_unqual_ptr(T*); 223template<typename T> int& qual_vs_unqual_ref(__strong T&); 224template<typename T> double& qual_vs_unqual_ref(__weak T&); 225template<typename T> float& qual_vs_unqual_ref(T&); 226 227void 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 244void 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 261namespace 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 275namespace 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 290namespace 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 299namespace 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 309namespace 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 325namespace 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 352namespace 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 394namespace 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 421namespace 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 446namespace 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