在 C++17 中排序的移位操作数

Shift operands sequenced in C++17

我阅读了 C++17 标准 $8.5.7.4:

The expression E1 is sequenced before the expression E2.

对于移位运算符。

另外 cppreference 规则 19 说:

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

但是当我尝试使用 gcc 7.3.0 或 clang 6.0.0 编译以下代码时

#include <iostream>
using namespace std;

int main() {
    int i = 5;
    cout << (i++ << i) << endl;
    return 0;
}

我收到以下 gcc 警告:

../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;
           ~^~

当当警告是:

warning: unsequenced modification and access to 'i' [-Wunsequenced]

我使用以下命令编译:

g++ -std=c++17 ../src/Cpp_shift.cpp -o Cpp_shift -Wall
clang++ -std=c++17 ../src/Cpp_shift.cpp -o Cpp_shift -Wall

我在两种情况下都得到了预期的 320 作为输出 ( 5 * 2 ^ 6 )

有人可以解释为什么我会收到此警告吗?我忽略了什么吗?我也阅读了 相关问题,但它没有回答我的问题。

编辑:所有其他变体 ++i << ii << ++ii << i++ 都会导致相同的警告。

edit2:(i << ++i) 导致 clang 为 320(正确),gcc 为 384(不正确)。如果 ++ 位于 E2,gcc 似乎会给出错误的结果,(i << i++) 也会给出错误的结果。

标准明确了移位运算符的操作数的评估顺序。

n4659 - §8.8 (p4):

The expression E1 is sequenced before the expression E2.

表达式i++ << i中没有未定义的行为,定义良好。这是 Clang and GCC 两者中的错误。