コンパイラーの振る舞いは実際には何も証明できないことは知っていますが、コンパイラーの内部表現が何を与えるかをチェックするのは興味深いと思いました(アセンブリ検査よりも少し高いレベルです)。
私はこのコードでClang/LLVMオンラインデモを使用しました:
#include <stdio.h>
#include <stdlib.h>
struct X
{
X const& f(int i) const
{
printf("%d\n", i);
return *this;
}
};
int main(int argc, char **argv) {
int i = 0;
X x;
x.f(++i).f(++i).f(++i); // line 16
}
そして、標準の最適化(C ++モード)でコンパイルすると、次のようになります。
/tmp/webcompile/_13371_0.cc:関数'int main(int、char **)':/
tmp/webcompile/_13371_0.cc:16:警告:'i'の操作が未定義の可能性があります
私はこれを面白いと思いました(他のコンパイラはこれについて警告しましたか?Comeau onlineは警告しませんでした)
余談ですが、次の中間表現も生成されました(右にスクロール)。
@.str = private constant [4 x i8] c"%d\0A\00", align 1 ; <[4 x i8]*> [#uses=1]
define i32 @main(i32 %argc, i8** nocapture %argv) nounwind {
entry:
%0 = tail call i32 (i8*, ...)* @printf(i8* noalias getelementptr inbounds ([4 x i8]* @.str, i64 0, i64 0), i32 3) nounwind ; <i32> [#uses=0]
^^^^^
%1 = tail call i32 (i8*, ...)* @printf(i8* noalias getelementptr inbounds ([4 x i8]* @.str, i64 0, i64 0), i32 3) nounwind ; <i32> [#uses=0]
^^^^^
%2 = tail call i32 (i8*, ...)* @printf(i8* noalias getelementptr inbounds ([4 x i8]* @.str, i64 0, i64 0), i32 3) nounwind ; <i32> [#uses=0]
^^^^^
ret i32 0
}
どうやら、Clangはgcc 4.xxと同じように動作し、関数呼び出しを実行する前に最初にすべての引数を評価します。