https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85153
Bug ID: 85153 Summary: _Pragma to disable -Wswitch-unreachable diagnostic not properly working when used within preprocessor macro Product: gcc Version: 7.3.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: driver Assignee: unassigned at gcc dot gnu.org Reporter: falemagn at gmail dot com Target Milestone: --- Created attachment 43809 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=43809&action=edit The preprocessed source, which works as expected The preprocessed output (attached) behaves as expected, so I assume this problem has to do with the driver and/or a strange interaction between driver, preprocessor and compiler. For lack of better knowledge, I've filed this bug under the "driver" component. The whole code is on godbolt: https://godbolt.org/g/rTc3AU Given the following code, g++ properly emits a warning. int x; int test1(int val) { switch (val) { if (!x) { case 1: return 10; } } return 0; } pragmatest.cpp: In function ‘int test1(int)’: pragmatest.cpp:5:25: warning: statement will never be executed [-Wswitch-unreachable] if (!x) { ^~ If I then try to silence this warning with the proper _Pragma directive, in clear, like in the following code, it works as expected as in the compiler doesn't complain any longer: int test2(int val) { switch (val) { _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wswitch-unreachable\"") if (!x) { _Pragma("GCC diagnostic pop") case 1: return 10; } } return 0; } If I then try to to hide the pragmas within 2 macros, like in the following code, it still works: #define B _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wswitch-unreachable\"") #define E _Pragma("GCC diagnostic pop") int test3(int val) { switch (val) { B if (!x) E { case 1: return 10; } } return 0; } However, if now I want to turn the whole "B if (!x) E" statement into a define of its own, like in the following code, it doesn't work any longer. #define X() B if (!x) E int test4(int val) { switch (val) { X() { case 1: return 10; } } return 0; } pragmatest.cpp: In function ‘int test4(int)’: pragmatest.cpp:39:23: warning: statement will never be executed [-Wswitch-unreachable] #define X() B if (!x) E ^~ pragmatest.cpp:43:21: note: in expansion of macro ‘X’ X() { ^ This looked quite odd, and at first thought I couldn't figure out what was going on, but then I thought of using a layer of indirection around the pragma macros, thinking it might have something to do with secondary expansion, so I tried the following code, but still no luck. #define Y(x) x #define X2() Y(B) if (!x) Y(E) int test5(int val) { switch (val) { X2() { case 1: return 10; } } return 0; } pragmatest.cpp: In function ‘int test5(int)’: pragmatest.cpp:52:27: warning: statement will never be executed [-Wswitch-unreachable] #define X2() Y(B) if (!x) Y(E) ^~ pragmatest.cpp:55:21: note: in expansion of macro ‘X2’ X2() { ^~ So I tried something which in my mind wouldn't make sense at all - notice that I wrapped the x **variable** in the Y() macro - but what did I have to lose anyway? But the following code still (unsurprinsigly?) didn't work: #define X3() Y(B) if (!Y(x)) Y(E) int test6(int val) { switch (val) { X3() { case 1: return 10; } } return 0; } pragmatest.cpp: In function ‘int test6(int)’: pragmatest.cpp:63:27: warning: statement will never be executed [-Wswitch-unreachable] #define X3() Y(B) if (!Y(x)) Y(E) ^ pragmatest.cpp:66:21: note: in expansion of macro ‘X3’ X3() { ^~ However this time around the warning message gave me a hint! Why would the compiler complain only about the exclamation mark not being reachable? So I tried the following... and it worked! #define X4() Y(B) if (Y(!)x) Y(E) int test7(int val) { switch (val) { X4() { case 1: return 10; } } return 0; } That code above makes the compiler stay silent, against all odds. So I thought: let's see if removing the Y() wrapping around the pragma macros still works. Nope, it didn't. #define X5() B if (Y(!)x) E int test8(int val) { switch (val) { X5() { case 1: return 10; } } return 0; } pragmatest.cpp: In function ‘int test8(int)’: pragmatest.cpp:85:26: warning: statement will never be executed [-Wswitch-unreachable] #define X5() B if (Y(!)x) E ^ pragmatest.cpp:51:18: note: in definition of macro ‘Y’ #define Y(x) x ^ pragmatest.cpp:88:21: note: in expansion of macro ‘X5’ X5() { ^~ Again, the compiler indicated that the error has to do with the exclamation mark.