[Bug analyzer/109335] -Wanalyzer-malloc-leak false positives and false negatives

2024-05-15 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109335

--- Comment #4 from Alejandro Colomar  ---
Here's a smaller reproducer:

$ cat pass.c 
#include 

void my_free(char *p);
[[gnu::malloc(my_free)]] char *my_malloc(void);

int main(void)
{
char  *p;
p = my_malloc();
my_free(p);  // 2 false positives.
}

char *my_malloc(void)
{
return malloc(42);
}

void my_free(char *p)
{
free(p);
}


$ gcc-14 -Wall -Wextra pass.c -fanalyzer -O3
pass.c: In function ‘main’:
pass.c:10:9: warning: ‘p’ should have been deallocated with ‘free’ but was
deallocated with ‘my_free’ [CWE-762] [-Wanalyzer-mismatching-deallocation]
   10 | my_free(p);  // 2 false positives.
  | ^~
  ‘main’: events 1-2
|
|6 | int main(void)
|  | ^~~~
|  | |
|  | (1) entry to ‘main’
|..
|9 | p = my_malloc();
|  | ~~~
|  | |
|  | (2) calling ‘my_malloc’ from ‘main’
|
+--> ‘my_malloc’: events 3-4
   |
   |   13 | char *my_malloc(void)
   |  |   ^
   |  |   |
   |  |   (3) entry to ‘my_malloc’
   |   14 | {
   |   15 | return malloc(42);
   |  |~~
   |  ||
   |  |(4) allocated here (expects deallocation
with ‘free’)
   |
<--+
|
  ‘main’: events 5-6
|
|9 | p = my_malloc();
|  | ^~~
|  | |
|  | (5) returning to ‘main’ from ‘my_malloc’
|   10 | my_free(p);  // 2 false positives.
|  | ~~
|  | |
|  | (6) deallocated with ‘my_free’ here; allocation at (4)
expects deallocation with ‘free’
|
pass.c: In function ‘my_malloc’:
pass.c:15:16: warning: leak of ‘p’ [CWE-401] [-Wanalyzer-malloc-leak]
   15 | return malloc(42);
  |^~
  ‘main’: events 1-3
|
|6 | int main(void)
|  | ^~~~
|  | |
|  | (1) entry to ‘main’
|..
|9 | p = my_malloc();
|  | ~~~
|  | |
|  | (2) allocated here
|  | (3) calling ‘my_malloc’ from ‘main’
|
+--> ‘my_malloc’: events 4-5
   |
   |   13 | char *my_malloc(void)
   |  |   ^
   |  |   |
   |  |   (4) entry to ‘my_malloc’
   |   14 | {
   |   15 | return malloc(42);
   |  |~~
   |  ||
   |  |(5) ‘p’ leaks here; was allocated at (2)
   |

[Bug analyzer/109335] -Wanalyzer-malloc-leak false positives and false negatives

2024-05-15 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109335

--- Comment #3 from Alejandro Colomar  ---
Oops, no, that's a different story.  The analyzer is thinking it leaks
somewhere where it doesn't seem to leak.

The false positive still reproduces with

gcc-14 (Debian 14-20240429-1) 14.0.1 20240429 (experimental) [gcc-14
r14-10144-g41d7a8ceaaa]

[Bug analyzer/109335] -Wanalyzer-malloc-leak false positives and false negatives

2024-05-15 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109335

--- Comment #2 from Alejandro Colomar  ---
This is probably because there's no way to mark a function as being a valid
deallocator (i.e., the converse of [[gnu::malloc()]]).

As a workaround, such deallocators could be defined (C99) inline, so that the
analyzer can see that they are internally calling the actual deallocator, but
that's hard when the deallocator is in a library, which might support C89, as
is probably the case in libbsd.

[Bug c/94746] -Wsizeof-pointer-div not triggered by system header macros

2024-05-15 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94746

Alejandro Colomar  changed:

   What|Removed |Added

 Resolution|--- |WONTFIX
 Status|UNCONFIRMED |RESOLVED

--- Comment #4 from Alejandro Colomar  ---
A static_assert(3) is indeed the right solution.  As Arseny said, this is by
design, so I'll close it as WONTFIX.

[Bug c/95024] want a way to turn off -Werror for a specific diagnostic but only emit an warning if it was turned on before hand

2024-05-15 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95024

--- Comment #4 from Alejandro Colomar  ---
Sorry, I didn't make it clear; I somehow forgot about it.

Here's the problem:

$ cat err.c 
int
main(void)
{
short s;
int   *p;

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wno-error=incompatible-pointer-types"
p = 
#pragma GCC diagnostic pop
}


$ gcc err.c 
err.c: In function ‘main’:
err.c:8:32: warning: unknown option after ‘#pragma GCC diagnostic’ kind
[-Wpragmas]
8 | #pragma GCC diagnostic ignored "-Wno-error=incompatible-pointer-types"
  |^~~
err.c:8:32: note: did you mean ‘-Wno-incompatible-pointer-types’?
err.c:9:11: warning: assignment to ‘int *’ from incompatible pointer type
‘short int *’ [-Wincompatible-pointer-types]
9 | p = 
  |   ^

[Bug analyzer/115089] -Wanalyzer-use-of-uninitialized-value false negative

2024-05-15 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115089

--- Comment #4 from Alejandro Colomar  ---
Thanks, David!  I'm happy that this might help improve the analyzer.  :-)

[Bug analyzer/115089] -Wanalyzer-use-of-uninitialized-value false negative

2024-05-14 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115089

--- Comment #2 from Alejandro Colomar  ---
I found that Clang's analyzer finds this bug, so I'm less concerned that GCC
can't find it.

Feel free to ignore it if it's too hard to fix.  ;)


$ clang-tidy ./bug.c 
Error while trying to load a compilation database:
Could not auto-detect compilation database for file "./bug.c"
No compilation database found in /home/alx/tmp/analyzer or any parent directory
fixed-compilation-database: Error while opening fixed database: No such file or
directory
json-compilation-database: Error while opening JSON database: No such file or
directory
Running without flags.
1 warning generated.
/home/alx/tmp/analyzer/bug.c:16:2: warning: Undefined or garbage value returned
to caller [clang-analyzer-core.uninitialized.UndefReturn]
return x;  // maybe uninitialized use
^  ~
/home/alx/tmp/analyzer/bug.c:13:2: note: 'x' declared without an initial value
int x;
^
/home/alx/tmp/analyzer/bug.c:15:2: note: Calling 'g'
g();
^
/home/alx/tmp/analyzer/bug.c:6:6: note: Assuming the condition is false
if (arc4random() % 2)
^~~~
/home/alx/tmp/analyzer/bug.c:6:2: note: Taking false branch
if (arc4random() % 2)
^
/home/alx/tmp/analyzer/bug.c:8:1: note: Returning without writing to '*x'
}
^
/home/alx/tmp/analyzer/bug.c:15:2: note: Returning from 'g'
g();
^
/home/alx/tmp/analyzer/bug.c:16:2: note: Undefined or garbage value returned to
caller
return x;  // maybe uninitialized use
^  ~

[Bug analyzer/115089] New: -Wanalyzer-use-of-uninitialized-value false negative

2024-05-14 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115089

Bug ID: 115089
   Summary: -Wanalyzer-use-of-uninitialized-value false negative
   Product: gcc
   Version: 14.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: analyzer
  Assignee: dmalcolm at gcc dot gnu.org
  Reporter: alx at kernel dot org
  Target Milestone: ---

For this code, which I wrote to try to trigger
-Wanalyzer-use-of-uninitialized-value:

$ cat bug.c 
#include 

void
g(int *x)
{
if (arc4random() % 2)
*x = 42;
}

int
main(void)
{
int x;

g();
return x;  // maybe uninitialized use
}


I'm having a hard time triggering the warning.  No combination of flags seems
to trigger it.

$ gcc -Wall -Wextra -O3 -flto -fsanitize=undefined -fanalyzer bug.c
$ ./a.out; echo $?
42
$ ./a.out; echo $?
0

I tried 0,1,2,3 optimization levels, and nothing.  Also tried both
gcc (Debian 13.2.0-24) 13.2.0
and
gcc-14 (Debian 14-20240429-1) 14.0.1 20240429 (experimental) [gcc-14
r14-10144-g41d7a8ceaaa]

[Bug c/114731] -Wincompatible-pointer-types false positive in combination with _Generic(3)

2024-04-16 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114731

--- Comment #21 from Alejandro Colomar  ---
It would be interesting to learn why MSVC gets it right.  Maybe there's a
deterministic way to avoid this warning.  Although maybe it's just that they're
doing heuristics.

[Bug c/114731] -Wincompatible-pointer-types false positive in combination with _Generic(3)

2024-04-16 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114731

--- Comment #20 from Alejandro Colomar  ---
H, I like the _Generic() to assert the type.  Thanks!

With that, I find it more acceptable.  At least I don't need to use GNU
extensions, and the cast is coupled with the verification of the type.  It's a
bit repetitive, but acceptable.

I agree that using heuristics to fix this would be bad.

Feel free to close as WONTFIX.

Have a lovely day!
Alex


Below is the program using _Generic() to assert the type.


alx@debian:~/tmp/c$ cat g.c
#include 
#include 
#include 
#include 


#define a2i(TYPE, n, s, endp, base, min, max) \
({\
_Generic((TYPE) 0,\
long:   a2sl(_Generic(n, TYPE *: (long *) n), s,
endp, base, min, max), \
int:a2si(_Generic(n, TYPE *:  (int *) n), s,
endp, base, min, max)  \
);\
})


#define a2sl(n, s, endp, base, min, max)  \
( \
_Generic(endp,\
const char **:  a2sl_c,   \
char **:a2sl_nc,  \
void *: a2sl_nc   \
)(n, s, endp, base, min, max) \
)

#define a2si(n, s, endp, base, min, max)  \
( \
_Generic(endp,\
const char **:  a2si_c,   \
char **:a2si_nc,  \
void *: a2si_nc   \
)(n, s, endp, base, min, max) \
)


static inline int a2sl_c(long *restrict n, const char *s,
const char **restrict endp, int base, long min, long max);
static inline int a2si_c(int *restrict n, const char *s,
const char **restrict endp, int base, int min, int max);

static inline int a2sl_nc(long *restrict n, const char *s,
char **restrict endp, int base, long min, long max);
static inline int a2si_nc(int *restrict n, const char *s,
char **restrict endp, int base, int min, int max);


static inline int
a2sl_c(long *restrict n, const char *s,
const char **restrict endp, int base, long min, long max)
{
return a2sl_nc(n, s, (char **) endp, base, min, max);
}


static inline int
a2si_c(int *restrict n, const char *s,
const char **restrict endp, int base, int min, int max)
{
return a2si_nc(n, s, (char **) endp, base, min, max);
}


static inline int
a2sl_nc(long *restrict n, const char *s,
char **restrict endp, int base, long min, long max)
{
int  status;

*n = strtoi(s, endp, base, min, max, );
if (status != 0) {
errno = status;
return -1;
}
return 0;
}


static inline int
a2si_nc(int *restrict n, const char *s,
char **restrict endp, int base, int min, int max)
{
int  status;

*n = strtoi(s, endp, base, min, max, );
if (status != 0) {
errno = status;
return -1;
}
return 0;
}


int
main(void)
{
time_t  t;

a2i(time_t, , "42", NULL, 0, 0, 10);
}
alx@debian:~/tmp/c$ cc -Wall -Wextra g.c -S
alx@debian:~/tmp/c$

[Bug c/114731] -Wincompatible-pointer-types false positive in combination with _Generic(3)

2024-04-16 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114731

--- Comment #17 from Alejandro Colomar  ---
Neither -Wall nor -Wextra (nor -Wincompatible-pointer-types) imply -pedantic.

(Ahh, this is the pedwarn reference from Andrew.)

Which means the compiler could decide to turn off -Wincompatible-pointer-types
in dead _Generic() branches, as long as -pedantic is not specified.

Maybe split the warning into

-Wincompatible-pointer-types-generic
-Wincompatible-pointer-types

And make the -generic one not present in -Wall -Wextra, and only enabled by
-pedantic.

[Bug c/114731] -Wincompatible-pointer-types false positive in combination with _Generic(3)

2024-04-16 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114731

--- Comment #15 from Alejandro Colomar  ---
(In reply to uecker from comment #13)
> A couple of comments:
> 
> In principle, those warnings are not false positives. The design of _Generic
> requires that the non-taken branches are valid in C, so some warnings are
> required by the C standard.  We can tweak warnings (which we already did for
> some), but I do not think it is possible to solve all issues in this wa.

I showed you an example program in comment #12 that is an evidence that either
there's no requirement by ISO C that this results in a diagnostic, or maybe
it's required by GCC is already violating the standard here.  I'm repeating it
here:

$ cat constraint.c
void f(int *);

int
main(void)
{
unsigned u;
f();
}
$ cc constraint.c -S
$ 

> 
> There are different ways to work around this:
> 
> One can work around using explicit casts and/or temporary values so that the
> code of all branches is always valid. 

It's too error prone.

> It may be helpful to flatten multi-level _Generic to one level by matching
> an artificial function pointer type:
> 
> #define foo(a, b) _Generic((void(*)(typeof(a), typeof(b)))0, void(*)(int,
> int): ...)

The thing is that the intermediate macros are also an intended API, so I need
to either call it using two levels of macros, or reimplement it in the caller. 
This is also repetitive and error-prone, just like the casts.

[Bug c/114731] -Wincompatible-pointer-types false positive in combination with _Generic(3)

2024-04-16 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114731

--- Comment #14 from Alejandro Colomar  ---
Oops, I forgot to paste the version with casts.  Here it is.

It is too repetitive and error prone.


alx@debian:~/tmp/c$ cat g.c
#include 
#include 
#include 
#include 


#define is_same_type(a, b)__builtin_types_compatible_p(a, b)
#define is_same_typeof(a, b)  is_same_type(typeof(a), typeof(b))


#define a2i(TYPE, n, s, endp, base, min, max) \
({\
_Static_assert(is_same_typeof(TYPE *, n), "");\
_Generic((TYPE) 0,\
long:   a2sl((long *) n, s, endp, base, min, max),
\
int:a2si( (int *) n, s, endp, base, min, max) 
\
);\
})


#define a2sl(n, s, endp, base, min, max)  \
( \
_Generic(endp,\
const char **:  a2sl_c,   \
char **:a2sl_nc,  \
void *: a2sl_nc   \
)(n, s, endp, base, min, max) \
)

#define a2si(n, s, endp, base, min, max)  \
( \
_Generic(endp,\
const char **:  a2si_c,   \
char **:a2si_nc,  \
void *: a2si_nc   \
)(n, s, endp, base, min, max) \
)


static inline int a2sl_c(long *restrict n, const char *s,
const char **restrict endp, int base, long min, long max);
static inline int a2si_c(int *restrict n, const char *s,
const char **restrict endp, int base, int min, int max);

static inline int a2sl_nc(long *restrict n, const char *s,
char **restrict endp, int base, long min, long max);
static inline int a2si_nc(int *restrict n, const char *s,
char **restrict endp, int base, int min, int max);


static inline int
a2sl_c(long *restrict n, const char *s,
const char **restrict endp, int base, long min, long max)
{
return a2sl_nc(n, s, (char **) endp, base, min, max);
}


static inline int
a2si_c(int *restrict n, const char *s,
const char **restrict endp, int base, int min, int max)
{
return a2si_nc(n, s, (char **) endp, base, min, max);
}


static inline int
a2sl_nc(long *restrict n, const char *s,
char **restrict endp, int base, long min, long max)
{
int  status;

*n = strtoi(s, endp, base, min, max, );
if (status != 0) {
errno = status;
return -1;
}
return 0;
}


static inline int
a2si_nc(int *restrict n, const char *s,
char **restrict endp, int base, int min, int max)
{
int  status;

*n = strtoi(s, endp, base, min, max, );
if (status != 0) {
errno = status;
return -1;
}
return 0;
}


int
main(void)
{
time_t  t;

a2i(time_t, , "42", NULL, 0, 0, 10);
}
alx@debian:~/tmp/c$ cc -Wall -Wextra g.c -S
alx@debian:~/tmp/c$

[Bug c/114731] -Wincompatible-pointer-types false positive in combination with _Generic(3)

2024-04-16 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114731

--- Comment #12 from Alejandro Colomar  ---
Hi Martin,

On Tue, Apr 16, 2024 at 05:35:03AM +, uecker at gcc dot gnu.org wrote:
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97100
> 
> --- Comment #7 from uecker at gcc dot gnu.org ---
> 
> The fix suppresses certain warnings which are guarded by a flag, but it is not
> always clear whether a specific warning should be suppressed or not in dead
> code. 

_Generic(3)'s branches are by design using different types, to call
appropriate overload implementations.  These will necessarily result in
incompatible types somewhere.  If you're lucky and your overload
implementations are functions _and_ you call them all with the same
argument list, you can move the argument list out of the _Generic
expression, so as to avoid the warnings (because _Generic() will have
already been evaluated at the time the argument list is part of the
function call and the compiler has the information to diagnose.

If either you pass a different argument list (not my case) to each
overload, or your overloads must be implemented via macros (my case),
then you must put the argument list inside the _Generic() expression,
which will necessarily result in incompatible types (otherwise you
wouldn't be using _Generic() at all, probably).

> 
> You could also always add a cast.

I designed these macros precisely for type safety.  That is, to have the
compiler diagnose type mismatches.  For example, the call

err = a2i(time_t, , "42", endp, base, min, max);

is a type-safe version of BSD's

t = strtoi("42", endp, base, min, max);

Because nothing guarantees that intmax_t will be appropriate for parsing
a time_t.  My macro will call a wraper function that makes sure that we
call the right one, strtoi(3) or strtou(3), depending on the signedness
of time_t.  It goes even further and makes sure that  is actually a
time_t, by wrapping strtoi(3) in a call that accepts a long*.

If I do cast, then I lose all that type safety, and need to increase
the complexity by tinkering with GNU extesions such as ({}) and
__builtin_types_compatible_p(), and I also need to insert a
_Static_assert(3).  All of this is error prone, and requires that the
program is not DRY, so I would really like to avoid it.

It's nice, though, that it's possible to workaround it with a cast +
GNU extensions + some extra complexity.  At least I have a fallback.
But I don't think I'm content with keeping it like that.  See the
program below to see what needs to be done to make it work safely.

You mentioned in the #97100 thread that a C compiler must diagnose all
constraint violations.  Is the following then a violation of the
standard?

$ cat constraint.c 
void f(int *);

int main(void)
{
unsigned u;
f();
}
$ cc constraint.c -S
$ 

I don't see the compiler should be allowed not emit a diagnostic there,
and it's not ok to not emit a diagnostic in a dead branch of _Generic(),
independently of me having asked the compiler to warn about
-Wincompatible-pointer-types.  Dead branches of _Generic() are not just
any dead code; it's dead code that we know will result in incompatible
types, by design.  A warning about them there is bogus.

Please present a case where not warning about incompatible types in a
dead _Generic() branch would be bad.

> Fundamentally, the program is that _Generic is not ideally designed for this
> use case. One could consider an extension

Why not?  What's the design use-case for _Generic() if it's not
overloading a macro for different types, and then call the appropriate
overload function or macro?  Even if you open-code the branches in the
_Generic() expressions, you're doing the same thing: writing code for
handling different types, which will almost necessarily result in
incompatible types in all branches but one.

Have a lovely day!
Alex

[Bug c/97100] -Wformat checks all arms of _Generic leading to irrelevant type expectation warnings

2024-04-16 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97100

--- Comment #14 from Alejandro Colomar  ---
Hi Martin,

For the discussion of my -Wincompatible-pointer-types reproducer, please visit
.  I'll reply to you
there, since it's more on-topic, and also, I posted there the full reproducer.

Have a lovely day!
Alex

[Bug c/114731] -Wincompatible-pointer-types false positive in combination with _Generic(3)

2024-04-15 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114731

--- Comment #11 from Alejandro Colomar  ---
What are pedwarns?  :)

[Bug c/114731] -Wincompatible-pointer-types false positive in combination with _Generic(3)

2024-04-15 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114731

--- Comment #9 from Alejandro Colomar  ---
The related bug claims to be fixed in trunk.  I can still reproduce mine in
gcc-14, from Debian RC-Buggy.


alx@debian:~/tmp/c$ gcc-14 -Wall -Wextra g.c -S
g.c: In function ‘main’:
g.c:96:21: error: passing argument 1 of ‘a2si_c’ from incompatible pointer type
[-Wincompatible-pointer-types]
   96 | a2i(time_t, , "42", NULL, 0, 0, 10);
  | ^~
  | |
  | time_t * {aka long int *}
g.c:30:11: note: in definition of macro ‘a2si’
   30 | )(n, s, endp, base, min, max)  
  \
  |   ^
g.c:96:9: note: in expansion of macro ‘a2i’
   96 | a2i(time_t, , "42", NULL, 0, 0, 10);
  | ^~~
g.c:54:22: note: expected ‘int * restrict’ but argument is of type ‘time_t *’
{aka ‘long int *’}
   54 | a2si_c(int *restrict n, const char *s,
  |~~^
alx@debian:~/tmp/c$ gcc-14 --version
gcc-14 (Debian 14-20240330-1) 14.0.1 20240330 (experimental) [master
r14-9728-g6fc84f680d0]
Copyright (C) 2024 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

[Bug c/97100] -Wformat checks all arms of _Generic leading to irrelevant type expectation warnings

2024-04-15 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97100

--- Comment #6 from Alejandro Colomar  ---
Oh well, in my case it is -Wincompatible-pointer-types.  Maybe the fix was only
for -Wformat.

[Bug c/97100] -Wformat checks all arms of _Generic leading to irrelevant type expectation warnings

2024-04-15 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97100

Alejandro Colomar  changed:

   What|Removed |Added

 CC||alx at kernel dot org

--- Comment #5 from Alejandro Colomar  ---
I can still reproduce it, using gcc-14 from Debian RC-Buggy.


alx@debian:~/tmp/c$ gcc-14 -Wall -Wextra g.c -S
g.c: In function ‘main’:
g.c:96:21: error: passing argument 1 of ‘a2si_c’ from incompatible pointer type
[-Wincompatible-pointer-types]
   96 | a2i(time_t, , "42", NULL, 0, 0, 10);
  | ^~
  | |
  | time_t * {aka long int *}
g.c:30:11: note: in definition of macro ‘a2si’
   30 | )(n, s, endp, base, min, max)  
  \
  |   ^
g.c:96:9: note: in expansion of macro ‘a2i’
   96 | a2i(time_t, , "42", NULL, 0, 0, 10);
  | ^~~
g.c:54:22: note: expected ‘int * restrict’ but argument is of type ‘time_t *’
{aka ‘long int *’}
   54 | a2si_c(int *restrict n, const char *s,
  |~~^
alx@debian:~/tmp/c$ gcc-14 --version
gcc-14 (Debian 14-20240330-1) 14.0.1 20240330 (experimental) [master
r14-9728-g6fc84f680d0]
Copyright (C) 2024 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

[Bug c/114731] -Wincompatible-pointer-types false positive in combination with _Generic(3)

2024-04-15 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114731

--- Comment #5 from Alejandro Colomar  ---
Ahhh, sorry Sam.  I had a mistake while writing the reproducer, and didn't
realize.  I thought it was a side effect of something else.


Here's a fixed reproducer, with the fixed diagnostics.


$ cat g.c 
#include 
#include 
#include 


#define a2i(TYPE, ...)\
( \
_Generic((TYPE) 0,\
long:   a2sl(__VA_ARGS__),\
int:a2si(__VA_ARGS__)\
) \
)


#define a2sl(n, s, endp, base, min, max)  \
( \
_Generic(endp,\
const char **:  a2sl_c,   \
char **:a2sl_nc,  \
void *: a2sl_c\
)(n, s, endp, base, min, max) \
)

#define a2si(n, s, endp, base, min, max)  \
( \
_Generic(endp,\
const char **:  a2si_c,   \
char **:a2si_nc,  \
void *: a2si_c\
)(n, s, endp, base, min, max) \
)


static inline int a2sl_c(long *restrict n, const char *s,
const char **restrict endp, int base, long min, long max);
static inline int a2si_c(int *restrict n, const char *s,
const char **restrict endp, int base, int min, int max);

static inline int a2sl_nc(long *restrict n, const char *s,
char **restrict endp, int base, long min, long max);
static inline int a2si_nc(int *restrict n, const char *s,
char **restrict endp, int base, int min, int max);


static inline int
a2sl_c(long *restrict n, const char *s,
const char **restrict endp, int base, long min, long max)
{
return a2sl_nc(n, s, (char **) endp, base, min, max);
}


static inline int
a2si_c(int *restrict n, const char *s,
const char **restrict endp, int base, int min, int max)
{
return a2si_nc(n, s, (char **) endp, base, min, max);
}


static inline int
a2sl_nc(long *restrict n, const char *s,
char **restrict endp, int base, long min, long max)
{
int  status;

*n = strtoi(s, endp, base, min, max, );
if (status != 0) {
errno = status;
return -1;
}
return 0;
}


static inline int
a2si_nc(int *restrict n, const char *s,
char **restrict endp, int base, int min, int max)
{
int  status;

*n = strtoi(s, endp, base, min, max, );
if (status != 0) {
errno = status;
return -1;
}
return 0;
}


int
main(void)
{
time_t  t;

a2i(time_t, , "42", NULL, 0, 0, 10);
}
alx@debian:~/tmp/c$ cc -Wall -Wextra g.c 
g.c: In function ‘main’:
g.c:96:21: warning: passing argument 1 of ‘a2si_c’ from incompatible pointer
type [-Wincompatible-pointer-types]
   96 | a2i(time_t, , "42", NULL, 0, 0, 10);
  | ^~
  | |
  | time_t * {aka long int *}
g.c:30:11: note: in definition of macro ‘a2si’
   30 | )(n, s, endp, base, min, max)  
  \
  |   ^
g.c:96:9: note: in expansion of macro ‘a2i’
   96 | a2i(time_t, , "42", NULL, 0, 0, 10);
  | ^~~
g.c:54:22: note: expected ‘int * restrict’ but argument is of type ‘time_t *’
{aka ‘long int *’}
   54 | a2si_c(int *restrict n, const char *s,
  |~~^
/usr/bin/ld: /tmp/ccQQX6M9.o: in function `a2sl_nc':
g.c:(.text+0x86): undefined reference to `strtoi'
collect2: error: ld returned 1 exit status

[Bug c/114731] -Wincompatible-pointer-types false positive in combination with _Generic(3)

2024-04-15 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114731

--- Comment #3 from Alejandro Colomar  ---
The diagnostic is spurious, because of course if I call the following macro



#define a2i(TYPE, ...)\
( \
_Generic((TYPE) 0,\
long:   a2sl(__VA_ARGS__),\
int:a2si(__VA_ARGS__),\
) \
)


I only want to use the variant corresponding to the type that I passed, and of
course the other variant will be incompatible with the one I want.  That's the
whole reason to use _Generic() in the first place.

[Bug c/114731] -Wincompatible-pointer-types false positive in combination with _Generic(3)

2024-04-15 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114731

--- Comment #2 from Alejandro Colomar  ---
That's precisely what I meant (my bad, I used incorrect wording).  I think that
diagnostic is spurious, and should be removed.

A few self-corrections:

-  I should have said diagnostics, instead of warnings.
-  I should have said compiler output, instead of output.

[Bug c/114731] New: -Wincompatible-pointer-types false positive in combination with _Generic(3)

2024-04-15 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114731

Bug ID: 114731
   Summary: -Wincompatible-pointer-types false positive in
combination with _Generic(3)
   Product: gcc
   Version: 13.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c
  Assignee: unassigned at gcc dot gnu.org
  Reporter: alx at kernel dot org
  Target Milestone: ---

Hi!

I'm writing type-generic macros with two levels of _Generic(3), because I want
to act depending on the type of two arguments.  It's implemented as a
single-_Generic() macro, which calls other single-_Generic() macros,
effectively implementing two levels of switching.

Here's a small reproducer of these macros:


#define a2i(TYPE, ...)\
( \
_Generic((TYPE) 0,\
long:   a2sl(__VA_ARGS__),\
int:a2si(__VA_ARGS__),\
) \
)


#define a2sl(n, s, endp, base, min, max)  \
( \
_Generic(endp,\
const char **:  a2sl_c,   \
char **:a2sl_nc,  \
void *: a2sl_c\
)(n, s, endp, base, min, max) \
)

#define a2si(n, s, endp, base, min, max)  \
( \
_Generic(endp,\
const char **:  a2si_c,   \
char **:a2si_nc,  \
void *: a2si_c\
)(n, s, endp, base, min, max) \
)


As long as you only use one _Generic, it's easy, because you can pass the
argument list outside of _Generic(), and it will call the right function. 
However, if you want to call a macro (the second level), you must write the
argument list inside the _Generic() switch.  This triggers warnings in all the
non-evaluated expressions.

These warnings should not be emitted, and only the evaluated expression in
_Generic() should emit warnings about types, I think.

Below is an entire reproducer program, and it's output:

$ cat g.c 
#include 
#include 
#include 


#define a2i(TYPE, ...)\
( \
_Generic((TYPE) 0,\
long:   a2sl(__VA_ARGS__),\
int:a2si(__VA_ARGS__),\
) \
)


#define a2sl(n, s, endp, base, min, max)  \
( \
_Generic(endp,\
const char **:  a2sl_c,   \
char **:a2sl_nc,  \
void *: a2sl_c\
)(n, s, endp, base, min, max) \
)

#define a2si(n, s, endp, base, min, max)  \
( \
_Generic(endp,\
const char **:  a2si_c,   \
char **:a2si_nc,  \
void *: a2si_c\
)(n, s, endp, base, min, max) \
)


static inline int a2sl_c(long *restrict n, const char *s,
const char **restrict endp, int base, long min, long max);
static inline int a2si_c(int *restrict n, const char *s,
const char **restrict endp, int base, int min, int max);

static inline int a2sl_nc(long *restrict n, const char *s,
char **restrict endp, int base, long min, long max);
static inline int a2si_nc(int *restrict n, const char *s,
char 

[Bug analyzer/109802] [13 Regression] ICE using dubious flexible arrays in unions

2024-04-14 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109802

--- Comment #6 from Alejandro Colomar  ---
Thanks for fixing it!

Would you mind showing which commit fixed this?  I'm curious about it.  I
searched in the git log, but nothing mentioned this bug number.

Now I can come to my original intent, which is asking if this code is supported
by GCC, as in

Does this code have defined behavior under GCC?
Does it need and -f flags to be defined?
Or is it just undefined behavior?

I ask because this code exists in a real project.

[Bug middle-end/108036] [11/12/13/14 Regression] Spurious warning for zero-sized array parameters to a function

2024-03-07 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108036

--- Comment #9 from Alejandro Colomar  ---
Hi Lundin!

On Thu, Mar 07, 2024 at 10:18:12AM +, daniel.lundin.mail at gmail dot com
wrote:
> --- Comment #8 from Daniel Lundin  ---
> I don't believe char past_end[0] is valid C, because it is an invalid array
> declaration. Unlike [] or [*] that declares an array of incomplete type. 
> 
> Since it is a function parameter, it will of course later get adjusted to a
> pointer to the first element. But it still has to be a valid declaration to
> begin with. Similarly, char arr[][] is invalid because it remains an 
> incomplete
> type after adjustment (see C17 6.7.6.4 §4).

Agree; ISO C seems to not allow this with their wording.  (I wish it did,
because it's just a matter of wording, not that they don't allow passing
a pointer to past the end).  But maybe the wording needed for allowing
this would have other undersirable consequences, so I'm happy as long as
GNU C would support this.

> gcc does allow [0] as an extension since that was commonly used for purposes 
> of
> implementing the "struct hack" back in the days before flexible array members
> were standardized.
> 
> The conclusion ought to be that gcc should let [0] through if compiled in
> -std=gnu23 mode but not in -std=c23 and/or -pedantic.

And agree; if support for this is added, pedantic or ISO C modes should
complain about it.

Have a lovely day!
Alex

[Bug analyzer/113990] New: -Wanalyzer-malloc-leak false positive with [[gnu::malloc(free)]] and a realloc() wrapper

2024-02-19 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113990

Bug ID: 113990
   Summary: -Wanalyzer-malloc-leak false positive with
[[gnu::malloc(free)]] and a realloc() wrapper
   Product: gcc
   Version: 13.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: analyzer
  Assignee: dmalcolm at gcc dot gnu.org
  Reporter: alx at kernel dot org
  Target Milestone: ---

When wrapping realloc(3) and marking the wrapper as [[gnu::malloc(free)]],
-fanalyzer complains about a leak.

```c
#include 
#include 


[[gnu::malloc(free)]]
static char *addchar(size_t *restrict n, char *restrict cc, char c);


int
main(int argc, char *argv[])
{
char*cc = NULL;
size_t  n = 0;

for (int i = 0; i < argc; i++)
cc = addchar(, cc, argv[i][0]);

free(cc);
exit(EXIT_SUCCESS);
}


static char *
addchar(size_t *restrict n, char *restrict cc, char c)
{
cc = realloc(cc, ++*n);
if (cc == NULL)
exit(EXIT_FAILURE);

cc[*n - 1] = c;

return cc;
}
```

$ gcc-14 -Wall -Wextra leak.c -fanalyzer
leak.c: In function ‘addchar’:
leak.c:32:16: warning: leak of ‘cc’ [CWE-401] [-Wanalyzer-malloc-leak]
   32 | return cc;
  |^~
  ‘main’: events 1-5
|
|   10 | main(int argc, char *argv[])
|  | ^~~~
|  | |
|  | (1) entry to ‘main’
|..
|   15 | for (int i = 0; i < argc; i++)
|  | 
|  |   |
|  |   (2) following ‘true’ branch (when ‘i <
argc’)...
|   16 | cc = addchar(, cc, argv[i][0]);
|  |  ~~~
|  |  |   |
|  |  |   (3) ...to here
|  |  (4) allocated here
|  |  (5) calling ‘addchar’ from ‘main’
|
+--> ‘addchar’: events 6-10
   |
   |   24 | addchar(size_t *restrict n, char *restrict cc, char c)
   |  | ^~~
   |  | |
   |  | (6) entry to ‘addchar’
   |   25 | {
   |   26 | cc = realloc(cc, ++*n);
   |  |  ~
   |  |  |
   |  |  (7) when ‘realloc’ succeeds, moving buffer
   |   27 | if (cc == NULL)
   |  |~
   |  ||
   |  |(8) following ‘false’ branch (when ‘cc’ is
non-NULL)...
   |..
   |   30 | cc[*n - 1] = c;
   |  |~~
   |  ||
   |  |(9) ...to here
   |   31 | 
   |   32 | return cc;
   |  |~~
   |  ||
   |  |(10) ‘cc’ leaks here; was allocated at (4)
   |


It is reproducible in both of these:

alx@debian:~/tmp$ gcc-14 --version | head -n1
gcc-14 (Debian 14-20240201-3) 14.0.1 20240131 (experimental) [master
r14-8680-g2f14c0dbb78]
alx@debian:~/tmp$ gcc-13 --version | head -n1
gcc-13 (Debian 13.2.0-13) 13.2.0

[Bug c/113984] -Wfree-nonheap-object false positive with VLA parameter

2024-02-18 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113984

--- Comment #1 from Alejandro Colomar  ---
With -O3, the warning also vanishes, as the function is probably inlined, and
there's no VLA parameter any more.

alx@debian:~/tmp$ gcc-14 -Wall -O3 nonheap.c 
alx@debian:~/tmp$ gcc-13 -Wall -O3 nonheap.c 
alx@debian:~/tmp$

[Bug c/113984] New: -Wfree-nonheap-object false positive with VLA parameter

2024-02-18 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113984

Bug ID: 113984
   Summary: -Wfree-nonheap-object false positive with VLA
parameter
   Product: gcc
   Version: 13.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c
  Assignee: unassigned at gcc dot gnu.org
  Reporter: alx at kernel dot org
  Target Milestone: ---

I can reproduce it with both of these:

$ gcc-13 --version | head -n1
gcc-13 (Debian 13.2.0-13) 13.2.0
$ gcc-14 --version | head -n1
gcc-14 (Debian 14-20240201-3) 14.0.1 20240131 (experimental) [master
r14-8680-g2f14c0dbb78]


See a small reproducer:


```c
#include 
#include 
#include 


static const char **add_string(size_t *restrict n,
const char *strings[restrict *n], const char *restrict string);


int
main(int argc, char *argv[argc + 1])
{
size_t  n = 0;
const char  **strings = NULL;

add_string(, strings, argv[0]);
}


static const char **
add_string(size_t *restrict n, const char *strings[restrict *n],
const char *restrict string)
{
strings = reallocarray(strings, ++*n, sizeof(const char *));
if (strings == NULL)
err(EXIT_FAILURE, "reallocarray(3)");

strings[*n - 1] = string;

return strings;
}
```


alx@debian:~/tmp$ gcc-13 -Wall nonheap.c 
nonheap.c: In function ‘add_string’:
nonheap.c:24:19: warning: ‘reallocarray’ called on unallocated object ‘strings’
[-Wfree-nonheap-object]
   24 | strings = reallocarray(strings, ++*n, sizeof(const char *));
  |   ^
nonheap.c:21:44: note: declared here
   21 | add_string(size_t *restrict n, const char *strings[restrict *n],
  |^~~~
alx@debian:~/tmp$ gcc-14 -Wall nonheap.c 
nonheap.c: In function ‘add_string’:
nonheap.c:24:19: warning: ‘reallocarray’ called on unallocated object ‘strings’
[-Wfree-nonheap-object]
   24 | strings = reallocarray(strings, ++*n, sizeof(const char *));
  |   ^
nonheap.c:21:44: note: declared here
   21 | add_string(size_t *restrict n, const char *strings[restrict *n],
  |^~~~


If I change the function to have the parameter be `const char **restrict
strings`, the warning vanishes.

[Bug target/103910] openjdk17 causes ICE on -O3 -march=opteron -fcheck-new: during GIMPLE pass: aprefetch: in gimple_build_call, at gimple.c:267

2024-02-06 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103910

Alejandro Colomar  changed:

   What|Removed |Added

 CC||alx at kernel dot org

--- Comment #13 from Alejandro Colomar  ---
I personally build PCHs in my build systems, as a test that the header files
are self-contained.  It has proved useful to me.  But I could live without it
if you  insist on removing it.  Just a data point.

[Bug c/113378] _Static_assert diagnostics lack information when compiling stdin

2024-01-15 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113378

--- Comment #6 from Alejandro Colomar  ---
On Mon, Jan 15, 2024 at 09:38:31AM +, pinskia at gcc dot gnu.org wrote:
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113378
> 
> --- Comment #5 from Andrew Pinski  ---
> (In reply to Alejandro Colomar from comment #4)
> > 
> > Not necessarily.  I use stdin for simplicity in small tests.  The
> > test suite
> 
> Which testsuite is this?

Nothing standard.  Just a hand-written GNUmakefile that runs all scripts
within share/tests/.


TESTS  := $(shell $(FIND) $(TESTSDIR) -type f | $(GREP) '\.sh$$' |
$(SORT))
_TESTS := $(patsubst $(srcdir)/share/%,$(builddir)/%.ck.touch,$(TESTS))
_tests := $(patsubst
$(srcdir)/share/%,$(builddir)/%.ick.touch,$(TESTS))


_TESTSDIRS := $(patsubst $(srcdir)/share/%,$(builddir)/%/,$(shell
$(FIND) $(TESTSDIR) -type d | $(SORT)))


$(_TESTSDIRS): | $$(dir $$(@D))
$(info  MKDIR   $@)
$(MKDIR) $@


$(_TESTS): $(builddir)/%.ck.touch: $(srcdir)/share/% $(MK) $(TU_h)
$(_LIB_a) $(_LIB_so_v) | $$(@D)/
$(info  SH (test)   $@)
PKG_CONFIG_LIBDIR=$(PCDIR) $<
touch $@

$(_tests): $(builddir)/%.ick.touch: $(srcdir)/share/% $(MK) $(_tu_h)
$(_lib_a) $(_lib_so) | $$(@D)/
$(info  SH (test)   $@)
$<
touch $@


.PHONY: check
check: $(_TESTS)


.PHONY: installcheck
installcheck: $(_tests)


>  I should note GCC uses dejagnu (and you can make your
> own testsuite using that too for other compilers too) which allows you to do
> things like:

I know.  I want to learn to use it if I find some time, and replace my
custom scripts.

> ```
> #include 
> 
> int
> main(void)
> {
>   unsigned char  n;
>   str2i(signed char, , "0"); /* { dg-error "-Werror=pointer-sign" } */
> }
> ```
> Which is easier to maintain than shell scripts like you provided in comment 
> #4.
>  Note a simple dejagnu testsuite supports dg-error/dg-warning by default; 
> GCC's
> version of dg-error/dg-warning has more features though.

Thanks!

Have a lovely day,
Alex

[Bug c/113378] _Static_assert diagnostics lack information when compiling stdin

2024-01-15 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113378

--- Comment #4 from Alejandro Colomar  ---
On Mon, Jan 15, 2024 at 08:35:53AM +, rguenth at gcc dot gnu.org wrote:
> --- Comment #3 from Richard Biener  ---
> We could buffer stdin to a temporary file ... (of course that would defeat 
> it's
> purpose somewhat).

Not necessarily.  I use stdin for simplicity in small tests.  The
test suite runs some sh(1) scripts, which themselves do more or less:


#!/usr/bin/bash
set -Eeuf;
out="$(mktemp)";
CFLAGS=...
LIBS=...

cc $CFLAGS -o "$out" -x c - $LIBS 2>&1 <<__EOF__ \
| if ! grep -- '-Werror=pointer-sign' >/dev/null; then \
>&2 printf '%s\n' "$0:$LINENO: Expected error:
[-Werror=pointer-sign]"; \
exit 1; \
else \
true; \
fi;
#include 

int
main(void)
{
unsigned char  n;

str2i(signed char, , "0");
}
__EOF__

And a script can have several of those embedded C programs, without
really having so many .c files.

If the compiler chooses to use a temporary file to improve the
diagnostics, that's not a problem.

[Bug c/113378] _Static_assert diagnostics lack information when compiling stdin

2024-01-13 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113378

--- Comment #2 from Alejandro Colomar  ---
(In reply to Andrew Pinski from comment #1)
> >I expect the same diagnostic information when compiling stdin.
> 
> 
> This part of the diagnostic:
> 2 | foo();
>   | ^~~
> 
> Comes from re-reading in the source file.

Makes sense.

I've tested with other diagnostics, and it's a general thing, not just about
static_assert().  Sorry, for the bogus bug report :)

[Bug c/113378] New: _Static_assert diagnostics lack information when compiling stdin

2024-01-13 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113378

Bug ID: 113378
   Summary: _Static_assert diagnostics lack information when
compiling stdin
   Product: gcc
   Version: 13.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c
  Assignee: unassigned at gcc dot gnu.org
  Reporter: alx at kernel dot org
  Target Milestone: ---

alx@debian:~/tmp$ cat is/asc.h 
#pragma GCC system_header
#define foo()  _Static_assert(sizeof(int) == sizeof(char))
alx@debian:~/tmp$ cat asc.c 
#include 
foo();
alx@debian:~/tmp$ cc -Wall -Wextra -isystem is asc.c
In file included from asc.c:1:
asc.c:2:1: error: static assertion failed
2 | foo();
  | ^~~
alx@debian:~/tmp$ cc -Wall -Wextra -isystem is -x c - :1:
:2:1: error: static assertion failed


I expect the same diagnostic information when compiling stdin.

[Bug c/107348] documentation: __builtin_classify_type() undocumented

2023-12-05 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107348

Alejandro Colomar  changed:

   What|Removed |Added

 Resolution|--- |FIXED
 Status|UNCONFIRMED |RESOLVED

--- Comment #7 from Alejandro Colomar  ---
I just realized it was fixed recently.  Thanks!


commit 53d834a7fae3afffebb45a2d66908f705773a7fc
Author: Jakub Jelinek 
Date:   Wed Sep 20 18:37:29 2023 +0200

c, c++: Accept __builtin_classify_type (typename)

As mentioned in my stdckdint.h mail, __builtin_classify_type has
a problem that argument promotion (the argument is passed to ...
prototyped builtin function) means that certain type classes will
simply never appear.
I think it is too late to change how it behaves, lots of code in the
wild might rely on the current behavior.

So, the following patch adds option to use a typename rather than
expression as the operand to the builtin, making it behave similarly
to sizeof, typeof or say the clang _Generic extension where the
first argument can be there not just expression, but also typename.

I think we have other prior art here, e.g. __builtin_va_arg also
expects typename.

I've added this to both C and C++, because it would be weird if it
supported it only in C and not in C++.

2023-09-20  Jakub Jelinek  

gcc/
* builtins.h (type_to_class): Declare.
* builtins.cc (type_to_class): No longer static.  Return
int rather than enum.
* doc/extend.texi (__builtin_classify_type): Document.
gcc/c/
* c-parser.cc (c_parser_postfix_expression_after_primary): Parse
__builtin_classify_type call with typename as argument.
gcc/cp/
* parser.cc (cp_parser_postfix_expression): Parse
__builtin_classify_type call with typename as argument.
* pt.cc (tsubst_copy_and_build): Handle __builtin_classify_type
with dependent typename as argument.
gcc/testsuite/
* c-c++-common/builtin-classify-type-1.c: New test.
* g++.dg/ext/builtin-classify-type-1.C: New test.
* g++.dg/ext/builtin-classify-type-2.C: New test.
* gcc.dg/builtin-classify-type-1.c: New test.

[Bug c/112833] Missing warnings on restrict misuse

2023-12-03 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112833

--- Comment #1 from Alejandro Colomar  ---
Oops, in the reproducer from above, I should only expect a warning at call
site.  The definition is correct, since all parameters are restrict, so it's
free to copy one to the other.

Here's a reproducer where the call is fine, but the definition is wrong, and
the compiler doesn't realize:


$ cat restrict.c 
#include 

long bogus2_strtol(const char *s, char **restrict ep, int base);

int
main(void)
{
char buf[3] = "foo";
char *p = buf;

bogus2_strtol(p, , -42);
}

long
bogus2_strtol(const char *s, char **restrict ep, int base)
{
memcpy(*ep, s, 1);
return base;
}
$ gcc -Wall -Wextra restrict.c -fanalyzer
$ gcc -Wall -Wextra restrict.c -fanalyzer -O3

[Bug c/112833] New: Missing warnings on restrict misuse

2023-12-03 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112833

Bug ID: 112833
   Summary: Missing warnings on restrict misuse
   Product: gcc
   Version: 13.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c
  Assignee: unassigned at gcc dot gnu.org
  Reporter: alx at kernel dot org
  Target Milestone: ---

Reproducer:


$ cat restrict.c 
long bogus_strtol(const char *restrict s, char **restrict ep, int base);

int
main(void)
{
char buf[3] = "foo";
char *p = buf;

bogus_strtol(p, , -42);
}

long
bogus_strtol(const char *restrict s, char **restrict ep, int base)
{
**ep = *s;
return base;
}
$ gcc -Wall -Wextra restrict.c -fanalyzer
$ gcc -Wall -Wextra restrict.c -fanalyzer -O3


I'd expect two -Wrestrict warnings, one at call site, and another at `**ep =
*s;`.

BTW, of course, I'd also expect a warning at calls to strtol(3), which I
consider has a wrong use of restrict in the prototype.

Original report at gcc-help@:


[Bug c/112507] New: Missed optimization of strcpy(3) (or stpcpy(3)) with previous strnlen(3)

2023-11-13 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112507

Bug ID: 112507
   Summary: Missed optimization of strcpy(3) (or stpcpy(3)) with
previous strnlen(3)
   Product: gcc
   Version: 13.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c
  Assignee: unassigned at gcc dot gnu.org
  Reporter: alx at kernel dot org
  Target Milestone: ---

The following code can be optimized to use memcpy(3), since the length
of the copy is known (we've just called strnlen(3), and discarded the
possibility of truncated lengths).

$ cat strxcpy.c
#include 
#include 
#include 

ssize_t
strxcpy(char *restrict dst, const char *restrict src, size_t dsize)
{
if (strnlen(src, dsize) == dsize)
return -1;

return stpcpy(dst, src) - dst;
}


This compiles to stpcpy(3).  Similar code written with strcpy(3) also
keeps strcpy(3).  But they could be optimized with mempcpy(3) or
memcpy(3).


On Mon, Nov 13, 2023 at 07:56:00AM +0100, Richard Biener wrote: 
> It looks like a transform for the strlen pass.

[Bug c/111269] location for non-constant expressions inside static assert could be better

2023-09-01 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111269

--- Comment #3 from Alejandro Colomar  ---
On 2023-09-01 18:57, pinskia at gcc dot gnu.org wrote:
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111269
>
> Andrew Pinski  changed:
>
>What|Removed |Added
> 
>See Also||https://gcc.gnu.org/bugzill
>||a/show_bug.cgi?id=55678
>

Did you accidentally point to a different bug?
I don't think that one is related at all.

_Static_assert escapes tick marks just to make me mad

[Bug c/111269] location for non-constant expressions inside static assert could be better

2023-09-01 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111269

--- Comment #2 from Alejandro Colomar  ---
Hi Andrew,

On 2023-09-01 18:55, pinskia at gcc dot gnu.org wrote:
> It is pointing to the whole expression and just the outermost operator, || .

That's what I suspected.

>
> Now the C++ front-end gives a better location and information on why it is not
> a constant expression:
> : In function 'int main()':
> :11:26: error: non-constant condition for static assertion
>11 | _Static_assert(0 || 7 > x, "");
>   |~~^~~~
> :11:33: error: the value of 'x' is not usable in a constant expression
>11 | _Static_assert(0 || 7 > x, "");
>   | ^
> :9:13: note: 'int x' is not const
> 9 | int x = 42;
>   | ^
>
>
> The C front-end could do better ...

Yep, g++ seems good here.  If it's something easy that I could do, I'd
love some pointer to the code I should look at to do the same that the
C++ front end does.

Cheers,
Alex

[Bug c/111269] New: Confusing location of error in source code

2023-09-01 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111269

Bug ID: 111269
   Summary: Confusing location of error in source code
   Product: gcc
   Version: 13.1.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c
  Assignee: unassigned at gcc dot gnu.org
  Reporter: alx at kernel dot org
  Target Milestone: ---

I've been confused for some time with a compilation error that
pointed to a slightly-off location.  I wasn't seeing that I used
a temporary variable in a constant expression.  The code could be
reduced to:

$ cat const.c 
int
main(void)
{
int x = 42;

_Static_assert(0 || 7 > x, "");
}
$ gcc-13 -Wall -Wextra const.c
const.c: In function ‘main’:
const.c:6:26: error: expression in static assertion is not constant
6 | _Static_assert(0 || 7 > x, "");
  |~~^~~~
$ clang-16 -Weverything const.c
const.c:6:26: error: static assertion expression is not an integral constant
expression
_Static_assert(0 || 7 > x, "");
   ~^
1 error generated.


Clang points to the precise location of the problem, while GCC is too fuzzy.

I suspect this is a duplicate of other bugs, but I'm not sure, so I'll let you
decide that.

[Bug middle-end/110617] RFE: Add a diagnostic-only variant of nonnull attribute

2023-07-11 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110617

--- Comment #8 from Alejandro Colomar  ---
Test

[Bug middle-end/110617] RFE: Add a diagnostic-only variant of nonnull attribute

2023-07-11 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110617

--- Comment #7 from Alejandro Colomar  ---
Hi Xi, Richard!

On 2023-07-11 10:34, xry111 at gcc dot gnu.org wrote:
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110617
>
> --- Comment #6 from Xi Ruoyao  ---
> Anyway I'm already too frustrated about this so I'll not continue
> working on nonnull within Glibc headers.  If you don't like this just close it
> as WONTFIX.
>

I understand your frustration.  I'll continue your work, if you
don't mind.

On 2023-07-11 09:46, rguenth at gcc dot gnu.org wrote:
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110617
>
> --- Comment #5 from Richard Biener  ---
> I think a -f... option to disable the code generation effects would make more
> sense than adding another attribute kind.
>

The idea of a -f... option makes sense.  However, I'm skeptical
about being able to reach null correctness via an attribute.  I
think a qualifier, similar to restrict or const, would be better
qualified (pun not intended  for this task.

Clang's _Nonnull (and _Nullable, and friends) are such qualifiers,
similar to restrict.  I think they are better designed for the
goal of having diagnostics if null correctness is breached.

However, they have issues as qualifiers, since the standard says
they should be dropped in lvalue to rvalue conversions (restrict
shares this same issue).  There's been a suggestion in an LLVM
forum to add an _Optional qualifier to the pointee, which would
workaround the issue that qualifiers are dropped.  I'll put both
alternatives next to each other for comparison:

#pragma clang assume_nonnull begin

int i;
int *p;
int *_Nullable q;
_Optional int *r;

p = NULL;  // warn
q = NULL;  // Ok
r = NULL;  // Ok

p =   // Ok
q =   // Ok
r =   // Ok

p = r;  // warn: '_Optional' qualifier is discarded in assignment
q = p;  // Ok
r = p;  // Ok

#pragma clang assume_nonnull end

Cheers,
Alex

-- 

GPG key fingerprint: A9348594CE31283A826FBDD8D57633D441E25BB5

[Bug middle-end/110617] RFE: Add a diagnostic-only variant of nonnull attribute

2023-07-10 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110617

Alejandro Colomar  changed:

   What|Removed |Added

 CC||alx at kernel dot org

--- Comment #3 from Alejandro Colomar  ---
Link:


[Bug tree-optimization/86259] [8 Regression] min(4, strlen(s)) optimized to strlen(s) with -flto

2023-05-22 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86259

--- Comment #43 from Alejandro Colomar  ---
GCC's manual also doesn't seem to document any deviation from ISO C
rules regarding mem*() functions.  It would be good to document what is
the GCC interpretation of ISO C regarding those rules, and what GCC
considers extensions.  And it would also be interesting to note the
reason for such extensions being old code, and that the idea is getting
rid of them at some point, maybe as default, or maybe via some flags
such as -fprovenance.

If str*() functions got the same exception recently, it would also be
good to mention that.

[Bug tree-optimization/86259] [8 Regression] min(4, strlen(s)) optimized to strlen(s) with -flto

2023-05-22 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86259

--- Comment #42 from Alejandro Colomar  ---
I'm very confused by this ticket.

The discussion seems to be settled by Martin Sebor that the presented
code has UB due to pointer provenance issues, according to the WG14
interpretation of the standard.

GCC historically had relaxed rules on mem*() functions, to let old code
work as expected.  This is by no means required by ISO C, and is only
a GNU extension.  ISO C is stricter and under its rules, memcpy(3)
cannot cross subobject boundaries.  This is the ideal behavior, and the
intention is to tighten the rules so that code analysis becomes easier.

Nobody seemed to rebute Martin's analysys that it's UB with solid
ground, and I agree that it looks like UB.

Did I understand that correctly?

And then I see that something has been 'fixed' in GCC, and that the
ticket is marked as RESOLVED FIXED.  This is very confusing, since
nothing in the ticket really documents what was broken.  It seems that
GCC's relaxed rules on mem*() functions were extended to cover str*()
functions too.

May I ask why?  And may I ask a -fprovenance to get strict provenance
rules?  I find very confusing when code breaks provenance rules, because
simlarly to how a compiler will have trouble analyzing the code, a human
brain will have trouble understanding where some copy data came from (at
least that's true for mine).

See the following question, which seems to be very related to pointer
provenance rules: .

I'd like to be able to guarantee that in my code nobody messes with
pointers to get magic copies out of nowhere.

Thanks.

[Bug analyzer/109802] [regression] during IPA pass: analyzer: internal compiler error (using dubious flexible arrays in unions)

2023-05-10 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109802

--- Comment #4 from Alejandro Colomar  ---
(In reply to Alejandro Colomar from comment #3)
> Hmm, I should have used offsetof(3) in a few placed to avoid issues due to
> padding, but I was lucky :).

Oh, no, I didn't need it.  I got it right.  Never mind.

[Bug analyzer/109802] [regression] during IPA pass: analyzer: internal compiler error (using dubious flexible arrays in unions)

2023-05-10 Thread alx at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109802

--- Comment #3 from Alejandro Colomar  ---
Hmm, I should have used offsetof(3) in a few placed to avoid issues due to
padding, but I was lucky :).