Re: [Boost-bugs] [Boost C++ Libraries] #6126: Signed integer members of Boost.Fusion adapted ADTs are not output correctly with Boost.Spirit.Karma rules

Subject: Re: [Boost-bugs] [Boost C++ Libraries] #6126: Signed integer members of Boost.Fusion adapted ADTs are not output correctly with Boost.Spirit.Karma rules
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2011-12-29 10:44:48


#6126: Signed integer members of Boost.Fusion adapted ADTs are not output
correctly with Boost.Spirit.Karma rules
-------------------------------+--------------------------------------------
  Reporter: t0rt1e@… | Owner: hkaiser
      Type: Bugs | Status: new
 Milestone: To Be Determined | Component: spirit
   Version: Boost 1.48.0 | Severity: Problem
Resolution: | Keywords: Boost.Spirit.Karma, Boost.Fusion, BOOST_FUSION_ADAPT_CLASS, BOOST_FUSION_ADAPT_ADT, short, int, long
-------------------------------+--------------------------------------------

Comment (by bugs@…):

 I have greatly reduced your minimal sample (attached),
 and came up with a 'fix'.

 Specific versions, options see at the bottom

 It sure looks like there is a compiler bug involved. The only problem I
 have with this hypothesis is, that it seems against all odds for more
 than one compiler to have the exact same bug in the same area. So, there
 might be some intricate case of undefined behaviour lurking, that I
 cannot for the life of me figure out. Let me show you where the problem
 happens:

 {{{boost_1_48_0/boost/spirit/home/karma/numeric/int.hpp}}}:207
 {{{
          static bool insert_int(OutputIterator& sink, Attribute const&
 attr)
          {
              return sign_inserter::call(sink, traits::test_zero(attr)
                        , traits::test_negative(attr), force_sign) &&
                     int_inserter<Radix, CharEncoding, Tag>::call(sink
                        , traits::get_absolute_value(attr));
          }
 }}}
 The problem is that the debugger shows that the value being passed to
 {{{get_absolute_value}}} is simply '0' (zero).
 Now with all my reasoning, I can't see why that happens except for a
 compiler bug.

 Now the simplest solution was to change the signature:
 {{{
          template <typename OutputIterator, typename Attribute>
              static bool insert_int(OutputIterator& sink, Attribute attr)
 }}}
 Out of curiosity I tried some other formulations, and the following
 variant, surprisingly (!!!) yielded the same problem (wrong output!):
 {{{
          static bool insert_int(OutputIterator& sink, Attribute const&
 attr)
          {
             if (!sign_inserter::call(sink, traits::test_zero(attr)
                      , traits::test_negative(attr), force_sign))
                 return false;
             Attribute copy(attr);
             return
                  int_inserter<Radix, CharEncoding, Tag>::call(sink
                          , traits::get_absolute_value(copy));
          }
 }}}
 whereas the following works correctly:
 {{{
          static bool insert_int(OutputIterator& sink, Attribute const&
 attr)
          {
             Attribute copy(attr);
             if (!sign_inserter::call(sink, traits::test_zero(attr)
                      , traits::test_negative(attr), force_sign))
                 return false;
             return
                  int_inserter<Radix, CharEncoding, Tag>::call(sink
                          , traits::get_absolute_value(copy));
          }
 }}}
 This most definitely bears the marks of a compiler bug, since both
 {{{test_zero}}} and {{{test_negative}}} take all their arguments by value
 and,
 besides, {{{attr}}} is a {{{const}}} reference. :-)

 Important things to note:

   * all testing done with
       o gcc 4.6.1 64bit, boost 1_48_0, flags: -g -O0 -fno-inline
       o clang++ version 2.9 (tags/RELEASE_29/final) x86_64-pc-linux-gnu
 with the boost lib and flags
   * valgrind was turning up invalid read warnings:
       o "Address 0x7fefffc3e is just below the stack ptr. To suppress,
         use: --workaround-gcc296-bugs=yes"
   * by generating a hardcoded (non-adapted) short_ of a specific value
     (e.g. 123) I could reliably make gcc output, say, -123 instead of
     the correct value first. This lead me to believe there was
     uninitialized memory / undefined behavior at play. Though the exact
     output varied across compilers, the valgrind diagnostics matched and
     the solution works for both compilers.
   * The output of valgrind is still not clean after adding my solution;
     there may be other instances of the same problem still!
     Specificly, a very similar invalid read is reported on line 242 of
     int.hpp (which has a very similar call pattern/reference parameter
     type). Someone may want to look into that one too.

-- 
Ticket URL: <https://svn.boost.org/trac/boost/ticket/6126#comment:6>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.

This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:08 UTC