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