Replace some uses of xstrprintf with string_printf

Message ID 20180807021605.10534-1-simon.marchi@polymtl.ca
State New
Headers show
Series
  • Replace some uses of xstrprintf with string_printf
Related show

Commit Message

Simon Marchi Aug. 7, 2018, 2:16 a.m.
From: Simon Marchi <simon.marchi@ericsson.com>


This patch replaces some simple uses of xstrprintf with with
string_printf, removing the need to do manual memory freeing.

The change in ada-lang.c fixes an apparent memory leak.

Regtested on the buildbot.

gdb/ChangeLog:

	* common/filestuff.h (gdb_fopen_cloexec): New overload.
	(gdb_open_cloexec): Likewise.
	* nat/linux-osdata.c (command_from_pid): Use string_printf.
	(commandline_from_pid): Likewise.
	(linux_xfer_osdata_threads): Likewise.
	(linux_xfer_osdata_fds): Likewise.
	* ada-lang.c (is_package_name): Likewise.
	* auxv.c (procfs_xfer_auxv): Likewise.
	* breakpoint.c (print_one_breakpoint_location): Use
	uiout::field_fmt.
	(print_one_catch_solib): Use string_printf.
	* coff-pe-read.c (add_pe_exported_sym): Likewise.
	(add_pe_forwarded_sym): Likewise.
	* dwarf2read.c (create_type_unit_group): Likewise.
	(build_error_marker_type): Likewise.
	* infcall.c (get_function_name): Likewise.
	* valprint.c (print_converted_chars_to_obstack): Likewise.
	* xtensa-tdep.c (xtensa_register_type): Likewise.
---
 gdb/ada-lang.c         |  6 ++----
 gdb/auxv.c             |  4 +---
 gdb/breakpoint.c       | 22 +++++++---------------
 gdb/coff-pe-read.c     | 32 ++++++++++++++++----------------
 gdb/common/filestuff.h | 19 +++++++++++++++++++
 gdb/dwarf2read.c       | 26 ++++++++++++--------------
 gdb/infcall.c          | 10 ++++------
 gdb/nat/linux-osdata.c | 32 +++++++++++++-------------------
 gdb/valprint.c         |  5 ++---
 gdb/xtensa-tdep.c      |  5 ++---
 10 files changed, 78 insertions(+), 83 deletions(-)

-- 
2.18.0

Comments

Tom Tromey Aug. 7, 2018, 3:53 p.m. | #1
>>>>> "Simon" == Simon Marchi <simon.marchi@polymtl.ca> writes:


Simon> From: Simon Marchi <simon.marchi@ericsson.com>
Simon> This patch replaces some simple uses of xstrprintf with with
Simon> string_printf, removing the need to do manual memory freeing.

Simon> The change in ada-lang.c fixes an apparent memory leak.

FWIW, I read this patch and I think it is good.

Simon> +  std::string message
Simon> +    = string_printf (_("<unknown type in %s, CU %s, DIE %s>"),
Simon> +		     objfile_name (objfile),
Simon> +		     sect_offset_str (cu->header.sect_off),
Simon> +		     sect_offset_str (die->sect_off));
Simon>    saved = (char *) obstack_copy0 (&objfile->objfile_obstack,

gnulib (and glibc) have an obstack_printf function, which would perhaps
avoid some allocations here.

However, I don't know if it is practical to import the gnulib
obstack_printf, because presumably it would want the gnulib obstack code
generally, and gdb is using the obstack from libiberty.

In the long run I tend to think it would be better to promote gnulib to
the top level and remove some things from libiberty.  But that seems
like a pretty big project.

Tom
Simon Marchi Aug. 7, 2018, 9:45 p.m. | #2
On 2018-08-07 11:53, Tom Tromey wrote:
>>>>>> "Simon" == Simon Marchi <simon.marchi@polymtl.ca> writes:

> 

> Simon> From: Simon Marchi <simon.marchi@ericsson.com>

> Simon> This patch replaces some simple uses of xstrprintf with with

> Simon> string_printf, removing the need to do manual memory freeing.

> 

> Simon> The change in ada-lang.c fixes an apparent memory leak.

> 

> FWIW, I read this patch and I think it is good.


Thanks, I pushed it.

> Simon> +  std::string message

> Simon> +    = string_printf (_("<unknown type in %s, CU %s, DIE %s>"),

> Simon> +		     objfile_name (objfile),

> Simon> +		     sect_offset_str (cu->header.sect_off),

> Simon> +		     sect_offset_str (die->sect_off));

> Simon>    saved = (char *) obstack_copy0 (&objfile->objfile_obstack,

> 

> gnulib (and glibc) have an obstack_printf function, which would perhaps

> avoid some allocations here.

> 

> However, I don't know if it is practical to import the gnulib

> obstack_printf, because presumably it would want the gnulib obstack 

> code

> generally, and gdb is using the obstack from libiberty.

> 

> In the long run I tend to think it would be better to promote gnulib to

> the top level and remove some things from libiberty.  But that seems

> like a pretty big project.


Ok, I don't really have an opinion because I don't know the history of 
all the parts.  But it would also be quite simple to do our own 
obstack_printf, like we have string_printf.

Simon

Patch

diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index d9854b74175f..07a053668489 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -5205,8 +5205,6 @@  is_package_name (const char *name)
      to NAME not existing in our list of symbols.  There is only one
      small complication with library-level functions (see below).  */
 
-  char *fun_name;
-
   /* If it is a function that has not been defined at library level,
      then we should be able to look it up in the symbols.  */
   if (standard_lookup (name, NULL, VAR_DOMAIN) != NULL)
@@ -5220,9 +5218,9 @@  is_package_name (const char *name)
   if (strstr (name, "__") != NULL)
     return 0;
 
-  fun_name = xstrprintf ("_ada_%s", name);
+  std::string fun_name = string_printf ("_ada_%s", name);
 
-  return (standard_lookup (fun_name, NULL, VAR_DOMAIN) == NULL);
+  return (standard_lookup (fun_name.c_str (), NULL, VAR_DOMAIN) == NULL);
 }
 
 /* Return nonzero if SYM corresponds to a renaming entity that is
diff --git a/gdb/auxv.c b/gdb/auxv.c
index dda14f2cae7c..13bf9c390aa3 100644
--- a/gdb/auxv.c
+++ b/gdb/auxv.c
@@ -46,13 +46,11 @@  procfs_xfer_auxv (gdb_byte *readbuf,
 		  ULONGEST len,
 		  ULONGEST *xfered_len)
 {
-  char *pathname;
   int fd;
   ssize_t l;
 
-  pathname = xstrprintf ("/proc/%d/auxv", inferior_ptid.pid ());
+  std::string pathname = string_printf ("/proc/%d/auxv", inferior_ptid.pid ());
   fd = gdb_open_cloexec (pathname, writebuf != NULL ? O_WRONLY : O_RDONLY, 0);
-  xfree (pathname);
   if (fd < 0)
     return TARGET_XFER_E_IO;
 
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 6b6e1f6c257c..8f0feaa47479 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -6038,16 +6038,9 @@  print_one_breakpoint_location (struct breakpoint *b,
   /* 1 */
   annotate_field (0);
   if (part_of_multiple)
-    {
-      char *formatted;
-      formatted = xstrprintf ("%d.%d", b->number, loc_number);
-      uiout->field_string ("number", formatted);
-      xfree (formatted);
-    }
+    uiout->field_fmt ("number", "%d.%d", b->number, loc_number);
   else
-    {
-      uiout->field_int ("number", b->number);
-    }
+    uiout->field_int ("number", b->number);
 
   /* 2 */
   annotate_field (1);
@@ -8048,7 +8041,6 @@  print_one_catch_solib (struct breakpoint *b, struct bp_location **locs)
   struct solib_catchpoint *self = (struct solib_catchpoint *) b;
   struct value_print_options opts;
   struct ui_out *uiout = current_uiout;
-  char *msg;
 
   get_user_print_options (&opts);
   /* Field 4, the address, is omitted (which makes the columns not
@@ -8060,23 +8052,23 @@  print_one_catch_solib (struct breakpoint *b, struct bp_location **locs)
       uiout->field_skip ("addr");
     }
 
+  std::string msg;
   annotate_field (5);
   if (self->is_load)
     {
       if (self->regex)
-	msg = xstrprintf (_("load of library matching %s"), self->regex);
+	msg = string_printf (_("load of library matching %s"), self->regex);
       else
-	msg = xstrdup (_("load of library"));
+	msg = _("load of library");
     }
   else
     {
       if (self->regex)
-	msg = xstrprintf (_("unload of library matching %s"), self->regex);
+	msg = string_printf (_("unload of library matching %s"), self->regex);
       else
-	msg = xstrdup (_("unload of library"));
+	msg = _("unload of library");
     }
   uiout->field_string ("what", msg);
-  xfree (msg);
 
   if (uiout->is_mi_like_p ())
     uiout->field_string ("catch-type", self->is_load ? "load" : "unload");
diff --git a/gdb/coff-pe-read.c b/gdb/coff-pe-read.c
index 97b646a56bdb..45f2197ed3ac 100644
--- a/gdb/coff-pe-read.c
+++ b/gdb/coff-pe-read.c
@@ -157,7 +157,6 @@  add_pe_exported_sym (minimal_symbol_reader &reader,
 		     const struct read_pe_section_data *section_data,
 		     const char *dll_name, struct objfile *objfile)
 {
-  char *qualified_name, *bare_name;
   /* Add the stored offset to get the loaded address of the symbol.  */
   CORE_ADDR vma = func_rva + section_data->vma_offset;
 
@@ -165,12 +164,14 @@  add_pe_exported_sym (minimal_symbol_reader &reader,
      of the dll name, e.g. KERNEL32!AddAtomA.  This matches the style
      used by windbg from the "Microsoft Debugging Tools for Windows".  */
 
+  std::string bare_name;
   if (sym_name == NULL || *sym_name == '\0')
-    bare_name = xstrprintf ("#%d", ordinal);
+    bare_name = string_printf ("#%d", ordinal);
   else
-    bare_name = xstrdup (sym_name);
+    bare_name = sym_name;
 
-  qualified_name = xstrprintf ("%s!%s", dll_name, bare_name);
+  std::string qualified_name
+    = string_printf ("%s!%s", dll_name, bare_name.c_str ());
 
   if ((section_data->ms_type == mst_unknown) && debug_coff_pe_read)
     fprintf_unfiltered (gdb_stdlog , _("Unknown section type for \"%s\""
@@ -178,17 +179,15 @@  add_pe_exported_sym (minimal_symbol_reader &reader,
 			section_data->section_name.c_str (), sym_name,
 			dll_name);
 
-  reader.record_with_info (qualified_name, vma, section_data->ms_type,
+  reader.record_with_info (qualified_name.c_str (), vma, section_data->ms_type,
 			   section_data->index);
 
   /* Enter the plain name as well, which might not be unique.  */
-  reader.record_with_info (bare_name, vma, section_data->ms_type,
+  reader.record_with_info (bare_name.c_str (), vma, section_data->ms_type,
 			   section_data->index);
   if (debug_coff_pe_read > 1)
     fprintf_unfiltered (gdb_stdlog, _("Adding exported symbol \"%s\""
 			" in dll \"%s\"\n"), sym_name, dll_name);
-  xfree (qualified_name);
-  xfree (bare_name);
 }
 
 /* Create a minimal symbol entry for an exported forward symbol.
@@ -209,7 +208,6 @@  add_pe_forwarded_sym (minimal_symbol_reader &reader,
   CORE_ADDR vma, baseaddr;
   struct bound_minimal_symbol msymbol;
   enum minimal_symbol_type msymtype;
-  char *qualified_name, *bare_name;
   int forward_dll_name_len = strlen (forward_dll_name);
   int forward_func_name_len = strlen (forward_func_name);
   int forward_len = forward_dll_name_len + forward_func_name_len + 2;
@@ -254,12 +252,14 @@  add_pe_forwarded_sym (minimal_symbol_reader &reader,
      of the dll name, e.g. KERNEL32!AddAtomA.  This matches the style
      used by windbg from the "Microsoft Debugging Tools for Windows".  */
 
+  std::string bare_name;
   if (sym_name == NULL || *sym_name == '\0')
-    bare_name = xstrprintf ("#%d", ordinal);
+    bare_name = string_printf ("#%d", ordinal);
   else
-    bare_name = xstrdup (sym_name);
+    bare_name = sym_name;
 
-  qualified_name = xstrprintf ("%s!%s", dll_name, bare_name);
+  std::string qualified_name
+    = string_printf ("%s!%s", dll_name, bare_name.c_str ());
 
   /* Note that this code makes a minimal symbol whose value may point
      outside of any section in this objfile.  These symbols can't
@@ -268,12 +268,12 @@  add_pe_forwarded_sym (minimal_symbol_reader &reader,
      code.  */
   baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 
-  reader.record_with_info (qualified_name, vma - baseaddr, msymtype, section);
+  reader.record_with_info (qualified_name.c_str (), vma - baseaddr, msymtype,
+			   section);
 
   /* Enter the plain name as well, which might not be unique.  */
-  reader.record_with_info (bare_name, vma - baseaddr, msymtype, section);
-  xfree (qualified_name);
-  xfree (bare_name);
+  reader.record_with_info (bare_name.c_str(), vma - baseaddr, msymtype,
+			   section);
 
   return 1;
 }
diff --git a/gdb/common/filestuff.h b/gdb/common/filestuff.h
index 0e46eb5da0b1..1a09c729f64b 100644
--- a/gdb/common/filestuff.h
+++ b/gdb/common/filestuff.h
@@ -48,6 +48,16 @@  extern void close_most_fds (void);
 extern int gdb_open_cloexec (const char *filename, int flags,
 			     /* mode_t */ unsigned long mode);
 
+/* Convenience wrapper for the above, which takes the filename as an
+   std::string.  */
+
+static inline int
+gdb_open_cloexec (const std::string &filename, int flags,
+		  /* mode_t */ unsigned long mode)
+{
+  return gdb_open_cloexec (filename.c_str (), flags, mode);
+}
+
 struct gdb_file_deleter
 {
   void operator() (FILE *file) const
@@ -66,6 +76,15 @@  typedef std::unique_ptr<FILE, gdb_file_deleter> gdb_file_up;
 extern gdb_file_up gdb_fopen_cloexec (const char *filename,
 				      const char *opentype);
 
+/* Convenience wrapper for the above, which takes the filename as an
+   std::string.  */
+
+static inline gdb_file_up
+gdb_fopen_cloexec (const std::string &filename, const char *opentype)
+{
+  return gdb_fopen_cloexec (filename.c_str (), opentype);
+}
+
 /* Like 'socketpair', but ensures that the returned file descriptors
    have the close-on-exec flag set.  */
 
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index a75821228956..e4b621d159c5 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -7757,19 +7757,17 @@  create_type_unit_group (struct dwarf2_cu *cu, sect_offset line_offset_struct)
     {
       unsigned int line_offset = to_underlying (line_offset_struct);
       struct partial_symtab *pst;
-      char *name;
+      std::string name;
 
       /* Give the symtab a useful name for debug purposes.  */
       if ((line_offset & NO_STMT_LIST_TYPE_UNIT_PSYMTAB) != 0)
-	name = xstrprintf ("<type_units_%d>",
-			   (line_offset & ~NO_STMT_LIST_TYPE_UNIT_PSYMTAB));
+	name = string_printf ("<type_units_%d>",
+			      (line_offset & ~NO_STMT_LIST_TYPE_UNIT_PSYMTAB));
       else
-	name = xstrprintf ("<type_units_at_0x%x>", line_offset);
+	name = string_printf ("<type_units_at_0x%x>", line_offset);
 
-      pst = create_partial_symtab (per_cu, name);
+      pst = create_partial_symtab (per_cu, name.c_str ());
       pst->anonymous = 1;
-
-      xfree (name);
     }
 
   tu_group->hash.dwo_unit = cu->dwo_unit;
@@ -21844,15 +21842,15 @@  build_error_marker_type (struct dwarf2_cu *cu, struct die_info *die)
   struct dwarf2_per_objfile *dwarf2_per_objfile
     = cu->per_cu->dwarf2_per_objfile;
   struct objfile *objfile = dwarf2_per_objfile->objfile;
-  char *message, *saved;
+  char *saved;
 
-  message = xstrprintf (_("<unknown type in %s, CU %s, DIE %s>"),
-			objfile_name (objfile),
-			sect_offset_str (cu->header.sect_off),
-			sect_offset_str (die->sect_off));
+  std::string message
+    = string_printf (_("<unknown type in %s, CU %s, DIE %s>"),
+		     objfile_name (objfile),
+		     sect_offset_str (cu->header.sect_off),
+		     sect_offset_str (die->sect_off));
   saved = (char *) obstack_copy0 (&objfile->objfile_obstack,
-				  message, strlen (message));
-  xfree (message);
+				  message.c_str (), message.length ());
 
   return init_type (objfile, TYPE_CODE_ERROR, 0, saved);
 }
diff --git a/gdb/infcall.c b/gdb/infcall.c
index c995ab7c9185..b2d1205faaff 100644
--- a/gdb/infcall.c
+++ b/gdb/infcall.c
@@ -385,13 +385,11 @@  get_function_name (CORE_ADDR funaddr, char *buf, int buf_size)
   }
 
   {
-    char *tmp = xstrprintf (_(RAW_FUNCTION_ADDRESS_FORMAT),
-                            hex_string (funaddr));
+    std::string tmp = string_printf (_(RAW_FUNCTION_ADDRESS_FORMAT),
+				     hex_string (funaddr));
 
-    gdb_assert (strlen (tmp) + 1 <= buf_size);
-    strcpy (buf, tmp);
-    xfree (tmp);
-    return buf;
+    gdb_assert (tmp.length () + 1 <= buf_size);
+    return strcpy (buf, tmp.c_str ());
   }
 }
 
diff --git a/gdb/nat/linux-osdata.c b/gdb/nat/linux-osdata.c
index 2323dcc878b2..9850cad235bd 100644
--- a/gdb/nat/linux-osdata.c
+++ b/gdb/nat/linux-osdata.c
@@ -115,7 +115,7 @@  linux_common_core_of_thread (ptid_t ptid)
 static void
 command_from_pid (char *command, int maxlen, PID_T pid)
 {
-  char *stat_path = xstrprintf ("/proc/%lld/stat", pid); 
+  std::string stat_path = string_printf ("/proc/%lld/stat", pid);
   gdb_file_up fp = gdb_fopen_cloexec (stat_path, "r");
   
   command[0] = '\0';
@@ -142,8 +142,6 @@  command_from_pid (char *command, int maxlen, PID_T pid)
     }
 
   command[maxlen - 1] = '\0'; /* Ensure string is null-terminated.  */
-	
-  xfree (stat_path);
 }
 
 /* Returns the command-line of the process with the given PID. The
@@ -152,7 +150,7 @@  command_from_pid (char *command, int maxlen, PID_T pid)
 static char *
 commandline_from_pid (PID_T pid)
 {
-  char *pathname = xstrprintf ("/proc/%lld/cmdline", pid);
+  std::string pathname = xstrprintf ("/proc/%lld/cmdline", pid);
   char *commandline = NULL;
   gdb_file_up f = gdb_fopen_cloexec (pathname, "r");
 
@@ -198,8 +196,6 @@  commandline_from_pid (PID_T pid)
 	}
     }
 
-  xfree (pathname);
-
   return commandline;
 }
 
@@ -572,16 +568,16 @@  linux_xfer_osdata_threads (gdb_byte *readbuf,
 		  && S_ISDIR (statbuf.st_mode))
 		{
 		  DIR *dirp2;
-		  char *pathname;
 		  PID_T pid;
 		  char command[32];
 
-		  pathname = xstrprintf ("/proc/%s/task", dp->d_name);
+		  std::string pathname
+		    = string_printf ("/proc/%s/task", dp->d_name);
 		  
 		  pid = atoi (dp->d_name);
 		  command_from_pid (command, sizeof (command), pid);
 
-		  dirp2 = opendir (pathname);
+		  dirp2 = opendir (pathname.c_str ());
 
 		  if (dirp2)
 		    {
@@ -615,8 +611,6 @@  linux_xfer_osdata_threads (gdb_byte *readbuf,
 
 		      closedir (dirp2);
 		    }
-
-		  xfree (pathname);
 		}
 	    }
 
@@ -781,7 +775,6 @@  linux_xfer_osdata_fds (gdb_byte *readbuf,
 	      if (stat (procentry, &statbuf) == 0
 		  && S_ISDIR (statbuf.st_mode))
 		{
-		  char *pathname;
 		  DIR *dirp2;
 		  PID_T pid;
 		  char command[32];
@@ -789,8 +782,9 @@  linux_xfer_osdata_fds (gdb_byte *readbuf,
 		  pid = atoi (dp->d_name);
 		  command_from_pid (command, sizeof (command), pid);
 
-		  pathname = xstrprintf ("/proc/%s/fd", dp->d_name);
-		  dirp2 = opendir (pathname);
+		  std::string pathname
+		    = string_printf ("/proc/%s/fd", dp->d_name);
+		  dirp2 = opendir (pathname.c_str ());
 
 		  if (dirp2)
 		    {
@@ -798,15 +792,17 @@  linux_xfer_osdata_fds (gdb_byte *readbuf,
 
 		      while ((dp2 = readdir (dirp2)) != NULL)
 			{
-			  char *fdname;
 			  char buf[1000];
 			  ssize_t rslt;
 
 			  if (!isdigit (dp2->d_name[0]))
 			    continue;
 
-			  fdname = xstrprintf ("%s/%s", pathname, dp2->d_name);
-			  rslt = readlink (fdname, buf, sizeof (buf) - 1);
+			  std::string fdname
+			    = string_printf ("%s/%s", pathname.c_str (),
+					     dp2->d_name);
+			  rslt = readlink (fdname.c_str (), buf,
+					   sizeof (buf) - 1);
 			  if (rslt >= 0)
 			    buf[rslt] = '\0';
 
@@ -826,8 +822,6 @@  linux_xfer_osdata_fds (gdb_byte *readbuf,
 
 		      closedir (dirp2);
 		    }
-
-		  xfree (pathname);
 		}
 	    }
 
diff --git a/gdb/valprint.c b/gdb/valprint.c
index a48f39eb3bec..d1d3232e10d7 100644
--- a/gdb/valprint.c
+++ b/gdb/valprint.c
@@ -2572,7 +2572,6 @@  print_converted_chars_to_obstack (struct obstack *obstack,
 	case REPEAT:
 	  {
 	    int j;
-	    char *s;
 
 	    /* We are outputting a character with a repeat count
 	       greater than options->repeat_count_threshold.  */
@@ -2595,13 +2594,13 @@  print_converted_chars_to_obstack (struct obstack *obstack,
 	      print_wchar (gdb_WEOF, elem->buf, elem->buflen, width,
 			   byte_order, obstack, quote_char, &need_escape);
 	    obstack_grow_wstr (obstack, LCST ("'"));
-	    s = xstrprintf (_(" <repeats %u times>"), elem->repeat_count);
+	    std::string s = string_printf (_(" <repeats %u times>"),
+					   elem->repeat_count);
 	    for (j = 0; s[j]; ++j)
 	      {
 		gdb_wchar_t w = gdb_btowc (s[j]);
 		obstack_grow (obstack, &w, sizeof (gdb_wchar_t));
 	      }
-	    xfree (s);
 	  }
 	  break;
 
diff --git a/gdb/xtensa-tdep.c b/gdb/xtensa-tdep.c
index 60e34c3075b2..7c0d8c15a752 100644
--- a/gdb/xtensa-tdep.c
+++ b/gdb/xtensa-tdep.c
@@ -319,15 +319,14 @@  xtensa_register_type (struct gdbarch *gdbarch, int regnum)
 
 	      if (tp == NULL)
 		{
-		  char *name = xstrprintf ("int%d", size * 8);
+		  std::string name = string_printf ("int%d", size * 8);
 
 		  tp = XNEW (struct ctype_cache);
 		  tp->next = tdep->type_entries;
 		  tdep->type_entries = tp;
 		  tp->size = size;
 		  tp->virtual_type
-		    = arch_integer_type (gdbarch, size * 8, 1, name);
-		  xfree (name);
+		    = arch_integer_type (gdbarch, size * 8, 1, name.c_str ());
 		}
 
 	      reg->ctype = tp->virtual_type;