[Bug c++/109470] unexpected const & behavior

2023-04-11 Thread redi at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109470

--- Comment #8 from Jonathan Wakely  ---
No, "full-expression" is a formal term defined very precisely in the C++
standard. There is no opportunity for GCC to review that without failing to
conform to the C++ standard. Changing when temporary objects are destroyed
would be a massive breaking change to the C++ language that would break
assumptions made by correct code.

Just because you don't get a warning with other compilers, doesn't mean your
code is correct. The code accesses an object outside its lifetime, and so has
undefined behaviour. That is true with all compilers.

Clang gives a runtime error with -fsanitize=address e.g.
https://godbolt.org/z/dhcEhvzze

That's because the program has undefined behaviour. This is not just GCC's
interpretation of the C++ standard, it's a fact.

[Bug c++/109470] unexpected const & behavior

2023-04-11 Thread jakub at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109470

Jakub Jelinek  changed:

   What|Removed |Added

 CC||jakub at gcc dot gnu.org

--- Comment #7 from Jakub Jelinek  ---
You can use -fsanitize=address to get such bugs diagnosed at runtime:
g++ -fsanitize=address -o /tmp/pr109470{,.C} -g; /tmp/pr109470
=
==2466554==ERROR: AddressSanitizer: stack-use-after-scope on address
0x7ffe08313d80 at pc 0x00401304 bp 0x7ffe08313d20 sp 0x7ffe08313d18
READ of size 4 at 0x7ffe08313d80 thread T0
#0 0x401303 in main /tmp/pr109470.C:17
#1 0x7f5b06f7958f in __libc_start_call_main (/lib64/libc.so.6+0x2958f)
#2 0x7f5b06f79648 in __libc_start_main@GLIBC_2.2.5
(/lib64/libc.so.6+0x29648)
#3 0x4010e4 in _start (/tmp/pr109470+0x4010e4)

Address 0x7ffe08313d80 is located in stack of thread T0 at offset 64 in frame
#0 0x4011b5 in main /tmp/pr109470.C:12

  This frame has 2 object(s):
[48, 52) 'MAX' (line 14)
[64, 68) '' <== Memory access at offset 64 is inside this variable
HINT: this may be a false positive if your program uses some custom stack
unwind mechanism, swapcontext or vfork
  (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-use-after-scope /tmp/pr109470.C:17 in main
Shadow bytes around the buggy address:
  0x10004105a760: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10004105a770: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10004105a780: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10004105a790: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10004105a7a0: 00 00 00 00 00 00 00 00 f1 f1 f1 f1 f1 f1 04 f2
=>0x10004105a7b0:[f8]f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00
  0x10004105a7c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10004105a7d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10004105a7e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10004105a7f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10004105a800: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:   00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:   fa
  Freed heap region:   fd
  Stack left redzone:  f1
  Stack mid redzone:   f2
  Stack right redzone: f3
  Stack after return:  f5
  Stack use after scope:   f8
  Global redzone:  f9
  Global init order:   f6
  Poisoned by user:f7
  Container overflow:  fc
  Array cookie:ac
  Intra object redzone:bb
  ASan internal:   fe
  Left alloca redzone: ca
  Right alloca redzone:cb
==2466554==ABORTING

C++ has always behaved like this and changing it would significantly penalize
all the code in the wild that uses C++ correctly.  There are some exceptions
where the lifetime is extended, but is certainly not one of them.

[Bug c++/109470] unexpected const & behavior

2023-04-11 Thread johannes.kellner at wandelbots dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109470

--- Comment #6 from Johannes Kellner  
---
Ok, Ok :)
It's not to me to argue this.

It's just an unexpected behavior (something I was unaware off/ something that
does not happen when doing the same code with other compilers clang/msvc).

And in my humble opinion - `full-expression containing the call` could be
understood as - until end of enclosing scope.
Or at least if understood this way, I would not have the uninitialized variable
:)

I just had a stupid error and found this as the reason. We discussed it and
even others in my team, assumed that it might be a bug. As we were not able to
reproduce this behavior in other compilers we tested.
Nor did see this as `invalid` code - `ugly` yes, but not `invalid`. And yes,
this code is 'not the best possible way'...

Well maybe you take this ticket as a reason to `review` the interpretation,
that `full-expression containing the call` does not mean until the `end of
enclosing scope`...

For me, I'm fine with current outcome.
Thank you anyway for the quick, very friendly and professional responses!

Best regards

[Bug c++/109470] unexpected const & behavior

2023-04-11 Thread redi at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109470

--- Comment #5 from Jonathan Wakely  ---
(In reply to Johannes Kellner from comment #3)
> 'A temporary object bound to a reference parameter in a function call
> persists until the completion of the full-expression containing the call.'
> 
> So this does not mean, that the temporary object, (int)lenght, should life
> until the end of main ??? As main() is the enclosing scope?

No, because it says "completion of the full-expression" not "end of the
enclosing scope".

The full-expression ends at the semi-colon.

[Bug c++/109470] unexpected const & behavior

2023-04-11 Thread pinskia at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109470

Andrew Pinski  changed:

   What|Removed |Added

 Resolution|--- |INVALID
 Status|UNCONFIRMED |RESOLVED

--- Comment #4 from Andrew Pinski  ---
The function call in this case is Min.

So after the semicolon of the definition of dst, the temp is destroyed.

[Bug c++/109470] unexpected const & behavior

2023-04-11 Thread johannes.kellner at wandelbots dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109470

Johannes Kellner  changed:

   What|Removed |Added

 Resolution|INVALID |---
 Status|RESOLVED|UNCONFIRMED

--- Comment #3 from Johannes Kellner  
---
'A temporary object bound to a reference parameter in a function call persists
until the completion of the full-expression containing the call.'

So this does not mean, that the temporary object, (int)lenght, should life
until the end of main ??? As main() is the enclosing scope?

[Bug c++/109470] unexpected const & behavior

2023-04-11 Thread xry111 at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109470

--- Comment #2 from Xi Ruoyao  ---
With "-Wall -O1" this is diagnosed properly, but with a spurious
maybe-uninitialized warning:

In file included from /usr/include/c++/12.2.0/cassert:44,
 from t.c:2:
t.c: In function 'int main()':
t.c:17:11: warning: dangling pointer 'dst' to an unnamed temporary may be used
[-Wdangling-pointer=]
   17 |assert(dst <= MAX);
  |   ^~~
t.c:16:24: note: unnamed temporary defined here
   16 |const int& dst = Min(MAX, (int)lenght);
  | ~~~^~
t.c:16:24: warning: '' may be used uninitialized
[-Wmaybe-uninitialized]

With "-Wall -O2" only the spurious maybe-uninitialized warning is emitted,
which is not very helpful.

With "-Wall -O0" no warning at all (diagnosing this issue at least needs some
IPA).

[Bug c++/109470] unexpected const & behavior

2023-04-11 Thread xry111 at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109470

Xi Ruoyao  changed:

   What|Removed |Added

 CC||xry111 at gcc dot gnu.org
 Resolution|--- |INVALID
 Status|UNCONFIRMED |RESOLVED

--- Comment #1 from Xi Ruoyao  ---
The standard says:

A temporary object bound to a reference parameter in a function call persists
until the completion of the full-expression containing the call.

So at the "assert" line the lifetime of the temporary object created by the
prvalue to glvalue materialization of (int)lenght has already ended.  Any
reference to the temporary is dangling and it's undefined behavior to use such
a reference.