Skip to content

Commit c000f75

Browse files
[libc++][test] Avoid non-Standard zero-length arrays (#74183)
Found while running libc++'s test suite with MSVC's STL, where we use both MSVC's compiler and Clang/LLVM. MSVC's compiler rejects the non-Standard extension of zero-length arrays. For conformance, I'm changing these occurrences to `std::array<int, 0>`. Many of these files already had `#include <array>`; I'm adding it to the rest. I wanted to add `-Wzero-length-array` to `libcxx/utils/libcxx/test/params.py` to prevent future occurrences, but it complained about product code 😿 : ``` In file included from /home/runner/_work/llvm-project/llvm-project/libcxx/test/std/input.output/iostream.format/input.streams/istream.formatted/istream.formatted.arithmetic/long.pass.cpp:18: In file included from /home/runner/_work/llvm-project/llvm-project/build/generic-cxx03/include/c++/v1/istream:170: In file included from /home/runner/_work/llvm-project/llvm-project/build/generic-cxx03/include/c++/v1/ostream:172: In file included from /home/runner/_work/llvm-project/llvm-project/build/generic-cxx03/include/c++/v1/__system_error/error_code.h:18: In file included from /home/runner/_work/llvm-project/llvm-project/build/generic-cxx03/include/c++/v1/__system_error/error_category.h:15: /home/runner/_work/llvm-project/llvm-project/build/generic-cxx03/include/c++/v1/string:811:25: error: zero size arrays are an extension [-Werror,-Wzero-length-array] 811 | char __padding_[sizeof(value_type) - 1]; | ^~~~~~~~~~~~~~~~~~~~~~ /home/runner/_work/llvm-project/llvm-project/build/generic-cxx03/include/c++/v1/string:817:19: note: in instantiation of member class 'std::basic_string<char>::__short' requested here 817 | static_assert(sizeof(__short) == (sizeof(value_type) * (__min_cap + 1)), "__short has an unexpected size."); | ^ /home/runner/_work/llvm-project/llvm-project/build/generic-cxx03/include/c++/v1/string:2069:5: note: in instantiation of template class 'std::basic_string<char>' requested here 2069 | _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_DECLARE, char) | ^ /home/runner/_work/llvm-project/llvm-project/build/generic-cxx03/include/c++/v1/__string/extern_template_lists.h:31:60: note: expanded from macro '_LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST' 31 | _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, value_type const*, size_type)) \ | ^ ``` I pushed a tiny commit to fix unrelated comment typos, in an attempt to clear out spurious CI failures.
1 parent e3b3c91 commit c000f75

File tree

18 files changed

+125
-120
lines changed

18 files changed

+125
-120
lines changed

libcxx/test/libcxx/gdb/gdb_pretty_printer_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ def invoke(self, arg, from_tty):
7676
except RuntimeError as e:
7777
# At this point, lots of different things could be wrong, so don't try to
7878
# recover or figure it out. Don't exit either, because then it's
79-
# impossible debug the framework itself.
79+
# impossible to debug the framework itself.
8080
print("FAIL: Something is wrong in the test framework.")
8181
print(str(e))
8282
test_failures += 1

libcxx/test/std/algorithms/alg.modifying.operations/alg.random.shuffle/random_shuffle.pass.cpp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS
1818

1919
#include <algorithm>
20+
#include <array>
2021
#include <cassert>
2122

2223
#include "test_macros.h"
@@ -26,18 +27,18 @@ template <class Iter>
2627
void
2728
test_with_iterator()
2829
{
29-
int empty[] = {};
30-
std::random_shuffle(Iter(empty), Iter(empty));
30+
std::array<int, 0> empty = {};
31+
std::random_shuffle(Iter(empty.data()), Iter(empty.data()));
3132

32-
const int all_elements[] = {1, 2, 3, 4};
33-
int shuffled[] = {1, 2, 3, 4};
34-
const unsigned size = sizeof(all_elements)/sizeof(all_elements[0]);
33+
const int all_elements[] = {1, 2, 3, 4};
34+
int shuffled[] = {1, 2, 3, 4};
35+
const unsigned size = sizeof(all_elements) / sizeof(all_elements[0]);
3536

36-
std::random_shuffle(Iter(shuffled), Iter(shuffled+size));
37-
assert(std::is_permutation(shuffled, shuffled+size, all_elements));
37+
std::random_shuffle(Iter(shuffled), Iter(shuffled + size));
38+
assert(std::is_permutation(shuffled, shuffled + size, all_elements));
3839

39-
std::random_shuffle(Iter(shuffled), Iter(shuffled+size));
40-
assert(std::is_permutation(shuffled, shuffled+size, all_elements));
40+
std::random_shuffle(Iter(shuffled), Iter(shuffled + size));
41+
assert(std::is_permutation(shuffled, shuffled + size, all_elements));
4142
}
4243

4344

libcxx/test/std/algorithms/alg.modifying.operations/alg.transform/ranges.transform.binary.iterator.pass.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -89,41 +89,41 @@ constexpr bool test_iterators() {
8989
}
9090

9191
{ // first range empty
92-
int a[] = {};
92+
std::array<int, 0> a = {};
9393
int b[] = {5, 4, 3, 2, 1};
9494
int c[5];
9595

9696
auto ret = std::ranges::transform(
97-
In1(a), Sent1(In1(a)), In2(b), Sent2(In2(b + 5)), Out(c), [](int i, int j) { return i + j; });
97+
In1(a.data()), Sent1(In1(a.data())), In2(b), Sent2(In2(b + 5)), Out(c), [](int i, int j) { return i + j; });
9898

99-
assert(base(ret.in1) == a);
99+
assert(base(ret.in1) == a.data());
100100
assert(base(ret.in2) == b);
101101
assert(base(ret.out) == c);
102102
}
103103

104104
{ // second range empty
105105
int a[] = {5, 4, 3, 2, 1};
106-
int b[] = {};
106+
std::array<int, 0> b = {};
107107
int c[5];
108108

109109
auto ret = std::ranges::transform(
110-
In1(a), Sent1(In1(a + 5)), In2(b), Sent2(In2(b)), Out(c), [](int i, int j) { return i + j; });
110+
In1(a), Sent1(In1(a + 5)), In2(b.data()), Sent2(In2(b.data())), Out(c), [](int i, int j) { return i + j; });
111111

112112
assert(base(ret.in1) == a);
113-
assert(base(ret.in2) == b);
113+
assert(base(ret.in2) == b.data());
114114
assert(base(ret.out) == c);
115115
}
116116

117117
{ // both ranges empty
118-
int a[] = {};
119-
int b[] = {};
118+
std::array<int, 0> a = {};
119+
std::array<int, 0> b = {};
120120
int c[5];
121121

122122
auto ret = std::ranges::transform(
123-
In1(a), Sent1(In1(a)), In2(b), Sent2(In2(b)), Out(c), [](int i, int j) { return i + j; });
123+
In1(a.data()), Sent1(In1(a.data())), In2(b.data()), Sent2(In2(b.data())), Out(c), [](int i, int j) { return i + j; });
124124

125-
assert(base(ret.in1) == a);
126-
assert(base(ret.in2) == b);
125+
assert(base(ret.in1) == a.data());
126+
assert(base(ret.in2) == b.data());
127127
assert(base(ret.out) == c);
128128
}
129129

libcxx/test/std/algorithms/alg.modifying.operations/alg.transform/ranges.transform.binary.range.pass.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -92,47 +92,47 @@ constexpr bool test_iterators() {
9292
}
9393

9494
{ // first range empty
95-
int a[] = {};
95+
std::array<int, 0> a = {};
9696
int b[] = {5, 4, 3, 2, 1};
9797
int c[5];
9898

99-
auto range1 = std::ranges::subrange(In1(a), Sent1(In1(a)));
99+
auto range1 = std::ranges::subrange(In1(a.data()), Sent1(In1(a.data())));
100100
auto range2 = std::ranges::subrange(In2(b), Sent2(In2(b + 5)));
101101

102102
auto ret = std::ranges::transform(range1, range2, Out(c), [](int i, int j) { return i + j; });
103103

104-
assert(base(ret.in1) == a);
104+
assert(base(ret.in1) == a.data());
105105
assert(base(ret.in2) == b);
106106
assert(base(ret.out) == c);
107107
}
108108

109109
{ // second range empty
110110
int a[] = {5, 4, 3, 2, 1};
111-
int b[] = {};
111+
std::array<int, 0> b = {};
112112
int c[5];
113113

114114
auto range1 = std::ranges::subrange(In1(a), Sent1(In1(a + 5)));
115-
auto range2 = std::ranges::subrange(In2(b), Sent2(In2(b)));
115+
auto range2 = std::ranges::subrange(In2(b.data()), Sent2(In2(b.data())));
116116

117117
auto ret = std::ranges::transform(range1, range2, Out(c), [](int i, int j) { return i + j; });
118118

119119
assert(base(ret.in1) == a);
120-
assert(base(ret.in2) == b);
120+
assert(base(ret.in2) == b.data());
121121
assert(base(ret.out) == c);
122122
}
123123

124124
{ // both ranges empty
125-
int a[] = {};
126-
int b[] = {};
125+
std::array<int, 0> a = {};
126+
std::array<int, 0> b = {};
127127
int c[5];
128128

129-
auto range1 = std::ranges::subrange(In1(a), Sent1(In1(a)));
130-
auto range2 = std::ranges::subrange(In2(b), Sent2(In2(b)));
129+
auto range1 = std::ranges::subrange(In1(a.data()), Sent1(In1(a.data())));
130+
auto range2 = std::ranges::subrange(In2(b.data()), Sent2(In2(b.data())));
131131

132132
auto ret = std::ranges::transform(range1, range2, Out(c), [](int i, int j) { return i + j; });
133133

134-
assert(base(ret.in1) == a);
135-
assert(base(ret.in2) == b);
134+
assert(base(ret.in1) == a.data());
135+
assert(base(ret.in2) == b.data());
136136
assert(base(ret.out) == c);
137137
}
138138

libcxx/test/std/algorithms/alg.modifying.operations/alg.transform/ranges.transform.unary.pass.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -108,19 +108,19 @@ constexpr bool test_iterators() {
108108

109109
{ // first range empty
110110
{
111-
int a[] = {};
111+
std::array<int, 0> a = {};
112112
int b[5];
113-
auto ret = std::ranges::transform(In1(a), Sent1(In1(a)), Out(b), [](int i) { return i * 2; });
114-
assert(base(ret.in) == a);
113+
auto ret = std::ranges::transform(In1(a.data()), Sent1(In1(a.data())), Out(b), [](int i) { return i * 2; });
114+
assert(base(ret.in) == a.data());
115115
assert(base(ret.out) == b);
116116
}
117117

118118
{
119-
int a[] = {};
119+
std::array<int, 0> a = {};
120120
int b[5];
121-
auto range = std::ranges::subrange(In1(a), Sent1(In1(a)));
121+
auto range = std::ranges::subrange(In1(a.data()), Sent1(In1(a.data())));
122122
auto ret = std::ranges::transform(range, Out(b), [](int i) { return i * 2; });
123-
assert(base(ret.in) == a);
123+
assert(base(ret.in) == a.data());
124124
assert(base(ret.out) == b);
125125
}
126126
}

libcxx/test/std/algorithms/alg.nonmodifying/alg.ends_with/ranges.ends_with.pass.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -156,9 +156,9 @@ constexpr void test_iterators() {
156156

157157
{ // suffix has zero length
158158
int a[] = {1, 2, 3, 4, 5, 6};
159-
int p[] = {};
159+
std::array<int, 0> p = {};
160160
auto whole = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
161-
auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p)));
161+
auto suffix = std::ranges::subrange(Iter2(p.data()), Sent2(Iter2(p.data())));
162162
{
163163
bool ret = std::ranges::ends_with(whole.begin(), whole.end(), suffix.begin(), suffix.end());
164164
assert(ret);
@@ -170,9 +170,9 @@ constexpr void test_iterators() {
170170
}
171171

172172
{ // range has zero length
173-
int a[] = {};
173+
std::array<int, 0> a = {};
174174
int p[] = {1, 2, 3, 4, 5, 6, 7, 8};
175-
auto whole = std::ranges::subrange(Iter1(a), Sent1(Iter1(a)));
175+
auto whole = std::ranges::subrange(Iter1(a.data()), Sent1(Iter1(a.data())));
176176
auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 8)));
177177
{
178178
bool ret = std::ranges::ends_with(whole.begin(), whole.end(), suffix.begin(), suffix.end());

libcxx/test/std/algorithms/alg.nonmodifying/alg.equal/ranges.equal.pass.cpp

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
// Proj1 proj1 = {}, Proj2 proj2 = {});
2424

2525
#include <algorithm>
26+
#include <array>
2627
#include <cassert>
2728
#include <concepts>
2829
#include <functional>
@@ -200,32 +201,32 @@ constexpr void test_iterators() {
200201

201202
{ // check that two empty ranges work
202203
{
203-
int a[] = {};
204-
int b[] = {};
205-
auto ret = std::ranges::equal(Iter1(a), Sent1(Iter1(a)), Iter2(b), Sent2(Iter2(b)));
204+
std::array<int, 0> a = {};
205+
std::array<int, 0> b = {};
206+
auto ret = std::ranges::equal(Iter1(a.data()), Sent1(Iter1(a.data())), Iter2(b.data()), Sent2(Iter2(b.data())));
206207
assert(ret);
207208
}
208209
{
209-
int a[] = {};
210-
int b[] = {};
211-
auto range1 = std::ranges::subrange(Iter1(a), Sent1(Iter1(a)));
212-
auto range2 = std::ranges::subrange(Iter2(b), Sent2(Iter2(b)));
210+
std::array<int, 0> a = {};
211+
std::array<int, 0> b = {};
212+
auto range1 = std::ranges::subrange(Iter1(a.data()), Sent1(Iter1(a.data())));
213+
auto range2 = std::ranges::subrange(Iter2(b.data()), Sent2(Iter2(b.data())));
213214
auto ret = std::ranges::equal(range1, range2);
214215
assert(ret);
215216
}
216217
}
217218

218219
{ // check that it works with the first range empty
219220
{
220-
int a[] = {};
221+
std::array<int, 0> a = {};
221222
int b[] = {1, 2};
222-
auto ret = std::ranges::equal(Iter1(a), Sent1(Iter1(a)), Iter2(b), Sent2(Iter2(b + 2)));
223+
auto ret = std::ranges::equal(Iter1(a.data()), Sent1(Iter1(a.data())), Iter2(b), Sent2(Iter2(b + 2)));
223224
assert(!ret);
224225
}
225226
{
226-
int a[] = {};
227+
std::array<int, 0> a = {};
227228
int b[] = {1, 2};
228-
auto range1 = std::ranges::subrange(Iter1(a), Sent1(Iter1(a)));
229+
auto range1 = std::ranges::subrange(Iter1(a.data()), Sent1(Iter1(a.data())));
229230
auto range2 = std::ranges::subrange(Iter2(b), Sent2(Iter2(b + 2)));
230231
auto ret = std::ranges::equal(range1, range2);
231232
assert(!ret);
@@ -235,15 +236,15 @@ constexpr void test_iterators() {
235236
{ // check that it works with the second range empty
236237
{
237238
int a[] = {1, 2};
238-
int b[] = {};
239-
auto ret = std::ranges::equal(Iter1(a), Sent1(Iter1(a + 2)), Iter2(b), Sent2(Iter2(b)));
239+
std::array<int, 0> b = {};
240+
auto ret = std::ranges::equal(Iter1(a), Sent1(Iter1(a + 2)), Iter2(b.data()), Sent2(Iter2(b.data())));
240241
assert(!ret);
241242
}
242243
{
243244
int a[] = {1, 2};
244-
int b[] = {};
245+
std::array<int, 0> b = {};
245246
auto range1 = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 2)));
246-
auto range2 = std::ranges::subrange(Iter2(b), Sent2(Iter2(b)));
247+
auto range2 = std::ranges::subrange(Iter2(b.data()), Sent2(Iter2(b.data())));
247248
auto ret = std::ranges::equal(range1, range2);
248249
assert(!ret);
249250
}

libcxx/test/std/algorithms/alg.nonmodifying/alg.find.end/ranges.find_end.pass.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -182,16 +182,16 @@ constexpr void test_iterators() {
182182
{ // pattern has zero length
183183
{
184184
int a[] = {6, 7, 8};
185-
int p[] = {};
186-
auto ret = std::ranges::find_end(Iter1(a), Sent1(Iter1(a + 3)), Iter2(p), Sent2(Iter2(p)));
185+
std::array<int, 0> p = {};
186+
auto ret = std::ranges::find_end(Iter1(a), Sent1(Iter1(a + 3)), Iter2(p.data()), Sent2(Iter2(p.data())));
187187
assert(base(ret.begin()) == a + 3);
188188
assert(base(ret.end()) == a + 3);
189189
}
190190
{
191191
int a[] = {6, 7, 8};
192-
int p[] = {};
192+
std::array<int, 0> p = {};
193193
auto range1 = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 3)));
194-
auto range2 = std::ranges::subrange(Iter2(p), Sent2(Iter2(p)));
194+
auto range2 = std::ranges::subrange(Iter2(p.data()), Sent2(Iter2(p.data())));
195195
auto ret = std::ranges::find_end(range1, range2);
196196
assert(base(ret.begin()) == a + 3);
197197
assert(base(ret.end()) == a + 3);
@@ -200,20 +200,20 @@ constexpr void test_iterators() {
200200

201201
{ // range has zero length
202202
{
203-
int a[] = {};
203+
std::array<int, 0> a = {};
204204
int p[] = {6, 7, 8};
205-
auto ret = std::ranges::find_end(Iter1(a), Sent1(Iter1(a)), Iter2(p), Sent2(Iter2(p + 3)));
206-
assert(base(ret.begin()) == a);
207-
assert(base(ret.end()) == a);
205+
auto ret = std::ranges::find_end(Iter1(a.data()), Sent1(Iter1(a.data())), Iter2(p), Sent2(Iter2(p + 3)));
206+
assert(base(ret.begin()) == a.data());
207+
assert(base(ret.end()) == a.data());
208208
}
209209
{
210-
int a[] = {};
210+
std::array<int, 0> a = {};
211211
int p[] = {6, 7, 8};
212-
auto range1 = std::ranges::subrange(Iter1(a), Sent1(Iter1(a)));
212+
auto range1 = std::ranges::subrange(Iter1(a.data()), Sent1(Iter1(a.data())));
213213
auto range2 = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 3)));
214214
auto ret = std::ranges::find_end(range1, range2);
215-
assert(base(ret.begin()) == a);
216-
assert(base(ret.end()) == a);
215+
assert(base(ret.begin()) == a.data());
216+
assert(base(ret.end()) == a.data());
217217
}
218218
}
219219

libcxx/test/std/algorithms/alg.nonmodifying/alg.foreach/ranges.for_each.pass.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
// ranges::for_each(R&& r, Fun f, Proj proj = {});
2020

2121
#include <algorithm>
22+
#include <array>
2223
#include <ranges>
2324

2425
#include "almost_satisfies_types.h"
@@ -98,12 +99,12 @@ constexpr void test_iterator() {
9899

99100
{ // check that an empty range works
100101
{
101-
int a[] = {};
102-
std::ranges::for_each(Iter(a), Sent(Iter(a)), [](auto&) { assert(false); });
102+
std::array<int, 0> a = {};
103+
std::ranges::for_each(Iter(a.data()), Sent(Iter(a.data())), [](auto&) { assert(false); });
103104
}
104105
{
105-
int a[] = {};
106-
auto range = std::ranges::subrange(Iter(a), Sent(Iter(a)));
106+
std::array<int, 0> a = {};
107+
auto range = std::ranges::subrange(Iter(a.data()), Sent(Iter(a.data())));
107108
std::ranges::for_each(range, [](auto&) { assert(false); });
108109
}
109110
}

libcxx/test/std/algorithms/alg.nonmodifying/alg.foreach/ranges.for_each_n.pass.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
// ranges::for_each_n(I first, iter_difference_t<I> n, Fun f, Proj proj = {});
1717

1818
#include <algorithm>
19+
#include <array>
1920
#include <ranges>
2021

2122
#include "almost_satisfies_types.h"
@@ -58,8 +59,8 @@ constexpr void test_iterator() {
5859
}
5960

6061
{ // check that an empty range works
61-
int a[] = {};
62-
std::ranges::for_each_n(Iter(a), 0, [](auto&) { assert(false); });
62+
std::array<int, 0> a = {};
63+
std::ranges::for_each_n(Iter(a.data()), 0, [](auto&) { assert(false); });
6364
}
6465
}
6566

0 commit comments

Comments
 (0)