[Boost.Math] Re: [Monotone-debian] Bug#653764: FTBFS with Boost 1.48: lgamma_small.hpp:483:38: error: expected primary-expression before 'do'

Hello, Boost Developers: I recently did rebuilds of all Debian packages that use Boost with Boost 1.48 and this is one of the casualties of the upgrade (from 1.46.1). On Sat, Dec 31, 2011 at 12:02:37PM +0100, Zack Weinberg wrote:
On Fri, Dec 30, 2011 at 9:53 PM, Steve M. Robbins <smr@debian.org> wrote:
This package failed to build using the newest Boost version 1.48: ... /usr/include/boost/math/special_functions/detail/lgamma_small.hpp: In function 'T boost::math::detail::lgamma_small_imp(T, T, T, const mpl_::int_<0>&, const Policy&, const L&)': ... /usr/include/boost/math/special_functions/detail/lgamma_small.hpp:483:38: error: expected primary-expression before 'do'
I'm not in a position to verify this for myself for another week, but I have a horrible feeling I know what's wrong: Monotone defines several one-character macros for its own use, and L() is one of them. It looks like Boost is using L() for its own purposes and expecting it not to be a macro.
Zack, you are absolutely right. The lgamma_small header has a templated class method using "L" as one of the templates: template <class T, class Policy, class L> T lgamma_small_imp(T z, T zm1, T zm2, const mpl::int_<0>&, const Policy& pol, const L&) The compile error at line 483 is at a call to L(): result = log(gamma_imp(z, pol, L()));
I'd argue that Boost headers should take care to defend themselves from the possibility of such macros, but fixing that in Boost might be an enormous amount of work, and in any case, 1.48 is already out there.
Boost.Math developers: What is the right thing to do here? More descriptive class template parameters? Attached is a trivial file to reproduce the bug. Thanks, -Steve

On Jan 1, 2012, at 4:30 PM, Steve M. Robbins wrote:
Hello,
Boost Developers: I recently did rebuilds of all Debian packages that use Boost with Boost 1.48 and this is one of the casualties of the upgrade (from 1.46.1).
On Sat, Dec 31, 2011 at 12:02:37PM +0100, Zack Weinberg wrote:
On Fri, Dec 30, 2011 at 9:53 PM, Steve M. Robbins <smr@debian.org> wrote:
This package failed to build using the newest Boost version 1.48: ... /usr/include/boost/math/special_functions/detail/lgamma_small.hpp: In function 'T boost::math::detail::lgamma_small_imp(T, T, T, const mpl_::int_<0>&, const Policy&, const L&)': ... /usr/include/boost/math/special_functions/detail/lgamma_small.hpp:483:38: error: expected primary-expression before 'do'
I'm not in a position to verify this for myself for another week, but I have a horrible feeling I know what's wrong: Monotone defines several one-character macros for its own use, and L() is one of them. It looks like Boost is using L() for its own purposes and expecting it not to be a macro.
Zack, you are absolutely right. The lgamma_small header has a templated class method using "L" as one of the templates:
template <class T, class Policy, class L> T lgamma_small_imp(T z, T zm1, T zm2, const mpl::int_<0>&, const Policy& pol, const L&)
The compile error at line 483 is at a call to L():
result = log(gamma_imp(z, pol, L()));
I'd argue that Boost headers should take care to defend themselves from the possibility of such macros, but fixing that in Boost might be an enormous amount of work, and in any case, 1.48 is already out there.
How, though? #undef L That would break client code.
Boost.Math developers: What is the right thing to do here? More descriptive class template parameters?
This is a hard problem - because pretty much whatever identifier gets chosen, you have a chance that some program/library/package somewhere has defined it in a macro. Several years ago, I worked with a guy who was passionately anti-C++. He said, "Look - it's all crap. if I add '#include <vector>' to my source file, all of a sudden I get all these compile errors! What kind of idiot writes this stuff?" Finally, I got tired of his complaining, and looked at the problems that he was having. Buried in one of his header files was '#define T true' ;-) -- Marshall Marshall Clow Idio Software <mailto:mclow.lists@gmail.com> A.D. 1517: Martin Luther nails his 95 Theses to the church door and is promptly moderated down to (-1, Flamebait). -- Yu Suzuki

On Jan 1, 2012, at 4:51 PM, Marshall Clow wrote:
On Jan 1, 2012, at 4:30 PM, Steve M. Robbins wrote:
On Sat, Dec 31, 2011 at 12:02:37PM +0100, Zack Weinberg wrote:
Monotone defines several one-character macros for its own use, and L() is one of them. It looks like Boost is using L() for its own purposes and expecting it not to be a macro.
I'd argue that Boost headers should take care to defend themselves
How, though? #undef L
That would break client code.
Boost.Math developers: What is the right thing to do here? More descriptive class template parameters?
This is a hard problem - because pretty much whatever identifier gets chosen, you have a chance that some program/library/package somewhere has defined it in a macro.
Several years ago, I worked with a guy who was passionately anti-C++. He said, "Look - it's all crap. if I add '#include <vector>' to my source file, all of a sudden I get all these compile errors! What kind of idiot writes this stuff?"
Finally, I got tired of his complaining, and looked at the problems that he was having.
Buried in one of his header files was '#define T true' ;-)
The error is defining macros under likely-to-collide names which will be seen by code outside of your control. Monotone should either use a more descriptive name or define the macro after including foreign headers. Mr. T's problem has too many solutions to list, but since he likes C, I'll just say s/T/1/g. Josh

I'm not in a position to verify this for myself for another week, but I have a horrible feeling I know what's wrong: Monotone defines several one-character macros for its own use, and L() is one of them. It looks like Boost is using L() for its own purposes and expecting it not to be a macro.
Zack, you are absolutely right. The lgamma_small header has a templated class method using "L" as one of the templates:
template <class T, class Policy, class L> T lgamma_small_imp(T z, T zm1, T zm2, const mpl::int_<0>&, const Policy& pol, const L&)
The compile error at line 483 is at a call to L():
result = log(gamma_imp(z, pol, L()));
This isn't new to 1.48: the code has used "L" as a template param since at least 1.38.
I'd argue that Boost headers should take care to defend themselves from the possibility of such macros, but fixing that in Boost might be an enormous amount of work, and in any case, 1.48 is already out there.
Boost.Math developers: What is the right thing to do here? More descriptive class template parameters?
That's what I'll use as a fix in this case, in general though, we can only fix "known issues" given that any symbol can be poisoned in the preprocessor :-( Thanks for the heads up, John.

I'm not in a position to verify this for myself for another week, but I have a horrible feeling I know what's wrong: Monotone defines several one-character macros for its own use, and L() is one of them. It looks like Boost is using L() for its own purposes and expecting it not to be a macro.
I've changed the name in Trunk to "Lanczos". Note, however, that there are some uses of "L" still present that aren't going to be removed: we have some constants defined with something like: BOOST_JOIN(x, L) where "x" here evaluates to a numeric value, and it would be really quite complex to remove the use of L in this case. As long as L is a function-like macro in monotone we should be OK though. John.

On 1/1/2012 7:30 PM, Steve M. Robbins wrote:
Hello,
Boost Developers: I recently did rebuilds of all Debian packages that use Boost with Boost 1.48 and this is one of the casualties of the upgrade (from 1.46.1).
On Sat, Dec 31, 2011 at 12:02:37PM +0100, Zack Weinberg wrote:
On Fri, Dec 30, 2011 at 9:53 PM, Steve M. Robbins<smr@debian.org> wrote:
This package failed to build using the newest Boost version 1.48: ... /usr/include/boost/math/special_functions/detail/lgamma_small.hpp: In function 'T boost::math::detail::lgamma_small_imp(T, T, T, const mpl_::int_<0>&, const Policy&, const L&)': ... /usr/include/boost/math/special_functions/detail/lgamma_small.hpp:483:38: error: expected primary-expression before 'do'
I'm not in a position to verify this for myself for another week, but I have a horrible feeling I know what's wrong: Monotone defines several one-character macros for its own use, and L() is one of them.
Any programmer who doesn't attempt to give distinctive names to macros in their header file(s) is really clueless. I don't know who/what "monotone" is but whoever did the programming for "it" has done a really poor job by naming a macro "L".

From: Edward Diener
I'm not in a position to verify this for myself for another week, but I have a horrible feeling I know what's wrong: Monotone defines several one-character macros for its own use, and L() is one of them.
Any programmer who doesn't attempt to give distinctive names to macros in their header file(s) is really clueless. I don't know who/what "monotone" is but whoever did the programming for "it" has done a really poor job by naming a macro "L".
We have seen this issue from Microsoft, Apple and Sun plus a host of smaller library vendors. My favorite was the electrical engineering package that defined every symbol for electrical units as a macro that was the conversion factor to their standard units. The world is literally full of clueless programmers, or rather, it is full of code written by clueless programmers that competent maintainers now feel unable to fix because it would break working code. The standard library protects itself by prepending double underscore to every identifier that isn't a documented interface. "#define T true" shouldn't break <vector> because it should be using __T and not bare T. That is why boost breaks but not the stl when this silliness crops up (with the notable exception of min/max from windows.h since those are documented interfaces of the stl). Since the syntax error is in boost files and not the offending macro (no way for compiler to point to the macro after preprocessor has garbled the code) people tend to complain to us because they don't understand the error. The only way to protect oneself is to use long, descriptive variable names even for template parameters. What normally happens is #undefine gets added to the user code or they swap the order of includes once they figure out why they are getting the error. We could make a header file that defines every one, two or three character macro then undefines them. Including that header would tell people where they have stupid macros defined because the preprocessor error would point them right to them. I wouldn't want it included in any boost library though because it would break working code. We all pay for the mistakes of the past, and we were all clueless programmers at some point. Regards, Luke
participants (6)
-
Edward Diener
-
John Maddock
-
Joshua Juran
-
Marshall Clow
-
Simonson, Lucanus J
-
Steve M. Robbins