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