https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89718
Bug ID: 89718 Summary: _Pragma GCC diagnostic ignored inside macro Product: gcc Version: 9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: federico.kircheis at gmail dot com Target Milestone: --- Given following piece of code ---- #define DIAGNOSTIC_HELPER0(x) #x #define DIAGNOSTIC_HELPER1(kind, y) DIAGNOSTIC_HELPER0(GCC diagnostic kind #y) #define DIAGNOSTIC(kind, warning, statements)\ _Pragma("GCC diagnostic push")\ _Pragma(DIAGNOSTIC_HELPER1(kind, warning))\ statements \ _Pragma("GCC diagnostic pop") DIAGNOSTIC(error, -Wuninitialized, int foo(int a, int b){return a;} int main(){ int i; return foo(i, i); } ---- I would expect it not to compile when executing `g++ main.cpp`, but it compiles without any issues. With clang++ (expected behavior): -- clang++ main.cpp main.cpp:15:16: error: variable 'i' is uninitialized when used here [-Werror,-Wuninitialized] return foo(i, i); ^ main.cpp:7:5: note: expanded from macro 'DIAGNOSTIC' statements \ ^~~~~~~~~~ main.cpp:14:5: note: variable 'i' is declared here int i; ^ 1 error generated. -- When manually "expanding" the macros to ---- _Pragma("GCC diagnostic push")\ _Pragma(DIAGNOSTIC_HELPER1(error, -Wuninitialized)) int foo(int a, int b){return a;} int main(){ int i; return foo(i, i); } _Pragma("GCC diagnostic pop") ---- The behavior is the expected: -- g++ main.cpp main.cpp: In function ‘int main()’: main.cpp:26:15: error: ‘i’ is used uninitialized in this function [-Werror=uninitialized] return foo(i, i); ~~~^~~~~~ cc1plus: some warnings being treated as errors -- and no file is generated. Notice that the same behavior (__pragma not taken into account) is reproducible when using "ignored" or "warning" instead of "error". Some other considerations/information: msvc works like clang (with other pragmas obviously). With the provided code, also (tested on https://godbolt.org/) elcc (any version), djggp4.9.4, and zapcc, all behaves like clang (pragma is taken into account). While testing different compilers, I discovered that this seems to be a "partial" regression, since gcc 4.9.4. Here the compiler triggers a warning (and not error) when using "GCC diagnostic error", but does not ignore the warning when using "GCC diagnostic ignored". It is a regression compared to gcc 4.4.7, since it triggers an error (when using "GCC diagnostic error", I'm unsure why the warnings are generated): -- <source>:16: warning: expected [error|warning|ignored] after '#pragma GCC diagnostic' <source>:16: warning: expected [error|warning|ignored] after '#pragma GCC diagnostic' <source>: In function 'int main()': <source>:10: error: 'i' is used uninitialized in this function Compiler returned: 1 -- My local gcc version: -- g++ (Debian 8.3.0-2) 8.3.0 Copyright (C) 2018 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- but the behavior is consistent since gcc5 on different operating systems. Notice that this is not a duplicate of https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69543, since ---- # define ERR_BEGIN \ _Pragma ("GCC diagnostic push") \ _Pragma ("GCC diagnostic error \"-Wuninitialized\"")\ _Pragma ("GCC diagnostic error \"-Wmaybe-uninitialized\"") # define ERR_END \ _Pragma ("GCC diagnostic pop") int main (int yylval, char**) { char *yyvsp; ERR_BEGIN *++yyvsp = yylval; ERR_END } ---- triggers a compile error: -- g++ /tmp/main.cpp /tmp/main.cpp: In function ‘int main(int, char**)’: /tmp/main.cpp:12:12: error: ‘yyvsp’ is used uninitialized in this function [-Werror=uninitialized] *++yyvsp = yylval; ~~~~~~~~~^~~~~~~~ cc1plus: some warnings being treated as errors --