https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120987

--- Comment #10 from Tom de Vries <vries at gcc dot gnu.org> ---
(In reply to Tom de Vries from comment #4)
> and then rethrown:
> ...
>       if (file_exception.reason < 0)
>         throw_exception (std::move (file_exception));
> ...
> 
> The gdb_exception class contains a message member:
> ...
>   std::shared_ptr<std::string> message;
> ...
> and the std::move should leave file_exception.message in a "valid but
> unspecified state" but gcc seems optimize that away.

Let's look at this in a bit more detail, at "-O0 -g".

We set a breakpoint at the line containing throw_exception, and run to it.

At that point, message is:
...
(gdb) p file_exception.message
$2 = std::shared_ptr<std::__cxx11::basic_string<char, std::char_traits<char>, s
td::allocator<char> >> (use count 1, weak count 0) = {get() = 0x1371640}
...

We step into throw_exception, until here:
...
      188   else if (exception.reason == RETURN_ERROR)
  >   189     throw gdb_exception_error (std::move (exception));
...

Then step into gdb_exception_error constructor:
...
      280   explicit gdb_exception_error (gdb_exception &&ex) noexcept
  >   281     : gdb_exception (std::move (ex))       
...

Then into gdb_exception constructor:
...
  >   144   explicit gdb_exception (gdb_exception &&other) noexcept = default
...

Then into shared_ptr constructor:
...
      358       shared_ptr(shared_ptr&& __r) noexcept
  >   359       : __shared_ptr<_Tp>(std::move(__r)) { }
...

Then into __shared_ptr constructor:
...
│     1532       __shared_ptr(__shared_ptr&& __r) noexcept                    │
│  >  1533       : _M_ptr(__r._M_ptr), _M_refcount()                          │
│     1534       {                                                            │
│     1535         _M_refcount._M_swap(__r._M_refcount);                      │
│     1536         __r._M_ptr = nullptr;                                      │
│     1537       }                                                            │
...

When entering this function, file_exception.message still has the same value.

After the swap, we have:
...
(gdb) p file_exception.message
$10 = std::shared_ptr<std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char> >> (empty) = {get() = 0x1371640}
(gdb) 
...
and after the nullptr assignment we have:
...
gdb) p file_exception.message
$12 = std::shared_ptr<std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char> >> (empty) = {get() = 0x0}
...

Now with "-O2 -flto=auto".

We start out with:
...
(gdb) p file_exception.message
$2 = std::shared_ptr<std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char> >> (use count 1, weak count 0) = {get() = <optimized out>}
...

We step into throw_exception, then gdb_exception_error constructor, then
gdb_exception constructor, then shared_ptr constructor, then __shared_ptr
constructor.  The code is scattered by lto, so I stepi through it.

Finally, we reach __cxa_throw.

At that point, file_exception.message is still the same (though the optimized
out part may have changed):
...
(gdb) p file_exception.message
$21 = std::shared_ptr<std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char> >> (use count 1, weak count 0) = {
  get() = <optimized out>}
...
but the use count should have been 0 at that point.

Looking at the first argument of __cxa_throw, the construction of the exception
object went ok:
...
(gdb) p /x $rdi
$23 = 0xe145b0
(gdb) p  ((gdb_exception *)0xe145b0)->message
$24 = std::shared_ptr<std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char> >> (use count 1, weak count 0) = {get() = 0xe14620}
(gdb) p  *((gdb_exception *)0xe145b0)->message
$25 = "No symbol table is loaded.  Use the \"file\" command."
...

Reply via email to