[llvm-bugs] [Bug 49450] New: [bit.pow.two] functions use wrong constraints for -funsigned-char

via llvm-bugs llvm-bugs at lists.llvm.org
Fri Mar 5 03:45:32 PST 2021


https://bugs.llvm.org/show_bug.cgi?id=49450

            Bug ID: 49450
           Summary: [bit.pow.two] functions use wrong constraints for
                    -funsigned-char
           Product: libc++
           Version: 11.0
          Hardware: All
                OS: All
            Status: NEW
          Severity: normal
          Priority: P
         Component: All Bugs
          Assignee: unassignedclangbugs at nondot.org
          Reporter: zilla at kayari.org
                CC: llvm-bugs at lists.llvm.org, mclow.lists at gmail.com

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.

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20210305/51cca1f3/attachment.html>


More information about the llvm-bugs mailing list