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

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

このコミットは、Go言語のツールチェインにおけるC言語コンパイル時の警告設定に関する変更と、それに伴うコード修正を扱っています。特に、cmd/distツールに-Wstrict-prototypesフラグを追加し、その結果として発生したプロトタイプ宣言の不一致エラーを修正しています。

コミット

commit 255fb521da978916da0d4a2052d7941d950e2a6a
Author: Shenghou Ma <minux.ma@gmail.com>
Date:   Tue Feb 5 21:43:04 2013 +0800

    cmd/dist: add -Wstrict-prototypes to CFLAGS and fix all the compiler errors
    Plan 9 compilers insist this but as we don't have Plan 9
    builders, we'd better let gcc check the prototypes.
    
    Inspired by CL 7289050.
    
    R=golang-dev, seed, dave, rsc, lucio.dere
    CC=akumar, golang-dev
    https://golang.org/cl/7288056

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

https://github.com/golang/go/commit/255fb521da978916da0d4a2052d7941d950e2a6a

元コミット内容

cmd/dist: CFLAGSに-Wstrict-prototypesを追加し、すべてのコンパイラエラーを修正。 Plan 9コンパイラはこのプロトタイプ宣言の厳格さを要求するが、Plan 9のビルダがないため、gccにプロトタイプをチェックさせる方が良い。 CL 7289050に触発された。

変更の背景

この変更の背景には、Go言語のビルドシステムが複数のCコンパイラ(特にGCCとPlan 9コンパイラ)をサポートしているという事情があります。

  1. Plan 9コンパイラの厳格なプロトタイプ要件: Plan 9のCコンパイラは、関数のプロトタイプ宣言に関して非常に厳格なルールを持っています。引数を持たない関数であっても、voidキーワードを用いて明示的に引数がないことを示すvoid func(void);のような形式を要求します。古いCのスタイル(K&R C)では、引数リストが空のvoid func();は「引数の型が不明」を意味し、コンパイラが引数の型チェックを行わないため、潜在的なバグの原因となる可能性がありました。

  2. Goプロジェクトのビルド環境: Goプロジェクトは、様々なプラットフォームでビルドされることを想定しており、その中にはPlan 9環境も含まれます。しかし、コミットメッセージにあるように、Plan 9のビルド環境が常に利用可能であるとは限りません。

  3. GCCでのプロトタイプチェックの強化: Plan 9コンパイラがデフォルトで厳格なプロトタイプチェックを行うのに対し、GCCでは-Wstrict-prototypesフラグを使用することで、同様の厳格なチェックを有効にできます。このフラグは、引数リストが空の関数宣言(例: void func();)に対して警告を発し、引数がないことを明示的に示すvoid func(void);形式を推奨します。

これらの背景から、Plan 9環境でのビルドが困難な場合でも、GCCを使って同様のプロトタイプ関連の潜在的な問題を早期に発見し、修正するために、GCCのコンパイルオプションに-Wstrict-prototypesを追加することが決定されました。これにより、コードベース全体の品質と移植性が向上します。

コミットメッセージで言及されているCL 7289050については、GoのGerrit Change-IDの形式とは異なり、Web検索では関連する情報が見つかりませんでした。これは、コミットメッセージ内の誤記であるか、Goプロジェクトの外部の参照である可能性があります。一方で、CL 7288056はGoのジェネリクス実装に関連する変更を指しており、直接的な関連性は薄いものの、Goの言語機能拡張におけるコンパイラ周りの変更が活発であった時期を示唆している可能性があります。

前提知識の解説

C言語の関数プロトタイプ宣言

C言語において、関数プロトタイプ宣言は関数のシグネチャ(戻り値の型、関数名、引数の型と数)をコンパイラに伝えるものです。これにより、コンパイラは関数呼び出しが正しく行われているか(引数の型や数が一致しているかなど)をチェックできます。

  • 古いCのスタイル (K&R C): void func(); この形式は、引数の型や数が不明であることを意味し、コンパイラは引数に関する型チェックを行いません。これは、関数呼び出し時に誤った型の引数を渡してもコンパイルエラーにならないため、実行時エラーの原因となる可能性があります。

  • 新しいCのスタイル (ANSI C以降): void func(void); この形式は、関数が引数を一切取らないことを明示的に示します。コンパイラはこれに基づいて厳格な型チェックを行います。

-Wstrict-prototypes (GCCコンパイラフラグ)

GCC(GNU Compiler Collection)における-Wstrict-prototypesフラグは、関数プロトタイプ宣言が古いK&R Cスタイルである場合に警告を発するためのコンパイラオプションです。このフラグを有効にすると、void func();のような宣言に対して警告が出力され、void func(void);のように引数がないことを明示的に示すように促されます。これにより、コードの品質と安全性が向上します。

Plan 9コンパイラ

Plan 9はベル研究所で開発された分散オペレーティングシステムです。Plan 9には独自のCコンパイラ(例: 5c, 6c, 8cなど、それぞれ異なるアーキテクチャ向け)が含まれており、これらはANSI C標準に準拠しつつも、特定のコーディングスタイルや慣習に対してGCCよりも厳格なチェックを行う傾向があります。特に、関数プロトタイプに関しては、引数がない関数にはvoidを明示的に指定することを強く推奨、あるいは要求します。

cmd/dist

Go言語のソースコードリポジトリにおけるsrc/cmd/distは、Goのビルドシステムの一部です。これは、Goのツールチェイン(コンパイラ、リンカなど)をビルドするためのユーティリティやスクリプトを含んでいます。C言語で書かれたGoのコンポーネントをコンパイルする際に、このdistツールがCコンパイラを呼び出し、適切なコンパイルフラグを渡します。

技術的詳細

このコミットの技術的詳細は、主にC言語の関数プロトタイプ宣言の厳格化と、Goのビルドプロセスにおけるコンパイラフラグの管理にあります。

  1. -Wstrict-prototypesの追加: src/cmd/dist/build.cファイルにおいて、Cコンパイラに渡されるデフォルトのコンパイルフラグリストproto_gccargs-Wstrict-prototypesが追加されました。これにより、Goのツールチェインをビルドする際にC言語のソースコードがコンパイルされる際、GCCが厳格なプロトタイプチェックを行うようになります。

    --- a/src/cmd/dist/build.c
    +++ b/src/cmd/dist/build.c
    @@ -398,6 +398,9 @@ setup(void)\n // gccargs is the gcc command line to use for compiling a single C file.\n static char *proto_gccargs[] = {\n  	"-Wall",\n+ 	// native Plan 9 compilers don't like non-standard prototypes\n+ 	// so let gcc catch them.\n+ 	"-Wstrict-prototypes",\n  	"-Wno-sign-compare",\n  	"-Wno-missing-braces",\n  	"-Wno-parentheses",
    

    この変更は、Plan 9コンパイラがデフォルトで持つ厳格なプロトタイプ要件をGCCでも模倣し、Goのコードベース全体で一貫した品質基準を適用することを目的としています。

  2. プロトタイプ宣言の修正: -Wstrict-prototypesフラグの追加により、既存のC言語ソースコード内でK&Rスタイルの関数プロトタイプ宣言が使用されている箇所がコンパイルエラー(または警告)として検出されました。このコミットでは、それらの箇所を新しいANSI Cスタイルに修正しています。具体的には、引数を取らない関数宣言の引数リストにvoidを追加しています。

    例: void checklabels(); から void checklabels(void); への変更。

    この修正は、src/cmd/5g/gg.h, src/cmd/6g/gg.h, src/cmd/8g/gg.h (Goの各アーキテクチャ向けコンパイラのヘッダファイル), src/cmd/ld/lib.h, src/cmd/ld/macho.h (リンカ関連のヘッダファイル), src/cmd/prof/main.c (プロファイラ関連のソースファイル), src/libmach/darwin.c (Mach-O関連のソースファイル) など、Goツールチェインの様々なC言語ソースファイルにわたって行われています。

    これらの修正は、単にコンパイルエラーを解消するだけでなく、コードの可読性と保守性を向上させ、将来的なコンパイラのバージョンアップや異なるコンパイラ環境への対応を容易にする効果もあります。

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

このコミットにおけるコアとなるコードの変更は、以下の2つのタイプに分類されます。

  1. コンパイラフラグの追加: src/cmd/dist/build.c ファイル内の proto_gccargs 配列に "-Wstrict-prototypes" が追加されました。これは、GoのビルドプロセスにおいてC言語のソースコードをコンパイルする際に、GCCが厳格なプロトタイプチェックを行うように指示するものです。

  2. C言語の関数プロトタイプ宣言の修正: Goツールチェイン内の複数のC言語ヘッダファイルおよびソースファイルにおいて、引数を取らない関数宣言が void func(); から void func(void); の形式に修正されました。

    具体的には以下のファイルが変更されています。

    • src/cmd/5g/gg.h
    • src/cmd/6g/gg.h
    • src/cmd/8g/gg.h
    • src/cmd/ld/lib.h
    • src/cmd/ld/macho.h
    • src/cmd/prof/main.c
    • src/libmach/darwin.c

コアとなるコードの解説

src/cmd/dist/build.c の変更

--- a/src/cmd/dist/build.c
+++ b/src/cmd/dist/build.c
@@ -398,6 +398,9 @@ setup(void)\n // gccargs is the gcc command line to use for compiling a single C file.\n static char *proto_gccargs[] = {\n  	"-Wall",\n+ 	// native Plan 9 compilers don't like non-standard prototypes\n+ 	// so let gcc catch them.\n+ 	"-Wstrict-prototypes",\n  	"-Wno-sign-compare",\n  	"-Wno-missing-braces",\n  	"-Wno-parentheses",

このスニペットは、GoのビルドシステムがC言語のソースファイルをコンパイルする際に使用するGCCのコマンドライン引数を定義している部分です。proto_gccargsは、GoのコンパイラやリンカなどのC言語で書かれた部分をビルドする際に適用される共通のフラグのリストです。ここに-Wstrict-prototypesが追加されたことで、GCCは引数リストが空の関数宣言(例: void func();)に対して警告を発するようになります。コメントにあるように、これはPlan 9コンパイラの厳格な要件をGCCでも満たすための措置です。

各ヘッダファイルおよびソースファイルの変更例

--- a/src/cmd/5g/gg.h
+++ b/src/cmd/5g/gg.h
@@ -84,7 +84,7 @@ void\tcgen_dcl(Node*);\n int\tneedconvert(Type*, Type*);\n void\tgenconv(Type*, Type*);\n void\tallocparams(void);\n-void\tchecklabels();\n+void\tchecklabels(void);\n void\tginscall(Node*, int);\n```
この例は、`src/cmd/5g/gg.h`における`checklabels`関数のプロトタイプ宣言の変更を示しています。元の宣言`void checklabels();`は、引数の型が不明であることを意味する古いK&R Cスタイルです。これを`void checklabels(void);`に修正することで、関数が引数を一切取らないことを明示的に示し、`-Wstrict-prototypes`フラグによる警告を解消しています。同様の修正が、他の変更されたファイル内の複数の関数に対して適用されています。

これらの変更は、Goのツールチェインが使用するC言語コードの品質と移植性を向上させるための重要なステップです。特に、異なるコンパイラ環境間での互換性を確保し、潜在的なバグを早期に発見するのに役立ちます。

## 関連リンク

*   **Go言語の公式ドキュメント**: Go言語のビルドプロセスやツールチェインに関する詳細な情報は、公式ドキュメントで確認できます。
    *   [https://go.dev/doc/](https://go.dev/doc/)
*   **GCCのドキュメント**: `-Wstrict-prototypes`フラグに関する詳細な情報は、GCCの公式ドキュメントで確認できます。
    *   [https://gcc.gnu.org/onlinedocs/](https://gcc.gnu.org/onlinedocs/)
*   **Plan 9 from Bell Labs**: Plan 9オペレーティングシステムとそのCコンパイラに関する情報。
    *   [https://9p.io/plan9/](https://9p.io/plan9/)

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

*   **GCCの警告オプションに関するドキュメント**:
    *   [https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html](https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html)
*   **C言語の関数プロトタイプに関する解説**:
    *   [https://en.wikipedia.org/wiki/Function_prototype](https://en.wikipedia.org/wiki/Function_prototype)
*   **Plan 9 Cコンパイラに関する情報**:
    *   [https://www.cs.bell-labs.com/sys/doc/compiler/c.pdf](https://www.cs.bell-labs.com/sys/doc/compiler/c.pdf) (Plan 9 Cコンパイラのドキュメント)
*   **Go Gerrit Change-ID 7288056に関する情報**:
    *   Web検索結果より、Goのジェネリクスに関連する変更であることが示唆されていますが、このコミットとの直接的な関連性は薄いです。
    *   [https://go.dev/cl/7288056](https://go.dev/cl/7288056) (GoのGerritレビューシステムへのリンク)