Bug 53391 - Slightly misleading warning on printf format mismatch
Summary: Slightly misleading warning on printf format mismatch
Status: UNCONFIRMED
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 4.7.0
: P3 minor
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on:
Blocks:
 
Reported: 2012-05-18 00:01 UTC by Keith Thompson
Modified: 2023-10-12 00:43 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Keith Thompson 2012-05-18 00:01:22 UTC
Given the following program (c.c):

#include <stdio.h>
int main(void) {
    typedef long my_long;
    my_long x = 42;
    printf("x = %d\n", (long)x);
    return 0;
}

"gcc -c c.c" produces the following warning:

c.c: In function ‘main’:
c.c:5:5: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘my_long’ [-Wformat]

The argument is actually of type long, not my_long; the warning should say "..., but argument 2 has type ‘long’".

Now because of the way typedefs work, long and my_long are really different names for the same type. gcc is obviously trying to be clever about which name makes for a clearer warning message. In this case, since x is explicitly converted to long, referring to "long" would be less confusing. *Some* warning is certainly appropriate, since "%d" requires an int argument.

(Speculation: gcc sees that the cast is a no-op, so it ignores it, which is fine except that it results in this misleading warning message.)

Ubuntu x86 12.04
gcc (Ubuntu/Linaro 4.7.0-7ubuntu3) 4.7.0
Comment 1 Jakub Jelinek 2012-05-18 08:31:59 UTC
This is not about trying to be clever, the useless conversion is long gone before the warning is emitted.
Comment 2 Keith Thompson 2012-05-18 18:26:31 UTC
The cleverness I was referring to was having diagnostics refer to an appropriate typedef rather than to the original type (e.g., "size_t" rather than "unsigned int").  I find this clever in a *good* way.

The conversion is a no-op if my_long happens to be the same type as long, as it is in this example -- but it's very useful from the programmer's point of view if my_long (or something with a more meaningful name) *could* be either long or int.

I suppose solving this would require saving some information about the cast so that the name of the type of the expression ("my_long" rather than "long") can be referred to in diagnostic messages.

I should note that this is not production code.  The original program was intended to use "%ld" and convert the argument to long; I ran into the misleading warning due to a logic error.