This patch was approved by Caroline Tice, the maintainer of VTV.
https://gcc.gnu.org/pipermail/gcc-patches/2026-September/730139.html

I recreated it so that the diffs match the line numbers in the
current code. Since I don't have write access, could someone push it?

Corrected patch below the dotted line.
Thanks!

--------
vtv: Fix Memory Leak and Other Improvements

Currently, vtable_find_or_create_map_decl, given a class decl,
calls get_mangled_vtable_map_var_name (from mangle.cc) to:

  (1) create a VTV map entry for the given class; and
  (2) return the expected DECL_ASSEMBLER_NAME of its VTV tracker.

Here are some improvements for that logic:

a. (2) was only needed once for each class, and in that case, we
call get_identifier (var_name). Now we only generate the identifier
iff it is needed.

b. Since get_identifier copies data,var_name was always leaked.
This is now done without heap allocation.

c. get_identifier was called twice for the same symbol, which
costs an extra hash table lookup. Now we store it in a variable.

d. "vtable-class-hierarchy" and "mangle" depend on each other.
This is just because (1) is done inside mangle.cc. By moving that
statement to vtable-class-hierarchy, we avoid one extra circular
dependency.

The effect of vtable_find_or_create_map_decl has not changed.
Successfully bootstrapped with "--enable-vtable-verify".

gcc/cp/ChangeLog:

        * cp-tree.h (get_mangled_vtable_map_var_name): Only get the
          name, without side effects.
        (get_mangled_type_name_if_anon): Split off from function above.
        * mangle.cc (get_mangled_type_name_if_anon): Only get the name,
          without side effects.
        (get_mangled_vtable_map_var_name): Split off from function
        above.
        * vtable-class-hierarchy.cc (vtable_find_or_create_map_decl):
        Fix memory leak.
---
 gcc/cp/cp-tree.h                 |  3 +-
 gcc/cp/mangle.cc                 | 52 ++++++++++++++++----------------
 gcc/cp/vtable-class-hierarchy.cc | 22 +++++++++-----
 3 files changed, 42 insertions(+), 35 deletions(-)

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 369d2a9119d..4138cf34fc1 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -9171,7 +9171,8 @@ extern tree mangle_tls_wrapper_fn         (tree);
 extern bool decl_tls_wrapper_p                 (tree);
 extern tree mangle_ref_init_variable           (tree);
 extern tree mangle_template_parm_object                (tree);
-extern char *get_mangled_vtable_map_var_name    (tree);
+extern tree get_mangled_type_name_if_anon      (tree);
+extern tree get_mangled_vtable_map_var_name    (tree);
 extern bool mangle_return_type_p               (tree);
 extern tree mangle_decomp                      (tree, vec<tree> &);
 extern void mangle_module_substitution         (int);
diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc
index b2697f27c32..2fe580b463b 100644
--- a/gcc/cp/mangle.cc
+++ b/gcc/cp/mangle.cc
@@ -48,7 +48,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "target.h"
-#include "vtable-verify.h"
 #include "cp-tree.h"
 #include "stringpool.h"
 #include "cgraph.h"
@@ -5417,40 +5416,41 @@ mangle_template_parm_object (tree expr)
 }
 
 /* Given a CLASS_TYPE, such as a record for std::bad_exception this
-   function generates a mangled name for the vtable map variable of
-   the class type.  For example, if the class type is
-   "std::bad_exception", the mangled name for the class is
-   "St13bad_exception".  This function would generate the name
-   "_ZN4_VTVISt13bad_exceptionE12__vtable_mapE", which unmangles as:
-   "_VTV<std::bad_exception>::__vtable_map".  */
+   function returns NULL_TREE if TYPE_NAME (CLASS_TYPE) is not from
+   an anonymous namespace. Otherwise, returns the mangled type name.
+   */

+tree
+get_mangled_type_name_if_anon(tree class_type)
+ {
+  gcc_assert (TREE_CODE (class_type) == RECORD_TYPE);
+  tree class_id = DECL_ASSEMBLER_NAME (TYPE_NAME (class_type));
+  bool is_anon = strstr (IDENTIFIER_POINTER (class_id), "<anon>") != NULL;
+  return is_anon ? get_mangled_id (TYPE_NAME (class_type)) : NULL_TREE;
+}

-char *
-get_mangled_vtable_map_var_name (tree class_type)
+/* Given a CLASS_TYPE_ASSEMBLER_NAME, such as of the TYPE_NAME of a
+   record for std::bad_exception, this function generates a mangled
+   identifier for the vtable map variable of the class type.
+   For example, if the class type is "std::bad_exception", the mangled
+   name for the class is "St13bad_exception".  This function would
+   generate the name "_ZN4_VTVISt13bad_exceptionE12__vtable_mapE",
+   which unmangles as "_VTV<std::bad_exception>::__vtable_map".  */
+
+tree
+get_mangled_vtable_map_var_name (tree class_type_assembler_name)
 {
-  char *var_name = NULL;
   const char *prefix = "_ZN4_VTVI";
   const char *postfix = "E12__vtable_mapE";

-  gcc_assert (TREE_CODE (class_type) == RECORD_TYPE);
-
-  tree class_id = DECL_ASSEMBLER_NAME (TYPE_NAME (class_type));
-
-  if (strstr (IDENTIFIER_POINTER (class_id), "<anon>") != NULL)
-    {
-      class_id = get_mangled_id (TYPE_NAME (class_type));
-      vtbl_register_mangled_name (TYPE_NAME (class_type), class_id);
-    }
-
-  unsigned int len = strlen (IDENTIFIER_POINTER (class_id)) +
-                     strlen (prefix) +
-                     strlen (postfix) + 1;
+  const char * class_name =
+    IDENTIFIER_POINTER (class_type_assembler_name);

-  var_name = (char *) xmalloc (len);
+  gcc_assert (strstr (class_name, "<anon>") == NULL);

- sprintf (var_name, "%s%s%s", prefix, IDENTIFIER_POINTER (class_id), postfix);
+  char *var_name = ACONCAT ((prefix, class_name, postfix, NULL));

-  return var_name;
+  return get_identifier(var_name);
 }

 #include "gt-cp-mangle.h"
diff --git a/gcc/cp/vtable-class-hierarchy.cc b/gcc/cp/vtable-class-hierarchy.cc
index 2e52ea3c4a0..37ce5623806 100644
--- a/gcc/cp/vtable-class-hierarchy.cc
+++ b/gcc/cp/vtable-class-hierarchy.cc
@@ -1204,15 +1204,22 @@ vtv_generate_init_routine (void)
 struct vtbl_map_node *
 vtable_find_or_create_map_decl (tree base_type)
 {
-  char *var_name = NULL;
   struct vtbl_map_node *vtable_map_node = NULL;
+  tree base_type_name = DECL_ASSEMBLER_NAME (TYPE_NAME (base_type));

   /* Verify the type has an associated vtable.  */
   if (!TYPE_BINFO (base_type) || !BINFO_VTABLE (TYPE_BINFO (base_type)))
     return NULL;

   /* Create map lookup symbol for base class */
-  var_name = get_mangled_vtable_map_var_name (base_type);
+  tree mangled_base_type_name = get_mangled_type_name_if_anon (base_type);
+
+  if (mangled_base_type_name != NULL_TREE)
+    {
+      vtbl_register_mangled_name
+        (TYPE_NAME (base_type), mangled_base_type_name);
+      base_type_name = mangled_base_type_name;
+    }

   /* We've already created the variable; just look it.  */
   vtable_map_node = vtbl_map_get_node (TYPE_MAIN_VARIANT (base_type));
@@ -1223,17 +1230,16 @@ vtable_find_or_create_map_decl (tree base_type)
          variable for this class, do so now, and add it to the
          varpool, to make sure it gets saved and written out.  */

-      tree var_decl = NULL;
+      tree var_name = get_mangled_vtable_map_var_name (base_type_name);
       tree var_type = build_pointer_type (void_type_node);
-      tree initial_value = integer_zero_node;

-      var_decl  = build_decl (UNKNOWN_LOCATION, VAR_DECL,
-                              get_identifier (var_name), var_type);
+      tree var_decl =
+        build_decl (UNKNOWN_LOCATION, VAR_DECL, var_name, var_type);

       DECL_EXTERNAL (var_decl) = 0;
       TREE_STATIC (var_decl) = 1;
       DECL_VISIBILITY (var_decl) = VISIBILITY_HIDDEN;
-      SET_DECL_ASSEMBLER_NAME (var_decl, get_identifier (var_name));
+      SET_DECL_ASSEMBLER_NAME (var_decl, var_name);
       DECL_ARTIFICIAL (var_decl) = 1;
       /* We cannot mark this variable as read-only because we want to be
          able to write to it at runtime.  */
@@ -1246,7 +1252,7 @@ vtable_find_or_create_map_decl (tree base_type)

       set_decl_section_name (var_decl, ".vtable_map_vars");
       symtab_node::get (var_decl)->implicit_section = true;
-      DECL_INITIAL (var_decl) = initial_value;
+      DECL_INITIAL (var_decl) = integer_zero_node;

       comdat_linkage (var_decl);

--
2.47.3


Reply via email to