简体   繁体   中英

gcc size_t and sizeof arithmetic conversion to int

I decided to test compile a project with -Wsign-conversion enabled, to see what warnings would come up, and came across something that doesn't seem right, where gcc behaves differently than clang. Can someone please tell me which is correct?

I have a function that takes a size_t param:

void func(size_t) {}

some other struct

struct Test {};

and calling code

int i = some_initialiser();
func(sizeof(Test) + static_cast<size_t>(i));

So from my understanding, sizeof returns size_t , and arithmetic between two variables of type size_t should return a size_t , so there shouldn't be any conversion here other than my static_cast , but gcc gives me the warning

 warning: conversion to ‘long unsigned int’ from ‘int’ may change the sign of the result [-Wsign-conversion]

Clang doesn't warn here, but does warn if I remove the static_cast in the function call, as expected.

This is a known bug in gcc, fixed in versions 9.3.0 and above.

The warning is valid (compilers can warn about anything they like), but gcc's behavior contradicts its own documentation. There is an existing bug report for this problem (see below).

Here's a simpler test case that illustrates the issue:

#include <cstddef>
int main() {
    int i = 42;
    size_t s0 = sizeof (int) + (size_t)i;
    size_t s1 = sizeof (int) + static_cast<size_t>(i);
}

When I compile it on my system using gcc 9.1.0, I get:

$ g++ -Wsign-conversion -c c.cpp
c.cpp: In function ‘int main()’:
c.cpp:4:32: warning: conversion to ‘long unsigned int’ from ‘int’ may change the sign of the result [-Wsign-conversion]
    4 |     size_t s0 = sizeof (int) + (size_t)i;
      |                                ^~~~~~~~~
c.cpp:5:32: warning: conversion to ‘long unsigned int’ from ‘int’ may change the sign of the result [-Wsign-conversion]
    5 |     size_t s1 = sizeof (int) + static_cast<size_t>(i);
      |                                ^~~~~~~~~~~~~~~~~~~~~~
$ 

Note that the warning occurs both for a C-style cast and for a static_cast .

It's true that the conversion may change the sign of the result (converting a negative int to size_t yields a positive result), but gcc's documentation for -Wsign-conversion says:

'-Wsign-conversion'
     Warn for implicit conversions that may change the sign of an
     integer value, like assigning a signed integer expression to an
     unsigned integer variable.  An explicit cast silences the warning.
     In C, this option is enabled also by '-Wconversion'.

In this case, an explicit cast is not silencing the warning.

This bug had already been reported:
Bug 87519 - -Wsign-conversion -Wconversion explicit cast fails to silence warning

The fix is commit 61e52125c935279af11b10d27060a96bff7477a4 in the gcc git repo, committed 2019-08-08.

The warning is correct.

If i has a negative value the casting will be problematic. Your function should return an unsigned value (eg unsigned int).

From GCC documentation - https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html :

For C++, also warn for confusing overload resolution for user-defined conversions; and conversions that never use a type conversion operator: conversions to void , the same type, a base class or a reference to them. Warnings about conversions between signed and unsigned integers are disabled by default in C++ unless -Wsign-conversion is explicitly enabled.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM