Bug 67854 - Missing diagnostic for passing bool to va_arg
Summary: Missing diagnostic for passing bool to va_arg
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 6.0
: P3 normal
Target Milestone: ---
Assignee: Marek Polacek
URL:
Keywords: diagnostic
Depends on:
Blocks:
 
Reported: 2015-10-05 17:15 UTC by Mikhail Maltsev
Modified: 2016-03-02 07:30 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2015-10-20 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Mikhail Maltsev 2015-10-05 17:15:04 UTC
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.
Comment 1 jsm-csl@polyomino.org.uk 2015-10-05 17:22:29 UTC
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.
Comment 2 Mikhail Maltsev 2015-10-05 17:47:44 UTC
(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
              ^
Comment 3 Marek Polacek 2015-10-20 08:58:42 UTC
Confirmed.
Comment 4 Sergei Trofimovich 2016-02-23 09:22:10 UTC
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.
Comment 5 Marek Polacek 2016-02-23 09:41:18 UTC
Sorry about that.  I'll look into that this week.
Comment 6 Manuel López-Ibáñez 2016-02-23 09:58:49 UTC
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);
Comment 7 Marek Polacek 2016-02-23 10:04:12 UTC
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).
Comment 8 Marek Polacek 2016-02-24 15:11:43 UTC
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.
Comment 9 Marek Polacek 2016-03-02 07:24:51 UTC
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
Comment 10 Marek Polacek 2016-03-02 07:30:15 UTC
Fixed.