[インデックス 17936] ファイルの概要
このコミットは、Goコンパイラおよびリンカのツールチェーン(cmd/8c
, cmd/8g
, cmd/8l
)における、Plan 9環境でのコンパイル時に発生していた書式指定子の不一致に関する警告を修正するものです。具体的には、printf
系の関数呼び出しにおいて、long long
型の引数に対して誤った書式指定子(%d
や%ux
)が使用されていた問題を、適切な書式指定子(%lld
や%llux
)に修正することで解決しています。
コミット
commit 58005207d2404c8f6454c522c44d44926974496d
Author: David du Colombier <0intro@gmail.com>
Date: Mon Dec 9 18:47:22 2013 -0500
cmd/8c, cmd/8g, cmd/8l: fix Plan 9 warnings
warning: src/cmd/8c/list.c:124 format mismatch d VLONG, arg 3
warning: src/cmd/8c/list.c:134 format mismatch d VLONG, arg 3
warning: src/cmd/8c/list.c:142 format mismatch d VLONG, arg 3
warning: src/cmd/8c/list.c:152 format mismatch d VLONG, arg 3
warning: src/cmd/8c/list.c:156 format mismatch d VLONG, arg 4
warning: src/cmd/8c/list.c:160 format mismatch d VLONG, arg 4
warning: src/cmd/8c/list.c:165 format mismatch d VLONG, arg 4
warning: src/cmd/8c/list.c:167 format mismatch d VLONG, arg 3
warning: src/cmd/8c/list.c:172 format mismatch d VLONG, arg 4
warning: src/cmd/8c/list.c:174 format mismatch d VLONG, arg 3
warning: src/cmd/8c/list.c:178 format mismatch d VLONG, arg 3
warning: src/cmd/8c/list.c:184 format mismatch d VLONG, arg 3
warning: src/cmd/8g/list.c:91 format mismatch d VLONG, arg 4
warning: src/cmd/8g/list.c:100 format mismatch d VLONG, arg 4
warning: src/cmd/8g/list.c:114 format mismatch d VLONG, arg 5
warning: src/cmd/8g/list.c:118 format mismatch d VLONG, arg 5
warning: src/cmd/8g/list.c:122 format mismatch d VLONG, arg 5
warning: src/cmd/8g/list.c:126 format mismatch d VLONG, arg 5
warning: src/cmd/8g/list.c:136 format mismatch d VLONG, arg 4
warning: src/cmd/8l/list.c:107 format mismatch d VLONG, arg 4
warning: src/cmd/8l/list.c:125 format mismatch ux VLONG, arg 4
warning: src/cmd/8l/list.c:128 format mismatch ux VLONG, arg 4
warning: src/cmd/8l/list.c:130 format mismatch d VLONG, arg 4
warning: src/cmd/8l/list.c:134 format mismatch d VLONG, arg 5
warning: src/cmd/8l/list.c:138 format mismatch d VLONG, arg 6
warning: src/cmd/8l/list.c:143 format mismatch d VLONG, arg 5
warning: src/cmd/8l/list.c:148 format mismatch d VLONG, arg 5
warning: src/cmd/8l/list.c:150 format mismatch d VLONG, arg 4
warning: src/cmd/8l/list.c:154 format mismatch d VLONG, arg 4
warning: src/cmd/8l/list.c:158 format mismatch d VLONG, arg 4
warning: src/cmd/8l/obj.c:132 format mismatch ux VLONG, arg 2
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/39710043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/58005207d2404c8f6454c522c44d44926974496d
元コミット内容
このコミットは、Go言語のコンパイラ(8c
、8g
)とリンカ(8l
)のソースコードにおいて、Plan 9環境でコンパイルした際に発生する書式指定子の不一致に関する警告を修正するものです。具体的には、src/cmd/8c/list.c
、src/cmd/8g/list.c
、src/cmd/8l/list.c
、src/cmd/8l/obj.c
の各ファイルで、sprintf
やsnprintf
といった書式付き出力関数において、long long
型の引数(Plan 9の内部表現ではVLONG
と示される)に対して、int
型を想定する%d
やunsigned int
型を想定する%ux
といった書式指定子が誤って使用されていた箇所を、それぞれlong long int
型を想定する%lld
やunsigned long long int
型を想定する%llux
に修正しています。
変更の背景
Go言語の初期のツールチェーンは、Bell Labsが開発したオペレーティングシステムであるPlan 9のツールチェーン(8c
, 8g
, 8l
など)をベースにしていました。Plan 9のコンパイラは、C言語の標準ライブラリ関数であるprintf
系の書式指定子に対して非常に厳格な型チェックを行います。
このコミットが修正している警告は、まさにこの厳格な型チェックに起因するものです。Goのコンパイラやリンカの内部処理では、オフセット値やアドレスなど、64ビット整数(long long
型)を扱う場面が多く存在します。しかし、これらの値を文字列に変換して出力する際に、誤って32ビット整数を想定する%d
や%ux
といった書式指定子を使用していたため、Plan 9のコンパイラが「d
(またはux
)書式指定子にはint
(またはunsigned int
)が期待されるが、実際にはVLONG
(long long
)が渡されている」という警告を発していました。
これらの警告は、プログラムの動作に直接的なバグを引き起こすものではありませんでしたが、潜在的な問題を示唆し、コンパイル時のノイズとなっていました。開発プロセスにおいて警告をゼロに保つことは、将来的なバグの混入を防ぎ、コードの品質を維持するために重要です。そのため、このコミットでは、これらの書式指定子の不一致警告を解消し、コードの健全性を向上させることを目的としています。
前提知識の解説
Plan 9とGo言語のツールチェーン
- Plan 9 from Bell Labs: ベル研究所で開発された分散オペレーティングシステムです。その設計思想やツールチェーンは、Go言語の開発に大きな影響を与えました。特に、Go言語の初期のコンパイラやリンカは、Plan 9のツールチェーン(
8c
,8g
,8l
など)の構造や命名規則を踏襲していました。 8c
,8g
,8l
:8c
: x86アーキテクチャ向けのCコンパイラ。Go言語のコンパイラ自体はC言語で書かれていたため、このコンパイラでビルドされていました。8g
: x86アーキテクチャ向けのGoコンパイラ。Goソースコードをアセンブリコードに変換します。8l
: x86アーキテクチャ向けのリンカ。コンパイルされたオブジェクトファイルを結合して実行可能ファイルを生成します。 これらのツールは、Go言語の初期のビルドシステムにおいて中心的な役割を担っていました。
C言語の書式指定子と型
C言語のprintf
やsprintf
などの書式付き出力関数では、出力する変数の型に合わせて適切な書式指定子を使用する必要があります。
%d
: 符号付き10進整数(通常はint
型、32ビット)%ld
: 符号付き10進整数(long int
型)%lld
: 符号付き10進整数(long long int
型、64ビット)%u
: 符号なし10進整数(通常はunsigned int
型)%lu
: 符号なし10進整数(unsigned long int
型)%llu
: 符号なし10進整数(unsigned long long int
型)%x
: 符号なし16進整数(通常はunsigned int
型)%lx
: 符号なし16進整数(unsigned long int
型)%llx
: 符号なし16進整数(unsigned long long int
型)
書式指定子と引数の型が一致しない場合、コンパイラは警告を発したり、未定義の動作を引き起こす可能性があります。特に、引数のサイズが書式指定子が期待するサイズと異なる場合(例: 64ビット整数を%d
で出力しようとする場合)、値が切り捨てられたり、メモリ上の予期しないデータが読み込まれたりする可能性があります。
VLONG
Plan 9のコンパイラが警告メッセージで示すVLONG
は、その内部で定義されているデータ型で、通常は64ビット整数(long long
型に相当)を指します。この警告は、コンパイラがVLONG
型の引数を受け取ったにもかかわらず、int
型を期待する書式指定子(%d
)が使われていることを指摘しています。
技術的詳細
このコミットの技術的詳細は、C言語における書式指定子の厳密な型マッチングに集約されます。Goのコンパイラとリンカのコードベースでは、a->offset
やa->offset2
といったフィールドが、おそらく64ビットのオフセット値やアドレスを格納するためにlong long
型(またはそれに相当する型)として定義されていました。
これらの値をsprintf
やsnprintf
関数で文字列に変換する際、開発者が誤って32ビット整数用の書式指定子である%d
(10進数)や%ux
(符号なし16進数)を使用していました。Plan 9のコンパイラは、このような型と書式指定子の不一致を検出し、警告として報告します。
例えば、src/cmd/8c/list.c
の以下の行が修正されています。
// 修正前
sprintf(str, "$%d-%d", a->offset, a->offset2);
// 修正後
sprintf(str, "$%lld-%d", a->offset, a->offset2); // a->offsetがlong long型
この例では、a->offset
がlong long
型であるにもかかわらず、%d
が使われていたため、%lld
に修正されています。a->offset2
は引き続き%d
が使われていることから、こちらはint
型であると推測できます。
同様に、src/cmd/8l/obj.c
では、unsigned long long
型の値に対して%ux
が使われていた箇所が%llux
に修正されています。
// 修正前
print("warning: -D0x%ux is ignored because of -R0x%ux\\n", INITDAT, INITRND);
// 修正後
print("warning: -D0x%llux is ignored because of -R0x%ux\\n", INITDAT, INITRND); // INITDATがunsigned long long型
これらの修正は、単に警告を消すだけでなく、コードの正確性と移植性を向上させます。異なるコンパイラやプラットフォームでは、書式指定子の不一致がより深刻な問題(クラッシュや誤った値の出力)を引き起こす可能性があるため、このような修正はベストプラクティスとされています。
コアとなるコードの変更箇所
このコミットでは、以下の4つのファイルが変更されています。
src/cmd/8c/list.c
src/cmd/8g/list.c
src/cmd/8l/list.c
src/cmd/8l/obj.c
これらのファイルは、Go言語のx86アーキテクチャ向けコンパイラ(8c
、8g
)とリンカ(8l
)の内部で、アセンブリコードのリスト出力やオブジェクトファイルの処理に関連する部分です。変更のほとんどは、sprintf
またはsnprintf
関数呼び出しにおける書式指定子の変更です。
具体的には、%d
が%lld
に、%ux
が%llux
に変更されています。
コアとなるコードの解説
変更された各ファイルは、Goのツールチェーンにおける異なる役割を担っています。
src/cmd/8c/list.c
: Cコンパイラ8c
のリスト出力部分。アセンブリコードの生成過程で、定数、オフセット、シンボル名などを文字列として整形する際に使用されます。Dconv
関数内で、a->offset
やa->offset2
といった構造体メンバーの値を整形する際に書式指定子が修正されています。src/cmd/8g/list.c
: Goコンパイラ8g
のリスト出力部分。8c
と同様に、Goコードから生成されるアセンブリコードの要素(オフセット、シンボルなど)を整形する際に使用されます。ここでもDconv
関数が修正の中心です。src/cmd/8l/list.c
: リンカ8l
のリスト出力部分。リンク処理中に、プログラムカウンタ(PC)のオフセット、外部シンボル、自動変数、パラメータなどのアドレスやオフセットを整形して出力する際に使用されます。Dconv
関数内で、a->offset
やbigP->pcond->pc
といった値の書式指定子が修正されています。src/cmd/8l/obj.c
: リンカ8l
のオブジェクトファイル処理部分。初期化データやランダム化に関する警告メッセージを出力する際に使用されます。archinit
関数内で、INITDAT
という値の書式指定子が%ux
から%llux
に修正されています。これは、INITDAT
がunsigned long long
型の値であるためです。
これらの変更は、Goのツールチェーンが内部で扱うアドレスやオフセットが64ビット幅であることを反映し、それらの値を正しく文字列に変換するための修正です。これにより、Plan 9の厳格なコンパイラでも警告なしにビルドできるようになり、コードの正確性と保守性が向上しました。
関連リンク
- Go言語の公式リポジトリ: https://github.com/golang/go
- Go言語の初期のツールチェーンに関する議論(Plan 9との関連): Go言語の歴史や設計思想に関するドキュメントやブログ記事を参照すると、Plan 9の影響について詳しく知ることができます。
参考にした情報源リンク
- C言語の
printf
書式指定子に関するドキュメント(例: cppreference.com, man pages) - Plan 9のドキュメント(特に
fmt
ライブラリやコンパイラの警告に関する情報) - Go言語の初期のツールチェーンに関する設計ドキュメントやメーリングリストのアーカイブ(golang-devなど)
- コミットメッセージに記載されているGoのコードレビューシステムへのリンク: https://golang.org/cl/39710043 (現在はGo Gerritにリダイレクトされます)