Skip to content

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]

@github-actions
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