Wish: __builtin_side_effect_free_p, __builtin_lvalue_p

Niels Möller nisse@lysator.liu.se
Sun Feb 25 13:26:00 GMT 2001


Richard Henderson <rth@redhat.com> writes:

> On Wed, Feb 21, 2001 at 11:49:48AM +0100, Niels Möller wrote:
> >   #define FOO(f, a) ((f)->foo((f), (a)))
> 
> Try
> 
>   #define FOO(f, a)  ({ __typeof(f) f_ = (f); f_->foo(f_, (a)); })

It seems I replied too quickly. There's one problem with the above
suggestion: It doesn't really solve the problem.

Say that I conditionalize the definition (as I want the code to
compile with other compilers) as follows.

  #ifdef __GNUC__
  # define FOO(f, a)  ({ __typeof(f) f_ = (f); f_->foo(f_, (a)); })
  #else
  # define FOO(f, a)  ((f)->foo((f), (a)))
  #endif

Next, assume that somewhere in my code, I accidentally use the macro
with a first argument that has side effects,

  x = FOO(read_some_data(...), 1);

This code will work fine when compiled with gcc, thanks to the block
construction above. But when compiled with some other compiler, the
bug is still there. And gcc didn't help me find it.

So what I'm asking for is not a way to make the code work correctly
when compiled with gcc. I'm asking for a way to get gcc to *complain*
about the incorrect use of the macro. I can't see how to do get the
current gcc to do that correctly, the (void)&(f) construction being
the best approximation I have been able to come up with.

I think that would be a good thing to add, analogous to
__builtin_constant_p (although what I'd really need is probably
__builtin_side_effect_free_or_warn). An analogous
__builtin_constant_or_warn would probably be useful as well, for macros
that are intended to be used only with constants.

It's fine if the checking is done only when optimization is enabled (I
imagine that most of the information needed is already available for
use by the optimizer). If I want to get the most warnings out from
gcc, I have to enable optimization anyway.

Looking at expand_builtin in expr.c (from gcc-2.95.2), it seems that
implementation should be straight-forward, something like

--- expr.c-original     Thu Jul  1 00:59:55 1999
+++ expr.c      Sun Feb 25 22:15:52 2001
@@ -9171,6 +9171,22 @@
          return tmp;
        }

+    case BUILT_IN_SIDE_EFFECT_FREE_OR_WARN:
+      if (arglist == 0)
+       error("`__builtin_sideeffect_free_or_warn' used with no argument")
+      else
+       {
+         tree arg = TREE_VALUE (arglist);
+
+         /* We warn if evaluating the argument has side-effects. */
+         STRIP_NOPS (arg);
+
+         if (TREE_SIDE_EFFECTS (arg))
+           warning("`__builtin_sideeffect_free_or_warn' with potential sideeffects'");
+
+         return arg;
+       }
+
     case BUILT_IN_FRAME_ADDRESS:
       /* The argument must be a nonnegative integer constant.
         It counts the number of frames to scan up the stack.

Does it have to be more complex than this?

Best regards,
/Niels



More information about the Gcc-bugs mailing list