diff --git a/gdb/frame.c b/gdb/frame.c index cefdde5ed1e..e7974060cb8 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -2190,15 +2190,18 @@ reinit_frame_cache (void) sentinel_frame = nullptr; } + /* Invalidation copies the frame-id from the managed frame_info object + into the frame_info_ptr, so this must run before the frame_info + objects are invalidated. */ + for (frame_info_ptr &iter : frame_info_ptr::frame_list) + iter.invalidate (); + frame_stash_invalidate (); /* Since we can't really be sure what the first object allocated was. */ obstack_free (&frame_cache_obstack, 0); obstack_init (&frame_cache_obstack); - for (frame_info_ptr &iter : frame_info_ptr::frame_list) - iter.invalidate (); - frame_debug_printf ("generation=%d", frame_cache_generation); } @@ -3436,9 +3439,23 @@ frame_info_ptr::frame_info_ptr (struct frame_info *ptr) return; m_cached_level = ptr->level; +} +void +frame_info_ptr::invalidate () +{ + if (m_ptr == nullptr) + return; + + gdb_assert (m_cached_level == m_ptr->level); + + /* If a frame_info_ptr is invalidated multiple times then we will end up + updating m_cached_id multiple times. This should be harmless as the + underlying frame_id should never change. */ if (m_cached_level != 0 || m_ptr->this_id.value.user_created_p) m_cached_id = m_ptr->this_id.value; + + m_ptr = nullptr; } /* See frame-info-ptr.h. */ diff --git a/gdb/frame.h b/gdb/frame.h index f6553fb7b6d..b386303d895 100644 --- a/gdb/frame.h +++ b/gdb/frame.h @@ -327,10 +327,7 @@ public: } /* Invalidate this pointer. */ - void invalidate () - { - m_ptr = nullptr; - } + void invalidate (); private: /* We sometimes need to construct frame_info_ptr objects around the diff --git a/gdb/testsuite/gdb.python/pretty-print-call-by-hand.exp b/gdb/testsuite/gdb.python/pretty-print-call-by-hand.exp index 52162fc9952..a2a29c4d0f8 100644 --- a/gdb/testsuite/gdb.python/pretty-print-call-by-hand.exp +++ b/gdb/testsuite/gdb.python/pretty-print-call-by-hand.exp @@ -108,6 +108,8 @@ with_test_prefix "frame movement down" { with_test_prefix "frame movement up" { if { [start_test "TAG: final frame"] == 0 } { gdb_test "up" [multi_line "#1 .*in g \\(mt=mytype is .*\\, depth=1\\).*" ".*first frame.*"] + gdb_test "p f ()" " = 2" + gdb_test "frame" [multi_line "#1 .*in g \\(mt=mytype is .*\\, depth=1\\).*" ".*first frame.*"] } }