reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174
  175
  176
  177
  178
  179
  180
  181
  182
  183
  184
  185
  186
  187
  188
  189
  190
  191
  192
  193
  194
  195
  196
  197
  198
  199
  200
  201
  202
  203
  204
  205
  206
  207
  208
  209
  210
  211
  212
  213
  214
  215
  216
  217
  218
// RUN: %clang_cc1 -fobjc-runtime-has-weak -fsyntax-only -fobjc-arc -verify -fblocks %s
// rdar://8843600

void * cvt(id arg) // expected-note{{candidate function not viable: cannot convert argument of incomplete type 'void *' to '__strong id'}}
{
  void* voidp_val;
  (void)(int*)arg; // expected-error {{cast of an Objective-C pointer to 'int *' is disallowed with ARC}}
  (void)(id)arg;
  (void)(__autoreleasing id*)arg; // expected-error{{cast of an Objective-C pointer to '__autoreleasing id *' is disallowed with ARC}}
  (void)(id*)arg; // expected-error{{cast of an Objective-C pointer to '__strong id *' is disallowed with ARC}}

  (void)(__autoreleasing id**)voidp_val;
  (void)(void*)voidp_val;
  (void)(void**)arg; // expected-error {{cast of an Objective-C pointer to 'void **' is disallowed}}
  cvt((void*)arg); // expected-error {{no matching function for call to 'cvt'}}
  cvt(0);
  (void)(__strong id**)(0);

  // FIXME: Diagnostic could be better here.
  return arg; // expected-error{{cannot initialize return object of type 'void *' with an lvalue of type '__strong id'}}
}

// rdar://8898937
namespace rdar8898937 {

typedef void (^dispatch_block_t)(void);

void dispatch_once(dispatch_block_t block);
static void _dispatch_once(dispatch_block_t block)
{
  dispatch_once(block);
}

}

void static_casts(id arg) {
  void* voidp_val;
  (void)static_cast<int*>(arg); // expected-error {{cannot cast from type 'id' to pointer type 'int *'}}
  (void)static_cast<id>(arg);
  (void)static_cast<__autoreleasing id*>(arg); // expected-error{{cannot cast from type 'id' to pointer type '__autoreleasing id *'}}
  (void)static_cast<id*>(arg); // expected-error {{cannot cast from type 'id' to pointer type '__strong id *'}}

  (void)static_cast<__autoreleasing id**>(voidp_val);
  (void)static_cast<void*>(voidp_val);
  (void)static_cast<void**>(arg); // expected-error {{cannot cast from type 'id' to pointer type 'void **'}}
  (void)static_cast<__strong id**>(0);  

  __strong id *idp;
  (void)static_cast<__autoreleasing id*>(idp); // expected-error{{static_cast from '__strong id *' to '__autoreleasing id *' is not allowed}}
  (void)static_cast<__weak id*>(idp); // expected-error{{static_cast from '__strong id *' to '__weak id *' is not allowed}}
}

void test_const_cast(__strong id *sip, __weak id *wip, 
                     const __strong id *csip, __weak const id *cwip) {
  // Cannot use const_cast to cast between ownership qualifications or
  // add/remove ownership qualifications.
  (void)const_cast<__strong id *>(wip); // expected-error{{is not allowed}}
  (void)const_cast<__weak id *>(sip); // expected-error{{is not allowed}}

  // It's acceptable to cast away constness.
  (void)const_cast<__strong id *>(csip);
  (void)const_cast<__weak id *>(cwip);
}

void test_reinterpret_cast(__strong id *sip, __weak id *wip, 
                           const __strong id *csip, __weak const id *cwip) {
  // Okay to reinterpret_cast to add/remove/change ownership
  // qualifications.
  (void)reinterpret_cast<__strong id *>(wip);
  (void)reinterpret_cast<__weak id *>(sip);

  // Not allowed to cast away constness
  (void)reinterpret_cast<__strong id *>(csip); // expected-error{{reinterpret_cast from '__strong id const *' to '__strong id *' casts away qualifiers}}
  (void)reinterpret_cast<__weak id *>(cwip); // expected-error{{reinterpret_cast from '__weak id const *' to '__weak id *' casts away qualifiers}}
  (void)reinterpret_cast<__weak id *>(csip); // expected-error{{reinterpret_cast from '__strong id const *' to '__weak id *' casts away qualifiers}}
  (void)reinterpret_cast<__strong id *>(cwip); // expected-error{{reinterpret_cast from '__weak id const *' to '__strong id *' casts away qualifiers}}
}

void test_cstyle_cast(__strong id *sip, __weak id *wip, 
                      const __strong id *csip, __weak const id *cwip) {
  // C-style casts aren't allowed to change Objective-C ownership
  // qualifiers (beyond what the normal implicit conversion allows).

  (void)(__strong id *)wip; // expected-error{{C-style cast from '__weak id *' to '__strong id *' casts away qualifiers}}
  (void)(__strong id *)cwip; // expected-error{{C-style cast from '__weak id const *' to '__strong id *' casts away qualifiers}}
  (void)(__weak id *)sip; // expected-error{{C-style cast from '__strong id *' to '__weak id *' casts away qualifiers}}
  (void)(__weak id *)csip; // expected-error{{C-style cast from '__strong id const *' to '__weak id *' casts away qualifiers}}

  (void)(__strong const id *)wip; // expected-error{{C-style cast from '__weak id *' to '__strong id const *' casts away qualifiers}}
  (void)(__strong const id *)cwip; // expected-error{{C-style cast from '__weak id const *' to '__strong id const *' casts away qualifiers}}
  (void)(__weak const id *)sip; // expected-error{{C-style cast from '__strong id *' to '__weak id const *' casts away qualifiers}}
  (void)(__weak const id *)csip; // expected-error{{C-style cast from '__strong id const *' to '__weak id const *' casts away qualifiers}}
  (void)(__autoreleasing const id *)wip; // expected-error{{C-style cast from '__weak id *' to '__autoreleasing id const *' casts away qualifiers}}
  (void)(__autoreleasing const id *)cwip; // expected-error{{C-style cast from '__weak id const *' to '__autoreleasing id const *' casts away qualifiers}}
  (void)(__autoreleasing const id *)sip;
  (void)(__autoreleasing const id *)csip;
}

void test_functional_cast(__strong id *sip, __weak id *wip,
                          __autoreleasing id *aip) {
  // Functional casts aren't allowed to change Objective-C ownership
  // qualifiers (beyond what the normal implicit conversion allows).

  typedef __strong id *strong_id_pointer;
  typedef __weak id *weak_id_pointer;
  typedef __autoreleasing id *autoreleasing_id_pointer;

  typedef const __strong id *const_strong_id_pointer;
  typedef const __weak id *const_weak_id_pointer;
  typedef const __autoreleasing id *const_autoreleasing_id_pointer;

  (void)strong_id_pointer(wip); // expected-error{{functional-style cast from '__weak id *' to 'strong_id_pointer' (aka '__strong id *') casts away qualifiers}}
  (void)weak_id_pointer(sip); // expected-error{{functional-style cast from '__strong id *' to 'weak_id_pointer' (aka '__weak id *') casts away qualifiers}}
  (void)autoreleasing_id_pointer(sip); // expected-error{{functional-style cast from '__strong id *' to 'autoreleasing_id_pointer' (aka '__autoreleasing id *') casts away qualifiers}}
  (void)autoreleasing_id_pointer(wip); // expected-error{{functional-style cast from '__weak id *' to 'autoreleasing_id_pointer' (aka '__autoreleasing id *') casts away qualifiers}}
  (void)const_strong_id_pointer(wip); // expected-error{{functional-style cast from '__weak id *' to 'const_strong_id_pointer' (aka 'const __strong id *') casts away qualifiers}}
  (void)const_weak_id_pointer(sip); // expected-error{{functional-style cast from '__strong id *' to 'const_weak_id_pointer' (aka 'const __weak id *') casts away qualifiers}}
  (void)const_autoreleasing_id_pointer(sip);
  (void)const_autoreleasing_id_pointer(aip);
  (void)const_autoreleasing_id_pointer(wip); // expected-error{{functional-style cast from '__weak id *' to 'const_autoreleasing_id_pointer' (aka 'const __autoreleasing id *') casts away qualifiers}}
}

void test_unsafe_unretained(__strong id *sip, __weak id *wip,
                            __autoreleasing id *aip,
                            __unsafe_unretained id *uip,
                            const __unsafe_unretained id *cuip) {
  uip = sip; // expected-error{{assigning to '__unsafe_unretained id *' from incompatible type '__strong id *'}}
  uip = wip; // expected-error{{assigning to '__unsafe_unretained id *' from incompatible type '__weak id *'}}
  uip = aip; // expected-error{{assigning to '__unsafe_unretained id *' from incompatible type '__autoreleasing id *'}}

  cuip = sip;
  cuip = wip; // expected-error{{assigning to '__unsafe_unretained id const *' from incompatible type '__weak id *'}}
  cuip = aip;
}

void to_void(__strong id *sip, __weak id *wip,
             __autoreleasing id *aip,
             __unsafe_unretained id *uip) {
  void *vp1 = sip;
  void *vp2 = wip;
  void *vp3 = aip;
  void *vp4 = uip;
  (void)(void*)sip;
  (void)(void*)wip;
  (void)(void*)aip;
  (void)(void*)uip;
  (void)static_cast<void*>(sip);
  (void)static_cast<void*>(wip);
  (void)static_cast<void*>(aip);
  (void)static_cast<void*>(uip);
  (void)reinterpret_cast<void*>(sip);
  (void)reinterpret_cast<void*>(wip);
  (void)reinterpret_cast<void*>(aip);
  (void)reinterpret_cast<void*>(uip);

  (void)(void*)&sip;
  (void)(void*)&wip;
  (void)(void*)&aip;
  (void)(void*)&uip;
  (void)static_cast<void*>(&sip);
  (void)static_cast<void*>(&wip);
  (void)static_cast<void*>(&aip);
  (void)static_cast<void*>(&uip);
  (void)reinterpret_cast<void*>(&sip);
  (void)reinterpret_cast<void*>(&wip);
  (void)reinterpret_cast<void*>(&aip);
  (void)reinterpret_cast<void*>(&uip);
}

void from_void(void *vp) {
  __strong id *sip = (__strong id *)vp;
  __weak id *wip = (__weak id *)vp;
  __autoreleasing id *aip = (__autoreleasing id *)vp;
  __unsafe_unretained id *uip = (__unsafe_unretained id *)vp;
  __strong id *sip2 = static_cast<__strong id *>(vp);
  __weak id *wip2 = static_cast<__weak id *>(vp);
  __autoreleasing id *aip2 = static_cast<__autoreleasing id *>(vp);
  __unsafe_unretained id *uip2 = static_cast<__unsafe_unretained id *>(vp);
  __strong id *sip3 = reinterpret_cast<__strong id *>(vp);
  __weak id *wip3 = reinterpret_cast<__weak id *>(vp);
  __autoreleasing id *aip3 = reinterpret_cast<__autoreleasing id *>(vp);
  __unsafe_unretained id *uip3 = reinterpret_cast<__unsafe_unretained id *>(vp);

  __strong id **sipp = (__strong id **)vp;
  __weak id **wipp = (__weak id **)vp;
  __autoreleasing id **aipp = (__autoreleasing id **)vp;
  __unsafe_unretained id **uipp = (__unsafe_unretained id **)vp;

  sip = vp; // expected-error{{assigning to '__strong id *' from incompatible type 'void *'}}
  wip = vp; // expected-error{{assigning to '__weak id *' from incompatible type 'void *'}}
  aip = vp; // expected-error{{assigning to '__autoreleasing id *' from incompatible type 'void *'}}
  uip = vp; // expected-error{{assigning to '__unsafe_unretained id *' from incompatible type 'void *'}}
}

typedef void (^Block)();
typedef void (^Block_strong)() __strong;
typedef void (^Block_autoreleasing)() __autoreleasing;

@class NSString;

void ownership_transfer_in_cast(void *vp, Block *pblk) {
  __strong NSString **sip2 = static_cast<NSString **>(static_cast<__strong id *>(vp));
  __strong NSString **&si2pref = static_cast<NSString **&>(sip2);
  __weak NSString **wip2 = static_cast<NSString **>(static_cast<__weak id *>(vp));
  __autoreleasing id *aip2 = static_cast<id *>(static_cast<__autoreleasing id *>(vp));
  __unsafe_unretained id *uip2 = static_cast<id *>(static_cast<__unsafe_unretained id *>(vp));
  __strong id *sip3 = reinterpret_cast<id *>(reinterpret_cast<__strong id *>(vp));
  __weak id *wip3 = reinterpret_cast<id *>(reinterpret_cast<__weak id *>(vp));
  __autoreleasing id *aip3 = reinterpret_cast<id *>(reinterpret_cast<__autoreleasing id *>(vp));
  __unsafe_unretained id *uip3 = reinterpret_cast<id *>(reinterpret_cast<__unsafe_unretained id *>(vp));

  Block_strong blk_strong1;
  Block_strong blk_strong2 = static_cast<Block>(blk_strong1);
  Block_autoreleasing *blk_auto = static_cast<Block*>(pblk);
}

// Make sure we don't crash.
void writeback_test(NSString & &) {} // expected-error {{type name declared as a reference to a reference}}