https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68052
--- Comment #3 from Olivier Blin <gcc at blino dot org> --- Quoting Martin Sebor's answer from the gcc-help mailing list: https://gcc.gnu.org/ml/gcc-help/2015-10/msg00128.html > I'm inclined to say it's a bug. I recommend opening it in Bugzilla. > The only way I was able to work around it is by changing MY_PRINTF > from a function-like macro to an object macro like so: > > #define MY_PRINTF printf > > The problem isn't specific to -Wformat but can be reproduced with > other warnings as well. For example, replacing the contents of > the header in the test case with this: > > #pragma GCC system_header > > static inline void __attribute__ ((deprecated)) foobar (void) { } > > #define foo foobar > #define bar() foobar() > > and the body of main with > > foo (); > bar (); > > emits a warning for each of foo() and bar() in C but just one, > for foo(), in C++. > > While stepping through the code that checks to see whether or not > a diagnostic should be issued (diagnostic_issue_diagnostic) I see > that the difference in the bar() case is in the return value of > the linemap_macro_expansion_map_p() function which is documented > to > > Return TRUE if MAP encodes locations coming from a macro > replacement-list at macro expansion point. > > and implemented by testing the location MAP's REASON member for > equality to the LC_ENTER_MACRO constant. In C, the REASON member > is set to LC_LEAVE while in C++ to LC_ENTER_MACRO. In C, the > call to bar is then treated as an ordinary token whose location > (i.e., bar's invocation) determines whether or not to issue the > diagnostic. In C++ the reference to bar is recognized as a macro > expansion and the function proceeds to find the token it expands > to and use that to determine whether or not to diagnose it. And > since the token bar() expands to is defined in a system header, > C++ doesn't issue the warning. > > In the case of foo(), the REASON is LC_LEAVE in both front-ends > and so they both diagnose it. > > Martin