File: attr-counted-by-vla.c

package info (click to toggle)
llvm-toolchain-19 1%3A19.1.7-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,998,520 kB
  • sloc: cpp: 6,951,680; ansic: 1,486,157; asm: 913,598; python: 232,024; f90: 80,126; objc: 75,281; lisp: 37,276; pascal: 16,990; sh: 10,009; ml: 5,058; perl: 4,724; awk: 3,523; makefile: 3,167; javascript: 2,504; xml: 892; fortran: 664; cs: 573
file content (196 lines) | stat: -rw-r--r-- 6,902 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
// RUN: %clang_cc1 -fsyntax-only -verify %s

#define __counted_by(f)  __attribute__((counted_by(f)))

struct bar;

struct not_found {
  int count;
  struct bar *fam[] __counted_by(bork); // expected-error {{use of undeclared identifier 'bork'}}
};

struct no_found_count_not_in_substruct {
  unsigned long flags;
  unsigned char count; // expected-note {{'count' declared here}}
  struct A {
    int dummy;
    int array[] __counted_by(count); // expected-error {{'counted_by' field 'count' isn't within the same struct as the annotated flexible array}}
  } a;
};

struct not_found_count_not_in_unnamed_substruct {
  unsigned char count; // expected-note {{'count' declared here}}
  struct {
    int dummy;
    int array[] __counted_by(count); // expected-error {{'counted_by' field 'count' isn't within the same struct as the annotated flexible array}}
  } a;
};

struct not_found_count_not_in_unnamed_substruct_2 {
  struct {
    unsigned char count; // expected-note {{'count' declared here}}
  };
  struct {
    int dummy;
    int array[] __counted_by(count); // expected-error {{'counted_by' field 'count' isn't within the same struct as the annotated flexible array}}
  } a;
};

struct not_found_count_in_other_unnamed_substruct {
  struct {
    unsigned char count;
  } a1;

  struct {
    int dummy;
    int array[] __counted_by(count); // expected-error {{use of undeclared identifier 'count'}}
  };
};

struct not_found_count_in_other_substruct {
  struct _a1 {
    unsigned char count;
  } a1;

  struct {
    int dummy;
    int array[] __counted_by(count); // expected-error {{use of undeclared identifier 'count'}}
  };
};

struct not_found_count_in_other_substruct_2 {
  struct _a2 {
    unsigned char count;
  } a2;

  int array[] __counted_by(count); // expected-error {{use of undeclared identifier 'count'}}
};

struct not_found_suggest {
  int bork;
  struct bar *fam[] __counted_by(blork); // expected-error {{use of undeclared identifier 'blork'}}
};

int global; // expected-note {{'global' declared here}}

struct found_outside_of_struct {
  int bork;
  struct bar *fam[] __counted_by(global); // expected-error {{field 'global' in 'counted_by' not inside structure}}
};

struct self_referrential {
  int bork;
  struct bar *self[] __counted_by(self); // expected-error {{use of undeclared identifier 'self'}}
};

struct non_int_count {
  double dbl_count;
  struct bar *fam[] __counted_by(dbl_count); // expected-error {{'counted_by' requires a non-boolean integer type argument}}
};

struct array_of_ints_count {
  int integers[2];
  struct bar *fam[] __counted_by(integers); // expected-error {{'counted_by' requires a non-boolean integer type argument}}
};

struct not_a_fam {
  int count;
  // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'struct bar' is an incomplete type}}
  struct bar *non_fam __counted_by(count);
};

struct not_a_c99_fam {
  int count;
  struct bar *non_c99_fam[0] __counted_by(count); // expected-error {{'counted_by' on arrays only applies to C99 flexible array members}}
};

struct annotated_with_anon_struct {
  unsigned long flags;
  struct {
    unsigned char count;
    int array[] __counted_by(crount); // expected-error {{use of undeclared identifier 'crount'}}
  };
};

//==============================================================================
// __counted_by on a struct VLA with element type that has unknown size
//==============================================================================

struct size_unknown; // expected-note 2{{forward declaration of 'struct size_unknown'}}
struct on_member_arr_incomplete_ty_ty_pos {
  int count;
  // expected-error@+2{{'counted_by' only applies to pointers or C99 flexible array members}}
  // expected-error@+1{{array has incomplete element type 'struct size_unknown'}}
  struct size_unknown buf[] __counted_by(count);
};

struct on_member_arr_incomplete_const_ty_ty_pos {
  int count;
  // expected-error@+2{{'counted_by' only applies to pointers or C99 flexible array members}}
  // expected-error@+1{{array has incomplete element type 'const struct size_unknown'}}
  const struct size_unknown buf[] __counted_by(count);
};

struct on_member_arr_void_ty_ty_pos {
  int count;
  // expected-error@+2{{'counted_by' only applies to pointers or C99 flexible array members}}
  // expected-error@+1{{array has incomplete element type 'void'}}
  void buf[] __counted_by(count);
};

typedef void(fn_ty)(int);

struct on_member_arr_fn_ptr_ty {
  int count;
  // An Array of function pointers is allowed
  fn_ty* buf[] __counted_by(count);
};

struct on_member_arr_fn_ty {
  int count;
  // An array of functions is not allowed.
  // expected-error@+2{{'counted_by' only applies to pointers or C99 flexible array members}}
  // expected-error@+1{{'buf' declared as array of functions of type 'fn_ty' (aka 'void (int)')}}
  fn_ty buf[] __counted_by(count);
};


// `buffer_of_structs_with_unnannotated_vla`,
// `buffer_of_structs_with_annotated_vla`, and
// `buffer_of_const_structs_with_annotated_vla` are currently prevented because
// computing the size of `Arr` at runtime would require an O(N) walk of `Arr`
// elements to take into account the length of the VLA in each struct instance.

struct has_unannotated_VLA {
  int count;
  char buffer[];
};

struct has_annotated_VLA {
  int count;
  char buffer[] __counted_by(count);
};

struct buffer_of_structs_with_unnannotated_vla {
  int count;
  // Treating this as a warning is a temporary fix for existing attribute adopters. It **SHOULD BE AN ERROR**.
  // expected-warning@+1{{'counted_by' should not be applied to an array with element of unknown size because 'struct has_unannotated_VLA' is a struct type with a flexible array member. This will be an error in a future compiler version}}
  struct has_unannotated_VLA Arr[] __counted_by(count);
};


struct buffer_of_structs_with_annotated_vla {
  int count;
  // Treating this as a warning is a temporary fix for existing attribute adopters. It **SHOULD BE AN ERROR**.
  // expected-warning@+1{{'counted_by' should not be applied to an array with element of unknown size because 'struct has_annotated_VLA' is a struct type with a flexible array member. This will be an error in a future compiler version}}
  struct has_annotated_VLA Arr[] __counted_by(count);
};

struct buffer_of_const_structs_with_annotated_vla {
  int count;
  // Treating this as a warning is a temporary fix for existing attribute adopters. It **SHOULD BE AN ERROR**.
  // Make sure the `const` qualifier is printed when printing the element type.
  // expected-warning@+1{{'counted_by' should not be applied to an array with element of unknown size because 'const struct has_annotated_VLA' is a struct type with a flexible array member. This will be an error in a future compiler version}}
  const struct has_annotated_VLA Arr[] __counted_by(count);
};