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

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

このコミットは、Go言語のランタイムの一部であるlib9ライブラリにおける、Plan 9環境での不整合とコンパイラの警告を修正することを目的としています。具体的には、到達不能なコードや未使用の変数に関する警告の解消、およびPlan 9と非Plan 9環境でのビルドの差異を適切に扱うための変更が含まれています。

コミット

commit 705d7c164fa61181f2f943fb2541b39b39ced637
Author: David du Colombier <0intro@gmail.com>
Date:   Thu Feb 13 20:05:55 2014 +0100

    lib9: fix inconsistencies and warnings on Plan 9
    
    warning: src/lib9/fmt/dorfmt.c:64 unreachable code RETURN
    warning: src/lib9/fmt/fltfmt.c:184 set and not used: p
    warning: src/lib9/utf/utflen.c:35 unreachable code RETURN
    warning: src/lib9/utf/utfrrune.c:45 unreachable code RETURN
    warning: src/lib9/utf/utfrune.c:44 unreachable code RETURN
    
    LGTM=rsc
    R=rsc, iant, gobot
    CC=golang-codereviews
    https://golang.org/cl/57170052

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

https://github.com/golang/go/commit/705d7c164fa61181f2f943fb2541b39b39ced637

元コミット内容

このコミットは、lib9ライブラリにおける以下の問題に対処しています。

  • Plan 9環境での不整合: Plan 9オペレーティングシステム上でのビルド時に発生する問題。
  • コンパイラの警告:
    • src/lib9/fmt/dorfmt.c:64: 到達不能なコード(unreachable code RETURN
    • src/lib9/fmt/fltfmt.c:184: 設定されたが使用されていない変数(set and not used: p
    • src/lib9/utf/utflen.c:35: 到達不能なコード(unreachable code RETURN
    • src/lib9/utf/utfrrune.c:45: 到達不能なコード(unreachable code RETURN
    • src/lib9/utf/utfrune.c:44: 到達不能なコード(unreachable code RETURN

これらの警告は、コードの品質と保守性に影響を与える可能性があり、修正が必要とされていました。

変更の背景

Go言語は、その設計思想の一部として、シンプルさと堅牢性を重視しています。コンパイラの警告は、潜在的なバグや非効率なコード、あるいは意図しない動作を示す可能性があるため、これらを解消することはコードベースの健全性を保つ上で重要です。

このコミットで修正されているlib9は、Go言語の初期段階において、Plan 9オペレーティングシステムから移植されたC言語のライブラリ群です。Plan 9はベル研究所で開発された分散オペレーティングシステムであり、その設計思想はGo言語にも大きな影響を与えています。lib9は、Goのランタイムや標準ライブラリの一部として、ファイルシステム操作、文字列処理、フォーマットなど、低レベルの機能を提供していました。

警告の発生は、主に以下の理由が考えられます。

  1. コードの進化とデッドコード: 時間の経過とともにコードが変更され、以前は到達可能だったコードパスが、新しいロジックの導入によって到達不能になった。
  2. 未使用変数: 変数が宣言され、値が設定されたものの、その後の処理で一度も使用されなかった。これは、リファクタリングの過程で変数の必要性がなくなった場合や、単なるプログラミングミスによって発生します。
  3. Plan 9固有のビルド問題: Go言語はクロスプラットフォームを強く意識していますが、特定のOS(この場合はPlan 9)に特化したコードやビルド設定が存在する場合、他のOSとの間で不整合が生じることがあります。特に、C言語のヘッダーファイルのインクルードや、ポインタの型変換に関する問題は、異なるコンパイラや環境で顕在化しやすいです。

これらの問題を修正することで、Go言語のコードベース全体の品質が向上し、特にPlan 9環境でのビルドの安定性が確保されます。

前提知識の解説

1. Plan 9とlib9

  • Plan 9: ベル研究所で開発された分散オペレーティングシステム。Unixの設計思想をさらに推し進め、すべてのリソースをファイルとして扱うという徹底した思想が特徴です。Go言語の設計者の一部(Rob Pike, Ken Thompsonなど)はPlan 9の開発にも携わっており、Go言語にはPlan 9の思想が色濃く反映されています。
  • lib9: Plan 9のユーザー空間ライブラリ群を指します。Go言語の初期のランタイムや標準ライブラリの一部は、このlib9のC言語コードをベースに移植・再実装されました。低レベルのシステムコール、文字列操作、フォーマット、UTF-8処理など、基本的な機能を提供します。

2. C言語におけるコンパイラ警告

  • unreachable code (到達不能なコード): プログラムの実行フローが、特定のコードブロックに決して到達しないことを意味します。これは通常、return文、break文、continue文、または無限ループの後に続くコードで発生します。コンパイラは、このコードが実行されることがないため、警告を発します。これはデッドコードであり、削除するか、ロジックを修正する必要があります。
  • set and not used (設定されたが使用されていない変数): 変数が宣言され、初期値が設定されたにもかかわらず、その変数の値がプログラムのどこでも読み取られない場合に発生します。これは、プログラミングミス、またはリファクタリングの際に変数が不要になったにもかかわらず削除されなかった場合に起こります。未使用の変数はメモリを無駄にし、コードの可読性を低下させる可能性があります。

3. Goビルドタグ (// +build)

Go言語には、特定のファイルが特定の環境でのみコンパイルされるように制御するための「ビルドタグ」という仕組みがあります。ファイルの先頭に// +build tagのようなコメントを記述することで、そのファイルがコンパイルされる条件を指定できます。

  • // +build plan9: このタグが付いているファイルは、GoがPlan 9環境向けにビルドされる場合にのみコンパイルされます。
  • // +build !plan9: このタグが付いているファイルは、GoがPlan 9以外の環境向けにビルドされる場合にのみコンパイルされます。

これにより、OS固有のコードを分離し、クロスプラットフォーム対応を容易にしています。

4. C言語の型変換とポインタ

  • uintptr_t: C言語の標準ライブラリ<stdint.h>で定義されている型で、ポインタを保持できる十分な大きさを持つ符号なし整数型です。ポインタと整数の間で安全に変換を行うために使用されます。
  • void*: 任意の型のデータへのポインタを表す汎用ポインタ型です。void*から他のポインタ型への変換は暗黙的に行われることがありますが、明示的なキャストが推奨されます。
  • uintptr: Go言語におけるuintptr型は、ポインタを保持できる十分な大きさを持つ符号なし整数型です。C言語のuintptr_tに相当します。Goでは、ポインタとuintptrの間で直接的な変換は許可されておらず、unsafeパッケージを使用する必要があります。このコミットではC言語のコードを扱っているため、C言語のuintptr_tの概念が適用されます。

5. C言語の標準ライブラリ

  • <string.h>: C言語の標準ライブラリで、文字列操作関数(strlen, strcpy, memcpyなど)を提供します。
  • <u.h>: Plan 9のユーザー空間プログラミングにおける標準ヘッダーファイルの一つで、基本的な型定義やユーティリティ関数が含まれます。
  • <libc.h>: Plan 9のユーザー空間プログラミングにおける標準ヘッダーファイルの一つで、一般的なライブラリ関数が含まれます。
  • _BSD_SOURCE: BSD系のシステムコールやライブラリ関数を有効にするためのマクロです。通常、#define _BSD_SOURCEをインクルードする前に定義します。

技術的詳細

このコミットは、複数のファイルにわたる小規模な修正の集合体であり、それぞれが特定の警告や不整合に対処しています。

  1. src/lib9/errstr.c:

    • // +build !plan9タグが追加されました。これは、このファイルがPlan 9以外の環境でのみコンパイルされるべきであることを示します。errstr.cは、エラー文字列の処理に関するコードを含んでおり、Plan 9とそれ以外のOSでエラー処理のメカニズムが異なるため、条件付きコンパイルが必要になります。
    • #include <string.h>が削除されました。このファイル内でstring.hの関数が直接使用されていないか、または他のヘッダーファイル(例えば<libc.h>)を通じて必要な関数が提供されるようになったため、冗長なインクルードが削除されました。
  2. src/lib9/fmt/dorfmt.c:

    • dorfmt関数の末尾にあったreturn 0;が削除されました。元のコードでは、このreturn 0;は常に到達不能でした。これは、関数内のif(fmt == nil) return -1;の後に続くコードが、fmtnilでない場合にのみ実行され、そのパスのどこかで関数が終了するためです。この修正により、「unreachable code RETURN」警告が解消されます。
  3. src/lib9/fmt/errfmt.c:

    • このファイルは新規追加されました。
    • // +build plan9タグが付与されており、Plan 9環境でのみコンパイルされます。
    • __errfmt関数が定義されており、これはPlan 9のエラー文字列を取得し、フォーマットするためのものです。
    • rerrstr(buf, sizeof buf): Plan 9固有の関数で、システムのエラー文字列をbufに読み込みます。
    • __fmtcpy(f, buf, utflen(buf), strlen(buf)): フォーマット構造体fにエラー文字列bufをコピーします。utflenはUTF-8文字列の文字数を、strlenはバイト数を返します。これは、UTF-8対応のエラーメッセージ処理を示唆しています。
  4. src/lib9/fmt/fltfmt.c:

    • xsub1関数のabort()呼び出しの後にreturn 0;が追加されました。abort()はプログラムを異常終了させる関数ですが、コンパイラは関数の戻り値の型がvoidでない場合、すべてのコードパスでreturn文があることを期待します。abort()が呼び出された後、実際にはコードは実行されませんが、コンパイラの警告を抑制するために形式的にreturnが追加されました。
    • xfmtexp関数で、*p++ = '\0';*p = '\0';に修正されました。元のコードでは、ヌル終端文字を書き込んだ後にポインタpがインクリメントされていましたが、これは不要であり、場合によってはバッファオーバーランの潜在的な原因となる可能性がありました。修正により、ヌル終端文字を書き込んだ後もポインタpは元の位置に留まります。
    • xdtoa関数で、変数宣言の順序が変更されました。int oerrno;int d, e2, e, ee, i, ndigit;の後に移動しました。これは「set and not used: p」警告とは直接関係ありませんが、コードの可読性や特定のコンパイラでの警告抑制のために行われた可能性があります。元のコミットメッセージの警告はpに関するものでしたが、この変更はoerrnoに関するものであり、別の警告か、あるいは関連するクリーンアップの一部と考えられます。
  5. src/lib9/fmt/fmtfd.c:

    • f->farg = (void*)(uintptr_t)fd;f->farg = (void*)(uintptr)fd;に修正されました。これは、C言語のuintptr_t型ではなく、Go言語のuintptr型(またはそれに相当する型)へのキャストを意図している可能性があります。uintptr_tはC99で導入された型ですが、Goのコードベースではuintptrという用語が使われることが多いため、表記の統一を図ったか、あるいは特定のコンパイラ環境での警告を避けるための変更と考えられます。ポインタを整数に変換し、それを再度ポインタに変換する際に、適切な型キャストを行うことで、ポインタのサイズに関する警告や不整合を避けることができます。
  6. src/lib9/utf/utfecpy.c, src/lib9/utf/utfrrune.c, src/lib9/utf/utfrune.c, src/lib9/utf/utfutf.c:

    • これらのファイルでは、#define _BSD_SOURCE 1#include <string.h>が削除され、代わりに#include <u.h>#include <libc.h>が追加されました。これは、これらのUTF-8処理関連のファイルが、BSD固有の定義や標準Cライブラリのstring.hに依存するのではなく、Plan 9の標準ヘッダーファイルに依存するように変更されたことを意味します。これにより、Plan 9環境でのビルドの互換性が向上し、よりPlan 9ネイティブなアプローチに移行したことを示しています。
  7. src/lib9/utf/utflen.c:

    • utflen関数の末尾にあったreturn 0;が削除されました。dorfmt.cと同様に、このreturn 0;は常に到達不能でした。関数内のループが終了すると、nが返されるべきであり、このreturn 0;はデッドコードでした。この修正により、「unreachable code RETURN」警告が解消されます。

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

1. 到達不能なコードの削除 (src/lib9/fmt/dorfmt.c, src/lib9/utf/utflen.c)

--- a/src/lib9/fmt/dorfmt.c
+++ b/src/lib9/fmt/dorfmt.c
@@ -61,5 +61,4 @@ dorfmt(Fmt *f, const Rune *fmt)
 	\tif(fmt == nil)
 	\t\treturn -1;
 	}\n-\treturn 0;\t\t/* not reached */
 }\n
--- a/src/lib9/utf/utflen.c
+++ b/src/lib9/utf/utflen.c
@@ -32,5 +32,4 @@ utflen(const char *s)
 	\t\ts += chartorune(&rune, s);
 	\t\tn++;
 	}\n-\treturn 0;\n
 }\n

2. Plan 9固有のエラーフォーマットの追加 (src/lib9/fmt/errfmt.c)

--- /dev/null
+++ b/src/lib9/fmt/errfmt.c
@@ -0,0 +1,32 @@
+// +build plan9
+
+/*
+ * The authors of this software are Rob Pike and Ken Thompson,
+ * with contributions from Mike Burrows and Sean Dorward.
+ *
+ *     Copyright (c) 2002-2006 by Lucent Technologies.
+ *     Portions Copyright (c) 2004 Google Inc.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES 
+ * NOR GOOGLE INC MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING 
+ * THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+#include <u.h>
+#include <libc.h>
+#include "fmtdef.h"
+
+int
+__errfmt(Fmt *f)
+{
+	char buf[ERRMAX];
+
+	rerrstr(buf, sizeof buf);
+	return __fmtcpy(f, buf, utflen(buf), strlen(buf));
+}

3. ヘッダーファイルの変更とビルドタグの追加 (src/lib9/errstr.c, src/lib9/utf/utfecpy.cなど)

--- a/src/lib9/errstr.c
+++ b/src/lib9/errstr.c
@@ -1,3 +1,5 @@
+// +build !plan9
+
 /*
 Plan 9 from User Space src/lib9/errstr.c
 http://code.swtch.com/plan9port/src/tip/src/lib9/errstr.c
@@ -32,7 +34,6 @@ THE SOFTWARE.
 
 #include <u.h>
 #include <errno.h>
-#include <string.h>
 #include <libc.h>\n
--- a/src/lib9/utf/utfecpy.c
+++ b/src/lib9/utf/utfecpy.c
@@ -11,8 +11,8 @@
  * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
  * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
  */
-#define _BSD_SOURCE 1
-#include <string.h>
+#include <u.h>
+#include <libc.h>\n
 #include "utf.h"\n
 #include "utfdef.h"\n

コアとなるコードの解説

1. 到達不能なコードの削除

dorfmt関数とutflen関数からreturn 0;が削除されたのは、これらのreturn文がコードの実行パス上、決して到達しない位置にあったためです。C言語のコンパイラは、このようなデッドコードに対して警告を発します。関数が値を返す場合、すべての可能な実行パスでreturn文が存在する必要がありますが、このケースでは、それより前のreturn文やループの終了によって、このreturn 0;に到達することがありませんでした。これにより、コンパイラの警告が解消され、コードがよりクリーンになりました。

2. Plan 9固有のエラーフォーマットの追加

src/lib9/fmt/errfmt.cの追加は、Plan 9環境に特化したエラーメッセージのフォーマット処理を導入したことを示しています。

  • // +build plan9タグにより、このファイルはPlan 9向けビルドでのみコンパイルされます。
  • __errfmt関数は、Plan 9のシステムコールrerrstrを使用してエラー文字列を取得し、それを__fmtcpy関数でフォーマットバッファにコピーします。
  • utflen(buf)strlen(buf)の両方を使用していることから、エラーメッセージがUTF-8エンコードされている可能性があり、文字数とバイト数の両方を考慮して正確に処理していることがわかります。 この変更により、Plan 9環境でのエラー報告が適切に行われるようになります。

3. ヘッダーファイルの変更とビルドタグの追加

src/lib9/errstr.c// +build !plan9タグが追加され、#include <string.h>が削除されたことは、このファイルがPlan 9以外の環境向けのエラー文字列処理を担当し、Plan 9固有のヘッダーファイルや機能に依存しないことを明確にしています。

また、src/lib9/utfディレクトリ内の複数のファイルで_BSD_SOURCEマクロと<string.h>のインクルードが削除され、代わりに<u.h><libc.h>が追加されたことは、これらのUTF-8処理関連のコードが、BSD互換性レイヤーや標準Cライブラリではなく、Plan 9のネイティブなライブラリとヘッダーに依存するように変更されたことを意味します。これにより、Plan 9環境でのビルドの整合性が向上し、よりPlan 9の慣習に沿ったコードベースになりました。

これらの変更は全体として、Go言語のlib9部分が、各ターゲットOS(特にPlan 9)の特性に合わせて適切にビルドされ、コンパイラの警告を解消し、コードの品質と保守性を向上させることを目的としています。

関連リンク

参考にした情報源リンク