No functional change intended.
gcc/ChangeLog:
* Makefile.in (OBJS-libcommon): Add
diagnostics/option-classifier.o.
* diagnostic.cc (diagnostics::option_classifier::init): Move to
diagnostics/option-classifier.cc.
(diagnostics::option_classifier::fini): Likewise.
(diagnostics::option_classifier::pch_save): Likewise.
(diagnostics::option_classifier::pch_restore): Likewise.
(diagnostics::option_classifier::push): Likewise.
(diagnostics::option_classifier::pop): Likewise.
(diagnostics::option_classifier::classify_diagnostic): Likewise.
(diagnostics::option_classifier::update_effective_level_from_pragmas):
Likewise.
* diagnostics/context.h: Include
"diagnostics/option-classifier.h".
(class option_classifier): Move to
diagnostics/option-classifier.h.
* diagnostics/option-classifier.cc: New file, based on material
from diagnostic.cc.
* diagnostics/option-classifier.h: New file, based on material
from diagnostics/context.h.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
diagnostics/sarif-sink.o \
diagnostics/text-sink.o \
diagnostics/macro-unwinding.o \
+ diagnostics/option-classifier.o \
diagnostics/paths.o \
diagnostics/paths-output.o \
diagnostics/source-printing.o \
context->m_source_printing.max_width = value;
}
-void
-diagnostics::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 = vNULL;
- m_classification_history = vNULL;
-}
-
-void
-diagnostics::option_classifier::fini ()
-{
- XDELETEVEC (m_classify_diagnostic);
- m_classify_diagnostic = nullptr;
- m_classification_history.release ();
- m_push_list.release ();
-}
-
-/* Save the diagnostics::option_classifier state to F for PCH
- output. Returns 0 on success, -1 on error. */
-
-int
-diagnostics::option_classifier::pch_save (FILE *f)
-{
- unsigned int lengths[2] = { m_classification_history.length (),
- m_push_list.length () };
- if (fwrite (lengths, sizeof (lengths), 1, f) != 1
- || (lengths[0]
- && fwrite (m_classification_history.address (),
- sizeof (classification_change_t),
- lengths[0], f) != lengths[0])
- || (lengths[1]
- && fwrite (m_push_list.address (), sizeof (int),
- lengths[1], f) != lengths[1]))
- return -1;
- return 0;
-}
-
-/* Read the diagnostics::option_classifier state from F for PCH
- read. Returns 0 on success, -1 on error. */
-
-int
-diagnostics::option_classifier::pch_restore (FILE *f)
-{
- unsigned int lengths[2];
- if (fread (lengths, sizeof (lengths), 1, f) != 1)
- return -1;
- gcc_checking_assert (m_classification_history.is_empty ());
- gcc_checking_assert (m_push_list.is_empty ());
- m_classification_history.safe_grow (lengths[0]);
- m_push_list.safe_grow (lengths[1]);
- if ((lengths[0]
- && fread (m_classification_history.address (),
- sizeof (classification_change_t),
- lengths[0], f) != lengths[0])
- || (lengths[1]
- && fread (m_push_list.address (), sizeof (int),
- lengths[1], f) != lengths[1]))
- return -1;
- return 0;
-}
-
-/* Save all diagnostic classifications in a stack. */
-
-void
-diagnostics::option_classifier::push ()
-{
- m_push_list.safe_push (m_classification_history.length ());
-}
-
-/* Restore the topmost classification set off the stack. If the stack
- is empty, revert to the state based on command line parameters. */
-
-void
-diagnostics::option_classifier::pop (location_t where)
-{
- int jump_to;
-
- if (!m_push_list.is_empty ())
- jump_to = m_push_list.pop ();
- else
- jump_to = 0;
-
- classification_change_t v = { where, jump_to, DK_POP };
- m_classification_history.safe_push (v);
-}
-
/* Initialize the diagnostic message outputting machinery. */
void
}
}
-/* Interface to specify diagnostic kind overrides. Returns the
- previous setting, or DK_UNSPECIFIED if the parameters are out of
- range. If OPTION_ID is zero, the new setting is for all the
- diagnostics. */
-diagnostic_t
-diagnostics::option_classifier::
-classify_diagnostic (const diagnostics::context *context,
- diagnostic_option_id option_id,
- diagnostic_t new_kind,
- location_t where)
-{
- diagnostic_t old_kind;
-
- if (option_id.m_idx < 0
- || option_id.m_idx >= m_n_opts
- || new_kind >= DK_LAST_DIAGNOSTIC_KIND)
- return DK_UNSPECIFIED;
-
- old_kind = m_classify_diagnostic[option_id.m_idx];
-
- /* Handle pragmas separately, since we need to keep track of *where*
- the pragmas were. */
- if (where != UNKNOWN_LOCATION)
- {
- unsigned i;
-
- /* Record the command-line status, so we can reset it back on DK_POP. */
- if (old_kind == DK_UNSPECIFIED)
- {
- old_kind = (!context->option_enabled_p (option_id)
- ? DK_IGNORED : DK_ANY);
- m_classify_diagnostic[option_id.m_idx] = old_kind;
- }
-
- classification_change_t *p;
- FOR_EACH_VEC_ELT_REVERSE (m_classification_history, i, p)
- if (p->option == option_id.m_idx)
- {
- old_kind = p->kind;
- break;
- }
-
- classification_change_t v
- = { where, option_id.m_idx, new_kind };
- m_classification_history.safe_push (v);
- }
- else
- m_classify_diagnostic[option_id.m_idx] = new_kind;
-
- return old_kind;
-}
-
/* Helper function for print_parseable_fixits. Print TEXT to PP, obeying the
escaping rules for -fdiagnostics-parseable-fixits. */
}
}
-/* 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 this object.
-
- Return the new kind of DIAGNOSTIC if it was updated, or DK_UNSPECIFIED
- otherwise. */
-
-diagnostic_t
-diagnostics::option_classifier::
-update_effective_level_from_pragmas (diagnostic_info *diagnostic) const
-{
- if (m_classification_history.is_empty ())
- return DK_UNSPECIFIED;
-
- /* Iterate over the locations, checking the diagnostic disposition
- for the diagnostic at each. If it's explicitly set as opposed
- to unspecified, update the disposition for this instance of
- the diagnostic and return it. */
- for (location_t loc: diagnostic->m_iinfo.m_ilocs)
- {
- /* FIXME: Stupid search. Optimize later. */
- unsigned int i;
- classification_change_t *p;
- FOR_EACH_VEC_ELT_REVERSE (m_classification_history, i, p)
- {
- location_t pragloc = p->location;
- if (!linemap_location_before_p (line_table, pragloc, loc))
- continue;
-
- if (p->kind == (int) DK_POP)
- {
- /* Move on to the next region. */
- i = p->option;
- continue;
- }
-
- diagnostic_option_id option = p->option;
- /* The option 0 is for all the diagnostics. */
- if (option == 0 || option == diagnostic->m_option_id)
- {
- diagnostic_t kind = p->kind;
- if (kind != DK_UNSPECIFIED)
- diagnostic->m_kind = kind;
- return kind;
- }
- }
- }
-
- return DK_UNSPECIFIED;
-}
-
/* Generate a URL string describing CWE. The caller is responsible for
freeing the string. */
#ifndef GCC_DIAGNOSTICS_CONTEXT_H
#define GCC_DIAGNOSTICS_CONTEXT_H
+#include "diagnostics/option-classifier.h"
+
namespace diagnostics {
/* Forward declarations. */
virtual char *make_option_url (diagnostic_option_id option_id) const = 0;
};
-/* 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 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 (diagnostic_option_id option_id) const
- {
- return get_current_override (option_id) == DK_UNSPECIFIED;
- }
-
- diagnostic_t get_current_override (diagnostic_option_id option_id) const
- {
- gcc_assert (option_id.m_idx < m_n_opts);
- return m_classify_diagnostic[option_id.m_idx];
- }
-
- diagnostic_t
- classify_diagnostic (const context *context,
- diagnostic_option_id option_id,
- diagnostic_t new_kind,
- location_t where);
-
- diagnostic_t
- update_effective_level_from_pragmas (diagnostic_info *diagnostic) const;
-
- int pch_save (FILE *);
- int pch_restore (FILE *);
-
-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 classification_change_t
- {
- location_t location;
-
- /* For DK_POP, this is the index of the corresponding push (as stored
- in m_push_list).
- Otherwise, this is an option index. */
- 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. */
- vec<classification_change_t> m_classification_history;
-
- /* For context::get_classification_history, declared later. */
- friend class context;
-
- /* For pragma push/pop. */
- vec<int> m_push_list;
-};
-
/* A bundle of options relating to printing the user's source code
(potentially with a margin, underlining, labels, etc). */
--- /dev/null
+/* Stacks of set of classifications of diagnostics.
+ Copyright (C) 1999-2025 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "version.h"
+#include "diagnostic.h"
+
+namespace diagnostics {
+
+void
+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 = vNULL;
+ m_classification_history = vNULL;
+}
+
+void
+option_classifier::fini ()
+{
+ XDELETEVEC (m_classify_diagnostic);
+ m_classify_diagnostic = nullptr;
+ m_classification_history.release ();
+ m_push_list.release ();
+}
+
+/* Save the diagnostics::option_classifier state to F for PCH
+ output. Returns 0 on success, -1 on error. */
+
+int
+option_classifier::pch_save (FILE *f)
+{
+ unsigned int lengths[2] = { m_classification_history.length (),
+ m_push_list.length () };
+ if (fwrite (lengths, sizeof (lengths), 1, f) != 1
+ || (lengths[0]
+ && fwrite (m_classification_history.address (),
+ sizeof (classification_change_t),
+ lengths[0], f) != lengths[0])
+ || (lengths[1]
+ && fwrite (m_push_list.address (), sizeof (int),
+ lengths[1], f) != lengths[1]))
+ return -1;
+ return 0;
+}
+
+/* Read the diagnostics::option_classifier state from F for PCH
+ read. Returns 0 on success, -1 on error. */
+
+int
+option_classifier::pch_restore (FILE *f)
+{
+ unsigned int lengths[2];
+ if (fread (lengths, sizeof (lengths), 1, f) != 1)
+ return -1;
+ gcc_checking_assert (m_classification_history.is_empty ());
+ gcc_checking_assert (m_push_list.is_empty ());
+ m_classification_history.safe_grow (lengths[0]);
+ m_push_list.safe_grow (lengths[1]);
+ if ((lengths[0]
+ && fread (m_classification_history.address (),
+ sizeof (classification_change_t),
+ lengths[0], f) != lengths[0])
+ || (lengths[1]
+ && fread (m_push_list.address (), sizeof (int),
+ lengths[1], f) != lengths[1]))
+ return -1;
+ return 0;
+}
+
+/* Save all diagnostic classifications in a stack. */
+
+void
+option_classifier::push ()
+{
+ m_push_list.safe_push (m_classification_history.length ());
+}
+
+/* Restore the topmost classification set off the stack. If the stack
+ is empty, revert to the state based on command line parameters. */
+
+void
+option_classifier::pop (location_t where)
+{
+ int jump_to;
+
+ if (!m_push_list.is_empty ())
+ jump_to = m_push_list.pop ();
+ else
+ jump_to = 0;
+
+ classification_change_t v = { where, jump_to, DK_POP };
+ m_classification_history.safe_push (v);
+}
+
+/* Interface to specify diagnostic kind overrides. Returns the
+ previous setting, or DK_UNSPECIFIED if the parameters are out of
+ range. If OPTION_ID is zero, the new setting is for all the
+ diagnostics. */
+
+diagnostic_t
+option_classifier::classify_diagnostic (const context *dc,
+ diagnostic_option_id option_id,
+ diagnostic_t new_kind,
+ location_t where)
+{
+ diagnostic_t old_kind;
+
+ if (option_id.m_idx < 0
+ || option_id.m_idx >= m_n_opts
+ || new_kind >= DK_LAST_DIAGNOSTIC_KIND)
+ return DK_UNSPECIFIED;
+
+ old_kind = m_classify_diagnostic[option_id.m_idx];
+
+ /* Handle pragmas separately, since we need to keep track of *where*
+ the pragmas were. */
+ if (where != UNKNOWN_LOCATION)
+ {
+ unsigned i;
+
+ /* Record the command-line status, so we can reset it back on DK_POP. */
+ if (old_kind == DK_UNSPECIFIED)
+ {
+ old_kind = (!dc->option_enabled_p (option_id)
+ ? DK_IGNORED : DK_ANY);
+ m_classify_diagnostic[option_id.m_idx] = old_kind;
+ }
+
+ classification_change_t *p;
+ FOR_EACH_VEC_ELT_REVERSE (m_classification_history, i, p)
+ if (p->option == option_id.m_idx)
+ {
+ old_kind = p->kind;
+ break;
+ }
+
+ classification_change_t v
+ = { where, option_id.m_idx, new_kind };
+ m_classification_history.safe_push (v);
+ }
+ else
+ m_classify_diagnostic[option_id.m_idx] = new_kind;
+
+ return old_kind;
+}
+
+/* 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 this object.
+
+ Return the new kind of DIAGNOSTIC if it was updated, or DK_UNSPECIFIED
+ otherwise. */
+
+diagnostic_t
+option_classifier::
+update_effective_level_from_pragmas (diagnostic_info *diagnostic) const
+{
+ if (m_classification_history.is_empty ())
+ return DK_UNSPECIFIED;
+
+ /* Iterate over the locations, checking the diagnostic disposition
+ for the diagnostic at each. If it's explicitly set as opposed
+ to unspecified, update the disposition for this instance of
+ the diagnostic and return it. */
+ for (location_t loc: diagnostic->m_iinfo.m_ilocs)
+ {
+ /* FIXME: Stupid search. Optimize later. */
+ unsigned int i;
+ classification_change_t *p;
+ FOR_EACH_VEC_ELT_REVERSE (m_classification_history, i, p)
+ {
+ location_t pragloc = p->location;
+ if (!linemap_location_before_p (line_table, pragloc, loc))
+ continue;
+
+ if (p->kind == (int) DK_POP)
+ {
+ /* Move on to the next region. */
+ i = p->option;
+ continue;
+ }
+
+ diagnostic_option_id option = p->option;
+ /* The option 0 is for all the diagnostics. */
+ if (option == 0 || option == diagnostic->m_option_id)
+ {
+ diagnostic_t kind = p->kind;
+ if (kind != DK_UNSPECIFIED)
+ diagnostic->m_kind = kind;
+ return kind;
+ }
+ }
+ }
+
+ return DK_UNSPECIFIED;
+}
+
+} // namespace diagnostics
--- /dev/null
+/* Stacks of set of classifications of diagnostics.
+ Copyright (C) 2000-2025 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_DIAGNOSTICS_OPTION_CLASSIFIER_H
+#define GCC_DIAGNOSTICS_OPTION_CLASSIFIER_H
+
+namespace diagnostics {
+
+/* Forward declarations. */
+class context;
+
+/* 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 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 (diagnostic_option_id option_id) const
+ {
+ return get_current_override (option_id) == DK_UNSPECIFIED;
+ }
+
+ diagnostic_t get_current_override (diagnostic_option_id option_id) const
+ {
+ gcc_assert (option_id.m_idx < m_n_opts);
+ return m_classify_diagnostic[option_id.m_idx];
+ }
+
+ diagnostic_t
+ classify_diagnostic (const context *context,
+ diagnostic_option_id option_id,
+ diagnostic_t new_kind,
+ location_t where);
+
+ diagnostic_t
+ update_effective_level_from_pragmas (diagnostic_info *diagnostic) const;
+
+ int pch_save (FILE *);
+ int pch_restore (FILE *);
+
+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 classification_change_t
+ {
+ location_t location;
+
+ /* For DK_POP, this is the index of the corresponding push (as stored
+ in m_push_list).
+ Otherwise, this is an option index. */
+ 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. */
+ vec<classification_change_t> m_classification_history;
+
+ /* For context::get_classification_history, declared later. */
+ friend class context;
+
+ /* For pragma push/pop. */
+ vec<int> m_push_list;
+};
+
+} // namespace diagnostics
+
+#endif /* ! GCC_DIAGNOSTICS_OPTION_CLASSIFIER_H */