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.