Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 12294] ファイルの概要

test: add a couple of cases to const1.go that crashed gccgo

コミット

  • Author: Ian Lance Taylor iant@golang.org
  • Date: Wed Feb 29 17:39:02 2012 -0800
  • Commit Hash: f0886ab7e21c1e7c7de59085dbcbaf1cb7a48737

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/f0886ab7e21c1e7c7de59085dbcbaf1cb7a48737

元コミット内容

test: add a couple of cases to const1.go that crashed gccgo

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/5713045

変更の背景

このコミットは、Go言語のコンパイラ実装の一つである gccgo において、特定の定数式が正しく評価されずにコンパイラがクラッシュするという深刻なバグが存在したため、その問題を再現し、修正が正しく適用されたことを検証するためのテストケースを追加するものです。具体的には、ビット反転演算子 (^) を含む定数式、特に符号あり整数型 (int64) と組み合わせた場合に gccgo が異常終了する問題が報告されていました。このテストケースの追加により、将来的に同様の回帰バグが発生しないようにするための安全網が強化されます。

前提知識の解説

  • Go言語の定数 (Constants): Go言語における定数は、コンパイル時にその値が確定する不変のエンティティです。これらは数値(整数、浮動小数点数)、真偽値、文字列のいずれかであり、多くの場合、特定の型を持たない「型なし定数 (untyped constants)」として扱われます。型なし定数は、それが使用される文脈(例えば変数への代入や関数呼び出しの引数)に応じて、適切な型に自動的に変換されます。この柔軟性が、Go言語の定数システムの強力な特徴の一つです。ただし、変換先の型の範囲を超える値の場合には、コンパイルエラー("overflow")が発生します。

  • gccgo: gccgo は、Go言語のソースコードをコンパイルするためのコンパイラフロントエンドの一つで、GNU Compiler Collection (GCC) の一部として開発されています。Go言語の公式コンパイラである gc (Go toolchain の一部) とは異なる実装であり、それぞれが異なる最適化戦略やコード生成ロジックを持っています。そのため、両方のコンパイラで同じGoコードが正しく動作することを確認することは、Go言語のエコシステム全体の健全性を保つ上で重要です。過去には、gcgccgo の間で定数評価の挙動に差異が見られることがありました。

  • ビット反転演算子 ^ (Bitwise NOT): ^ はGo言語における単項のビット反転演算子です。この演算子は、オペランドの各ビットを反転させます(0を1に、1を0に)。

    • 符号なし整数型の場合: ^0 は、その型の全てのビットが1になった値を表します。例えば、uint8 型の場合、^0255 (バイナリで 11111111) となります。
    • 符号あり整数型の場合: 2の補数表現を使用するシステムでは、^0-1 となります。例えば、int64 型の場合、^0int64 の全てのビットが1になった値であり、これは -1 を表します。
  • Go言語の整数型: Go言語には、int8, int16, int32, int64 といった符号あり整数型と、uint8, uint16, uint32, uint64 といった符号なし整数型があります。それぞれの型は異なるビット幅を持ち、表現できる値の範囲が異なります。定数式がこれらの型に代入される際、その値が型の範囲内に収まっているかどうかが厳密にチェックされます。

技術的詳細

このコミットが対処している問題は、gccgo がGo言語の定数評価、特にビット反転演算子 ^ と型なし定数の組み合わせを処理する際のバグに起因します。Go言語の仕様では、^0 のような型なし定数式は、そのコンテキストに応じて適切な型に推論され、その型のセマンティクスに従って評価されるべきです。

既存のテストケース b5 = uint8(^0)ERROR "overflow" とコメントされています。これは、^0 が型なし定数として評価された後、uint8 型に変換される際にオーバーフローが発生することを示しています。uint8 の最大値は 255 ですが、^0 がもし int 型のコンテキストで評価され、その結果が uint8 の範囲を超えていた場合、あるいは uint8 のビット幅を超えた値として内部的に扱われていた場合に、オーバーフローエラーとなる可能性があります。

gccgo は、特に int64(^0)^int64(0) のような、int64 型の文脈で ^ 演算子を使用する定数式を処理する際にクラッシュしていました。これは、gccgo の定数評価器が、型なし定数 ^0 の内部表現を正しく扱えなかったか、またはそれを符号あり整数型(特に int64)に変換する際のロジックに欠陥があったことを示唆しています。int64 型における ^0-1 という明確な値を持つため、この評価でコンパイラがクラッシュすることは、コンパイラの基本的な機能に問題があったことを意味します。

このコミットによって追加されたテストケースは、gccgoint64 型の文脈で ^ 演算子を含む定数式を正しく評価し、コンパイル時にクラッシュすることなく、期待される -1 という値を生成できるようになったことを確認します。これにより、gccgo の定数評価の堅牢性が向上しました。

コアとなるコードの変更箇所

--- a/test/const1.go
+++ b/test/const1.go
@@ -43,7 +43,9 @@ var (
 	b3        = Uint8 - Uint8         // OK
 	b4        = Uint8 - Uint8 - Uint8 // ERROR "overflow"
 	b5        = uint8(^0)             // ERROR "overflow"
+	b5a       = int64(^0)             // OK
 	b6        = ^uint8(0)             // OK
+	b6a       = ^int64(0)             // OK
 	b7        = uint8(Minus1)         // ERROR "overflow"
 	b8        = uint8(int8(-1))       // ERROR "overflow"
 	b8a       = uint8(-1)             // ERROR "overflow"

コアとなるコードの解説

このコミットでは、test/const1.go ファイルの定数テストスイートに以下の2つの新しいテストケースが追加されました。

  1. b5a = int64(^0) // OK

    • この行は、型なし定数 ^0int64 型の変数 b5a に代入するケースをテストしています。Go言語の仕様では、int64 型の文脈における ^0 は、2の補数表現において全てのビットが1になった値、すなわち -1 を表します。この行が // OK とコメントされていることから、この定数式がGo言語の仕様に則って正しく評価され、int64 型の -1 として扱われるべきであることを示しています。以前の gccgo はこのケースでクラッシュしていたため、このテストケースの追加は、gccgo がこの特定の定数評価を正しく処理できるようになったことを検証します。
  2. b6a = ^int64(0) // OK

    • この行は、明示的に int64(0) と型付けされた値 0 に対してビット反転演算子 ^ を適用するケースをテストしています。結果は int64 型の -1 となります。既存の b6 = ^uint8(0) と比較すると、オペランドの型が uint8 から int64 に変わった場合の ^ 演算子の挙動を確認しています。これも // OK とコメントされており、gccgo がこの定数式も正しく処理できるようになったことを示しています。

これらの追加されたテストケースは、gccgo^ 演算子と符号あり整数型(特に int64)の組み合わせにおける定数評価のバグを修正したことを確認するために不可欠です。既存の b5 = uint8(^0)ERROR "overflow" であることと対比して、int64 の場合はオーバーフローが発生せず、期待される結果が得られることを明確に示しています。これにより、gccgo の定数評価の正確性と安定性が向上しました。

関連リンク

参考にした情報源リンク

  • なし (提供されたコミット情報と一般的なGo言語の知識に基づいています)