https://gcc.gnu.org/g:0654c543363d935e19f2088dffc655688de35be6
commit r16-2535-g0654c543363d935e19f2088dffc655688de35be6 Author: David Malcolm <dmalc...@redhat.com> Date: Fri Jul 25 15:13:39 2025 -0400 diagnostics: move option_classifier to its own files 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 <dmalc...@redhat.com> Diff: --- gcc/Makefile.in | 1 + gcc/diagnostic.cc | 193 ------------------------------ gcc/diagnostics/context.h | 82 +------------ gcc/diagnostics/option-classifier.cc | 222 +++++++++++++++++++++++++++++++++++ gcc/diagnostics/option-classifier.h | 110 +++++++++++++++++ 5 files changed, 335 insertions(+), 273 deletions(-) diff --git a/gcc/Makefile.in b/gcc/Makefile.in index a7c184ceae0e..9a867b72ab67 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1861,6 +1861,7 @@ OBJS-libcommon = diagnostic-spec.o diagnostic.o diagnostic-color.o \ 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 \ diff --git a/gcc/diagnostic.cc b/gcc/diagnostic.cc index 847464d1e5f0..9aecd0653cc9 100644 --- a/gcc/diagnostic.cc +++ b/gcc/diagnostic.cc @@ -126,95 +126,6 @@ diagnostic_set_caret_max_width (diagnostics::context *context, int value) 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 @@ -1078,58 +989,6 @@ diagnostics::logical_locations::manager::function_p (key k) const } } -/* 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. */ @@ -1239,58 +1098,6 @@ diagnostics::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 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. */ diff --git a/gcc/diagnostics/context.h b/gcc/diagnostics/context.h index 21688439aaa5..9dee03342b2a 100644 --- a/gcc/diagnostics/context.h +++ b/gcc/diagnostics/context.h @@ -20,6 +20,8 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_DIAGNOSTICS_CONTEXT_H #define GCC_DIAGNOSTICS_CONTEXT_H +#include "diagnostics/option-classifier.h" + namespace diagnostics { /* Forward declarations. */ @@ -73,86 +75,6 @@ public: 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). */ diff --git a/gcc/diagnostics/option-classifier.cc b/gcc/diagnostics/option-classifier.cc new file mode 100644 index 000000000000..77bce36a7302 --- /dev/null +++ b/gcc/diagnostics/option-classifier.cc @@ -0,0 +1,222 @@ +/* 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 diff --git a/gcc/diagnostics/option-classifier.h b/gcc/diagnostics/option-classifier.h new file mode 100644 index 000000000000..809449ee71c9 --- /dev/null +++ b/gcc/diagnostics/option-classifier.h @@ -0,0 +1,110 @@ +/* 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 */