C++コンパイラ GCCとClangからのメッセージをお読みください
Upcoming SlideShare
Loading in...5
×

Like this? Share it with your network

Share

C++コンパイラ GCCとClangからのメッセージをお読みください

  • 5,005 views
Uploaded on

 

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
5,005
On Slideshare
4,969
From Embeds
36
Number of Embeds
3

Actions

Shares
Downloads
19
Comments
0
Likes
4

Embeds 36

https://twitter.com 30
http://a0.twimg.com 5
http://paper.li 1

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. C++コンパイラ GCCとClangからのメッセージをお読みください
  • 2. お詫びとおことわり● うっかり自宅のclangにアクセスできなくして しまったので、一部のサンプルコード(のエ ラーメッセージ)を掲載できなくなってしまい ました。● なので実感のつかみにくいかもしれませんがご 了承ください。
  • 3. GCCのエラーといえば /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h: In function ‘void std::sort(_RAIter, _RAIter) [with _RAIter = std::_List_iterator<int>]’: prog.cpp:6: instantiated from here /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h:4783: error: no match for ‘operator-’ in ‘__last - __first’ /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h: In function ‘void std::__final_insertion_sort(_RandomAccessIterator, _RandomAccessIterator) [with _RandomAccessIterator = std::_List_iterator<int>]’: /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h:4785: instantiated#include <list> from ‘void std::sort(_RAIter, _RAIter) [with _RAIter = std::_List_iterator<int>]’ prog.cpp:6: instantiated from here#include <algorithm> /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h:1827: error: no match for ‘operator-’ in ‘__last - __first’ /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h:1829: error: no match for ‘operator+’ in ‘__first + 16’int main() { /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h:1830: error: no match for ‘operator+’ in ‘__first + 16’ std::list<int> l; /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h: In function ‘void std::__insertion_sort(_RandomAccessIterator, _RandomAccessIterator) [with _RandomAccessIterator = std::_List_iterator<int>]’: std::sort(l.begin(), /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h:1833: instantiated from ‘void std::__final_insertion_sort(_RandomAccessIterator, l.end()); _RandomAccessIterator) [with _RandomAccessIterator = std::_List_iterator<int>]’ /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h:4785: instantiated} from ‘void std::sort(_RAIter, _RAIter) [with _RAIter = std::_List_iterator<int>]’ prog.cpp:6: instantiated from here /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h:1753: error: no match for ‘operator+’ in ‘__first + 1’ /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h:1833: instantiated from ‘void std::__final_insertion_sort(_RandomAccessIterator, _RandomAccessIterator) [with _RandomAccessIterator = std::_List_iterator<int>]’ /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h:4785: instantiated from ‘void std::sort(_RAIter, _RAIter) [with _RAIter = std::_List_iterator<int>]’ prog.cpp:6: instantiated from here /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h:1759: error: no match for ‘operator+’ in ‘__i + 1’ !!!非常に明解で分かりやすい!!!
  • 4. 熟練の暗号解読班の定石手段● エラーメッセージから “instantiated from here” を探す● そこからエラーメッセージを逆に辿りながら、 実体化された型や関数呼び出しをドキュメント と照合する ● テンプレート引数は要件を満たしているか ● 実体化されたテンプレートの定義は意図したものか
  • 5. 熟練の暗号解読班の定石手段● boost::mpl::eval_if<boost::mpl::apply<boost ::remove_reference<boost::mpl::placeholders ::…… ● perl -ple s/(?:w+::)*//g● boost::fusion::vector<hoge, fuga, piyo, void_, void_, void_, void_, void_, void_, void_, …… ● perl -ple s/,void_//g;● STLfilt
  • 6. 一方新兵はClangを使った● ヴィジュアルで位置を指摘してくれる! /usr/include/c++/4.3/bits/stl_algo.h:4784:22: error: invalid operands to binary expression (std::_List_iterator<int> and std::_List_iterator<int>) std::__lg(__last - __first) * 2); ~~~~~~ ^ ~~~~~~~● マクロ展開後のコードのエラーならそれも追っ てくれる! for FOO(1); f /tmp/webcompile/_20978_0.cc:6:5: error: no matching function call to ^~~ ● void f() {} /tmp/webcompile/_20978_0.cc:2:13: note: instantiated from: #define FOO BAR #define FOO BAR ^ #define BAR f /tmp/webcompile/_20978_0.cc:3:13: note: instantiated from: #define BAR f int main() { ^ FOO(1); /tmp/webcompile/_20978_0.cc:1:6: note: candidate function not } viable: requires 0 arguments, but 1 was provided void f() {} ^ 1 error generated. Clang大勝利!!!
  • 7. ところがnamespace ns { struct z {}; template<typename T> struct s {}; template<typename T> auto f(s<T> x) -> decltype(f(T())) { return f(T()); } template<typename T> struct a { static_assert(sizeof(T) && false, "failed"); }; template<typename T = int> auto f(z x) -> decltype(a<T>(), 1) { return 0; } s<s<s<z> > > three;}int main() { これを現行のClangとGCCでコンパイルすると f(ns::three);} f(ns::three); の関数呼びだしを解決できなかった という旨のメッセージを吐く
  • 8. ところが● 先のコードは、再帰的な実体化を試みた末auto f(z)-> decltype(a<T>, 0)の実体化に失敗するのが原因 ● f(ns::three)の呼び出し解決するためにauto f(s<s<z> >)を実体化しよ うとする。 ● 戻り値の型を求めるためにf(T())の呼び出し解決をしようとする – その呼び出しを解決するためにf(s<z>)を(ry ● その解決のためにf(z)を解決しようとして、失敗する – f(T())の呼び出し解決に失敗する ● f(T())の(ry ● f(ns::three)の呼び出し解決に失敗する ● f(ns::three)の呼び出しがエラーとなる
  • 9. ところが● 先のコードは、再帰的な実体化を試みた末auto f(z)-> decltype(a<T>, 0)の実体化に失敗するのが原因 ● f(ns::three)の呼び出し解決するためにauto f(s<s<z> >)を実体化しよ うとする。 ● 戻り値の型を求めるためにf(T())の呼び出し解決をしようとする – その呼び出しを解決するためにf(s<z>)を(ry ● その解決のためにf(z)を解決しようとして、失敗する – f(T())の呼び出し解決に失敗する ● f(T())の(ry ● f(ns::three)の呼び出し解決に失敗する ● f(ns::three)の呼び出しがエラーとなる
  • 10. 老兵再び● Clangには呼び出し解決に失敗した場合、各呼び 出し候補について、その候補が選ばれなかった 理由を表示する機能がある。● GCC4.7にも同様の機能が付いたが、こちらはあ る候補の選択されなかった理由が「関数の呼び 出し解決失敗」である場合、その呼び出しの候 補と失敗理由についても再帰的に表示してくれ る GCC(>=4.7)大勝利!!!
  • 11. まとめ● 両方でコンパイルできるようにコードを書い て、適切に使い分けましょう
  • 12. 問題● ドキュメントがない部分(内部実装など)を通る と、どの実体化でおかしくなったのか判別する ことが困難 ● See: PStade.Oven