-2

I have a piece of code which assigns an 8-bit unsigned int (std::uint8_t) to a 32-bit unsigned int (std::uint32_t):

std::uint32_t a{0};
std::uint8_t b{1};

a = b << 16;

When I try to compile this with -Werror -Wsign-conversion -fsanitize=undefined, it fails with a sign-conversion error:

<source>:9:11: error: conversion to 'uint32_t' {aka 'unsigned int'} from 'int' may change the sign of the result [-Werror=sign-conversion]

Why is this? What is being promoted to int?

https://godbolt.org/z/j6or6dsGG

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
jjcasmar
  • 1,387
  • 1
  • 18
  • 30
  • 4
    Well, everything with rank below `int` is always promoted before _any_ arithmetic. – user17732522 Aug 03 '23 at 14:24
  • I fixed the code in the question. The error come directly from the godbolt MRE – jjcasmar Aug 03 '23 at 14:27
  • 1
    Swap `b` with `static_cast(b)` in the last statement. Promotion is stopping at `int`, which is the step that "works", but with a warning. You need to explicitly ask to promote further. – Brian61354270 Aug 03 '23 at 14:31
  • 1
    The compiler warning is a false positive on all major platforms (and the compiler should know what platform it's targeting). There's no value of `b` that will result in a negative intermediate result during `a = b << 16;`. For 16-bit `int`, that's an undefined shift. For 32-bit `int`, the intermediate value is always positive and exactly representable in the destination type. For "24-bit `int`" you would have a problem but has anyone ever seen one of these? – Ben Voigt Aug 03 '23 at 14:44
  • 2
    @Brian61354270: Never use a `static_cast` when an implicit widening conversion is available. Here the better (and shorter and simpler) code would be `a = b; a <<= 16;` – Ben Voigt Aug 03 '23 at 14:45

0 Answers0