224 lines · c
1// RUN: %clang_cc1 -fsyntax-only -Wpointer-arith -verify %s2// RUN: %clang_cc1 -fsyntax-only -Wpointer-arith -fexperimental-late-parse-attributes %s -verify3 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 on struct member pointer in decl attribute position15//==============================================================================16 17struct on_member_pointer_complete_ty {18 int count;19 struct size_known * buf __counted_by(count);20};21 22struct on_member_pointer_incomplete_ty {23 int count;24 struct size_unknown * buf __counted_by(count); // ok25};26 27struct on_member_pointer_const_incomplete_ty {28 int count;29 const struct size_unknown * buf __counted_by(count); // ok30};31 32struct on_member_pointer_void_ty {33 int count;34 // expected-warning@+2{{'counted_by' on a pointer to void is a GNU extension, treated as 'sized_by'}}35 // expected-note@+1{{use '__sized_by' to suppress this warning}}36 void* buf __counted_by(count);37};38 39struct on_member_pointer_fn_ptr_ty {40 int count;41 // buffer of `count` function pointers is allowed42 void (**fn_ptr)(void) __counted_by(count);43};44 45struct on_member_pointer_fn_ptr_ty_ptr_ty {46 int count;47 // buffer of `count` function pointers is allowed48 fn_ptr_ty* fn_ptr __counted_by(count);49};50 51struct on_member_pointer_fn_ty {52 int count;53 // buffer of `count` functions is not allowed54 // expected-error@+1{{'counted_by' 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(count);56};57 58struct on_member_pointer_fn_ptr_ty_ty {59 int count;60 // buffer of `count` functions is not allowed61 // expected-error@+1{{'counted_by' 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(count);63};64 65struct has_unannotated_vla {66 int count;67 int buffer[];68};69 70struct on_member_pointer_struct_with_vla {71 int count;72 // 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}}73 struct has_unannotated_vla* objects __counted_by(count);74};75 76struct has_annotated_vla {77 int count;78 int buffer[] __counted_by(count);79};80 81// Currently prevented because computing the size of `objects` at runtime would82// require an O(N) walk of `objects` to take into account the length of the VLA83// in each struct instance.84struct on_member_pointer_struct_with_annotated_vla {85 int count;86 // 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}}87 struct has_annotated_vla* objects __counted_by(count);88};89 90struct on_pointer_anon_buf {91 int count;92 struct {93 struct size_known *buf __counted_by(count);94 };95};96 97struct on_pointer_anon_count {98 struct {99 int count;100 };101 struct size_known *buf __counted_by(count);102};103 104//==============================================================================105// __counted_by on struct member pointer in type attribute position106//==============================================================================107// TODO: Correctly parse counted_by as a type attribute. Currently it is parsed108// as a declaration attribute109 110struct on_member_pointer_complete_ty_ty_pos {111 int count;112 struct size_known *__counted_by(count) buf;113};114 115struct on_member_pointer_incomplete_ty_ty_pos {116 int count;117 struct size_unknown * __counted_by(count) buf; // ok118};119 120struct on_member_pointer_const_incomplete_ty_ty_pos {121 int count;122 const struct size_unknown * __counted_by(count) buf; // ok123};124 125struct on_member_pointer_void_ty_ty_pos {126 int count;127 // expected-warning@+2{{'counted_by' on a pointer to void is a GNU extension, treated as 'sized_by'}}128 // expected-note@+1{{use '__sized_by' to suppress this warning}}129 void *__counted_by(count) buf;130};131 132// -133 134struct on_member_pointer_fn_ptr_ty_pos {135 int count;136 // buffer of `count` function pointers is allowed137 void (** __counted_by(count) fn_ptr)(void);138};139 140struct on_member_pointer_fn_ptr_ty_ptr_ty_pos {141 int count;142 // buffer of `count` function pointers is allowed143 fn_ptr_ty* __counted_by(count) fn_ptr;144};145 146struct on_member_pointer_fn_ty_ty_pos {147 int count;148 // buffer of `count` functions is not allowed149 // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'void (void)' is a function type}}150 void (* __counted_by(count) fn_ptr)(void);151};152 153struct on_member_pointer_fn_ptr_ty_ty_pos {154 int count;155 // buffer of `count` functions is not allowed156 // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'void (void)' is a function type}}157 fn_ptr_ty __counted_by(count) fn_ptr;158};159 160// TODO: This should be forbidden but isn't due to counted_by being treated161// as a declaration attribute.162struct on_member_pointer_fn_ptr_ty_ty_pos_inner {163 int count;164 void (* __counted_by(count) * fn_ptr)(void);165};166 167struct on_member_pointer_struct_with_vla_ty_pos {168 int count;169 // 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}}170 struct has_unannotated_vla *__counted_by(count) objects;171};172 173// Currently prevented because computing the size of `objects` at runtime would174// require an O(N) walk of `objects` to take into account the length of the VLA175// in each struct instance.176struct on_member_pointer_struct_with_annotated_vla_ty_pos {177 int count;178 // 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}}179 struct has_annotated_vla* __counted_by(count) objects;180};181 182struct on_nested_pointer_inner {183 // TODO: This should be disallowed because in the `-fbounds-safety` model184 // `__counted_by` can only be nested when used in function parameters.185 int count;186 struct size_known *__counted_by(count) *buf;187};188 189struct on_nested_pointer_outer {190 int count;191 struct size_known **__counted_by(count) buf;192};193 194struct on_pointer_anon_buf_ty_pos {195 int count;196 struct {197 struct size_known * __counted_by(count) buf;198 };199};200 201struct on_pointer_anon_count_ty_pos {202 struct {203 int count;204 };205 struct size_known *__counted_by(count) buf;206};207 208//==============================================================================209// __counted_by on struct non-pointer members210//==============================================================================211 212struct on_pod_ty {213 int count;214 // expected-error@+1{{'counted_by' only applies to pointers or C99 flexible array members}}215 int wrong_ty __counted_by(count);216};217 218struct on_void_ty {219 int count;220 // expected-error@+2{{'counted_by' only applies to pointers or C99 flexible array members}}221 // expected-error@+1{{field has incomplete type 'void'}}222 void wrong_ty __counted_by(count);223};224