257 lines · c
1// RUN: %clang_cc1 -fexperimental-late-parse-attributes -fsyntax-only -Wpointer-arith -verify %s2 3#define __counted_by_or_null(f) __attribute__((counted_by_or_null(f)))4#define __counted_by(f) __attribute__((counted_by(f)))5 6struct size_unknown;7struct size_known {8 int field;9};10 11typedef void(*fn_ptr_ty)(void);12 13//==============================================================================14// __counted_by_or_null on struct member pointer in decl attribute position15//==============================================================================16 17struct on_member_pointer_complete_ty {18 struct size_known * buf __counted_by_or_null(count);19 int count;20};21 22struct on_member_pointer_incomplete_ty {23 struct size_unknown * buf __counted_by_or_null(count); // ok24 int count;25};26 27struct on_member_pointer_const_incomplete_ty {28 const struct size_unknown * buf __counted_by_or_null(count); // ok29 int count;30};31 32struct on_member_pointer_void_ty {33 // expected-warning@+2{{'counted_by_or_null' on a pointer to void is a GNU extension, treated as 'sized_by_or_null'}}34 // expected-note@+1{{use '__sized_by_or_null' to suppress this warning}}35 void* buf __counted_by_or_null(count);36 int count;37};38 39struct on_member_pointer_fn_ptr_ty {40 // buffer of `count` function pointers is allowed41 void (**fn_ptr)(void) __counted_by_or_null(count);42 int count;43};44 45 46struct on_member_pointer_fn_ptr_ty_ptr_ty {47 // buffer of `count` function pointers is allowed48 fn_ptr_ty* fn_ptr __counted_by_or_null(count);49 int count;50};51 52struct on_member_pointer_fn_ty {53 // buffer of `count` functions is not allowed54 // expected-error@+1{{'counted_by_or_null' cannot be applied to a pointer with pointee of unknown size because 'void (void)' is a function type}}55 void (*fn_ptr)(void) __counted_by_or_null(count);56 int count;57};58 59struct on_member_pointer_fn_ptr_ty_ty {60 // buffer of `count` functions is not allowed61 // expected-error@+1{{'counted_by_or_null' cannot be applied to a pointer with pointee of unknown size because 'void (void)' is a function type}}62 fn_ptr_ty fn_ptr __counted_by_or_null(count);63 int count;64};65 66struct has_unannotated_vla {67 int count;68 int buffer[];69};70 71struct on_member_pointer_struct_with_vla {72 // expected-error@+1{{'counted_by_or_null' 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}}73 struct has_unannotated_vla* objects __counted_by_or_null(count);74 int count;75};76 77struct 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 would83// require an O(N) walk of `objects` to take into account the length of the VLA84// in each struct instance.85struct on_member_pointer_struct_with_annotated_vla {86 // expected-error@+1{{'counted_by_or_null' 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}}87 struct has_annotated_vla* objects __counted_by_or_null(count);88 int count;89};90 91struct on_pointer_anon_buf {92 // TODO: Support referring to parent scope93 struct {94 // expected-error@+1{{use of undeclared identifier 'count'}}95 struct size_known *buf __counted_by_or_null(count);96 };97 int count;98};99 100struct on_pointer_anon_count {101 struct size_known *buf __counted_by_or_null(count);102 struct {103 int count;104 };105};106 107//==============================================================================108// __counted_by_or_null on struct member pointer in type attribute position109//==============================================================================110// TODO: Correctly parse counted_by_or_null as a type attribute. Currently it is parsed111// as a declaration attribute and is **not** late parsed resulting in the `count`112// field being unavailable.113 114struct on_member_pointer_complete_ty_ty_pos {115 // TODO: Allow this116 // expected-error@+1{{use of undeclared identifier 'count'}}117 struct size_known *__counted_by_or_null(count) buf;118 int count;119};120 121struct on_member_pointer_incomplete_ty_ty_pos {122 // TODO: Allow this123 // expected-error@+1{{use of undeclared identifier 'count'}}124 struct size_unknown * __counted_by_or_null(count) buf;125 int count;126};127 128struct on_member_pointer_const_incomplete_ty_ty_pos {129 // TODO: Allow this130 // expected-error@+1{{use of undeclared identifier 'count'}}131 const struct size_unknown * __counted_by_or_null(count) buf;132 int count;133};134 135struct on_member_pointer_void_ty_ty_pos {136 // TODO: This should fail because the attribute is137 // on a pointer with the pointee being an incomplete type.138 // expected-error@+1{{use of undeclared identifier 'count'}}139 void *__counted_by_or_null(count) buf;140 int count;141};142 143// -144 145struct on_member_pointer_fn_ptr_ty_pos {146 // TODO: buffer of `count` function pointers should be allowed147 // but fails because this isn't late parsed.148 // expected-error@+1{{use of undeclared identifier 'count'}}149 void (** __counted_by_or_null(count) fn_ptr)(void);150 int count;151};152 153struct on_member_pointer_fn_ptr_ty_ptr_ty_pos {154 // TODO: buffer of `count` function pointers should be allowed155 // but fails because this isn't late parsed.156 // expected-error@+1{{use of undeclared identifier 'count'}}157 fn_ptr_ty* __counted_by_or_null(count) fn_ptr;158 int count;159};160 161struct on_member_pointer_fn_ty_ty_pos {162 // TODO: This should fail because the attribute is163 // on a pointer with the pointee being a function type.164 // expected-error@+1{{use of undeclared identifier 'count'}}165 void (* __counted_by_or_null(count) fn_ptr)(void);166 int count;167};168 169struct on_member_pointer_fn_ptr_ty_ty_pos {170 // TODO: buffer of `count` function pointers should be allowed171 // expected-error@+1{{use of undeclared identifier 'count'}}172 void (** __counted_by_or_null(count) fn_ptr)(void);173 int count;174};175 176struct on_member_pointer_fn_ptr_ty_typedef_ty_pos {177 // TODO: This should fail because the attribute is178 // on a pointer with the pointee being a function type.179 // expected-error@+1{{use of undeclared identifier 'count'}}180 fn_ptr_ty __counted_by_or_null(count) fn_ptr;181 int count;182};183 184struct on_member_pointer_fn_ptr_ty_ty_pos_inner {185 // TODO: This should fail because the attribute is186 // on a pointer with the pointee being a function type.187 // expected-error@+1{{use of undeclared identifier 'count'}}188 void (* __counted_by_or_null(count) * fn_ptr)(void);189 int count;190};191 192struct on_member_pointer_struct_with_vla_ty_pos {193 // TODO: This should fail because the attribute is194 // on a pointer with the pointee being a struct type with a VLA.195 // expected-error@+1{{use of undeclared identifier 'count'}}196 struct has_unannotated_vla *__counted_by_or_null(count) objects;197 int count;198};199 200struct on_member_pointer_struct_with_annotated_vla_ty_pos {201 // TODO: This should fail because the attribute is202 // on a pointer with the pointee being a struct type with a VLA.203 // expected-error@+1{{use of undeclared identifier 'count'}}204 struct has_annotated_vla* __counted_by_or_null(count) objects;205 int count;206};207 208struct on_nested_pointer_inner {209 // TODO: This should be disallowed because in the `-fbounds-safety` model210 // `__counted_by_or_null` can only be nested when used in function parameters.211 // expected-error@+1{{use of undeclared identifier 'count'}}212 struct size_known *__counted_by_or_null(count) *buf;213 int count;214};215 216struct on_nested_pointer_outer {217 // TODO: Allow this218 // expected-error@+1{{use of undeclared identifier 'count'}}219 struct size_known **__counted_by_or_null(count) buf;220 int count;221};222 223struct on_pointer_anon_buf_ty_pos {224 struct {225 // TODO: Support referring to parent scope226 // expected-error@+1{{use of undeclared identifier 'count'}}227 struct size_known * __counted_by_or_null(count) buf;228 };229 int count;230};231 232struct on_pointer_anon_count_ty_pos {233 // TODO: Allow this234 // expected-error@+1{{use of undeclared identifier 'count'}}235 struct size_known *__counted_by_or_null(count) buf;236 struct {237 int count;238 };239};240 241//==============================================================================242// __counted_by_or_null on struct non-pointer members243//==============================================================================244 245struct on_pod_ty {246 // expected-error-re@+1{{'counted_by_or_null' only applies to pointers{{$}}}}247 int wrong_ty __counted_by_or_null(count);248 int count;249};250 251struct on_void_ty {252 // expected-error-re@+2{{'counted_by_or_null' only applies to pointers{{$}}}}253 // expected-error@+1{{field has incomplete type 'void'}}254 void wrong_ty __counted_by_or_null(count);255 int count;256};257