225 lines · c
1// RUN: %clang_cc1 -fsyntax-only -Wpointer-arith -verify %s2// RUN: %clang_cc1 -fexperimental-late-parse-attributes -fsyntax-only -Wpointer-arith -verify %s3 4#define __counted_by_or_null(f) __attribute__((counted_by_or_null(f)))5#define __counted_by(f) __attribute__((counted_by(f)))6 7struct size_unknown;8struct size_known {9 int field;10};11 12typedef void(*fn_ptr_ty)(void);13 14//==============================================================================15// __counted_by_or_null on struct member pointer in decl attribute position16//==============================================================================17 18struct on_member_pointer_complete_ty {19 int count;20 struct size_known * buf __counted_by_or_null(count);21};22 23struct on_member_pointer_incomplete_ty {24 int count;25 struct size_unknown * buf __counted_by_or_null(count); // ok26};27 28struct on_member_pointer_const_incomplete_ty {29 int count;30 const struct size_unknown * buf __counted_by_or_null(count); // ok31};32 33struct on_member_pointer_void_ty {34 int count;35 // expected-warning@+2{{'counted_by_or_null' on a pointer to void is a GNU extension, treated as 'sized_by_or_null'}}36 // expected-note@+1{{use '__sized_by_or_null' to suppress this warning}}37 void* buf __counted_by_or_null(count);38};39 40struct on_member_pointer_fn_ptr_ty {41 int count;42 // buffer of `count` function pointers is allowed43 void (**fn_ptr)(void) __counted_by_or_null(count);44};45 46struct on_member_pointer_fn_ptr_ty_ptr_ty {47 int count;48 // buffer of `count` function pointers is allowed49 fn_ptr_ty* fn_ptr __counted_by_or_null(count);50};51 52struct on_member_pointer_fn_ty {53 int count;54 // buffer of `count` functions is not allowed55 // 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}}56 void (*fn_ptr)(void) __counted_by_or_null(count);57};58 59struct on_member_pointer_fn_ptr_ty_ty {60 int count;61 // buffer of `count` functions is not allowed62 // 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}}63 fn_ptr_ty fn_ptr __counted_by_or_null(count);64};65 66struct has_unannotated_vla {67 int count;68 int buffer[];69};70 71struct on_member_pointer_struct_with_vla {72 int count;73 // 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}}74 struct has_unannotated_vla* objects __counted_by_or_null(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 int count;87 // 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}}88 struct has_annotated_vla* objects __counted_by_or_null(count);89};90 91struct on_pointer_anon_buf {92 int count;93 struct {94 struct size_known *buf __counted_by_or_null(count);95 };96};97 98struct on_pointer_anon_count {99 struct {100 int count;101 };102 struct size_known *buf __counted_by_or_null(count);103};104 105//==============================================================================106// __counted_by_or_null on struct member pointer in type attribute position107//==============================================================================108// TODO: Correctly parse counted_by_or_null as a type attribute. Currently it is parsed109// as a declaration attribute110 111struct on_member_pointer_complete_ty_ty_pos {112 int count;113 struct size_known *__counted_by_or_null(count) buf;114};115 116struct on_member_pointer_incomplete_ty_ty_pos {117 int count;118 struct size_unknown * __counted_by_or_null(count) buf; // ok119};120 121struct on_member_pointer_const_incomplete_ty_ty_pos {122 int count;123 const struct size_unknown * __counted_by_or_null(count) buf; // ok124};125 126struct on_member_pointer_void_ty_ty_pos {127 int count;128 // expected-warning@+2{{'counted_by_or_null' on a pointer to void is a GNU extension, treated as 'sized_by_or_null'}}129 // expected-note@+1{{use '__sized_by_or_null' to suppress this warning}}130 void *__counted_by_or_null(count) buf;131};132 133// -134 135struct on_member_pointer_fn_ptr_ty_pos {136 int count;137 // buffer of `count` function pointers is allowed138 void (** __counted_by_or_null(count) fn_ptr)(void);139};140 141struct on_member_pointer_fn_ptr_ty_ptr_ty_pos {142 int count;143 // buffer of `count` function pointers is allowed144 fn_ptr_ty* __counted_by_or_null(count) fn_ptr;145};146 147struct on_member_pointer_fn_ty_ty_pos {148 int count;149 // buffer of `count` functions is not allowed150 // 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}}151 void (* __counted_by_or_null(count) fn_ptr)(void);152};153 154struct on_member_pointer_fn_ptr_ty_ty_pos {155 int count;156 // buffer of `count` functions is not allowed157 // 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}}158 fn_ptr_ty __counted_by_or_null(count) fn_ptr;159};160 161// TODO: This should be forbidden but isn't due to counted_by_or_null being treated162// as a declaration attribute.163struct on_member_pointer_fn_ptr_ty_ty_pos_inner {164 int count;165 void (* __counted_by_or_null(count) * fn_ptr)(void);166};167 168struct on_member_pointer_struct_with_vla_ty_pos {169 int count;170 // 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}}171 struct has_unannotated_vla *__counted_by_or_null(count) objects;172};173 174// Currently prevented because computing the size of `objects` at runtime would175// require an O(N) walk of `objects` to take into account the length of the VLA176// in each struct instance.177struct on_member_pointer_struct_with_annotated_vla_ty_pos {178 int count;179 // 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}}180 struct has_annotated_vla* __counted_by_or_null(count) objects;181};182 183struct on_nested_pointer_inner {184 // TODO: This should be disallowed because in the `-fbounds-safety` model185 // `__counted_by_or_null` can only be nested when used in function parameters.186 int count;187 struct size_known *__counted_by_or_null(count) *buf;188};189 190struct on_nested_pointer_outer {191 int count;192 struct size_known **__counted_by_or_null(count) buf;193};194 195struct on_pointer_anon_buf_ty_pos {196 int count;197 struct {198 struct size_known * __counted_by_or_null(count) buf;199 };200};201 202struct on_pointer_anon_count_ty_pos {203 struct {204 int count;205 };206 struct size_known *__counted_by_or_null(count) buf;207};208 209//==============================================================================210// __counted_by_or_null on struct non-pointer members211//==============================================================================212 213struct on_pod_ty {214 int count;215 // expected-error-re@+1{{'counted_by_or_null' only applies to pointers{{$}}}}216 int wrong_ty __counted_by_or_null(count);217};218 219struct on_void_ty {220 int count;221 // expected-error-re@+2{{'counted_by_or_null' only applies to pointers{{$}}}}222 // expected-error@+1{{field has incomplete type 'void'}}223 void wrong_ty __counted_by_or_null(count);224};225