Search code examples
c++gccclangcompiler-warnings

Why is the result type of a sum of two unsigned integers different in Clang and GCC


I am writing some low level code for my emulator which involves a lot of 16 and 8 bit unsigned integers. I enabled -Wconversion warning in my project and all warnings are considered as errors (-Werror).

Consider this code snippet:

#include <cstdint>

int main ()
{
    uint16_t a = 4;
    uint16_t b = 6;
    uint16_t c = a + b;
}

Until GCC 9.3 with -std=c++17 -Wconversion -Werror as compilation flags, gives the following error:

<source>: In function 'int main()':
<source>:7:20: error: conversion from 'int' to 'uint16_t' {aka 'short unsigned int'} may change value [-Werror=conversion]
    7 |     uint16_t c = a + b;

      |                  ~~^~~

But the same code does not give this error for GCC 10.1, and for any compiler version of Clang (Tested it until Clang 5.0.0). Link to compiler explorer.

So my questions are the following:

  • IMO, addition of two unsigned ints should not be implicitly converted to an int. Or is my assumption wrong?
  • Why Clang and GCC(until 9.3) produce different results? Does the standard stipulate any constraints on this operation or is it up to the compiler vendor to decide?
  • What changed in GCC 10.1? Why is this error not popping up for GCC 10.1?

Solution

  • IMO, addition of two unsigned ints should not be implicitly converted to an int. Or is my assumption wrong?

    This assumption is not wrong. Unsigned int is never implicitly converted to int.

    However on your system, uint16_t happens to be unsigned short int. Assuming that unsigned short ints aren't implicitly converted to int is a wrong assumption. They are promoted to int on most systems.

    There was recently a good question about why the promotion is to signed int: https://stackoverflow.com/a/62042330/2079303

    Why Clang and GCC(until 9.3) produce different results?

    They don't. Both will promote to int. One simply didn't warn about the conversion. The conversion isn't ill-formed so there is no requirement to issue a diagnostic.

    or is it up to the compiler vendor to decide?

    Diagnostic messages are up to the compiler vendor's discretion(, except that a diagnostic message is required when program is ill-formed, unless otherwise specified).

    What changed in GCC 10.1? Why is this error not popping up for GCC 10.1?

    Perhaps they decided that the warning isn't useful in this case, and got rid of it.