I read in the C++17 Standard $8.5.7.4:
The expression E1 is sequenced before the expression E2.
for shift operators.
Also cppreference rule 19 says:
In a shift operator expression E1<>E2, every value computation and side-effect of E1 is sequenced before every value computation and side effect of E2
But when I try to compile the following code with gcc 7.3.0 or clang 6.0.0
#include <iostream>
using namespace std;
int main() {
int i = 5;
cout << (i++ << i) << endl;
return 0;
}
I get the following gcc warning:
../src/Cpp_shift.cpp: In function ‘int main()’:
../src/Cpp_shift.cpp:6:12: warning: operation on ‘i’ may be undefined [-Wsequence-point]
cout << (i++ << i) << endl;
~^~
The clang warning is:
warning: unsequenced modification and access to 'i' [-Wunsequenced]
I used the following commands to compile:
g++ -std=c++17 ../src/Cpp_shift.cpp -o Cpp_shift -Wall
clang++ -std=c++17 ../src/Cpp_shift.cpp -o Cpp_shift -Wall
I get the expected 320
as output in both cases ( 5 * 2 ^ 6 )
Can someone explain why I get this warning? Did I overlook something? I also read this related question, but it does not answer my question.
edit: all other variants ++i << i
, i << ++i
and i << i++
result in the same warning.
edit2: (i << ++i)
results in 320
for clang (correct) and 384
for gcc (incorrect). It seems that gcc gives a wrong result if the ++
is at E2
, (i << i++)
also gives a wrong result.
<<
was introduced, but possibly it wasn't until C++14 or C++17. As it is it's clearly a bug, which ideally should be reported. – Pupa160
in case 5. the++
executed after << – Sicknessi++ << i
is execute asi << i; i++
– Sicknessg++ -std=c++17 ../src/Cpp_shift.cpp -o Cpp_shift -Wall
I got that warning too, but when I compile without the-Wall
flag, I didn't get any warning at all. It might be a coding warning of this flag. So, because it's not an undefined behavior of c++17, the problem is probably with this flag implementation. – Mages-Wall
I still get the same wrong result with gcc for(i << ++i)
. clang gives the warning also without-Wall
. – Isocline-fsanitize=undefined
and 160 with it – Damascene