12

I just had a redefine conflict in the project I'm working on and while tracing down why it's not happening on all platforms (turned out to be to order of includes), I stumbled upon the following behavior which I cannot explain.

1. compiles without warnings

    #define LIST_HEAD(a) { int a = 0; }                                                                                                                     
    #include <sys/queue.h>                                                          

    int main() {                                                                    
        return 0;                                                               
    }

2. "macro redefined" warning

    #include <sys/queue.h>
    #define LIST_HEAD(a) { int a = 0; }                                                                                                       

    int main() {                                                                    
        return 0;                                                               
    }

I would expect both cases to produce the warning, since there're no checks in <sys/queue.h> that would prevent a redefine.

So why does the first case produces no warning, while the second one does? What I'm missing here?

Btw: I get the same results on my Mac with clang and my Linux box with gcc.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
grasbueschel
  • 879
  • 2
  • 8
  • 24
  • 1
    Maybe sys/queue.h has a #undef LIST_HEAD somewhere? Check – Name Dec 16 '12 at 16:27
  • Anybody interested in answering, I found the source code for sys/queue.h here: http://freebsd.active-venture.com/FreeBSD-srctree/newsrc/sys/queue.h.html – Name Dec 16 '12 at 16:35
  • It looks like the LIST_HEAD defined in queue.h has two parameters, the one you're defining has one(parameter). Maybe this difference in the number of parameters makes the compiler give/not give a warning depending on the order they were defined. – Name Dec 16 '12 at 16:37
  • 1
    @JesusPlusPlus No undef's in queue.h. I've checked this before. And I've also checked the number of parameters. That doesn't make any difference. – grasbueschel Dec 16 '12 at 16:40
  • Well then I guess a cannot say why... – Name Dec 16 '12 at 16:42

1 Answers1

14

By default, this warning is suppressed in system headers. The code in <sys/queue.h> is considered to come from a system header because sys/queue.h was found by searching a path marked as containing system headers.

So in (2) you see the warning because it is generated within your code, while in (1) the warning is generated within queue.h, and so is suppressed. Add -Wsystem-headers to your compilation options, and you'll see the warning in both cases.

John Marshall
  • 6,815
  • 1
  • 28
  • 38
  • So `-Wsystem.headers` is not totally useless... but having this feature without all the other garbage produced by this warning would be nice since macro redefinition is undefined behavior, it wouldn't be so hard to implement I think. Anyway, +1! – effeffe Dec 16 '12 at 16:53
  • To be a little more precise: GCC's preprocessor suppresses this warning in system headers ([system header warnings are normally unhelpful in finding bugs in your own code, therefore suppressed](http://gcc.gnu.org/onlinedocs/cpp/Invocation.html#index-Wsystem_002dheaders-139)), and apparently clang does something similar. But this doesn't mean other compilers necessarily suppress warnings similarly... – John Marshall Dec 16 '12 at 16:56