gcc は include 失敗してもコンパイルが止まらない

例えば、hoge_t という(typedef された)構造体の定義が hoge.h にあるとすると、

#include "hoge.h"
int main(void) {
  hoge_t a;
  hoge_t b;
  return 0;
}

これで、hoge.h が include パスに存在しない時、

% gcc test.c
test.c:1:18: error: hoge.h: No such file or directory
test.c: In function ‘main’:
test.c:3: error: ‘hoge_t’ undeclared (first use in this function)
test.c:3: error: (Each undeclared identifier is reported only once
test.c:3: error: for each function it appears in.)
test.c:3: error: expected ‘;’ before ‘a’
test.c:4: error: expected ‘;’ before ‘b’

のようになる。

10数年近く C 言語と格闘してる自分は、'hoge_t' undeclared を見れば、「はいはい include パス include パス」とか言って、No such file or directory のファイルの場所を確認する程度には慣れてるので困ってはないけど、大量のエラーメッセージが目に悪いのは確か。

gcc のオプションに include に失敗した時点でコンパイルを止めるのがあればいいのに。

逆インクルードガード

@do_aki さんから提案を頂きました。

ソースコードに手を加えるなら、インクルードガードと逆をやることで
できそうですが。 ifndef で error にする

必要な include が取り込まれてない場合に、#ifndef で error にする手法は、よくヘッダファイルのバージョン依存チェックで使われますね。

// #include "hoge.h"
#ifndef __HOGE_H__
#error "hoge.h must be included"
#endif
int main(void) {
  hoge_t a;
  hoge_t b;
  return 0;
}
% gcc test.c
test.c:3:2: error: #error "hoge.h must be included"
test.c: In function ‘main’:
test.c:6: error: ‘hoge_t’ undeclared (first use in this function)
test.c:6: error: (Each undeclared identifier is reported only once
test.c:6: error: for each function it appears in.)
test.c:6: error: expected ‘;’ before ‘a’
test.c:7: error: expected ‘;’ before ‘b’

コンパイルが通らない事は保障できるけど、レベルが error なのでコンパイルを途中で止められませんでした。
#fatal があればいいのに。

実は gcc-4.5 で対応済み

結構前に要望が上がっていて最近の gcc では対応済みでした。thank you > @uebayasi さん

gcc should have an option to treat missing includes as fatal, and stop
compilation immediately.

gcc-4.5 の ChangeLog に記載があります。

If a header named in a #include directive is not found, the compiler exits immediately.
This avoids a cascade of errors arising from declarations expected to be found in that header being missing.

メジャーな OS のパッケージの gcc が 4.5 になるのは、もう少しかかるかも。前のめりな MacOS ならそろそろって気がしますけど。