Boost C++ Libraries: Ticket #4523: fix for #4501 https://svn.boost.org/trac10/ticket/4523 <p> The following three patches fix issue <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/4501" title="#4501: Bugs: BOOST_PP_SEQ_FOR_EACH fails in corner case (closed: fixed)">#4501</a>. detail_auto_rec.patch and repetition_for.patch extend the maximum loop count in BOOST_PP_FOR from 255 to 256. seq_for_each.patch modifies the state of BOOST_PP_SEQ_FOR_EACH in such a way that the calculation of the sequence size is done just once now, and its cached value is used for loop control instead. This cuts down on the evaluation cost especially for long sequences. Small sequences benefit from an early-out execution path, in the frequent case, when no outer for loop blocks iteration slots. </p> <p> I manually enabled configuration flags 0x0004, 0x0010, 0x0020 (MSVC, BCC, EDG resp.) to enforce the execution of compiler specific code under GCC, and they compiled and executed fine, but that is only a poor replacement for the native compilers, of course. The code for MWCC and DMG does not conform to C90 or later, so GNU gcc could not be fooled to emulate them. </p> <p> cheers </p> <p> Wolf Lammen </p> <p> complexity: </p> <p> BOOST_CONFIG_FLAGS 0x0001 (strict) </p> <pre class="wiki">boost 1.43.0: patched: 0 elements 345 replacements 67 replacements 1 388 105 2 431 142 4 520 216 8 710 364 16 1138 660 32 2186 1252 64 5050 2436 128 13850 4804 255 elements 43441 replacements 9503 256 failure 9540 </pre> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/4523 Trac 1.4.3 ookami1@… Sun, 08 Aug 2010 14:25:19 GMT attachment set https://svn.boost.org/trac10/ticket/4523 https://svn.boost.org/trac10/ticket/4523 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">detail_auto_rec.patch</span> </li> </ul> Ticket ookami1@… Sun, 08 Aug 2010 14:25:53 GMT attachment set https://svn.boost.org/trac10/ticket/4523 https://svn.boost.org/trac10/ticket/4523 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">repetition_for.patch</span> </li> </ul> Ticket ookami1@… Sun, 08 Aug 2010 14:26:42 GMT attachment set https://svn.boost.org/trac10/ticket/4523 https://svn.boost.org/trac10/ticket/4523 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">seq_for_each.patch</span> </li> </ul> Ticket Steven Watanabe Sun, 08 Aug 2010 17:51:51 GMT <link>https://svn.boost.org/trac10/ticket/4523#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4523#comment:1</guid> <description> <p> For the future, it would have been better to have added this as a comment to <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/4501" title="#4501: Bugs: BOOST_PP_SEQ_FOR_EACH fails in corner case (closed: fixed)">#4501</a> instead of creating a new ticket. </p> </description> <category>Ticket</category> </item> <item> <author>ookami1@…</author> <pubDate>Mon, 30 Aug 2010 15:10:39 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/4523#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4523#comment:2</guid> <description> <p> Hold on a second here. This cannot be applied unmodified without breaking other code. </p> <p> If I was to design the preprocessor code from scratch, I would start looping indices from 0, as this would simplify their handling in several places. Unfortunately, there is already code out there, that expects them starting from 1, so BOOST_PP_FOR must not shift the start index to 0, as suggested by the patch. I'll come back to this, once I have some spare time again. </p> <p> cheers Wolf Lammen </p> </description> <category>Ticket</category> </item> <item> <author>ookami1@…</author> <pubDate>Sat, 18 Sep 2010 15:07:30 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/4523#comment:3 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4523#comment:3</guid> <description> <p> As a first step, the following patch modifies the automatic detection of free loop slots. The 1.44 implementation returns values between 1 and 256 only for calls to BOOST_PP_AUTO_REC(predicate, 256). This is an insufficient range for loops handling sequences of maximum length. </p> <p> This patch extends the range of returned values for BOOST_PP_AUTO_REC(predicate, n) from 1 to n+1. This is in preparation for other patches following, for now, you normally should not see any difference. The extra value is delivered only when a loop overflows anyway, and so, at most, error cases are affected. </p> <p> The patch speeds up the expension of all outermost loops, but increases the number of expansions by a few percent for all inner loops. </p> <p> cheers </p> <p> Wolf Lammen </p> </description> <category>Ticket</category> </item> <item> <author>ookami1@…</author> <pubDate>Sat, 18 Sep 2010 15:08:21 GMT</pubDate> <title>attachment set https://svn.boost.org/trac10/ticket/4523 https://svn.boost.org/trac10/ticket/4523 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">detail_auto_rec.2.patch</span> </li> </ul> Ticket ookami1@… Sun, 19 Sep 2010 18:14:32 GMT <link>https://svn.boost.org/trac10/ticket/4523#comment:4 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4523#comment:4</guid> <description> <p> The following patch allows BOOST_PP_FOR to run up to 256 iterations, one more than 1.44 code does. This extension is nessecary to make a couple of macros in preprocessor/seq expand successfully on sequences of maximum length, and it brings BOOST_PP_FOR in line with BOOST_PP_LIMIT_FOR indicating 256 successful iterations. </p> <p> In a loop of n iterations, you need n loop control checks for each iteration, and one final extra check to exit the loop. This last extra check is not always provided for in the 1.44 BOOST_PP_FOR implementation. If the loop count reaches 256, the maximum allowed, the 257-th cycle expansion unconditionally results in an error, and, thus, omits the final check. </p> <p> The idea here is to run into an error only, if a final check indicates continuation of the loop. As a consequence, the 257-th loop cycle BOOST_PP_FOR_257 becomes a meaningful entry point into the loop, which in turn requires an extension of BOOST_PP_AUTO_REC. The previous patch does the nessecary modifications, and needs to be applied as well. </p> <p> It would have had been nice, if indexing of loop iterations had started with 0, so reserving the range 0 - 255 for successful iterations. It would have meant, all indices were from the preprocessor integer range and would have appeared in natural order. Unfortunately, it was once decided to start with 1, and meanwhile there is code out there, that relies on this fact. </p> <p> In order to not break outside code, I decided to leave the indexing as is, i.e running from 1 to 256, then index 257 assigned to the ultimate final check cycle, and index 0 reserved for the unconditionally failing error macro. </p> <p> The proposed changes here should not affect code that runs successfully under 1.44 code, as it extends BOOST_PP_FOR only. Code triggering errors in BOOST_PP_FOR is likely to see different behavior, as previously failing loops may now succeed, and error indices have been moved. I was unable to locate an instance inside Boost itself, where this hurts. </p> <p> The following code fails under the current 1.44 implementation, but will run successfully after having the patches applied: </p> <pre class="wiki">#include &lt;boost/preprocessor.hpp&gt; #define P(r, s) s #define O(r, s) BOOST_PP_DEC(s) #define M(r, s) (s) char const a[] = BOOST_PP_STRINGIZE(BOOST_PP_FOR(256, P, O, M)); int main() { printf("%s", a); return 0; } </pre><p> Cheers </p> <p> Wolf Lammen </p> </description> <category>Ticket</category> </item> <item> <author>ookami1@…</author> <pubDate>Sun, 19 Sep 2010 18:15:34 GMT</pubDate> <title>attachment set https://svn.boost.org/trac10/ticket/4523 https://svn.boost.org/trac10/ticket/4523 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">repetition_for.2.patch</span> </li> </ul> Ticket ookami1@… Sun, 19 Sep 2010 20:04:26 GMT <link>https://svn.boost.org/trac10/ticket/4523#comment:5 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4523#comment:5</guid> <description> <p> While I am at BOOST_PP_FOR, I suggest the following simplification, that reduces </p> <ul><li>file size; </li><li>text to store in macros; </li><li>evaluation costs, measured in replacements; </li></ul><p> for all preprocessors complying to either C90 or C99. Broken preprocessors are not affected, as their code is held in separate files. </p> <p> This is pure optimization, the behavior should not change, and these modifications are orthogonal to the changes in the previous patch. </p> <p> cheers </p> <p> Wolf Lammen </p> </description> <category>Ticket</category> </item> <item> <dc:creator>anonymous</dc:creator> <pubDate>Sun, 19 Sep 2010 20:04:56 GMT</pubDate> <title>attachment set https://svn.boost.org/trac10/ticket/4523 https://svn.boost.org/trac10/ticket/4523 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">repetition_for.optimize.patch</span> </li> </ul> Ticket ookami1@… Sun, 19 Sep 2010 20:42:07 GMT <link>https://svn.boost.org/trac10/ticket/4523#comment:6 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4523#comment:6</guid> <description> <p> The complete revisited set of patches now comprises </p> <ul><li>detail_auto_rec.2.patch </li><li>repetition_for.2.patch </li><li>seq_for_each.patch </li></ul><p> If you like, add </p> <ul><li>repetition_for.optimize.patch </li></ul><p> which further cuts down on evaluation costs (last line in the table above: from 9540 down to 8247) </p> <p> Cheers </p> <p> Wolf Lammen </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Edward Diener</dc:creator> <pubDate>Sun, 17 May 2015 18:03:13 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/4523#comment:7 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4523#comment:7</guid> <description> <p> I am not seeing this example failing in the latest version of Boost, which is Boost 1.58. I do see a failure in VC++ stating: </p> <p> fatal error C1009: compiler limit : macros nested too deeply </p> <p> but that is a compiler problem which Boost PP cannot solve. </p> <p> Your test passes with gcc and clang. </p> </description> <category>Ticket</category> </item> <item> <author>ookami1@…</author> <pubDate>Sun, 17 May 2015 20:44:25 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/4523#comment:8 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4523#comment:8</guid> <description> <p> Weird. </p> <p> I checked my example program against boost 1.58, and still got following output (the obvious middle part replaced by ...): </p> <p> (256) (255) (254)...(5) (4) (3) (2) (1) BOOST_PP_ERROR(0x0002, BOOST_PP_FOR_OVERFLOW). </p> <p> I cannot confirm that the problem is fixed. </p> <p> Cheers Wolf </p> </description> <category>Ticket</category> </item> <item> <dc:creator>anonymous</dc:creator> <pubDate>Sun, 17 May 2015 20:50:38 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/4523#comment:9 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4523#comment:9</guid> <description> <p> Seems to be not fixed, see my comment below. </p> <p> Some more information: </p> <p> gcc -v yields ... gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) </p> <p> uname -a: Linux wolf-tux 3.13.0-52-generic <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/86" title="#86: Tasks: Property and path utilities (closed: Fixed)">#86</a>-Ubuntu SMP Mon May 4 04:32:59 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux </p> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/4523#comment:7" title="Comment 7">eldiener</a>: </p> <blockquote class="citation"> <p> I am not seeing this example failing in the latest version of Boost, which is Boost 1.58. I do see a failure in VC++ stating: </p> <p> fatal error C1009: compiler limit : macros nested too deeply </p> <p> but that is a compiler problem which Boost PP cannot solve. </p> <p> Your test passes with gcc and clang. </p> </blockquote> </description> <category>Ticket</category> </item> <item> <dc:creator>Edward Diener</dc:creator> <pubDate>Mon, 18 May 2015 01:00:10 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/4523#comment:10 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4523#comment:10</guid> <description> <p> Both of you are correct. My test passed but the output for the seq_256 test is junk. I will look into this further. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Edward Diener</dc:creator> <pubDate>Mon, 18 May 2015 06:31:41 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/4523#comment:11 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4523#comment:11</guid> <description> <p> I have fixed this on the latest 'develop' branch of Boost PP. I have used a different technique than the patches submitted as I did not want to make as drastic a change as was suggested to auto_rec. I did use the technique suggested in the seq_for_each patch of caching the seq size rather than having to recalculate it each time. The fix further consists of accepting the 257th inner-loop in BOOST_PP_FOR without forcing an error as long the op(r,state) returned 0, meaning the BOOST_PP_FOR processing is finished. </p> <p> I tested this successfully with gcc and clang with the example given in <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/4501" title="#4501: Bugs: BOOST_PP_SEQ_FOR_EACH fails in corner case (closed: fixed)">#4501</a>. The VC++ compiler issues a compiler error: </p> <pre class="wiki">fatal error C1009: compiler limit : macros nested too deeply </pre><p> but Boost PP can do nothing about that. VC++ succeeds when the number of sequence elements are more reasonable, although I did not experiment with the exact maximum number on which VC++ will process a BOOST_PP_SEQ_FOR_EACH correctly. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Edward Diener</dc:creator> <pubDate>Tue, 19 May 2015 15:42:17 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/4523#comment:12 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4523#comment:12</guid> <description> <p> I have had to back out this change in 'develop' because of a problem encountered. I will be working on another fix for this problem. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Edward Diener</dc:creator> <pubDate>Wed, 20 May 2015 00:15:23 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/4523#comment:13 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4523#comment:13</guid> <description> <p> I have corrected the fix for this bug and it is now on the 'develop' branch. The previous fix was not wrong itself but led to potential warnings from various compilers in C++03 mode. The corrected fix avoids any warnings in any C++ mode. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Edward Diener</dc:creator> <pubDate>Fri, 21 Aug 2015 13:54:08 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/4523#comment:14 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4523#comment:14</guid> <description> <p> This has now been fixed in the latest Boost 1.59 release. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Edward Diener</dc:creator> <pubDate>Fri, 21 Aug 2015 13:54:25 GMT</pubDate> <title>status changed; resolution set https://svn.boost.org/trac10/ticket/4523#comment:15 https://svn.boost.org/trac10/ticket/4523#comment:15 <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