https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97798

--- Comment #6 from Jonathan Wakely <redi at gcc dot gnu.org> ---
I think the reduction is not a fair representation of the original code.
Obviously shifting by -1 is not OK, but the code doesn't do that ... at least
not for most targets.

The problem is specific to msp430 because of it's 20-bit type:


  template<typename _Value>
    struct __numeric_traits_integer
    {
      static const int is_signed = ((_Value)-1 < 0);
      static const int digits = sizeof(_Value) * __CHAR_BIT__ - is_signed;

      static const _Value __max = (is_signed ? (((((_Value)1 << (digits - 1)) -
1) << 1) + 1) : ~(_Value)0);
    };

static_assert( sizeof(__int20) == 4 ); // uhoh
static_assert( __numeric_traits_integer<__int20>::digits == 31 ); // uhoh

static_assert( __numeric_traits_integer<__int20>::__max < __INT_MAX__ );


The expression initializing __max works fine on 32-bit and 64-bit targets, but
for __int20 it's wrong. sizeof(__int20) is 4 (as shown by the static assert
that passes) and so we determine digits as 31, but it should be 19 for this
type.

The code assumes that all bits in the object representation are part of the
value representation, which is wrong for __int20.

The code above produced this warning with GCC 10.0 (the last time I built
msp430):

num.C: In instantiation of ‘const __int20
__numeric_traits_integer<__int20>::__max’:
num.C:13:51:   required from here
num.C:7:62: warning: left shift count >= width of type [-Wshift-count-overflow]
    7 |       static const _Value __max = (is_signed ? (((((_Value)1 << (digits
- 1)) - 1) << 1) + 1) : ~(_Value)0);
      |                                                  
~~~~~~~~~~~^~~~~~~~~~~~~~~~
num.C:7:62: error: right operand of shift expression ‘(1 << 30)’ is greater
than or equal to the precision 20 of the left operand [-fpermissive]
num.C:13:57: error: non-constant condition for static assertion
   13 | static_assert( __numeric_traits_integer<__int20>::__max < __INT_MAX__
);
      |                                                         ^


Presumably the shift is now an error rather than a warning, because it occurs
in a constant expression.

Maybe the right solution is for the library to specialize the trait for
__int20.

Reply via email to