1 // RUN: %clang_cc1 -fblocks -verify %s 2 3 /** 4 * Test 'noderef' attribute with c++ constructs. 5 */ 6 7 #define NODEREF __attribute__((noderef)) 8 9 void Normal() { 10 int NODEREF i; // expected-warning{{'noderef' can only be used on an array or pointer type}} 11 int NODEREF *i_ptr; // expected-note 2 {{i_ptr declared here}} 12 int NODEREF **i_ptr2; // ok 13 int *NODEREF i_ptr3; // expected-warning{{'noderef' can only be used on an array or pointer type}} 14 int *NODEREF *i_ptr4; // ok 15 16 auto NODEREF *auto_i_ptr = i_ptr; 17 auto NODEREF auto_i = i; // expected-warning{{'noderef' can only be used on an array or pointer type}} 18 19 struct { 20 int x; 21 int y; 22 } NODEREF *s; 23 24 int __attribute__((noderef(10))) * no_args; // expected-error{{'noderef' attribute takes no arguments}} 25 26 int i2 = *i_ptr; // expected-warning{{dereferencing i_ptr; was declared with a 'noderef' type}} 27 int &i3 = *i_ptr; // expected-warning{{dereferencing i_ptr; was declared with a 'noderef' type}} 28 int *i_ptr5 = i_ptr; // expected-warning{{casting to dereferenceable pointer removes 'noderef' attribute}} 29 int *i_ptr6(i_ptr); // expected-warning{{casting to dereferenceable pointer removes 'noderef' attribute}} 30 } 31 32 const int NODEREF *const_i_ptr; 33 static int NODEREF *static_i_ptr; 34 35 void ParenTypes() { 36 int NODEREF(*i_ptr); // ok (same as `int NODEREF *`) 37 int NODEREF *(*i_ptr2); // ok (same as `int NODEREF **`) 38 } 39 40 // Function declarations 41 int NODEREF func(); // expected-warning{{'noderef' can only be used on an array or pointer type}} 42 int NODEREF *func2(); // ok (returning pointer) 43 44 typedef int NODEREF (*func3)(int); // expected-warning{{'noderef' can only be used on an array or pointer type}} 45 typedef int NODEREF *(*func4)(int); 46 47 void Arrays() { 48 int NODEREF i_arr[10]; // ok 49 int NODEREF i_arr2[10][10]; // ok 50 int NODEREF *i_arr3[10]; // ok 51 int NODEREF i_arr4[] = {1, 2}; 52 } 53 54 void ParenArrays() { 55 int NODEREF(i_ptr[10]); 56 int NODEREF(i_ptr2[10])[10]; 57 } 58 59 typedef int NODEREF *(*func5[10])(int); 60 61 // Arguments 62 void func6(int NODEREF x); // expected-warning{{'noderef' can only be used on an array or pointer type}} 63 void func7(int NODEREF *x); 64 void func8() NODEREF; 65 66 void References() { 67 int x = 2; 68 int NODEREF &y = x; // expected-warning{{'noderef' can only be used on an array or pointer type}} 69 int *xp = &x; 70 int NODEREF *&a = xp; // ok (reference to a NODEREF *) 71 int *NODEREF &b = xp; // expected-warning{{'noderef' can only be used on an array or pointer type}} 72 } 73 74 void BlockPointers() { 75 typedef int NODEREF (^IntBlock)(); // expected-warning{{'noderef' can only be used on an array or pointer type}} 76 } 77 78 class A { 79 public: 80 int member; 81 int NODEREF *member2; 82 int NODEREF member3; // expected-warning{{'noderef' can only be used on an array or pointer type}} 83 int *member4; 84 85 int func() { return member; } 86 virtual int func_virt() { return member; } 87 88 A(NODEREF int *x) : member4(x) {} // expected-warning{{casting to dereferenceable pointer removes 'noderef' attribute}} 89 }; 90 91 class Child : public A {}; 92 93 void MemberPointer() { 94 int NODEREF A::*var = &A::member; // expected-warning{{'noderef' can only be used on an array or pointer type}} 95 } 96 97 int MethodCall(NODEREF A *a) { // expected-note{{a declared here}} 98 return a->func(); // expected-warning{{dereferencing a; was declared with a 'noderef' type}} 99 } 100 101 int ChildCall(NODEREF Child *child) { // expected-note{{child declared here}} 102 return child->func(); // expected-warning{{dereferencing child; was declared with a 'noderef' type}} 103 } 104 105 template <class Ty> 106 class B { 107 Ty NODEREF *member; 108 Ty NODEREF member2; // expected-warning{{'noderef' can only be used on an array or pointer type}} 109 }; 110 111 void test_lambdas() { 112 auto l = [](int NODEREF *x){ // expected-note{{x declared here}} 113 return *x; // expected-warning{{dereferencing x; was declared with a 'noderef' type}} 114 }; 115 } 116 117 int NODEREF *glob_ptr; // expected-note{{glob_ptr declared here}} 118 int glob_int = *glob_ptr; // expected-warning{{dereferencing glob_ptr; was declared with a 'noderef' type}} 119 120 void cast_from_void_ptr(NODEREF void *x) { 121 int *a = static_cast<int *>(x); // expected-warning{{casting to dereferenceable pointer removes 'noderef' attribute}} 122 123 // Allow regular C-style casts and C-style through reinterpret_casts to be holes 124 int *b = reinterpret_cast<int *>(x); 125 int *c = (int *)x; 126 } 127 128 void conversion_sequences() { 129 NODEREF int *x; 130 int *x2 = x; // expected-warning{{casting to dereferenceable pointer removes 'noderef' attribute}} 131 int *x3 = static_cast<int *>(x); // expected-warning{{casting to dereferenceable pointer removes 'noderef' attribute}} 132 int *x4 = reinterpret_cast<int *>(x); 133 134 // Functional cast - This is exactly equivalent to a C-style cast. 135 typedef int *INT_PTR; 136 int *x5 = INT_PTR(x); 137 138 NODEREF Child *child; 139 Child *child2 = dynamic_cast<Child *>(child); // expected-warning{{casting to dereferenceable pointer removes 'noderef' attribute}} 140 } 141 142 int *static_cast_from_same_ptr_type(NODEREF int *x) { 143 return static_cast<int *>(x); // expected-warning{{casting to dereferenceable pointer removes 'noderef' attribute}} 144 } 145 146 A *dynamic_cast_up(NODEREF Child *child) { 147 return dynamic_cast<A *>(child); // expected-warning{{casting to dereferenceable pointer removes 'noderef' attribute}} 148 } 149 150 Child *dynamic_cast_down(NODEREF A *a) { 151 return dynamic_cast<Child *>(a); // expected-warning{{casting to dereferenceable pointer removes 'noderef' attribute}} 152 } 153 154 A *dynamic_cast_side(NODEREF A *a) { 155 return dynamic_cast<A *>(a); // expected-warning{{casting to dereferenceable pointer removes 'noderef' attribute}} 156 } 157 158 void *dynamic_cast_to_void_ptr(NODEREF A *a) { 159 return dynamic_cast<void *>(a); // expected-warning{{casting to dereferenceable pointer removes 'noderef' attribute}} 160 } 161 162 int *const_cast_check(NODEREF const int *x) { 163 return const_cast<int *>(x); // expected-warning{{casting to dereferenceable pointer removes 'noderef' attribute}} 164 } 165 166 const int *const_cast_check(NODEREF int *x) { 167 return const_cast<const int *>(x); // expected-warning{{casting to dereferenceable pointer removes 'noderef' attribute}} 168 } 169