Boost C++ Libraries: Ticket #6126: Signed integer members of Boost.Fusion adapted ADTs are not output correctly with Boost.Spirit.Karma rules https://svn.boost.org/trac10/ticket/6126 <p> Boost.Spirit.Karma output rules should show the same behavior for Boost.Fusion-adapted structs (direct access of the public member variables) and ADTs (access to the private member variables via getters and setters). This has been the case in Boost 1.44 and is demonstrated in this test case for rational number ADTs and structs, which use signed integer member variables. The test case takes into account the name change of macro <code>BOOST_FUSION_ADAPT_CLASS</code> to <code>BOOST_FUSION_ADAPT_ADT</code> as well as the additionally required header <code>boost/spirit/include/support_adapt_adt_attributes.hpp</code> (cf. to ticket <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/5780" title="#5780: Bugs: Boost.Fusion adapted class boost::rational&lt;long&gt; causes compile errors ... (closed: fixed)">#5780</a>). </p> <p> Compilation of this test case against Boost 1.45.0 and 1.46.1 will fail. Compilation against Boost 1.47.0 and 1.48.0 will succeed, but the output of negative values of signed integer members of Boost.Fusion-adapted ADTs will be wrong. The minus sign is output correctly, but it is followed by a wrong value, which seems to be yielded by a cast from a signed to an unsigned integer value instead of taking the absolute value of the signed integer value. This has been observed on Mac OS X 10.7.2 (x86_64) with Xcode 4.2 using Apple's g++ 4.2.1, Apple's clang++ 3.0. Interestingly, compiling the test case against Boost 1.47.0 or Boost 1.48.0 using MacPorts g++ 4.5.3, will yield more output checks to fail for Boost.Fusion-adapted ADTs used in Karma output rules. </p> <p> Compilation against Boost from the Subversion trunk (rev. 75505) does only succeed using Apple's clang++ 3.0 and execution will yield the same wrong output for negative values of signed integer members of Boost.Fusion-adapted ADTs. Compilation fails with Apple's g++ 4.2.1 and MacPorts g++ 4.5.3. </p> <p> Attached to this ticket are the source of the test case, the output of the failing test case compiled against Boost 1.47/1.48 using gcc 4.2.1 and clang++ 3.0 as well as the different output using MacPorts g++ 4.5.3. The g++ 4.2.1 and g++ 4.5.3 compiler outputs for compilation against Boost trunk rev. 75505 are attached as well. </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/6126 Trac 1.4.3 t0rt1e@… Wed, 16 Nov 2011 15:36:40 GMT attachment set https://svn.boost.org/trac10/ticket/6126 https://svn.boost.org/trac10/ticket/6126 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">test_signed_integer_output_with_karma.cpp</span> </li> </ul> <p> test case </p> Ticket t0rt1e@… Wed, 16 Nov 2011 15:38:18 GMT attachment set https://svn.boost.org/trac10/ticket/6126 https://svn.boost.org/trac10/ticket/6126 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">test_signed_integer_output_with_karma_boost148_gcc42_clang3.log</span> </li> </ul> <p> Test case output showing failing checks when compiled against Boost 1.48.0 using Apple's g++ 4.2.1 or clang++ 3.0 </p> Ticket t0rt1e@… Wed, 16 Nov 2011 15:39:10 GMT attachment set https://svn.boost.org/trac10/ticket/6126 https://svn.boost.org/trac10/ticket/6126 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">test_signed_integer_output_with_karma_boost148_gcc45.log</span> </li> </ul> <p> Test case output showing failing checks when compiled against Boost 1.48.0 using <a class="missing wiki">MacPorts</a> g++ 4.5.3 </p> Ticket t0rt1e@… Wed, 16 Nov 2011 15:41:00 GMT attachment set https://svn.boost.org/trac10/ticket/6126 https://svn.boost.org/trac10/ticket/6126 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">test_signed_integer_output_with_karma_boost_trunk_gcc42.log</span> </li> </ul> <p> Apple's g++ 4.2.1 output failing to compile test case against Boost trunk rev. 75505 </p> Ticket t0rt1e@… Wed, 16 Nov 2011 15:41:40 GMT attachment set https://svn.boost.org/trac10/ticket/6126 https://svn.boost.org/trac10/ticket/6126 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">test_signed_integer_output_with_karma_boost_trunk_gcc45.log</span> </li> </ul> <p> <a class="missing wiki">MacPorts</a> g++ 4.5.3 output failing to compile test case against Boost trunk rev. 75505 </p> Ticket t0rt1e@… Thu, 15 Dec 2011 16:47:00 GMT <link>https://svn.boost.org/trac10/ticket/6126#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6126#comment:1</guid> <description> <p> I have checked the test case against the current Boost trunk (Subversion revision 75963). It fails still to compile with Apple gcc 4.2.1 or <a class="missing wiki">MacPorts</a> g++ 4.5.3 / 4.6.2 and compiles fine with Apple clang++ 3.0 but shows wrong runtime behavior. </p> </description> <category>Ticket</category> </item> <item> <author>t0rt1e@…</author> <pubDate>Wed, 28 Dec 2011 17:21:16 GMT</pubDate> <title>attachment set https://svn.boost.org/trac10/ticket/6126 https://svn.boost.org/trac10/ticket/6126 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">test_signed_integer_output_with_karma_minimal.cpp</span> </li> </ul> <p> Minimal test case making not use of Boost.unit_test features to compile cleanly against Boost svn trunk </p> Ticket t0rt1e@… Wed, 28 Dec 2011 17:39:23 GMT <link>https://svn.boost.org/trac10/ticket/6126#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6126#comment:2</guid> <description> <p> The original test case using Boost.unit_test fails to compile against the Boost svn trunk due to an issue related to the usage of enable_if&lt;&gt; in some Boost.unit_test header. Therefore, I simplified the test case to just show the wrong formatting of signed integer ADT members. For details cf. to <a class="ext-link" href="http://sourceforge.net/mailarchive/forum.php?thread_name=CAGCnmH11u2%2Bvfef9v8YpPnbv1cN%3Da5Px2xSu%3DKTnaKBve2vTwQ%40mail.gmail.com&amp;forum_name=spirit-general"><span class="icon">​</span>this thread</a> on the Boost.spirit-general mailing list. </p> </description> <category>Ticket</category> </item> <item> <author>t0rt1e@…</author> <pubDate>Wed, 28 Dec 2011 17:46:09 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/6126#comment:3 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6126#comment:3</guid> <description> <p> The original test case using Boost.unit_test fails to compile against the Boost svn trunk due to an issue related to the usage of enable_if&lt;&gt; in some Boost.unit_test header. Therefore, I simplified the test case to just show the wrong formatting of signed integer ADT members. For details cf. to the thread with the same title started on 2011-12-26 on the Boost.spirit-general mailing list. (Sorry, I would've supplied a link, but I was not able get past the captcha presented by the Trac system.) </p> </description> <category>Ticket</category> </item> <item> <author>vexocide@…</author> <pubDate>Thu, 29 Dec 2011 10:36:08 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/6126#comment:4 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6126#comment:4</guid> <description> <p> I've managed to reproduce the problem, and it's quite interesting to say the least: </p> <pre class="wiki">~ Jeroen$ g++ --version i686-apple-darwin10-g++-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5666) (dot 3) ~ Jeroen$ g++ test_signed_integer_output_with_karma_minimal.cpp -o test -I library/boost-trunk/ ~ Jeroen$ ./test rational_int_adt(2, -6) = -771751935/3 (expected: -1/3) rational_int_adt(-2, 4) = -771751935/2 (expected: -1/2) ~ Jeroen$ g++ test_signed_integer_output_with_karma_minimal.cpp -o test -O2 -I library/boost-trunk/ ~ Jeroen$ ./test rational_int_adt(2, -6) = -1/3 (expected: -1/3) rational_int_adt(-2, 4) = -1/2 (expected: -1/2) rational_int_struct(2, -6) = 2/-6 (expected: 2/-6) ~ Jeroen$ g++-mp-4.4 --version g++-mp-4.4 (GCC) 4.4.6 ~ Jeroen$ g++-mp-4.4 test_signed_integer_output_with_karma_minimal.cpp -o test -I Documents/Code/library/boost-trunk/ ~ Jeroen$ ./test rational_int_adt(2, -6) = -1/1 (expected: -1/3) rational_int_adt(-2, 4) = -1/1 (expected: -1/2) rational_int_struct(2, -6) = 2/-6 (expected: 2/-6) ~ Jeroen$ g++-mp-4.4 test_signed_integer_output_with_karma_minimal.cpp -o test -O2 -I Documents/Code/library/boost-trunk/ ~ Jeroen$ ./test rational_int_adt(2, -6) = -1/3 (expected: -1/3) rational_int_adt(-2, 4) = -1/2 (expected: -1/2) rational_int_struct(2, -6) = 2/-6 (expected: 2/-6) ~ Jeroen$ g++-mp-4.6 --version g++-mp-4.6 (GCC) 4.6.2 ~ Jeroen$ g++-mp-4.6 test_signed_integer_output_with_karma_minimal.cpp -o test -I library/boost-trunk/ ~ Jeroen$ ./test rational_int_adt(2, -6) = -771751935/3 (expected: -1/3) rational_int_adt(-2, 4) = -771751935/2 (expected: -1/2) rational_int_struct(2, -6) = 2/-6 (expected: 2/-6) ~ Jeroen$ g++-mp-4.6 test_signed_integer_output_with_karma_minimal.cpp -o test -O2 -I library/boost-trunk/ ~ Jeroen$ ./test rational_int_adt(2, -6) = 0/0 (expected: -1/3) rational_int_adt(-2, 4) = 0/0 (expected: -1/2) rational_int_struct(2, -6) = 2/-6 (expected: 2/-6) </pre><p> Yes, that's four different outputs depending on the compiler version and optimization flags used... Hartmut has tried this using MSVC (not sure which version) and that worked just fine. I've currently broken my clang++ installation thus I can't try that, unfortunately. </p> <p> I believe that I've found the culprit (a specific temporary) and could provide a patch, but that'll come tomorrow (I'll need to thoroughly test it, for obvious reasons). In the mean time someone should ask the GCC guys what's going on. </p> </description> <category>Ticket</category> </item> <item> <author>t0rt1e@…</author> <pubDate>Thu, 29 Dec 2011 10:38:18 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/6126#comment:5 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6126#comment:5</guid> <description> <p> I can help with the clang++ output: </p> <pre class="wiki">$ clang++ --versionApple clang version 3.0 (tags/Apple/clang-211.12) (based on LLVM 3.0svn)Target: x86_64-apple-darwin11.2.0 Thread model: posix $ clang++ -o test_signed_integer_output_with_karma_minimal \ test_signed_integer_output_with_karma_minimal.cpp \ -I/Users/maehne/Build/boost-trunk/ maehne@epsilon3:Boost $ ./test_signed_integer_output_with_karma_minimal rational_int_adt(2, -6) = -32767/3 (expected: -1/3) rational_int_adt(-2, 4) = -32767/2 (expected: -1/2) rational_int_struct(2, -6) = 2/-6 (expected: 2/-6) $ clang++ -O2 -o test_signed_integer_output_with_karma_minimal \ test_signed_integer_output_with_karma_minimal.cpp \ -I/Users/maehne/Build/boost-trunk/ $ ./test_signed_integer_output_with_karma_minimal rational_int_adt(2, -6) = 0/0 (expected: -1/3) rational_int_adt(-2, 4) = 0/0 (expected: -1/2) rational_int_struct(2, -6) = 2/-6 (expected: 2/-6) </pre><p> So, also for clang++ the results depend on the optimization settings. </p> <p> That would be great if you've found the culprit! The compiler/optimization-dependent output also made me think of some undefined behavior to be triggered by the C++ code, but, unfortunately, I'm not familiar enough with the Boost.Fusion and Boost.Spirit codebase to hunt it down. Thanks a lot for investing so much effort to analyze and resolve the bug! If you need help to test the patch, I can try it out on my side with my production code. </p> </description> <category>Ticket</category> </item> <item> <author>bugs@…</author> <pubDate>Thu, 29 Dec 2011 10:44:48 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/6126#comment:6 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6126#comment:6</guid> <description> <p> I have greatly reduced your minimal sample (attached), and came up with a 'fix'. </p> <p> Specific versions, options see at the bottom </p> <p> 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: </p> <p> <code>boost_1_48_0/boost/spirit/home/karma/numeric/int.hpp</code>:207 </p> <pre class="wiki"> static bool insert_int(OutputIterator&amp; sink, Attribute const&amp; attr) { return sign_inserter::call(sink, traits::test_zero(attr) , traits::test_negative(attr), force_sign) &amp;&amp; int_inserter&lt;Radix, CharEncoding, Tag&gt;::call(sink , traits::get_absolute_value(attr)); } </pre><p> The problem is that the debugger shows that the value being passed to <code>get_absolute_value</code> is simply '0' (zero). Now with all my reasoning, I can't see why that happens except for a compiler bug. </p> <p> Now the simplest solution was to change the signature: </p> <pre class="wiki"> template &lt;typename OutputIterator, typename Attribute&gt; static bool insert_int(OutputIterator&amp; sink, Attribute attr) </pre><p> Out of curiosity I tried some other formulations, and the following variant, surprisingly (!!!) yielded the same problem (wrong output!): </p> <pre class="wiki"> static bool insert_int(OutputIterator&amp; sink, Attribute const&amp; attr) { if (!sign_inserter::call(sink, traits::test_zero(attr) , traits::test_negative(attr), force_sign)) return false; Attribute copy(attr); return int_inserter&lt;Radix, CharEncoding, Tag&gt;::call(sink , traits::get_absolute_value(copy)); } </pre><p> whereas the following works correctly: </p> <pre class="wiki"> static bool insert_int(OutputIterator&amp; sink, Attribute const&amp; attr) { Attribute copy(attr); if (!sign_inserter::call(sink, traits::test_zero(attr) , traits::test_negative(attr), force_sign)) return false; return int_inserter&lt;Radix, CharEncoding, Tag&gt;::call(sink , traits::get_absolute_value(copy)); } </pre><p> This most definitely bears the marks of a compiler bug, since both <code>test_zero</code> and <code>test_negative</code> take all their arguments by value and, besides, <code>attr</code> is a <code>const</code> reference. :-) </p> <p> Important things to note: </p> <ul><li>all testing done with </li></ul><blockquote> <blockquote> <p> 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 </p> </blockquote> </blockquote> <ul><li>valgrind was turning up invalid read warnings: </li></ul><blockquote> <blockquote> <p> o "Address 0x7fefffc3e is just below the stack ptr. To suppress, </p> <blockquote> <p> use: --workaround-gcc296-bugs=yes" </p> </blockquote> </blockquote> </blockquote> <ul><li>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. </li><li>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. </li></ul><p> </p> </description> <category>Ticket</category> </item> <item> <author>bugs@…</author> <pubDate>Thu, 29 Dec 2011 10:45:46 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/6126#comment:7 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6126#comment:7</guid> <description> <blockquote class="citation"> <p> The problem is that the debugger shows that the value being passed to get_absolute_value is simply '0' (zero). </p> </blockquote> <p> For clarity: this is was the value the debugger turned up when debugging the minimal test case. The actual value is undefined and apparently depends on prior contents of the stack (see notes at the bottom for reasons why I think that is the case). </p> </description> <category>Ticket</category> </item> <item> <author>bugs@…</author> <pubDate>Thu, 29 Dec 2011 10:51:01 GMT</pubDate> <title>attachment set https://svn.boost.org/trac10/ticket/6126 https://svn.boost.org/trac10/ticket/6126 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">test_short_output_with_karma.cpp</span> </li> </ul> <p> Further reduced test case </p> Ticket vexocide@… Thu, 29 Dec 2011 10:54:29 GMT <link>https://svn.boost.org/trac10/ticket/6126#comment:8 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6126#comment:8</guid> <description> <p> This matches what I've found. My initial patch was <a class="ext-link" href="http://codepad.org/u6ffbDXT"><span class="icon">​</span>http://codepad.org/u6ffbDXT</a> but this isn't fully correct as the type of the value returned by <code>get_absolute_value</code> isn't necessarily Attribute (<code>get_absolute_value</code> may return an <code>unsigned int</code> for an <code>int</code> for example, not quite sure why). </p> </description> <category>Ticket</category> </item> <item> <author>t0rt1e@…</author> <pubDate>Tue, 10 Jan 2012 17:15:50 GMT</pubDate> <title>keywords, severity changed https://svn.boost.org/trac10/ticket/6126#comment:9 https://svn.boost.org/trac10/ticket/6126#comment:9 <ul> <li><strong>keywords</strong> patch proposed added </li> <li><strong>severity</strong> <span class="trac-field-old">Problem</span> → <span class="trac-field-new">Regression</span> </li> </ul> <p> I have tested Jeroen Habraken's and Seth Heren's patches against <code>test_signed_integer_output_with_karma_minimal.cpp</code>. Like suggested by Seth, copying the <code>attr</code> value in <code>any_int_generator&lt;T, CharEncoding, Tag, Radix, force_sign&gt;::insert_int&lt; OutputIterator, Attribute&gt;(sink, attr)</code> has reliably resolved the problem for me on Mac OS X Lion 10.7.2 when compiling with g++ 4.2.1, 4.5.3, 4.6.2 and clang++ 3.0 version. I kept the structure of the <code>return</code> statement and just replace <code>attr</code> with <code>attr_copy</code>. </p> <p> I attach a patch against Boost svn rev. 76398. </p> Ticket t0rt1e@… Tue, 10 Jan 2012 17:19:18 GMT attachment set https://svn.boost.org/trac10/ticket/6126 https://svn.boost.org/trac10/ticket/6126 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">karma_numeric_int_hpp.patch</span> </li> </ul> <p> Patch for boost/spirit/home/karma/numeric/int.hpp based on SVN rev. 76398 </p> Ticket t0rt1e@… Fri, 20 Jan 2012 14:57:33 GMT <link>https://svn.boost.org/trac10/ticket/6126#comment:10 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6126#comment:10</guid> <description> <p> I just tried to compile <code>test_signed_integer_output_with_karma_minimal.cpp</code> with <code>g++ 4.7.0 20120114 (experimental)</code> from MacPorts against Boost trunk (svn rev. 76591). Compilation succeeds, but running the test gives still completely wrong output depending on the chosen optimization level: </p> <pre class="wiki">$ g++-mp-4.7 -O0 -o test_signed_integer_output_with_karma_minimal test_signed_integer_output_with_karma_minimal.cpp -I.../boost-trunk $ ./test_signed_integer_output_with_karma_minimal rational_int_adt(2, -6) = -771751935/3 (expected: -1/3) rational_int_adt(-2, 4) = -771751935/2 (expected: -1/2) rational_int_struct(2, -6) = 2/-6 (expected: 2/-6) $ g++-mp-4.7 -O1 -o test_signed_integer_output_with_karma_minimal test_signed_integer_output_with_karma_minimal.cpp -I.../boost-trunk $ ./test_signed_integer_output_with_karma_minimal rational_int_adt(2, -6) = 0/0 (expected: -1/3) rational_int_adt(-2, 4) = 0/0 (expected: -1/2) rational_int_struct(2, -6) = 2/-6 (expected: 2/-6) </pre><p> Output with optimization <code>-O2</code> or <code>-O3</code> is the same as with <code>-O1</code>. </p> </description> <category>Ticket</category> </item> <item> <author>t0rt1e@…</author> <pubDate>Tue, 31 Jan 2012 14:36:53 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/6126#comment:11 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6126#comment:11</guid> <description> <p> I tried to dig further into the problem by following Seth Heren's debug into the <code>any_integer_iterator::insert_int()</code> member function at <code>boost/spirit/home/karma/numeric/int.hpp:210</code> when executing the compiled <code>test_short_output_with_karma.cpp</code>. I could further narrow down the moment, when the <code>*attr</code> value becomes zero by serializing the statements and inlining the <code>sign_inserter::call</code> (see attached diagnostic patch <code>boost_spirit_home_karma_numeric_int_diagnostic.patch</code> against Boost trunk 76795). The <code>*attr</code> value becomes zero after a character is put into the <code>sink</code>, which happens in our case in line <code>boost/spirit/home/karma/numeric/int.hpp:221</code>. Why??? Has anyone an idea? Before everything is OK. I tested it by copying the Attribute via a dummy function into another variable. Here's the relevant code snippet with some comments: </p> <pre class="wiki"> template &lt;typename OutputIterator, typename Attribute&gt; static bool insert_int(OutputIterator&amp; sink, Attribute const&amp; attr) { // I have serialized the calls to better follow with the debugger what's going on. bool is_zero = traits::test_zero(attr); bool is_neg = traits::test_negative(attr); // Until here everything seems OK, *attr still has its value. // I can use, e.g., the attribute in a function call. Attribute attr_copy = dummy_function(attr); // bool r1 = sign_inserter::call(sink, is_zero // , is_neg, force_sign); // After the sign_inserter call, *attr becomes surprisingly zero. // Therefore, I inlined the important code parts to output the sign. if (is_neg) { *sink = '-'; // After putting the character into the sink, the *attr becomes zero. // Why??? This happens consistently unimportant whether it's // compiled using g++ or clang++ on Linux or Mac OS X. Is the sink // not correctly constructed and leaks memory? ++sink; } else if (force_sign) { if (is_zero) { *sink = ' '; } else { *sink = '+'; } ++sink; } bool r1 = true; bool r2 = int_inserter&lt;Radix, CharEncoding, Tag&gt;::call(sink , traits::get_absolute_value(attr)); return r1 &amp;&amp; r2; // return sign_inserter::call(sink, traits::test_zero(attr) // , traits::test_negative(attr), force_sign) &amp;&amp; // int_inserter&lt;Radix, CharEncoding, Tag&gt;::call(sink // , traits::get_absolute_value(attr)); } // Dummy function for pure diagnostic reasons. It just returns a copy of the attribute. template&lt;typename Attribute&gt; static Attribute dummy_function(Attribute const&amp; attr) { return attr; }; </pre><p> I'm not anymore sure that we are facing a compiler bug. Maybe the <code>sink</code> is for some reason not correctly initialized? </p> </description> <category>Ticket</category> </item> <item> <author>t0rt1e@…</author> <pubDate>Tue, 31 Jan 2012 14:38:06 GMT</pubDate> <title>attachment set https://svn.boost.org/trac10/ticket/6126 https://svn.boost.org/trac10/ticket/6126 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">boost_spirit_home_karma_numeric_int_diagnostic.patch</span> </li> </ul> <p> Diagnostic patch to be able to better debug insert_int </p> Ticket t0rt1e@… Wed, 01 Feb 2012 08:05:01 GMT <link>https://svn.boost.org/trac10/ticket/6126#comment:12 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6126#comment:12</guid> <description> <p> I just wanted to add that the bug is also present in Boost 1.49.0beta1. As this bug happens with g++ and clang++ on Linux and Mac OS X, it might be worth to at least mention it as a known issue in the documentation if it cannot be resolved until the final 1.49.0 release. </p> </description> <category>Ticket</category> </item> <item> <author>bugs@…</author> <pubDate>Thu, 02 Feb 2012 00:45:20 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/6126#comment:13 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6126#comment:13</guid> <description> <p> I tracked it down to extract_from_attribute&lt;&gt;::call&lt;&gt;(attr,ctx,true_type). It will generate an inner typedef of </p> <blockquote> <p> typedef typename mpl::eval_if&lt; </p> <blockquote> <p> is_one_element_sequence </p> </blockquote> <p> , detail::value_at_c&lt;Attribute, 0&gt; , mpl::identity&lt;Attribute const&amp;&gt; </p> <blockquote class="citation"> <p> ::type type; </p> </blockquote> </blockquote> <p> which is going to be a reference. This is ok for tuples, adapted structs (typical fusion sequences) but not for ADT's as the accessor function returns a <code>short</code>, which <strong>can</strong> be bound to a const&amp; <strong>but</strong> only locally (its lifetime won't be extended outside the scope in which the reference is declared). </p> <p> Now the way I see it in the code, the sample from the docs<a class="changeset" href="https://svn.boost.org/trac10/changeset/1" title="Import core sources for SVNmanger 0.38 ">[1]</a> <code>(int, int, obj.get_age(), obj.set_age(val))</code> won't work without undefined behaviour, precisely because it results in <code>extract_from_attribute&lt;&gt;::call&lt;&gt;</code> returning a reference to a local (<code>int</code> in that case). </p> <p> For the OP, I guess the best way to fix it would be to make the accessors return (const) references: (see attached) </p> <blockquote> <p> struct XR { </p> <blockquote> <p> short x; </p> </blockquote> </blockquote> <blockquote> <blockquote> <p> explicit XR(short num = 0) : x(num) {} const short&amp; getx() const { return x; } </p> <blockquote> <p> short&amp; getx() { return x; } </p> </blockquote> <p> void setx(short v) { x = v; } </p> </blockquote> <p> }; </p> </blockquote> <blockquote> <p> BOOST_FUSION_ADAPT_ADT(XR, (short&amp;, const short&amp;, obj.getx(), obj.setx(val))) </p> </blockquote> <p> This also removed all the other valgrind messages that were previously unaccounted for. </p> <p> <a class="changeset" href="https://svn.boost.org/trac10/changeset/1" title="Import core sources for SVNmanger 0.38 ">[1]</a> <a href="http://www.boost.org/doc/libs/1_48_0/libs/fusion/doc/html/fusion/adapted/adapt_adt.html">http://www.boost.org/doc/libs/1_48_0/libs/fusion/doc/html/fusion/adapted/adapt_adt.html</a> </p> </description> <category>Ticket</category> </item> <item> <author>bugs@…</author> <pubDate>Thu, 02 Feb 2012 01:03:19 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/6126#comment:14 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6126#comment:14</guid> <description> <p> Thinking aloud: </p> <p> I suppose the extract_from helper should just return the attribute proxy by value. </p> <p> I can see how that is undesirable for the general case (non-copyable or copy-expensive attributes), but keep in mind that for adapted ADT's, the <code>adt_attribute_proxy</code> instance can easily be returned by value while still allowing the compiler to generate optimum code: </p> <ul><li>RVO elides the copying, </li><li>the caller can bind the temporary to a const&amp; in case it needs to access it twice (insert_int) and </li><li>inlining does the rest </li></ul><hr /> <p> Of the wall: might this (the 'premature' decaying of the proxy to it's exposed attribute type) have something to do with the special casing of single-element-sequences in attribute extraction (decaying of a sequence to it's single element)? </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Hartmut Kaiser</dc:creator> <pubDate>Thu, 02 Feb 2012 01:14:58 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/6126#comment:15 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6126#comment:15</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/6126#comment:13" title="Comment 13">bugs@…</a>: </p> <blockquote class="citation"> <p> I tracked it down to extract_from_attribute&lt;&gt;::call&lt;&gt;(attr,ctx,true_type). It will generate an inner typedef of </p> <blockquote> <p> typedef typename mpl::eval_if&lt; </p> <blockquote> <p> is_one_element_sequence </p> </blockquote> <p> , detail::value_at_c&lt;Attribute, 0&gt; , mpl::identity&lt;Attribute const&amp;&gt; </p> <blockquote class="citation"> <p> ::type type; </p> </blockquote> </blockquote> <p> which is going to be a reference. This is ok for tuples, adapted structs (typical fusion sequences) but not for ADT's as the accessor function returns a <code>short</code>, which <strong>can</strong> be bound to a const&amp; <strong>but</strong> only locally (its lifetime won't be extended outside the scope in which the reference is declared). </p> <p> Now the way I see it in the code, the sample from the docs<a class="changeset" href="https://svn.boost.org/trac10/changeset/1" title="Import core sources for SVNmanger 0.38 ">[1]</a> <code>(int, int, obj.get_age(), obj.set_age(val))</code> won't work without undefined behaviour, precisely because it results in <code>extract_from_attribute&lt;&gt;::call&lt;&gt;</code> returning a reference to a local (<code>int</code> in that case). </p> <p> For the OP, I guess the best way to fix it would be to make the accessors return (const) references: (see attached) </p> <blockquote> <p> struct XR { </p> <blockquote> <p> short x; </p> </blockquote> </blockquote> <blockquote> <blockquote> <p> explicit XR(short num = 0) : x(num) {} const short&amp; getx() const { return x; } </p> <blockquote> <p> short&amp; getx() { return x; } </p> </blockquote> <p> void setx(short v) { x = v; } </p> </blockquote> <p> }; </p> </blockquote> <blockquote> <p> BOOST_FUSION_ADAPT_ADT(XR, (short&amp;, const short&amp;, obj.getx(), obj.setx(val))) </p> </blockquote> <p> This also removed all the other valgrind messages that were previously unaccounted for. </p> <p> <a class="changeset" href="https://svn.boost.org/trac10/changeset/1" title="Import core sources for SVNmanger 0.38 ">[1]</a> <a href="http://www.boost.org/doc/libs/1_48_0/libs/fusion/doc/html/fusion/adapted/adapt_adt.html">http://www.boost.org/doc/libs/1_48_0/libs/fusion/doc/html/fusion/adapted/adapt_adt.html</a> </p> </blockquote> <p> That's excellent news! Thanks. That allows to revert the patch above. </p> </description> <category>Ticket</category> </item> <item> <author>Seth Heeren <bugs@…></author> <pubDate>Thu, 02 Feb 2012 01:24:25 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/6126#comment:16 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6126#comment:16</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/6126#comment:15" title="Comment 15">hkaiser</a>: </p> <blockquote class="citation"> <p> That's excellent news! Thanks. That allows to revert the patch above. </p> </blockquote> <p> Do you have ideas on how to fix it? My suggestion for the OP is really a workaround: </p> <ul><li>bug: ADT accessors returning by value leads to UB </li><li>workaround: don't do that, then? </li></ul><p> The docs clearly suggest that returning by value from the accessors is <code>ok</code> practice (and that adds value, IMO). However, the code appears to have the assumption that attributes can always be fully 'resolved' to a reference. </p> <p> Apart from specializing extract_from_attribute for adt_attribute_proxy I don't see an easy way to resolve this. And I wouldn't think that this approach is entirely trivial, either (it might be enough due to the implicit conversion of the proxy to its exposed type?) </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Hartmut Kaiser</dc:creator> <pubDate>Thu, 02 Feb 2012 01:31:39 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/6126#comment:17 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6126#comment:17</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/6126#comment:16" title="Comment 16">Seth Heeren &lt;bugs@…&gt;</a>: </p> <blockquote class="citation"> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/6126#comment:15" title="Comment 15">hkaiser</a>: </p> <blockquote class="citation"> <p> That's excellent news! Thanks. That allows to revert the patch above. </p> </blockquote> <p> Do you have ideas on how to fix it? My suggestion for the OP is really a workaround: </p> <ul><li>bug: ADT accessors returning by value leads to UB </li><li>workaround: don't do that, then? </li></ul><p> The docs clearly suggest that returning by value from the accessors is <code>ok</code> practice (and that adds value, IMO). However, the code appears to have the assumption that attributes can always be fully 'resolved' to a reference. </p> </blockquote> <p> The docs are Fusion related. There it is possible and valid to do such things. The problem is that Karma (falsely) assumes this as well. </p> <blockquote class="citation"> <p> Apart from specializing extract_from_attribute for adt_attribute_proxy I don't see an easy way to resolve this. And I wouldn't think that this approach is entirely trivial, either (it might be enough due to the implicit conversion of the proxy to its exposed type?) </p> </blockquote> <p> Yep, that's what I think needs to be done, at least as a first step. </p> </description> <category>Ticket</category> </item> <item> <author>t0rt1e@…</author> <pubDate>Thu, 02 Feb 2012 23:07:20 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/6126#comment:18 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6126#comment:18</guid> <description> <p> Thank you very much Seth and Hartmut for finally tracking down the root of the problem! It's good to know that we are facing undefined behavior instead of a compiler bug. </p> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/6126#comment:17" title="Comment 17">hkaiser</a>: </p> <blockquote class="citation"> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/6126#comment:16" title="Comment 16">Seth Heeren &lt;bugs@…&gt;</a>: </p> <blockquote class="citation"> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/6126#comment:15" title="Comment 15">hkaiser</a>: </p> <blockquote class="citation"> <p> That's excellent news! Thanks. That allows to revert the patch above. </p> </blockquote> <p> Do you have ideas on how to fix it? My suggestion for the OP is really a workaround: </p> <ul><li>bug: ADT accessors returning by value leads to UB </li><li>workaround: don't do that, then? </li></ul><p> The docs clearly suggest that returning by value from the accessors is <code>ok</code> practice (and that adds value, IMO). However, the code appears to have the assumption that attributes can always be fully 'resolved' to a reference. </p> </blockquote> </blockquote> <p> I second Seth's opinion that supporting ADTs, which getters return by value gives added value. In my case, I cannot simply change the return type in the signature of the getters. The original test case <code>test_signed_integer_output_with_karma</code> I provided is close to my production code, where I adapted <code>boost::rational&lt;long&gt;</code> for usage in Spirit and Karma rules. Its implementation returns the numerator and denominator by value. </p> <blockquote class="citation"> <p> The docs are Fusion related. There it is possible and valid to do such things. The problem is that Karma (falsely) assumes this as well. </p> </blockquote> <p> Well, at least till Boost 1.48.0, the Karma tutorial demonstrates adapting <code>std::complex&lt;double&gt;</code> for usage with Karma, which <code>real()</code> and <code>imag()</code> member functions also return by value. </p> <blockquote class="citation"> <blockquote class="citation"> <p> Apart from specializing extract_from_attribute for adt_attribute_proxy I don't see an easy way to resolve this. And I wouldn't think that this approach is entirely trivial, either (it might be enough due to the implicit conversion of the proxy to its exposed type?) </p> </blockquote> <p> Yep, that's what I think needs to be done, at least as a first step. </p> </blockquote> <p> Could you maybe provide some more instructions how to specialize correctly <code>adt_attribute_proxy</code> for <code>std::rational&lt;long&gt;</code> or <code>std::complex&lt;double&gt;</code>? I think such kind of explanation and some pitfall notes would be very helpful in the Spirit.Karma documentation. I have not yet had the time to actually try myself specializing <code>adt_attribute_proxy</code>, but hope it won't be more effort than implementing my own rational class. </p> <p> It would be nice if this issue could be resolved in the long term in a more user-friendly way. </p> <p> Thank you very much for your help! </p> </description> <category>Ticket</category> </item> <item> <author>t0rt1e@…</author> <pubDate>Mon, 06 Feb 2012 15:09:17 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/6126#comment:19 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6126#comment:19</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/6126#comment:17" title="Comment 17">hkaiser</a>: </p> <blockquote class="citation"> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/6126#comment:16" title="Comment 16">Seth Heeren &lt;bugs@…&gt;</a>: </p> <blockquote class="citation"> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/6126#comment:15" title="Comment 15">hkaiser</a>: </p> <blockquote class="citation"> <p> That's excellent news! Thanks. That allows to revert the patch above. </p> </blockquote> </blockquote> </blockquote> <p> [...] </p> <blockquote class="citation"> <blockquote class="citation"> <p> Apart from specializing extract_from_attribute for adt_attribute_proxy I don't see an easy way to resolve this. And I wouldn't think that this approach is entirely trivial, either (it might be enough due to the implicit conversion of the proxy to its exposed type?) </p> </blockquote> <p> Yep, that's what I think needs to be done, at least as a first step. </p> </blockquote> <p> Since reimplementing the boost::rational getters to return by reference instead by value isn't an option for me, I had a look to the Karma sources to try Seth's suggestion. <code>extract_from_attribute</code> has been already specialized for <code>adt_attribute_proxy</code> in <code>boost/spirit/home/support/adapt_adt_attributes.hpp:192</code>. Commenting out this specialization, will generate a compiler warning: </p> <pre class="wiki">boost/spirit/home/karma/detail/extract_from.hpp:71:20: warning: returning reference to local temporary object return extract_from&lt;Exposed&gt;(fusion::at_c&lt;0&gt;(attr), ctx); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ </pre><p> This also happens if the return <code>type</code> <code>typedef</code> is changed to <code>fusion::extension::adt_attribute_proxy&lt;T, N, Const&gt;</code> in <code>boost/spirit/home/support/adapt_adt_attributes.hpp:192</code> and the proxy object is directly returned <code>call()</code> like suggested by Seth. I tried to further follow the <code>extract_from</code> to see where the proxy gets converted to a const ref to the contained type, but unfortunately got lost. So, I'm stuck again. </p> </description> <category>Ticket</category> </item> <item> <author>t0rt1e@…</author> <pubDate>Wed, 08 Feb 2012 14:27:33 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/6126#comment:20 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6126#comment:20</guid> <description> <blockquote class="citation"> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/6126#comment:13" title="Comment 13">bugs@…</a>: </p> </blockquote> <p> [snip] </p> <blockquote class="citation"> <p> For the OP, I guess the best way to fix it would be to make the accessors return (const) references: (see attached) </p> <blockquote> <p> struct XR { </p> <blockquote> <p> short x; </p> </blockquote> </blockquote> <blockquote> <blockquote> <p> explicit XR(short num = 0) : x(num) {} const short&amp; getx() const { return x; } </p> <blockquote> <p> short&amp; getx() { return x; } </p> </blockquote> <p> void setx(short v) { x = v; } </p> </blockquote> <p> }; </p> </blockquote> <blockquote> <p> BOOST_FUSION_ADAPT_ADT(XR, (short&amp;, const short&amp;, obj.getx(), obj.setx(val))) </p> </blockquote> <p> This also removed all the other valgrind messages that were previously unaccounted for. </p> </blockquote> <p> Without any alternative, I went through the pain to reimplement <code>boost::rational&lt;long&gt;</code> for my project so that its getters return <code>const long&amp;</code>. For some reasons that I don't fully understand, the with <code>BOOST_FUSION_ADAPT_ADT()</code> adapted class showed still the same wrong output when used in the Karma rules. I used: </p> <pre class="wiki">BOOST_FUSION_ADAPT_ADT( bufilt::rational, (const long&amp;, const long&amp;, obj.numerator(), /**/) (const long&amp;, const long&amp;, obj.denominator(), /**/) ) </pre><p> Then, I tried to use <code>BOOST_FUSION_ADAPT_STRUCT()</code> in the following way: </p> <pre class="wiki">BOOST_FUSION_ADAPT_STRUCT( bufilt::rational, (const long&amp;, numerator()) (const long&amp;, denominator()) ) </pre><p> after remembering having seen a post from someone with a similar problem on the Boost or Spirit mailing list, for which this did the trick. This surprisingly worked! (I just need read access to the struct members for use in the Karma rules.) </p> <p> So this resolves my urgent problem, but the solution remains a hack that I would like to get rid off again. </p> </description> <category>Ticket</category> </item> <item> <author>Nikita Kniazev <nok.raven@…></author> <pubDate>Wed, 14 Mar 2018 00:08:51 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/6126#comment:21 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6126#comment:21</guid> <description> <p> I am sorry I do not have a time machine, but... Good news here :-) </p> <p> I opened a PR fixing the bug <a class="ext-link" href="https://github.com/boostorg/spirit/pull/375"><span class="icon">​</span>https://github.com/boostorg/spirit/pull/375</a>. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Joel de Guzman</dc:creator> <pubDate>Thu, 22 Nov 2018 13:55:04 GMT</pubDate> <title>status changed; resolution set https://svn.boost.org/trac10/ticket/6126#comment:22 https://svn.boost.org/trac10/ticket/6126#comment:22 <ul> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">fixed</span> </li> </ul> Ticket