@@ -69,6 +69,148 @@ void good_struct_self_loop(cb *c) {
6969 }
7070}
7171
72+ // Inout pointer and count
73+
74+ void good_inout_span (int *__counted_by (*count) *p, size_t *count, std::span<int> sp) {
75+ *p = sp.data ();
76+ *count = sp.size ();
77+ }
78+
79+ void bad_inout_span (int *__counted_by (*count) *p, size_t *count, std::span<int> sp) {
80+ *p = sp.data (); // TODO-expected-warning{{unsafe assignment to count-attributed pointer}}
81+ *count = 42 ;
82+ }
83+
84+ void good_inout_subspan_const (int *__counted_by (*count) *p, size_t *count, std::span<int> sp) {
85+ *p = sp.first (42 ).data ();
86+ *count = 42 ;
87+ }
88+
89+ void good_inout_subspan_var (int *__counted_by (*count) *p, size_t *count, std::span<int> sp, size_t new_count) {
90+ *p = sp.first (new_count).data ();
91+ *count = new_count;
92+ }
93+
94+ void good_inout_subspan_complex (int *__counted_by (*count) *p, size_t *count, std::span<int> sp, size_t i, size_t j) {
95+ *p = sp.first (i + j * 2 ).data ();
96+ *count = i + j * 2 ;
97+ }
98+
99+ void good_inout_span_if (int *__counted_by (*count) *p, size_t *count, std::span<int> sp) {
100+ if (p && count) {
101+ *p = sp.data ();
102+ *count = sp.size ();
103+ }
104+ }
105+
106+ void bad_inout_span_if (int *__counted_by (*count) *p, size_t *count, std::span<int> sp, size_t size) {
107+ if (p && count) {
108+ *p = sp.data (); // TODO-expected-warning{{unsafe assignment to count-attributed pointer}}
109+ *count = size;
110+ }
111+ }
112+
113+ class inout_class {
114+ void good_inout_span (int *__counted_by (*count) *p, size_t *count, std::span<int> sp) {
115+ *p = sp.data ();
116+ *count = sp.size ();
117+ }
118+
119+ void bad_inout_span (int *__counted_by (*count) *p, size_t *count, std::span<int> sp) {
120+ *p = sp.data (); // TODO-expected-warning{{unsafe assignment to count-attributed pointer}}
121+ *count = 42 ;
122+ }
123+
124+ void good_inout_subspan_const (int *__counted_by (*count) *p, size_t *count, std::span<int> sp) {
125+ *p = sp.first (42 ).data ();
126+ *count = 42 ;
127+ }
128+ };
129+
130+ // Inout pointer
131+
132+ void bad_inout_ptr_span (int *__counted_by (count) *p, int count, std::span<int> sp) {
133+ *p = sp.data (); // TODO-expected-warning{{unsafe assignment to count-attributed pointer}}
134+ }
135+
136+ void good_inout_ptr_subspan (int *__counted_by (count) *p, size_t count, std::span<int> sp) {
137+ *p = sp.first (count).data ();
138+ }
139+
140+ void good_inout_ptr_const_subspan (int *__counted_by (42 ) *p, std::span<int> sp) {
141+ *p = sp.first (42 ).data ();
142+ }
143+
144+ void good_inout_ptr_multi_subspan (int *__counted_by (a + b) *p, size_t a, size_t b, std::span<int> sp) {
145+ *p = sp.first (a + b).data ();
146+ }
147+
148+ class inout_ptr_class {
149+ void bad_inout_ptr_span (int *__counted_by (count) *p, int count, std::span<int> sp) {
150+ *p = sp.data (); // TODO-expected-warning{{unsafe assignment to count-attributed pointer}}
151+ }
152+
153+ void good_inout_ptr_subspan (int *__counted_by (count) *p, size_t count, std::span<int> sp) {
154+ *p = sp.first (count).data ();
155+ }
156+ };
157+
158+ // Immutable pointers/dependent values
159+
160+ void immutable_ptr_to_ptr (int *__counted_by (*count) *p, int *count) {
161+ p = nullptr ; // expected-warning{{cannot assign to parameter 'p' because it points to a count-attributed pointer}}
162+ *count = 0 ;
163+ }
164+
165+ void immutable_ptr_to_value (int *__counted_by (*count) *p, int *count) {
166+ *p = nullptr ;
167+ count = nullptr ; // expected-warning{{cannot assign to parameter 'count' because it points to a dependent count}}
168+ }
169+
170+ void immutable_ptr_with_inout_value (int *__counted_by (*count) p, int *count) {
171+ p = nullptr ; // expected-warning{{cannot assign to parameter 'p' because its type depends on an inout dependent count}}
172+ *count = 0 ;
173+ }
174+
175+ void immutable_ptr_with_inout_value2 (int *__counted_by (*count) p, int *__counted_by(*count) *q, int *count) {
176+ p = nullptr ; // expected-warning{{cannot assign to parameter 'p' because its type depends on an inout dependent count}}
177+ *q = nullptr ;
178+ *count = 0 ;
179+ }
180+
181+ void immutable_value_with_inout_ptr (int *__counted_by (count) *p, int count) {
182+ *p = nullptr ;
183+ count = 0 ; // expected-warning{{cannot assign to parameter 'count' because it's used as dependent count in an inout count-attributed pointer}}
184+ }
185+
186+ void immutable_value_with_inout_ptr2 (int *__counted_by (count) p, int *__counted_by(count) *q, int count) {
187+ p = nullptr ;
188+ *q = nullptr ;
189+ count = 0 ; // expected-warning{{cannot assign to parameter 'count' because it's used as dependent count in an inout count-attributed pointer}}
190+ }
191+
192+ class immutable_class {
193+ void immutable_ptr_to_ptr (int *__counted_by (*count) *p, int *count) {
194+ p = nullptr ; // expected-warning{{cannot assign to parameter 'p' because it points to a count-attributed pointer}}
195+ *count = 0 ;
196+ }
197+
198+ void immutable_ptr_to_value (int *__counted_by (*count) *p, int *count) {
199+ *p = nullptr ;
200+ count = nullptr ; // expected-warning{{cannot assign to parameter 'count' because it points to a dependent count}}
201+ }
202+
203+ void immutable_ptr_with_inout_value (int *__counted_by (*count) p, int *count) {
204+ p = nullptr ; // expected-warning{{cannot assign to parameter 'p' because its type depends on an inout dependent count}}
205+ *count = 0 ;
206+ }
207+
208+ void immutable_value_with_inout_ptr (int *__counted_by (count) *p, int count) {
209+ *p = nullptr ;
210+ count = 0 ; // expected-warning{{cannot assign to parameter 'count' because it's used as dependent count in an inout count-attributed pointer}}
211+ }
212+ };
213+
72214// Assigns to bounds-attributed that we consider too complex to analyze.
73215
74216void too_complex_assign_to_ptr (int *__counted_by (count) p, int count, int *q) {
0 commit comments