diagnostics: introduce class diagnostic_option_classifier

This patch gathers the 6 fields in diagnostic_context relating to
keeping track of overriding the severity of warnings, and
pushing/popping those severities, moving them all into a new class
diagnostic_option_classifier.

No functional change intended.

gcc/ChangeLog:
	* diagnostic.cc (diagnostic_context::push_diagnostics): Convert
	to...
	(diagnostic_option_classifier::push): ...this.
	(diagnostic_context::pop_diagnostics): Convert to...
	(diagnostic_option_classifier::pop): ...this.
	(diagnostic_context::initialize): Move code to...
	(diagnostic_option_classifier::init): ...this new function.
	(diagnostic_context::finish): Move code to...
	(diagnostic_option_classifier::fini): ...this new function.
	(diagnostic_context::classify_diagnostic): Convert to...
	(diagnostic_option_classifier::classify_diagnostic): ...this.
	(diagnostic_context::update_effective_level_from_pragmas): Convert
	to...
	(diagnostic_option_classifier::update_effective_level_from_pragmas):
	...this.
	(diagnostic_context::diagnostic_enabled): Update for refactoring.
	* diagnostic.h (struct diagnostic_classification_change_t): Move into...
	(class diagnostic_option_classifier): ...this new class.
	(diagnostic_context::option_unspecified_p): Update for move of
	fields into m_option_classifier.
	(diagnostic_context::classify_diagnostic): Likewise.
	(diagnostic_context::push_diagnostics): Likewise.
	(diagnostic_context::pop_diagnostics): Likewise.
	(diagnostic_context::update_effective_level_from_pragmas): Delete.
	(diagnostic_context::m_classify_diagnostic): Move into class
	diagnostic_option_classifier.
	(diagnostic_context::m_option_classifier): Likewise.
	(diagnostic_context::m_classification_history): Likewise.
	(diagnostic_context::m_n_classification_history): Likewise.
	(diagnostic_context::m_push_list): Likewise.
	(diagnostic_context::m_n_push): Likewise.
	(diagnostic_context::m_option_classifier): New.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
This commit is contained in:
David Malcolm 2023-11-06 14:28:41 -05:00
parent a526cc6ff3
commit 38763e2c18
2 changed files with 163 additions and 92 deletions

View file

@ -149,13 +149,63 @@ diagnostic_set_caret_max_width (diagnostic_context *context, int value)
context->m_source_printing.max_width = value;
}
void
diagnostic_option_classifier::init (int n_opts)
{
m_n_opts = n_opts;
m_classify_diagnostic = XNEWVEC (diagnostic_t, n_opts);
for (int i = 0; i < n_opts; i++)
m_classify_diagnostic[i] = DK_UNSPECIFIED;
m_push_list = nullptr;
m_n_push = 0;
}
void
diagnostic_option_classifier::fini ()
{
XDELETEVEC (m_classify_diagnostic);
m_classify_diagnostic = nullptr;
free (m_push_list);
m_n_push = 0;
}
/* Save all diagnostic classifications in a stack. */
void
diagnostic_option_classifier::push ()
{
m_push_list = (int *) xrealloc (m_push_list, (m_n_push + 1) * sizeof (int));
m_push_list[m_n_push ++] = m_n_classification_history;
}
/* Restore the topmost classification set off the stack. If the stack
is empty, revert to the state based on command line parameters. */
void
diagnostic_option_classifier::pop (location_t where)
{
int jump_to;
if (m_n_push)
jump_to = m_push_list [-- m_n_push];
else
jump_to = 0;
const int i = m_n_classification_history;
m_classification_history =
(diagnostic_classification_change_t *) xrealloc (m_classification_history, (i + 1)
* sizeof (diagnostic_classification_change_t));
m_classification_history[i].location = where;
m_classification_history[i].option = jump_to;
m_classification_history[i].kind = DK_POP;
m_n_classification_history ++;
}
/* Initialize the diagnostic message outputting machinery. */
void
diagnostic_context::initialize (int n_opts)
{
int i;
/* Allocate a basic pretty-printer. Clients will replace this a
much more elaborated pretty-printer if they wish. */
this->printer = XNEW (pretty_printer);
@ -165,12 +215,10 @@ diagnostic_context::initialize (int n_opts)
memset (m_diagnostic_count, 0, sizeof m_diagnostic_count);
m_warning_as_error_requested = false;
m_n_opts = n_opts;
m_classify_diagnostic = XNEWVEC (diagnostic_t, n_opts);
for (i = 0; i < n_opts; i++)
m_classify_diagnostic[i] = DK_UNSPECIFIED;
m_option_classifier.init (n_opts);
m_source_printing.enabled = false;
diagnostic_set_caret_max_width (this, pp_line_cutoff (this->printer));
for (i = 0; i < rich_location::STATICALLY_ALLOCATED_RANGES; i++)
for (int i = 0; i < rich_location::STATICALLY_ALLOCATED_RANGES; i++)
m_source_printing.caret_chars[i] = '^';
m_show_cwe = false;
m_show_rules = false;
@ -326,8 +374,7 @@ diagnostic_context::finish ()
delete m_file_cache;
m_file_cache = nullptr;
XDELETEVEC (m_classify_diagnostic);
m_classify_diagnostic = nullptr;
m_option_classifier.fini ();
/* diagnostic_context::initialize allocates this->printer using XNEW
and placement-new. */
@ -1052,9 +1099,11 @@ default_diagnostic_finalizer (diagnostic_context *context,
range. If OPTION_INDEX is zero, the new setting is for all the
diagnostics. */
diagnostic_t
diagnostic_context::classify_diagnostic (int option_index,
diagnostic_t new_kind,
location_t where)
diagnostic_option_classifier::
classify_diagnostic (const diagnostic_context *context,
int option_index,
diagnostic_t new_kind,
location_t where)
{
diagnostic_t old_kind;
@ -1074,10 +1123,10 @@ diagnostic_context::classify_diagnostic (int option_index,
/* Record the command-line status, so we can reset it back on DK_POP. */
if (old_kind == DK_UNSPECIFIED)
{
old_kind = !m_option_enabled (option_index,
m_lang_mask,
m_option_state)
? DK_IGNORED : (m_warning_as_error_requested
old_kind = !context->m_option_enabled (option_index,
context->m_lang_mask,
context->m_option_state)
? DK_IGNORED : (context->warning_as_error_requested_p ()
? DK_ERROR : DK_WARNING);
m_classify_diagnostic[option_index] = old_kind;
}
@ -1104,37 +1153,6 @@ diagnostic_context::classify_diagnostic (int option_index,
return old_kind;
}
/* Save all diagnostic classifications in a stack. */
void
diagnostic_context::push_diagnostics (location_t where ATTRIBUTE_UNUSED)
{
m_push_list = (int *) xrealloc (m_push_list, (m_n_push + 1) * sizeof (int));
m_push_list[m_n_push ++] = m_n_classification_history;
}
/* Restore the topmost classification set off the stack. If the stack
is empty, revert to the state based on command line parameters. */
void
diagnostic_context::pop_diagnostics (location_t where)
{
int jump_to;
int i;
if (m_n_push)
jump_to = m_push_list [-- m_n_push];
else
jump_to = 0;
i = m_n_classification_history;
m_classification_history =
(diagnostic_classification_change_t *) xrealloc (m_classification_history, (i + 1)
* sizeof (diagnostic_classification_change_t));
m_classification_history[i].location = where;
m_classification_history[i].option = jump_to;
m_classification_history[i].kind = DK_POP;
m_n_classification_history ++;
}
/* Helper function for print_parseable_fixits. Print TEXT to PP, obeying the
escaping rules for -fdiagnostics-parseable-fixits. */
@ -1246,14 +1264,14 @@ diagnostic_context::get_any_inlining_info (diagnostic_info *diagnostic)
/* Update the kind of DIAGNOSTIC based on its location(s), including
any of those in its inlining stack, relative to any
#pragma GCC diagnostic
directives recorded within CONTEXT.
directives recorded within this object.
Return the new kind of DIAGNOSTIC if it was updated, or DK_UNSPECIFIED
otherwise. */
diagnostic_t
diagnostic_context::
update_effective_level_from_pragmas (diagnostic_info *diagnostic)
diagnostic_option_classifier::
update_effective_level_from_pragmas (diagnostic_info *diagnostic) const
{
if (m_n_classification_history <= 0)
return DK_UNSPECIFIED;
@ -1444,14 +1462,14 @@ diagnostic_context::diagnostic_enabled (diagnostic_info *diagnostic)
return false;
/* This tests for #pragma diagnostic changes. */
diagnostic_t diag_class = update_effective_level_from_pragmas (diagnostic);
diagnostic_t diag_class
= m_option_classifier.update_effective_level_from_pragmas (diagnostic);
/* This tests if the user provided the appropriate -Werror=foo
option. */
if (diag_class == DK_UNSPECIFIED
&& (m_classify_diagnostic[diagnostic->option_index]
!= DK_UNSPECIFIED))
diagnostic->kind = m_classify_diagnostic[diagnostic->option_index];
&& !option_unspecified_p (diagnostic->option_index))
diagnostic->kind = m_option_classifier.get_current_override (diagnostic->option_index);
/* This allows for future extensions, like temporarily disabling
warnings for ranges of source code. */

View file

@ -168,16 +168,6 @@ struct diagnostic_info
} m_iinfo;
};
/* Each time a diagnostic's classification is changed with a pragma,
we record the change and the location of the change in an array of
these structs. */
struct diagnostic_classification_change_t
{
location_t location;
int option;
diagnostic_t kind;
};
/* Forward declarations. */
typedef void (*diagnostic_starter_fn) (diagnostic_context *,
diagnostic_info *);
@ -240,6 +230,79 @@ public:
void on_diagram (const diagnostic_diagram &diagram) override;
};
/* A stack of sets of classifications: each entry in the stack is
a mapping from option index to diagnostic severity that can be changed
via pragmas. The stack can be pushed and popped. */
class diagnostic_option_classifier
{
public:
void init (int n_opts);
void fini ();
/* Save all diagnostic classifications in a stack. */
void push ();
/* Restore the topmost classification set off the stack. If the stack
is empty, revert to the state based on command line parameters. */
void pop (location_t where);
bool option_unspecified_p (int opt) const
{
return get_current_override (opt) == DK_UNSPECIFIED;
}
diagnostic_t get_current_override (int opt) const
{
gcc_assert (opt < m_n_opts);
return m_classify_diagnostic[opt];
}
diagnostic_t
classify_diagnostic (const diagnostic_context *context,
int option_index,
diagnostic_t new_kind,
location_t where);
diagnostic_t
update_effective_level_from_pragmas (diagnostic_info *diagnostic) const;
private:
/* Each time a diagnostic's classification is changed with a pragma,
we record the change and the location of the change in an array of
these structs. */
struct diagnostic_classification_change_t
{
location_t location;
int option;
diagnostic_t kind;
};
int m_n_opts;
/* For each option index that can be passed to warning() et al
(OPT_* from options.h when using this code with the core GCC
options), this array may contain a new kind that the diagnostic
should be changed to before reporting, or DK_UNSPECIFIED to leave
it as the reported kind, or DK_IGNORED to not report it at
all. */
diagnostic_t *m_classify_diagnostic;
/* History of all changes to the classifications above. This list
is stored in location-order, so we can search it, either
binary-wise or end-to-front, to find the most recent
classification for a given diagnostic, given the location of the
diagnostic. */
diagnostic_classification_change_t *m_classification_history;
/* The size of the above array. */
int m_n_classification_history;
/* For pragma push/pop. */
int *m_push_list;
int m_n_push;
};
/* This data structure bundles altogether any information relevant to
the context of a diagnostic message. */
class diagnostic_context
@ -273,8 +336,7 @@ public:
bool option_unspecified_p (int opt) const
{
gcc_assert (opt < m_n_opts);
return m_classify_diagnostic[opt] == DK_UNSPECIFIED;
return m_option_classifier.option_unspecified_p (opt);
}
bool report_diagnostic (diagnostic_info *);
@ -287,9 +349,22 @@ public:
diagnostic_t
classify_diagnostic (int option_index,
diagnostic_t new_kind,
location_t where);
void push_diagnostics (location_t where ATTRIBUTE_UNUSED);
void pop_diagnostics (location_t where);
location_t where)
{
return m_option_classifier.classify_diagnostic (this,
option_index,
new_kind,
where);
}
void push_diagnostics (location_t where ATTRIBUTE_UNUSED)
{
m_option_classifier.push ();
}
void pop_diagnostics (location_t where)
{
m_option_classifier.pop (where);
}
void emit_diagram (const diagnostic_diagram &diagram);
@ -376,9 +451,6 @@ private:
bool diagnostic_enabled (diagnostic_info *diagnostic);
void get_any_inlining_info (diagnostic_info *diagnostic);
diagnostic_t
update_effective_level_from_pragmas (diagnostic_info *diagnostic);
/* Data members.
Ideally, all of these would be private and have "m_" prefixes. */
@ -401,27 +473,8 @@ private:
al. */
int m_n_opts;
/* For each option index that can be passed to warning() et al
(OPT_* from options.h when using this code with the core GCC
options), this array may contain a new kind that the diagnostic
should be changed to before reporting, or DK_UNSPECIFIED to leave
it as the reported kind, or DK_IGNORED to not report it at
all. */
diagnostic_t *m_classify_diagnostic;
/* History of all changes to the classifications above. This list
is stored in location-order, so we can search it, either
binary-wise or end-to-front, to find the most recent
classification for a given diagnostic, given the location of the
diagnostic. */
diagnostic_classification_change_t *m_classification_history;
/* The size of the above array. */
int m_n_classification_history;
/* For pragma push/pop. */
int *m_push_list;
int m_n_push;
/* The stack of sets of overridden diagnostic option severities. */
diagnostic_option_classifier m_option_classifier;
/* True if we should print any CWE identifiers associated with
diagnostics. */