diff options
Diffstat (limited to 'test/SemaObjCXX')
21 files changed, 1130 insertions, 5 deletions
diff --git a/test/SemaObjCXX/Inputs/arc-system-header.h b/test/SemaObjCXX/Inputs/arc-system-header.h new file mode 100644 index 0000000..d7adeb4 --- /dev/null +++ b/test/SemaObjCXX/Inputs/arc-system-header.h @@ -0,0 +1,14 @@ +@interface B +@end + + +@interface A { +@public + union { + struct { + B *b; + } a_b; + void *void_ptr; + } data; +} +@end diff --git a/test/SemaObjCXX/arc-0x.mm b/test/SemaObjCXX/arc-0x.mm new file mode 100644 index 0000000..fa022af --- /dev/null +++ b/test/SemaObjCXX/arc-0x.mm @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -std=c++0x -fobjc-nonfragile-abi -fsyntax-only -fobjc-arc -verify -fblocks -fobjc-exceptions %s + +// "Move" semantics, trivial version. +void move_it(__strong id &&from) { + id to = static_cast<__strong id&&>(from); +} + +// Deduction with 'auto'. +@interface A ++ alloc; +- init; +@end + +// Ensure that deduction works with lifetime qualifiers. +void deduction(id obj) { + auto a = [[A alloc] init]; + __strong A** aPtr = &a; + + auto a2([[A alloc] init]); + __strong A** aPtr2 = &a2; + + __strong id *idp = new auto(obj); + + __strong id array[17]; + for (auto x : array) { + __strong id *xPtr = &x; + } + + @try { + } @catch (auto e) { // expected-error {{'auto' not allowed in exception declaration}} + } +} diff --git a/test/SemaObjCXX/arc-bool-conversion.mm b/test/SemaObjCXX/arc-bool-conversion.mm new file mode 100644 index 0000000..86da3ca --- /dev/null +++ b/test/SemaObjCXX/arc-bool-conversion.mm @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -fobjc-nonfragile-abi -fsyntax-only -fobjc-arc -verify -fblocks -triple x86_64-apple-darwin10.0.0 %s +// rdar://9310049 + +bool fn(id obj) { + return (bool)obj; +} + diff --git a/test/SemaObjCXX/arc-bridged-cast.mm b/test/SemaObjCXX/arc-bridged-cast.mm new file mode 100644 index 0000000..cbbe79e --- /dev/null +++ b/test/SemaObjCXX/arc-bridged-cast.mm @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fobjc-nonfragile-abi -fsyntax-only -fobjc-arc -fblocks -verify %s + +typedef const void *CFTypeRef; +typedef const struct __CFString *CFStringRef; + +@interface NSString +@end + +CFTypeRef CFCreateSomething(); +CFStringRef CFCreateString(); +CFTypeRef CFGetSomething(); +CFStringRef CFGetString(); + +id CreateSomething(); +NSString *CreateNSString(); + +template<typename IdType, typename StringType, typename IntPtrType> +void from_cf() { + id obj1 = (__bridge_transfer IdType)CFCreateSomething(); + id obj2 = (__bridge_transfer StringType)CFCreateString(); + (__bridge IntPtrType)CFCreateSomething(); // expected-error{{incompatible types casting 'CFTypeRef' (aka 'const void *') to 'int *' with a __bridge cast}} + id obj3 = (__bridge IdType)CFGetSomething(); + id obj4 = (__bridge StringType)CFGetString(); +} + +template void from_cf<id, NSString*, int*>(); // expected-note{{in instantiation of function template specialization}} + +template<typename IdType, typename StringType> +void to_cf(id obj) { + CFTypeRef cf1 = (__bridge_retained IdType)CreateSomething(); + CFStringRef cf2 = (__bridge_retained StringType)CreateNSString(); + CFTypeRef cf3 = (__bridge IdType)CreateSomething(); + CFStringRef cf4 = (__bridge StringType)CreateNSString(); +} + +template void to_cf<CFTypeRef, CFStringRef>(id); diff --git a/test/SemaObjCXX/arc-libcxx.mm b/test/SemaObjCXX/arc-libcxx.mm new file mode 100644 index 0000000..7992f60 --- /dev/null +++ b/test/SemaObjCXX/arc-libcxx.mm @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -fsyntax-only -fobjc-arc -fobjc-arc-cxxlib=libc++ -fobjc-nonfragile-abi -fobjc-runtime-has-weak -verify %s + +@interface A @end + +void f(__strong id &sir, __weak id &wir, __autoreleasing id &air, + __unsafe_unretained id &uir) { + __strong id *sip = std::addressof(sir); + __weak id *wip = std::addressof(wir); + __autoreleasing id *aip = std::addressof(air); + __unsafe_unretained id *uip = std::addressof(uir); +} diff --git a/test/SemaObjCXX/arc-libstdcxx.mm b/test/SemaObjCXX/arc-libstdcxx.mm new file mode 100644 index 0000000..edb7a9e --- /dev/null +++ b/test/SemaObjCXX/arc-libstdcxx.mm @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -fsyntax-only -fobjc-arc -fobjc-arc-cxxlib=libstdc++ -fobjc-nonfragile-abi -fobjc-runtime-has-weak -verify %s + +@interface A @end + +int check0[std::__is_scalar<__strong id>::__value? -1 : 1]; +int check1[std::__is_scalar<__weak id>::__value? -1 : 1]; +int check2[std::__is_scalar<__autoreleasing id>::__value? -1 : 1]; +int check3[std::__is_scalar<__strong A*>::__value? -1 : 1]; +int check4[std::__is_scalar<__weak A*>::__value? -1 : 1]; +int check5[std::__is_scalar<__autoreleasing A*>::__value? -1 : 1]; diff --git a/test/SemaObjCXX/arc-memfunc.mm b/test/SemaObjCXX/arc-memfunc.mm new file mode 100644 index 0000000..75b94c6 --- /dev/null +++ b/test/SemaObjCXX/arc-memfunc.mm @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fobjc-nonfragile-abi -fsyntax-only -fobjc-arc -verify -fblocks %s + +struct X0 { + static id makeObject1() __attribute__((ns_returns_retained)); + id makeObject2() __attribute__((ns_returns_retained)); +}; + +void test_X0(X0 x0, X0 *x0p) { + X0::makeObject1(); + x0.makeObject2(); + x0p->makeObject2(); + id (X0::*pmf)() __attribute__((ns_returns_retained)) = &X0::makeObject2; + (x0.*pmf)(); + (x0p->*pmf)(); +} diff --git a/test/SemaObjCXX/arc-non-pod.mm b/test/SemaObjCXX/arc-non-pod.mm new file mode 100644 index 0000000..6a47b3d --- /dev/null +++ b/test/SemaObjCXX/arc-non-pod.mm @@ -0,0 +1,116 @@ +// RUN: %clang_cc1 -fobjc-nonfragile-abi -fsyntax-only -fobjc-arc -Warc-abi -verify -fblocks -triple x86_64-apple-darwin10.0.0 %s + +// Classes that have an Objective-C object pointer. +struct HasObjectMember0 { // expected-warning{{'HasObjectMember0' cannot be shared between ARC and non-ARC code; add a copy constructor, a copy assignment operator, and a destructor to make it ABI-compatible}} + id x; +}; + +struct HasObjectMember1 { // expected-warning{{'HasObjectMember1' cannot be shared between ARC and non-ARC code; add a copy constructor, a copy assignment operator, and a destructor to make it ABI-compatible}} + id x[3]; +}; + +struct HasObjectMember2 { // expected-warning{{'HasObjectMember2' cannot be shared between ARC and non-ARC code; add a copy constructor, a copy assignment operator, and a destructor to make it ABI-compatible}} + id x[3][2]; +}; + +// Don't complain if the type has non-external linkage +namespace { + struct HasObjectMember3 { + id x[3][2]; + }; +} + +// Don't complain if the Objective-C pointer type was explicitly given +// no ownership. +struct HasObjectMember3 { + __unsafe_unretained id x[3][2]; +}; + +struct HasBlockPointerMember0 { // expected-warning{{'HasBlockPointerMember0' cannot be shared between ARC and non-ARC code; add a copy constructor, a copy assignment operator, and a destructor to make it ABI-compatible}} + int (^bp)(int); +}; + +struct HasBlockPointerMember1 { // expected-warning{{'HasBlockPointerMember1' cannot be shared between ARC and non-ARC code; add a copy constructor, a copy assignment operator, and a destructor to make it ABI-compatible}} + int (^bp[2][3])(int); +}; + +struct NonPOD { + NonPOD(const NonPOD&); +}; + +struct HasObjectMemberAndNonPOD0 { // expected-warning{{'HasObjectMemberAndNonPOD0' cannot be shared between ARC and non-ARC code; add a non-trivial copy assignment operator to make it ABI-compatible}} \ + // expected-warning{{'HasObjectMemberAndNonPOD0' cannot be shared between ARC and non-ARC code; add a non-trivial destructor to make it ABI-compatible}} + id x; + NonPOD np; +}; + +struct HasObjectMemberAndNonPOD1 { // expected-warning{{'HasObjectMemberAndNonPOD1' cannot be shared between ARC and non-ARC code; add a non-trivial copy assignment operator to make it ABI-compatible}} \ + // expected-warning{{'HasObjectMemberAndNonPOD1' cannot be shared between ARC and non-ARC code; add a non-trivial destructor to make it ABI-compatible}} + NonPOD np; + id x[3]; +}; + +struct HasObjectMemberAndNonPOD2 { // expected-warning{{'HasObjectMemberAndNonPOD2' cannot be shared between ARC and non-ARC code; add a non-trivial copy assignment operator to make it ABI-compatible}} \ + // expected-warning{{'HasObjectMemberAndNonPOD2' cannot be shared between ARC and non-ARC code; add a non-trivial destructor to make it ABI-compatible}} + NonPOD np; + id x[3][2]; +}; + +struct HasObjectMemberAndNonPOD3 { + HasObjectMemberAndNonPOD3 &operator=(const HasObjectMemberAndNonPOD3&); + ~HasObjectMemberAndNonPOD3(); + NonPOD np; + id x[3][2]; +}; + +struct HasBlockPointerMemberAndNonPOD0 { // expected-warning{{'HasBlockPointerMemberAndNonPOD0' cannot be shared between ARC and non-ARC code; add a non-trivial copy assignment operator to make it ABI-compatible}} \ +// expected-warning{{'HasBlockPointerMemberAndNonPOD0' cannot be shared between ARC and non-ARC code; add a non-trivial destructor to make it ABI-compatible}} + NonPOD np; + int (^bp)(int); +}; + +struct HasBlockPointerMemberAndNonPOD1 { // expected-warning{{'HasBlockPointerMemberAndNonPOD1' cannot be shared between ARC and non-ARC code; add a non-trivial copy assignment operator to make it ABI-compatible}} \ +// expected-warning{{'HasBlockPointerMemberAndNonPOD1' cannot be shared between ARC and non-ARC code; add a non-trivial destructor to make it ABI-compatible}} + NonPOD np; + int (^bp[2][3])(int); +}; + +int check_non_pod_objc_pointer0[__is_pod(id)? 1 : -1]; +int check_non_pod_objc_pointer1[__is_pod(__strong id)? -1 : 1]; +int check_non_pod_objc_pointer2[__is_pod(__unsafe_unretained id)? 1 : -1]; +int check_non_pod_objc_pointer3[__is_pod(id[2][3])? 1 : -1]; +int check_non_pod_objc_pointer4[__is_pod(__unsafe_unretained id[2][3])? 1 : -1]; +int check_non_pod_block0[__is_pod(int (^)(int))? 1 : -1]; +int check_non_pod_block1[__is_pod(int (^ __unsafe_unretained)(int))? 1 : -1]; +int check_non_pod_block2[__is_pod(int (^ __strong)(int))? -1 : 1]; + +struct FlexibleArrayMember0 { + int length; + id array[]; // expected-error{{flexible array member 'array' of non-POD element type 'id __strong[]'}} +}; + +struct FlexibleArrayMember1 { + int length; + __unsafe_unretained id array[]; +}; + +// It's okay to pass a retainable type through an ellipsis. +void variadic(...); +void test_variadic() { + variadic(1, 17, @"Foo"); +} + +// It's okay to create a VLA of retainable types. +void vla(int n) { + id vla[n]; +} + +@interface Crufty { + union { + struct { + id object; // expected-note{{has __strong ownership}} + } an_object; // expected-error{{union member 'an_object' has a non-trivial copy constructor}} + void *ptr; + } storage; +} +@end diff --git a/test/SemaObjCXX/arc-object-init-destroy.mm b/test/SemaObjCXX/arc-object-init-destroy.mm new file mode 100644 index 0000000..196f493 --- /dev/null +++ b/test/SemaObjCXX/arc-object-init-destroy.mm @@ -0,0 +1,52 @@ +// RUN: %clang_cc1 -fobjc-nonfragile-abi -fobjc-runtime-has-weak -fsyntax-only -fobjc-arc -verify -Warc-abi -fblocks -triple x86_64-apple-darwin10.0.0 %s + +typedef __strong id strong_id; +typedef __weak id weak_id; +void test_pseudo_destructors(__strong id *sptr, __weak id *wptr) { + sptr->~id(); // okay + wptr->~id(); // okay + sptr->~strong_id(); // okay + wptr->~weak_id(); + sptr->~weak_id(); // expected-error{{pseudo-destructor destroys object of type '__strong id' with inconsistently-qualified type 'weak_id' (aka '__weak id')}} + wptr->strong_id::~strong_id(); // expected-error{{pseudo-destructor destroys object of type '__weak id' with inconsistently-qualified type 'strong_id' (aka '__strong id')}} + + sptr->id::~id(); // okay + wptr->id::~id(); // okay +} + +void test_delete(__strong id *sptr, __weak id *wptr) { + delete sptr; + delete wptr; + delete [] sptr; // expected-warning{{destroying an array of '__strong id'; this array must not have been allocated from non-ARC code}} + delete [] wptr; // expected-warning{{destroying an array of '__weak id'; this array must not have been allocated from non-ARC code}} +} + +void test_new(int n) { + (void)new strong_id; + (void)new weak_id; + (void)new strong_id [n]; // expected-warning{{allocating an array of 'strong_id' (aka '__strong id'); this array must not be deleted in non-ARC code}} + (void)new weak_id [n]; // expected-warning{{allocating an array of 'weak_id' (aka '__weak id'); this array must not be deleted in non-ARC code}} + + (void)new __strong id; + (void)new __weak id; + (void)new __strong id [n]; // expected-warning{{allocating an array of '__strong id'; this array must not be deleted in non-ARC code}} + + // Infer '__strong'. + __strong id *idptr = new id; + __strong id *idptr2 = new id [n]; // expected-warning{{allocating an array of '__strong id'; this array must not be deleted in non-ARC code}} + + // ... but not for arrays. + typedef id id_array[2][3]; + (void)new id_array; // expected-error{{'new' cannot allocate an array of 'id' with no explicit ownership}} + + typedef __strong id strong_id_array[2][3]; + typedef __strong id strong_id_3[3]; + strong_id_3 *idptr3 = new strong_id_array; // expected-warning{{allocating an array of '__strong id'; this array must not be deleted in non-ARC code}} +} + +void test_jump_scope() { + goto done; // expected-error{{goto into protected scope}} + __strong id x; // expected-note{{jump bypasses initialization of retaining variable}} + done: + return; +} diff --git a/test/SemaObjCXX/arc-overloading.mm b/test/SemaObjCXX/arc-overloading.mm new file mode 100644 index 0000000..06b332c --- /dev/null +++ b/test/SemaObjCXX/arc-overloading.mm @@ -0,0 +1,175 @@ +// RUN: %clang_cc1 -fobjc-nonfragile-abi -fobjc-runtime-has-weak -fsyntax-only -fobjc-arc -verify -fblocks %s + +// Simple ownership conversions + diagnostics. +int &f0(id __strong const *); // expected-note{{candidate function not viable: 1st argument ('__weak id *') has __weak ownership, but parameter has __strong ownership}} + +void test_f0() { + id __strong *sip; + id __strong const *csip; + id __weak *wip; + id __autoreleasing *aip; + id __unsafe_unretained *uip; + + int &ir1 = f0(sip); + int &ir2 = f0(csip); + int &ir3 = f0(aip); + int &ir4 = f0(uip); + f0(wip); // expected-error{{no matching function for call to 'f0'}} +} + +// Simple overloading +int &f1(id __strong const *); +float &f1(id __weak const *); + +void test_f1() { + id __strong *sip; + id __strong const *csip; + id __weak *wip; + id __autoreleasing *aip; + id __unsafe_unretained *uip; + + int &ir1 = f1(sip); + int &ir2 = f1(csip); + float &fr1 = f1(wip); + int &ir3 = f1(aip); + int &ir4 = f1(uip); +} + +// Simple overloading +int &f2(id __strong const *); // expected-note{{candidate function}} +float &f2(id __autoreleasing const *); // expected-note{{candidate function}} + +void test_f2() { + id __strong *sip; + id __strong const *csip; + id __weak *wip; + id __autoreleasing *aip; + id __unsafe_unretained *uip; + + // Prefer non-ownership conversions to ownership conversions. + int &ir1 = f2(sip); + int &ir2 = f2(csip); + float &fr1 = f2(aip); + + f2(uip); // expected-error{{call to 'f2' is ambiguous}} +} + +// Writeback conversion +int &f3(id __autoreleasing *); // expected-note{{candidate function not viable: 1st argument ('__unsafe_unretained id *') has __unsafe_unretained ownership, but parameter has __autoreleasing ownership}} + +void test_f3() { + id __strong sip; + id __weak wip; + id __autoreleasing aip; + id __unsafe_unretained uip; + + int &ir1 = f3(&sip); + int &ir2 = f3(&wip); + int &ir3 = f3(&aip); + f3(&uip); // expected-error{{no matching function for call to 'f3'}} +} + +// Writeback conversion vs. no conversion +int &f4(id __autoreleasing *); +float &f4(id __strong *); + +void test_f4() { + id __strong sip; + id __weak wip; + id __autoreleasing aip; + extern __weak id weak_global_ptr; + + float &fr1 = f4(&sip); + int &ir1 = f4(&wip); + int &ir2 = f4(&aip); + int &ir3 = f4(&weak_global_ptr); // expected-error{{passing address of non-local object to __autoreleasing parameter for write-back}} +} + +// Writeback conversion vs. other conversion. +int &f5(id __autoreleasing *); +float &f5(id const __unsafe_unretained *); + +void test_f5() { + id __strong sip; + id __weak wip; + id __autoreleasing aip; + + int &ir1 = f5(&wip); + float &fr1 = f5(&sip); + int &ir2 = f5(&aip); +} + +@interface A +@end + +int &f6(id __autoreleasing *); +float &f6(id const __unsafe_unretained *); + +void test_f6() { + A* __strong sip; + A* __weak wip; + A* __autoreleasing aip; + + int &ir1 = f6(&wip); + float &fr1 = f6(&sip); + int &ir2 = f6(&aip); +} + +// Reference binding +void f7(__strong id&); // expected-note{{candidate function not viable: 1st argument ('__weak id') has __weak ownership, but parameter has __strong ownership}} \ + // expected-note{{candidate function not viable: 1st argument ('__autoreleasing id') has __autoreleasing ownership, but parameter has __strong ownership}} \ + // expected-note{{candidate function not viable: 1st argument ('__unsafe_unretained id') has __unsafe_unretained ownership, but parameter has __strong ownership}} + +void test_f7() { + __strong id strong_id; + __weak id weak_id; + __autoreleasing id autoreleasing_id; + __unsafe_unretained id unsafe_id; + f7(strong_id); + f7(weak_id); // expected-error{{no matching function for call to 'f7'}} + f7(autoreleasing_id); // expected-error{{no matching function for call to 'f7'}} + f7(unsafe_id); // expected-error{{no matching function for call to 'f7'}} +} + +void f8(const __strong id&); + +void test_f8() { + __strong id strong_id; + __weak id weak_id; + __autoreleasing id autoreleasing_id; + __unsafe_unretained id unsafe_id; + + f8(strong_id); + f8(weak_id); + f8(autoreleasing_id); + f8(unsafe_id); +} + +int &f9(__strong id&); +float &f9(const __autoreleasing id&); + +void test_f9() { + __strong id strong_id; + __weak id weak_id; + __autoreleasing id autoreleasing_id; + __unsafe_unretained id unsafe_id; + + int &ir1 = f9(strong_id); + float &fr1 = f9(autoreleasing_id); + float &fr2 = f9(unsafe_id); + float &fr2a = f9(weak_id); + + __strong A *strong_a; + __weak A *weak_a; + __autoreleasing A *autoreleasing_a; + __unsafe_unretained A *unsafe_unretained_a; + float &fr3 = f9(strong_a); + float &fr4 = f9(autoreleasing_a); + float &fr5 = f9(unsafe_unretained_a); + float &fr6 = f9(weak_a); + + const __autoreleasing id& ar1 = strong_a; + const __autoreleasing id& ar2 = autoreleasing_a; + const __autoreleasing id& ar3 = unsafe_unretained_a; + const __autoreleasing id& ar4 = weak_a; +} diff --git a/test/SemaObjCXX/arc-system-header.mm b/test/SemaObjCXX/arc-system-header.mm new file mode 100644 index 0000000..cb2b858 --- /dev/null +++ b/test/SemaObjCXX/arc-system-header.mm @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -fobjc-arc -fobjc-nonfragile-abi -isystem %S/Inputs %s -verify + +#include <arc-system-header.h> + +void f(A* a) { + a->data.void_ptr = 0; + a->data.a_b.b = 0; // expected-error{{'a_b' is unavailable: this system field has retaining ownership}} +} +// Silly location below +// expected-note{{declaration has been explicitly marked unavailable here}} diff --git a/test/SemaObjCXX/arc-templates.mm b/test/SemaObjCXX/arc-templates.mm new file mode 100644 index 0000000..fa4e0a7 --- /dev/null +++ b/test/SemaObjCXX/arc-templates.mm @@ -0,0 +1,254 @@ +// RUN: %clang_cc1 -fobjc-nonfragile-abi -fobjc-runtime-has-weak -fsyntax-only -fobjc-arc -verify -fblocks %s + +@interface A +@end + +template<typename T, typename U> +struct is_same { + static const bool value = false; +}; + +template<typename T> +struct is_same<T, T> { + static const bool value = true; +}; + +// Instantiation for reference/pointer types that will get lifetime +// adjustments. +template<typename T> +struct X0 { + typedef T* pointer; // okay: ends up being strong. + typedef T& reference; // okay: ends up being strong +}; + +void test_X0() { + X0<id> x0id; + X0<A*> x0a; + X0<__strong A*> x0sa; + + id __strong *ptr; + id __strong val; + X0<__strong id>::pointer &ptr_ref = ptr; + X0<__strong id>::reference ref = val; +} + +int check_infer_strong[is_same<id, __strong id>::value? 1 : -1]; + +// Check template argument deduction (e.g., for specialization) using +// lifetime qualifiers. +template<typename T> +struct is_pointer_strong { + static const bool value = false; +}; + +template<typename T> +struct is_pointer_strong<__strong T*> { + static const bool value = true; +}; + +int check_ptr_strong1[is_pointer_strong<__strong id*>::value? 1 : -1]; +int check_ptr_strong2[is_pointer_strong<__weak id*>::value? -1 : 1]; +int check_ptr_strong3[is_pointer_strong<__autoreleasing id*>::value? -1 : 1]; +int check_ptr_strong4[is_pointer_strong<__unsafe_unretained id*>::value? -1 : 1]; +int check_ptr_strong5[is_pointer_strong<id>::value? -1 : 1]; + +// Check substitution into lifetime-qualified dependent types. +template<typename T> +struct make_strong_pointer { + typedef __strong T *type; +}; + +template<typename T> +struct make_strong_pointer<__weak T> { + typedef __strong T *type; +}; + +template<typename T> +struct make_strong_pointer<__autoreleasing T> { + typedef __strong T *type; +}; + +template<typename T> +struct make_strong_pointer<__unsafe_unretained T> { + typedef __strong T *type; +}; + +// Adding qualifiers +int check_make_strong1[is_same<make_strong_pointer<id>::type, __strong id *>::value ? 1 : -1]; +int check_make_strong2[is_same<make_strong_pointer<A*>::type, A* __strong *>::value ? 1 : -1]; + +// Adding redundant qualifiers +int check_make_strong3[is_same<make_strong_pointer<__strong id>::type, __strong id *>::value ? 1 : -1]; +int check_make_strong4[is_same<make_strong_pointer<__strong A*>::type, A* __strong *>::value ? 1 : -1]; + +// Adding nonsensical qualifiers. +int check_make_strong5[is_same<make_strong_pointer<int>::type, int *>::value ? 1 : -1]; +int check_make_strong6[is_same<make_strong_pointer<__weak id>::type, __strong id *>::value ? 1 : -1]; + +template<typename T> +struct make_weak { + typedef __weak T type; +}; + +int check_make_weak0[is_same<make_weak<id>::type, __weak id>::value? 1 : -1]; +int check_make_weak1[is_same<make_weak<__strong id>::type, __weak id>::value? 1 : -1]; +int check_make_weak2[is_same<make_weak<__autoreleasing id>::type, __weak id>::value? 1 : -1]; + +template<typename T> +struct make_weak_fail { + typedef T T_type; + typedef __weak T_type type; // expected-error{{the type 'T_type' (aka '__weak id') already has retainment attributes set on it}} \ + // expected-error{{the type 'T_type' (aka '__strong id') already has retainment attributes set on it}} +}; + +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}} + +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}} + +// Check template argument deduction from function templates. +template<typename T> struct identity { }; + +template<typename T> identity<T> accept_strong_ptr(__strong T*); +template<typename T> identity<T> accept_strong_ref(__strong T&); + +template<typename T> identity<T> accept_any_ptr(T*); +template<typename T> identity<T> accept_any_ref(T&); + +void test_func_deduction_id() { + __strong id *sip; + __weak id *wip; + __autoreleasing id *aip; + __unsafe_unretained id *uip; + + identity<id> res1 = accept_strong_ptr(sip); + identity<__strong id> res2 = accept_any_ptr(sip); + + __strong id si; + __weak id wi; + __autoreleasing id ai; + __unsafe_unretained id ui; + identity<id> res3 = accept_strong_ref(si); + identity<__strong id> res4 = accept_any_ref(si); + identity<__weak id> res5 = accept_any_ref(wi); + identity<__autoreleasing id> res6 = accept_any_ref(ai); + identity<__unsafe_unretained id> res7 = accept_any_ref(ui); +} + +void test_func_deduction_A() { + __strong A * *sip; + __weak A * *wip; + __autoreleasing A * *aip; + __unsafe_unretained A * *uip; + + identity<A *> res1 = accept_strong_ptr(sip); + identity<__strong A *> res2 = accept_any_ptr(sip); + + __strong A * si; + __weak A * wi; + __autoreleasing A * ai; + __unsafe_unretained A * ui; + identity<A *> res3 = accept_strong_ref(si); + identity<__strong A *> res4 = accept_any_ref(si); + identity<__weak A *> res5 = accept_any_ref(wi); + identity<__autoreleasing A *> res6 = accept_any_ref(ai); + identity<__unsafe_unretained A *> res7 = accept_any_ref(ui); +} + +// Test partial ordering (qualified vs. non-qualified). +template<typename T> +struct classify_pointer_pointer { + static const unsigned value = 0; +}; + +template<typename T> +struct classify_pointer_pointer<T*> { + static const unsigned value = 1; +}; + +template<typename T> +struct classify_pointer_pointer<__strong T*> { + static const unsigned value = 2; +}; + +template<typename T> +struct classify_pointer_pointer<__weak T*> { + static const unsigned value = 3; +}; + +template<typename T> +struct classify_pointer_pointer<T&> { + static const unsigned value = 4; +}; + +template<typename T> +struct classify_pointer_pointer<__strong T&> { + static const unsigned value = 5; +}; + +template<typename T> +struct classify_pointer_pointer<__weak T&> { + static const unsigned value = 6; +}; + +int classify_ptr1[classify_pointer_pointer<int>::value == 0? 1 : -1]; +int classify_ptr2[classify_pointer_pointer<int *>::value == 1? 1 : -1]; +int classify_ptr3[classify_pointer_pointer<id __strong *>::value == 2? 1 : -1]; +int classify_ptr4[classify_pointer_pointer<id __weak *>::value == 3? 1 : -1]; +int classify_ptr5[classify_pointer_pointer<int&>::value == 4? 1 : -1]; +int classify_ptr6[classify_pointer_pointer<id __strong&>::value == 5? 1 : -1]; +int classify_ptr7[classify_pointer_pointer<id __weak&>::value == 6? 1 : -1]; +int classify_ptr8[classify_pointer_pointer<id __autoreleasing&>::value == 4? 1 : -1]; +int classify_ptr9[classify_pointer_pointer<id __unsafe_unretained&>::value == 4? 1 : -1]; +int classify_ptr10[classify_pointer_pointer<id __autoreleasing *>::value == 1? 1 : -1]; +int classify_ptr11[classify_pointer_pointer<id __unsafe_unretained *>::value == 1? 1 : -1]; +int classify_ptr12[classify_pointer_pointer<int *>::value == 1? 1 : -1]; +int classify_ptr13[classify_pointer_pointer<A * __strong *>::value == 2? 1 : -1]; +int classify_ptr14[classify_pointer_pointer<A * __weak *>::value == 3? 1 : -1]; +int classify_ptr15[classify_pointer_pointer<int&>::value == 4? 1 : -1]; +int classify_ptr16[classify_pointer_pointer<A * __strong&>::value == 5? 1 : -1]; +int classify_ptr17[classify_pointer_pointer<A * __weak&>::value == 6? 1 : -1]; +int classify_ptr18[classify_pointer_pointer<A * __autoreleasing&>::value == 4? 1 : -1]; +int classify_ptr19[classify_pointer_pointer<A * __unsafe_unretained&>::value == 4? 1 : -1]; +int classify_ptr20[classify_pointer_pointer<A * __autoreleasing *>::value == 1? 1 : -1]; +int classify_ptr21[classify_pointer_pointer<A * __unsafe_unretained *>::value == 1? 1 : -1]; + +template<typename T> int& qual_vs_unqual_ptr(__strong T*); +template<typename T> double& qual_vs_unqual_ptr(__weak T*); +template<typename T> float& qual_vs_unqual_ptr(T*); +template<typename T> int& qual_vs_unqual_ref(__strong T&); +template<typename T> double& qual_vs_unqual_ref(__weak T&); +template<typename T> float& qual_vs_unqual_ref(T&); + +void test_qual_vs_unqual_id() { + __strong id *sip; + __weak id *wip; + __autoreleasing id *aip; + __unsafe_unretained id *uip; + + int &ir1 = qual_vs_unqual_ptr(sip); + double &dr1 = qual_vs_unqual_ptr(wip); + float &fr1 = qual_vs_unqual_ptr(aip); + float &fr2 = qual_vs_unqual_ptr(uip); + + int &ir2 = qual_vs_unqual_ref(*sip); + double &dr2 = qual_vs_unqual_ref(*wip); + float &fr3 = qual_vs_unqual_ref(*aip); + float &fr4 = qual_vs_unqual_ref(*uip); +} + +void test_qual_vs_unqual_a() { + __strong A * *sap; + __weak A * *wap; + __autoreleasing A * *aap; + __unsafe_unretained A * *uap; + + int &ir1 = qual_vs_unqual_ptr(sap); + double &dr1 = qual_vs_unqual_ptr(wap); + float &fr1 = qual_vs_unqual_ptr(aap); + float &fr2 = qual_vs_unqual_ptr(uap); + + int &ir2 = qual_vs_unqual_ref(*sap); + double &dr2 = qual_vs_unqual_ref(*wap); + float &fr3 = qual_vs_unqual_ref(*aap); + float &fr4 = qual_vs_unqual_ref(*uap); +} diff --git a/test/SemaObjCXX/arc-type-conversion.mm b/test/SemaObjCXX/arc-type-conversion.mm new file mode 100644 index 0000000..f52f54a --- /dev/null +++ b/test/SemaObjCXX/arc-type-conversion.mm @@ -0,0 +1,221 @@ +// RUN: %clang_cc1 -fobjc-nonfragile-abi -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{{C-style cast from 'id' to '__autoreleasing id *' casts away qualifiers}} + (void)(id*)arg; // expected-error{{C-style cast from 'id' to '__strong id *' casts away qualifiers}} + + (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 {{cast of Objective-C pointer type 'id' to C pointer type 'void *' requires a bridged cast}} \ + // expected-error {{no matching function for call to 'cvt'}} \ + // expected-note{{use __bridge to convert directly (no change in ownership)}} \ + // expected-note{{use __bridge_retained to make an ARC object available as a +1 'void *'}} + 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}} diff --git a/test/SemaObjCXX/arc-type-traits.mm b/test/SemaObjCXX/arc-type-traits.mm new file mode 100644 index 0000000..f50904b --- /dev/null +++ b/test/SemaObjCXX/arc-type-traits.mm @@ -0,0 +1,90 @@ +// RUN: %clang_cc1 -fsyntax-only -fobjc-arc -fobjc-nonfragile-abi -fobjc-runtime-has-weak -verify %s + +// Check the results of the various type-trait query functions on +// lifetime-qualified types in ARC. + +#define JOIN3(X,Y) X ## Y +#define JOIN2(X,Y) JOIN3(X,Y) +#define JOIN(X,Y) JOIN2(X,Y) + +#define TRAIT_IS_TRUE(Trait, Type) char JOIN2(Trait,__LINE__)[Trait(Type)? 1 : -1] +#define TRAIT_IS_FALSE(Trait, Type) char JOIN2(Trait,__LINE__)[Trait(Type)? -1 : 1] + +// __has_nothrow_assign +TRAIT_IS_TRUE(__has_nothrow_assign, __strong id); +TRAIT_IS_TRUE(__has_nothrow_assign, __weak id); +TRAIT_IS_TRUE(__has_nothrow_assign, __autoreleasing id); +TRAIT_IS_TRUE(__has_nothrow_assign, __unsafe_unretained id); + +// __has_nothrow_copy +TRAIT_IS_TRUE(__has_nothrow_copy, __strong id); +TRAIT_IS_TRUE(__has_nothrow_copy, __weak id); +TRAIT_IS_TRUE(__has_nothrow_copy, __autoreleasing id); +TRAIT_IS_TRUE(__has_nothrow_copy, __unsafe_unretained id); + +// __has_nothrow_constructor +TRAIT_IS_TRUE(__has_nothrow_constructor, __strong id); +TRAIT_IS_TRUE(__has_nothrow_constructor, __weak id); +TRAIT_IS_TRUE(__has_nothrow_constructor, __autoreleasing id); +TRAIT_IS_TRUE(__has_nothrow_constructor, __unsafe_unretained id); + +// __has_trivial_assign +TRAIT_IS_FALSE(__has_trivial_assign, __strong id); +TRAIT_IS_FALSE(__has_trivial_assign, __weak id); +TRAIT_IS_FALSE(__has_trivial_assign, __autoreleasing id); +TRAIT_IS_TRUE(__has_trivial_assign, __unsafe_unretained id); + +// __has_trivial_copy +TRAIT_IS_FALSE(__has_trivial_copy, __strong id); +TRAIT_IS_FALSE(__has_trivial_copy, __weak id); +TRAIT_IS_FALSE(__has_trivial_copy, __autoreleasing id); +TRAIT_IS_TRUE(__has_trivial_copy, __unsafe_unretained id); + +// __has_trivial_constructor +TRAIT_IS_FALSE(__has_trivial_constructor, __strong id); +TRAIT_IS_FALSE(__has_trivial_constructor, __weak id); +TRAIT_IS_FALSE(__has_trivial_constructor, __autoreleasing id); +TRAIT_IS_TRUE(__has_trivial_constructor, __unsafe_unretained id); + +// __has_trivial_destructor +TRAIT_IS_FALSE(__has_trivial_destructor, __strong id); +TRAIT_IS_FALSE(__has_trivial_destructor, __weak id); +TRAIT_IS_TRUE(__has_trivial_destructor, __autoreleasing id); +TRAIT_IS_TRUE(__has_trivial_destructor, __unsafe_unretained id); + +// __is_literal +TRAIT_IS_FALSE(__is_literal, __strong id); +TRAIT_IS_FALSE(__is_literal, __weak id); +TRAIT_IS_FALSE(__is_literal, __autoreleasing id); +TRAIT_IS_FALSE(__is_literal, __unsafe_unretained id); + +// __is_literal_type +TRAIT_IS_FALSE(__is_literal_type, __strong id); +TRAIT_IS_FALSE(__is_literal_type, __weak id); +TRAIT_IS_FALSE(__is_literal_type, __autoreleasing id); +TRAIT_IS_FALSE(__is_literal_type, __unsafe_unretained id); + +// __is_pod +TRAIT_IS_FALSE(__is_pod, __strong id); +TRAIT_IS_FALSE(__is_pod, __weak id); +TRAIT_IS_FALSE(__is_pod, __autoreleasing id); +TRAIT_IS_TRUE(__is_pod, __unsafe_unretained id); + +// __is_trivial +TRAIT_IS_FALSE(__is_trivial, __strong id); +TRAIT_IS_FALSE(__is_trivial, __weak id); +TRAIT_IS_FALSE(__is_trivial, __autoreleasing id); +TRAIT_IS_TRUE(__is_trivial, __unsafe_unretained id); + +// __is_scalar +TRAIT_IS_FALSE(__is_scalar, __strong id); +TRAIT_IS_FALSE(__is_scalar, __weak id); +TRAIT_IS_FALSE(__is_scalar, __autoreleasing id); +TRAIT_IS_TRUE(__is_scalar, __unsafe_unretained id); + +// __is_standard_layout +TRAIT_IS_TRUE(__is_standard_layout, __strong id); +TRAIT_IS_TRUE(__is_standard_layout, __weak id); +TRAIT_IS_TRUE(__is_standard_layout, __autoreleasing id); +TRAIT_IS_TRUE(__is_standard_layout, __unsafe_unretained id); + diff --git a/test/SemaObjCXX/arc-unavailable-for-weakref.mm b/test/SemaObjCXX/arc-unavailable-for-weakref.mm new file mode 100644 index 0000000..a7b3570 --- /dev/null +++ b/test/SemaObjCXX/arc-unavailable-for-weakref.mm @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin11 -fobjc-nonfragile-abi -fobjc-runtime-has-weak -fsyntax-only -fobjc-arc -verify %s +// rdar://9693477 + +__attribute__((objc_arc_weak_reference_unavailable)) +@interface NSOptOut1072 // expected-note {{class is declared here}} +@end + +@interface sub : NSOptOut1072 @end // expected-note 2 {{class is declared here}} + +int main() { + __weak sub *w2; // expected-error {{class is incompatible with __weak references}} + + __weak NSOptOut1072 *ns1; // expected-error {{class is incompatible with __weak references}} + + id obj; + + ns1 = (__weak sub *)obj; // expected-error {{assignment of a weak-unavailable object to a __weak object}} \ + // expected-error {{class is incompatible with __weak references}} +} + +// rdar://9732636 +__attribute__((objc_arc_weak_reference_unavailable)) +@interface NOWEAK ++ (id) new; +@end + +NOWEAK * Test1() { + NOWEAK * strong1 = [NOWEAK new]; + __weak id weak1; + weak1 = strong1; // expected-error {{assignment of a weak-unavailable object to a __weak object}} + + __weak id weak2 = strong1; // expected-error {{assignment of a weak-unavailable object to a __weak object}} + return (__weak id)strong1; // expected-error {{cast of weak-unavailable object of type 'NOWEAK *' to a __weak object of type '__weak id'}} +} + +@protocol P @end +@protocol P1 @end + +NOWEAK<P, P1> * Test2() { + NOWEAK<P, P1> * strong1 = 0; + __weak id<P> weak1; + weak1 = strong1; // expected-error {{assignment of a weak-unavailable object to a __weak object}} + + __weak id<P> weak2 = strong1; // expected-error {{assignment of a weak-unavailable object to a __weak object}} + return (__weak id<P, P1>)strong1; // expected-error {{cast of weak-unavailable object of type 'NOWEAK<P,P1> *' to a __weak object of type '__weak id<P,P1>'}} +} + diff --git a/test/SemaObjCXX/exceptions-fragile.mm b/test/SemaObjCXX/exceptions-fragile.mm index d1e7077..71e259a 100644 --- a/test/SemaObjCXX/exceptions-fragile.mm +++ b/test/SemaObjCXX/exceptions-fragile.mm @@ -6,7 +6,7 @@ void opaque(); namespace test0 { void test() { try { - } catch (NSException *e) { // expected-error {{can't catch Objective C exceptions in C++ in the non-unified exception model}} + } catch (NSException *e) { // expected-warning {{can not catch an exception thrown with @throw in C++ in the non-unified exception model}} } } } diff --git a/test/SemaObjCXX/gc-attributes.mm b/test/SemaObjCXX/gc-attributes.mm index 70a93b2..4549683 100644 --- a/test/SemaObjCXX/gc-attributes.mm +++ b/test/SemaObjCXX/gc-attributes.mm @@ -3,7 +3,7 @@ @interface A @end -void f0(__strong A**); // expected-note{{candidate function not viable: 1st argument ('A *__weak *') has __weak lifetime, but parameter has __strong lifetime}} +void f0(__strong A**); // expected-note{{candidate function not viable: 1st argument ('A *__weak *') has __weak ownership, but parameter has __strong ownership}} void test_f0() { A *a; @@ -12,7 +12,7 @@ void test_f0() { f0(&a2); // expected-error{{no matching function}} } -void f1(__weak A**); // expected-note{{candidate function not viable: 1st argument ('A *__strong *') has __strong lifetime, but parameter has __weak lifetime}} +void f1(__weak A**); // expected-note{{candidate function not viable: 1st argument ('A *__strong *') has __strong ownership, but parameter has __weak ownership}} void test_f1() { A *a; diff --git a/test/SemaObjCXX/null_objc_pointer.mm b/test/SemaObjCXX/null_objc_pointer.mm new file mode 100644 index 0000000..0da9e50 --- /dev/null +++ b/test/SemaObjCXX/null_objc_pointer.mm @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wnull-arithmetic %s +#define NULL __null + +@interface X +@end + +void f() { + bool b; + X *d; + b = d < NULL || NULL < d || d > NULL || NULL > d; + b = d <= NULL || NULL <= d || d >= NULL || NULL >= d; + b = d == NULL || NULL == d || d != NULL || NULL != d; +} diff --git a/test/SemaObjCXX/nullptr.mm b/test/SemaObjCXX/nullptr.mm index 4cd5669..4a9d1a0 100644 --- a/test/SemaObjCXX/nullptr.mm +++ b/test/SemaObjCXX/nullptr.mm @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++0x -fblocks -fsyntax-only -verify %s @interface A @end @@ -11,3 +11,6 @@ void comparisons(A *a) { void assignment(A *a) { a = nullptr; } + +int PR10145a = (void(^)())0 == nullptr; +int PR10145b = nullptr == (void(^)())0; diff --git a/test/SemaObjCXX/property-type-mismatch.mm b/test/SemaObjCXX/property-type-mismatch.mm new file mode 100644 index 0000000..059793c --- /dev/null +++ b/test/SemaObjCXX/property-type-mismatch.mm @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// rdar://9740328 + +@protocol P1; + +@interface NSObject +@end + +@interface A : NSObject +@property (assign) NSObject<P1> *prop; +@end + +@protocol P2 <P1> +@end + +@interface B : A +@property (assign) NSObject<P2> *prop; +@end + diff --git a/test/SemaObjCXX/related-result-type-inference.mm b/test/SemaObjCXX/related-result-type-inference.mm index c3cab05..675e6ac 100644 --- a/test/SemaObjCXX/related-result-type-inference.mm +++ b/test/SemaObjCXX/related-result-type-inference.mm @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fobjc-infer-related-result-type -verify %s +// RUN: %clang_cc1 -verify %s @interface Unrelated @end |