[Bug middle-end/91395] Report an uninitialized variable on its initialization statement (setjmp)

2019-08-08 Thread ali at pivotal dot io
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91395

--- Comment #4 from Adam  ---
(In reply to Andrew Pinski from comment #3)
> In theory other can cause a call to longjmp but gcc does not know it cannot.

Thanks for the quick reply.

I got the longjmp() part, it could be called anytime. The part I don't get is
why it reports since gcc could tell that no one changes the
save_exception_stack (it has a certain short life).

The POSIX's statement as I know has two facts: "a local not-volatile variable"
and "it's been changed between setjmp() and longjmp()". Have I missed anything?

[Bug middle-end/91395] Report an uninitialized variable on its initialization statement (setjmp)

2019-08-08 Thread ali at pivotal dot io
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91395

--- Comment #2 from Adam  ---
I got the point "The local variables that do not have the volatile type and
have been changed between the setjmp() invocation and longjmp() call are
indeterminate"

But save_exception_stack is not changed between the setjmp() invocation and
longjmp() call, it is defined every time. Still looks expected?

[Bug c/91395] New: Report an uninitialized variable on its initialization statement (setjmp)

2019-08-08 Thread ali at pivotal dot io
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91395

Bug ID: 91395
   Summary: Report an uninitialized variable on its initialization
statement (setjmp)
   Product: gcc
   Version: 9.1.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c
  Assignee: unassigned at gcc dot gnu.org
  Reporter: ali at pivotal dot io
  Target Milestone: ---

Version:
$ gcc-9 --version
gcc-9 (Ubuntu 9.1.0-2ubuntu2~19.04) 9.1.0
(Actually from gcc 7)

Reproducer:
```
#include 

extern int other(void);
extern void trigger(int *cond1);
extern sigjmp_buf *global_exception_stack;

void
trigger(int *cond1)
{
while (1)
{
if (*cond1 == 0)
*cond1 = other();

while (*cond1)
{
sigjmp_buf *save_exception_stack =
global_exception_stack;
sigjmp_buf local_sigjmp_buf;

if (sigsetjmp(local_sigjmp_buf, 0) == 0)
global_exception_stack = _sigjmp_buf;
else
global_exception_stack = (sigjmp_buf *)
save_exception_stack;

global_exception_stack = (sigjmp_buf *)
save_exception_stack;
}
}
}
```

```
$ gcc-9 -O1 -Werror=uninitialized -fexpensive-optimizations -ftree-pre -c -o
/dev/null reproducer.c
reproducer.c: In function 'trigger':
reproducer.c:17:16: error: 'save_exception_stack' is used uninitialized in this
function [-Werror=uninitialized]
   17 |sigjmp_buf *save_exception_stack = global_exception_stack;
  |^~~~
cc1: some warnings being treated as errors
```

Observation:
1, asm code re-ordering matters.
2, when it reports warning, initializing asm codes are before the setjmp().

When it warns:
```
sigjmp_buf *save_exception_stack = PG_exception_stack;
  2f:   48 8b 1d 00 00 00 00mov0x0(%rip),%rbx# 36

  36:   48 89 5c 24 18  mov%rbx,0x18(%rsp)
sigjmp_buf local_sigjmp_buf;

if (sigsetjmp(local_sigjmp_buf, 0) == 0)
```

When it doesn't complain:
```
sigjmp_buf *save_exception_stack = PG_exception_stack;
sigjmp_buf local_sigjmp_buf;

if (sigsetjmp(local_sigjmp_buf, 0) == 0)
  29:   48 8d 44 24 20  lea0x20(%rsp),%rax
  2e:   48 89 44 24 08  mov%rax,0x8(%rsp)
...
sigjmp_buf *save_exception_stack = PG_exception_stack;
  3c:   48 8b 1d 00 00 00 00mov0x0(%rip),%rbx# 43

  43:   48 89 5c 24 18  mov%rbx,0x18(%rsp)
```

I guess it might be an optimization regression of gcc, it was always smart
enough to reorder the local variables to avoid this issue (initializing them
after setjmp() obviously has no such issue because it will be initialized as we
wish after longjmp() wherever anyway), but higher version gcc's updates lost
the optimization in some cases.