gcc4.3 warning for multiple scope_exits

View: New views
5 Messages — Rating Filter:   Alert me  

gcc4.3 warning for multiple scope_exits

by Kim Barrett-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Boost.ScopeExit uses a tricky bit of code (from Steven Watanabe) to allow a
macro expansion to contain code which will declare a variable exactly once,
regardless of how many times the macro is used in a given
scope. Unfortunately, gcc4.3 -Wall generates a warning for this code in the
second and later uses of the macro in the same scope. The warning is

   comparisons like X<=Y<=Z do not have their mathematical meaning

It is complaining about a statement that gets parsed as

   identifier < 0 > variable;

Valid code, and correct in this particular case, but the warning is there
never the less.

I realize that boost doesn't have a no-warnings policy (dealing with compiler
variations that lead to actual errors is hard enough), but since my team has a
general policy of using -Werror and I've been proselytizing the use of
scope_exit within our group, I was motivated to find a way to kill this
warning.

After studying Steven's trick (ouch! my brain hurts) I've come up with an
extension of the same technique which avoids the warning, using the time
honored approach of adding another level of indirection. Here's my patch:

----------

--- scope_exit.hpp.orig 2009-07-09 13:19:36.000000000 -0400
+++ scope_exit.hpp.new  2009-07-09 13:20:04.000000000 -0400
@@ -36,14 +36,21 @@
      typedef void* declared;
      struct undeclared { declared dummy[2]; };

+    template<int>
+    struct holder
+    {
+        declared value;
+        static const int apply_value = 0;
+        friend void operator>(int, const holder&) {}
+    };
+
      template<>
      struct declare<sizeof(undeclared)>
      {
          template<int>
          struct apply
          {
-            declared value;
-            friend void operator>(bool, const apply&) {}
+            static const int apply_value = 0;
          };
      };

@@ -214,8 +221,9 @@
          BOOST_PP_SEQ_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_MEMBER, id,
seq)          \
          BOOST_SCOPE_EXIT_AUX_PARAMS_T_CTOR(id, seq)
\
      } BOOST_SCOPE_EXIT_AUX_PARAMS(id)
BOOST_SCOPE_EXIT_AUX_PARAMS_INIT(id, seq)\
-    boost::scope_exit::aux::declare<sizeof(boost_scope_exit_args)>
\
-        ::apply<0> boost_scope_exit_args;
\
+    boost::scope_exit::aux::holder<
\
+
boost::scope_exit::aux::declare<sizeof(boost_scope_exit_args)>
\
+            ::apply<0>::apply_value> boost_scope_exit_args;
\
      boost_scope_exit_args.value = &BOOST_SCOPE_EXIT_AUX_PARAMS(id);
\
      struct BOOST_SCOPE_EXIT_AUX_GUARD_T(id) {
\
          BOOST_SCOPE_EXIT_AUX_PARAMS_T(id)* boost_se_params_;
\


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: gcc4.3 warning for multiple scope_exits

by Alexander Nasonov :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Kim Barrett <kab.conundrums <at> verizon.net> writes:

>
> Boost.ScopeExit uses a tricky bit of code (from Steven Watanabe) to allow a
> macro expansion to contain code which will declare a variable exactly once,
> regardless of how many times the macro is used in a given
> scope. Unfortunately, gcc4.3 -Wall generates a warning for this code in the
> second and later uses of the macro in the same scope. The warning is
>
>    comparisons like X<=Y<=Z do not have their mathematical meaning
>
> It is complaining about a statement that gets parsed as
>
>    identifier < 0 > variable;
>
> Valid code, and correct in this particular case, but the warning is there
> never the less.

Hi Kim,

I don't understand how it works for the second use within one scope:

boost::scope_exit::aux::holder<
  boost::scope_exit::aux::declare<
    sizeof(boost_scope_exit_args)
  >::apply<0>::apply_value
> boost_scope_exit_args;

If sizeof(boost_scope_exit_args) is equal to sizeof(declared),
the resulting type would be holder<(0<0>::apply_value)>. But I don't
see a global variable apply_value in your patch.

BTW, I modified Steven's code and introduced a bug because
sizeof(declare<sizeof(undeclared)>::apply<0>) does not necessarily
equal to sizeof(declared).

Alex

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: gcc4.3 warning for multiple scope exits

by Kim Barrett-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

At 10:48 AM +0000 7/14/09, Alexander Nasonov wrote:
>boost::scope_exit::aux::holder<
>   boost::scope_exit::aux::declare<
>     sizeof(boost_scope_exit_args)
>   >::apply<0>::apply_value
>>  boost_scope_exit_args;
>
>If sizeof(boost_scope_exit_args) is equal to sizeof(declared),
>the resulting type would be holder<(0<0>::apply_value)>. But I don't
>see a global variable apply_value in your patch.

The added parenthesis in the above, in

   holder<(0<0>::apply_value)>

don't describe the actual parse and evaluation. Instead, that snippet
gets parsed and evaluated as

   holder<(0<0)>::apply_value

so that the whole (expression) statement (with disambiguating
parenthesis added) is

  holder<(0<0)>::apply_value > boost_scope_exit_args;

>BTW, I modified Steven's code and introduced a bug because
>sizeof(declare<sizeof(undeclared)>::apply<0>) does not necessarily
>equal to sizeof(declared).

Are you sure? Perhaps I'm missing something, but it looks to me like
those values should indeed be the same. The "apply" class template in
question has one member, of type "declared". Given that, I would be
surprised if the "apply" class template could have a different size
(or alignment) from the "declared" type.
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: gcc4.3 warning for multiple scope exits

by Alexander Nasonov :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Kim Barrett <kab.conundrums <at> verizon.net> writes:

>
> At 10:48 AM +0000 7/14/09, Alexander Nasonov wrote:
> >boost::scope_exit::aux::holder<
> >   boost::scope_exit::aux::declare<
> >     sizeof(boost_scope_exit_args)
> >   >::apply<0>::apply_value
> >>  boost_scope_exit_args;
> >
> >If sizeof(boost_scope_exit_args) is equal to sizeof(declared),
> >the resulting type would be holder<(0<0>::apply_value)>. But I don't
> >see a global variable apply_value in your patch.
>
> The added parenthesis in the above, in
>
>    holder<(0<0>::apply_value)>
>
> don't describe the actual parse and evaluation. Instead, that snippet
> gets parsed and evaluated as
>
>    holder<(0<0)>::apply_value
>

This is crazy, isn't it?

Q: correctly indent the following code: <see code above>
A: it's impossible

For the second use, the correct indentation is:

boost::scope_exit::aux::holder<
  boost::scope_exit::aux::declare<
    sizeof(boost_scope_exit_args)
  >::apply < 0
>::apply_value > boost_scope_exit_args;


> >BTW, I modified Steven's code and introduced a bug because
> >sizeof(declare<sizeof(undeclared)>::apply<0>) does not necessarily
> >equal to sizeof(declared).
>
> Are you sure? Perhaps I'm missing something, but it looks to me like
> those values should indeed be the same. The "apply" class template in
> question has one member, of type "declared". Given that, I would be
> surprised if the "apply" class template could have a different size
> (or alignment) from the "declared" type.

They're the same because void* is well aligned and there is no padding
in struct apply<0> but strictly speaking, they don't have to be of equal
size. I like explicit specializations for declared and undeclared, though.
They make reading code a little bit easier (and here "a little bit" make
a big difference, given how complex the trick is).

Perhaps adding BOOST_STATIC_ASSERT would be enough?

Alex
multiplied by a complec.


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: gcc4.3 warning for multiple scope exits

by Kim Barrett-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

At 1:38 PM +0000 7/14/09, Alexander Nasonov wrote:
>This is crazy, isn't it?

No kidding!

>Q: correctly indent the following code: <see code above>
>A: it's impossible
>
>For the second use, the correct indentation is:
>
>boost::scope_exit::aux::holder<
>   boost::scope_exit::aux::declare<
>     sizeof(boost_scope_exit_args)
>   >::apply < 0
>  >::apply_value > boost_scope_exit_args;

Yes. (I *think*. See discussion of "crazy" above.)

>They're the same because void* is well aligned and there is no padding
>in struct apply<0> but strictly speaking, they don't have to be of equal
>size.

Hm. Everything involved looks like POD to me (albeit with oddly spelled
names, if one is a C programmer). I think lots of code would be broken
if such types could be different in size. But I admit I can't right now
put together a string of text in the standard that would guarantee that
they are the same size.

>  I like explicit specializations for declared and undeclared, though.
>They make reading code a little bit easier (and here "a little bit" make
>a big difference, given how complex the trick is).

Completely agree.

>Perhaps adding BOOST_STATIC_ASSERT would be enough?

I don't see any way that could hurt. Even if not necessary, it may help
guide future readers in the right direction.
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost