xref: /llvm-project/clang/test/Sema/attr-counted-by-struct-ptrs.c (revision 876ee11eeeb2b6a7ccfefea00265b4bfd5f9b6dd)
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