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

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

このコミットは、Go言語のテストスイートがgccgoコンパイラのエラーメッセージを正しく認識できるようにするための変更です。具体的には、gccgoが出力するエラーメッセージに対応するための新しいディレクティブGCCGO_ERRORを導入し、既存の6gコンパイラ用のerrchkスクリプトがこれを無視するように調整しています。これにより、同じテストコードが異なるGoコンパイラ環境下でも期待通りに動作し、エラー検出のロジックが統一されます。

コミット

commit 9c9cc2c9d8bd2303e1f0c3619c1451ac469fc086
Author: Ian Lance Taylor <iant@golang.org>
Date:   Tue Nov 11 18:18:34 2008 -0800

    Recognize gccgo error messages.  This uses GCCGO_ERROR, which
    is recognized by the gccgo testsuite but is ignored by the
    errchk script used with 6g.
    
    method1.go:7:1: error: redefinition of 'M': parameter types changed
    method1.go:6:1: note: previous definition of 'M' was here
    method1.go:10:1: error: redefinition of 'f': parameter types changed
    method1.go:9:1: note: previous definition of 'f' was here
    method1.go:13:1: error: redefinition of 'g': parameter names changed
    method1.go:12:1: note: previous definition of 'g' was here
    
    R=rsc
    DELTA=5  (0 added, 0 deleted, 5 changed)
    OCL=18962
    CL=19058

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

https://github.com/golang/go/commit/9c9cc2c9d8bd2303e1f0c3619c1451ac469fc086

元コミット内容

commit 9c9cc2c9d8bd2303e1f0c3619c1451ac469fc086
Author: Ian Lance Taylor <iant@golang.org>
Date:   Tue Nov 11 18:18:34 2008 -0800

    Recognize gccgo error messages.  This uses GCCGO_ERROR, which
    is recognized by the gccgo testsuite but is ignored by the
    errchk script used with 6g.
    
    method1.go:7:1: error: redefinition of 'M': parameter types changed
    method1.go:6:1: note: previous definition of 'M' was here
    method1.go:10:1: error: redefinition of 'f': parameter types changed
    method1.go:9:1: note: previous definition of 'f' was here
    method1.go:13:1: error: redefinition of 'g': parameter names changed
    method1.go:12:1: note: previous definition of 'g' was here
    
    R=rsc
    DELTA=5  (0 added, 0 deleted, 5 changed)
    OCL=18962
    CL=19058
---
 test/method1.go | 10 +++++-----\n 1 file changed, 5 insertions(+), 5 deletions(-)\n
diff --git a/test/method1.go b/test/method1.go
index f25eb30c8b..c88607d425 100644
--- a/test/method1.go
+++ b/test/method1.go
@@ -7,12 +7,12 @@
 package main
 
 type T struct { }\n-func (t *T) M(int, string);\n-func (t *T) M(int, float) { }   // ERROR \"redeclared\"\n+func (t *T) M(int, string);\t// GCCGO_ERROR \"previous\"\n+func (t *T) M(int, float) { }   // ERROR \"redeclared|redefinition\"\n \n-func f(int, string);\n-func f(int, float) { }  // ERROR \"redeclared\"\n+func f(int, string);\t// GCCGO_ERROR \"previous\"\n+func f(int, float) { }  // ERROR \"redeclared|redefinition\"\n \n-func g(a int, b string);\n+func g(a int, b string);  // GCCGO_ERROR \"previous\"\n func g(a int, c string);  // ERROR \"names changed\"\n \n```

## 変更の背景

Go言語の初期開発段階では、複数のコンパイラが存在していました。このコミットの時点では、主にGoogleが開発していたオリジナルのGoコンパイラ(通称`6g`、`8g`、`5g`など、ターゲットアーキテクチャによって名前が異なる)と、GCC(GNU Compiler Collection)のフロントエンドとして開発されていた`gccgo`がありました。

Go言語のテストスイートは、コンパイラが特定のコードに対して期待されるエラーを正しく報告するかどうかを検証するために、エラーメッセージのパターンマッチングを利用していました。しかし、`6g`と`gccgo`では、同じエラーに対するメッセージのフォーマットや詳細度が異なることがありました。

この差異が問題となり、`gccgo`でテストを実行すると、`6g`向けに書かれた既存のテストがエラーメッセージの不一致により失敗する可能性がありました。特に、`gccgo`はエラーが発生した箇所だけでなく、関連する以前の定義箇所なども`note`として詳細に出力する傾向がありました。このコミットは、このようなコンパイラ間のエラーメッセージの差異を吸収し、テストスイートが両方のコンパイラで適切に機能するようにするために行われました。

## 前提知識の解説

*   **Go言語のコンパイラ:**
    *   **`6g`/`8g`/`5g` (gcコンパイラ):** Go言語の公式ツールチェインに含まれる、Goチームが開発したオリジナルのコンパイラ群です。これらはGo言語のセマンティクスに特化しており、高速なコンパイルが特徴です。初期のGo開発では主要なコンパイラでした。
    *   **`gccgo`:** GCCのフロントエンドとして実装されたGoコンパイラです。GCCの最適化バックエンドを利用できるため、生成されるバイナリのパフォーマンスが向上する可能性があります。しかし、GCCのアーキテクチャに依存するため、コンパイル速度は`gc`コンパイラに比べて遅い傾向があります。
*   **Go言語のテストスイートとエラーチェック:**
    *   Go言語のテストスイートには、コンパイラが特定の不正なコードに対して期待されるエラーを報告するかどうかを検証するテストが含まれています。これらのテストファイルには、期待されるエラーメッセージのパターンをコメントとして記述する慣習があります。
    *   **`// ERROR "pattern"`:** これは、Goのテストフレームワークが使用するディレクティブで、その行またはその周辺でコンパイラが指定された`pattern`にマッチするエラーメッセージを出力することを期待します。もしパターンにマッチするエラーが出力されなかったり、異なるエラーが出力されたりすると、テストは失敗します。
    *   **`errchk`スクリプト:** `gc`コンパイラ(`6g`など)のテスト実行時に、`// ERROR`ディレクティブを解析し、実際のコンパイラ出力と照合する役割を担うスクリプトです。

## 技術的詳細

このコミットの核心は、異なるコンパイラ(`6g`と`gccgo`)が生成するエラーメッセージの差異を、テストスイートのレベルで吸収することにあります。

`gccgo`は、エラーメッセージに加えて、そのエラーに関連する「以前の定義」などの`note`(補足情報)を詳細に出力する傾向があります。例えば、関数の再定義エラーの場合、`gccgo`は「redefinition of 'M'」というエラーに加えて、「previous definition of 'M' was here」という`note`を別の行で出力することがあります。

既存の`// ERROR "pattern"`ディレクティブは、通常、単一のエラーメッセージ行にマッチすることを想定していました。`gccgo`の出力する追加の`note`行は、`6g`では出力されないため、`gccgo`でテストを実行すると、これらの`note`行が予期せぬ出力として扱われ、テストが失敗する原因となっていました。

この問題を解決するために、以下の戦略が取られました。

1.  **`GCCGO_ERROR`ディレクティブの導入:**
    *   `// GCCGO_ERROR "pattern"`という新しいコメントディレクティブが導入されました。
    *   このディレクティブは、`gccgo`コンパイラでテストを実行する際にのみ認識され、指定された`pattern`にマッチするエラーメッセージ(または`note`メッセージ)が出力されることを期待します。
    *   一方、`6g`コンパイラ用の`errchk`スクリプトは、この`GCCGO_ERROR`ディレクティブを完全に無視するように設計されました。これにより、`6g`でのテストの振る舞いは変更されません。
2.  **既存の`ERROR`ディレクティブの調整:**
    *   `// ERROR "redeclared"`のような既存のディレクティブは、`gccgo`の出力にも対応できるように、パターンが拡張されました。例えば、`"redeclared|redefinition"`のように、`6g`の「redeclared」と`gccgo`の「redefinition」の両方にマッチするように変更されています。
    *   これにより、主要なエラーメッセージは両方のコンパイラで共通の`ERROR`ディレクティブで捕捉できるようになります。
3.  **`GCCGO_ERROR`と`ERROR`の併用:**
    *   `test/method1.go`の変更箇所を見ると、`gccgo`が追加で出力する`note`行(例: `previous definition of 'M' was here`)に対しては`// GCCGO_ERROR "previous"`が追加されています。
    *   これにより、`gccgo`でテストを実行した際には、この`note`行も期待される出力として扱われ、テストが成功します。`6g`ではこの行は出力されないため、`GCCGO_ERROR`ディレクティブは無視され、問題になりません。

このアプローチにより、単一のテストファイルが、異なるコンパイラ環境下でも期待されるエラーメッセージの出力を検証できるようになり、テストスイートの互換性と堅牢性が向上しました。

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

変更は`test/method1.go`ファイルに集中しています。

```diff
--- a/test/method1.go
+++ b/test/method1.go
@@ -7,12 +7,12 @@
 package main
 
 type T struct { }\n-func (t *T) M(int, string);\n-func (t *T) M(int, float) { }   // ERROR \"redeclared\"\n+func (t *T) M(int, string);\t// GCCGO_ERROR \"previous\"\n+func (t *T) M(int, float) { }   // ERROR \"redeclared|redefinition\"\n \n-func f(int, string);\n-func f(int, float) { }  // ERROR \"redeclared\"\n+func f(int, string);\t// GCCGO_ERROR \"previous\"\n+func f(int, float) { }  // ERROR \"redeclared|redefinition\"\n \n-func g(a int, b string);\n+func g(a int, b string);  // GCCGO_ERROR \"previous\"\n func g(a int, c string);  // ERROR \"names changed\"\n \n```

## コアとなるコードの解説

このコミットは、`test/method1.go`というテストファイル内のコメントディレクティブを修正しています。このファイルは、Go言語におけるメソッドや関数の再定義、パラメータの変更に関するコンパイラのエラー検出をテストするためのものです。

変更のポイントは以下の通りです。

1.  **`func (t *T) M(int, string);` の行:**
    *   変更前: コメントなし。
    *   変更後: `// GCCGO_ERROR "previous"` が追加されました。
    *   これは、`gccgo`が`M`メソッドの再定義エラーを報告する際に、「以前の定義がここにある」という`note`メッセージを出力することを期待しています。`6g`はこの`note`を出力しないため、`GCCGO_ERROR`は`6g`のテスト実行時には無視されます。

2.  **`func (t *T) M(int, float) { } // ERROR "redeclared"` の行:**
    *   変更前: `// ERROR "redeclared"`
    *   変更後: `// ERROR "redeclared|redefinition"`
    *   `M`メソッドの再定義エラーに対する期待パターンが拡張されました。`6g`は「redeclared」というメッセージを、`gccgo`は「redefinition」というメッセージを出力する可能性があるため、両方にマッチするように`|`(OR)演算子で結合されています。

3.  **`func f(int, string);` の行:**
    *   `M`メソッドと同様に、`// GCCGO_ERROR "previous"` が追加されました。これは、`f`関数の再定義に関する`gccgo`の`note`メッセージに対応します。

4.  **`func f(int, float) { } // ERROR "redeclared"` の行:**
    *   `M`メソッドと同様に、`// ERROR "redeclared|redefinition"` に変更されました。

5.  **`func g(a int, b string);` の行:**
    *   `M`メソッドや`f`関数と同様に、`// GCCGO_ERROR "previous"` が追加されました。これは、`g`関数のパラメータ名変更に関する`gccgo`の`note`メッセージに対応します。

これらの変更により、`test/method1.go`は`6g`と`gccgo`の両方のコンパイラで、期待されるエラーメッセージの出力を正確に検証できるようになりました。テストの互換性と網羅性が向上しています。

## 関連リンク

*   Go言語の公式ウェブサイト: [https://go.dev/](https://go.dev/)
*   GCCGoプロジェクトページ (GCCのGoフロントエンド): [https://gcc.gnu.org/onlinedocs/gccgo/](https://gcc.gnu.org/onlinedocs/gccgo/)

## 参考にした情報源リンク

*   Go言語のテストに関するドキュメント(一般的なテストの書き方): [https://go.dev/doc/tutorial/add-a-test](https://go.dev/doc/tutorial/add-a-test)
*   Go言語の初期のコンパイラに関する議論(歴史的背景): [https://go.dev/doc/faq#Why_does_Go_have_its_own_compiler_and_tools](https://go.dev/doc/faq#Why_does_Go_have_its_own_compiler_and_tools)
*   Go言語のテストスイートにおける`// ERROR`ディレクティブの利用に関する情報(Goソースコード内のテストファイルや関連ドキュメント)
    *   Goのソースコードリポジトリ内の`src/cmd/go/test.go`や`src/cmd/compile/internal/test/test.go`などのテスト実行ロジックを解析することで、これらのディレクティブの挙動を詳細に理解できます。
    *   具体的なドキュメントリンクは存在しないが、Goのテストフレームワークの慣習として広く知られている。