Consider the following code: $ cat test.c #include <stdarg.h> void foo(va_list ap) { va_arg(ap, char); va_arg(ap, unsigned char); } $ cc1 -std=c99 test.c In file included from test.c:1:0: test.c: In function 'foo': test.c:5:16: warning: 'char' is promoted to 'int' when passed through '...' va_arg(ap, char); ^ test.c:5:16: note: (so you should pass 'int' not 'char' to 'va_arg') test.c:5:16: note: if this code is reached, the program will abort test.c:6:16: warning: 'unsigned char' is promoted to 'int' when passed through '...' va_arg(ap, unsigned char); ^ test.c:6:16: note: if this code is reached, the program will abort However: $ cat test2.c #include <stdbool.h> #include <stdarg.h> void foo(va_list ap) { va_arg(ap, bool); } $ cc1 -std=c99 -Wall -Wextra test2.c va_arg(ap, bool) is expanded into __builtin_trap, but no warning is issued.
I wonder if this is yet another issue with macros from system headers (bool being defined in a system header to expand to _Bool) ... maybe we need a systematic review of diagnostic locations in the C-family front ends to identify such cases where the diagnostic relates to a property of the use of the (type / expression) macro from a system header, not to a property of that (type / expression) itself, and so system-header suppression should only apply if the use itself is in a system header.
(In reply to joseph@codesourcery.com from comment #1) > I wonder if this is yet another issue with macros from system headers > (bool being defined in a system header to expand to _Bool) ... Looks like it is. In gimplify.c:gimplify_va_arg_expr we have: /* Unfortunately, this is merely undefined, rather than a constraint violation, so we cannot make this an error. If this call is never executed, the program is still strictly conforming. */ warned = warning_at (loc, 0, "%qT is promoted to %qT when passed through %<...%>", type, promoted_type); And warning_at returns false. Also, for #include <stdarg.h> #define BOOL _Bool void foo(va_list ap) { va_arg(ap, BOOL); } GCC outputs: In file included from test2.c:1:0: test2.c: In function 'foo': test2.c:2:14: warning: '_Bool' is promoted to 'int' when passed through '...' #define BOOL _Bool ^ test2.c:5:16: note: in expansion of macro 'BOOL' va_arg(ap, BOOL); ^ test2.c:2:14: note: (so you should pass 'int' not '_Bool' to 'va_arg') #define BOOL _Bool ^ test2.c:5:16: note: in expansion of macro 'BOOL' va_arg(ap, BOOL); ^ test2.c:2:14: note: if this code is reached, the program will abort #define BOOL _Bool ^ test2.c:5:16: note: in expansion of macro 'BOOL' va_arg(ap, BOOL); IMHO, it would be more correct to output something like this: test2.c: In function 'foo': test2.c:5:16: warning: '_Bool' is promoted to 'int' when passed through '...' va_arg(ap, BOOL); ^ test2.c:2:14: note: expanded from macro 'BOOL' #define BOOL _Bool ^
Confirmed.
Came up again in https://www.linux.org.ru/forum/development/12376493 The simplified test that which pre problem: typedef __builtin_va_list __gnuc_va_list; typedef __gnuc_va_list va_list; void func(va_list arg) { _Bool value = __builtin_va_arg( arg //# 5 "a.c" 3 4 , _Bool); (void)value; } $ gcc-5.3.0 -c -O2 -Wall -Wextra a.c a.c: In function 'func': a.c:8:21: warning: '_Bool' is promoted to 'int' when passed through '...' , _Bool); ^ a.c:8:21: note: (so you should pass 'int' not '_Bool' to 'va_arg') a.c:8:21: note: if this code is reached, the program will abort If we uncomment line pragmas is stops working: typedef __builtin_va_list __gnuc_va_list; typedef __gnuc_va_list va_list; void func(va_list arg) { _Bool value = __builtin_va_arg( arg # 5 "a.c" 3 4 , _Bool); (void)value; } $ gcc-5.3.0 -c -O2 -Wall -Wextra a.c No warning.
Sorry about that. I'll look into that this week.
In cases where we want to emit diagnostics about a token that is located in a macro that is itself defined in system header, for example, for the NULL macro, using the original location of the token will suppress the diagnostic (unless -Wsystem-header). Instead, one should use: source_location loc = expansion_point_location_if_in_system_header (original_location);
Yeah, I know; I've already fixed the NULL case some time ago (though I'm not sure if all the appropriate spots are fixed).
I have a fix. But re Comment 4, I think GCC does what's desirable: we shouldn't warn if the bogus code is in a system header. For that we have -Wsystem-headers. The testcase in Description is a bug that is fixed with my patch.
Author: mpolacek Date: Wed Mar 2 07:24:19 2016 New Revision: 233891 URL: https://gcc.gnu.org/viewcvs?rev=233891&root=gcc&view=rev Log: PR c/67854 * gimplify.c (gimplify_va_arg_expr): Use expanded location for the "is promoted to" warning. * gcc.dg/pr67854.c: New test. Added: trunk/gcc/testsuite/gcc.dg/pr67854.c Modified: trunk/gcc/ChangeLog trunk/gcc/gimplify.c trunk/gcc/testsuite/ChangeLog
Fixed.