0

Having the following code (greatly simplified):

#define DO_SOME_STUFF(val,x,y) \
  if (x>y) \
  { \
    val = val >> (x-y); \
  } else { \
    val = val >> (y-x); \
  }

An example of calling the macro with expansion will be:

 int val = 5;
 DO_SOME_STUFF(val,5,10);
 => 
 if (5>10)
 {
   // dead code
   val = val >> (5-10); // negative shift warning here
 } else {
   // live code
   val = val >> (10-5); // valid code
 }

Now, since there is dead code, it will be removed by the compiler and everyone will be happy since I will never negative shift - so I'm doing legal stuff here.

Unfortunately, I receive the warnings before the code gets removed (or so it seems).

In the project I'm working the function will be called 100+ times, and the only solution I came up so far is to do the following:

#pragma GCC diagnostic ignored "-Wshift-count-negative"
DO_SOME_STUFF(val,300,20);
#pragma GCC diagnostic pop

This isn't very nice, since i will add a ton of these which will result in hard-to-read blue code, and I would rather avoid it if possible.

Is there an elegant way to remove the warning just for my macro expansion or to ask the compiler to ignore dead code ? (unfortunately i cannot add the #pragma options to my macro definition).

MichaelCMS
  • 4,703
  • 2
  • 23
  • 29
  • 11
    That's one of the reasons to use functions instead.. – Eugene Sh. Jan 11 '18 at 14:40
  • 2
    Are you stuck with C macro or is a pure C++ solution acceptable? – YSC Jan 11 '18 at 14:40
  • 5
    get rid of the macro. There is absolutely no reason to have one here. – bolov Jan 11 '18 at 14:41
  • 2
    Any actual reason to use a macro here? Because if not, you probably should just make this a normal function for several reasons. – Zinki Jan 11 '18 at 14:42
  • I'm not sure my answer is sufficiently well detailed: I'll remove it. I think this is still UB even if the branch is not reachable. See https://stackoverflow.com/questions/23153445/can-branches-with-undefined-behavior-be-assumed-unreachable-and-optimized-as-dea – Bathsheba Jan 11 '18 at 14:48
  • Or is it? Let's wait for the experts to move in. – Bathsheba Jan 11 '18 at 14:49
  • Well, The macro is much faster since the call to the functionality is with constants, and it gets optimized, so in the end I end up with only a very small number of operations. The function (which I already have) requires looping with multiple branching.In the actual case by expanding the macro, I end up using 4 operations and no branching. Multiply this by allot and you get the overview. – MichaelCMS Jan 11 '18 at 14:54
  • 5
    If you declare function with `static` or `static inline` it will likely be equally optimized. – user694733 Jan 11 '18 at 15:00
  • 3
    @MichaelCMS I wouldn't assume that. Check the resulting assembly with full optimizations using functions. It's entirely possible that the function gets inlined and the unreachable branch (and thus the branch condition itself) gets optimized out. And it would do it without any warnings. – François Andrieux Jan 11 '18 at 15:00
  • Ok guys, I'll try this out... But for the sake of general knowledge, what if the macro would be the only viable solution ? – MichaelCMS Jan 11 '18 at 15:02
  • On the fun I'm having with this question, I've asked the community: https://stackoverflow.com/questions/48210052/is-the-behaviour-of-a-program-that-has-undefined-behaviour-on-an-unreachable-pat – Bathsheba Jan 11 '18 at 15:03
  • @Bathsheba aww. I was going to post it was a duplicate of this one before you deleted it ;) – UKMonkey Jan 11 '18 at 15:04
  • @UK: It's back, had the XOR swap incorrect. Oops. – Bathsheba Jan 11 '18 at 15:06
  • 1
    I've downvoted because I still can't tell if its a C or a C++ question. – YSC Jan 11 '18 at 15:17
  • @YSC the question is valid for both. I have a macro that gives warnings in dead code. This can happen in both languages, and the "use some other code" answers are nice just for the sake of know how. In real life you are sometimes stuck with some piece of code that you have to use. This isn't a X Y problem, I want to know if it's possible to remove warnings from the code that will be removed by the compiler. – MichaelCMS Jan 11 '18 at 15:24
  • 2
    even if the question can be asked for c as well for c++, the answers will be different depending on what language you actually want – 463035818_is_not_an_ai Jan 11 '18 at 15:48
  • 1
    The question is valid for both language, but what about answers? I've asked you before if you expect answers for C or C++. You failed to answer. – YSC Jan 11 '18 at 15:49
  • 1
    @YSC I'm expecting an answer for suppressing warnings in dead code ( code that gets optimized out by the compiler), if it's possible or not. and I gave a piece of code that generates this behavior. The code is valid for both C and C++ and I'm searching for an answer that will be valid for both C and C++. Since it needs to be valid for both it means that only the subset common for the two languages can be used. Is it now a bit clearer? – MichaelCMS Jan 12 '18 at 09:08

1 Answers1

4

In c++11 you could use a template constexpr function instead of the macro. It can then be executed during the compilation and will not produce a warning.

template <typename T, typename T2>
constexpr T do_some_stuff(const T& val, const T2& x, const T2& y)
{  
  return x > y ? val >> (x - y) : val >> (y - x);
}

template <typename T, typename T2>
constexpr T do_some_stuff_wrong(const T& val, const T2& x, const T2& y)
{  
  return x < y ? val >> (x - y) : val >> (y - x);
}

int main() 
{
    constexpr int val = do_some_stuff(5, 5, 10); // no warning
    constexpr int val2 = do_some_stuff_wrong(5, 5, 10); // warning
}

Live example

AMA
  • 4,114
  • 18
  • 32
  • Thanks. Was actually wondering about the C++ version. Now all I need is an answer for the C version (which is my real life problem unfortunately). – MichaelCMS Jan 11 '18 at 15:04
  • 3
    Then why tag C++ if it's a C problem ? – Andrei Damian Jan 11 '18 at 15:09
  • @AndreiAndrey because the problem is valid for c++ pre c++11 – MichaelCMS Jan 11 '18 at 15:12
  • It would be a plus if `val` could be another type than `x` and `y`. – YSC Jan 11 '18 at 15:20
  • @AMA the code doesn't compile on my side. Did it work for you ? – MichaelCMS Jan 11 '18 at 15:36
  • @MichaelCMS there's a live link at the bottom: the code works with gcc and clang. I didn't test it elsewhere. – AMA Jan 11 '18 at 15:40
  • @AMA updated: only works for c++14. Another limitation that this approach has is that it doesn't work if one of the parameters is a variable, and I need that "val" to have some operations performed on it inside the expansion. – MichaelCMS Jan 11 '18 at 15:41
  • 1
    @MichaelCMS added a fix, to make it work with c++11. Yes, the second limitation is there. – AMA Jan 11 '18 at 15:54
  • @MichaelCMS: this is confusing. How can this C++ answer work if your "real world problem" is in C? – Jongware Jan 13 '18 at 02:17
  • 1
    @usr2564301 It doesn't. However it shows a valid answer for an interpretation of my question. The answer isn't complete since it doesn't work for C++ pre 11 either, that's why it's not accepted. – MichaelCMS Jan 17 '18 at 14:57