https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64332
Manuel López-Ibáñez <manu at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Keywords| |diagnostic Status|UNCONFIRMED |NEW Last reconfirmed| |2014-12-16 CC| |manu at gcc dot gnu.org Component|c++ |c Summary|gcc/g++ handles |wrong location for |system_header differently |Wattributes warning Ever confirmed|0 |1 --- Comment #4 from Manuel López-Ibáñez <manu at gcc dot gnu.org> --- The difference that you see is because of macro expansion and bad location info in the C FE. This testcase makes it clear: $ cat test.c #define __constructor __attribute__((constructor)) typedef void (*__cb_type)(void *); int foo(__cb_type __constructor); $ cc1 -Wattributes test.c test.c:3:1: warning: ‘constructor’ attribute ignored [-Wattributes] int foo(__cb_type __constructor); ^ $ cc1plus -Wattributes test.c test.c:1:50: warning: ‘constructor’ attribute ignored [-Wattributes] #define __constructor __attribute__((constructor)) ^ test.c:3:19: note: in expansion of macro ‘__constructor’ int foo(__cb_type __constructor); ^ The C FE does not point to __constructor (3:1 vs 3:19), thus it doesn't realize this comes from a macro expansion, thus (in your testcase) the system_header is applied. The C++ FE sees that the attribute actually appears in 1:50 and not 3:19, thus in your testcase the pragma system_header does not apply. Whether the correct behavior is that the system_header applies to the definition or to the expansion location, I am not sure. However, the bad location of the C FE is clearly a bug.