xref: /llvm-project/clang/test/Sema/attr-counted-by-late-parsed-struct-ptrs.c (revision 29189738b832b111b905fcc037a287eeeb0aab2c)
1 // RUN: %clang_cc1 -fexperimental-late-parse-attributes -fsyntax-only -verify %s
2 
3 #define __counted_by(f)  __attribute__((counted_by(f)))
4 
5 struct size_unknown;
6 struct size_known {
7   int field;
8 };
9 
10 typedef void(*fn_ptr_ty)(void);
11 
12 //==============================================================================
13 // __counted_by on struct member pointer in decl attribute position
14 //==============================================================================
15 
16 struct on_member_pointer_complete_ty {
17   struct size_known * buf __counted_by(count);
18   int count;
19 };
20 
21 struct on_member_pointer_incomplete_ty {
22   struct size_unknown * buf __counted_by(count); // expected-error{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'struct size_unknown' is an incomplete type}}
23   int count;
24 };
25 
26 struct on_member_pointer_const_incomplete_ty {
27   // 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}}
28   const struct size_unknown * buf __counted_by(count);
29   int count;
30 };
31 
32 struct on_member_pointer_void_ty {
33   void* buf __counted_by(count); // expected-error{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'void' is an incomplete type}}
34   int count;
35 };
36 
37 struct on_member_pointer_fn_ptr_ty {
38   // buffer of `count` function pointers is allowed
39   void (**fn_ptr)(void) __counted_by(count);
40   int count;
41 };
42 
43 
44 struct on_member_pointer_fn_ptr_ty_ptr_ty {
45   // buffer of `count` function pointers is allowed
46   fn_ptr_ty* fn_ptr __counted_by(count);
47   int count;
48 };
49 
50 struct on_member_pointer_fn_ty {
51   // buffer of `count` functions is not allowed
52   // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'void (void)' is a function type}}
53   void (*fn_ptr)(void) __counted_by(count);
54   int count;
55 };
56 
57 struct on_member_pointer_fn_ptr_ty_ty {
58   // buffer of `count` functions is not allowed
59   // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'void (void)' is a function type}}
60   fn_ptr_ty fn_ptr __counted_by(count);
61   int count;
62 };
63 
64 struct has_unannotated_vla {
65   int count;
66   int buffer[];
67 };
68 
69 struct on_member_pointer_struct_with_vla {
70   // 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}}
71   struct has_unannotated_vla* objects __counted_by(count);
72   int count;
73 };
74 
75 struct has_annotated_vla {
76   int count;
77   int buffer[] __counted_by(count);
78 };
79 
80 // Currently prevented because computing the size of `objects` at runtime would
81 // require an O(N) walk of `objects` to take into account the length of the VLA
82 // in each struct instance.
83 struct on_member_pointer_struct_with_annotated_vla {
84   // 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}}
85   struct has_annotated_vla* objects __counted_by(count);
86   int count;
87 };
88 
89 struct on_pointer_anon_buf {
90   // TODO: Support referring to parent scope
91   struct {
92     // expected-error@+1{{use of undeclared identifier 'count'}}
93     struct size_known *buf __counted_by(count);
94   };
95   int count;
96 };
97 
98 struct on_pointer_anon_count {
99   struct size_known *buf __counted_by(count);
100   struct {
101     int count;
102   };
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 and is **not** late parsed resulting in the `count`
110 // field being unavailable.
111 
112 struct on_member_pointer_complete_ty_ty_pos {
113   // TODO: Allow this
114   // expected-error@+1{{use of undeclared identifier 'count'}}
115   struct size_known *__counted_by(count) buf;
116   int count;
117 };
118 
119 struct on_member_pointer_incomplete_ty_ty_pos {
120   // TODO: Allow this
121   // expected-error@+1{{use of undeclared identifier 'count'}}
122   struct size_unknown * __counted_by(count) buf;
123   int count;
124 };
125 
126 struct on_member_pointer_const_incomplete_ty_ty_pos {
127   // TODO: Allow this
128   // expected-error@+1{{use of undeclared identifier 'count'}}
129   const struct size_unknown * __counted_by(count) buf;
130   int count;
131 };
132 
133 struct on_member_pointer_void_ty_ty_pos {
134   // TODO: This should fail because the attribute is
135   // on a pointer with the pointee being an incomplete type.
136   // expected-error@+1{{use of undeclared identifier 'count'}}
137   void *__counted_by(count) buf;
138   int count;
139 };
140 
141 // -
142 
143 struct on_member_pointer_fn_ptr_ty_pos {
144   // TODO: buffer of `count` function pointers should be allowed
145   // but fails because this isn't late parsed.
146   // expected-error@+1{{use of undeclared identifier 'count'}}
147   void (** __counted_by(count) fn_ptr)(void);
148   int count;
149 };
150 
151 struct on_member_pointer_fn_ptr_ty_ptr_ty_pos {
152   // TODO: buffer of `count` function pointers should be allowed
153   // but fails because this isn't late parsed.
154   // expected-error@+1{{use of undeclared identifier 'count'}}
155   fn_ptr_ty* __counted_by(count) fn_ptr;
156   int count;
157 };
158 
159 struct on_member_pointer_fn_ty_ty_pos {
160   // TODO: This should fail because the attribute is
161   // on a pointer with the pointee being a function type.
162   // expected-error@+1{{use of undeclared identifier 'count'}}
163   void (* __counted_by(count) fn_ptr)(void);
164   int count;
165 };
166 
167 struct on_member_pointer_fn_ptr_ty_ty_pos {
168   // TODO: buffer of `count` function pointers should be allowed
169   // expected-error@+1{{use of undeclared identifier 'count'}}
170   void (** __counted_by(count) fn_ptr)(void);
171   int count;
172 };
173 
174 struct on_member_pointer_fn_ptr_ty_typedef_ty_pos {
175   // TODO: This should fail because the attribute is
176   // on a pointer with the pointee being a function type.
177   // expected-error@+1{{use of undeclared identifier 'count'}}
178   fn_ptr_ty __counted_by(count) fn_ptr;
179   int count;
180 };
181 
182 struct on_member_pointer_fn_ptr_ty_ty_pos_inner {
183   // TODO: This should fail because the attribute is
184   // on a pointer with the pointee being a function type.
185   // expected-error@+1{{use of undeclared identifier 'count'}}
186   void (* __counted_by(count) * fn_ptr)(void);
187   int count;
188 };
189 
190 struct on_member_pointer_struct_with_vla_ty_pos {
191   // TODO: This should fail because the attribute is
192   // on a pointer with the pointee being a struct type with a VLA.
193   // expected-error@+1{{use of undeclared identifier 'count'}}
194   struct has_unannotated_vla *__counted_by(count) objects;
195   int count;
196 };
197 
198 struct on_member_pointer_struct_with_annotated_vla_ty_pos {
199   // TODO: This should fail because the attribute is
200   // on a pointer with the pointee being a struct type with a VLA.
201   // expected-error@+1{{use of undeclared identifier 'count'}}
202   struct has_annotated_vla* __counted_by(count) objects;
203   int count;
204 };
205 
206 struct on_nested_pointer_inner {
207   // TODO: This should be disallowed because in the `-fbounds-safety` model
208   // `__counted_by` can only be nested when used in function parameters.
209   // expected-error@+1{{use of undeclared identifier 'count'}}
210   struct size_known *__counted_by(count) *buf;
211   int count;
212 };
213 
214 struct on_nested_pointer_outer {
215   // TODO: Allow this
216   // expected-error@+1{{use of undeclared identifier 'count'}}
217   struct size_known **__counted_by(count) buf;
218   int count;
219 };
220 
221 struct on_pointer_anon_buf_ty_pos {
222   struct {
223     // TODO: Support referring to parent scope
224     // expected-error@+1{{use of undeclared identifier 'count'}}
225     struct size_known * __counted_by(count) buf;
226   };
227   int count;
228 };
229 
230 struct on_pointer_anon_count_ty_pos {
231   // TODO: Allow this
232   // expected-error@+1{{use of undeclared identifier 'count'}}
233   struct size_known *__counted_by(count) buf;
234   struct {
235     int count;
236   };
237 };
238 
239 //==============================================================================
240 // __counted_by on struct non-pointer members
241 //==============================================================================
242 
243 struct on_pod_ty {
244   // expected-error@+1{{'counted_by' only applies to pointers or C99 flexible array members}}
245   int wrong_ty __counted_by(count);
246   int count;
247 };
248 
249 struct on_void_ty {
250   // expected-error@+2{{'counted_by' only applies to pointers or C99 flexible array members}}
251   // expected-error@+1{{field has incomplete type 'void'}}
252   void wrong_ty __counted_by(count);
253   int count;
254 };
255