get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 2224523,
    "url": "http://patchwork.ozlabs.org/api/patches/2224523/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/gcc/patch/aeJBl9yfK6jlFWzw@kam.mff.cuni.cz/",
    "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": "<aeJBl9yfK6jlFWzw@kam.mff.cuni.cz>",
    "list_archive_url": null,
    "date": "2026-04-17T14:20:07",
    "name": "Fix lookup of vtables in ipa-devirt",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "2c6c6be747bf6a3bd724af2021b6c59cc9ecc3ba",
    "submitter": {
        "id": 4327,
        "url": "http://patchwork.ozlabs.org/api/people/4327/?format=api",
        "name": "Jan Hubicka",
        "email": "hubicka@ucw.cz"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/gcc/patch/aeJBl9yfK6jlFWzw@kam.mff.cuni.cz/mbox/",
    "series": [
        {
            "id": 500350,
            "url": "http://patchwork.ozlabs.org/api/series/500350/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/gcc/list/?series=500350",
            "date": "2026-04-17T14:20:07",
            "name": "Fix lookup of vtables in ipa-devirt",
            "version": 1,
            "mbox": "http://patchwork.ozlabs.org/series/500350/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2224523/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2224523/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=ucw.cz header.i=@ucw.cz header.a=rsa-sha256\n header.s=gen1 header.b=FlpogNO6;\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=ucw.cz header.i=@ucw.cz header.a=rsa-sha256\n header.s=gen1 header.b=FlpogNO6",
            "sourceware.org;\n dmarc=pass (p=none dis=none) header.from=ucw.cz",
            "sourceware.org; spf=pass smtp.mailfrom=kam.mff.cuni.cz",
            "server2.sourceware.org;\n arc=none smtp.remote-ip=195.113.20.16"
        ],
        "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 4fxxtd4g2Vz1yDF\n\tfor <incoming@patchwork.ozlabs.org>; Sat, 18 Apr 2026 00:23:05 +1000 (AEST)",
            "from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id C75A64C900C5\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 17 Apr 2026 14:23:03 +0000 (GMT)",
            "from nikam.ms.mff.cuni.cz (nikam.ms.mff.cuni.cz [195.113.20.16])\n by sourceware.org (Postfix) with ESMTPS id 52FDB4AA51B4\n for <gcc-patches@gcc.gnu.org>; Fri, 17 Apr 2026 14:20:09 +0000 (GMT)",
            "by nikam.ms.mff.cuni.cz (Postfix, from userid 16202)\n id 825BC28097F; Fri, 17 Apr 2026 16:20:07 +0200 (CEST)"
        ],
        "DKIM-Filter": [
            "OpenDKIM Filter v2.11.0 sourceware.org C75A64C900C5",
            "OpenDKIM Filter v2.11.0 sourceware.org 52FDB4AA51B4"
        ],
        "DMARC-Filter": "OpenDMARC Filter v1.4.2 sourceware.org 52FDB4AA51B4",
        "ARC-Filter": "OpenARC Filter v1.0.0 sourceware.org 52FDB4AA51B4",
        "ARC-Seal": "i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1776435610; cv=none;\n b=CVnxQ4y4kN4e7T4JBLVO8eHiXlF6FdGaurppNAmJUbwns0yLJVhn4NdiJXlLfLqJDVNXVNL7/dW0RR3DKiFl9wAMRrlpAkt2JM41UFGjTMNUZzH2QwwnDWzPqSlVVGYYuBMk1Hbovr/k0XMLJ3X9Ocp2vm9zl/qg+hV35X5AMyM=",
        "ARC-Message-Signature": "i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1776435610; c=relaxed/simple;\n bh=4tNpCa+1+YMgQ8dZaccdPEFVrG1WdqfnAIel9Ah7jYc=;\n h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version;\n b=Nup8SY/xGRmIGfnnuXUN8SgV6LRiksvs7LTtXIzg0wJHhWhj7PGhelr7h1cKx2L2PZaUXW1MY/tmhiVJPql6kfSGFR1NbdMITR7wnj489D4YE1SJvWMvK9drP9caYVOZE90DSknok6wlpq/SWEuiCVrED0VBH7K3wnW/Fa9GDJI=",
        "ARC-Authentication-Results": "i=1; server2.sourceware.org",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=ucw.cz; s=gen1;\n t=1776435607;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:mime-version:mime-version:content-type:content-type;\n bh=e3+PODxBMaHI7MAwkbwi9fhPqm5/E51Trd/9wM0tlBE=;\n b=FlpogNO6LmmQBlQDbc7Xr9rQ49viJuGg71FkKiRx9vtx/6vSekzHxL1dSJTBej6e6v7iT3\n 8FSh2NOyhLHHnUQ6OeQVbs6d7Q4O2zR54yO19GHrBW94qV93vCjdUgEjgAfjfmxPNBc0pJ\n V+/w2UkGFsjN1PsSdUZVs4UdNIigu1Y=",
        "Date": "Fri, 17 Apr 2026 16:20:07 +0200",
        "From": "Jan Hubicka <hubicka@ucw.cz>",
        "To": "gcc-patches@gcc.gnu.org",
        "Subject": "Fix lookup of vtables in ipa-devirt",
        "Message-ID": "<aeJBl9yfK6jlFWzw@kam.mff.cuni.cz>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=us-ascii",
        "Content-Disposition": "inline",
        "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": "Hi,\nthis patch solves first problem discussed in PR120098 where modified\ndevirt-23 testcase leads to wrong code.  The testcase triggers situation\nwhre anonymous type MultiTermDocs is derived by C.  When we look for possible\npolymorphic call targets, we special case anonymous type and check if they\nhave been instantiated by looking if their virtual table is used at all.\nIn this case it is not, however C has construction vtable which refers to\nMultiTermDocs's virtual function.\n\nSince we have no easy way to go from a type to all construction vtables\nof its derived types, this is fixed by adding a walk of variables\nand noting them.  Walk is triggered lazilly only when such anonymous types\nexists.\n\ngcc/ChangeLog:\n\n\tPR ipa/120098\n\t* ipa-devirt.cc (odr_type_p): Add no_derived_construction_vtables\n\t(odr_types_ptr): Move ahead in file.\n\t(odr_types): Move ahead in file.\n\t(anonymous_construction_vtable_p): New function.\n\t(mark_derived_construction_vtables): New function.\n\t(construction_vtable_hook): New function.\n\t(type_possibly_instantiated_p): Watch for construction vtables.\n\ngcc/testsuite/ChangeLog:\n\n\tPR ipa/120098\n\t* g++.dg/torture/pr120098.C: New test.",
    "diff": "diff --git a/gcc/ipa-devirt.cc b/gcc/ipa-devirt.cc\nindex 8577e9b30fb..db55084fe75 100644\n--- a/gcc/ipa-devirt.cc\n+++ b/gcc/ipa-devirt.cc\n@@ -227,8 +227,17 @@ struct GTY(()) odr_type_d\n   bool rtti_broken;\n   /* Set when the canonical type is determined using the type name.  */\n   bool tbaa_enabled;\n+  /* Set when we determined there are no derived construction vtables.  */\n+  bool no_derived_construction_vtables;\n };\n \n+/* ODR types also stored into ODR_TYPE vector to allow consistent\n+   walking.  Bases appear before derived types.  Vector is garbage collected\n+   so we won't end up visiting empty types.  */\n+\n+static GTY(()) vec <odr_type, va_gc> *odr_types_ptr;\n+#define odr_types (*odr_types_ptr)\n+\n /* Return TRUE if all derived types of T are known and thus\n    we may consider the walk of derived type complete.\n \n@@ -268,6 +277,46 @@ type_all_ctors_visible_p (tree t)\n \t && type_in_anonymous_namespace_p (t);\n }\n \n+/* Return true if VTABLE is is a virtual table of an anonymous namespace\n+   type and it is not the main virtual table for its type.  */\n+\n+static bool\n+anonymous_construction_vtable_p (tree vtable)\n+{\n+  if (!DECL_VIRTUAL_P (vtable)\n+      || !type_in_anonymous_namespace_p (DECL_CONTEXT (vtable)))\n+    return false;\n+  tree vtable2 = BINFO_VTABLE (TYPE_BINFO (DECL_CONTEXT (vtable)));\n+  if (TREE_CODE (vtable2) == POINTER_PLUS_EXPR)\n+    vtable2 = TREE_OPERAND (TREE_OPERAND (vtable2, 0), 0);\n+  return vtable2 != vtable;\n+}\n+\n+/* Set if construction vtables are computed.  */\n+static bool construction_vtables_detected = false;\n+\n+/* Mark all bases of T as having derived construction vtables.  */\n+\n+static void\n+mark_derived_construction_vtables (odr_type t)\n+{\n+  for (odr_type b: t->bases)\n+    {\n+      b->no_derived_construction_vtables = false;\n+      mark_derived_construction_vtables (b);\n+    }\n+}\n+\n+/* Watch removal of construction vtables so we recompute their\n+   existence.  */\n+\n+void\n+construction_vtable_hook (varpool_node *v, void *)\n+{\n+  if (anonymous_construction_vtable_p (v->decl))\n+    construction_vtables_detected = false;\n+}\n+\n /* Return TRUE if type may have instance.  */\n \n static bool\n@@ -284,7 +333,34 @@ type_possibly_instantiated_p (tree t)\n   if (TREE_CODE (vtable) == POINTER_PLUS_EXPR)\n     vtable = TREE_OPERAND (TREE_OPERAND (vtable, 0), 0);\n   vnode = varpool_node::get (vtable);\n-  return vnode && vnode->definition;\n+  if (vnode && vnode->definition)\n+    return true;\n+\n+  /* If T is derived, we may see only the construction vtable.\n+     To find them, we need to walk symbol table. Cache the result\n+     and only recompute when some vtables are removed.  This only\n+     happens in unreachable node removal, which is only called\n+     constant number of times during computation.  */\n+  odr_type odr_t = get_odr_type (t);\n+  if (odr_t->derived_types.length () && !construction_vtables_detected)\n+    {\n+      static bool hook_registered = false;\n+      if (!hook_registered)\n+\t{\n+\t  symtab->add_varpool_removal_hook (construction_vtable_hook, NULL);\n+\t  hook_registered = true;\n+\t}\n+      for (odr_type t: odr_types)\n+\tif (t)\n+\t  t->no_derived_construction_vtables = true;\n+      FOR_EACH_VARIABLE (vnode)\n+\tif (vnode->definition\n+\t    && anonymous_construction_vtable_p (vnode->decl))\n+\t  mark_derived_construction_vtables\n+\t    (get_odr_type (DECL_CONTEXT (vnode->decl)));\n+      construction_vtables_detected = true;\n+    }\n+  return !odr_t->no_derived_construction_vtables;\n }\n \n /* Return true if T or type derived from T may have instance.  */\n@@ -507,13 +583,6 @@ odr_name_hasher::remove (odr_type_d *v)\n typedef hash_table<odr_name_hasher> odr_hash_type;\n static odr_hash_type *odr_hash;\n \n-/* ODR types are also stored into ODR_TYPE vector to allow consistent\n-   walking.  Bases appear before derived types.  Vector is garbage collected\n-   so we won't end up visiting empty types.  */\n-\n-static GTY(()) vec <odr_type, va_gc> *odr_types_ptr;\n-#define odr_types (*odr_types_ptr)\n-\n /* All enums defined and accessible for the unit.  */\n static GTY(()) vec <tree, va_gc> *odr_enums;\n \n@@ -1979,6 +2048,7 @@ get_odr_type (tree type, bool insert)\n       val->type = type;\n       val->bases = vNULL;\n       val->derived_types = vNULL;\n+      val->no_derived_construction_vtables = false;\n       if (type_with_linkage_p (type))\n         val->anonymous_namespace = type_in_anonymous_namespace_p (type);\n       else\ndiff --git a/gcc/testsuite/g++.dg/torture/pr120098.C b/gcc/testsuite/g++.dg/torture/pr120098.C\nnew file mode 100644\nindex 00000000000..882f613d5d2\n--- /dev/null\n+++ b/gcc/testsuite/g++.dg/torture/pr120098.C\n@@ -0,0 +1,47 @@\n+// { dg-do run }\n+\n+#define N ((int*)0)\n+namespace {\n+class A {\n+public:\n+  unsigned length;\n+};\n+class B {};\n+class MultiTermDocs : public virtual B {\n+protected:\n+  A readerTermDocs;\n+  A subReaders;\n+  virtual B *m_fn1(int *) { return (B *)0; }\n+  virtual inline  ~MultiTermDocs();\n+  inline void wrap(void)\n+  {\n+  m_fn1(N);\n+  m_fn1(N);\n+  m_fn1(N);\n+  m_fn1(N);\n+  m_fn1(N);\n+  m_fn1(N);\n+  m_fn1(N);\n+  m_fn1(N);\n+  m_fn1(N);\n+  }\n+};\n+class C : MultiTermDocs {\n+  B *m_fn1(int *);\n+};\n+MultiTermDocs::~MultiTermDocs() {\n+  wrap ();\n+  if (&readerTermDocs) {\n+    B *a;\n+    for (unsigned i = 0; i < subReaders.length; i++)\n+      (a != 0);\n+  }\n+}\n+\n+B *C::m_fn1(int *) { __builtin_abort (); }\n+}\n+\n+int main()\n+{\n+  class C c;\n+}\n",
    "prefixes": []
}