Bug 98151 - integer output gives different results with -O2 and -O3
Summary: integer output gives different results with -O2 and -O3
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 10.2.1
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
Depends on:
Reported: 2020-12-05 03:11 UTC by Brad Bell
Modified: 2020-12-05 14:50 UTC (History)
1 user (show)

See Also:
Known to work:
Known to fail:
Last reconfirmed: 2020-12-05 00:00:00

bash shell script that creates the souce code, compiles, and runs the test (759 bytes, application/x-shellscript)
2020-12-05 03:11 UTC, Brad Bell

Note You need to log in before you can comment on or make changes to this bug.
Description Brad Bell 2020-12-05 03:11:33 UTC
Created attachment 49688 [details]
bash shell script that creates the souce code, compiles, and runs the test

The attached bash script creates a c++ file called int_output.cpp, then compiles and runs the program. If you run the script with no arguments you will get the following usage message:

    usage: ./int_output.sh print optimize
    print:    is either 0 or 1
    optimize: is -O2 or -O3

    If print is 0 and optimize is -O3, the test will fail.
    Otherwise, the test will pass

The program starts with the maximum integer, uses a stringstream to convert it to a string, and then converts it back to an integer. It then checks that the result is the maximum integer; i.e., the integer it started with.

If print is 0 (1) the value of the starting and ending integers are printed.
The optimize argument determines the optimization level during the g++ compliation.

The only case that fails is when print is 0 and optimize is -O3.
In addition, if one uses clang++, instead of g++, all the cases give the correct result.
Comment 1 Andrew Pinski 2020-12-05 03:18:39 UTC
I think you have an signed integer overflow happening.
Take a look at:
10 * result + s[index++] - '0'
To avoid the overflow, do instead:
10 * result + (s[index++] - '0')
Comment 2 Brad Bell 2020-12-05 04:07:05 UTC
That fixed my test result.
Sorry I missed that.

Comment 3 Jakub Jelinek 2020-12-05 09:21:54 UTC
There is another UB in it, if you try to parse the INT_MIN value there is another signed integer overflow, because 0x80000000 is not representable in int, while -0x7fffffff-1 is.
Better to compute the result in unsigned type and only at the end cast to int.
Comment 4 Jonathan Wakely 2020-12-05 13:56:10 UTC
Compiling with -fsanitize=undefined (as suggested by the bug reporting guidelines) would have shown the undefined behaviour.
Comment 5 Brad Bell 2020-12-05 14:50:34 UTC
Compiling with
    g++ -fsanitize=undefined -O2 int_output.cpp -o int_output
does in fact give a very useful message

I scanned the page
and looked for things that might be related to my bug.
Sorry I missed the most important flag (for my case) at the top.

It might help others to have the individual compiler flags in bold or in a list.

Thanks again