No functional change intended. gcc/ChangeLog: * diagnostics/context.cc: Eliminate digraphs::lazy_digraph in favor of lazily_created template. * diagnostics/context.h: Likewise. * diagnostics/digraphs.cc: Likewise, also digraphs::lazy_digraphs. * diagnostics/digraphs.h: Likewise. * diagnostics/html-sink.cc: Likewise. * diagnostics/metadata.h: Likewise. * diagnostics/sarif-sink.cc: Likewise. * diagnostics/sink.h: Likewise. * diagnostics/text-sink.h: Likewise. * lazily-created.h: New file. * libgdiagnostics.cc: Eliminate digraphs::lazy_digraph in favor of lazily_created template.
gcc/testsuite/ChangeLog: * gcc.dg/plugin/diagnostic_plugin_test_graphs.cc: Eliminate digraphs::lazy_digraph and digraphs::lazy_digraphs in favor of lazily_created template. * gcc.dg/plugin/diagnostic_plugin_test_metadata.cc: Define INCLUDE_VECTOR since diagnostics/metadata.h now requires it. * gcc.dg/plugin/diagnostic_plugin_test_paths.cc: Likewise. --- gcc/diagnostics/context.cc | 2 +- gcc/diagnostics/context.h | 7 ++- gcc/diagnostics/digraphs.cc | 22 -------- gcc/diagnostics/digraphs.h | 42 --------------- gcc/diagnostics/html-sink.cc | 11 ++-- gcc/diagnostics/metadata.h | 18 ++++--- gcc/diagnostics/sarif-sink.cc | 13 ++--- gcc/diagnostics/sink.h | 2 +- gcc/diagnostics/text-sink.h | 3 +- gcc/lazily-created.h | 51 +++++++++++++++++++ gcc/libgdiagnostics.cc | 9 ++-- .../plugin/diagnostic_plugin_test_graphs.cc | 10 ++-- .../plugin/diagnostic_plugin_test_metadata.cc | 1 + .../plugin/diagnostic_plugin_test_paths.cc | 1 + 14 files changed, 93 insertions(+), 99 deletions(-) create mode 100644 gcc/lazily-created.h diff --git a/gcc/diagnostics/context.cc b/gcc/diagnostics/context.cc index e8a87c82f23e..9b235c8426d4 100644 --- a/gcc/diagnostics/context.cc +++ b/gcc/diagnostics/context.cc @@ -1439,7 +1439,7 @@ context::report_verbatim (text_info &text) } void -context::report_global_digraph (const digraphs::lazy_digraph &ldg) +context::report_global_digraph (const lazily_created<digraphs::digraph> &ldg) { for (auto sink_ : m_sinks) sink_->report_global_digraph (ldg); diff --git a/gcc/diagnostics/context.h b/gcc/diagnostics/context.h index 8ac724a7ac2a..f47370b11973 100644 --- a/gcc/diagnostics/context.h +++ b/gcc/diagnostics/context.h @@ -20,6 +20,7 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_DIAGNOSTICS_CONTEXT_H #define GCC_DIAGNOSTICS_CONTEXT_H +#include "lazily-created.h" #include "unique-argv.h" #include "diagnostics/option-classifier.h" #include "diagnostics/context-options.h" @@ -30,9 +31,7 @@ namespace diagnostics { class change_set; } - namespace digraphs { - class lazy_digraph; - } + namespace digraphs { class digraph; } namespace logical_locations { class manager; @@ -426,7 +425,7 @@ public: /* Report a directed graph associated with the run as a whole to any sinks that support directed graphs. */ void - report_global_digraph (const digraphs::lazy_digraph &); + report_global_digraph (const lazily_created<digraphs::digraph> &); enum kind classify_diagnostic (option_id opt_id, diff --git a/gcc/diagnostics/digraphs.cc b/gcc/diagnostics/digraphs.cc index b77390c0f1c7..4a2ea4fca3c7 100644 --- a/gcc/diagnostics/digraphs.cc +++ b/gcc/diagnostics/digraphs.cc @@ -351,28 +351,6 @@ diagnostics::digraphs::edge::to_json_sarif_edge () const return make_sarif_edge (*this, nullptr); } -// class lazy_digraph - -const diagnostics::digraphs::digraph & -diagnostics::digraphs::lazy_digraph::get_or_create_digraph () const -{ - if (!m_digraph) - m_digraph = create_digraph (); - gcc_assert (m_digraph); - return *m_digraph; -} - -// class lazy_digraphs - -const std::vector<std::unique_ptr<diagnostics::digraphs::digraph>> & -diagnostics::digraphs::lazy_digraphs::get_or_create_digraphs () const -{ - if (!m_digraphs) - m_digraphs = create_digraphs (); - gcc_assert (m_digraphs); - return *m_digraphs; -} - #if CHECKING_P namespace diagnostics { diff --git a/gcc/diagnostics/digraphs.h b/gcc/diagnostics/digraphs.h index fc73f6e73623..7193ee48c3fa 100644 --- a/gcc/diagnostics/digraphs.h +++ b/gcc/diagnostics/digraphs.h @@ -373,48 +373,6 @@ private: node &m_dst_node; }; -/* Abstract base class for lazily creating - a digraph on demand. - - This allows us to avoid the work of creating the digraph for - the common case where we just have a text sink. */ - -class lazy_digraph -{ -public: - virtual ~lazy_digraph () {} - - const digraph & - get_or_create_digraph () const; - -private: - virtual std::unique_ptr<digraph> - create_digraph () const = 0; - - mutable std::unique_ptr<digraph> m_digraph; -}; - -/* Abstract base class for lazily creating a collection of - digraphs on demand. - - This allows us to avoid the work of creating the digraphs for - the common case where we just have a text sink. */ - -class lazy_digraphs -{ -public: - virtual ~lazy_digraphs () {} - - const std::vector<std::unique_ptr<digraph>> & - get_or_create_digraphs () const; - -private: - virtual std::unique_ptr<std::vector<std::unique_ptr<digraph>>> - create_digraphs () const = 0; - - mutable std::unique_ptr<std::vector<std::unique_ptr<digraph>>> m_digraphs; -}; - } // namespace digraphs } // namespace diagnostics diff --git a/gcc/diagnostics/html-sink.cc b/gcc/diagnostics/html-sink.cc index 35525cb890c5..07e71871d181 100644 --- a/gcc/diagnostics/html-sink.cc +++ b/gcc/diagnostics/html-sink.cc @@ -123,7 +123,7 @@ public: enum kind orig_diag_kind, html_sink_buffer *buffer); void emit_diagram (const diagram &d); - void emit_global_graph (const digraphs::lazy_digraph &); + void emit_global_graph (const lazily_created<digraphs::digraph> &); void end_group (); @@ -1148,7 +1148,7 @@ html_builder::make_element_for_diagnostic (const diagnostic_info &diagnostic, if (diagnostic.m_metadata) if (auto ldg = diagnostic.m_metadata->get_lazy_digraphs ()) { - auto &digraphs = ldg->get_or_create_digraphs (); + auto &digraphs = ldg->get_or_create (); for (auto &dg : digraphs) add_graph (*dg, *xp.get_insertion_point ()); } @@ -1271,9 +1271,9 @@ html_builder::add_graph (const digraphs::digraph &dg, } void -html_builder::emit_global_graph (const digraphs::lazy_digraph &ldg) +html_builder::emit_global_graph (const lazily_created<digraphs::digraph> &ldg) { - auto &dg = ldg.get_or_create_digraph (); + auto &dg = ldg.get_or_create (); gcc_assert (m_body_element); add_graph (dg, *m_body_element); } @@ -1392,7 +1392,8 @@ public: } void - report_global_digraph (const digraphs::lazy_digraph &ldg) final override + report_global_digraph (const lazily_created<digraphs::digraph> &ldg) + final override { m_builder.emit_global_graph (ldg); } diff --git a/gcc/diagnostics/metadata.h b/gcc/diagnostics/metadata.h index cdca105ebdfd..c28f9821ee8b 100644 --- a/gcc/diagnostics/metadata.h +++ b/gcc/diagnostics/metadata.h @@ -21,13 +21,12 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_DIAGNOSTICS_METADATA_H #define GCC_DIAGNOSTICS_METADATA_H +#include "lazily-created.h" + namespace diagnostics { class sarif_object; - - namespace digraphs { - class lazy_digraphs; - } // namespace digraphs + namespace digraphs { class digraph; } /* A bundle of additional metadata that can be associated with a diagnostic. @@ -41,6 +40,9 @@ namespace diagnostics { class metadata { public: + using lazy_digraphs + = lazily_created<std::vector<std::unique_ptr<digraphs::digraph>>>; + /* Abstract base class for referencing a rule that has been violated, such as within a coding standard, or within a specification. */ class rule @@ -97,12 +99,12 @@ class metadata const rule &get_rule (unsigned idx) const { return *(m_rules[idx]); } void - set_lazy_digraphs (const digraphs::lazy_digraphs *lazy_digraphs) + set_lazy_digraphs (const lazy_digraphs *lazy_digraphs_) { - m_lazy_digraphs = lazy_digraphs; + m_lazy_digraphs = lazy_digraphs_; } - const digraphs::lazy_digraphs * + const lazy_digraphs * get_lazy_digraphs () const { return m_lazy_digraphs; @@ -114,7 +116,7 @@ class metadata /* An optional way to create directed graphs associated with the diagnostic, for the sinks that support this (e.g. SARIF). */ - const digraphs::lazy_digraphs *m_lazy_digraphs; + const lazy_digraphs *m_lazy_digraphs; }; } // namespace diagnostics diff --git a/gcc/diagnostics/sarif-sink.cc b/gcc/diagnostics/sarif-sink.cc index 74252b4b77a1..05c0a8eb3a92 100644 --- a/gcc/diagnostics/sarif-sink.cc +++ b/gcc/diagnostics/sarif-sink.cc @@ -781,7 +781,7 @@ public: void end_group (); void - report_global_digraph (const digraphs::lazy_digraph &); + report_global_digraph (const lazily_created<digraphs::digraph> &); std::unique_ptr<sarif_result> take_current_result () { @@ -1908,9 +1908,9 @@ sarif_builder::end_group () void sarif_builder:: -report_global_digraph (const digraphs::lazy_digraph &ldg) +report_global_digraph (const lazily_created<digraphs::digraph> &ldg) { - auto &dg = ldg.get_or_create_digraph (); + auto &dg = ldg.get_or_create (); /* Presumably the location manager must be nullptr; see https://github.com/oasis-tcs/sarif-spec/issues/712 */ @@ -2075,7 +2075,7 @@ sarif_builder::make_result_object (const diagnostic_info &diagnostic, if (diagnostic.m_metadata) if (auto ldg = diagnostic.m_metadata->get_lazy_digraphs ()) { - auto &digraphs = ldg->get_or_create_digraphs (); + auto &digraphs = ldg->get_or_create (); auto graphs_arr = std::make_unique<json::array> (); for (auto &iter : digraphs) graphs_arr->append (make_sarif_graph (*iter, this, @@ -3930,9 +3930,10 @@ public: } void - report_global_digraph (const digraphs::lazy_digraph &lazy_digraph) final override + report_global_digraph (const lazily_created<digraphs::digraph> &ldg) + final override { - m_builder.report_global_digraph (lazy_digraph); + m_builder.report_global_digraph (ldg); } sarif_builder &get_builder () { return m_builder; } diff --git a/gcc/diagnostics/sink.h b/gcc/diagnostics/sink.h index 04de99a06df1..ac4e0fb64455 100644 --- a/gcc/diagnostics/sink.h +++ b/gcc/diagnostics/sink.h @@ -75,7 +75,7 @@ public: virtual void update_printer () = 0; virtual void - report_global_digraph (const digraphs::lazy_digraph &) = 0; + report_global_digraph (const lazily_created<digraphs::digraph> &) = 0; context &get_context () const { return m_context; } pretty_printer *get_printer () const { return m_printer.get (); } diff --git a/gcc/diagnostics/text-sink.h b/gcc/diagnostics/text-sink.h index 460e53e630cb..5c60976641ef 100644 --- a/gcc/diagnostics/text-sink.h +++ b/gcc/diagnostics/text-sink.h @@ -73,7 +73,8 @@ public: void update_printer () override; void - report_global_digraph (const digraphs::lazy_digraph &) final override + report_global_digraph (const lazily_created<digraphs::digraph> &) + final override { // no-op for text } diff --git a/gcc/lazily-created.h b/gcc/lazily-created.h new file mode 100644 index 000000000000..a6010cac8b57 --- /dev/null +++ b/gcc/lazily-created.h @@ -0,0 +1,51 @@ +/* Template for deferring object creation until the object is needed. + Copyright (C) 2024-2025 Free Software Foundation, Inc. + Contributed by David Malcolm <dmalc...@redhat.com> + +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_LAZILY_CREATED_H +#define GCC_LAZILY_CREATED_H + +/* A template for deferring object creation for a type T until the object + is needed, to avoid potentially expensive creation of T unless it's + actually needed (e.g. for directed graphs associated with a diagnostic, + which are ignored by the default "text" sink). */ + +template <typename T> +class lazily_created +{ + public: + virtual ~lazily_created () {} + + const T & + get_or_create () const + { + if (!m_object) + m_object = create_object (); + gcc_assert (m_object); + return *m_object; + } + +private: + virtual std::unique_ptr<T> + create_object () const = 0; + + mutable std::unique_ptr<T> m_object; +}; + +#endif /* ! GCC_LAZILY_CREATED_H */ diff --git a/gcc/libgdiagnostics.cc b/gcc/libgdiagnostics.cc index 7df8c95cb83d..7351d33641bc 100644 --- a/gcc/libgdiagnostics.cc +++ b/gcc/libgdiagnostics.cc @@ -1188,13 +1188,14 @@ private: std::vector<std::unique_ptr<libgdiagnostics_path_event>> m_events; }; -class prebuilt_digraphs : public diagnostics::digraphs::lazy_digraphs +class prebuilt_digraphs + : public lazily_created<std::vector<std::unique_ptr<diagnostics::digraphs::digraph>>> { public: using digraph = diagnostics::digraphs::digraph; std::unique_ptr<std::vector<std::unique_ptr<digraph>>> - create_digraphs () const final override + create_object () const final override { return std::make_unique<std::vector<std::unique_ptr<digraph>>> (std::move (m_digraphs)); } @@ -1665,7 +1666,7 @@ diagnostic_manager::new_execution_path () void diagnostic_manager::take_global_graph (std::unique_ptr<diagnostic_graph> graph) { - class prebuilt_lazy_digraph : public diagnostics::digraphs::lazy_digraph + class prebuilt_lazy_digraph : public lazily_created<diagnostics::digraphs::digraph> { public: prebuilt_lazy_digraph (std::unique_ptr<diagnostic_graph> graph) @@ -1674,7 +1675,7 @@ diagnostic_manager::take_global_graph (std::unique_ptr<diagnostic_graph> graph) } std::unique_ptr<diagnostics::digraphs::digraph> - create_digraph () const final override + create_object () const final override { return std::move (m_graph); } diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_graphs.cc b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_graphs.cc index fe54fe90c90c..7398a2908258 100644 --- a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_graphs.cc +++ b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_graphs.cc @@ -97,7 +97,7 @@ check_for_named_call (gimple *stmt, return call; } -class lazy_passes_graph : public diagnostics::digraphs::lazy_digraph +class lazy_passes_graph : public lazily_created<diagnostics::digraphs::digraph> { public: lazy_passes_graph (const ::gcc::pass_manager &pass_manager_) @@ -105,8 +105,9 @@ public: { } +private: std::unique_ptr<diagnostics::digraphs::digraph> - create_digraph () const final override + create_object () const final override { auto g = std::make_unique<diagnostics::digraphs::digraph> (); g->set_description ("Optimization Passes"); @@ -176,14 +177,13 @@ public: return result; } -private: const ::gcc::pass_manager &m_pass_manager; }; static void report_diag_with_graphs (location_t loc) { - class my_lazy_digraphs : public diagnostics::digraphs::lazy_digraphs + class my_lazy_digraphs : public diagnostics::metadata::lazy_digraphs { public: using diagnostic_graph = diagnostics::digraphs::digraph; @@ -191,7 +191,7 @@ report_diag_with_graphs (location_t loc) using diagnostic_edge = diagnostics::digraphs::edge; std::unique_ptr<std::vector<std::unique_ptr<diagnostic_graph>>> - create_digraphs () const final override + create_object () const final override { auto graphs = std::make_unique<std::vector<std::unique_ptr<diagnostic_graph>>> (); diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_metadata.cc b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_metadata.cc index a1d003e53664..f1722583119c 100644 --- a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_metadata.cc +++ b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_metadata.cc @@ -1,5 +1,6 @@ /* This plugin exercises diagnostics::metadata. */ +#define INCLUDE_VECTOR #include "gcc-plugin.h" #include "config.h" #include "system.h" diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_paths.cc b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_paths.cc index 2c9ff1c5b065..875f4a849e8c 100644 --- a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_paths.cc +++ b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_paths.cc @@ -6,6 +6,7 @@ specific tests within the compiler's IR. We can't use any real diagnostics for this, so we have to fake it, hence this plugin. */ +#define INCLUDE_VECTOR #include "gcc-plugin.h" #include "config.h" #include "system.h" -- 2.26.3