1

I'm trying to compile the following seemingly simple code using GCC 3.4.6 and Boost 1.43 and it's generating an internal compiler error:

#include <string>
#include <boost/spirit/include/lex_lexertl.hpp>
#include <boost/spirit/include/qi.hpp>

namespace lex    = boost::spirit::lex;
namespace qi     = boost::spirit::qi;

typedef lex::lexertl::token<std::string::iterator> TokenT;
typedef lex::lexertl::actor_lexer<TokenT> LexerT;

template <typename LexerT>
struct Tokens: public lex::lexer<LexerT>
{};

int main()
{
   typedef Tokens<LexerT>::iterator_type IteratorT;
   qi::rule<IteratorT, int> expression;

   expression = (qi::int_ >> qi::int_) [ qi::_val = qi::_1 ];
}

The generated error:

.../boost/mpl/aux_/preprocessed/gcc/template_arity.hpp:83: internal compiler error: in lookup_member, at cp/search.c:1300

The last line in main() is generating this error. This error goes away by either letting the expression rule work on an std::string::iterator instead of IteratorT.

Any help with fixing the error while still working with a lexer is much appreciated.

Thanks!

Haitham Gad
  • 1,529
  • 2
  • 13
  • 23
  • 2
    first off... get a newer compiler. Is this cygwin? Use mingw, link: http://mingw-w64.sourceforge.net/ (4.7.1 in [64bit](http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/rubenvb/release/) and [32bit](http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/rubenvb/release/) here) – sehe Jul 17 '12 at 21:31
  • Current [GCC](http://gcc.gnu.org/) is 4.7.1. Version 3.4.6 is very, very old (circa March 2006). – Jonathan Leffler Jul 17 '12 at 21:32
  • I know it's an old compiler, but that's the latest one supported by the build environment at my work place, so I have no choice! BTW: I made some edits to the question. It seems it has nothing to do with deferred function objects. It's the lexer! – Haitham Gad Jul 17 '12 at 21:43
  • What build environment only supports GCC 3.4.6? No actual *build* environment I know of. – rubenvb Jul 18 '12 at 08:23
  • It's not really about the build environment I guess (which is internally-built in our case). It's more about the platforms we support (RHEL 3 & 4) and the default compiler and C libraries available on them. Life isn't ideal when it comes to business you know :) – Haitham Gad Jul 18 '12 at 12:04
  • @HaithamGad as I've argued [more in-depth on the \[spirit-general\] list](http://boost.2283326.n4.nabble.com/Internal-compiler-error-with-Boost-1-43-and-GCC-3-4-6-tp4633170p4633239.html), I think in this sad case you'd have to accept that Boost Spirit is simply not supported on your platforms. Don't use it. That's business reality for you in my opinion... – sehe Jul 18 '12 at 20:55

1 Answers1

1

You missed the parens:

qi::rule<IteratorT, int()> expression;

This might fix the compile error (allthough I can't check, since both gcc, clang and msvc happily compiled it)


You may want to reduce the compiler stress:

  • increase available RAM
  • decrease limits (see below)
  • disable debug information (-g0)
  • and optimizations (-O0; alternatively, optimize for size -Os)

Possibly more in that region.

LIMITS

I did a simple

grep -EoRh '\<\w+_LIMIT\>' ~/custom/boost_1_50_0/boost/spirit/home/ -h | sort -u

to get a list of possible defines, and based a following change on it:

#ifdef LEAN
#define PHOENIX_ACTOR_LIMIT      3 // boost 1_50 default: 10
#define PHOENIX_ARG_LIMIT        5 // boost 1_50 default: 10
#define PHOENIX_CATCH_LIMIT      1 // boost 1_50 default:  9
#define PHOENIX_COMPOSITE_LIMIT  5 // boost 1_50 default: 10
#define PHOENIX_DYNAMIC_LIMIT    1 // boost 1_50 default: 10
#define PHOENIX_LIMIT            5 // boost 1_50 default: 10
#define PHOENIX_LOCAL_LIMIT      3 // boost 1_50 default: 10
#define PHOENIX_MEMBER_LIMIT     3 // boost 1_50 default:  8
#define SPIRIT_ARGUMENTS_LIMIT   5 // boost 1_50 default: 10
#define SPIRIT_ATTRIBUTES_LIMIT  5 // boost 1_50 default: 10
#endif

#include <string>
#include <boost/spirit/include/lex_lexertl.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_function.hpp>
#include <boost/spirit/include/phoenix.hpp>

namespace lex    = boost::spirit::lex;
namespace qi     = boost::spirit::qi;
namespace phx    = boost::phoenix;

struct funcImpl
{
   template <typename T>
   struct result { typedef int type; };

   template <typename T>
   int operator()(T& x) const {
      return 0;
   }
};

typedef lex::lexertl::token<std::string::iterator> TokenT;
typedef lex::lexertl::actor_lexer<TokenT> LexerT;

template <typename LexerT>
struct Tokens: public lex::lexer<LexerT>
{};

int main()
{
   //typedef Tokens<LexerT>::iterator_type IteratorT;
   typedef char* IteratorT;
   qi::rule<IteratorT, int()> expression;

   phx::function<funcImpl> func = funcImpl();
   expression = (qi::int_ >> qi::int_) [ qi::_val = func(qi::_1) ];


   std::cout   << "#define PHOENIX_ACTOR_LIMIT "                       << PHOENIX_ACTOR_LIMIT                       << '\n';
   std::cout   << "#define PHOENIX_ARG_LIMIT "                         << PHOENIX_ARG_LIMIT                         << '\n';
   std::cout   << "#define PHOENIX_CATCH_LIMIT "                       << PHOENIX_CATCH_LIMIT                       << '\n';
   std::cout   << "#define PHOENIX_COMPOSITE_LIMIT "                   << PHOENIX_COMPOSITE_LIMIT                   << '\n';
   std::cout   << "#define PHOENIX_DYNAMIC_LIMIT "                     << PHOENIX_DYNAMIC_LIMIT                     << '\n';
   std::cout   << "#define PHOENIX_LIMIT "                             << PHOENIX_LIMIT                             << '\n';
   std::cout   << "#define PHOENIX_LOCAL_LIMIT "                       << PHOENIX_LOCAL_LIMIT                       << '\n';
   std::cout   << "#define PHOENIX_MEMBER_LIMIT "                      << PHOENIX_MEMBER_LIMIT                      << '\n';
   std::cout   << "#define SPIRIT_ARGUMENTS_LIMIT "                    << SPIRIT_ARGUMENTS_LIMIT                    << '\n';
   std::cout   << "#define SPIRIT_ATTRIBUTES_LIMIT "                   << SPIRIT_ATTRIBUTES_LIMIT                   << '\n';
   //std::cout << "#define BOOST_PHOENIX_LIMIT "                       << BOOST_PHOENIX_LIMIT                       << '\n';
   //std::cout << "#define BOOST_SPIRIT_CLOSURE_LIMIT "                << BOOST_SPIRIT_CLOSURE_LIMIT                << '\n';
   //std::cout << "#define BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT " << BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT << '\n';
   //std::cout << "#define BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT "       << BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT       << '\n';
   //std::cout << "#define BOOST_SPIRIT_SELECT_LIMIT "                 << BOOST_SPIRIT_SELECT_LIMIT                 << '\n';
   //std::cout << "#define BOOST_SPIRIT_SWITCH_CASE_LIMIT "            << BOOST_SPIRIT_SWITCH_CASE_LIMIT            << '\n';
   //std::cout << "#define PHOENIX_CONSTRUCT_LIMIT "                   << PHOENIX_CONSTRUCT_LIMIT                   << '\n';
   //std::cout << "#define SPIRIT_CLOSURE_LIMIT "                      << SPIRIT_CLOSURE_LIMIT                      << '\n';
}

Now, the following size changes happen (in LoC preprocessed):

sehe@mint12:/tmp$ g++ -g0 -O0 -I /home/sehe/custom/boost_1_50_0/ test.cpp -E | wc -l
193011
sehe@mint12:/tmp$ g++ -g0 -O0 -I ./boost_1_43_0/ test.cpp -DLEAN -E | wc -l
168862

basically, a >10% reduction in code lines. It just might help.

sehe
  • 374,641
  • 47
  • 450
  • 633
  • Thanks for the suggestion. Unfortunately, it doesn't fix it! – Haitham Gad Jul 17 '12 at 21:45
  • @HaithamGad I added some more hints/tweaks that _might_ help you get this past the compiler. I still think you should use a newer compiler. There is no platform where GNU 3.4 is supported anymore anyway. It's rarely hard to extract a tarball in a local directory and just use the binaries from there. IME, this usually works from embedded systems to AIX, Solaris etc.: http://gcc.gnu.org/install/binaries.html – sehe Jul 17 '12 at 22:31
  • Thanks Seth. I use a newer compiler at home, and I had my code compiling on it, but when I try the version at my workplace it keeps breaking. The thing is, we release our products on RedHat Enterprise Linux 3 & 4 and this is the default compiler version on these ancient platforms. I tried you're code, but it's still breaking. Anyway, never mind. I think it has to do with a combination of the usage of the lexer, the sequencing operator and the use of semantic actions. I'll try tweaking the code until it compiles. – Haitham Gad Jul 17 '12 at 23:05
  • I pasted all the errors here in case anyone can decipher any of them: http://pastebin.com/BMPCSUzc – Haitham Gad Jul 18 '12 at 06:57