Home | History | Annotate | Download | only in SemaObjCXX
      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