From patchwork Mon Oct 2 16:33:19 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Malcolm X-Patchwork-Id: 147371 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:612c:2a8e:b0:403:3b70:6f57 with SMTP id in14csp1546363vqb; Mon, 2 Oct 2023 09:34:58 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEwPVzbuT1mj07yZ0LvVq9waYDqbM9YEf0hTZudvq6I+uWxFcCve1z9fyFOmO8gFUytXq1d X-Received: by 2002:a17:906:3050:b0:9ad:e180:16e3 with SMTP id d16-20020a170906305000b009ade18016e3mr10375223ejd.37.1696264497879; Mon, 02 Oct 2023 09:34:57 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1696264497; cv=none; d=google.com; s=arc-20160816; b=NDkcNKVSMaptduTDHUaqhjzc1jgvK7D3KdyeXjvtLDCA/qa8ljhmmCx/mPap/CLZim sLdZ9DcVJ6kQIvxjiBz3/f+dT+LWEsJSEKK99zODC2CPGlBBepBpqc+i66RH6m3wmFe9 gjUDKDnVOU6ULr+sRrg2Cno1ClkpFJh3ZSdrZJy55b9+ONLvm53GTUacpA8/FO5u5hlw nJHuA/Q64LyRMnqApZBrbm6cjpQjG2TD0mgiv7vq+QBvLD0yVR2dG9mDHq+xIY+cyqcO 05vOpiaNolxHtjUYMkLofmbXmnBUS3aUs2I9QHlFq1bZhYWk90eM5xG+YI5xBIDxx0MI lPsA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:message-id:date:subject:cc:to:from:dkim-signature :dmarc-filter:delivered-to; bh=vXX01PRfVURzBBxgm+UsolknwWOSeWoUlZRsvAiBeQY=; fh=NXemEfxTRbZtBxUkxR2ehQUaYlcDfMdzPkO8MChVQE4=; b=EaNj3lf99WE06qGdQkbvo3ZrfDTnALvNbirfzJjCtdzsc1QNUFcJJu8xCpe6Hybp/W wHoWY5QQ2ri5Cb2jd8niKBm3+Rpt0ks/kNPjrc+4MZQVx3MwJtgkSsOeAgALpiDR/nvT qnq/LXiw1zQdo8pOEXWwdemWICBhwb4e9USQztEjfhXOl/e08bsgHOqK5vr/4bDRFcsA 8vyxOegOSSFIbXU4ExEr6dJYXDIC3dwoLz7oDFWufYDZmP8wsn51DJITO/7QRla2AdGF x6l3qhr+khtfU3x+T+D9RyYKbzKl0WjN6I+7yI1gHsK1We1tQv+0jYP7kbySuY24ZIcv elLw== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@redhat.com header.s=mimecast20190719 header.b=Wp2CRKC+; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from server2.sourceware.org (ip-8-43-85-97.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id lo6-20020a170906fa0600b0099bbed21b65si19337496ejb.1014.2023.10.02.09.34.57 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 02 Oct 2023 09:34:57 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@redhat.com header.s=mimecast20190719 header.b=Wp2CRKC+; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id E646C385CC8E for ; Mon, 2 Oct 2023 16:34:09 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 27AB4385C6F2 for ; Mon, 2 Oct 2023 16:33:23 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 27AB4385C6F2 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1696264402; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=vMMkJiUa6TFkgntFAeLOwXbO2GBS6ff9wsHI2zPl4x4=; b=Wp2CRKC+/unkNSMVjOLd12sWXKNHCDB+a5eWo/hHlU0OViACXq6b/YskGuESBVEhmWyTC6 xLcGlxD9162R3jLzxM3XoO3A0RPfHkJd4odH1PYPwCbG5Tr2IkVZVOUeF+7t5tbZXuOeTx wjmdIu97vdXh0FQpTvBMBRDo2cGPjjY= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-536-wbHKKKbsPxSvMPwBuA7XOQ-1; Mon, 02 Oct 2023 12:33:20 -0400 X-MC-Unique: wbHKKKbsPxSvMPwBuA7XOQ-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.rdu2.redhat.com [10.11.54.8]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 8723797E400 for ; Mon, 2 Oct 2023 16:33:20 +0000 (UTC) Received: from t14s.localdomain.com (unknown [10.22.18.119]) by smtp.corp.redhat.com (Postfix) with ESMTP id 48EE3C15BB8; Mon, 2 Oct 2023 16:33:20 +0000 (UTC) From: David Malcolm To: gcc-patches@gcc.gnu.org Cc: David Malcolm Subject: [pushed] diagnostics: add diagnostic_output_format class Date: Mon, 2 Oct 2023 12:33:19 -0400 Message-Id: <20231002163319.4034817-1-dmalcolm@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.8 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-23.6 required=5.0 tests=BAYES_00, DKIM_INVALID, DKIM_SIGNED, GIT_PATCH_0, KAM_ASCII_DIVIDERS, KAM_DMARC_NONE, KAM_DMARC_STATUS, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1778662242221172024 X-GMAIL-MSGID: 1778662242221172024 Eliminate various global variables in the json/sarif output code by bundling together callbacks and state into a new diagnostic_output_format class, with per-output-format subclasses. No functional change intended. Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu. Pushed to trunk as r14-4368-g140820265d96b0. gcc/ChangeLog: * diagnostic-format-json.cc (toplevel_array): Remove global in favor of json_output_format::m_top_level_array. (cur_group): Likewise, for json_output_format::m_cur_group. (cur_children_array): Likewise, for json_output_format::m_cur_children_array. (class json_output_format): New. (json_begin_diagnostic): Remove, in favor of json_output_format::on_begin_diagnostic. (json_end_diagnostic): Convert to... (json_output_format::on_end_diagnostic): ...this. (json_begin_group): Remove, in favor of json_output_format::on_begin_group. (json_end_group): Remove, in favor of json_output_format::on_end_group. (json_flush_to_file): Remove, in favor of json_output_format::flush_to_file. (json_stderr_final_cb): Remove, in favor of json_output_format dtor. (json_output_base_file_name): Remove global. (class json_stderr_output_format): New. (json_file_final_cb): Remove. (class json_file_output_format): New. (json_emit_diagram): Remove. (diagnostic_output_format_init_json): Update. (diagnostic_output_format_init_json_file): Update. * diagnostic-format-sarif.cc (the_builder): Remove this global, moving to a field of the sarif_output_format. (sarif_builder::maybe_make_artifact_content_object): Use the context's m_file_cache. (get_source_lines): Convert to... (sarif_builder::get_source_lines): ...this, using context's m_file_cache. (sarif_begin_diagnostic): Remove, in favor of sarif_output_format::on_begin_diagnostic. (sarif_end_diagnostic): Remove, in favor of sarif_output_format::on_end_diagnostic. (sarif_begin_group): Remove, in favor of sarif_output_format::on_begin_group. (sarif_end_group): Remove, in favor of sarif_output_format::on_end_group. (sarif_flush_to_file): Delete. (sarif_stderr_final_cb): Delete. (sarif_output_base_file_name): Delete. (sarif_file_final_cb): Delete. (class sarif_output_format): New. (sarif_emit_diagram): Delete. (class sarif_stream_output_format): New. (class sarif_file_output_format): New. (diagnostic_output_format_init_sarif): Update. (diagnostic_output_format_init_sarif_stderr): Update. (diagnostic_output_format_init_sarif_file): Update. (diagnostic_output_format_init_sarif_stream): Update. * diagnostic-show-locus.cc (diagnostic_show_locus): Update. * diagnostic.cc (default_diagnostic_final_cb): Delete, moving to diagnostic_text_output_format's dtor. (diagnostic_initialize): Update, making a new instance of diagnostic_text_output_format. (diagnostic_finish): Delete m_output_format, rather than calling final_cb. (diagnostic_report_diagnostic): Assert that m_output_format is non-NULL. Replace call to begin_group_cb with call to m_output_format->on_begin_group. Replace call to diagnostic_starter with call to m_output_format->on_begin_diagnostic. Replace call to diagnostic_finalizer with call to m_output_format->on_end_diagnostic. (diagnostic_emit_diagram): Replace both optional call to m_diagrams.m_emission_cb and default implementation with call to m_output_format->on_diagram. Move default implementation to diagnostic_text_output_format::on_diagram. (auto_diagnostic_group::~auto_diagnostic_group): Replace call to end_group_cb with call to m_output_format->on_end_group. (diagnostic_text_output_format::~diagnostic_text_output_format): New, based on default_diagnostic_final_cb. (diagnostic_text_output_format::on_begin_diagnostic): New, based on code from diagnostic_report_diagnostic. (diagnostic_text_output_format::on_end_diagnostic): Likewise. (diagnostic_text_output_format::on_diagram): New, based on code from diagnostic_emit_diagram. * diagnostic.h (class diagnostic_output_format): New. (class diagnostic_text_output_format): New. (diagnostic_context::begin_diagnostic): Move to... (diagnostic_context::m_text_callbacks::begin_diagnostic): ...here. (diagnostic_context::start_span): Move to... (diagnostic_context::m_text_callbacks::start_span): ...here. (diagnostic_context::end_diagnostic): Move to... (diagnostic_context::m_text_callbacks::end_diagnostic): ...here. (diagnostic_context::begin_group_cb): Remove, in favor of m_output_format->on_begin_group. (diagnostic_context::end_group_cb): Remove, in favor of m_output_format->on_end_group. (diagnostic_context::final_cb): Remove, in favor of m_output_format's dtor. (diagnostic_context::m_output_format): New field. (diagnostic_context::m_diagrams.m_emission_cb): Remove, in favor of m_output_format->on_diagram. (diagnostic_starter): Update. (diagnostic_finalizer): Update. (diagnostic_output_format_init_sarif_stream): New. * input.cc (location_get_source_line): Move implementation apart from call to diagnostic_file_cache_init to... (file_cache::get_source_line): ...this new function... (location_get_source_line): ...and reintroduce, rewritten in terms of file_cache::get_source_line. (get_source_file_content): Likewise, refactor into... (file_cache::get_source_file_content): ...this new function. * input.h (file_cache::get_source_line): New decl. (file_cache::get_source_file_content): New decl. * selftest-diagnostic.cc (test_diagnostic_context::test_diagnostic_context): Update. * tree-diagnostic-path.cc (event_range::print): Update for change to diagnostic_context's start_span callback. gcc/fortran/ChangeLog: * error.cc (gfc_diagnostics_init): Update for change to start_span. gcc/jit/ChangeLog: * dummy-frontend.cc (jit_langhook_init): Update for change to diagnostic_context callbacks. gcc/testsuite/ChangeLog: * gcc.dg/plugin/diagnostic_group_plugin.c (test_begin_group_cb, test_end_group_cb): Replace with... (class test_output_format): ...this new subclass. (plugin_init): Update. --- gcc/diagnostic-format-json.cc | 230 +++++++++--------- gcc/diagnostic-format-sarif.cc | 212 ++++++++-------- gcc/diagnostic-show-locus.cc | 2 +- gcc/diagnostic.cc | 115 ++++----- gcc/diagnostic.h | 109 ++++++--- gcc/fortran/error.cc | 2 +- gcc/input.cc | 26 +- gcc/input.h | 3 + gcc/jit/dummy-frontend.cc | 4 +- gcc/selftest-diagnostic.cc | 2 +- .../gcc.dg/plugin/diagnostic_group_plugin.c | 45 ++-- gcc/tree-diagnostic-path.cc | 2 +- 12 files changed, 417 insertions(+), 335 deletions(-) diff --git a/gcc/diagnostic-format-json.cc b/gcc/diagnostic-format-json.cc index 539b98b5e74..346abb31ac4 100644 --- a/gcc/diagnostic-format-json.cc +++ b/gcc/diagnostic-format-json.cc @@ -28,18 +28,63 @@ along with GCC; see the file COPYING3. If not see #include "json.h" #include "selftest.h" -/* The top-level JSON array of pending diagnostics. */ +/* Subclass of diagnostic_output_format for JSON output. */ -static json::array *toplevel_array; +class json_output_format : public diagnostic_output_format +{ +public: + void on_begin_group () final override + { + /* No-op. */ + } + void on_end_group () final override + { + m_cur_group = nullptr; + m_cur_children_array = nullptr; + } + void + on_begin_diagnostic (diagnostic_info *) final override + { + /* No-op. */ + } + void + on_end_diagnostic (diagnostic_info *diagnostic, + diagnostic_t orig_diag_kind) final override; + void on_diagram (const diagnostic_diagram &) final override + { + /* No-op. */ + } -/* The JSON object for the current diagnostic group. */ +protected: + json_output_format (diagnostic_context &context) + : diagnostic_output_format (context), + m_toplevel_array (new json::array ()), + m_cur_group (nullptr), + m_cur_children_array (nullptr) + { + } -static json::object *cur_group; + /* Flush the top-level array to OUTF. */ + void + flush_to_file (FILE *outf) + { + m_toplevel_array->dump (outf); + fprintf (outf, "\n"); + delete m_toplevel_array; + m_toplevel_array = nullptr; + } + +private: + /* The top-level JSON array of pending diagnostics. */ + json::array *m_toplevel_array; -/* The JSON array for the "children" array within the current diagnostic - group. */ + /* The JSON object for the current diagnostic group. */ + json::object *m_cur_group; -static json::array *cur_children_array; + /* The JSON array for the "children" array within the current diagnostic + group. */ + json::array *m_cur_children_array; +}; /* Generate a JSON object for LOC. */ @@ -139,20 +184,13 @@ json_from_metadata (const diagnostic_metadata *metadata) return metadata_obj; } -/* No-op implementation of "begin_diagnostic" for JSON output. */ - -static void -json_begin_diagnostic (diagnostic_context *, diagnostic_info *) -{ -} - -/* Implementation of "end_diagnostic" for JSON output. +/* Implementation of "on_end_diagnostic" vfunc for JSON output. Generate a JSON object for DIAGNOSTIC, and store for output within current diagnostic group. */ -static void -json_end_diagnostic (diagnostic_context *context, diagnostic_info *diagnostic, - diagnostic_t orig_diag_kind) +void +json_output_format::on_end_diagnostic (diagnostic_info *diagnostic, + diagnostic_t orig_diag_kind) { json::object *diag_obj = new json::object (); @@ -178,22 +216,22 @@ json_end_diagnostic (diagnostic_context *context, diagnostic_info *diagnostic, // FIXME: encoding of the message (json::string requires UTF-8) diag_obj->set ("message", - new json::string (pp_formatted_text (context->printer))); - pp_clear_output_area (context->printer); + new json::string (pp_formatted_text (m_context.printer))); + pp_clear_output_area (m_context.printer); char *option_text; - option_text = context->option_name (context, diagnostic->option_index, - orig_diag_kind, diagnostic->kind); + option_text = m_context.option_name (&m_context, diagnostic->option_index, + orig_diag_kind, diagnostic->kind); if (option_text) { diag_obj->set ("option", new json::string (option_text)); free (option_text); } - if (context->get_option_url) + if (m_context.get_option_url) { - char *option_url = context->get_option_url (context, - diagnostic->option_index); + char *option_url = m_context.get_option_url (&m_context, + diagnostic->option_index); if (option_url) { diag_obj->set ("option_url", new json::string (option_url)); @@ -203,21 +241,21 @@ json_end_diagnostic (diagnostic_context *context, diagnostic_info *diagnostic, /* If we've already emitted a diagnostic within this auto_diagnostic_group, then add diag_obj to its "children" array. */ - if (cur_group) + if (m_cur_group) { - gcc_assert (cur_children_array); - cur_children_array->append (diag_obj); + gcc_assert (m_cur_children_array); + m_cur_children_array->append (diag_obj); } else { /* Otherwise, make diag_obj be the top-level object within the group; add a "children" array and record the column origin. */ - toplevel_array->append (diag_obj); - cur_group = diag_obj; - cur_children_array = new json::array (); - diag_obj->set ("children", cur_children_array); + m_toplevel_array->append (diag_obj); + m_cur_group = diag_obj; + m_cur_children_array = new json::array (); + diag_obj->set ("children", m_cur_children_array); diag_obj->set ("column-origin", - new json::integer_number (context->column_origin)); + new json::integer_number (m_context.column_origin)); } const rich_location *richloc = diagnostic->richloc; @@ -228,7 +266,8 @@ json_end_diagnostic (diagnostic_context *context, diagnostic_info *diagnostic, for (unsigned int i = 0; i < richloc->get_num_locations (); i++) { const location_range *loc_range = richloc->get_range (i); - json::object *loc_obj = json_from_location_range (context, loc_range, i); + json::object *loc_obj + = json_from_location_range (&m_context, loc_range, i); if (loc_obj) loc_array->append (loc_obj); } @@ -240,7 +279,7 @@ json_end_diagnostic (diagnostic_context *context, diagnostic_info *diagnostic, for (unsigned int i = 0; i < richloc->get_num_fixit_hints (); i++) { const fixit_hint *hint = richloc->get_fixit_hint (i); - json::object *fixit_obj = json_from_fixit_hint (context, hint); + json::object *fixit_obj = json_from_fixit_hint (&m_context, hint); fixit_array->append (fixit_obj); } } @@ -257,9 +296,9 @@ json_end_diagnostic (diagnostic_context *context, diagnostic_info *diagnostic, } const diagnostic_path *path = richloc->get_path (); - if (path && context->make_json_for_path) + if (path && m_context.make_json_for_path) { - json::value *path_value = context->make_json_for_path (context, path); + json::value *path_value = m_context.make_json_for_path (&m_context, path); diag_obj->set ("path", path_value); } @@ -267,71 +306,51 @@ json_end_diagnostic (diagnostic_context *context, diagnostic_info *diagnostic, new json::literal (richloc->escape_on_output_p ())); } -/* No-op implementation of "begin_group_cb" for JSON output. */ - -static void -json_begin_group (diagnostic_context *) -{ -} - -/* Implementation of "end_group_cb" for JSON output. */ - -static void -json_end_group (diagnostic_context *) +class json_stderr_output_format : public json_output_format { - cur_group = NULL; - cur_children_array = NULL; -} - -/* Flush the top-level array to OUTF. */ - -static void -json_flush_to_file (FILE *outf) -{ - toplevel_array->dump (outf); - fprintf (outf, "\n"); - delete toplevel_array; - toplevel_array = NULL; -} - -/* Callback for final cleanup for JSON output to stderr. */ - -static void -json_stderr_final_cb (diagnostic_context *) -{ - json_flush_to_file (stderr); -} - -static char *json_output_base_file_name; - -/* Callback for final cleanup for JSON output to a file. */ +public: + json_stderr_output_format (diagnostic_context &context) + : json_output_format (context) + { + } + ~json_stderr_output_format () + { + flush_to_file (stderr); + } +}; -static void -json_file_final_cb (diagnostic_context *) +class json_file_output_format : public json_output_format { - char *filename = concat (json_output_base_file_name, ".gcc.json", NULL); - FILE *outf = fopen (filename, "w"); - if (!outf) - { - const char *errstr = xstrerror (errno); - fnotice (stderr, "error: unable to open '%s' for writing: %s\n", - filename, errstr); - free (filename); - return; - } - json_flush_to_file (outf); - fclose (outf); - free (filename); -} +public: + json_file_output_format (diagnostic_context &context, + const char *base_file_name) + : json_output_format (context), + m_base_file_name (xstrdup (base_file_name)) + { + } -/* Callback for diagnostic_context::m_diagrams.m_emission_cb. */ + ~json_file_output_format () + { + char *filename = concat (m_base_file_name, ".gcc.json", NULL); + free (m_base_file_name); + m_base_file_name = nullptr; + FILE *outf = fopen (filename, "w"); + if (!outf) + { + const char *errstr = xstrerror (errno); + fnotice (stderr, "error: unable to open '%s' for writing: %s\n", + filename, errstr); + free (filename); + return; + } + flush_to_file (outf); + fclose (outf); + free (filename); + } -static void -json_emit_diagram (diagnostic_context *, - const diagnostic_diagram &) -{ - /* No-op. */ -} +private: + char *m_base_file_name; +}; /* Populate CONTEXT in preparation for JSON output (either to stderr, or to a file). */ @@ -339,17 +358,8 @@ json_emit_diagram (diagnostic_context *, static void diagnostic_output_format_init_json (diagnostic_context *context) { - /* Set up top-level JSON array. */ - if (toplevel_array == NULL) - toplevel_array = new json::array (); - /* Override callbacks. */ - context->begin_diagnostic = json_begin_diagnostic; - context->end_diagnostic = json_end_diagnostic; - context->begin_group_cb = json_begin_group; - context->end_group_cb = json_end_group; context->print_path = NULL; /* handled in json_end_diagnostic. */ - context->m_diagrams.m_emission_cb = json_emit_diagram; /* The metadata is handled in JSON format, rather than as text. */ context->show_cwe = false; @@ -368,7 +378,8 @@ void diagnostic_output_format_init_json_stderr (diagnostic_context *context) { diagnostic_output_format_init_json (context); - context->final_cb = json_stderr_final_cb; + delete context->m_output_format; + context->m_output_format = new json_stderr_output_format (*context); } /* Populate CONTEXT in preparation for JSON output to a file named @@ -379,8 +390,9 @@ diagnostic_output_format_init_json_file (diagnostic_context *context, const char *base_file_name) { diagnostic_output_format_init_json (context); - context->final_cb = json_file_final_cb; - json_output_base_file_name = xstrdup (base_file_name); + delete context->m_output_format; + context->m_output_format = new json_file_output_format (*context, + base_file_name); } #if CHECKING_P diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc index f56c4ce033d..d8cca21d834 100644 --- a/gcc/diagnostic-format-sarif.cc +++ b/gcc/diagnostic-format-sarif.cc @@ -215,6 +215,9 @@ private: json::object * make_reporting_descriptor_reference_object_for_cwe_id (int cwe_id); json::object *make_artifact_object (const char *filename); + char *get_source_lines (const char *filename, + int start_line, + int end_line) const; json::object *maybe_make_artifact_content_object (const char *filename) const; json::object *maybe_make_artifact_content_object (const char *filename, int start_line, @@ -248,8 +251,6 @@ private: int m_tabstop; }; -static sarif_builder *the_builder; - /* class sarif_object : public json::object. */ sarif_property_bag & @@ -1540,7 +1541,8 @@ json::object * sarif_builder::maybe_make_artifact_content_object (const char *filename) const { /* Let input.cc handle any charset conversion. */ - char_span utf8_content = get_source_file_content (filename); + char_span utf8_content + = m_context->m_file_cache->get_source_file_content (filename); if (!utf8_content) return NULL; @@ -1558,16 +1560,17 @@ sarif_builder::maybe_make_artifact_content_object (const char *filename) const /* Attempt to read the given range of lines from FILENAME; return a freshly-allocated 0-terminated buffer containing them, or NULL. */ -static char * -get_source_lines (const char *filename, - int start_line, - int end_line) +char * +sarif_builder::get_source_lines (const char *filename, + int start_line, + int end_line) const { auto_vec result; for (int line = start_line; line <= end_line; line++) { - char_span line_content = location_get_source_line (filename, line); + char_span line_content + = m_context->m_file_cache->get_source_line (filename, line); if (!line_content.get_buffer ()) return NULL; result.reserve (line_content.length () + 1); @@ -1680,82 +1683,6 @@ sarif_builder::make_artifact_content_object (const char *text) const return content_obj; } -/* No-op implementation of "begin_diagnostic" for SARIF output. */ - -static void -sarif_begin_diagnostic (diagnostic_context *, diagnostic_info *) -{ -} - -/* Implementation of "end_diagnostic" for SARIF output. */ - -static void -sarif_end_diagnostic (diagnostic_context *context, diagnostic_info *diagnostic, - diagnostic_t orig_diag_kind) -{ - gcc_assert (the_builder); - the_builder->end_diagnostic (context, diagnostic, orig_diag_kind); -} - -/* No-op implementation of "begin_group_cb" for SARIF output. */ - -static void -sarif_begin_group (diagnostic_context *) -{ -} - -/* Implementation of "end_group_cb" for SARIF output. */ - -static void -sarif_end_group (diagnostic_context *) -{ - gcc_assert (the_builder); - the_builder->end_group (); -} - -/* Flush the top-level array to OUTF. */ - -static void -sarif_flush_to_file (FILE *outf) -{ - gcc_assert (the_builder); - the_builder->flush_to_file (outf); - delete the_builder; - the_builder = NULL; -} - -/* Callback for final cleanup for SARIF output to stderr. */ - -static void -sarif_stderr_final_cb (diagnostic_context *) -{ - gcc_assert (the_builder); - sarif_flush_to_file (stderr); -} - -static char *sarif_output_base_file_name; - -/* Callback for final cleanup for SARIF output to a file. */ - -static void -sarif_file_final_cb (diagnostic_context *) -{ - char *filename = concat (sarif_output_base_file_name, ".sarif", NULL); - FILE *outf = fopen (filename, "w"); - if (!outf) - { - const char *errstr = xstrerror (errno); - fnotice (stderr, "error: unable to open '%s' for writing: %s\n", - filename, errstr); - free (filename); - return; - } - gcc_assert (the_builder); - sarif_flush_to_file (outf); - fclose (outf); - free (filename); -} - /* Callback for diagnostic_context::ice_handler_cb for when an ICE occurs. */ @@ -1773,15 +1700,89 @@ sarif_ice_handler (diagnostic_context *context) fnotice (stderr, "Internal compiler error:\n"); } -/* Callback for diagnostic_context::m_diagrams.m_emission_cb. */ +class sarif_output_format : public diagnostic_output_format +{ +public: + void on_begin_group () final override + { + /* No-op, */ + } + void on_end_group () final override + { + m_builder.end_group (); + } + void + on_begin_diagnostic (diagnostic_info *) final override + { + /* No-op, */ + } + void + on_end_diagnostic (diagnostic_info *diagnostic, + diagnostic_t orig_diag_kind) final override + { + m_builder.end_diagnostic (&m_context, diagnostic, orig_diag_kind); + } + void on_diagram (const diagnostic_diagram &diagram) final override + { + m_builder.emit_diagram (&m_context, diagram); + } -static void -sarif_emit_diagram (diagnostic_context *context, - const diagnostic_diagram &diagram) +protected: + sarif_output_format (diagnostic_context &context) + : diagnostic_output_format (context), + m_builder (&context) + {} + + sarif_builder m_builder; +}; + +class sarif_stream_output_format : public sarif_output_format { - gcc_assert (the_builder); - the_builder->emit_diagram (context, diagram); -} +public: + sarif_stream_output_format (diagnostic_context &context, FILE *stream) + : sarif_output_format (context), + m_stream (stream) + { + } + ~sarif_stream_output_format () + { + m_builder.flush_to_file (m_stream); + } +private: + FILE *m_stream; +}; + +class sarif_file_output_format : public sarif_output_format +{ +public: + sarif_file_output_format (diagnostic_context &context, + const char *base_file_name) + : sarif_output_format (context), + m_base_file_name (xstrdup (base_file_name)) + { + } + ~sarif_file_output_format () + { + char *filename = concat (m_base_file_name, ".sarif", NULL); + free (m_base_file_name); + m_base_file_name = nullptr; + FILE *outf = fopen (filename, "w"); + if (!outf) + { + const char *errstr = xstrerror (errno); + fnotice (stderr, "error: unable to open '%s' for writing: %s\n", + filename, errstr); + free (filename); + return; + } + m_builder.flush_to_file (outf); + fclose (outf); + free (filename); + } + +private: + char *m_base_file_name; +}; /* Populate CONTEXT in preparation for SARIF output (either to stderr, or to a file). */ @@ -1789,16 +1790,9 @@ sarif_emit_diagram (diagnostic_context *context, static void diagnostic_output_format_init_sarif (diagnostic_context *context) { - the_builder = new sarif_builder (context); - /* Override callbacks. */ - context->begin_diagnostic = sarif_begin_diagnostic; - context->end_diagnostic = sarif_end_diagnostic; - context->begin_group_cb = sarif_begin_group; - context->end_group_cb = sarif_end_group; context->print_path = NULL; /* handled in sarif_end_diagnostic. */ context->ice_handler_cb = sarif_ice_handler; - context->m_diagrams.m_emission_cb = sarif_emit_diagram; /* The metadata is handled in SARIF format, rather than as text. */ context->show_cwe = false; @@ -1817,7 +1811,8 @@ void diagnostic_output_format_init_sarif_stderr (diagnostic_context *context) { diagnostic_output_format_init_sarif (context); - context->final_cb = sarif_stderr_final_cb; + delete context->m_output_format; + context->m_output_format = new sarif_stream_output_format (*context, stderr); } /* Populate CONTEXT in preparation for SARIF output to a file named @@ -1825,9 +1820,22 @@ diagnostic_output_format_init_sarif_stderr (diagnostic_context *context) void diagnostic_output_format_init_sarif_file (diagnostic_context *context, - const char *base_file_name) + const char *base_file_name) +{ + diagnostic_output_format_init_sarif (context); + delete context->m_output_format; + context->m_output_format = new sarif_file_output_format (*context, + base_file_name); +} + +/* Populate CONTEXT in preparation for SARIF output to STREAM. */ + +void +diagnostic_output_format_init_sarif_stream (diagnostic_context *context, + FILE *stream) { diagnostic_output_format_init_sarif (context); - context->final_cb = sarif_file_final_cb; - sarif_output_base_file_name = xstrdup (base_file_name); + delete context->m_output_format; + context->m_output_format = new sarif_stream_output_format (*context, + stream); } diff --git a/gcc/diagnostic-show-locus.cc b/gcc/diagnostic-show-locus.cc index 0778223ccb5..4439d9a4804 100644 --- a/gcc/diagnostic-show-locus.cc +++ b/gcc/diagnostic-show-locus.cc @@ -2876,7 +2876,7 @@ diagnostic_show_locus (diagnostic_context * context, { expanded_location exploc = layout.get_expanded_location (line_span); - context->start_span (context, exploc); + context->m_text_callbacks.start_span (context, exploc); } } /* Iterate over the lines within this span (using linenum_arith_t to diff --git a/gcc/diagnostic.cc b/gcc/diagnostic.cc index b4bbd60590b..65a78840a66 100644 --- a/gcc/diagnostic.cc +++ b/gcc/diagnostic.cc @@ -150,28 +150,6 @@ diagnostic_set_caret_max_width (diagnostic_context *context, int value) context->m_source_printing.max_width = value; } -/* Default implementation of final_cb. */ - -static void -default_diagnostic_final_cb (diagnostic_context *context) -{ - /* Some of the errors may actually have been warnings. */ - if (diagnostic_kind_count (context, DK_WERROR)) - { - /* -Werror was given. */ - if (context->warning_as_error_requested) - pp_verbatim (context->printer, - _("%s: all warnings being treated as errors"), - progname); - /* At least one -Werror= was given. */ - else - pp_verbatim (context->printer, - _("%s: some warnings being treated as errors"), - progname); - pp_newline_and_flush (context->printer); - } -} - /* Initialize the diagnostic message outputting machinery. */ void diagnostic_initialize (diagnostic_context *context, int n_opts) @@ -209,7 +187,7 @@ diagnostic_initialize (diagnostic_context *context, int n_opts) context->max_errors = 0; context->internal_error = NULL; diagnostic_starter (context) = default_diagnostic_starter; - context->start_span = default_diagnostic_start_span_fn; + context->m_text_callbacks.start_span = default_diagnostic_start_span_fn; diagnostic_finalizer (context) = default_diagnostic_finalizer; context->option_enabled = NULL; context->option_state = NULL; @@ -242,15 +220,12 @@ diagnostic_initialize (diagnostic_context *context, int n_opts) context->edit_context_ptr = NULL; context->diagnostic_group_nesting_depth = 0; context->diagnostic_group_emission_count = 0; - context->begin_group_cb = NULL; - context->end_group_cb = NULL; - context->final_cb = default_diagnostic_final_cb; + context->m_output_format = new diagnostic_text_output_format (*context); context->set_locations_cb = nullptr; context->ice_handler_cb = NULL; context->includes_seen = NULL; context->m_client_data_hooks = NULL; context->m_diagrams.m_theme = NULL; - context->m_diagrams.m_emission_cb = NULL; diagnostics_text_art_charset_init (context, DIAGNOSTICS_TEXT_ART_CHARSET_DEFAULT); } @@ -326,8 +301,8 @@ void diagnostic_initialize_input_context (diagnostic_context *context, void diagnostic_finish (diagnostic_context *context) { - if (context->final_cb) - context->final_cb (context); + delete context->m_output_format; + context->m_output_format= nullptr; if (context->m_diagrams.m_theme) { @@ -1508,6 +1483,8 @@ diagnostic_report_diagnostic (diagnostic_context *context, location_t location = diagnostic_location (diagnostic); diagnostic_t orig_diag_kind = diagnostic->kind; + gcc_assert (context->m_output_format); + /* Give preference to being able to inhibit warnings, before they get reclassified to something else. */ bool report_warning_p = true; @@ -1598,14 +1575,11 @@ diagnostic_report_diagnostic (diagnostic_context *context, /* Is this the initial diagnostic within the stack of groups? */ if (context->diagnostic_group_emission_count == 0) - { - if (context->begin_group_cb) - context->begin_group_cb (context); - } + context->m_output_format->on_begin_group (); context->diagnostic_group_emission_count++; pp_format (context->printer, &diagnostic->message); - (*diagnostic_starter (context)) (context, diagnostic); + context->m_output_format->on_begin_diagnostic (diagnostic); pp_output_formatted_text (context->printer); if (context->show_cwe) print_any_cwe (context, diagnostic); @@ -1613,7 +1587,7 @@ diagnostic_report_diagnostic (diagnostic_context *context, print_any_rules (context, diagnostic); if (context->show_option_requested) print_option_information (context, diagnostic, orig_diag_kind); - (*diagnostic_finalizer (context)) (context, diagnostic, orig_diag_kind); + context->m_output_format->on_end_diagnostic (diagnostic, orig_diag_kind); switch (context->extra_output_kind) { default: @@ -2214,22 +2188,8 @@ diagnostic_emit_diagram (diagnostic_context *context, if (context->m_diagrams.m_theme == nullptr) return; - if (context->m_diagrams.m_emission_cb) - { - context->m_diagrams.m_emission_cb (context, diagram); - return; - } - - /* Default implementation. */ - char *saved_prefix = pp_take_prefix (context->printer); - pp_set_prefix (context->printer, NULL); - /* Use a newline before and after and a two-space indent - to make the diagram stand out a little from the wall of text. */ - pp_newline (context->printer); - diagram.get_canvas ().print_to_pp (context->printer, " "); - pp_newline (context->printer); - pp_set_prefix (context->printer, saved_prefix); - pp_flush (context->printer); + gcc_assert (context->m_output_format); + context->m_output_format->on_diagram (diagram); } /* Special case error functions. Most are implemented in terms of the @@ -2331,14 +2291,59 @@ auto_diagnostic_group::~auto_diagnostic_group () If any diagnostics were emitted, give the context a chance to do something. */ if (global_dc->diagnostic_group_emission_count > 0) - { - if (global_dc->end_group_cb) - global_dc->end_group_cb (global_dc); - } + global_dc->m_output_format->on_end_group (); global_dc->diagnostic_group_emission_count = 0; } } +/* class diagnostic_text_output_format : public diagnostic_output_format. */ + +diagnostic_text_output_format::~diagnostic_text_output_format () +{ + /* Some of the errors may actually have been warnings. */ + if (diagnostic_kind_count (&m_context, DK_WERROR)) + { + /* -Werror was given. */ + if (m_context.warning_as_error_requested) + pp_verbatim (m_context.printer, + _("%s: all warnings being treated as errors"), + progname); + /* At least one -Werror= was given. */ + else + pp_verbatim (m_context.printer, + _("%s: some warnings being treated as errors"), + progname); + pp_newline_and_flush (m_context.printer); + } +} + +void +diagnostic_text_output_format::on_begin_diagnostic (diagnostic_info *diagnostic) +{ + (*diagnostic_starter (&m_context)) (&m_context, diagnostic); +} + +void +diagnostic_text_output_format::on_end_diagnostic (diagnostic_info *diagnostic, + diagnostic_t orig_diag_kind) +{ + (*diagnostic_finalizer (&m_context)) (&m_context, diagnostic, orig_diag_kind); +} + +void +diagnostic_text_output_format::on_diagram (const diagnostic_diagram &diagram) +{ + char *saved_prefix = pp_take_prefix (m_context.printer); + pp_set_prefix (m_context.printer, NULL); + /* Use a newline before and after and a two-space indent + to make the diagram stand out a little from the wall of text. */ + pp_newline (m_context.printer); + diagram.get_canvas ().print_to_pp (m_context.printer, " "); + pp_newline (m_context.printer); + pp_set_prefix (m_context.printer, saved_prefix); + pp_flush (m_context.printer); +} + /* Set the output format for CONTEXT to FORMAT, using BASE_FILE_NAME for file-based output formats. */ diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h index 1f2d93c3d00..a2c8740cbd0 100644 --- a/gcc/diagnostic.h +++ b/gcc/diagnostic.h @@ -177,6 +177,51 @@ class diagnostic_client_data_hooks; class logical_location; class diagnostic_diagram; +/* Abstract base class for a particular output format for diagnostics; + each value of -fdiagnostics-output-format= will have its own + implementation. */ + +class diagnostic_output_format +{ +public: + virtual ~diagnostic_output_format () {} + + virtual void on_begin_group () = 0; + virtual void on_end_group () = 0; + virtual void on_begin_diagnostic (diagnostic_info *) = 0; + virtual void on_end_diagnostic (diagnostic_info *, + diagnostic_t orig_diag_kind) = 0; + virtual void on_diagram (const diagnostic_diagram &diagram) = 0; + +protected: + diagnostic_output_format (diagnostic_context &context) + : m_context (context) + {} + + diagnostic_context &m_context; +}; + +/* Subclass of diagnostic_output_format for classic text-based output + to stderr. + + Uses diagnostic_context.m_text_callbacks to provide client-specific + textual output (e.g. include paths, macro expansions, etc). */ + +class diagnostic_text_output_format : public diagnostic_output_format +{ +public: + diagnostic_text_output_format (diagnostic_context &context) + : diagnostic_output_format (context) + {} + ~diagnostic_text_output_format (); + void on_begin_group () override {} + void on_end_group () override {} + void on_begin_diagnostic (diagnostic_info *) override; + void on_end_diagnostic (diagnostic_info *, + diagnostic_t orig_diag_kind) override; + void on_diagram (const diagnostic_diagram &diagram) override; +}; + /* This data structure bundles altogether any information relevant to the context of a diagnostic message. */ struct diagnostic_context @@ -264,22 +309,25 @@ struct diagnostic_context /* Maximum number of errors to report. */ int max_errors; - /* This function is called before any message is printed out. It is - responsible for preparing message prefix and such. For example, it - might say: - In file included from "/usr/local/include/curses.h:5: - from "/home/gdr/src/nifty_printer.h:56: - ... - */ - diagnostic_starter_fn begin_diagnostic; - - /* This function is called by diagnostic_show_locus in between - disjoint spans of source code, so that the context can print - something to indicate that a new span of source code has begun. */ - diagnostic_start_span_fn start_span; - - /* This function is called after the diagnostic message is printed. */ - diagnostic_finalizer_fn end_diagnostic; + /* Client-supplied callbacks for use in text output. */ + struct { + /* This function is called before any message is printed out. It is + responsible for preparing message prefix and such. For example, it + might say: + In file included from "/usr/local/include/curses.h:5: + from "/home/gdr/src/nifty_printer.h:56: + ... + */ + diagnostic_starter_fn begin_diagnostic; + + /* This function is called by diagnostic_show_locus in between + disjoint spans of source code, so that the context can print + something to indicate that a new span of source code has begun. */ + diagnostic_start_span_fn start_span; + + /* This function is called after the diagnostic message is printed. */ + diagnostic_finalizer_fn end_diagnostic; + } m_text_callbacks; /* Client hook to report an internal error. */ void (*internal_error) (diagnostic_context *, const char *, va_list *); @@ -402,18 +450,9 @@ struct diagnostic_context diagnostic_group was pushed. */ int diagnostic_group_emission_count; - /* Optional callbacks for handling diagnostic groups. */ - - /* If non-NULL, this will be called immediately before the first - time a diagnostic is emitted within a stack of groups. */ - void (*begin_group_cb) (diagnostic_context * context); - - /* If non-NULL, this will be called when a stack of groups is - popped if any diagnostics were emitted within that group. */ - void (*end_group_cb) (diagnostic_context * context); - - /* Callback for final cleanup. */ - void (*final_cb) (diagnostic_context *context); + /* How to output diagnostics (text vs a structured format such as JSON). + Must be non-NULL; owned by context. */ + diagnostic_output_format *m_output_format; /* Callback to set the locations of call sites along the inlining stack corresponding to a diagnostic location. Needed to traverse @@ -441,9 +480,6 @@ struct diagnostic_context Can be NULL (if text art is disabled). */ text_art::theme *m_theme; - /* Callback for emitting diagrams. */ - void (*m_emission_cb) (diagnostic_context *context, - const diagnostic_diagram &diagram); } m_diagrams; }; @@ -454,12 +490,13 @@ diagnostic_inhibit_notes (diagnostic_context * context) } -/* Client supplied function to announce a diagnostic. */ -#define diagnostic_starter(DC) (DC)->begin_diagnostic +/* Client supplied function to announce a diagnostic + (for text-based diagnostic output). */ +#define diagnostic_starter(DC) (DC)->m_text_callbacks.begin_diagnostic /* Client supplied function called after a diagnostic message is - displayed. */ -#define diagnostic_finalizer(DC) (DC)->end_diagnostic + displayed (for text-based diagnostic output). */ +#define diagnostic_finalizer(DC) (DC)->m_text_callbacks.end_diagnostic /* Extension hooks for client. */ #define diagnostic_context_auxiliary_data(DC) (DC)->x_data @@ -638,6 +675,8 @@ extern void diagnostic_output_format_init_json_file (diagnostic_context *context extern void diagnostic_output_format_init_sarif_stderr (diagnostic_context *context); extern void diagnostic_output_format_init_sarif_file (diagnostic_context *context, const char *base_file_name); +extern void diagnostic_output_format_init_sarif_stream (diagnostic_context *context, + FILE *stream); /* Compute the number of digits in the decimal representation of an integer. */ extern int num_digits (int); diff --git a/gcc/fortran/error.cc b/gcc/fortran/error.cc index 378f7393133..0b6c850e6d9 100644 --- a/gcc/fortran/error.cc +++ b/gcc/fortran/error.cc @@ -1637,7 +1637,7 @@ void gfc_diagnostics_init (void) { diagnostic_starter (global_dc) = gfc_diagnostic_starter; - global_dc->start_span = gfc_diagnostic_start_span; + global_dc->m_text_callbacks.start_span = gfc_diagnostic_start_span; diagnostic_finalizer (global_dc) = gfc_diagnostic_finalizer; diagnostic_format_decoder (global_dc) = gfc_format_decoder; global_dc->m_source_printing.caret_chars[0] = '1'; diff --git a/gcc/input.cc b/gcc/input.cc index eaf301ec7c1..0b00b8923db 100644 --- a/gcc/input.cc +++ b/gcc/input.cc @@ -946,7 +946,7 @@ file_cache_slot::read_line_num (size_t line_num, If the function fails, a NULL char_span is returned. */ char_span -location_get_source_line (const char *file_path, int line) +file_cache::get_source_line (const char *file_path, int line) { char *buffer = NULL; ssize_t len; @@ -957,9 +957,7 @@ location_get_source_line (const char *file_path, int line) if (file_path == NULL) return char_span (NULL, 0); - diagnostic_file_cache_init (); - - file_cache_slot *c = global_dc->m_file_cache->lookup_or_add_file (file_path); + file_cache_slot *c = lookup_or_add_file (file_path); if (c == NULL) return char_span (NULL, 0); @@ -970,6 +968,13 @@ location_get_source_line (const char *file_path, int line) return char_span (buffer, len); } +char_span +location_get_source_line (const char *file_path, int line) +{ + diagnostic_file_cache_init (); + return global_dc->m_file_cache->get_source_line (file_path, line); +} + /* Return a NUL-terminated copy of the source text between two locations, or NULL if the arguments are invalid. The caller is responsible for freeing the return value. */ @@ -1062,6 +1067,15 @@ get_source_text_between (location_t start, location_t end) return xstrdup (buf); } + +char_span +file_cache::get_source_file_content (const char *file_path) +{ + file_cache_slot *c = lookup_or_add_file (file_path); + return c->get_full_file_content (); +} + + /* Get a borrowed char_span to the full content of FILE_PATH as decoded according to the input charset, encoded as UTF-8. */ @@ -1069,9 +1083,7 @@ char_span get_source_file_content (const char *file_path) { diagnostic_file_cache_init (); - - file_cache_slot *c = global_dc->m_file_cache->lookup_or_add_file (file_path); - return c->get_full_file_content (); + return global_dc->m_file_cache->get_source_file_content (file_path); } /* Determine if FILE_PATH missing a trailing newline on its final line. diff --git a/gcc/input.h b/gcc/input.h index d1087b7a9e8..bfd71dfd619 100644 --- a/gcc/input.h +++ b/gcc/input.h @@ -150,6 +150,9 @@ class file_cache void initialize_input_context (diagnostic_input_charset_callback ccb, bool should_skip_bom); + char_span get_source_file_content (const char *file_path); + char_span get_source_line (const char *file_path, int line); + private: file_cache_slot *evicted_cache_tab_entry (unsigned *highest_use_count); file_cache_slot *add_file (const char *file_path); diff --git a/gcc/jit/dummy-frontend.cc b/gcc/jit/dummy-frontend.cc index 8b7294e32cc..a729086bafb 100644 --- a/gcc/jit/dummy-frontend.cc +++ b/gcc/jit/dummy-frontend.cc @@ -589,8 +589,8 @@ jit_langhook_init (void) } gcc_assert (global_dc); - global_dc->begin_diagnostic = jit_begin_diagnostic; - global_dc->end_diagnostic = jit_end_diagnostic; + diagnostic_starter (global_dc) = jit_begin_diagnostic; + diagnostic_finalizer (global_dc) = jit_end_diagnostic; build_common_tree_nodes (false); diff --git a/gcc/selftest-diagnostic.cc b/gcc/selftest-diagnostic.cc index 5469e555fc0..d632c51b2d9 100644 --- a/gcc/selftest-diagnostic.cc +++ b/gcc/selftest-diagnostic.cc @@ -39,7 +39,7 @@ test_diagnostic_context::test_diagnostic_context () m_source_printing.enabled = true; m_source_printing.show_labels_p = true; show_column = true; - start_span = start_span_cb; + m_text_callbacks.start_span = start_span_cb; m_source_printing.min_margin_width = 6; m_source_printing.max_width = 80; } diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic_group_plugin.c b/gcc/testsuite/gcc.dg/plugin/diagnostic_group_plugin.c index 3396b384163..0a4f25efe24 100644 --- a/gcc/testsuite/gcc.dg/plugin/diagnostic_group_plugin.c +++ b/gcc/testsuite/gcc.dg/plugin/diagnostic_group_plugin.c @@ -181,27 +181,31 @@ test_diagnostic_start_span_fn (diagnostic_context *context, pp_newline (context->printer); } -/* Custom diagnostic callback: loudly announce a new diagnostic group. */ +/* Custom output format subclass. */ -static void -test_begin_group_cb (diagnostic_context * context) +class test_output_format : public diagnostic_text_output_format { - pp_string (context->printer, - "================================= BEGIN GROUP =============================="); - pp_newline (context->printer); -} - -/* Custom diagnostic callback: loudly announce the end of a - diagnostic group. */ + public: + test_output_format (diagnostic_context &context) + : diagnostic_text_output_format (context) + {} -static void -test_end_group_cb (diagnostic_context * context) -{ - pp_set_prefix (context->printer, NULL); - pp_string (context->printer, - "---------------------------------- END GROUP -------------------------------"); - pp_newline_and_flush (context->printer); -} + void on_begin_group () final override + { + /* Loudly announce a new diagnostic group. */ + pp_string (m_context.printer, + "================================= BEGIN GROUP =============================="); + pp_newline (m_context.printer); + } + void on_end_group () final override + { + /* Loudly announce the end of a diagnostic group. */ + pp_set_prefix (m_context.printer, NULL); + pp_string (m_context.printer, + "---------------------------------- END GROUP -------------------------------"); + pp_newline_and_flush (m_context.printer); + } +}; /* Entrypoint for the plugin. Install custom callbacks into the global_dc. @@ -220,9 +224,8 @@ plugin_init (struct plugin_name_args *plugin_info, return 1; diagnostic_starter (global_dc) = test_diagnostic_starter; - global_dc->start_span = test_diagnostic_start_span_fn; - global_dc->begin_group_cb = test_begin_group_cb; - global_dc->end_group_cb = test_end_group_cb; + global_dc->m_text_callbacks.start_span = test_diagnostic_start_span_fn; + global_dc->m_output_format = new test_output_format (*global_dc); pass_info.pass = new pass_test_groups (g); pass_info.reference_pass_name = "*warn_function_noreturn"; diff --git a/gcc/tree-diagnostic-path.cc b/gcc/tree-diagnostic-path.cc index b1b483a27aa..97ee0f04091 100644 --- a/gcc/tree-diagnostic-path.cc +++ b/gcc/tree-diagnostic-path.cc @@ -206,7 +206,7 @@ struct event_range = linemap_client_expand_location_to_spelling_point (initial_loc, LOCATION_ASPECT_CARET); if (exploc.file != LOCATION_FILE (dc->last_location)) - dc->start_span (dc, exploc); + dc->m_text_callbacks.start_span (dc, exploc); } /* If we have an UNKNOWN_LOCATION (or BUILTINS_LOCATION) as the