Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2196540/?format=api
{ "id": 2196540, "url": "http://patchwork.ozlabs.org/api/patches/2196540/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/patch/20260214155201.1049644-5-dmalcolm@redhat.com/", "project": { "id": 17, "url": "http://patchwork.ozlabs.org/api/projects/17/?format=api", "name": "GNU Compiler Collection", "link_name": "gcc", "list_id": "gcc-patches.gcc.gnu.org", "list_email": "gcc-patches@gcc.gnu.org", "web_url": null, "scm_url": null, "webscm_url": null, "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20260214155201.1049644-5-dmalcolm@redhat.com>", "list_archive_url": null, "date": "2026-02-14T15:52:00", "name": "[4/5] Add json-diagnostic.{cc,h}", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "4ffc111b3017804322f5df1b4fefcc14da3c45ea", "submitter": { "id": 24465, "url": "http://patchwork.ozlabs.org/api/people/24465/?format=api", "name": "David Malcolm", "email": "dmalcolm@redhat.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/gcc/patch/20260214155201.1049644-5-dmalcolm@redhat.com/mbox/", "series": [ { "id": 492183, "url": "http://patchwork.ozlabs.org/api/series/492183/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/list/?series=492183", "date": "2026-02-14T15:51:56", "name": "Improve diagnostics for bad JSON inputs [PR124094]", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/492183/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2196540/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2196540/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "gcc-patches@gcc.gnu.org" ], "Delivered-To": [ "patchwork-incoming@legolas.ozlabs.org", "gcc-patches@gcc.gnu.org" ], "Authentication-Results": [ "legolas.ozlabs.org;\n\tdkim=pass (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=A7HAjH5S;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org\n (client-ip=2620:52:6:3111::32; helo=vm01.sourceware.org;\n envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org;\n receiver=patchwork.ozlabs.org)", "sourceware.org;\n\tdkim=pass (1024-bit key,\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=A7HAjH5S", "sourceware.org; dmarc=pass (p=quarantine dis=none)\n header.from=redhat.com", "sourceware.org; spf=pass smtp.mailfrom=redhat.com", "server2.sourceware.org;\n arc=none smtp.remote-ip=170.10.133.124" ], "Received": [ "from vm01.sourceware.org (vm01.sourceware.org\n [IPv6:2620:52:6:3111::32])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fCtw86bkwz1xpl\n\tfor <incoming@patchwork.ozlabs.org>; Sun, 15 Feb 2026 02:57:28 +1100 (AEDT)", "from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id EB1D94B9DB7F\n\tfor <incoming@patchwork.ozlabs.org>; Sat, 14 Feb 2026 15:57:26 +0000 (GMT)", "from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.133.124])\n by sourceware.org (Postfix) with ESMTP id 427004BAD169\n for <gcc-patches@gcc.gnu.org>; Sat, 14 Feb 2026 15:52:30 +0000 (GMT)", "from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com\n (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by\n relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3,\n cipher=TLS_AES_256_GCM_SHA384) id us-mta-52-5pG0BbG5OZGwd7tVIWI23g-1; Sat,\n 14 Feb 2026 10:52:24 -0500", "from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com\n (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest\n SHA256)\n (No client certificate requested)\n by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS\n id B3FB91956053; Sat, 14 Feb 2026 15:52:22 +0000 (UTC)", "from t14s.localdomain.com (unknown [10.22.88.22])\n by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP\n id D789C1955D85; Sat, 14 Feb 2026 15:52:19 +0000 (UTC)" ], "DKIM-Filter": [ "OpenDKIM Filter v2.11.0 sourceware.org EB1D94B9DB7F", "OpenDKIM Filter v2.11.0 sourceware.org 427004BAD169" ], "DMARC-Filter": "OpenDMARC Filter v1.4.2 sourceware.org 427004BAD169", "ARC-Filter": "OpenARC Filter v1.0.0 sourceware.org 427004BAD169", "ARC-Seal": "i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1771084355; cv=none;\n b=xSx8GRfjpbB0ATE/7MIwc7R2UcrpTyvb1Y4uETG6+QC5drFS/mLvswVIvZ2/hWUP7QHA2pmhzmVIM+dH8KrVPwFUDOBgJl32/zuXIXXMNQcy7T1V+C+Hk3lMtpGbfsntKroNtBcfG5G1PgycopBL6/WJW55We4lDN9Vnbe5rSdI=", "ARC-Message-Signature": "i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1771084355; c=relaxed/simple;\n bh=dYHotCI7Yz7tIGBjGb/CBLBQdRopOPWkuOXy/QyWLh8=;\n h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version;\n b=s398A86HUFNYqUeYsgnrf9CK3xzt/GLWv/qn773xToPXLtfVBfeoKiwV76tV00gNcPve/b0qxYE/LdvHuI3wSuKTPCRU1Mb8LBoMw8YWk9mCW4OexRDqCqivPPXNYQRtoMc50wjIy6HpyIO0GdcWDl2Am4ql62MUA0j9MmCGdtI=", "ARC-Authentication-Results": "i=1; server2.sourceware.org", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1771084349;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:cc:mime-version:mime-version:content-type:content-type:\n content-transfer-encoding:content-transfer-encoding:\n in-reply-to:in-reply-to:references:references;\n bh=7zuC5/q4sEyUZwNLDjerarWXYaYE3wxohYnVDG/2X34=;\n b=A7HAjH5SU525BV1v3UVt/othXqUT+DOSIzx2YcaQog0yxQfTiujuj6QAzp5vu8Swu4Y4ep\n nsczQH3QtQnagvbsMBDlPHyoVQkS9UVg4M34dmpHEjUF/0s5wMctr3NOC3EfvteFnffVFB\n YIvZQc5QqKmcc901RQcC/wQr8ifsPA4=", "X-MC-Unique": "5pG0BbG5OZGwd7tVIWI23g-1", "X-Mimecast-MFC-AGG-ID": "5pG0BbG5OZGwd7tVIWI23g_1771084343", "From": "David Malcolm <dmalcolm@redhat.com>", "To": "gcc-patches@gcc.gnu.org, Yangyu Chen <cyy@cyyself.name>,\n Soumya AR <soumyaa@nvidia.com>, jakub@redhat.com,\n Richard Biener <richard.guenther@gmail.com>", "Cc": "Alfie Richards <alfie.richards@arm.com>,\n Sandra Loosemore <sloosemore@baylibre.com>,\n Martin Liska <martin.liska@hey.com>,\n Evgeny Stupachenko <evstupac@gmail.com>,\n Alice Carlotti <alice.carlotti@arm.com>,\n Jeff Law <jeffrey.law@oss.qualcomm.com>,\n Jerry DeLisle <jvdelisle@gcc.gnu.org>, Harald Anlauf <anlauf@gmx.de>,\n Paul Thomas <pault@gcc.gnu.org>,\n Richard Sandiford <rdsandiford@googlemail.com>,\n Joseph Myers <josmyers@redhat.com>, Jason Merrill <jason@redhat.com>,\n David Malcolm <dmalcolm@redhat.com>", "Subject": "[PATCH 4/5] Add json-diagnostic.{cc,h}", "Date": "Sat, 14 Feb 2026 10:52:00 -0500", "Message-ID": "<20260214155201.1049644-5-dmalcolm@redhat.com>", "In-Reply-To": "<20260214155201.1049644-1-dmalcolm@redhat.com>", "References": "<tencent_048DF6A8630E2E590C79C840A31F1FA86006@qq.com>\n <20260214155201.1049644-1-dmalcolm@redhat.com>", "MIME-Version": "1.0", "X-Scanned-By": "MIMEDefang 3.0 on 10.30.177.17", "X-Mimecast-Spam-Score": "0", "X-Mimecast-MFC-PROC-ID": "9L_EByHSz01U7w6vy6ZdtPQHDudKgn71QvBCpPqmFwU_1771084343", "X-Mimecast-Originator": "redhat.com", "Content-Transfer-Encoding": "8bit", "content-type": "text/plain; charset=\"US-ASCII\"; x-default=true", "X-BeenThere": "gcc-patches@gcc.gnu.org", "X-Mailman-Version": "2.1.30", "Precedence": "list", "List-Id": "Gcc-patches mailing list <gcc-patches.gcc.gnu.org>", "List-Unsubscribe": "<https://gcc.gnu.org/mailman/options/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe>", "List-Archive": "<https://gcc.gnu.org/pipermail/gcc-patches/>", "List-Post": "<mailto:gcc-patches@gcc.gnu.org>", "List-Help": "<mailto:gcc-patches-request@gcc.gnu.org?subject=help>", "List-Subscribe": "<https://gcc.gnu.org/mailman/listinfo/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe>", "Errors-To": "gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org" }, "content": "This patch adds support for emitting diagnostics about JSON input files\nto global_dc, showing both the file/line/columns and the JSON Pointer\nfor the problematic json::value. Test coverage is added by the followup\non aarch64.\n\ngcc/ChangeLog:\n\t* Makefile.in (OBJS-libcommon): Add json-diagnostic.o.\n\t* diagnostics/client-data-hooks.h\n\t(class client_data_hooks_decorator): New.\n\t* diagnostics/context.cc (context::set_client_data_hooks): Return\n\tthe old hooks.\n\t* diagnostics/context.h (context::set_client_data_hooks): Update\n\tdecl likewise.\n\t* json-diagnostic.cc: New file.\n\t* json-diagnostic.h: New file.\n\nSigned-off-by: David Malcolm <dmalcolm@redhat.com>\n---\n gcc/Makefile.in | 2 +-\n gcc/diagnostics/client-data-hooks.h | 53 ++++\n gcc/diagnostics/context.cc | 5 +-\n gcc/diagnostics/context.h | 4 +-\n gcc/json-diagnostic.cc | 374 ++++++++++++++++++++++++++++\n gcc/json-diagnostic.h | 74 ++++++\n 6 files changed, 508 insertions(+), 4 deletions(-)\n create mode 100644 gcc/json-diagnostic.cc\n create mode 100644 gcc/json-diagnostic.h", "diff": "diff --git a/gcc/Makefile.in b/gcc/Makefile.in\nindex 54865765b6ef6..d4170dd7a3262 100644\n--- a/gcc/Makefile.in\n+++ b/gcc/Makefile.in\n@@ -1905,7 +1905,7 @@ OBJS-libcommon = \\\n \tgcc-diagnostic-spec.o \\\n \tgraphviz.o pex.o \\\n \tpretty-print.o intl.o \\\n-\tjson.o json-parsing.o \\\n+\tjson.o json-parsing.o json-diagnostic.o \\\n \tpub-sub.o \\\n \txml.o \\\n \tsbitmap.o \\\ndiff --git a/gcc/diagnostics/client-data-hooks.h b/gcc/diagnostics/client-data-hooks.h\nindex 6fa31d0d65e00..bd760dcb70bba 100644\n--- a/gcc/diagnostics/client-data-hooks.h\n+++ b/gcc/diagnostics/client-data-hooks.h\n@@ -63,6 +63,59 @@ class client_data_hooks\n add_sarif_invocation_properties (sarif_object &invocation_obj) const = 0;\n };\n \n+/* Implementation of client_data_hooks that delegates vfuncs to an\n+ optional inner object. */\n+\n+class client_data_hooks_decorator : public client_data_hooks\n+{\n+ public:\n+ client_data_hooks_decorator (const client_data_hooks *inner)\n+ : m_inner (inner)\n+ {\n+ }\n+\n+ const client_version_info *get_any_version_info () const override\n+ {\n+ if (m_inner)\n+ return m_inner->get_any_version_info ();\n+ return nullptr;\n+ }\n+\n+ const logical_locations::manager *\n+ get_logical_location_manager () const override\n+ {\n+ if (m_inner)\n+ return m_inner->get_logical_location_manager ();\n+ return nullptr;\n+ }\n+\n+ logical_locations::key\n+ get_current_logical_location () const override\n+ {\n+ if (m_inner)\n+ return m_inner->get_current_logical_location ();\n+ return logical_locations::key ();\n+ }\n+\n+ const char *\n+ maybe_get_sarif_source_language (const char *filename) const override\n+ {\n+ if (m_inner)\n+ return m_inner->maybe_get_sarif_source_language (filename);\n+ return nullptr;\n+ }\n+\n+ void\n+ add_sarif_invocation_properties (sarif_object &invocation_obj) const override\n+ {\n+ if (m_inner)\n+ m_inner->add_sarif_invocation_properties (invocation_obj);\n+ }\n+\n+private:\n+ const client_data_hooks *m_inner;\n+};\n+\n class client_plugin_info;\n \n /* Abstract base class for a diagnostics::context to get at\ndiff --git a/gcc/diagnostics/context.cc b/gcc/diagnostics/context.cc\nindex 03d570665843d..98af6ecb1b665 100644\n--- a/gcc/diagnostics/context.cc\n+++ b/gcc/diagnostics/context.cc\n@@ -529,12 +529,13 @@ context::set_main_input_filename (const char *filename)\n sink_->set_main_input_filename (filename);\n }\n \n-void\n+std::unique_ptr<client_data_hooks>\n context::set_client_data_hooks (std::unique_ptr<client_data_hooks> hooks)\n {\n- delete m_client_data_hooks;\n+ std::unique_ptr<client_data_hooks> old_hooks (m_client_data_hooks);\n /* Ideally the field would be a std::unique_ptr here. */\n m_client_data_hooks = hooks.release ();\n+ return old_hooks;\n }\n \n void\ndiff --git a/gcc/diagnostics/context.h b/gcc/diagnostics/context.h\nindex 742319fbd204f..514ff1e68f9b8 100644\n--- a/gcc/diagnostics/context.h\n+++ b/gcc/diagnostics/context.h\n@@ -388,7 +388,9 @@ public:\n /* Various setters for use by option-handling logic. */\n void set_sink (std::unique_ptr<sink> sink_);\n void set_text_art_charset (enum diagnostic_text_art_charset charset);\n- void set_client_data_hooks (std::unique_ptr<client_data_hooks> hooks);\n+\n+ std::unique_ptr<client_data_hooks>\n+ set_client_data_hooks (std::unique_ptr<client_data_hooks> hooks);\n \n void push_owned_urlifier (std::unique_ptr<urlifier>);\n void push_borrowed_urlifier (const urlifier &);\ndiff --git a/gcc/json-diagnostic.cc b/gcc/json-diagnostic.cc\nnew file mode 100644\nindex 0000000000000..bf61cd0007ecf\n--- /dev/null\n+++ b/gcc/json-diagnostic.cc\n@@ -0,0 +1,374 @@\n+/* Diagnostics relating to JSON values.\n+ Copyright (C) 2026 Free Software Foundation, Inc.\n+ Contributed by David Malcolm <dmalcolm@redhat.com>.\n+\n+This file is part of GCC.\n+\n+GCC is free software; you can redistribute it and/or modify it under\n+the terms of the GNU General Public License as published by the Free\n+Software Foundation; either version 3, or (at your option) any later\n+version.\n+\n+GCC is distributed in the hope that it will be useful, but WITHOUT ANY\n+WARRANTY; without even the implied warranty of MERCHANTABILITY or\n+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License\n+for more details.\n+\n+You should have received a copy of the GNU General Public License\n+along with GCC; see the file COPYING3. If not see\n+<http://www.gnu.org/licenses/>. */\n+\n+#define INCLUDE_MAP\n+#define INCLUDE_STRING\n+#define INCLUDE_VECTOR\n+#include \"config.h\"\n+#include \"system.h\"\n+#include \"coretypes.h\"\n+#include \"intl.h\"\n+#include \"diagnostic.h\"\n+#include \"json-diagnostic.h\"\n+#include \"diagnostics/dumping.h\"\n+#include \"diagnostics/logging.h\"\n+#include \"diagnostics/logical-locations.h\"\n+#include \"diagnostics/client-data-hooks.h\"\n+#include \"diagnostics/text-sink.h\"\n+#include \"diagnostics/physical-location-maker.h\"\n+#include \"pretty-print-markup.h\"\n+\n+static bool\n+emit_json_diagnostic (gcc_json_context &ctxt,\n+\t\t enum diagnostics::kind kind,\n+\t\t const json::value &js_val,\n+\t\t diagnostics::option_id option_id,\n+\t\t const char *gmsgid, va_list *ap)\n+ ATTRIBUTE_GCC_DIAG(5,0);\n+\n+using log_function_params = diagnostics::logging::log_function_params;\n+using auto_inc_log_depth = diagnostics::logging::auto_inc_depth;\n+\n+class json_logical_location_manager\n+ : public diagnostics::logical_locations::manager\n+{\n+public:\n+ using key = diagnostics::logical_locations::key;\n+ using kind = diagnostics::logical_locations::kind;\n+\n+ void\n+ dump (FILE *outfile, int indent) const final override\n+ {\n+ diagnostics::dumping::emit_heading (outfile, indent,\n+\t\t\t\t\t\"json_logical_location_manager\");\n+ }\n+\n+ label_text\n+ get_short_name (key k) const final override\n+ {\n+ auto *js_val = js_from_key (k);\n+ const json::pointer::token &pointer_token = js_val->get_pointer_token ();\n+ pretty_printer pp;\n+ pointer_token.print (&pp);\n+ return label_text::take (xstrdup (pp_formatted_text (&pp)));\n+ }\n+\n+ label_text\n+ get_name_with_scope (key k) const final override\n+ {\n+ auto *js_val = js_from_key (k);\n+ pretty_printer pp;\n+ js_val->print_pointer (&pp);\n+ return label_text::take (xstrdup (pp_formatted_text (&pp)));\n+ }\n+\n+ label_text\n+ get_internal_name (key) const final override\n+ {\n+ return label_text ();\n+ }\n+\n+ kind\n+ get_kind (key k) const final override\n+ {\n+ auto *js_val = js_from_key (k);\n+\n+ switch (js_val->get_kind ())\n+ {\n+ default:\n+\tgcc_unreachable ();\n+\n+ case json::JSON_OBJECT:\n+\treturn kind::object;\n+\n+ case json::JSON_ARRAY:\n+\treturn kind::array;\n+\n+ case json::JSON_INTEGER:\n+ case json::JSON_FLOAT:\n+ case json::JSON_STRING:\n+ case json::JSON_TRUE:\n+ case json::JSON_FALSE:\n+ case json::JSON_NULL:\n+\treturn kind::property;\n+ }\n+ }\n+\n+ label_text\n+ get_name_for_path_output (key k) const final override\n+ {\n+ return get_name_with_scope (k);\n+ }\n+\n+ key\n+ get_parent (key k) const final override\n+ {\n+ auto *js_val = js_from_key (k);\n+ auto &pointer_token = js_val->get_pointer_token ();\n+ return key_from_js (pointer_token.m_parent);\n+ }\n+\n+ static const json::value *\n+ js_from_key (key k)\n+ {\n+ return k.cast_to<const json::value *> ();\n+ }\n+\n+ static key\n+ key_from_js (const json::value *js_val)\n+ {\n+ return key::from_ptr (js_val);\n+ }\n+\n+private:\n+ static void\n+ print_json_pointer_token (pretty_printer *);\n+};\n+\n+/* Implementation of diagnostics::client_data_hooks\n+ for reporting a diagnostic at a particular json::value\n+ in a JSON input file.\n+\n+ It wraps another hooks instance, but uses a\n+ json_logical_location_manager, has a specific\n+ json::value for the current logical location,\n+ and treats the SARIF source lang as \"json\". */\n+\n+class json_client_data_hooks : public diagnostics::client_data_hooks_decorator\n+{\n+public:\n+ json_client_data_hooks (const json::value &js_val,\n+\t\t\t const client_data_hooks *inner)\n+ : diagnostics::client_data_hooks_decorator (inner),\n+ m_js_val (js_val)\n+ {}\n+\n+ const diagnostics::logical_locations::manager *\n+ get_logical_location_manager () const override\n+ {\n+ return &m_logical_loc_mgr;\n+ }\n+\n+ diagnostics::logical_locations::key\n+ get_current_logical_location () const override\n+ {\n+ /* Use the json value's pointer as the key. */\n+ return json_logical_location_manager::key_from_js (&m_js_val);\n+ }\n+\n+ const char *\n+ maybe_get_sarif_source_language (const char *) const override\n+ {\n+ return \"json\";\n+ }\n+\n+private:\n+ json_logical_location_manager m_logical_loc_mgr;\n+ const json::value &m_js_val;\n+};\n+\n+namespace pp_markup {\n+\n+/* Print the JSON Pointer of a given json::value in quotes. */\n+\n+class quoted_json_pointer : public pp_element\n+{\n+public:\n+ quoted_json_pointer (const json::value &js_val)\n+ : m_js_val (js_val)\n+ {\n+ }\n+\n+ void\n+ add_to_phase_2 (context &ctxt) final override\n+ {\n+ ctxt.begin_quote ();\n+ m_js_val.print_pointer (&ctxt.m_pp);\n+ ctxt.end_quote ();\n+ }\n+\n+private:\n+ const json::value &m_js_val;\n+};\n+\n+} // namespace pp_markup\n+\n+/* text_sink starter for diagnostics relating to JSON. */\n+\n+static void\n+json_text_starter (diagnostics::text_sink &sink,\n+\t\t const diagnostics::diagnostic_info *diagnostic)\n+{\n+ pretty_printer *pp = sink.get_printer ();\n+\n+ /* If this isn't the root value, report its json pointer. */\n+ diagnostics::logical_locations::key k;\n+ if (auto data_hooks = sink.get_context ().get_client_data_hooks ())\n+ k = data_hooks->get_current_logical_location ();\n+ const json::value *js_val = json_logical_location_manager::js_from_key (k);\n+ if (js_val && js_val->get_pointer_token ().m_parent)\n+ {\n+ const char *file = LOCATION_FILE (diagnostic_location (diagnostic));\n+ char *new_prefix = file ? sink.file_name_as_prefix (file) : nullptr;\n+ pp_set_prefix (pp, new_prefix);\n+\n+ pp_markup::quoted_json_pointer e (*js_val);\n+ switch (js_val->get_kind ())\n+\t{\n+\tdefault:\n+\t pp_printf (pp, _(\"In JSON value %e\"), &e);\n+\t break;\n+\tcase json::JSON_OBJECT:\n+\t pp_printf (pp, _(\"In JSON object %e\"), &e);\n+\t break;\n+\tcase json::JSON_ARRAY:\n+\t pp_printf (pp, _(\"In JSON array %e\"), &e);\n+\t break;\n+\t}\n+ pp_newline (pp);\n+ }\n+\n+ pp_set_prefix (pp, sink.build_prefix (*diagnostic));\n+}\n+\n+\n+/* class gcc_json_context : public json::simple_location_map. */\n+\n+location_t\n+gcc_json_context::make_location_for_point (const json::location_map::point &p)\n+{\n+ diagnostics::physical_location_maker m (line_table);\n+ return m.new_location_from_file_line_column (m_filename,\n+\t\t\t\t\t p.m_line,\n+\t\t\t\t\t p.m_column + 1);\n+}\n+\n+location_t\n+gcc_json_context::make_location_for_range (const json::location_map::range &r)\n+{\n+ location_t start_loc = make_location_for_point (r.m_start);\n+ location_t end_loc = make_location_for_point (r.m_end);\n+ return make_location (start_loc, start_loc, end_loc);\n+}\n+\n+/* Emit a diagnostic on global_dc of the relevant KIND relating to JS_VAL,\n+ using CTXT to get at file/line/column info.\n+\n+ Temporarily override global_dc's logical location to refer to JS_VAL\n+ and the text_sink starter and finalizer to be suitable for handling\n+ reporting within a JSON file. */\n+\n+static bool\n+emit_json_diagnostic (gcc_json_context &ctxt,\n+\t\t enum diagnostics::kind kind,\n+\t\t const json::value &js_val,\n+\t\t diagnostics::option_id option_id,\n+\t\t const char *gmsgid, va_list *ap)\n+{\n+ auto logger = global_dc->get_logger ();\n+ log_function_params (logger, __func__)\n+ .log_param_option_id (\"option_id\", option_id)\n+ .log_param_string (\"gmsgid\", gmsgid);\n+ auto_inc_log_depth depth_sentinel (logger);\n+\n+ auto_diagnostic_group d;\n+\n+ // Get physical location for JS_VAL.\n+ location_t phys_loc\n+ = ctxt.make_location_for_range (ctxt.get_range_for_value (js_val));\n+ rich_location richloc (line_table, phys_loc);\n+\n+ // Set logical location by overriding client data hooks\n+ auto tmp_client_data_hooks\n+ = std::make_unique<json_client_data_hooks>\n+\t(js_val, global_dc->get_client_data_hooks ());\n+ auto old_client_data_hooks\n+ = global_dc->set_client_data_hooks (std::move (tmp_client_data_hooks));\n+\n+ // Override text hooks\n+ auto old_text_starter = text_starter (global_dc);\n+ auto old_text_finalizer = text_finalizer (global_dc);\n+ text_starter (global_dc) = json_text_starter;\n+ text_finalizer (global_dc) = diagnostics::default_text_finalizer;\n+\n+ bool ret = global_dc->diagnostic_impl (&richloc, nullptr, option_id,\n+\t\t\t\t\t gmsgid, ap, kind);\n+\n+ // Restore old text and client data hooks:\n+ text_starter (global_dc) = old_text_starter;\n+ text_finalizer (global_dc) = old_text_finalizer;\n+ global_dc->set_client_data_hooks (std::move (old_client_data_hooks));\n+\n+ if (logger)\n+ logger->log_bool_return (\"emit_diagnostic\", ret);\n+\n+ return ret;\n+}\n+\n+\n+/* Emit an error on gcc's global_dc relating to JS_VAL. */\n+\n+void\n+json_error (gcc_json_context &ctxt,\n+\t const json::value &js_val,\n+\t const char *gmsgid, ...)\n+{\n+ va_list ap;\n+ va_start (ap, gmsgid);\n+ emit_json_diagnostic (ctxt,\n+\t\t\tdiagnostics::kind::error,\n+\t\t\tjs_val, -1,\n+\t\t\tgmsgid, &ap);\n+ va_end (ap);\n+}\n+\n+/* Emit a warning on gcc's global_dc relating to JS_VAL. */\n+\n+bool\n+json_warning (gcc_json_context &ctxt,\n+\t const json::value &js_val,\n+\t diagnostics::option_id option_id,\n+\t const char *gmsgid, ...)\n+{\n+ va_list ap;\n+ va_start (ap, gmsgid);\n+ bool ret = emit_json_diagnostic (ctxt,\n+\t\t\t\t diagnostics::kind::warning,\n+\t\t\t\t js_val, option_id,\n+\t\t\t\t gmsgid, &ap);\n+ va_end (ap);\n+ return ret;\n+}\n+\n+/* Emit a note on gcc's global_dc relating to JS_VAL. */\n+\n+void\n+json_note (gcc_json_context &ctxt,\n+\t const json::value &js_val,\n+\t const char *gmsgid, ...)\n+{\n+ va_list ap;\n+ va_start (ap, gmsgid);\n+ emit_json_diagnostic (ctxt,\n+\t\t\tdiagnostics::kind::note,\n+\t\t\tjs_val, -1,\n+\t\t\tgmsgid, &ap);\n+ va_end (ap);\n+}\ndiff --git a/gcc/json-diagnostic.h b/gcc/json-diagnostic.h\nnew file mode 100644\nindex 0000000000000..1773ee0a0fd50\n--- /dev/null\n+++ b/gcc/json-diagnostic.h\n@@ -0,0 +1,74 @@\n+/* Diagnostics relating to JSON values.\n+ Copyright (C) 2026 Free Software Foundation, Inc.\n+ Contributed by David Malcolm <dmalcolm@redhat.com>.\n+\n+This file is part of GCC.\n+\n+GCC is free software; you can redistribute it and/or modify it under\n+the terms of the GNU General Public License as published by the Free\n+Software Foundation; either version 3, or (at your option) any later\n+version.\n+\n+GCC is distributed in the hope that it will be useful, but WITHOUT ANY\n+WARRANTY; without even the implied warranty of MERCHANTABILITY or\n+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License\n+for more details.\n+\n+You should have received a copy of the GNU General Public License\n+along with GCC; see the file COPYING3. If not see\n+<http://www.gnu.org/licenses/>. */\n+\n+#ifndef GCC_JSON_DIAGNOSTIC_H\n+#define GCC_JSON_DIAGNOSTIC_H\n+\n+#include \"json-parsing.h\"\n+\n+/* Implementation of json::location_map for use with\n+ GCC diagnostics.\n+ Stores location information for json::value * from parsing, and\n+ can generate location_t values for the. */\n+\n+class gcc_json_context : public json::simple_location_map\n+{\n+public:\n+ gcc_json_context (const char *filename)\n+ : m_filename (filename)\n+ {\n+ }\n+\n+ location_t\n+ make_location_for_point (const json::location_map::point &);\n+\n+ location_t\n+ make_location_for_range (const json::location_map::range &);\n+\n+private:\n+ const char *m_filename;\n+};\n+\n+/* Emit an error on gcc's global_dc relating to JS_VAL. */\n+\n+extern void\n+json_error (gcc_json_context &ctxt,\n+\t const json::value &js_val,\n+\t const char *gmsgid, ...)\n+ ATTRIBUTE_GCC_DIAG(3,4);\n+\n+/* Emit a warning on gcc's global_dc relating to JS_VAL. */\n+\n+extern bool\n+json_warning (gcc_json_context &ctxt,\n+\t const json::value &js_val,\n+\t diagnostics::option_id option_id,\n+\t const char *gmsgid, ...)\n+ ATTRIBUTE_GCC_DIAG(4,5);\n+\n+/* Emit a note on gcc's global_dc relating to JS_VAL. */\n+\n+extern void\n+json_note (gcc_json_context &ctxt,\n+\t const json::value &js_val,\n+\t const char *gmsgid, ...)\n+ ATTRIBUTE_GCC_DIAG(3,4);\n+\n+#endif /* GCC_JSON_DIAGNOSTIC_H */\n", "prefixes": [ "4/5" ] }