Skip to content

[libc++][test] Avoid non-Standard zero-length arrays #74183

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Dec 3, 2023

Conversation

StephanTLavavej
Copy link
Member

@StephanTLavavej StephanTLavavej commented Dec 2, 2023

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.

I'm adding pointers in order to avoid disrupting the following code.

Add `-Wzero-length-array` to `params.py` to prevent future occurrences.

Might need to be clang-formatted.
@StephanTLavavej StephanTLavavej requested a review from a team as a code owner December 2, 2023 06:50
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Dec 2, 2023
@llvmbot
Copy link
Member

llvmbot commented Dec 2, 2023

@llvm/pr-subscribers-libcxx

Author: Stephan T. Lavavej (StephanTLavavej)

Changes

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&lt;int, 0&gt;. Then, in order to avoid disrupting the following code, I'm extracting .data() as a pointer.

Many of these files already had #include &lt;array&gt;; I'm adding it to the rest.

Finally, I'm adding -Wzero-length-array to params.py to hopefully prevent future occurrences.

This might need to be clang-formatted, I'll push a commit if so. (I'm still confused as to why some but not all files experience clang-format enforcement.)


Patch is 20.33 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/74183.diff

16 Files Affected:

  • (modified) libcxx/test/std/algorithms/alg.modifying.operations/alg.random.shuffle/random_shuffle.pass.cpp (+3-1)
  • (modified) libcxx/test/std/algorithms/alg.modifying.operations/alg.transform/ranges.transform.binary.iterator.pass.cpp (+8-4)
  • (modified) libcxx/test/std/algorithms/alg.modifying.operations/alg.transform/ranges.transform.binary.range.pass.cpp (+8-4)
  • (modified) libcxx/test/std/algorithms/alg.modifying.operations/alg.transform/ranges.transform.unary.pass.cpp (+4-2)
  • (modified) libcxx/test/std/algorithms/alg.nonmodifying/alg.ends_with/ranges.ends_with.pass.cpp (+4-2)
  • (modified) libcxx/test/std/algorithms/alg.nonmodifying/alg.equal/ranges.equal.pass.cpp (+17-8)
  • (modified) libcxx/test/std/algorithms/alg.nonmodifying/alg.find.end/ranges.find_end.pass.cpp (+8-4)
  • (modified) libcxx/test/std/algorithms/alg.nonmodifying/alg.foreach/ranges.for_each.pass.cpp (+5-2)
  • (modified) libcxx/test/std/algorithms/alg.nonmodifying/alg.foreach/ranges.for_each_n.pass.cpp (+3-1)
  • (modified) libcxx/test/std/algorithms/alg.nonmodifying/alg.search/ranges.search.pass.cpp (+8-4)
  • (modified) libcxx/test/std/algorithms/alg.nonmodifying/alg.search/ranges.search_n.pass.cpp (+4-2)
  • (modified) libcxx/test/std/algorithms/alg.nonmodifying/alg.starts_with/ranges.starts_with.pass.cpp (+8-4)
  • (modified) libcxx/test/std/algorithms/alg.sorting/alg.partitions/ranges.is_partitioned.pass.cpp (+5-2)
  • (modified) libcxx/test/std/algorithms/alg.sorting/alg.sort/is.sorted/ranges.is_sorted.pass.cpp (+4-2)
  • (modified) libcxx/test/std/algorithms/alg.sorting/alg.sort/is.sorted/ranges.is_sorted_until.pass.cpp (+4-2)
  • (modified) libcxx/utils/libcxx/test/params.py (+1)
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.random.shuffle/random_shuffle.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.random.shuffle/random_shuffle.pass.cpp
index 087a498642881df..43932cc2696a467 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.random.shuffle/random_shuffle.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.random.shuffle/random_shuffle.pass.cpp
@@ -17,6 +17,7 @@
 // ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS
 
 #include <algorithm>
+#include <array>
 #include <cassert>
 
 #include "test_macros.h"
@@ -26,7 +27,8 @@ template <class Iter>
 void
 test_with_iterator()
 {
-    int empty[] = {};
+    std::array<int, 0> empty_arr = {};
+    int* const empty = empty_arr.data();
     std::random_shuffle(Iter(empty), Iter(empty));
 
     const int all_elements[] = {1, 2, 3, 4};
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.transform/ranges.transform.binary.iterator.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.transform/ranges.transform.binary.iterator.pass.cpp
index b604263e525d272..74e41293b9f155f 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.transform/ranges.transform.binary.iterator.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.transform/ranges.transform.binary.iterator.pass.cpp
@@ -89,7 +89,8 @@ constexpr bool test_iterators() {
   }
 
   { // first range empty
-    int a[] = {};
+    std::array<int, 0> a_arr = {};
+    int* const a = a_arr.data();
     int b[] = {5, 4, 3, 2, 1};
     int c[5];
 
@@ -103,7 +104,8 @@ constexpr bool test_iterators() {
 
   { // second range empty
     int a[] = {5, 4, 3, 2, 1};
-    int b[] = {};
+    std::array<int, 0> b_arr = {};
+    int* const b = b_arr.data();
     int c[5];
 
     auto ret = std::ranges::transform(
@@ -115,8 +117,10 @@ constexpr bool test_iterators() {
   }
 
   { // both ranges empty
-    int a[] = {};
-    int b[] = {};
+    std::array<int, 0> a_arr = {};
+    int* const a = a_arr.data();
+    std::array<int, 0> b_arr = {};
+    int* const b = b_arr.data();
     int c[5];
 
     auto ret = std::ranges::transform(
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.transform/ranges.transform.binary.range.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.transform/ranges.transform.binary.range.pass.cpp
index 08ca8aa3fd9ee24..feaeafa397c7b96 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.transform/ranges.transform.binary.range.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.transform/ranges.transform.binary.range.pass.cpp
@@ -92,7 +92,8 @@ constexpr bool test_iterators() {
   }
 
   { // first range empty
-    int a[] = {};
+    std::array<int, 0> a_arr = {};
+    int* const a = a_arr.data();
     int b[] = {5, 4, 3, 2, 1};
     int c[5];
 
@@ -108,7 +109,8 @@ constexpr bool test_iterators() {
 
   { // second range empty
     int a[] = {5, 4, 3, 2, 1};
-    int b[] = {};
+    std::array<int, 0> b_arr = {};
+    int* const b = b_arr.data();
     int c[5];
 
     auto range1 = std::ranges::subrange(In1(a), Sent1(In1(a + 5)));
@@ -122,8 +124,10 @@ constexpr bool test_iterators() {
   }
 
   { // both ranges empty
-    int a[] = {};
-    int b[] = {};
+    std::array<int, 0> a_arr = {};
+    int* const a = a_arr.data();
+    std::array<int, 0> b_arr = {};
+    int* const b = b_arr.data();
     int c[5];
 
     auto range1 = std::ranges::subrange(In1(a), Sent1(In1(a)));
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.transform/ranges.transform.unary.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.transform/ranges.transform.unary.pass.cpp
index eeacf83664cfeef..c2d59b4e402d6c4 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.transform/ranges.transform.unary.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.transform/ranges.transform.unary.pass.cpp
@@ -108,7 +108,8 @@ constexpr bool test_iterators() {
 
   { // first range empty
     {
-      int a[] = {};
+      std::array<int, 0> a_arr = {};
+      int* const a = a_arr.data();
       int b[5];
       auto ret = std::ranges::transform(In1(a), Sent1(In1(a)), Out(b), [](int i) { return i * 2; });
       assert(base(ret.in) == a);
@@ -116,7 +117,8 @@ constexpr bool test_iterators() {
     }
 
     {
-      int a[] = {};
+      std::array<int, 0> a_arr = {};
+      int* const a = a_arr.data();
       int b[5];
       auto range = std::ranges::subrange(In1(a), Sent1(In1(a)));
       auto ret = std::ranges::transform(range, Out(b), [](int i) { return i * 2; });
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.ends_with/ranges.ends_with.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.ends_with/ranges.ends_with.pass.cpp
index ce4dffffc4763a5..5fcb6c23dcd4a49 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.ends_with/ranges.ends_with.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.ends_with/ranges.ends_with.pass.cpp
@@ -156,7 +156,8 @@ constexpr void test_iterators() {
 
  { // suffix has zero length
    int a[] = {1, 2, 3, 4, 5, 6};
-   int p[] = {};
+   std::array<int, 0> p_arr = {};
+   int* const p = p_arr.data();
    auto whole = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
    auto suffix  = std::ranges::subrange(Iter2(p), Sent2(Iter2(p)));
    {
@@ -170,7 +171,8 @@ constexpr void test_iterators() {
  }
 
  { // range has zero length
-   int a[] = {};
+   std::array<int, 0> a_arr = {};
+   int* const a = a_arr.data();
    int p[] = {1, 2, 3, 4, 5, 6, 7, 8};
    auto whole = std::ranges::subrange(Iter1(a), Sent1(Iter1(a)));
    auto suffix  = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 8)));
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.equal/ranges.equal.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.equal/ranges.equal.pass.cpp
index 828f75ea11d358d..5e57cfa6094338d 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.equal/ranges.equal.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.equal/ranges.equal.pass.cpp
@@ -23,6 +23,7 @@
 //                                Proj1 proj1 = {}, Proj2 proj2 = {});
 
 #include <algorithm>
+#include <array>
 #include <cassert>
 #include <concepts>
 #include <functional>
@@ -200,14 +201,18 @@ constexpr void test_iterators() {
 
   { // check that two empty ranges work
     {
-      int a[] = {};
-      int b[] = {};
+      std::array<int, 0> a_arr = {};
+      int* const a = a_arr.data();
+      std::array<int, 0> b_arr = {};
+      int* const b = b_arr.data();
       auto ret = std::ranges::equal(Iter1(a), Sent1(Iter1(a)), Iter2(b), Sent2(Iter2(b)));
       assert(ret);
     }
     {
-      int a[] = {};
-      int b[] = {};
+      std::array<int, 0> a_arr = {};
+      int* const a = a_arr.data();
+      std::array<int, 0> b_arr = {};
+      int* const b = b_arr.data();
       auto range1 = std::ranges::subrange(Iter1(a), Sent1(Iter1(a)));
       auto range2 = std::ranges::subrange(Iter2(b), Sent2(Iter2(b)));
       auto ret = std::ranges::equal(range1, range2);
@@ -217,13 +222,15 @@ constexpr void test_iterators() {
 
   { // check that it works with the first range empty
     {
-      int a[] = {};
+      std::array<int, 0> a_arr = {};
+      int* const a = a_arr.data();
       int b[] = {1, 2};
       auto ret = std::ranges::equal(Iter1(a), Sent1(Iter1(a)), Iter2(b), Sent2(Iter2(b + 2)));
       assert(!ret);
     }
     {
-      int a[] = {};
+      std::array<int, 0> a_arr = {};
+      int* const a = a_arr.data();
       int b[] = {1, 2};
       auto range1 = std::ranges::subrange(Iter1(a), Sent1(Iter1(a)));
       auto range2 = std::ranges::subrange(Iter2(b), Sent2(Iter2(b + 2)));
@@ -235,13 +242,15 @@ constexpr void test_iterators() {
   { // check that it works with the second range empty
     {
       int a[] = {1, 2};
-      int b[] = {};
+      std::array<int, 0> b_arr = {};
+      int* const b = b_arr.data();
       auto ret = std::ranges::equal(Iter1(a), Sent1(Iter1(a + 2)), Iter2(b), Sent2(Iter2(b)));
       assert(!ret);
     }
     {
       int a[] = {1, 2};
-      int b[] = {};
+      std::array<int, 0> b_arr = {};
+      int* const b = b_arr.data();
       auto range1 = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 2)));
       auto range2 = std::ranges::subrange(Iter2(b), Sent2(Iter2(b)));
       auto ret = std::ranges::equal(range1, range2);
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.find.end/ranges.find_end.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.find.end/ranges.find_end.pass.cpp
index d826ff6ddf426b7..6753ea913a844c3 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.find.end/ranges.find_end.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.find.end/ranges.find_end.pass.cpp
@@ -182,14 +182,16 @@ constexpr void test_iterators() {
   { // pattern has zero length
     {
       int a[] = {6, 7, 8};
-      int p[] = {};
+      std::array<int, 0> p_arr = {};
+      int* const p = p_arr.data();
       auto ret = std::ranges::find_end(Iter1(a), Sent1(Iter1(a + 3)), Iter2(p), Sent2(Iter2(p)));
       assert(base(ret.begin()) == a + 3);
       assert(base(ret.end()) == a + 3);
     }
     {
       int a[] = {6, 7, 8};
-      int p[] = {};
+      std::array<int, 0> p_arr = {};
+      int* const p = p_arr.data();
       auto range1 = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 3)));
       auto range2 = std::ranges::subrange(Iter2(p), Sent2(Iter2(p)));
       auto ret = std::ranges::find_end(range1, range2);
@@ -200,14 +202,16 @@ constexpr void test_iterators() {
 
   { // range has zero length
     {
-      int a[] = {};
+      std::array<int, 0> a_arr = {};
+      int* const a = a_arr.data();
       int p[] = {6, 7, 8};
       auto ret = std::ranges::find_end(Iter1(a), Sent1(Iter1(a)), Iter2(p), Sent2(Iter2(p + 3)));
       assert(base(ret.begin()) == a);
       assert(base(ret.end()) == a);
     }
     {
-      int a[] = {};
+      std::array<int, 0> a_arr = {};
+      int* const a = a_arr.data();
       int p[] = {6, 7, 8};
       auto range1 = std::ranges::subrange(Iter1(a), Sent1(Iter1(a)));
       auto range2 = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 3)));
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.foreach/ranges.for_each.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.foreach/ranges.for_each.pass.cpp
index 52b91268edda6da..d2b02873b9677ea 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.foreach/ranges.for_each.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.foreach/ranges.for_each.pass.cpp
@@ -19,6 +19,7 @@
 //     ranges::for_each(R&& r, Fun f, Proj proj = {});
 
 #include <algorithm>
+#include <array>
 #include <ranges>
 
 #include "almost_satisfies_types.h"
@@ -98,11 +99,13 @@ constexpr void test_iterator() {
 
   { // check that an empty range works
     {
-      int a[] = {};
+      std::array<int, 0> a_arr = {};
+      int* const a = a_arr.data();
       std::ranges::for_each(Iter(a), Sent(Iter(a)), [](auto&) { assert(false); });
     }
     {
-      int a[] = {};
+      std::array<int, 0> a_arr = {};
+      int* const a = a_arr.data();
       auto range = std::ranges::subrange(Iter(a), Sent(Iter(a)));
       std::ranges::for_each(range, [](auto&) { assert(false); });
     }
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.foreach/ranges.for_each_n.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.foreach/ranges.for_each_n.pass.cpp
index 913819979ca1cda..2b54de303cd871a 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.foreach/ranges.for_each_n.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.foreach/ranges.for_each_n.pass.cpp
@@ -16,6 +16,7 @@
 //     ranges::for_each_n(I first, iter_difference_t<I> n, Fun f, Proj proj = {});
 
 #include <algorithm>
+#include <array>
 #include <ranges>
 
 #include "almost_satisfies_types.h"
@@ -58,7 +59,8 @@ constexpr void test_iterator() {
   }
 
   { // check that an empty range works
-    int a[] = {};
+    std::array<int, 0> a_arr = {};
+    int* const a = a_arr.data();
     std::ranges::for_each_n(Iter(a), 0, [](auto&) { assert(false); });
   }
 }
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/ranges.search.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/ranges.search.pass.cpp
index b35729962492b12..0152093d40ca781 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/ranges.search.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/ranges.search.pass.cpp
@@ -183,14 +183,16 @@ constexpr void test_iterators() {
   { // pattern has zero length
     {
       int a[] = {6, 7, 8};
-      int p[] = {};
+      std::array<int, 0> p_arr = {};
+      int* const p = p_arr.data();
       auto ret = std::ranges::search(Iter1(a), Sent1(Iter1(a + 3)), Iter2(p), Sent2(Iter2(p)));
       assert(base(ret.begin()) == a);
       assert(base(ret.end()) == a);
     }
     {
       int a[] = {6, 7, 8};
-      int p[] = {};
+      std::array<int, 0> p_arr = {};
+      int* const p = p_arr.data();
       auto range1 = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 3)));
       auto range2 = std::ranges::subrange(Iter2(p), Sent2(Iter2(p)));
       auto ret = std::ranges::search(range1, range2);
@@ -201,14 +203,16 @@ constexpr void test_iterators() {
 
   { // range has zero length
     {
-      int a[] = {};
+      std::array<int, 0> a_arr = {};
+      int* const a = a_arr.data();
       int p[] = {6, 7, 8};
       auto ret = std::ranges::search(Iter1(a), Sent1(Iter1(a)), Iter2(p), Sent2(Iter2(p + 3)));
       assert(base(ret.begin()) == a);
       assert(base(ret.end()) == a);
     }
     {
-      int a[] = {};
+      std::array<int, 0> a_arr = {};
+      int* const a = a_arr.data();
       int p[] = {6, 7, 8};
       auto range1 = std::ranges::subrange(Iter1(a), Sent1(Iter1(a)));
       auto range2 = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 3)));
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/ranges.search_n.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/ranges.search_n.pass.cpp
index feca3b276c9a5c5..dbab7088d28f4e3 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/ranges.search_n.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/ranges.search_n.pass.cpp
@@ -171,13 +171,15 @@ constexpr void test_iterators() {
 
   { // range has zero length
     {
-      int a[] = {};
+      std::array<int, 0> a_arr = {};
+      int* const a = a_arr.data();
       auto ret = std::ranges::search_n(Iter(a), Sent(Iter(a)), 1, 1);
       assert(base(ret.begin()) == a);
       assert(base(ret.end()) == a);
     }
     {
-      int a[] = {};
+      std::array<int, 0> a_arr = {};
+      int* const a = a_arr.data();
       auto range = std::ranges::subrange(Iter(a), Sent(Iter(a)));
       auto ret = std::ranges::search_n(range, 1, 1);
       assert(base(ret.begin()) == a);
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.starts_with/ranges.starts_with.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.starts_with/ranges.starts_with.pass.cpp
index 85c6bf96b2aa5df..86f476d75b2e6df 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.starts_with/ranges.starts_with.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.starts_with/ranges.starts_with.pass.cpp
@@ -136,14 +136,16 @@ constexpr void test_iterators() {
   { // prefix has zero length
     {
       int a[] = {1, 2, 3, 4, 5, 6};
-      int p[] = {};
+      std::array<int, 0> p_arr = {};
+      int* const p = p_arr.data();
       std::same_as<bool> decltype(auto) ret =
           std::ranges::starts_with(Iter1(a), Sent1(Iter1(a + 6)), Iter2(p), Sent2(Iter2(p)));
       assert(ret);
     }
     {
       int a[]                               = {1, 2, 3, 4, 5, 6};
-      int p[]                               = {};
+      std::array<int, 0> p_arr = {};
+      int* const p = p_arr.data();
       auto whole                            = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
       auto prefix                           = std::ranges::subrange(Iter2(p), Sent2(Iter2(p)));
       std::same_as<bool> decltype(auto) ret = std::ranges::starts_with(whole, prefix);
@@ -153,14 +155,16 @@ constexpr void test_iterators() {
 
   { // range has zero length
     {
-      int a[] = {};
+      std::array<int, 0> a_arr = {};
+      int* const a = a_arr.data();
       int p[] = {1, 2, 3, 4, 5, 6, 7, 8};
       std::same_as<bool> decltype(auto) ret =
           std::ranges::starts_with(Iter1(a), Sent1(Iter1(a)), Iter2(p), Sent2(Iter2(p + 8)));
       assert(!ret);
     }
     {
-      int a[]                               = {};
+      std::array<int, 0> a_arr = {};
+      int* const a = a_arr.data();
       int p[]                               = {1, 2, 3, 4, 5, 6, 7, 8};
       auto whole                            = std::ranges::subrange(Iter1(a), Sent1(Iter1(a)));
       auto prefix                           = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 8)));
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.partitions/ranges.is_partitioned.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.partitions/ranges.is_partitioned.pass.cpp
index 72b58f5534140bf..990ab0959a625f9 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.partitions/ranges.is_partitioned.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.partitions/ranges.is_partitioned.pass.cpp
@@ -19,6 +19,7 @@
 
 
 #include <algorithm>
+#include <array>
 #include <cassert>
 
 #include "almost_satisfies_types.h"
@@ -131,12 +132,14 @@ constexpr void test_iterators() {
 
   { // check that an empty range is partitioned
     {
-      int a[] = {};
+      std::array<int, 0> a_arr = {};
+      int* const a = a_arr.data();
       auto ret = std::ranges::is_partitioned(Iter(a), Sent(Iter(a)), [](int i) { return i < 3; });
       assert(ret);
     }
     {
-      int a[] = {};
+      std::array<int, 0> a_arr = {};
+      int* const a = a_arr.data();
       auto range = std::ranges::subrange(Iter(a), Sent(Iter(a)));
       auto ret = std::ranges::is_partitioned(range, [](int i) { return i < 3; });
       assert(ret);
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.sort/is.sorted/ranges.is_sorted.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.sort/is.sorted/ranges.is_sorted.pass.cpp
index b8831f76c58e535..5bc399d818b6a96 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.sort/is.sorted/ranges.is_sorted.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.sort/is.sorted/ranges.is_sorted.pass.cpp
@@ -109,12 +109,14 @@ constexpr void test_iterators() {
 
   { // check that an empty range works
     {
-      int a[] = {};
+      std::array<int, 0> a_arr = {};
+      int* const a = a_arr.data();
       auto ret = std::ranges::is_sorted(Iter(a), Sent(Iter(a)));
       assert(ret);
     }
     {
-      int a[] = {};
+      std::array<int, 0> a_arr = {};
+      int* const a = a_arr.data();
       auto range = std::ranges::subrange(Iter(a), Sent(Iter(a)));
       auto ret = std::ranges::is_sorted(range);
       assert(ret);
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.sort/is.sorted/ranges.is_sorted_until.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.sort/is.sorted/ranges.is_sorted_until.pass.cpp
index c5a0fe8831237a5..9348e63fb93a26b 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.sort/is.sorted/ranges.is_sorted_until.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.sort/is.sorted/ranges.is_sorted_until.pass.cpp
@@ -110,12 +110,14 @@ constexpr void test_iterators() {
 
   { // check that an empty range works
     {
-      int a[] = {};
+      std::array<int, 0> a_arr = {};
+      int* const a = a_arr.data();
       auto ret = std::ranges::is_sorted_until(Iter(a), Sent(Iter(a)));
       assert(base(ret) == a);
     }
     {
-      int a[] = {};
+      std::array<int, 0> a_arr = {};
+      int* const a = a_arr.data();
       auto range = std::ranges::subrange(Iter(a), Sent(Iter(a)));
       auto ret = std::ranges::is_sorted_until(range);
       assert(base(ret) == a);
diff --git a/libcxx/utils/libcxx/test/params.py b/libcxx/utils/libcxx/test/params.py
index 3fedbf972c0c822..ef532adc2cc02d8 100644
--- a/libcxx/utils/libcxx/test/params.py
+++ ...
[truncated]

Copy link

github-actions bot commented Dec 2, 2023

✅ With the latest revision this PR passed the C/C++ code formatter.

Copy link
Contributor

@philnik777 philnik777 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better to just replace the uses instead of doing the array/pointer dance. IMO that will just be confusing in the future.

@StephanTLavavej
Copy link
Member Author

@philnik777 Done, thanks!

@philnik777 philnik777 merged commit c000f75 into llvm:main Dec 3, 2023
@StephanTLavavej StephanTLavavej deleted the stl-12-absolute-zero branch December 3, 2023 09:49
philnik777 pushed a commit that referenced this pull request Jan 29, 2024
…ges.contains.pass.cpp` (#79792)

* Fix MSVC error C2466: cannot allocate an array of constant size 0
  + MSVC rejects this non-Standard extension. Previous fixes: #74183
* Fix MSVC warning C4805: `'=='`: unsafe mix of type `'int'` and type
`'const bool'` in operation
+ AFAICT, these lambdas were copy-pasted, and didn't intend to take and
return `int` here. This part of the test is using `vector<bool>` for
random-access but non-contiguous iterators, and it's checking how many
times the projection is invoked, but the projection doesn't need to do
anything squirrely, it should otherwise be an identity.
* Fix typos: "continuous" => "contiguous".
ldionne pushed a commit that referenced this pull request May 28, 2024
* Guard `std::__make_from_tuple_impl` tests with `#ifdef _LIBCPP_VERSION` and `LIBCPP_STATIC_ASSERT`.
* Change `_LIBCPP_CONSTEXPR_SINCE_CXX20` to `TEST_CONSTEXPR_CXX20`.
+ Other functions in `variant.swap/swap.pass.cpp` were already using the proper test macro.
* Mark `what` as `[[maybe_unused]]` when used by `TEST_LIBCPP_REQUIRE`.
  + This updates one occurrence in `libcxx/test/libcxx` for consistency.
* Windows `_putenv_s()` takes 2 arguments, not 3.
  + See MSVC documentation: https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/putenv-s-wputenv-s?view=msvc-170
+ POSIX `setenv()` takes `int overwrite`, but Windows `_putenv_s()` always overwrites.
* Avoid non-Standard zero-length arrays.
  + Followup to #74183 and #79792.
* Add `operator++()` to `unsized_it`.
+ The Standard requires this due to [N4981][] [move.iter.requirements]/1 "The template parameter `Iterator` shall
  either meet the *Cpp17InputIterator* requirements ([input.iterators])
  or model `input_iterator` ([iterator.concept.input])."
+ MSVC's STL requires this because it has a strengthened exception
  specification in `move_iterator` that inspects the underlying iterator's
  increment operator.
* `uniform_int_distribution` forbids `int8_t`/`uint8_t`.
  + See [N4981][] [rand.req.genl]/1.5. MSVC's STL enforces this.
+ Note that when changing the distribution's `IntType`, we need to be
  careful to preserve the original value range of `[0, max_input]`.
* fstreams are constructible from `const fs::path::value_type*` on wide systems.
  + See [ifstream.cons], [ofstream.cons], [fstream.cons].
* In `msvc_stdlib_force_include.h`, map `_HAS_CXX23` to `TEST_STD_VER` 23 instead of 99.
+ On 2023-05-23, 7140050
  started recognizing 23 as a distinct value.
* Fix test name typo: `destory_elements.pass.cpp` => `destroy_elements.pass.cpp`

[N4981]: https://wg21.link/N4981
vg0204 pushed a commit to vg0204/llvm-project that referenced this pull request May 29, 2024
* Guard `std::__make_from_tuple_impl` tests with `#ifdef _LIBCPP_VERSION` and `LIBCPP_STATIC_ASSERT`.
* Change `_LIBCPP_CONSTEXPR_SINCE_CXX20` to `TEST_CONSTEXPR_CXX20`.
+ Other functions in `variant.swap/swap.pass.cpp` were already using the proper test macro.
* Mark `what` as `[[maybe_unused]]` when used by `TEST_LIBCPP_REQUIRE`.
  + This updates one occurrence in `libcxx/test/libcxx` for consistency.
* Windows `_putenv_s()` takes 2 arguments, not 3.
  + See MSVC documentation: https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/putenv-s-wputenv-s?view=msvc-170
+ POSIX `setenv()` takes `int overwrite`, but Windows `_putenv_s()` always overwrites.
* Avoid non-Standard zero-length arrays.
  + Followup to llvm#74183 and llvm#79792.
* Add `operator++()` to `unsized_it`.
+ The Standard requires this due to [N4981][] [move.iter.requirements]/1 "The template parameter `Iterator` shall
  either meet the *Cpp17InputIterator* requirements ([input.iterators])
  or model `input_iterator` ([iterator.concept.input])."
+ MSVC's STL requires this because it has a strengthened exception
  specification in `move_iterator` that inspects the underlying iterator's
  increment operator.
* `uniform_int_distribution` forbids `int8_t`/`uint8_t`.
  + See [N4981][] [rand.req.genl]/1.5. MSVC's STL enforces this.
+ Note that when changing the distribution's `IntType`, we need to be
  careful to preserve the original value range of `[0, max_input]`.
* fstreams are constructible from `const fs::path::value_type*` on wide systems.
  + See [ifstream.cons], [ofstream.cons], [fstream.cons].
* In `msvc_stdlib_force_include.h`, map `_HAS_CXX23` to `TEST_STD_VER` 23 instead of 99.
+ On 2023-05-23, llvm@7140050
  started recognizing 23 as a distinct value.
* Fix test name typo: `destory_elements.pass.cpp` => `destroy_elements.pass.cpp`

[N4981]: https://wg21.link/N4981
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants