[libc++][NFC] Add __element_count and use it in the constexpr C functions

This makes it less ambiguous what the parameter is meant to get.

Reviewed By: #libc, ldionne

Spies: ldionne, libcxx-commits

Differential Revision: https://reviews.llvm.org/D152040

GitOrigin-RevId: 355f4667446bf3ef38d3b52485b64d1a71a47507
diff --git a/include/__algorithm/equal.h b/include/__algorithm/equal.h
index c07d4e2..b69aeff 100644
--- a/include/__algorithm/equal.h
+++ b/include/__algorithm/equal.h
@@ -50,7 +50,7 @@
                   int> = 0>
 _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
 __equal_iter_impl(_Tp* __first1, _Tp* __last1, _Up* __first2, _BinaryPredicate&) {
-  return std::__constexpr_memcmp_equal(__first1, __first2, (__last1 - __first1) * sizeof(_Tp));
+  return std::__constexpr_memcmp_equal(__first1, __first2, __element_count(__last1 - __first1));
 }
 
 template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate>
@@ -100,7 +100,7 @@
                         int> = 0>
 _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal_impl(
     _Tp* __first1, _Tp* __last1, _Up* __first2, _Up*, _Pred&, _Proj1&, _Proj2&) {
-  return std::__constexpr_memcmp_equal(__first1, __first2, (__last1 - __first1) * sizeof(_Tp));
+  return std::__constexpr_memcmp_equal(__first1, __first2, __element_count(__last1 - __first1));
 }
 
 template <class _BinaryPredicate, class _RandomAccessIterator1, class _RandomAccessIterator2>
diff --git a/include/__string/char_traits.h b/include/__string/char_traits.h
index 61975cc..5c441df 100644
--- a/include/__string/char_traits.h
+++ b/include/__string/char_traits.h
@@ -373,7 +373,7 @@
 
   static _LIBCPP_HIDE_FROM_ABI constexpr int
   compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
-      return std::__constexpr_memcmp(__s1, __s2, __n);
+      return std::__constexpr_memcmp(__s1, __s2, __element_count(__n));
   }
 
     static _LIBCPP_HIDE_FROM_ABI constexpr
diff --git a/include/__string/constexpr_c_functions.h b/include/__string/constexpr_c_functions.h
index 9a768cf..13084e6 100644
--- a/include/__string/constexpr_c_functions.h
+++ b/include/__string/constexpr_c_functions.h
@@ -23,6 +23,10 @@
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
+// Type used to encode that a function takes an integer that represents a number
+// of elements as opposed to a number of bytes.
+enum class __element_count : size_t {};
+
 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 size_t __constexpr_strlen(const char* __str) {
   // GCC currently doesn't support __builtin_strlen for heap-allocated memory during constant evaluation.
   // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70816
@@ -42,14 +46,16 @@
 // of invoking it on every object individually.
 template <class _Tp, class _Up>
 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 int
-__constexpr_memcmp(const _Tp* __lhs, const _Up* __rhs, size_t __count) {
+__constexpr_memcmp(const _Tp* __lhs, const _Up* __rhs, __element_count __n) {
   static_assert(__libcpp_is_trivially_lexicographically_comparable<_Tp, _Up>::value,
                 "_Tp and _Up have to be trivially lexicographically comparable");
 
+  auto __count = static_cast<size_t>(__n);
+
   if (__libcpp_is_constant_evaluated()) {
 #ifdef _LIBCPP_COMPILER_CLANG_BASED
     if (sizeof(_Tp) == 1 && !is_same<_Tp, bool>::value)
-      return __builtin_memcmp(__lhs, __rhs, __count);
+      return __builtin_memcmp(__lhs, __rhs, __count * sizeof(_Tp));
 #endif
 
     while (__count != 0) {
@@ -58,13 +64,13 @@
       if (*__rhs < *__lhs)
         return 1;
 
-      __count -= sizeof(_Tp);
+      --__count;
       ++__lhs;
       ++__rhs;
     }
     return 0;
   } else {
-    return __builtin_memcmp(__lhs, __rhs, __count);
+    return __builtin_memcmp(__lhs, __rhs, __count * sizeof(_Tp));
   }
 }
 
@@ -73,26 +79,28 @@
 // of invoking it on every object individually.
 template <class _Tp, class _Up>
 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
-__constexpr_memcmp_equal(const _Tp* __lhs, const _Up* __rhs, size_t __count) {
+__constexpr_memcmp_equal(const _Tp* __lhs, const _Up* __rhs, __element_count __n) {
   static_assert(__libcpp_is_trivially_equality_comparable<_Tp, _Up>::value,
                 "_Tp and _Up have to be trivially equality comparable");
 
+  auto __count = static_cast<size_t>(__n);
+
   if (__libcpp_is_constant_evaluated()) {
 #ifdef _LIBCPP_COMPILER_CLANG_BASED
     if (sizeof(_Tp) == 1 && is_integral<_Tp>::value && !is_same<_Tp, bool>::value)
-      return __builtin_memcmp(__lhs, __rhs, __count) == 0;
+      return __builtin_memcmp(__lhs, __rhs, __count * sizeof(_Tp)) == 0;
 #endif
     while (__count != 0) {
       if (*__lhs != *__rhs)
         return false;
 
-      __count -= sizeof(_Tp);
+      --__count;
       ++__lhs;
       ++__rhs;
     }
     return true;
   } else {
-    return __builtin_memcmp(__lhs, __rhs, __count) == 0;
+    return __builtin_memcmp(__lhs, __rhs, __count * sizeof(_Tp)) == 0;
   }
 }
 
diff --git a/test/libcxx/strings/c.strings/constexpr.cstring.compile.pass.cpp b/test/libcxx/strings/c.strings/constexpr.cstring.compile.pass.cpp
index 9c941dd..0739e75 100644
--- a/test/libcxx/strings/c.strings/constexpr.cstring.compile.pass.cpp
+++ b/test/libcxx/strings/c.strings/constexpr.cstring.compile.pass.cpp
@@ -19,12 +19,12 @@
 constexpr unsigned char Bananf[] = "Bananf";
 
 static_assert(std::__constexpr_strlen("Banane") == 6, "");
-static_assert(std::__constexpr_memcmp(Banane, Banand, 6) == 1, "");
-static_assert(std::__constexpr_memcmp(Banane, Banane, 6) == 0, "");
-static_assert(std::__constexpr_memcmp(Banane, Bananf, 6) == -1, "");
+static_assert(std::__constexpr_memcmp(Banane, Banand, std::__element_count(6)) == 1, "");
+static_assert(std::__constexpr_memcmp(Banane, Banane, std::__element_count(6)) == 0, "");
+static_assert(std::__constexpr_memcmp(Banane, Bananf, std::__element_count(6)) == -1, "");
 
-static_assert(!std::__constexpr_memcmp_equal(Banane, Banand, 6), "");
-static_assert(std::__constexpr_memcmp_equal(Banane, Banane, 6), "");
+static_assert(!std::__constexpr_memcmp_equal(Banane, Banand, std::__element_count(6)), "");
+static_assert(std::__constexpr_memcmp_equal(Banane, Banane, std::__element_count(6)), "");
 
 
 constexpr bool test_constexpr_wmemchr() {