プログラムを書いているときには当然色々ミスをするが、GCC(gcc/g++)が出すメッセージは Clang(clang/clang++)に比べて分かりにくい/不親切なことが多い。
例えば、FooBarという名前のクラスが宣言されていて、それを使おうとしたときに以下のように間違ってFooBazと書いたとする。
int main(int, char**){ FooBaz foobar; }
g++-5.4.0でコンパイルした場合のメッセージは以下のようになる。
g++ -g -Wall -Wextra -c -o main.o main.cpp main.cpp: In function 'int main(int, char**)': main.cpp:9:5: error: 'FooBaz' was not declared in this scope FooBaz foobar; ^
最新のg++-6.2では、エラーの位置を示す'^'が波線(~~~~~~)になるが、内容は特に変わらない。
/usr/local/gcc-6.2.0/bin/g++ -g -Wall -Wextra -c -o main.o main.cpp main.cpp: In function 'int main(int, char**)': main.cpp:9:5: error: 'FooBaz' was not declared in this scope FooBaz foobar; ^~~~~~
clang++-3.8では以下のように修正候補を挙げてくれる。
clang++ -g -Wall -Wextra -c -o main.o main.cpp main.cpp:9:5: error: unknown type name 'FooBaz'; did you mean 'FooBar'? FooBaz foobar; ^~~~~~ FooBar main.cpp:3:7: note: 'FooBar' declared here class FooBar { ^ 1 error generated.
あるいは、以下のように文末のセミコロンを忘れた場合、
int main(int, char**){ FooBaz foobar foobar.method1(); }
g++-5.4、g++-6.2、clang++-3.8でコンパイルした結果はそれぞれ以下のようになる。
# g++-5.4 g++ -g -Wall -Wextra -c -o main.o main.cpp main.cpp: In function 'int main(int, char**)': main.cpp:10:5: error: expected initializer before 'foobar' foobar.method1(); ^ # g++-6.2 /usr/local/gcc-6.2.0/bin/g++ -g -Wall -Wextra -c -o main.o main.cpp main.cpp: In function 'int main(int, char**)': main.cpp:10:5: error: expected initializer before 'foobar' foobar.method1(); ^~~~~~ # clang++-3.8 clang++ -g -Wall -Wextra -c -o main.o main.cpp main.cpp:9:18: error: expected ';' at end of declaration FooBar foobar ^ ; 1 error generated.
g++では、セミコロンを忘れた行の次の行がエラーとなっているが(普通に解析したらそうなるだろう)、clang++ではちゃんと「セミコロンがない」というメッセージになっている。
これがClangを使う一つの理由だったのだが、Phoronixの記事によれば、GCC7ではエラーメッセージか改善され、タイプミスに対する修正のヒント(Fix-it hints)を出すようになるらしい。
また、その場所にアンダーラインが引かれる、セミコロンがないことに関するFix-it hintsを出す、などと書かれているで、多分Clangと似たような感じになるのだろう。
一昔前まで、フリーで使えるC/C++コンパイラと言えばGCC一択だったところにClangの登場し、GCCにない機能が色々使えるようになったが、それに刺激されたGCCも改善が進んでいるようだ。