[Bug c/107100] -fanalyzer false positive about leak in function with attribute((malloc)) obtained from another function with attribute((malloc(free,1)))
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107100 --- Comment #1 from Eric Blake --- Might be a dup of bug#101648
[Bug c/107100] New: -fanalyzer false positive about leak in function with attribute((malloc)) obtained from another function with attribute((malloc(free,1)))
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107100 Bug ID: 107100 Summary: -fanalyzer false positive about leak in function with attribute((malloc)) obtained from another function with attribute((malloc(free,1))) Product: gcc Version: 12.2.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: eblake at redhat dot com Target Milestone: --- I'm at a loss for why disabling -O2 or removing __attribute__((malloc(free,1))) from function f silences a false-positive warning about a memory leak in function g with __attribute((malloc)) specifically documenting that g() wants to return a just-allocated pointer: $ cat foo.c #include #include char * __attribute__((malloc)) #ifndef HACK __attribute__((malloc(free,1))) #endif f (const char *i) { return strdup (i); } char * __attribute__((malloc)) __attribute__((malloc(free,1))) bar (void) { char *x = f ("test"); return x; } $ gcc -O2 -Wsuggest-attribute=malloc -fanalyzer -o foo.o -c foo.c $ gcc -DHACK -Wsuggest-attribute=malloc -fanalyzer -o foo.o -c foo.c $ gcc -Wsuggest-attribute=malloc -fanalyzer -o foo.o -c foo.c foo.c: In function ‘f’: foo.c:11:10: warning: leak of ‘x’ [CWE-401] [-Wanalyzer-malloc-leak] 11 | return strdup (i); | ^~ ‘bar’: events 1-3 | | 17 | bar (void) | | ^~~ | | | | | (1) entry to ‘bar’ | 18 | { | 19 | char *x = f ("test"); | | ~~ | | | | | (2) allocated here | | (3) calling ‘f’ from ‘bar’ | +--> ‘f’: events 4-5 | |9 | f (const char *i) | | ^ | | | | | (4) entry to ‘f’ | 10 | { | 11 | return strdup (i); | | ~~ | | | | | (5) ‘x’ leaks here; was allocated at (2) |
[Bug c/91688] New: -Woverride-init could use an intermediate mode of operation
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91688 Bug ID: 91688 Summary: -Woverride-init could use an intermediate mode of operation Product: gcc Version: 9.2.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: eblake at redhat dot com Target Milestone: --- Right now, -Woverride-init is so strong that it interferes with the use of gcc's extension of ranged-array initializer syntax as a common way to pre-initialize an array to a specific non-zero default value then override specific members in the array to a different value. Thus, it is not part of -Wall (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=24010#c4). However, this warning is so strong that the qemu project is unable to use -Woverride-init (it would fail to compile due to intentional reinitialization overrides of ranged defaults), but thus failed to diagnose a bug (a partial initialization caused zero-initialization of an unmentioned member, overriding an earlier explicit mention of that member: https://lists.gnu.org/archive/html/qemu-devel/2019-09/msg01143.html), at least without using pragmas to temporarily silence the warning. I am wondering if it would be possible to split this warning into two categories: -Woverride-init=1 (preferably hoisted into -Wall) which warns about obvious inadvertent overrides, and -Woverride-init=2 (only part of -Wextra, if at all) that warns about all overrides, where the difference depends on whether the second initializer occurs on a subobject that is larger in size than the first initializer's subobject. For some demonstrations of what I mean (and intentionally using -Wno-missing-braces): $ cat foo.c #include struct A { int i; int j; }; struct B { struct A one; struct A two; struct A three; int four[2]; }; void dump (struct B *b) { printf ("one=[%d,%d],two=[%d,%d],three=[%d,%d],four=[%d,%d]\n", b->one.i, b->one.j, b->two.i, b->two.j, b->three.i, b->three.j, b->four[0], b->four[1]); } int main(void) { struct B b1 = { .one.i = 1, .two.j = 2, 3, .four[1] = 9, .one = { 5, 6 }, .two = { 7 }, .three = { .j = 8 }, .four[0 ... 1] = 4, }; struct B b2 = { .one = { 4, 5 }, .two = { 6 }, .three = { .j = 7 }, .four[0 ... 1] = 4, .one.i = 1, .two.j = 2, 3, .four[1] = 9, }; dump (&b1); dump (&b2); return 0; } $ gcc -Wall -Wextra -Wno-missing-braces -o foo foo.c foo.c: In function ‘main’: foo.c:28:11: warning: initialized field overwritten [-Woverride-init] 28 |.one = { 5, 6 }, | ^ foo.c:28:11: note: (near initialization for ‘b1.one’) foo.c:29:11: warning: initialized field overwritten [-Woverride-init] 29 |.two = { 7 }, | ^ foo.c:29:11: note: (near initialization for ‘b1.two’) foo.c:30:13: warning: initialized field overwritten [-Woverride-init] 30 |.three = { .j = 8 }, | ^ foo.c:30:13: note: (near initialization for ‘b1.three’) foo.c:31:21: warning: initialized field overwritten [-Woverride-init] 31 |.four[0 ... 1] = 4, | ^ foo.c:31:21: note: (near initialization for ‘b1.four[1]’) foo.c:38:13: warning: initialized field overwritten [-Woverride-init] 38 |.one.i = 1, | ^ foo.c:38:13: note: (near initialization for ‘b2.one.i’) foo.c:41:15: warning: initialized field overwritten [-Woverride-init] 41 |.four[1] = 9, | ^ foo.c:41:15: note: (near initialization for ‘b2.four[1]’) The four warnings for b1 all make sense at -Woverride-init=1: they are clearly inadvertent, in that the second half of initializers all touch a larger subset of the overall b2 object than the first half (providing both members for .one overrides the earlier specific setting of .one.i; providing a partial initializer for .two implies a zero-initialization override of the earlier .two.j; providing a partial initializer for .three implies a zero-initialization override of the earlier (non-designated) .three.i, and doing a ranged initializer over .four[0 ... 1] overrides the earlier specific initialization of .four[1].) However, while the first warning of b2 is reasonable (the explicit initialization of .one.i overrides the earlier explicit initialization of .one), this is a case of a more-specific override (.one.i is a smaller subset of b2 than .one), and the second one is the show-stopper that prevents the use of -Woverride-init in -Wall (it is intentional that a ranged initializer sets a non-zero default, and then later initializers of
[Bug c/89990] request warning: Use of out of bound compound initialised struct
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89990 --- Comment #1 from Eric Blake --- Other references to compound initializers going out of scope and causing problems: https://stackoverflow.com/questions/47691857/lifetime-of-a-compound-literal https://wiki.sei.cmu.edu/confluence/display/c/DCL21-C.+Understand+the+storage+of+compound+literals Having the compiler flag the programmer's use of undefined behavior, especially where the use-after-free SEEMS to work because an earlier version of the compiler deferred cleanup of the stack space until the function exited (even though it was entitled to do so as soon as the conditional's scope ended), would be handy.
[Bug c/88270] -Wformat-XXX option for flagging %m
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88270 --- Comment #5 from Eric Blake --- For what it's worth, POSIX requires syslog() to support %m, and this is the case even on BSD systems. So a new __attribute__((format(syslog, x, y))) archetype would be an easy way of at least notating functions where %m must be portable, even when flagging %m for printf.
[Bug c/88270] -Wformat-XXX option for flagging %m
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88270 --- Comment #3 from Eric Blake --- Confirmed that -Wpendantic flags %m: $ gcc -Wpedantic -Wformat foo.c -o foo foo.c: In function ‘main’: foo.c:3:10: warning: ISO C does not support the ‘%m’ gnu_printf format [-Wformat=] printf("%m %B\n"); ^ foo.c:3:13: warning: unknown conversion type character ‘B’ in format [-Wformat=] printf("%m %B\n"); ^ Although -Wpedantic is a rather heavy hammer compared to a fine-grained knob that can warn for just uses of %m (seeing as how we already have other knobs like -Wno-format-contains-nul -Wno-format-extra-args -Wformat-nonliteral -Wformat-overflow=N -Wformat-security -Wformat-signedness -Wformat-truncation=N). Then, as you say, if 'printf' starts flagging %m on BSD, we'd still need some way to specifically mark attributes on wrapper functions that accept more than the system print but less than the full gnu_printf. Maybe we could have multiple fine-grained attributes that each control one class of printf format extensions, which can then be combined as a set, where the existing printf, ms_printf, and gnu_printf are shorthands for specific members in that set? Then specific wrappers can hand-build the set matching what they actually support, rather than relying on the shorthands. Something like: Mark my own function as C89 + %m (but not C99 %hhd) __attribute__ (( format( (printf_c89, printf_m), 1, 0 ) )) Mark another function as supporting %1$'d which is POSIX extensions beyond C99 C: __attribute__ (( format( (printf_c89, printf_c99, printf_posix), 1, 0 ) )) Use the system printf: __attribute__ (( format( printf, 1, 0 ) )) which on glibc would probably be shorthand for: __attribute__ (( format( (printf_c89, printf_c99, printf_posix, printf_m, printf_llg, printf_q, printf_Z), 1, 0 ) )) and on Windows would probably be shorthand for: __attribute__ (( format( (printf_c89, printf_I64), 1, 0 ) )) I don't know what syntax would be best to specify an attribute as a set of fine-grained format pieces that act together as a whole; so much as just tossing out the idea of having finer-grained attributes which can be applied as a set where the existing high-level attributes are then broken into their fine-grained components.
[Bug c/88270] -Wformat-XXX option for flagging %m
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88270 --- Comment #1 from Eric Blake --- Note that gcc -Wformat DOES flag things like printf("%B"), %m is the only special-case where it is not flagged even on systems where it does not work, and where we'd want fine-tuned control over whether a particular function should flag it. $ cat foo.c #include int main (void) { printf("%m %B\n"); return 0; } $ gcc -Wformat foo.c -o foo foo.c: In function ‘main’: foo.c:3:13: warning: unknown conversion type character ‘B’ in format [-Wformat=] printf("%m %B\n"); ^ $ ./foo # on Linux Success %B $ ./foo # on BSD m B
[Bug c/88270] New: -Wformat-XXX option for flagging %m
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88270 Bug ID: 88270 Summary: -Wformat-XXX option for flagging %m Product: gcc Version: 8.2.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: eblake at redhat dot com Target Milestone: --- I was working porting a project originally written for Linux over to BSD systems, and had to fix code that called printf("%m") to spell out longhand printf("%s", strerror(errno)). Sadly, I couldn't find a -Wformat-FOO flag that would have let the compiler spot these instances on my behalf. At the same time, I found it a lot easier to write my own wrapper function [1] that expanded %m in-place before passing things on to the real printf-family functions (easy, since %m doesn't require parsing the rest of the format string or rewriting the va_list argument), rather than manually expand all existing %m in the code base, since most format strings in the code base already went through a common wrapper function. Of course, my wrapper is given __attribute__((printf...)), so that I can preserve compiler checking of -Wformat. But in that case, while I'd want -Wformat-FOO to warn about %m in native printf, I do NOT want it warning about %m passed to my wrapper. So the attribute system may also need tweaking to make this sort of compiler-aided portability flagging easier to implement. [1] https://github.com/libguestfs/nbdkit/commit/1c230358462c3495330
[Bug c/80060] New: RFE: -Wformat knob to ignore same-width incorrect types
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80060 Bug ID: 80060 Summary: RFE: -Wformat knob to ignore same-width incorrect types Product: gcc Version: 6.3.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: eblake at redhat dot com Target Milestone: --- When porting from one machine to another, especially when porting from 32-bit to 64-bit software, getting warnings about mismatches such as printf("%ld", (uint32_t)1) is awesome. But once something has been ported to a given platform, if two types have the same size but different rank, getting warnings about something that is not portable to other machines but which works in practice on the given machine is very noisy. And sometimes, the noise is unavoidable - there are many situations in which different implementations can pick a type that is consistent for their platform, but uses a different rank than what another platform chose - not all the world uses the types, but has a variety of other typedefs in place. Here's some examples: on 64-bit Linux, the header declares a struct with members specified with a typedef __u64: struct uffd_msg msg; struct uffd_msg { .. union { struct { __u64 flags; __u64 address; } pagefault; .. } arg; } Printing one of these values is obvious - the typedef name tells you it should be an unsigned 64-bit quantity, so let's try printf("%"PRIx64, msg.arg.pagefault.flags). Oops, on 64-bit Linux, that fails under -Wformat, because "%ld" is incompatible with 'unsigned long long'. But since the kernel headers typedef'd __u64 without any counterpart to something like PRIx64, there is no sane way to print a __u64 without writing an extra cast at every caller, which is prone to introduce more bugs than the warnings it silences: printf("%"PRIx64, (uint64_t)msg.arg.pagefault.flags). Another case: on 32-bit mingw, the declaration for ntohl() says that it returns a 'u_long', which is a 32-bit type. But POSIX says that ntohl() returns 'uint32_t'. So the obvious printf("%"PRIx32, ntohl(1)) fails to compile on mingw, because 'u_long' (which is 'unsigned long') is incompatible with 'uint32_t' (which is 'unsigned int') on that platform (arguably a bug in mingw's headers, but such is life). Again, the mismatch warning can be avoided with a cast, but that does not scale well: printf("%"PRIx32, (uint32_t)ntohl(1)) gcc recently introduced -Wformat-signedness (and it's counterpart -Wno-format-signedness) to let developers fine-tune how MUCH verbosity they want during warning checks. Are you porting code to a platform where 'int' and 'unsigned int' have different widths? (Some weirdnix hardware might exist like that, and C seems to make it possible, even though I can't name such a system) - then turn the warning on. But if you really DON'T care about "%d" used with 'unsigned', or "%x" used with 'int' (because in the end, the 32-bit value passed through varargs gets reinterpreted into the correct 32-bit value that gets printed, regardless of intermediate sign-incorrectness), then turn it off. So I'd love to have a new knob, maybe named -Wformat-same-rank, which controls whether gcc warns about using the wrong format specifier EVEN THOUGH the type passed to varargs has the same rank and therefore will print accurately; and projects can then use -Wno-format-same-rank to silence __u64/uint64_t or u_long/uint32_t differences while still getting warnings about real bugs of 32-bit vs. 64-bit mismatches.
[Bug c/69602] [6/7 Regression] over-ambitious logical-op warning on EAGAIN vs EWOULDBLOCK
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69602 --- Comment #15 from Eric Blake --- (In reply to Martin Sebor from comment #14) > I would suggest to keep the warning simple and avoid overdesigning it with > workarounds for this case. The solution in comment #12 (copied below) seems > like a good approach for avoiding the duplication and the warning. It's > already commonly used to deal with non-standard implementation-specific > macros that portable programs cannot otherwise rely on. > > 1149if ( cchRead < 0 > 1150&& ( errno == EAGAIN > 1151#if EAGAIN != EWOULDBLOCK > 1152|| errno == EWOULDBLOCK > 1153#endif > 1154)) Yuck. Mid-expression #ifdefs are awful - I much prefer it when #ifdefs can be limited to a per-statement or per-function scope. You're seriously proposing forcing software to uglify their code with mid-expression warnings to shut up compiler warnings that only occur on platforms where the two values are synonyms, and which can't even be portably seen as necessary when testing as platforms where the two values are distinct?
[Bug c/69602] New: over-ambitious logical-op warning on EAGAIN vs EWOULDBLOCK
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69602 Bug ID: 69602 Summary: over-ambitious logical-op warning on EAGAIN vs EWOULDBLOCK Product: gcc Version: 6.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: eblake at redhat dot com Target Milestone: --- POSIX says that EAGAIN and EWOULDBLOCK may be identical, but also that they may be distinct. Therefore, well-written portable code MUST check for both values in some circumstances. However, as shown by the sample code below, gcc 6.0's new warning is over-ambitious, and is likely to _cause_ rather than cure user bugs, when uninformed users unaware that Linux has the two errno values equal dumb down the code to silence the warning, but in the process break their code on other platforms where it is important to check for both values. $ cat foo.c #include int main(void) { if (errno == EAGAIN || errno == EWOULDBLOCK) return 1; return 0; } $ gcc -o foo foo.c -Werror=logical-op foo.c: In function 'main': foo.c:3:23: error: logical 'or' of equal expressions [-Werror=logical-op] if (errno == EAGAIN || errno == EWOULDBLOCK) ^~ cc1: some warnings being treated as errors $ gcc --version | head -n1 gcc (GCC) 6.0.0 20160129 (Red Hat 6.0.0-0.7)
[Bug c/65446] Improve -Wformat-signedness
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65446 --- Comment #4 from Eric Blake --- Arguably, "%u" with short should warn, while "%hu" with short should not. On the other hand, if I use "%hu" with int, it is unclear to me whether I should get a warning (the fact that I'm using %h to intentionally truncate the value before it is printed, even though %hu and %hd print different values, makes it hard to discern whether I have a mismatch). But this does mean that whatever changes are made to -Wformat-signedness, it should take into account the use of %h range-limiting vs. pre-integer-promotion types.
[Bug c/65446] Improve -Wformat-signedness
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65446 --- Comment #3 from Eric Blake --- see also bug 66249 where the implementation-defined signedness of enums comes into play, and where I argue that neither %d nor %u should warn when an enum type is passed through varargs where the range of the enum is identical through either format representation.
[Bug c/66249] New: -Wformat-signedness should not warn on enums
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66249 Bug ID: 66249 Summary: -Wformat-signedness should not warn on enums Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: eblake at redhat dot com Target Milestone: --- The standard is clear that enums have implementation-defined signedness (C99 6.7.2.2P4 "Each enumerated type shall be compatible with char, a signed integer type, or an unsigned integer type. The choice of type is implementation-defined, but shall be capable of representing the values of all the members of the enumeration."). However, while there is a way to force gcc to use a smaller or larger type (-fshort-enums), I don't know how to force gcc to use a signed or unsigned type for enums whose members could fit in either. As such, since I cannot guarantee that compiling on some other platform will want to use a different signedness, I'm forced to add casts any time I want to print an enum, when using the new -Wformat-signedness (implied by -Wformat=2). Here's a demonstration of what I mean (testing on Fedora rawhide): $ gcc --version | head -n1 gcc (GCC) 5.1.1 20150422 (Red Hat 5.1.1-1) $ cat foo.c #include int main(void) { int i = 0; unsigned u = 0; enum e_signed { as, bs = -1 } es = as; enum e_unsigned { au, bu = 0x } eu = au; enum e_implementation { ai } ei = ai; printf ("%u %d %u %d %u %d %u %d\n", i, u, es, es, eu, eu, ei, ei); return 0; } $ gcc -Wformat -Wformat-signedness foo.c -o foo foo.c: In function ‘main’: foo.c:8:11: warning: format ‘%u’ expects argument of type ‘unsigned int’, but argument 2 has type ‘int’ [-Wformat=] printf ("%u %d %u %d %u %d %u %d\n", i, u, es, es, eu, eu, ei, ei); ^ foo.c:8:11: warning: format ‘%d’ expects argument of type ‘int’, but argument 3 has type ‘unsigned int’ [-Wformat=] foo.c:8:11: warning: format ‘%u’ expects argument of type ‘unsigned int’, but argument 4 has type ‘int’ [-Wformat=] foo.c:8:11: warning: format ‘%d’ expects argument of type ‘int’, but argument 7 has type ‘unsigned int’ [-Wformat=] foo.c:8:11: warning: format ‘%d’ expects argument of type ‘int’, but argument 9 has type ‘unsigned int’ [-Wformat=] [dummy@rawhide64 ~]$ The warning for arguments 2, 3, 4, and 7 are expected (2 and 3 to show the normal usage of the warning, 4/5 to show that I can force an enum to be signed by including negative members, 6/7 to show that I can force an enum to be unsigned by including members larger than INT_MAX); and the lack of warning for arguments 5 and 6 is good. I can squelch the warning for the first four problematic arguments by either using the correct %d vs. %u counterpart, or by changing the signedness of the variable that I'm printing. However, argument 8/9 is problematic. From the compiler warning on argument 9, it looks like gcc defaults to unsigned, at least on my platform. But I _cannot_ know whether the compiler will pick a signed or unsigned representation for the enum on other platforms (since all members would fit in either type, and since the platform ABI may demand a particular signedness), so I cannot know whether %u or %d would trigger a warning because I picked the wrong type. My only recourse is to add a cast (such as "%d",(int)ei); but that is ugly. And look what happens when I add -fshort-enums to the mix: $ gcc -fshort-enums -Wformat -Wformat-signedness foo.c -o foo foo.c: In function ‘main’: foo.c:8:11: warning: format ‘%u’ expects argument of type ‘unsigned int’, but argument 2 has type ‘int’ [-Wformat=] printf ("%u %d %u %d %u %d %u %d\n", i, u, es, es, eu, eu, ei, ei); ^ foo.c:8:11: warning: format ‘%d’ expects argument of type ‘int’, but argument 3 has type ‘unsigned int’ [-Wformat=] foo.c:8:11: warning: format ‘%u’ expects argument of type ‘unsigned int’, but argument 4 has type ‘int’ [-Wformat=] foo.c:8:11: warning: format ‘%d’ expects argument of type ‘int’, but argument 7 has type ‘unsigned int’ [-Wformat=] [dummy@rawhide64 ~]$ Here, arguments 4/5 are still signed, arguments 6/7 are still unsigned; but arguments 8/9 are now a type compatible with 'char', and promotes to 'int' (whether the enum's underlying type is signed or unsigned). Oddly enough, the compiler did not warn for EITHER 8 or 9, but by the technical argument, "%u" should have warned for argument 8. And consider what happens from a promotion standpoint: if gcc picked 'char' (rather than 'signed char' or unsigned char') as the underlying type when -fshort-enums is in effect, and my enum contained a value in the range [128-255], then I am now dependent on whether 'char' is signed or unsigned for whether %d will print 128 or -128 (and %u would print 128 o
[Bug c/60194] -Wformat should also warn when using %d (instead of %u) for unsigned arguments
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60194 Eric Blake changed: What|Removed |Added CC||eblake at redhat dot com --- Comment #5 from Eric Blake --- See also bug 65446 for a possible hole in the -Wformat-signedness implementation, when dealing with integer promotion.
[Bug c/65446] Improve -Wformat-signedness
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65446 Eric Blake changed: What|Removed |Added CC||eblake at redhat dot com --- Comment #2 from Eric Blake --- 'unsigned short' promotes to 'int', not 'unsigned int', when passed through var-args. The warning is technically correct, but annoying, since all values of 'unsigned short' are representable in both 'int' and in 'unsigned int', therefore %d vs. %u won't ever have to deal with a negative value. "%u" with signed 'short' should indeed warn, because that is a case where promotion to 'int' differs from printing unsigned values. "%x" with 1 should indeed warn, because that is passing 'int'. Use "%x" with 1U if you want to avoid the warning.
[Bug c/58488] -Wuninitialized is useless for a variable whose address is later taken
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58488 --- Comment #3 from Eric Blake --- Since the engine is able to warn at -O0 when I _don't_ take the address, I don't see why the warning is lost by the mere action of taking the address.
[Bug c/58488] New: -Wuninitialized is useless for a variable whose address is later taken
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58488 Bug ID: 58488 Summary: -Wuninitialized is useless for a variable whose address is later taken Product: gcc Version: 4.8.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: eblake at redhat dot com Here's a simple example of where -Wuninitialized is rather useless at default optimization: $ cat foo.c #include int main(void) { char *oops; free(oops); void *other = #ifdef RELIABLE NULL #else &oops #endif ; return !other; } $ gcc -Werror -Wall -Wuninitialized -o foo -c foo.c $ gcc -Werror -Wall -Wuninitialized -o foo -c foo.c -DRELIABLE foo.c: In function ‘main’: foo.c:5:9: error: ‘oops’ is used uninitialized in this function [-Werror=uninitialized] free(oops); ^ cc1: all warnings being treated as errors $ gcc -Werror -Wall -Wuninitialized -o foo -c foo.c -O2 foo.c: In function ‘main’: foo.c:5:9: error: ‘oops’ is used uninitialized in this function [-Werror=uninitialized] free(oops); ^ cc1: all warnings being treated as errors $ gcc -Werror -Wall -Wuninitialized -o foo -c foo.c -DRELIABLE -O2 foo.c: In function ‘main’: foo.c:5:9: error: ‘oops’ is used uninitialized in this function [-Werror=uninitialized] free(oops); ^ cc1: all warnings being treated as errors I understand that -O2 enables better uninitialization checks, but I find it quite awkward that even without -O2, the mere taking an address of a variable hides it from the uninit checker. My end goal is to have a macro that does a one-shot evaluation of its argument: #define FREE(x) { typeof(x) *_x = &(x); free(*_x); *_x = NULL; } for safety, but that macro kills -Wuninit checking by virtue of the fact that it takes the address of the pointer. Even if I limit myself to a macro that evaluates its argument more than once (and forcing me to audit code to avoid FREE(side-effects) - if only there were a way to make the compiler automatically barf if it encounters side effects in a macro argument), I am unable to come up with a way to get the uninit checking that gcc provides regardless of optimization without also having the safety of ensuring the pointer isn't abused after the fact.
[Bug c/57475] "incompatible pointer type" message is not helpful enough
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57475 --- Comment #3 from Eric Blake --- (In reply to Manuel López-Ibáñez from comment #1) > We could detect the special case where the spelling is the same and report > where each type is declared. Be aware that "spelled the same" needs to disregard cv-qualification; the original message prompted this report was comparing 'const struct msghdr *' to 'struct msghdr *'; and I was left scratching my head why automatic 'const' wasn't being added.