noreturnの挙動(続)

id:MaD:20081209のコメント欄が長くなり過ぎたので新たに書きます。

稲葉さんからご指摘を受けましたけど、どうも最適化云々はおまけで本命はどうも if(foo) { abort(); } else { return bar; } のようなコードでコンパイラに警告を出させないことのようです。

http://d.hatena.ne.jp/MaD/20081209#c1228920872

警告抑止で使われる事は知っていたのだけれど, おまけも本命もあるのか?と思ってよく考えてみたら全くその通りだった。

非常に勉強になったので説明します。
まず上の様なコードのコントロールフローグラフは一番左の様になります。
return bar;はそこで関数を抜けるので次のエッジは除去しています。
このままだと右側のフローが値を返さないのでコンパイラが困ります。そこでfにnoreturn属性をつけると, 右の関数コール後のエッジが除去される(GCCではこれをnoreturn edgeと呼んでいる)ので,問題が解決します。

基本的にはnoreturnの役割はこれだけ(関数コールの次のエッジをnoreturn edgeにする)です。
そして次に到達不能コード除去(Dead code elimination)という別の最適化が行われると一番右の様になり, 元よりスリムなコードが生成されます。

つまり, 実際に関数呼び出し後の後処理コードを消しているのはDead code eliminationなので, noreturnの最適化効果はいわばたなぼたということですね。(もちろん処理系の実装方法により変わるのですが)

これは私の勉強不足でした。稲葉さんありがとうございました。(もし稲葉さんの意図が上と違うことならば是非教えてください)


そうすると「最適化できないとnoreturnの存在意義なし」とは言えないですね。ごめんなさい。

ただ, 良く分からないでattributeを使っちゃうような素人が利益を得て, 正しく使っている玄人が不利益を被るようなチェックの追加はやっぱり反対ですし, exit()等にnoreturnを追加すべき説得力のある理由もやっぱりないと思います。

言いたいことは言ったので, あとは主査の取りまとめを大人しく待とうと思います。