Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a GCC warning that detects bit shift operations on signed types?

If I read the C++ ISO specification (sections 5.8.2 and 5.8.3) right, the right-shift of negative signed types is implementation specific and the left-shift undefined behaviour.

Therefore I would like to find shift operations on signed types in our legacy source code which we compile with g++ 4.8.2.

Unfortunately, I couldn't find such an option in the manual. I can for example compile this code with "g++ -Wall -Wextra -pedantic" without a warning:

int si    = -1;
int left  = si << 1; // -2 (multiplication by 2, sign is preserved)
int right = si >> 1; // -1 (no change, only 1s)

Can anyone tell me if there is such a warning and, if not, why gcc doesn't care about it?

like image 676
man.in.the.middle Avatar asked Jul 31 '14 09:07

man.in.the.middle


People also ask

How do I enable warnings in GCC?

To enable all warnings, use following list of warnings (probably some warnings are duplicated, because I didn't bother to filter warnings enabled by -Wall ). Show activity on this post. Someone has created a set of tools for determining the complete set of warnings for a given GCC or Clang version.

Which option of GCC inhibit all warning messages?

If -Wfatal-errors is also specified, then -Wfatal-errors takes precedence over this option. Inhibit all warning messages. Make all warnings into errors.

Which option can be used to display compiler warnings?

You can use a #pragma warning directive to control the level of warning that's reported at compile time in specific source files. Warning pragma directives in source code are unaffected by the /w option.

What is bit shifting operations?

Bit shifting is an operation done on all the bits of a binary value in which they are moved by a determined number of places to either the left or right. Bit shifting is used when the operand is being used as a series of bits rather than as a whole.


1 Answers

AFAIK gcc doesn't provide such an option. The standard, as you cited, says:

N3690 - §5.8.3

The value of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a non-negative value, the value of the result is the integral part of the quotient of E1/2E2. If E1 has a signed type and a negative value, the resulting value is implementation-defined.

and that means doing

int si    = -1;
int right = si >> 1;

might or might not yield -1 as a result. It's implementation defined. And that means the compiler is not forced to yield a warning like "other compilers might do this another way".

Some of the reasons for this choice follow.

The original K&R passage says:

"Right shifting an unsigned quantity, fills vacated bits with 0. Right shifting a signed quantity will fill with sign bits (arithmetic shift) on some machines such as the PDP-11, and with 0 bits (logical shift) on others."

this means that the operation is architecture-dependent. The reason behind this is that some architectures are fast in doing one of the two but not both.

This reason plus the fact that the usefulness of sign-extended shifts is marginal made the standard take the choice of leaving it "implementation defined". By "usefulness of sign-extended shifts" I mean that right shifting a negative signed integer arithmetically does not work as the positive counterpart (because losing a 1 on the right makes the negative number smaller, i.e. bigger in modulus)

+63 >> 1 = +31 (integral part of quotient E1/2E2)
00111111 >> 1 = 00011111
-63 >> 1 = -32 
11000001 >> 1 = 11100000

References for further reading:

https://stackoverflow.com/a/1857965/1938163

http://www.ccsinfo.com/forum/viewtopic.php?t=45711

https://isocpp.org/std/the-standard


Edit: if the above doesn't address the issue (i.e. the code is valid, why should a compiler warn about that?) I'm providing a second solution: AST matchers

As described here: http://eli.thegreenplace.net/2014/07/29/ast-matchers-and-clang-refactoring-tools/ you can write some code to identify quickly all the right-shifts-with-signed-integers spots in your program.

Think of it as "writing my small one-task static analysis checker".


Edit 2: you might also try other static-analysis tools, clang has a -fsanitize=shift option which could work for you. AFAIK also for gcc they were implementing an undefined behavior sanitizer which could help diagnosing those errors. I've not been following the story but I guess you could give it a try as well.

like image 118
Marco A. Avatar answered Sep 27 '22 23:09

Marco A.