m_diagnostic_groups.m_group_nesting_depth = 0;
m_diagnostic_groups.m_diagnostic_nesting_level = 0;
m_diagnostic_groups.m_emission_count = 0;
+ m_diagnostic_groups.m_inhibiting_notes_from = 0;
m_output_sinks.safe_push
(new diagnostic_text_output_format (*this, nullptr, true));
m_set_locations_cb = nullptr;
/* Take any action which is expected to happen after the diagnostic
is written out. This function does not always return. */
+
void
diagnostic_context::action_after_output (diagnostic_t diag_kind)
{
}
}
+/* State whether we should inhibit notes in the current diagnostic_group and
+ its future children if any. */
+
+void
+diagnostic_context::inhibit_notes_in_group (bool inhibit)
+{
+ int curr_depth = (m_diagnostic_groups.m_group_nesting_depth
+ + m_diagnostic_groups.m_diagnostic_nesting_level);
+
+ if (inhibit)
+ {
+ /* If we're already inhibiting, there's nothing to do. */
+ if (m_diagnostic_groups.m_inhibiting_notes_from)
+ return;
+
+ /* Since we're called via warning/error/... that all have their own
+ diagnostic_group, we must consider that we started inhibiting in their
+ parent. */
+ gcc_assert (m_diagnostic_groups.m_group_nesting_depth > 0);
+ m_diagnostic_groups.m_inhibiting_notes_from = curr_depth - 1;
+ }
+ else if (m_diagnostic_groups.m_inhibiting_notes_from)
+ {
+ /* Only cancel inhibition at the depth that set it up. */
+ if (curr_depth >= m_diagnostic_groups.m_inhibiting_notes_from)
+ return;
+
+ m_diagnostic_groups.m_inhibiting_notes_from = 0;
+ }
+}
+
+/* Return whether notes must be inhibited in the current diagnostic_group. */
+
+bool
+diagnostic_context::notes_inhibited_in_group () const
+{
+ if (m_diagnostic_groups.m_inhibiting_notes_from
+ && (m_diagnostic_groups.m_group_nesting_depth
+ + m_diagnostic_groups.m_diagnostic_nesting_level
+ >= m_diagnostic_groups.m_inhibiting_notes_from))
+ return true;
+ return false;
+}
+
/* class logical_location. */
/* Return true iff this is a function or method. */
bool was_warning = (diagnostic->kind == DK_WARNING
|| diagnostic->kind == DK_PEDWARN);
if (was_warning && m_inhibit_warnings)
- return false;
+ {
+ inhibit_notes_in_group ();
+ return false;
+ }
if (m_adjust_diagnostic_info)
m_adjust_diagnostic_info (this, diagnostic);
not disabled by #pragma GCC diagnostic anywhere along the inlining
stack. . */
if (!diagnostic_enabled (diagnostic))
- return false;
+ {
+ inhibit_notes_in_group ();
+ return false;
+ }
if ((was_warning || diagnostic->kind == DK_WARNING)
&& ((!m_warn_system_headers
inlining stack (if there is one) are in system headers. */
return false;
+ if (diagnostic->kind == DK_NOTE && notes_inhibited_in_group ())
+ /* Bail for all the notes in the diagnostic_group that started to inhibit notes. */
+ return false;
+
if (diagnostic->kind != DK_NOTE && diagnostic->kind != DK_ICE)
check_max_errors (false);
error_recursion ();
}
+ /* We are accepting the diagnostic, so should stop inhibiting notes. */
+ inhibit_notes_in_group (/*inhibit=*/false);
+
m_lock++;
if (diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
sink->on_end_group ();
m_diagnostic_groups.m_emission_count = 0;
}
+ /* We're popping one level, so might need to stop inhibiting notes. */
+ inhibit_notes_in_group (/*inhibit=*/false);
}
void
diagnostic_context::pop_nesting_level ()
{
--m_diagnostic_groups.m_diagnostic_nesting_level;
+ /* We're popping one level, so might need to stop inhibiting notes. */
+ inhibit_notes_in_group (/*inhibit=*/false);
}
void
of the @code{auto_diagnostic_group} are related. For example,
@option{-fdiagnostics-format=json} will treat the first diagnostic
emitted within the group as a top-level diagnostic, and all subsequent
-diagnostics within the group as its children.
+diagnostics within the group as its children. Also, if a warning in the
+group is inhibited at nesting depth D, all subsequent notes at that depth
+or deeper will be inhibited as well, until an error or another warning
+is emitted, the depth decreases below D, or the group is popped.
@subsection Quoting
Text should be quoted by either using the @samp{q} modifier in a directive