<html>
    <head>
      <base href="https://bugs.llvm.org/">
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - [bit.pow.two] functions use wrong constraints for -funsigned-char"
   href="https://bugs.llvm.org/show_bug.cgi?id=49450">49450</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>[bit.pow.two] functions use wrong constraints for -funsigned-char
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>libc++
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>11.0
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>All
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>All
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>All Bugs
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedclangbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>zilla@kayari.org
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org, mclow.lists@gmail.com
          </td>
        </tr></table>
      <p>
        <div>
        <pre>This C++20 program is ill-formed, because the "Integral powers of 2" functions
in <bit> are all constrained to only work for the unsigned integer types (as
defined in [basic.types] p2).

#include <bit>
static_assert( std::popcount('0')  == 0 );

On targets where char is signed, it fails as expected:

bit.C:2:16: error: no matching function for call to 'popcount'
static_assert( std::popcount('0')  == 0 );
               ^~~~~~~~~~~~~
/usr/bin/../include/c++/v1/bit:417:1: note: candidate template ignored:
requirement 'integral_constant<bool, false>::value' was not satisfied [with _Tp
= char]
popcount(_Tp __t) noexcept
^
1 error generated.


But on Aarch64 (or any target using -funsigned-char) the call to popcount
compiles:

bit.C:2:1: error: static_assert failed due to requirement 'std::popcount('0')
== 0'
static_assert( std::popcount('0')  == 0 );
^              ~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.

The problem is in the __bitop_unsigned_integer constraint, fixed by this patch:

diff --git a/libcxx/include/bit b/libcxx/include/bit
index f8c37c3d6bbf..21b9dcafdb37 100644
--- a/libcxx/include/bit
+++ b/libcxx/include/bit
@@ -83,7 +83,7 @@ using __bitop_unsigned_integer _LIBCPP_NODEBUG_TYPE =
integral_constant<bool,
          is_integral<_Tp>::value &&
          is_unsigned<_Tp>::value &&
         _IsNotSame<typename remove_cv<_Tp>::type, bool>::value &&
-        _IsNotSame<typename remove_cv<_Tp>::type, signed char>::value &&
+        _IsNotSame<typename remove_cv<_Tp>::type, char>::value &&
         _IsNotSame<typename remove_cv<_Tp>::type, wchar_t>::value &&
         _IsNotSame<typename remove_cv<_Tp>::type, char16_t>::value &&
         _IsNotSame<typename remove_cv<_Tp>::type, char32_t>::value

There's no need to exclude signed char, because is_unsigned<_Tp> already did
that. But you do need to exclude plain char, because is_integral<char> is true
and is_unsigned<char> is sometimes true, but char is not an unsigned integer
type.</pre>
        </div>
      </p>


      <hr>
      <span>You are receiving this mail because:</span>

      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>