[Bug c/69602] New: over-ambitious logical-op warning on EAGAIN vs EWOULDBLOCK

2016-02-01 Thread eblake at redhat dot com
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/69602] [6/7 Regression] over-ambitious logical-op warning on EAGAIN vs EWOULDBLOCK

2017-01-24 Thread eblake at redhat dot com
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/80060] New: RFE: -Wformat knob to ignore same-width incorrect types

2017-03-15 Thread eblake at redhat dot com
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/91688] New: -Woverride-init could use an intermediate mode of operation

2019-09-06 Thread eblake at redhat dot com
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

2019-04-05 Thread eblake at redhat dot com
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] New: -Wformat-XXX option for flagging %m

2018-11-29 Thread eblake at redhat dot com
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/88270] -Wformat-XXX option for flagging %m

2018-11-29 Thread eblake at redhat dot com
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] -Wformat-XXX option for flagging %m

2018-11-29 Thread eblake at redhat dot com
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

2018-11-29 Thread eblake at redhat dot com
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/65446] Improve -Wformat-signedness

2015-05-21 Thread eblake at redhat dot com
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/60194] -Wformat should also warn when using %d (instead of %u) for unsigned arguments

2015-05-21 Thread eblake at redhat dot com
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/66249] New: -Wformat-signedness should not warn on enums

2015-05-21 Thread eblake at redhat dot com
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/65446] Improve -Wformat-signedness

2015-05-21 Thread eblake at redhat dot com
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/65446] Improve -Wformat-signedness

2015-05-21 Thread eblake at redhat dot com
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/57475] "incompatible pointer type" message is not helpful enough

2013-05-31 Thread eblake at redhat dot com
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.

[Bug c/58488] New: -Wuninitialized is useless for a variable whose address is later taken

2013-09-20 Thread eblake at redhat dot com
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/58488] -Wuninitialized is useless for a variable whose address is later taken

2013-09-23 Thread eblake at redhat dot com
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/107100] New: -fanalyzer false positive about leak in function with attribute((malloc)) obtained from another function with attribute((malloc(free,1)))

2022-09-30 Thread eblake at redhat dot com via Gcc-bugs
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/107100] -fanalyzer false positive about leak in function with attribute((malloc)) obtained from another function with attribute((malloc(free,1)))

2022-09-30 Thread eblake at redhat dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107100

--- Comment #1 from Eric Blake  ---
Might be a dup of bug#101648