/* The last file a line number was recorded for. */
struct subfile *m_last_subfile = NULL;
+ /* The address of the last line entry. */
+ CORE_ADDR m_last_address;
+
+ /* Set to true when a previous line at the same address (using
+ m_last_address) had m_is_stmt true. This is reset to false when a
+ line entry at a new address (m_address different to m_last_address) is
+ processed. */
+ bool m_stmt_at_address = false;
+
/* When true, record the lines we decode. */
bool m_currently_recording_lines = false;
fe->included_p = 1;
if (m_record_lines_p)
{
- if (m_last_subfile != m_cu->get_builder ()->get_current_subfile ()
- || end_sequence)
+ /* When we switch files we insert an end maker in the first file,
+ switch to the second file and add a new line entry. The
+ problem is that the end marker inserted in the first file will
+ discard any previous line entries at the same address. If the
+ line entries in the first file are marked as is-stmt, while
+ the new line in the second file is non-stmt, then this means
+ the end marker will discard is-stmt lines so we can have a
+ non-stmt line. This means that there are less addresses at
+ which the user can insert a breakpoint.
+
+ To improve this we track the last address in m_last_address,
+ and whether we have seen an is-stmt at this address. Then
+ when switching files, if we have seen a stmt at the current
+ address, and we are switching to create a non-stmt line, then
+ discard the new line. */
+ bool file_changed
+ = m_last_subfile != m_cu->get_builder ()->get_current_subfile ();
+ bool ignore_this_line
+ = (file_changed && !end_sequence && m_last_address == m_address
+ && !m_is_stmt && m_stmt_at_address);
+
+ if ((file_changed && !ignore_this_line) || end_sequence)
{
dwarf_finish_line (m_gdbarch, m_last_subfile, m_address,
m_currently_recording_lines ? m_cu : nullptr);
}
- if (!end_sequence)
+ if (!end_sequence && !ignore_this_line)
{
bool is_stmt = producer_is_codewarrior (m_cu) || m_is_stmt;
}
}
}
+
+ /* Track whether we have seen any m_is_stmt true at m_address in case we
+ have multiple line table entries all at m_address. */
+ if (m_last_address != m_address)
+ {
+ m_stmt_at_address = false;
+ m_last_address = m_address;
+ }
+ m_stmt_at_address |= m_is_stmt;
}
lnp_state_machine::lnp_state_machine (struct dwarf2_cu *cu, gdbarch *arch,
m_address = gdbarch_adjust_dwarf2_line (arch, 0, 0);
m_is_stmt = lh->default_is_stmt;
m_discriminator = 0;
+
+ m_last_address = m_address;
+ m_stmt_at_address = false;
}
void