1 // RUN: %clang_cc1 -fsyntax-only -verify %s 2 // RUN: %clang_cc1 -fsyntax-only -fexperimental-late-parse-attributes %s -verify 3 4 #define __counted_by(f) __attribute__((counted_by(f))) 5 6 struct size_unknown; 7 struct size_known { 8 int field; 9 }; 10 11 typedef void(*fn_ptr_ty)(void); 12 13 //============================================================================== 14 // __counted_by on struct member pointer in decl attribute position 15 //============================================================================== 16 17 struct on_member_pointer_complete_ty { 18 int count; 19 struct size_known * buf __counted_by(count); 20 }; 21 22 struct on_member_pointer_incomplete_ty { 23 int count; 24 // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'struct size_unknown' is an incomplete type}} 25 struct size_unknown * buf __counted_by(count); 26 }; 27 28 struct on_member_pointer_const_incomplete_ty { 29 int count; 30 // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'const struct size_unknown' is an incomplete type}} 31 const struct size_unknown * buf __counted_by(count); 32 }; 33 34 struct on_member_pointer_void_ty { 35 int count; 36 // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'void' is an incomplete type}} 37 void* buf __counted_by(count); 38 }; 39 40 struct on_member_pointer_fn_ptr_ty { 41 int count; 42 // buffer of `count` function pointers is allowed 43 void (**fn_ptr)(void) __counted_by(count); 44 }; 45 46 struct on_member_pointer_fn_ptr_ty_ptr_ty { 47 int count; 48 // buffer of `count` function pointers is allowed 49 fn_ptr_ty* fn_ptr __counted_by(count); 50 }; 51 52 struct on_member_pointer_fn_ty { 53 int count; 54 // buffer of `count` functions is not allowed 55 // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'void (void)' is a function type}} 56 void (*fn_ptr)(void) __counted_by(count); 57 }; 58 59 struct on_member_pointer_fn_ptr_ty_ty { 60 int count; 61 // buffer of `count` functions is not allowed 62 // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'void (void)' is a function type}} 63 fn_ptr_ty fn_ptr __counted_by(count); 64 }; 65 66 struct has_unannotated_vla { 67 int count; 68 int buffer[]; 69 }; 70 71 struct on_member_pointer_struct_with_vla { 72 int count; 73 // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'struct has_unannotated_vla' is a struct type with a flexible array member}} 74 struct has_unannotated_vla* objects __counted_by(count); 75 }; 76 77 struct has_annotated_vla { 78 int count; 79 int buffer[] __counted_by(count); 80 }; 81 82 // Currently prevented because computing the size of `objects` at runtime would 83 // require an O(N) walk of `objects` to take into account the length of the VLA 84 // in each struct instance. 85 struct on_member_pointer_struct_with_annotated_vla { 86 int count; 87 // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'struct has_annotated_vla' is a struct type with a flexible array member}} 88 struct has_annotated_vla* objects __counted_by(count); 89 }; 90 91 struct on_pointer_anon_buf { 92 int count; 93 struct { 94 struct size_known *buf __counted_by(count); 95 }; 96 }; 97 98 struct on_pointer_anon_count { 99 struct { 100 int count; 101 }; 102 struct size_known *buf __counted_by(count); 103 }; 104 105 //============================================================================== 106 // __counted_by on struct member pointer in type attribute position 107 //============================================================================== 108 // TODO: Correctly parse counted_by as a type attribute. Currently it is parsed 109 // as a declaration attribute 110 111 struct on_member_pointer_complete_ty_ty_pos { 112 int count; 113 struct size_known *__counted_by(count) buf; 114 }; 115 116 struct on_member_pointer_incomplete_ty_ty_pos { 117 int count; 118 // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'struct size_unknown' is an incomplete type}} 119 struct size_unknown * __counted_by(count) buf; 120 }; 121 122 struct on_member_pointer_const_incomplete_ty_ty_pos { 123 int count; 124 // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'const struct size_unknown' is an incomplete type}} 125 const struct size_unknown * __counted_by(count) buf; 126 }; 127 128 struct on_member_pointer_void_ty_ty_pos { 129 int count; 130 // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'void' is an incomplete type}} 131 void *__counted_by(count) buf; 132 }; 133 134 // - 135 136 struct on_member_pointer_fn_ptr_ty_pos { 137 int count; 138 // buffer of `count` function pointers is allowed 139 void (** __counted_by(count) fn_ptr)(void); 140 }; 141 142 struct on_member_pointer_fn_ptr_ty_ptr_ty_pos { 143 int count; 144 // buffer of `count` function pointers is allowed 145 fn_ptr_ty* __counted_by(count) fn_ptr; 146 }; 147 148 struct on_member_pointer_fn_ty_ty_pos { 149 int count; 150 // buffer of `count` functions is not allowed 151 // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'void (void)' is a function type}} 152 void (* __counted_by(count) fn_ptr)(void); 153 }; 154 155 struct on_member_pointer_fn_ptr_ty_ty_pos { 156 int count; 157 // buffer of `count` functions is not allowed 158 // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'void (void)' is a function type}} 159 fn_ptr_ty __counted_by(count) fn_ptr; 160 }; 161 162 // TODO: This should be forbidden but isn't due to counted_by being treated 163 // as a declaration attribute. 164 struct on_member_pointer_fn_ptr_ty_ty_pos_inner { 165 int count; 166 void (* __counted_by(count) * fn_ptr)(void); 167 }; 168 169 struct on_member_pointer_struct_with_vla_ty_pos { 170 int count; 171 // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'struct has_unannotated_vla' is a struct type with a flexible array member}} 172 struct has_unannotated_vla *__counted_by(count) objects; 173 }; 174 175 // Currently prevented because computing the size of `objects` at runtime would 176 // require an O(N) walk of `objects` to take into account the length of the VLA 177 // in each struct instance. 178 struct on_member_pointer_struct_with_annotated_vla_ty_pos { 179 int count; 180 // expected-error@+1{{counted_by' cannot be applied to a pointer with pointee of unknown size because 'struct has_annotated_vla' is a struct type with a flexible array member}} 181 struct has_annotated_vla* __counted_by(count) objects; 182 }; 183 184 struct on_nested_pointer_inner { 185 // TODO: This should be disallowed because in the `-fbounds-safety` model 186 // `__counted_by` can only be nested when used in function parameters. 187 int count; 188 struct size_known *__counted_by(count) *buf; 189 }; 190 191 struct on_nested_pointer_outer { 192 int count; 193 struct size_known **__counted_by(count) buf; 194 }; 195 196 struct on_pointer_anon_buf_ty_pos { 197 int count; 198 struct { 199 struct size_known * __counted_by(count) buf; 200 }; 201 }; 202 203 struct on_pointer_anon_count_ty_pos { 204 struct { 205 int count; 206 }; 207 struct size_known *__counted_by(count) buf; 208 }; 209 210 //============================================================================== 211 // __counted_by on struct non-pointer members 212 //============================================================================== 213 214 struct on_pod_ty { 215 int count; 216 // expected-error@+1{{'counted_by' only applies to pointers or C99 flexible array members}} 217 int wrong_ty __counted_by(count); 218 }; 219 220 struct on_void_ty { 221 int count; 222 // expected-error@+2{{'counted_by' only applies to pointers or C99 flexible array members}} 223 // expected-error@+1{{field has incomplete type 'void'}} 224 void wrong_ty __counted_by(count); 225 }; 226