diff mbox

Clarify that -fwrapv covers all signed arithmetic overflow

Message ID 1447763566-2529-1-git-send-email-bonzini@gnu.org
State New
Headers show

Commit Message

Paolo Bonzini Nov. 17, 2015, 12:32 p.m. UTC
GCC's -fwrapv option does not affect code generation for shifts
because currently GCC does not rely on the fact that certain
signed shifts trigger undefined behavior.  However, the definition
of signed arithmetic overflow does extend to shifts; it is only
code generation that is limited to addition, subtraction and
multiplication.

Make the documentation of -fwrapv consistent with the existing
text under -fstrict-overflow ("Using '-fwrapv' means that integer
signed overflow is fully defined: it wraps.").

Ok for trunk and the branches?

Paolo

* doc/invoke.texi (Optimize Options): Clarify the effect of -fwrapv.

Comments

Joseph Myers Nov. 17, 2015, 12:58 p.m. UTC | #1
On Tue, 17 Nov 2015, Paolo Bonzini wrote:

> GCC's -fwrapv option does not affect code generation for shifts
> because currently GCC does not rely on the fact that certain
> signed shifts trigger undefined behavior.  However, the definition
> of signed arithmetic overflow does extend to shifts; it is only
> code generation that is limited to addition, subtraction and
> multiplication.

It is part of the GNU C language, independent of -fwrapv, that shifts 
where the shift amount is in the range [0, width - 1] are fully defined 
(although ubsan will still sanitize those not defined in ISO C) - they are 
considered to be defined in terms of bits, not integers, so overflow is 
not a meaningful concept for them.

-fwrapv *should* however affect division and modulo -1, although it 
doesn't at present (see bug 30484).
Paolo Bonzini Nov. 17, 2015, 1:12 p.m. UTC | #2
On 17/11/2015 13:58, Joseph Myers wrote:
>> > GCC's -fwrapv option does not affect code generation for shifts
>> > because currently GCC does not rely on the fact that certain
>> > signed shifts trigger undefined behavior.  However, the definition
>> > of signed arithmetic overflow does extend to shifts; it is only
>> > code generation that is limited to addition, subtraction and
>> > multiplication.
> It is part of the GNU C language, independent of -fwrapv, that shifts 
> where the shift amount is in the range [0, width - 1] are fully defined 
> (although ubsan will still sanitize those not defined in ISO C)

-fwrapv should probably disable those checks, just like it disables e.g.
"signed integer overflow: 1 + 2147483647 cannot be represented in type
'int'".

> - they are 
> considered to be defined in terms of bits, not integers, so overflow is 
> not a meaningful concept for them.

Can you suggest a wording for "if the GNU C language definition changes
[which, no matter how unlikely, is explicitly not ruled out by the
manual] -fwrapv will be extended to signed shifts, and shifts of
negative numbers would return A*2^B whenever the result fits in the type"?

Paolo

> -fwrapv *should* however affect division and modulo -1, although it 
> doesn't at present (see bug 30484).
Joseph Myers Nov. 17, 2015, 3:27 p.m. UTC | #3
On Tue, 17 Nov 2015, Paolo Bonzini wrote:

> Can you suggest a wording for "if the GNU C language definition changes
> [which, no matter how unlikely, is explicitly not ruled out by the
> manual] -fwrapv will be extended to signed shifts, and shifts of
> negative numbers would return A*2^B whenever the result fits in the type"?

I don't think we can usefully say how a hypothetical change in one area 
would or would not affect a particular option.
Paolo Bonzini Nov. 17, 2015, 3:50 p.m. UTC | #4
On 17/11/2015 16:27, Joseph Myers wrote:
> > Can you suggest a wording for "if the GNU C language definition changes
> > [which, no matter how unlikely, is explicitly not ruled out by the
> > manual] -fwrapv will be extended to signed shifts, and shifts of
> > negative numbers would return A*2^B whenever the result fits in the type"?
>
> I don't think we can usefully say how a hypothetical change in one area 
> would or would not affect a particular option.

I agree.  That is why I phrased my original patch in the other way,
assuming that overflow _can_ be defined for signed left shifts but it is
not treated as undefined.  My definition of overflow for signed left
shifts would be shifting a 1 into or out of the sign bit.

However, I understood that you don't want to define overflow of signed
left shifts.

The reason why I am proposing this patch is that the current
documentation has a sort of catch-22:

* it doesn't promise that GCC will never rely on undefined behavior
rules for signed left shifts

* it says that -fwrapv affects add/sub/mult

This means that GCC has no future-proof option for projects that wish to
rely on definedness of signed left shifts.

In fact, as you mentioned, ubsan _already_ provides a case where GCC
does not treat left shift as an operation on the bit representation.
This makes it even more important to define such an option _now_ and to
make ubsan respect it (for which I've also sent an RFC patch earlier today).

Paolo
Joseph Myers Nov. 17, 2015, 4:02 p.m. UTC | #5
On Tue, 17 Nov 2015, Paolo Bonzini wrote:

> * it doesn't promise that GCC will never rely on undefined behavior
> rules for signed left shifts

I think we should remove the ", but this is subject to change" in 
implement-c.texi (while replacing it with noting that ubsan will still 
diagnose such cases, and they will also be diagnosed where constant 
expressions are required).
Paolo Bonzini Nov. 17, 2015, 5:07 p.m. UTC | #6
On 17/11/2015 17:02, Joseph Myers wrote:
> On Tue, 17 Nov 2015, Paolo Bonzini wrote:
> 
>> * it doesn't promise that GCC will never rely on undefined behavior
>> rules for signed left shifts
> 
> I think we should remove the ", but this is subject to change" in 
> implement-c.texi (while replacing it with noting that ubsan will still 
> diagnose such cases, and they will also be diagnosed where constant 
> expressions are required).

That's great.  I'll send a patch.

Paolo
Paolo Bonzini Nov. 17, 2015, 5:11 p.m. UTC | #7
On 17/11/2015 17:02, Joseph Myers wrote:
> On Tue, 17 Nov 2015, Paolo Bonzini wrote:
> 
>> * it doesn't promise that GCC will never rely on undefined behavior
>> rules for signed left shifts
> 
> I think we should remove the ", but this is subject to change" in 
> implement-c.texi (while replacing it with noting that ubsan will still 
> diagnose such cases, and they will also be diagnosed where constant 
> expressions are required).

... hmm, are you sure?  None of the following warn for me

int x = -1 << 2;
int y = 1 << 31;
int z = 2 << 31;

I tried with any combination of -ansi, -pedantic, -std=cXX,
-fsanitize=undefined.

Paolo
Joseph Myers Nov. 17, 2015, 5:21 p.m. UTC | #8
On Tue, 17 Nov 2015, Paolo Bonzini wrote:

> On 17/11/2015 17:02, Joseph Myers wrote:
> > On Tue, 17 Nov 2015, Paolo Bonzini wrote:
> > 
> >> * it doesn't promise that GCC will never rely on undefined behavior
> >> rules for signed left shifts
> > 
> > I think we should remove the ", but this is subject to change" in 
> > implement-c.texi (while replacing it with noting that ubsan will still 
> > diagnose such cases, and they will also be diagnosed where constant 
> > expressions are required).
> 
> ... hmm, are you sure?  None of the following warn for me
> 
> int x = -1 << 2;
> int y = 1 << 31;
> int z = 2 << 31;
> 
> I tried with any combination of -ansi, -pedantic, -std=cXX,
> -fsanitize=undefined.

With a recent trunk build I get:

$ ./build/gcc/xgcc -B./build/gcc/ -S -o /dev/null -pedantic -std=c11 t.c 
t.c:1:9: warning: initializer element is not a constant expression [-Wpedantic]
 int x = -1 << 2;
         ^

t.c:2:9: warning: initializer element is not a constant expression [-Wpedantic]
 int y = 1 << 31;
         ^

t.c:3:11: warning: result of '2 << 31' requires 34 bits to represent, but 'int' only has 32 bits [-Wshift-overflow=]
 int z = 2 << 31;
           ^

t.c:3:9: warning: initializer element is not a constant expression [-Wpedantic]
 int z = 2 << 31;
         ^

(and -pedantic-errors produces errors for the "not a constant expression" 
cases, as expected).
diff mbox

Patch

Index: doc/invoke.texi
===================================================================
--- doc/invoke.texi	(revision 227511)
+++ doc/invoke.texi	(working copy)
@@ -23705,9 +23705,10 @@ 
 @item -fwrapv
 @opindex fwrapv
 This option instructs the compiler to assume that signed arithmetic
-overflow of addition, subtraction and multiplication wraps around
-using twos-complement representation.  This flag enables some optimizations
-and disables others.  This option is enabled by default for the Java
+overflow wraps around using twos-complement representation.
+This flag affects code generation for addition, subtraction
+and multiplication, enabling some optimizations
+and disabling others.  This option is enabled by default for the Java
 front end, as required by the Java language specification.
 The options @option{-ftrapv} and @option{-fwrapv} override each other, so using
 @option{-ftrapv} @option{-fwrapv} on the command-line results in