get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/1.1/patches/2229945/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 2229945,
    "url": "http://patchwork.ozlabs.org/api/1.1/patches/2229945/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/gcc/patch/20260428232811.1953975-1-dmalcolm@redhat.com/",
    "project": {
        "id": 17,
        "url": "http://patchwork.ozlabs.org/api/1.1/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
    },
    "msgid": "<20260428232811.1953975-1-dmalcolm@redhat.com>",
    "date": "2026-04-28T23:28:11",
    "name": "[pushed:,r17-183] analyzer: split out various pending_diagnostic subclasses from region-model.cc",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "7dbeaf92e9e94a99a0ca1ccaebdcec42a2b394c6",
    "submitter": {
        "id": 24465,
        "url": "http://patchwork.ozlabs.org/api/1.1/people/24465/?format=api",
        "name": "David Malcolm",
        "email": "dmalcolm@redhat.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/gcc/patch/20260428232811.1953975-1-dmalcolm@redhat.com/mbox/",
    "series": [
        {
            "id": 501954,
            "url": "http://patchwork.ozlabs.org/api/1.1/series/501954/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/gcc/list/?series=501954",
            "date": "2026-04-28T23:28:11",
            "name": "[pushed:,r17-183] analyzer: split out various pending_diagnostic subclasses from region-model.cc",
            "version": 1,
            "mbox": "http://patchwork.ozlabs.org/series/501954/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2229945/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2229945/checks/",
    "tags": {},
    "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=PIZTNeCq;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org\n (client-ip=38.145.34.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=PIZTNeCq",
            "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.129.124"
        ],
        "Received": [
            "from vm01.sourceware.org (vm01.sourceware.org [38.145.34.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 4g4xTJ6Dd1z1yHv\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 29 Apr 2026 09:28:52 +1000 (AEST)",
            "from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id D5B2B4BBCD81\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 28 Apr 2026 23:28:50 +0000 (GMT)",
            "from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.129.124])\n by sourceware.org (Postfix) with ESMTP id 5D8864BBC0BB\n for <gcc-patches@gcc.gnu.org>; Tue, 28 Apr 2026 23:28:16 +0000 (GMT)",
            "from mx-prod-mc-05.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-553-nBdAHjSzM5igiR0b920N-Q-1; Tue,\n 28 Apr 2026 19:28:14 -0400",
            "from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com\n (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111])\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-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS\n id BD26E1956095\n for <gcc-patches@gcc.gnu.org>; Tue, 28 Apr 2026 23:28:13 +0000 (UTC)",
            "from t14s.localdomain.com (unknown [10.22.65.168])\n by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP\n id 1F917180045E; Tue, 28 Apr 2026 23:28:13 +0000 (UTC)"
        ],
        "DKIM-Filter": [
            "OpenDKIM Filter v2.11.0 sourceware.org D5B2B4BBCD81",
            "OpenDKIM Filter v2.11.0 sourceware.org 5D8864BBC0BB"
        ],
        "DMARC-Filter": "OpenDMARC Filter v1.4.2 sourceware.org 5D8864BBC0BB",
        "ARC-Filter": "OpenARC Filter v1.0.0 sourceware.org 5D8864BBC0BB",
        "ARC-Seal": "i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1777418896; cv=none;\n b=h4IJFgN1DYekbAHuThPOy0+rfi56kilg00IgH6odsnY1JY41Y+5c8QedSmESonmoHjy9UWZCpUWSV4J3n8PYIsPG5Xaz5ms7/t4YdFgrTGTOC1gjF/LTa+NA/OegG0WVlATHg+YczXnR+ZyCX7CB9dEE79ozDhHClKVeSrTmQ2I=",
        "ARC-Message-Signature": "i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1777418896; c=relaxed/simple;\n bh=Y0BF3ZS01q+xQffm3cW5Ntd9A14qzROhO38DELE+0fI=;\n h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version;\n b=UysE6cQrl0y4NAwBZOkzoVvtg3Mkv7CWl5XO9SwduKfLsywWoOADJYYASgwNMdSkerx1HLpdbi9f/078jLfj0IXgW3OrDPcNNJXCQv1lKlyIHCR2fFxtThw7vtmnzOGJfB7Q0lFO0+LmhXzgfVYr7lZqt26LTb+k5aryobWKqf8=",
        "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=1777418895;\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 bh=AKOn2N6Ykc3Tfb4hNW9UAjfpVjyH4wG6WVRm/vV1Dvg=;\n b=PIZTNeCqfjO+LuhzybyjEzu6WVz420UeSuW5KG1wW7odC1Gtypu2Ffr/ag2yB9fZ0z1Y4C\n BotLDKkbF9p38OgkyvaU/rDsDgtVe+mGTg3+JuXTqeA1zkOtecsgBduqK1hIfgrdWs1O59\n 2EerjcNSVFYqk2sYzWj9MYAJe619Els=",
        "X-MC-Unique": "nBdAHjSzM5igiR0b920N-Q-1",
        "X-Mimecast-MFC-AGG-ID": "nBdAHjSzM5igiR0b920N-Q_1777418893",
        "From": "David Malcolm <dmalcolm@redhat.com>",
        "To": "gcc-patches@gcc.gnu.org",
        "Cc": "David Malcolm <dmalcolm@redhat.com>",
        "Subject": "[pushed: r17-183] analyzer: split out various pending_diagnostic\n subclasses from region-model.cc",
        "Date": "Tue, 28 Apr 2026 19:28:11 -0400",
        "Message-ID": "<20260428232811.1953975-1-dmalcolm@redhat.com>",
        "MIME-Version": "1.0",
        "X-Scanned-By": "MIMEDefang 3.4.1 on 10.30.177.111",
        "X-Mimecast-Spam-Score": "0",
        "X-Mimecast-MFC-PROC-ID": "WxE-f_HrGcyUJG7IuxaWutLRMVk6BNKmJ9kzGTkeb5A_1777418893",
        "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": "Split up region-model.cc somewhat.  No functional change intended.\n\nSuccessfully bootstrapped & regrtested on powerpc64le-unknown-linux-gnu\n(albeit without ada,cobol,d, and possibly missing some optional test dependencies)\nPushed to trunk as r17-183-gd6dbbc97dd44b4.\n\ngcc/ChangeLog:\n\t* Makefile.in (ANALYZER_OBJS): Add\n\tanalyzer/poisoned-value-diagnostic.o,\n\tanalyzer/shift-diagnostics.o, and\n\tanalyzer/write-to-const-diagnostics.o.\n\ngcc/analyzer/ChangeLog:\n\t* poisoned-value-diagnostic.cc: New file, taken from material in\n\tregion-model.cc.\n\t* region-model.cc (class poisoned_value_diagnostic): Move to\n\tpoisoned-value-diagnostic.cc.\n\t(class shift_count_negative_diagnostic): Move to\n\tshift-diagnostics.cc.\n\t(class shift_count_overflow_diagnostic): Likewise.\n\t(region_model::get_gassign_result): Use factory functions when\n\tcreating diagnostics so that the subclasses can be moved to their\n\town source files.\n\t(region_model::check_for_poison): Likewise.\n\t(region_model::deref_rvalue): Likewise.\n\t(class write_to_const_diagnostic): Move to\n\twrite-to-const-diagnostics.cc.\n\t(class write_to_string_literal_diagnostic): Likewise.\n\t(region_model::check_for_writable_region): Use factory functions\n\twhen creating diagnostics so that the subclasses can be moved to\n\ttheir own source files.\n\t* region-model.h (make_poisoned_value_diagnostic): New decl.\n\t(make_shift_count_negative_diagnostic): New decl.\n\t(make_shift_count_overflow_diagnostic): New decl.\n\t(make_write_to_const_diagnostic): New decl.\n\t(make_write_to_string_literal_diagnostic): New decl.\n\t* shift-diagnostics.cc: New file, taken from material in\n\tregion-model.cc.\n\t* write-to-const-diagnostics.cc: Likewise.\n\nSigned-off-by: David Malcolm <dmalcolm@redhat.com>\n---\n gcc/Makefile.in                            |   5 +-\n gcc/analyzer/poisoned-value-diagnostic.cc  | 220 +++++++++++\n gcc/analyzer/region-model.cc               | 440 +--------------------\n gcc/analyzer/region-model.h                |  22 ++\n gcc/analyzer/shift-diagnostics.cc          | 148 +++++++\n gcc/analyzer/write-to-const-diagnostics.cc | 169 ++++++++\n 6 files changed, 577 insertions(+), 427 deletions(-)\n create mode 100644 gcc/analyzer/poisoned-value-diagnostic.cc\n create mode 100644 gcc/analyzer/shift-diagnostics.cc\n create mode 100644 gcc/analyzer/write-to-const-diagnostics.cc",
    "diff": "diff --git a/gcc/Makefile.in b/gcc/Makefile.in\nindex cbce3188794..0bccfffedc0 100644\n--- a/gcc/Makefile.in\n+++ b/gcc/Makefile.in\n@@ -1363,6 +1363,7 @@ ANALYZER_OBJS = \\\n \tanalyzer/known-function-manager.o \\\n \tanalyzer/ops.o \\\n \tanalyzer/pending-diagnostic.o \\\n+\tanalyzer/poisoned-value-diagnostic.o \\\n \tanalyzer/program-point.o \\\n \tanalyzer/program-state.o \\\n \tanalyzer/ranges.o \\\n@@ -1372,6 +1373,7 @@ ANALYZER_OBJS = \\\n \tanalyzer/region-model-asm.o \\\n \tanalyzer/region-model-manager.o \\\n \tanalyzer/region-model-reachability.o \\\n+\tanalyzer/shift-diagnostics.o \\\n \tanalyzer/sm.o \\\n \tanalyzer/sm-file.o \\\n \tanalyzer/sm-fd.o \\\n@@ -1389,7 +1391,8 @@ ANALYZER_OBJS = \\\n \tanalyzer/svalue.o \\\n \tanalyzer/symbol.o \\\n \tanalyzer/trimmed-graph.o \\\n-\tanalyzer/varargs.o\n+\tanalyzer/varargs.o \\\n+\tanalyzer/write-to-const-diagnostics.o \\\n \n # Language-independent object files.\n # We put the *-match.o and insn-*.o files first so that a parallel make\ndiff --git a/gcc/analyzer/poisoned-value-diagnostic.cc b/gcc/analyzer/poisoned-value-diagnostic.cc\nnew file mode 100644\nindex 00000000000..d29ceeaca63\n--- /dev/null\n+++ b/gcc/analyzer/poisoned-value-diagnostic.cc\n@@ -0,0 +1,220 @@\n+/* Implementation of class ana::poisoned_value_diagnostic.\n+   Copyright (C) 2019-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\n+under the terms of the GNU General Public License as published by\n+the Free Software Foundation; either version 3, or (at your option)\n+any later version.\n+\n+GCC is distributed in the hope that it will be useful, but\n+WITHOUT ANY WARRANTY; without even the implied warranty of\n+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+General Public License 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+#include \"analyzer/common.h\"\n+\n+#include \"analyzer/region-model.h\"\n+#include \"analyzer/feasible-graph.h\"\n+#include \"diagnostics/sarif-sink.h\"\n+\n+#if ENABLE_ANALYZER\n+\n+namespace ana {\n+\n+/* A subclass of pending_diagnostic for complaining about uses of\n+   poisoned values.  */\n+\n+class poisoned_value_diagnostic\n+: public pending_diagnostic_subclass<poisoned_value_diagnostic>\n+{\n+public:\n+  poisoned_value_diagnostic (tree expr, enum poison_kind pkind,\n+\t\t\t     const region *src_region,\n+\t\t\t     tree check_expr)\n+  : m_expr (expr), m_pkind (pkind),\n+    m_src_region (src_region),\n+    m_check_expr (check_expr)\n+  {}\n+\n+  const char *get_kind () const final override { return \"poisoned_value_diagnostic\"; }\n+\n+  bool use_of_uninit_p () const final override\n+  {\n+    return m_pkind == poison_kind::uninit;\n+  }\n+\n+  bool operator== (const poisoned_value_diagnostic &other) const\n+  {\n+    return (m_expr == other.m_expr\n+\t    && m_pkind == other.m_pkind\n+\t    && m_src_region == other.m_src_region);\n+  }\n+\n+  int get_controlling_option () const final override\n+  {\n+    switch (m_pkind)\n+      {\n+      default:\n+\tgcc_unreachable ();\n+      case poison_kind::uninit:\n+\treturn OPT_Wanalyzer_use_of_uninitialized_value;\n+      case poison_kind::freed:\n+      case poison_kind::deleted:\n+\treturn OPT_Wanalyzer_use_after_free;\n+      case poison_kind::popped_stack:\n+\treturn OPT_Wanalyzer_use_of_pointer_in_stale_stack_frame;\n+      }\n+  }\n+\n+  bool terminate_path_p () const final override { return true; }\n+\n+  bool emit (diagnostic_emission_context &ctxt) final override\n+  {\n+    switch (m_pkind)\n+      {\n+      default:\n+\tgcc_unreachable ();\n+      case poison_kind::uninit:\n+\t{\n+\t  ctxt.add_cwe (457); /* \"CWE-457: Use of Uninitialized Variable\".  */\n+\t  return ctxt.warn (\"use of uninitialized value %qE\",\n+\t\t\t    m_expr);\n+\t}\n+\tbreak;\n+      case poison_kind::freed:\n+\t{\n+\t  ctxt.add_cwe (416); /* \"CWE-416: Use After Free\".  */\n+\t  return ctxt.warn (\"use after %<free%> of %qE\",\n+\t\t\t    m_expr);\n+\t}\n+\tbreak;\n+      case poison_kind::deleted:\n+\t{\n+\t  ctxt.add_cwe (416); /* \"CWE-416: Use After Free\".  */\n+\t  return ctxt.warn (\"use after %<delete%> of %qE\",\n+\t\t\t    m_expr);\n+\t}\n+\tbreak;\n+      case poison_kind::popped_stack:\n+\t{\n+\t  /* TODO: which CWE?  */\n+\t  return ctxt.warn\n+\t    (\"dereferencing pointer %qE to within stale stack frame\",\n+\t     m_expr);\n+\t}\n+\tbreak;\n+      }\n+  }\n+\n+  bool\n+  describe_final_event (pretty_printer &pp,\n+\t\t\tconst evdesc::final_event &) final override\n+  {\n+    switch (m_pkind)\n+      {\n+      default:\n+\tgcc_unreachable ();\n+      case poison_kind::uninit:\n+\t{\n+\t  pp_printf (&pp,\n+\t\t     \"use of uninitialized value %qE here\",\n+\t\t     m_expr);\n+\t  return true;\n+\t}\n+      case poison_kind::freed:\n+\t{\n+\t  pp_printf (&pp,\n+\t\t     \"use after %<free%> of %qE here\",\n+\t\t     m_expr);\n+\t  return true;\n+\t}\n+      case poison_kind::deleted:\n+\t{\n+\t  pp_printf (&pp,\n+\t\t     \"use after %<delete%> of %qE here\",\n+\t\t     m_expr);\n+\t  return true;\n+\t}\n+      case poison_kind::popped_stack:\n+\t{\n+\t  pp_printf (&pp,\n+\t\t     \"dereferencing pointer %qE to within stale stack frame\",\n+\t\t     m_expr);\n+\t  return true;\n+\t}\n+      }\n+  }\n+\n+  void mark_interesting_stuff (interesting_t *interest) final override\n+  {\n+    if (m_src_region)\n+      interest->add_region_creation (m_src_region);\n+  }\n+\n+  /* Attempt to suppress false positives.\n+     Reject paths where the value of the underlying region isn't poisoned.\n+     This can happen due to state merging when exploring the exploded graph,\n+     where the more precise analysis during feasibility analysis finds that\n+     the region is in fact valid.\n+     To do this we need to get the value from the fgraph.  Unfortunately\n+     we can't simply query the state of m_src_region (from the enode),\n+     since it might be a different region in the fnode state (e.g. with\n+     heap-allocated regions, the numbering could be different).\n+     Hence we access m_check_expr, if available.  */\n+\n+  bool check_valid_fpath_p (const feasible_node &fnode)\n+    const final override\n+  {\n+    if (!m_check_expr)\n+      return true;\n+    const svalue *fsval = fnode.get_model ().get_rvalue (m_check_expr, nullptr);\n+    /* Check to see if the expr is also poisoned in FNODE (and in the\n+       same way).  */\n+    const poisoned_svalue * fspval = fsval->dyn_cast_poisoned_svalue ();\n+    if (!fspval)\n+      return false;\n+    if (fspval->get_poison_kind () != m_pkind)\n+      return false;\n+    return true;\n+  }\n+\n+  void\n+  maybe_add_sarif_properties (diagnostics::sarif_object &result_obj)\n+    const final override\n+  {\n+    auto &props = result_obj.get_or_create_properties ();\n+#define PROPERTY_PREFIX \"gcc/analyzer/poisoned_value_diagnostic/\"\n+    props.set (PROPERTY_PREFIX \"expr\", tree_to_json (m_expr));\n+    props.set_string (PROPERTY_PREFIX \"kind\", poison_kind_to_str (m_pkind));\n+    if (m_src_region)\n+      props.set (PROPERTY_PREFIX \"src_region\", m_src_region->to_json ());\n+    props.set (PROPERTY_PREFIX \"check_expr\", tree_to_json (m_check_expr));\n+#undef PROPERTY_PREFIX\n+  }\n+\n+private:\n+  tree m_expr;\n+  enum poison_kind m_pkind;\n+  const region *m_src_region;\n+  tree m_check_expr;\n+};\n+\n+std::unique_ptr<pending_diagnostic>\n+make_poisoned_value_diagnostic (tree expr, enum poison_kind pkind,\n+\t\t\t\tconst region *src_region,\n+\t\t\t\ttree check_expr)\n+{\n+  return std::make_unique<poisoned_value_diagnostic> (expr, pkind,\n+\t\t\t\t\t\t      src_region, check_expr);\n+}\n+\n+} // namespace ana\n+\n+#endif /* #if ENABLE_ANALYZER */\ndiff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc\nindex 6e25029d9d2..15210f5aa9c 100644\n--- a/gcc/analyzer/region-model.cc\n+++ b/gcc/analyzer/region-model.cc\n@@ -742,284 +742,6 @@ region_model::loop_replay_fixup (const region_model *dst_state)\n   m_store.loop_replay_fixup (dst_state->get_store (), m_mgr);\n }\n \n-/* A subclass of pending_diagnostic for complaining about uses of\n-   poisoned values.  */\n-\n-class poisoned_value_diagnostic\n-: public pending_diagnostic_subclass<poisoned_value_diagnostic>\n-{\n-public:\n-  poisoned_value_diagnostic (tree expr, enum poison_kind pkind,\n-\t\t\t     const region *src_region,\n-\t\t\t     tree check_expr)\n-  : m_expr (expr), m_pkind (pkind),\n-    m_src_region (src_region),\n-    m_check_expr (check_expr)\n-  {}\n-\n-  const char *get_kind () const final override { return \"poisoned_value_diagnostic\"; }\n-\n-  bool use_of_uninit_p () const final override\n-  {\n-    return m_pkind == poison_kind::uninit;\n-  }\n-\n-  bool operator== (const poisoned_value_diagnostic &other) const\n-  {\n-    return (m_expr == other.m_expr\n-\t    && m_pkind == other.m_pkind\n-\t    && m_src_region == other.m_src_region);\n-  }\n-\n-  int get_controlling_option () const final override\n-  {\n-    switch (m_pkind)\n-      {\n-      default:\n-\tgcc_unreachable ();\n-      case poison_kind::uninit:\n-\treturn OPT_Wanalyzer_use_of_uninitialized_value;\n-      case poison_kind::freed:\n-      case poison_kind::deleted:\n-\treturn OPT_Wanalyzer_use_after_free;\n-      case poison_kind::popped_stack:\n-\treturn OPT_Wanalyzer_use_of_pointer_in_stale_stack_frame;\n-      }\n-  }\n-\n-  bool terminate_path_p () const final override { return true; }\n-\n-  bool emit (diagnostic_emission_context &ctxt) final override\n-  {\n-    switch (m_pkind)\n-      {\n-      default:\n-\tgcc_unreachable ();\n-      case poison_kind::uninit:\n-\t{\n-\t  ctxt.add_cwe (457); /* \"CWE-457: Use of Uninitialized Variable\".  */\n-\t  return ctxt.warn (\"use of uninitialized value %qE\",\n-\t\t\t    m_expr);\n-\t}\n-\tbreak;\n-      case poison_kind::freed:\n-\t{\n-\t  ctxt.add_cwe (416); /* \"CWE-416: Use After Free\".  */\n-\t  return ctxt.warn (\"use after %<free%> of %qE\",\n-\t\t\t    m_expr);\n-\t}\n-\tbreak;\n-      case poison_kind::deleted:\n-\t{\n-\t  ctxt.add_cwe (416); /* \"CWE-416: Use After Free\".  */\n-\t  return ctxt.warn (\"use after %<delete%> of %qE\",\n-\t\t\t    m_expr);\n-\t}\n-\tbreak;\n-      case poison_kind::popped_stack:\n-\t{\n-\t  /* TODO: which CWE?  */\n-\t  return ctxt.warn\n-\t    (\"dereferencing pointer %qE to within stale stack frame\",\n-\t     m_expr);\n-\t}\n-\tbreak;\n-      }\n-  }\n-\n-  bool\n-  describe_final_event (pretty_printer &pp,\n-\t\t\tconst evdesc::final_event &) final override\n-  {\n-    switch (m_pkind)\n-      {\n-      default:\n-\tgcc_unreachable ();\n-      case poison_kind::uninit:\n-\t{\n-\t  pp_printf (&pp,\n-\t\t     \"use of uninitialized value %qE here\",\n-\t\t     m_expr);\n-\t  return true;\n-\t}\n-      case poison_kind::freed:\n-\t{\n-\t  pp_printf (&pp,\n-\t\t     \"use after %<free%> of %qE here\",\n-\t\t     m_expr);\n-\t  return true;\n-\t}\n-      case poison_kind::deleted:\n-\t{\n-\t  pp_printf (&pp,\n-\t\t     \"use after %<delete%> of %qE here\",\n-\t\t     m_expr);\n-\t  return true;\n-\t}\n-      case poison_kind::popped_stack:\n-\t{\n-\t  pp_printf (&pp,\n-\t\t     \"dereferencing pointer %qE to within stale stack frame\",\n-\t\t     m_expr);\n-\t  return true;\n-\t}\n-      }\n-  }\n-\n-  void mark_interesting_stuff (interesting_t *interest) final override\n-  {\n-    if (m_src_region)\n-      interest->add_region_creation (m_src_region);\n-  }\n-\n-  /* Attempt to suppress false positives.\n-     Reject paths where the value of the underlying region isn't poisoned.\n-     This can happen due to state merging when exploring the exploded graph,\n-     where the more precise analysis during feasibility analysis finds that\n-     the region is in fact valid.\n-     To do this we need to get the value from the fgraph.  Unfortunately\n-     we can't simply query the state of m_src_region (from the enode),\n-     since it might be a different region in the fnode state (e.g. with\n-     heap-allocated regions, the numbering could be different).\n-     Hence we access m_check_expr, if available.  */\n-\n-  bool check_valid_fpath_p (const feasible_node &fnode)\n-    const final override\n-  {\n-    if (!m_check_expr)\n-      return true;\n-    const svalue *fsval = fnode.get_model ().get_rvalue (m_check_expr, nullptr);\n-    /* Check to see if the expr is also poisoned in FNODE (and in the\n-       same way).  */\n-    const poisoned_svalue * fspval = fsval->dyn_cast_poisoned_svalue ();\n-    if (!fspval)\n-      return false;\n-    if (fspval->get_poison_kind () != m_pkind)\n-      return false;\n-    return true;\n-  }\n-\n-  void\n-  maybe_add_sarif_properties (diagnostics::sarif_object &result_obj)\n-    const final override\n-  {\n-    auto &props = result_obj.get_or_create_properties ();\n-#define PROPERTY_PREFIX \"gcc/analyzer/poisoned_value_diagnostic/\"\n-    props.set (PROPERTY_PREFIX \"expr\", tree_to_json (m_expr));\n-    props.set_string (PROPERTY_PREFIX \"kind\", poison_kind_to_str (m_pkind));\n-    if (m_src_region)\n-      props.set (PROPERTY_PREFIX \"src_region\", m_src_region->to_json ());\n-    props.set (PROPERTY_PREFIX \"check_expr\", tree_to_json (m_check_expr));\n-#undef PROPERTY_PREFIX\n-  }\n-\n-private:\n-  tree m_expr;\n-  enum poison_kind m_pkind;\n-  const region *m_src_region;\n-  tree m_check_expr;\n-};\n-\n-/* A subclass of pending_diagnostic for complaining about shifts\n-   by negative counts.  */\n-\n-class shift_count_negative_diagnostic\n-: public pending_diagnostic_subclass<shift_count_negative_diagnostic>\n-{\n-public:\n-  shift_count_negative_diagnostic (const gassign *assign, tree count_cst)\n-  : m_assign (assign), m_count_cst (count_cst)\n-  {}\n-\n-  const char *get_kind () const final override\n-  {\n-    return \"shift_count_negative_diagnostic\";\n-  }\n-\n-  bool operator== (const shift_count_negative_diagnostic &other) const\n-  {\n-    return (m_assign == other.m_assign\n-\t    && same_tree_p (m_count_cst, other.m_count_cst));\n-  }\n-\n-  int get_controlling_option () const final override\n-  {\n-    return OPT_Wanalyzer_shift_count_negative;\n-  }\n-\n-  bool emit (diagnostic_emission_context &ctxt) final override\n-  {\n-    return ctxt.warn (\"shift by negative count (%qE)\", m_count_cst);\n-  }\n-\n-  bool\n-  describe_final_event (pretty_printer &pp,\n-\t\t\tconst evdesc::final_event &) final override\n-  {\n-    pp_printf (&pp,\n-\t       \"shift by negative amount here (%qE)\",\n-\t       m_count_cst);\n-    return true;\n-  }\n-\n-private:\n-  const gassign *m_assign;\n-  tree m_count_cst;\n-};\n-\n-/* A subclass of pending_diagnostic for complaining about shifts\n-   by counts >= the width of the operand type.  */\n-\n-class shift_count_overflow_diagnostic\n-: public pending_diagnostic_subclass<shift_count_overflow_diagnostic>\n-{\n-public:\n-  shift_count_overflow_diagnostic (const gassign *assign,\n-\t\t\t\t   int operand_precision,\n-\t\t\t\t   tree count_cst)\n-  : m_assign (assign), m_operand_precision (operand_precision),\n-    m_count_cst (count_cst)\n-  {}\n-\n-  const char *get_kind () const final override\n-  {\n-    return \"shift_count_overflow_diagnostic\";\n-  }\n-\n-  bool operator== (const shift_count_overflow_diagnostic &other) const\n-  {\n-    return (m_assign == other.m_assign\n-\t    && m_operand_precision == other.m_operand_precision\n-\t    && same_tree_p (m_count_cst, other.m_count_cst));\n-  }\n-\n-  int get_controlling_option () const final override\n-  {\n-    return OPT_Wanalyzer_shift_count_overflow;\n-  }\n-\n-  bool emit (diagnostic_emission_context &ctxt) final override\n-  {\n-    return ctxt.warn (\"shift by count (%qE) >= precision of type (%qi)\",\n-\t\t      m_count_cst, m_operand_precision);\n-  }\n-\n-  bool\n-  describe_final_event (pretty_printer &pp,\n-\t\t\tconst evdesc::final_event &) final override\n-  {\n-    pp_printf (&pp,\n-\t       \"shift by count %qE here\",\n-\t       m_count_cst);\n-    return true;\n-  }\n-\n-private:\n-  const gassign *m_assign;\n-  int m_operand_precision;\n-  tree m_count_cst;\n-};\n-\n /* A subclass of pending_diagnostic for complaining about pointer\n    subtractions involving unrelated buffers.  */\n \n@@ -1340,16 +1062,14 @@ region_model::get_gassign_result (const gassign *assign,\n \t\t{\n \t\t  if (tree_int_cst_sgn (rhs2_cst) < 0)\n \t\t    ctxt->warn\n-\t\t      (std::make_unique<shift_count_negative_diagnostic>\n-\t\t\t (assign, rhs2_cst));\n+\t\t      (make_shift_count_negative_diagnostic (assign, rhs2_cst));\n \t\t  else if (compare_tree_int (rhs2_cst,\n \t\t\t\t\t     TYPE_PRECISION (TREE_TYPE (rhs1)))\n \t\t\t   >= 0)\n-\t\t    ctxt->warn\n-\t\t      (std::make_unique<shift_count_overflow_diagnostic>\n-\t\t\t (assign,\n-\t\t\t  int (TYPE_PRECISION (TREE_TYPE (rhs1))),\n-\t\t\t  rhs2_cst));\n+\t\t    ctxt->warn (make_shift_count_overflow_diagnostic\n+\t\t\t\t(assign,\n+\t\t\t\t int (TYPE_PRECISION (TREE_TYPE (rhs1))),\n+\t\t\t\t rhs2_cst));\n \t\t}\n \t  }\n \n@@ -1602,11 +1322,10 @@ region_model::check_for_poison (const svalue *sval,\n \tcheck_expr = expr;\n       else\n \tcheck_expr = nullptr;\n-      if (ctxt->warn\n-\t    (std::make_unique<poisoned_value_diagnostic> (diag_arg,\n-\t\t\t\t\t\t\t  pkind,\n-\t\t\t\t\t\t\t  src_region,\n-\t\t\t\t\t\t\t  check_expr)))\n+      if (ctxt->warn (make_poisoned_value_diagnostic (diag_arg,\n+\t\t\t\t\t\t      pkind,\n+\t\t\t\t\t\t      src_region,\n+\t\t\t\t\t\t      check_expr)))\n \t{\n \t  /* We only want to report use of a poisoned value at the first\n \t     place it gets used; return an unknown value to avoid generating\n@@ -3487,7 +3206,7 @@ region_model::deref_rvalue (const svalue *ptr_sval, tree ptr_tree,\n \t\tconst poisoned_svalue *poisoned_sval\n \t\t  = as_a <const poisoned_svalue *> (ptr_sval);\n \t\tenum poison_kind pkind = poisoned_sval->get_poison_kind ();\n-\t\tctxt->warn (std::make_unique<poisoned_value_diagnostic>\n+\t\tctxt->warn (make_poisoned_value_diagnostic\n \t\t\t      (ptr, pkind, nullptr, nullptr));\n \t      }\n \t  }\n@@ -3514,131 +3233,6 @@ region_model::get_rvalue_for_bits (tree type,\n   return m_mgr->get_or_create_bits_within (type, bits, sval);\n }\n \n-/* A subclass of pending_diagnostic for complaining about writes to\n-   constant regions of memory.  */\n-\n-class write_to_const_diagnostic\n-: public pending_diagnostic_subclass<write_to_const_diagnostic>\n-{\n-public:\n-  write_to_const_diagnostic (const region *reg, tree decl)\n-  : m_reg (reg), m_decl (decl)\n-  {}\n-\n-  const char *get_kind () const final override\n-  {\n-    return \"write_to_const_diagnostic\";\n-  }\n-\n-  bool operator== (const write_to_const_diagnostic &other) const\n-  {\n-    return (m_reg == other.m_reg\n-\t    && m_decl == other.m_decl);\n-  }\n-\n-  int get_controlling_option () const final override\n-  {\n-    return OPT_Wanalyzer_write_to_const;\n-  }\n-\n-  bool emit (diagnostic_emission_context &ctxt) final override\n-  {\n-    auto_diagnostic_group d;\n-    bool warned;\n-    switch (m_reg->get_kind ())\n-      {\n-      default:\n-\twarned = ctxt.warn (\"write to %<const%> object %qE\", m_decl);\n-\tbreak;\n-      case RK_FUNCTION:\n-\twarned = ctxt.warn (\"write to function %qE\", m_decl);\n-\tbreak;\n-      case RK_LABEL:\n-\twarned = ctxt.warn (\"write to label %qE\", m_decl);\n-\tbreak;\n-      }\n-    if (warned)\n-      inform (DECL_SOURCE_LOCATION (m_decl), \"declared here\");\n-    return warned;\n-  }\n-\n-  bool\n-  describe_final_event (pretty_printer &pp,\n-\t\t\tconst evdesc::final_event &) final override\n-  {\n-    switch (m_reg->get_kind ())\n-      {\n-      default:\n-\t{\n-\t  pp_printf (&pp,\n-\t\t     \"write to %<const%> object %qE here\", m_decl);\n-\t  return true;\n-\t}\n-      case RK_FUNCTION:\n-\t{\n-\t  pp_printf (&pp,\n-\t\t     \"write to function %qE here\", m_decl);\n-\t  return true;\n-\t}\n-      case RK_LABEL:\n-\t{\n-\t  pp_printf (&pp,\n-\t\t     \"write to label %qE here\", m_decl);\n-\t  return true;\n-\t}\n-      }\n-  }\n-\n-private:\n-  const region *m_reg;\n-  tree m_decl;\n-};\n-\n-/* A subclass of pending_diagnostic for complaining about writes to\n-   string literals.  */\n-\n-class write_to_string_literal_diagnostic\n-: public pending_diagnostic_subclass<write_to_string_literal_diagnostic>\n-{\n-public:\n-  write_to_string_literal_diagnostic (const region *reg)\n-  : m_reg (reg)\n-  {}\n-\n-  const char *get_kind () const final override\n-  {\n-    return \"write_to_string_literal_diagnostic\";\n-  }\n-\n-  bool operator== (const write_to_string_literal_diagnostic &other) const\n-  {\n-    return m_reg == other.m_reg;\n-  }\n-\n-  int get_controlling_option () const final override\n-  {\n-    return OPT_Wanalyzer_write_to_string_literal;\n-  }\n-\n-  bool emit (diagnostic_emission_context &ctxt) final override\n-  {\n-    return ctxt.warn (\"write to string literal\");\n-    /* Ideally we would show the location of the STRING_CST as well,\n-       but it is not available at this point.  */\n-  }\n-\n-  bool\n-  describe_final_event (pretty_printer &pp,\n-\t\t\tconst evdesc::final_event &) final override\n-  {\n-    pp_string (&pp, \"write to string literal here\");\n-    return true;\n-  }\n-\n-private:\n-  const region *m_reg;\n-};\n-\n /* Use CTXT to warn If DEST_REG is a region that shouldn't be written to.  */\n \n void\n@@ -3658,18 +3252,14 @@ region_model::check_for_writable_region (const region* dest_reg,\n       {\n \tconst function_region *func_reg = as_a <const function_region *> (base_reg);\n \ttree fndecl = func_reg->get_fndecl ();\n-\tctxt->warn\n-\t  (std::make_unique<write_to_const_diagnostic>\n-\t     (func_reg, fndecl));\n+\tctxt->warn (make_write_to_const_diagnostic (func_reg, fndecl));\n       }\n       break;\n     case RK_LABEL:\n       {\n \tconst label_region *label_reg = as_a <const label_region *> (base_reg);\n \ttree label = label_reg->get_label ();\n-\tctxt->warn\n-\t  (std::make_unique<write_to_const_diagnostic>\n-\t     (label_reg, label));\n+\tctxt->warn (make_write_to_const_diagnostic (label_reg, label));\n       }\n       break;\n     case RK_DECL:\n@@ -3682,13 +3272,11 @@ region_model::check_for_writable_region (const region* dest_reg,\n \t   \"this\" param is \"T* const\").  */\n \tif (TREE_READONLY (decl)\n \t    && is_global_var (decl))\n-\t  ctxt->warn\n-\t    (std::make_unique<write_to_const_diagnostic> (dest_reg, decl));\n+\t  ctxt->warn (make_write_to_const_diagnostic (dest_reg, decl));\n       }\n       break;\n     case RK_STRING:\n-      ctxt->warn\n-\t(std::make_unique<write_to_string_literal_diagnostic> (dest_reg));\n+      ctxt->warn (make_write_to_string_literal_diagnostic (dest_reg));\n       break;\n     }\n }\ndiff --git a/gcc/analyzer/region-model.h b/gcc/analyzer/region-model.h\nindex f4cf38e3e0f..4b0160a98b0 100644\n--- a/gcc/analyzer/region-model.h\n+++ b/gcc/analyzer/region-model.h\n@@ -1329,6 +1329,28 @@ private:\n   const supergraph *m_sg;\n };\n \n+/* Factory functions for various diagnostics.  */\n+\n+extern std::unique_ptr<pending_diagnostic>\n+make_poisoned_value_diagnostic (tree expr, enum poison_kind pkind,\n+\t\t\t\tconst region *src_region,\n+\t\t\t\ttree check_expr);\n+\n+extern std::unique_ptr<pending_diagnostic>\n+make_shift_count_negative_diagnostic (const gassign *assign,\n+\t\t\t\t      tree count_cst);\n+\n+extern std::unique_ptr<pending_diagnostic>\n+make_shift_count_overflow_diagnostic (const gassign *assign,\n+\t\t\t\t      int operand_precision,\n+\t\t\t\t      tree count_cst);\n+\n+extern std::unique_ptr<pending_diagnostic>\n+make_write_to_const_diagnostic (const region *dest_reg, tree decl);\n+\n+extern std::unique_ptr<pending_diagnostic>\n+make_write_to_string_literal_diagnostic (const region *reg);\n+\n } // namespace ana\n \n extern void debug (const region_model &rmodel);\ndiff --git a/gcc/analyzer/shift-diagnostics.cc b/gcc/analyzer/shift-diagnostics.cc\nnew file mode 100644\nindex 00000000000..2bc58de248d\n--- /dev/null\n+++ b/gcc/analyzer/shift-diagnostics.cc\n@@ -0,0 +1,148 @@\n+/* Diagnostics for complaining about shift operations.\n+   Copyright (C) 2020-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\n+under the terms of the GNU General Public License as published by\n+the Free Software Foundation; either version 3, or (at your option)\n+any later version.\n+\n+GCC is distributed in the hope that it will be useful, but\n+WITHOUT ANY WARRANTY; without even the implied warranty of\n+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+General Public License 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+#include \"analyzer/common.h\"\n+\n+#include \"analyzer/region-model.h\"\n+#include \"analyzer/feasible-graph.h\"\n+#include \"diagnostics/sarif-sink.h\"\n+\n+#if ENABLE_ANALYZER\n+\n+namespace ana {\n+\n+/* A subclass of pending_diagnostic for complaining about shifts\n+   by negative counts.  */\n+\n+class shift_count_negative_diagnostic\n+: public pending_diagnostic_subclass<shift_count_negative_diagnostic>\n+{\n+public:\n+  shift_count_negative_diagnostic (const gassign *assign, tree count_cst)\n+  : m_assign (assign), m_count_cst (count_cst)\n+  {}\n+\n+  const char *get_kind () const final override\n+  {\n+    return \"shift_count_negative_diagnostic\";\n+  }\n+\n+  bool operator== (const shift_count_negative_diagnostic &other) const\n+  {\n+    return (m_assign == other.m_assign\n+\t    && same_tree_p (m_count_cst, other.m_count_cst));\n+  }\n+\n+  int get_controlling_option () const final override\n+  {\n+    return OPT_Wanalyzer_shift_count_negative;\n+  }\n+\n+  bool emit (diagnostic_emission_context &ctxt) final override\n+  {\n+    return ctxt.warn (\"shift by negative count (%qE)\", m_count_cst);\n+  }\n+\n+  bool\n+  describe_final_event (pretty_printer &pp,\n+\t\t\tconst evdesc::final_event &) final override\n+  {\n+    pp_printf (&pp,\n+\t       \"shift by negative amount here (%qE)\",\n+\t       m_count_cst);\n+    return true;\n+  }\n+\n+private:\n+  const gassign *m_assign;\n+  tree m_count_cst;\n+};\n+\n+std::unique_ptr<pending_diagnostic>\n+make_shift_count_negative_diagnostic (const gassign *assign, tree count_cst)\n+{\n+  return std::make_unique<shift_count_negative_diagnostic> (assign, count_cst);\n+}\n+\n+/* A subclass of pending_diagnostic for complaining about shifts\n+   by counts >= the width of the operand type.  */\n+\n+class shift_count_overflow_diagnostic\n+: public pending_diagnostic_subclass<shift_count_overflow_diagnostic>\n+{\n+public:\n+  shift_count_overflow_diagnostic (const gassign *assign,\n+\t\t\t\t   int operand_precision,\n+\t\t\t\t   tree count_cst)\n+  : m_assign (assign), m_operand_precision (operand_precision),\n+    m_count_cst (count_cst)\n+  {}\n+\n+  const char *get_kind () const final override\n+  {\n+    return \"shift_count_overflow_diagnostic\";\n+  }\n+\n+  bool operator== (const shift_count_overflow_diagnostic &other) const\n+  {\n+    return (m_assign == other.m_assign\n+\t    && m_operand_precision == other.m_operand_precision\n+\t    && same_tree_p (m_count_cst, other.m_count_cst));\n+  }\n+\n+  int get_controlling_option () const final override\n+  {\n+    return OPT_Wanalyzer_shift_count_overflow;\n+  }\n+\n+  bool emit (diagnostic_emission_context &ctxt) final override\n+  {\n+    return ctxt.warn (\"shift by count (%qE) >= precision of type (%qi)\",\n+\t\t      m_count_cst, m_operand_precision);\n+  }\n+\n+  bool\n+  describe_final_event (pretty_printer &pp,\n+\t\t\tconst evdesc::final_event &) final override\n+  {\n+    pp_printf (&pp,\n+\t       \"shift by count %qE here\",\n+\t       m_count_cst);\n+    return true;\n+  }\n+\n+private:\n+  const gassign *m_assign;\n+  int m_operand_precision;\n+  tree m_count_cst;\n+};\n+\n+std::unique_ptr<pending_diagnostic>\n+make_shift_count_overflow_diagnostic (const gassign *assign,\n+\t\t\t\t      int operand_precision,\n+\t\t\t\t      tree count_cst)\n+{\n+  return std::make_unique<shift_count_overflow_diagnostic>\n+    (assign, operand_precision, count_cst);\n+}\n+\n+} // namespace ana\n+\n+#endif /* #if ENABLE_ANALYZER */\ndiff --git a/gcc/analyzer/write-to-const-diagnostics.cc b/gcc/analyzer/write-to-const-diagnostics.cc\nnew file mode 100644\nindex 00000000000..7d71f1a32ae\n--- /dev/null\n+++ b/gcc/analyzer/write-to-const-diagnostics.cc\n@@ -0,0 +1,169 @@\n+/* Implementation of write_to_const_diagnostic and\n+   write_to_string_literal_diagnostic.\n+   Copyright (C) 2020-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\n+under the terms of the GNU General Public License as published by\n+the Free Software Foundation; either version 3, or (at your option)\n+any later version.\n+\n+GCC is distributed in the hope that it will be useful, but\n+WITHOUT ANY WARRANTY; without even the implied warranty of\n+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+General Public License 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+#include \"analyzer/common.h\"\n+\n+#include \"analyzer/region-model.h\"\n+\n+#if ENABLE_ANALYZER\n+\n+namespace ana {\n+\n+/* A subclass of pending_diagnostic for complaining about writes to\n+   constant regions of memory.  */\n+\n+class write_to_const_diagnostic\n+: public pending_diagnostic_subclass<write_to_const_diagnostic>\n+{\n+public:\n+  write_to_const_diagnostic (const region *reg, tree decl)\n+  : m_reg (reg), m_decl (decl)\n+  {}\n+\n+  const char *get_kind () const final override\n+  {\n+    return \"write_to_const_diagnostic\";\n+  }\n+\n+  bool operator== (const write_to_const_diagnostic &other) const\n+  {\n+    return (m_reg == other.m_reg\n+\t    && m_decl == other.m_decl);\n+  }\n+\n+  int get_controlling_option () const final override\n+  {\n+    return OPT_Wanalyzer_write_to_const;\n+  }\n+\n+  bool emit (diagnostic_emission_context &ctxt) final override\n+  {\n+    auto_diagnostic_group d;\n+    bool warned;\n+    switch (m_reg->get_kind ())\n+      {\n+      default:\n+\twarned = ctxt.warn (\"write to %<const%> object %qE\", m_decl);\n+\tbreak;\n+      case RK_FUNCTION:\n+\twarned = ctxt.warn (\"write to function %qE\", m_decl);\n+\tbreak;\n+      case RK_LABEL:\n+\twarned = ctxt.warn (\"write to label %qE\", m_decl);\n+\tbreak;\n+      }\n+    if (warned)\n+      inform (DECL_SOURCE_LOCATION (m_decl), \"declared here\");\n+    return warned;\n+  }\n+\n+  bool\n+  describe_final_event (pretty_printer &pp,\n+\t\t\tconst evdesc::final_event &) final override\n+  {\n+    switch (m_reg->get_kind ())\n+      {\n+      default:\n+\t{\n+\t  pp_printf (&pp,\n+\t\t     \"write to %<const%> object %qE here\", m_decl);\n+\t  return true;\n+\t}\n+      case RK_FUNCTION:\n+\t{\n+\t  pp_printf (&pp,\n+\t\t     \"write to function %qE here\", m_decl);\n+\t  return true;\n+\t}\n+      case RK_LABEL:\n+\t{\n+\t  pp_printf (&pp,\n+\t\t     \"write to label %qE here\", m_decl);\n+\t  return true;\n+\t}\n+      }\n+  }\n+\n+private:\n+  const region *m_reg;\n+  tree m_decl;\n+};\n+\n+std::unique_ptr<pending_diagnostic>\n+make_write_to_const_diagnostic (const region *dest_reg, tree decl)\n+{\n+  return std::make_unique<write_to_const_diagnostic> (dest_reg, decl);\n+}\n+\n+/* A subclass of pending_diagnostic for complaining about writes to\n+   string literals.  */\n+\n+class write_to_string_literal_diagnostic\n+: public pending_diagnostic_subclass<write_to_string_literal_diagnostic>\n+{\n+public:\n+  write_to_string_literal_diagnostic (const region *reg)\n+  : m_reg (reg)\n+  {}\n+\n+  const char *get_kind () const final override\n+  {\n+    return \"write_to_string_literal_diagnostic\";\n+  }\n+\n+  bool operator== (const write_to_string_literal_diagnostic &other) const\n+  {\n+    return m_reg == other.m_reg;\n+  }\n+\n+  int get_controlling_option () const final override\n+  {\n+    return OPT_Wanalyzer_write_to_string_literal;\n+  }\n+\n+  bool emit (diagnostic_emission_context &ctxt) final override\n+  {\n+    return ctxt.warn (\"write to string literal\");\n+    /* Ideally we would show the location of the STRING_CST as well,\n+       but it is not available at this point.  */\n+  }\n+\n+  bool\n+  describe_final_event (pretty_printer &pp,\n+\t\t\tconst evdesc::final_event &) final override\n+  {\n+    pp_string (&pp, \"write to string literal here\");\n+    return true;\n+  }\n+\n+private:\n+  const region *m_reg;\n+};\n+\n+std::unique_ptr<pending_diagnostic>\n+make_write_to_string_literal_diagnostic (const region *reg)\n+{\n+  return std::make_unique<write_to_string_literal_diagnostic> (reg);\n+}\n+\n+} // namespace ana\n+\n+#endif /* #if ENABLE_ANALYZER */\n",
    "prefixes": [
        "pushed:",
        "r17-183"
    ]
}