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