Using STLFilt with MinGW

From Code::Blocks


What is STLFilt

STLFilt is an STL error message decryptor for C++. A more detailed description (taken from STLFilt webpage):

STLFilt simplifies and/or reformats long-winded C++ error and warning messages, with a focus on STL-related diagnostics. The result renders many of even the most cryptic diagnostics comprehensible.

STLFilt supports the following compilers:

  • Comeau C++ (comofilt)
  • GCC 2.95.x/3.x/4.x (gstlfilt)
  • MSVC++ 6/7/8/9 (incl. Dinkum Libraries) (stlfilt)
  • Metrowerks CodeWarrior Pro 7/8 (cwfilt)
  • Borland C++ / C++Builder (bccfilt)
  • Intel C++ 7/8 (intelfilt)
  • EDG Front End (Generic) (edgfilt)
  • Digital Mars C++ (dmcfilt)

This article will be focusing on gSTLFilt used with Code::Blocks MinGW bundled package for Microsoft Windows platform.

Installing STLFilt

Because the core of STLFilt is a perl script you will need to have a perl distribution installed, such as ActivePerl

STLFilt is distributed as an zip archive, which can be downloaded from here.

From the STLFilt archive you will be needing the following files: c++.exe, Proxy-gcc.INI, and gSTLFilt.pl

The installation steps are:

  • Rename "c:\Program Files\CodeBlocks\MinGW\bin\mingw32-g++.exe" to mingw32-g++2.exe
  • Copy gstlfilt.zip\c++.exe to c:\Program Files\CodeBlocks\MinGW\bin\ and rename it as mingw32-g++.exe
  • Copy gstlfilt.zip\gSTLFilt.pl to c:\Program Files\CodeBlocks\MinGW\bin\
  • Copy gstlfilt.zip\Proxy-gcc.INI to %windir% (for example: c:\windows)
  • Create an empty file named filtering.on in c:\Program Files\CodeBlocks\MinGW\bin\
  • Edit %windir%\Proxy-gcc.INI under [common]
filter_script=c:\Program Files\CodeBlocks\MinGW\bin\gSTLFilt.pl
toggle_file_dir=c:\Program Files\CodeBlocks\MinGW\bin\                    
native_gcc=mingw32-g++2.exe                     
perl_exe=c:\perl\bin\perl.exe

Testing STLFilt

Here is a test program:

#include <iostream>
#include <map>
#include <string>
#include <iterator>

using namespace std;

int main()
{
    map<int, string> months;

    months.insert(1, "January");
    months.insert(2, "February");

    copy(months.begin(), months.end(), ostream_iterator<pair<int, string> >(cout, "; "));
}

The error message without STLFilt is:

Compiling: main.cpp
D:\projects\edu\c++\testcb\main.cpp: In function `int main()':
D:\projects\edu\c++\testcb\main.cpp:12: error: no matching function for call to `std::map<int, std::string, std::less<int>, std::allocator<std::pair<const int, std::string> > >::insert(int, const char[8])'
C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_map.h:360: note: candidates are: std::pair<typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, _Alloc>::iterator, bool> std::map<_Key, _Tp, _Compare, _Alloc>::insert(const std::pair<const _Key, _Tp>&) [with _Key = int, _Tp = std::string, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, std::string> >]
C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_map.h:384: note:                 typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, _Alloc>::iterator std::map<_Key, _Tp, _Compare, _Alloc>::insert(typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, _Alloc>::iterator, const std::pair<const _Key, _Tp>&) [with _Key = int, _Tp = std::string, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, std::string> >]
D:\projects\edu\c++\testcb\main.cpp:13: error: no matching function for call to `std::map<int, std::string, std::less<int>, std::allocator<std::pair<const int, std::string> > >::insert(int, const char[9])'
C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_map.h:360: note: candidates are: std::pair<typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, _Alloc>::iterator, bool> std::map<_Key, _Tp, _Compare, _Alloc>::insert(const std::pair<const _Key, _Tp>&) [with _Key = int, _Tp = std::string, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, std::string> >]
C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_map.h:384: note:                 typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, _Alloc>::iterator std::map<_Key, _Tp, _Compare, _Alloc>::insert(typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, _Alloc>::iterator, const std::pair<const _Key, _Tp>&) [with _Key = int, _Tp = std::string, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, std::string> >]
C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stream_iterator.h: In member function `std::ostream_iterator<_Tp, _CharT, _Traits>& std::ostream_iterator<_Tp, _CharT, _Traits>::operator=(const _Tp&) [with _Tp = std::pair<int, std::string>, _CharT = char, _Traits = std::char_traits<char>]':
C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_algobase.h:234:   instantiated from `_OutputIterator std::__copy(_InputIterator, _InputIterator, _OutputIterator, std::input_iterator_tag) [with _InputIterator = std::_Rb_tree_iterator<std::pair<const int, std::string> >, _OutputIterator = std::ostream_iterator<std::pair<int, std::string>, char, std::char_traits<char> >]'
C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_algobase.h:266:   instantiated from `_OutputIterator std::__copy_aux2(_InputIterator, _InputIterator, _OutputIterator, __false_type) [with _InputIterator = std::_Rb_tree_iterator<std::pair<const int, std::string> >, _OutputIterator = std::ostream_iterator<std::pair<int, std::string>, char, std::char_traits<char> >]'
C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_algobase.h:308:   instantiated from `_OutputIterator std::__copy_ni2(_InputIterator, _InputIterator, _OutputIterator, __false_type) [with _InputIterator = std::_Rb_tree_iterator<std::pair<const int, std::string> >, _OutputIterator = std::ostream_iterator<std::pair<int, std::string>, char, std::char_traits<char> >]'
C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_algobase.h:327:   instantiated from `_OutputIterator std::__copy_ni1(_InputIterator, _InputIterator, _OutputIterator, __false_type) [with _InputIterator = std::_Rb_tree_iterator<std::pair<const int, std::string> >, _OutputIterator = std::ostream_iterator<std::pair<int, std::string>, char, std::char_traits<char> >]'
C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_algobase.h:358:   instantiated from `_OutputIterator std::copy(_InputIterator, _InputIterator, _OutputIterator) [with _InputIterator = std::_Rb_tree_iterator<std::pair<const int, std::string> >, _OutputIterator = std::ostream_iterator<std::pair<int, std::string>, char, std::char_traits<char> >]'
D:\projects\edu\c++\testcb\main.cpp:15:   instantiated from here
C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stream_iterator.h:196: error: no match for 'operator<<' in '*((std::ostream_iterator<std::pair<int, std::string>, char, std::char_traits<char> >*)this)->std::ostream_iterator<std::pair<int, std::string>, char, std::char_traits<char> >::_M_stream << __value'
C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/ostream.tcc:63: note: candidates are: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>&(*)(std::basic_ostream<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>]
C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/ostream.tcc:74: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ios<_CharT, _Traits>&(*)(std::basic_ios<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>]
C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/ostream.tcc:86: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::ios_base&(*)(std::ios_base&)) [with _CharT = char, _Traits = std::char_traits<char>]
C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/ostream.tcc:121: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long int) [with _CharT = char, _Traits = std::char_traits<char>]
C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/ostream.tcc:155: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long unsigned int) [with _CharT = char, _Traits = std::char_traits<char>]
C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/ostream.tcc:98: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(bool) [with _CharT = char, _Traits = std::char_traits<char>]
C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/ostream:178: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short int) [with _CharT = char, _Traits = std::char_traits<char>]
C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/ostream:189: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short unsigned int) [with _CharT = char, _Traits = std::char_traits<char>]
C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/ostream:193: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(int) [with _CharT = char, _Traits = std::char_traits<char>]
C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/ostream:204: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(unsigned int) [with _CharT = char, _Traits = std::char_traits<char>]
C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/ostream.tcc:179: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long long int) [with _CharT = char, _Traits = std::char_traits<char>]
C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/ostream.tcc:214: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long long unsigned int) [with _CharT = char, _Traits = std::char_traits<char>]
C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/ostream.tcc:238: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(double) [with _CharT = char, _Traits = std::char_traits<char>]
C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/ostream:219: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(float) [with _CharT = char, _Traits = std::char_traits<char>]
C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/ostream.tcc:261: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long double) [with _CharT = char, _Traits = std::char_traits<char>]
C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/ostream.tcc:284: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(const void*) [with _CharT = char, _Traits = std::char_traits<char>]
C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/ostream.tcc:307: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_streambuf<_CharT, _Traits>*) [with _CharT = char, _Traits = std::char_traits<char>]
Process terminated with status 1 (0 minutes, 1 seconds)
3 errors, 0 warnings

And now the error message with STLFilt enabled:

Compiling: main.cpp
D:\projects\edu\c++\testcb\main.cpp: In function `int main()':
D:\projects\edu\c++\testcb\main.cpp:12: error: No match for 
   `map<int, string>::insert(int, const char[8])'
D:\projects\edu\c++\testcb\main.cpp:13: error: No match for 
   `map<int, string>::insert(int, const char[9])'
stream_iterator.h: In member function 
   `ostream_iterator<pair<int, string>, char, char_traits<char> > &
    ostream_iterator<pair<int, string>, char, char_traits<char> >::operator=(
	const pair<int, string> &
    )':
stl_algobase.h:234:   instantiated from 
   `ostream_iterator<
	pair<int, string>, char, char_traits<char> 
    > __copy(
	iter, iter
      , ostream_iterator<pair<int, string>, char, char_traits<char> >
      , input_iterator_tag
    )'
    [STL Decryptor: Suppressed 4 more STL standard header messages]
D:\projects\edu\c++\testcb\main.cpp:15:   instantiated from here
stream_iterator.h:196: error: no match for 'operator<<' in '*(
	(ostream_iterator<pair<int, string>, char, char_traits<char> > *)this
    )->ostream_iterator<pair<int, string>, char, char_traits<char> >
    ::_M_stream << __value'
STL Decryptor reminders:
    Use the /hdr:L option to see all suppressed standard lib headers
    Use the /cand:L option to see all suppressed template candidates
Process terminated with status 1 (0 minutes, 2 seconds)
3 errors, 0 warnings

Removing Perl as a dependency

In order to remove perl as a dependency one needs to transform gSTLFilt.pl into an executable, here are two ways:

By using PAR and pp

set path=%path%;c:\perl\bin;"c:\Program Files\CodeBlocks\MinGW\bin\"
cpan
install PAR
install pp
q
set path=%path%;c:\Perl\site\bin\
pp gSTLFilt.pl -o gSTLFilt.exe

This takes allot of time and the resulted binary gSTLFilt.exe is 2.5Mb in size with a speed penalty and high CPU usage at first run, on subsequent runs the CPU usage is high for one to two seconds.

The binary is an executable containing a zip file with required parts of perl to execute property the perl script.

By using Perl2Exe

You don't need to install perl for this to work. The resulted binary size is 500kb, there is no high CPU usage at first run. The downfall is that you have a message nag for two seconds at exit (only for the shareware version).

In order to use gSTLFilt.exe instead of gSTLFilt.pl you should modify %windir%\Proxy-gcc.INI like this:

filter_script=.
perl_exe=c:\Program Files\CodeBlocks\MinGW\bin\gSTLFilt.exe

The dot for filter_script will give a Warning, but other than that it should work fine.