248 lines · c
1// RUN: %clang_cc1 -fexperimental-late-parse-attributes -fsyntax-only -verify %s2 3#define __sized_by_or_null(f) __attribute__((__sized_by_or_null__(f)))4 5struct size_unknown;6struct size_known {7 int field;8};9 10typedef void(*fn_ptr_ty)(void);11 12//==============================================================================13// __sized_by_or_null on struct member pointer in decl attribute position14//==============================================================================15 16struct on_member_pointer_complete_ty {17 struct size_known * buf __sized_by_or_null(size);18 int size;19};20 21struct on_member_pointer_incomplete_ty {22 struct size_unknown * buf __sized_by_or_null(size);23 int size;24};25 26struct on_member_pointer_const_incomplete_ty {27 const struct size_unknown * buf __sized_by_or_null(size);28 int size;29};30 31struct on_member_pointer_void_ty {32 void* buf __sized_by_or_null(size);33 int size;34};35 36struct on_member_pointer_fn_ptr_ty {37 // buffer of `size` function pointers is allowed38 void (**fn_ptr)(void) __sized_by_or_null(size);39 int size;40};41 42 43struct on_member_pointer_fn_ptr_ty_ptr_ty {44 // buffer of `size` function pointers is allowed45 fn_ptr_ty* fn_ptr __sized_by_or_null(size);46 int size;47};48 49struct on_member_pointer_fn_ty {50 // buffer of function(s) with size `size` is allowed51 // expected-error@+1{{'sized_by_or_null' cannot be applied to a pointer with pointee of unknown size because 'void (void)' is a function type}}52 void (*fn_ptr)(void) __sized_by_or_null(size);53 int size;54};55 56struct on_member_pointer_fn_ptr_ty_ty {57 // buffer of function(s) with size `size` is allowed58 // expected-error@+1{{'sized_by_or_null' cannot be applied to a pointer with pointee of unknown size because 'void (void)' is a function type}}59 fn_ptr_ty fn_ptr __sized_by_or_null(size);60 int size;61};62 63struct has_unannotated_vla {64 int size;65 int buffer[];66};67 68struct on_member_pointer_struct_with_vla {69 // expected-error@+1{{'sized_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}}70 struct has_unannotated_vla* objects __sized_by_or_null(size);71 int size;72};73 74struct has_annotated_vla {75 int size;76 // expected-error@+1{{'sized_by_or_null' only applies to pointers; did you mean to use 'counted_by'?}}77 int buffer[] __sized_by_or_null(size);78};79 80struct on_member_pointer_struct_with_annotated_vla {81 // expected-error@+1{{'sized_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}}82 struct has_annotated_vla* objects __sized_by_or_null(size);83 int size;84};85 86struct on_pointer_anon_buf {87 // TODO: Support referring to parent scope88 struct {89 // expected-error@+1{{use of undeclared identifier 'size'}}90 struct size_known *buf __sized_by_or_null(size);91 };92 int size;93};94 95struct on_pointer_anon_count {96 struct size_known *buf __sized_by_or_null(size);97 struct {98 int size;99 };100};101 102//==============================================================================103// __sized_by_or_null on struct member pointer in type attribute position104//==============================================================================105// TODO: Correctly parse sized_by_or_null as a type attribute. Currently it is parsed106// as a declaration attribute and is **not** late parsed resulting in the `size`107// field being unavailable.108 109struct on_member_pointer_complete_ty_ty_pos {110 // TODO: Allow this111 // expected-error@+1{{use of undeclared identifier 'size'}}112 struct size_known *__sized_by_or_null(size) buf;113 int size;114};115 116struct on_member_pointer_incomplete_ty_ty_pos {117 // TODO: Allow this118 // expected-error@+1{{use of undeclared identifier 'size'}}119 struct size_unknown * __sized_by_or_null(size) buf;120 int size;121};122 123struct on_member_pointer_const_incomplete_ty_ty_pos {124 // TODO: Allow this125 // expected-error@+1{{use of undeclared identifier 'size'}}126 const struct size_unknown * __sized_by_or_null(size) buf;127 int size;128};129 130struct on_member_pointer_void_ty_ty_pos {131 // TODO: This should fail because the attribute is132 // on a pointer with the pointee being an incomplete type.133 // expected-error@+1{{use of undeclared identifier 'size'}}134 void *__sized_by_or_null(size) buf;135 int size;136};137 138// -139 140struct on_member_pointer_fn_ptr_ty_pos {141 // TODO: buffer of `size` function pointers should be allowed142 // but fails because this isn't late parsed.143 // expected-error@+1{{use of undeclared identifier 'size'}}144 void (** __sized_by_or_null(size) fn_ptr)(void);145 int size;146};147 148struct on_member_pointer_fn_ptr_ty_ptr_ty_pos {149 // TODO: buffer of `size` function pointers should be allowed150 // but fails because this isn't late parsed.151 // expected-error@+1{{use of undeclared identifier 'size'}}152 fn_ptr_ty* __sized_by_or_null(size) fn_ptr;153 int size;154};155 156struct on_member_pointer_fn_ty_ty_pos {157 // TODO: This should fail because the attribute is158 // on a pointer with the pointee being a function type.159 // expected-error@+1{{use of undeclared identifier 'size'}}160 void (* __sized_by_or_null(size) fn_ptr)(void);161 int size;162};163 164struct on_member_pointer_fn_ptr_ty_ty_pos {165 // TODO: buffer of `size` function pointers should be allowed166 // expected-error@+1{{use of undeclared identifier 'size'}}167 void (** __sized_by_or_null(size) fn_ptr)(void);168 int size;169};170 171struct on_member_pointer_fn_ptr_ty_typedef_ty_pos {172 // TODO: This should be allowed with sized_by_or_null.173 // expected-error@+1{{use of undeclared identifier 'size'}}174 fn_ptr_ty __sized_by_or_null(size) fn_ptr;175 int size;176};177 178struct on_member_pointer_fn_ptr_ty_ty_pos_inner {179 // TODO: This should be allowed with sized_by_or_null.180 // expected-error@+1{{use of undeclared identifier 'size'}}181 void (* __sized_by_or_null(size) * fn_ptr)(void);182 int size;183};184 185struct on_member_pointer_struct_with_vla_ty_pos {186 // TODO: This should be allowed with sized_by_or_null.187 // expected-error@+1{{use of undeclared identifier 'size'}}188 struct has_unannotated_vla *__sized_by_or_null(size) objects;189 int size;190};191 192struct on_member_pointer_struct_with_annotated_vla_ty_pos {193 // TODO: This should be allowed with sized_by_or_null.194 // expected-error@+1{{use of undeclared identifier 'size'}}195 struct has_annotated_vla* __sized_by_or_null(size) objects;196 int size;197};198 199struct on_nested_pointer_inner {200 // TODO: This should be disallowed because in the `-fbounds-safety` model201 // `__sized_by_or_null` can only be nested when used in function parameters.202 // expected-error@+1{{use of undeclared identifier 'size'}}203 struct size_known *__sized_by_or_null(size) *buf;204 int size;205};206 207struct on_nested_pointer_outer {208 // TODO: Allow this209 // expected-error@+1{{use of undeclared identifier 'size'}}210 struct size_known **__sized_by_or_null(size) buf;211 int size;212};213 214struct on_pointer_anon_buf_ty_pos {215 struct {216 // TODO: Support referring to parent scope217 // expected-error@+1{{use of undeclared identifier 'size'}}218 struct size_known * __sized_by_or_null(size) buf;219 };220 int size;221};222 223struct on_pointer_anon_count_ty_pos {224 // TODO: Allow this225 // expected-error@+1{{use of undeclared identifier 'size'}}226 struct size_known *__sized_by_or_null(size) buf;227 struct {228 int size;229 };230};231 232//==============================================================================233// __sized_by_or_null on struct non-pointer members234//==============================================================================235 236struct on_pod_ty {237 // expected-error-re@+1{{'sized_by_or_null' only applies to pointers{{$}}}}238 int wrong_ty __sized_by_or_null(size);239 int size;240};241 242struct on_void_ty {243 // expected-error-re@+2{{'sized_by_or_null' only applies to pointers{{$}}}}244 // expected-error@+1{{field has incomplete type 'void'}}245 void wrong_ty __sized_by_or_null(size);246 int size;247};248