Use unique_xmalloc_ptr<char> when demangling

Message ID 20211004162047.677985-1-tromey@adacore.com
State New
Headers show
Series
  • Use unique_xmalloc_ptr<char> when demangling
Related show

Commit Message

Bruno Larsen via Gdb-patches Oct. 4, 2021, 4:20 p.m.
I noticed that some methods in language_defn could use
unique_xmalloc_ptr<char> rather than a plain 'char *'.  This patch
implements this change, fixing up the fallout and changing
gdb_demangle to also return this type.  In one spot, std::string is
used to simplify some related code, and in another, an auto_obstack is
used to avoid manual management.

Regression tested on x86-64 Fedora 34.
---
 gdb/ada-lang.c     | 16 ++++++----------
 gdb/c-lang.c       |  8 +++++---
 gdb/c-typeprint.c  | 34 +++++++++++++---------------------
 gdb/cp-support.c   | 29 ++++++++++++-----------------
 gdb/cp-support.h   |  2 +-
 gdb/d-lang.c       | 10 ++++++----
 gdb/d-lang.h       |  3 ++-
 gdb/dwarf2/read.c  |  5 ++---
 gdb/f-lang.h       |  3 ++-
 gdb/gdb-demangle.c |  9 +++------
 gdb/gdbtypes.c     |  8 +++-----
 gdb/gnu-v2-abi.c   |  9 +++++----
 gdb/gnu-v3-abi.c   |  9 +++------
 gdb/go-lang.c      | 23 +++++++++--------------
 gdb/go-lang.h      |  8 +++++---
 gdb/language.c     |  5 +++--
 gdb/language.h     | 12 +++++++-----
 gdb/minsyms.c      |  5 +++--
 gdb/objc-lang.c    | 12 +++++++-----
 gdb/rust-lang.h    |  8 +++++---
 gdb/symtab.c       | 21 +++++++++++----------
 gdb/symtab.h       |  4 ++--
 gdb/utils.c        | 11 +++--------
 23 files changed, 118 insertions(+), 136 deletions(-)

-- 
2.31.1

Comments

Bruno Larsen via Gdb-patches Oct. 4, 2021, 5:54 p.m. | #1
On 2021-10-04 12:20, Tom Tromey via Gdb-patches wrote:
> I noticed that some methods in language_defn could use

> unique_xmalloc_ptr<char> rather than a plain 'char *'.  This patch

> implements this change, fixing up the fallout and changing

> gdb_demangle to also return this type.  In one spot, std::string is

> used to simplify some related code, and in another, an auto_obstack is

> used to avoid manual management.


The obstack could also be replace with an std::string to which you
append.  But also if what is here works, there's not reason to change
it.

The patch LGTM in any case.

Simon

Patch

diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 1a3ce365d91..3b7c10f8e6c 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -1324,12 +1324,6 @@  ada_decode_symbol (const struct general_symbol_info *arg)
   return *resultp;
 }
 
-static char *
-ada_la_decode (const char *encoded, int options)
-{
-  return xstrdup (ada_decode (encoded).c_str ());
-}
-
 
 
 				/* Arrays */
@@ -13116,8 +13110,9 @@  class ada_language : public language_defn
   }
 
   /* See language.h.  */
-  bool sniff_from_mangled_name (const char *mangled,
-				char **out) const override
+  bool sniff_from_mangled_name
+       (const char *mangled,
+	gdb::unique_xmalloc_ptr<char> *out) const override
   {
     std::string demangled = ada_decode (mangled);
 
@@ -13155,9 +13150,10 @@  class ada_language : public language_defn
 
   /* See language.h.  */
 
-  char *demangle_symbol (const char *mangled, int options) const override
+  gdb::unique_xmalloc_ptr<char> demangle_symbol (const char *mangled,
+						 int options) const override
   {
-    return ada_la_decode (mangled, options);
+    return make_unique_xstrdup (ada_decode (mangled).c_str ());
   }
 
   /* See language.h.  */
diff --git a/gdb/c-lang.c b/gdb/c-lang.c
index 98f4984b020..98250f5151d 100644
--- a/gdb/c-lang.c
+++ b/gdb/c-lang.c
@@ -944,8 +944,9 @@  class cplus_language : public language_defn
   }
 
   /* See language.h.  */
-  bool sniff_from_mangled_name (const char *mangled,
-				char **demangled) const override
+  bool sniff_from_mangled_name
+       (const char *mangled,
+	gdb::unique_xmalloc_ptr<char> *demangled) const override
   {
     *demangled = gdb_demangle (mangled, DMGL_PARAMS | DMGL_ANSI);
     return *demangled != NULL;
@@ -953,7 +954,8 @@  class cplus_language : public language_defn
 
   /* See language.h.  */
 
-  char *demangle_symbol (const char *mangled, int options) const override
+  gdb::unique_xmalloc_ptr<char> demangle_symbol (const char *mangled,
+						 int options) const override
   {
     return gdb_demangle (mangled, options);
   }
diff --git a/gdb/c-typeprint.c b/gdb/c-typeprint.c
index 107d200bd55..33700aa34fd 100644
--- a/gdb/c-typeprint.c
+++ b/gdb/c-typeprint.c
@@ -674,16 +674,16 @@  is_type_conversion_operator (struct type *type, int i, int j)
    form.  Even the author of this function feels that writing little
    parsers like this everywhere is stupid.  */
 
-static char *
-remove_qualifiers (char *qid)
+static const char *
+remove_qualifiers (const char *qid)
 {
   int quoted = 0;	/* Zero if we're not in quotes;
 			   '"' if we're in a double-quoted string;
 			   '\'' if we're in a single-quoted string.  */
   int depth = 0;	/* Number of unclosed parens we've seen.  */
   char *parenstack = (char *) alloca (strlen (qid));
-  char *scan;
-  char *last = 0;	/* The character after the rightmost
+  const char *scan;
+  const char *last = 0;	/* The character after the rightmost
 			   `::' token we've seen so far.  */
 
   for (scan = qid; *scan; scan++)
@@ -1257,7 +1257,6 @@  c_type_print_base_struct_union (struct type *type, struct ui_file *stream,
 	    {
 	      const char *mangled_name;
 	      gdb::unique_xmalloc_ptr<char> mangled_name_holder;
-	      char *demangled_name;
 	      const char *physname = TYPE_FN_FIELD_PHYSNAME (f, j);
 	      int is_full_physname_constructor =
 		TYPE_FN_FIELD_CONSTRUCTOR (f, j)
@@ -1311,9 +1310,9 @@  c_type_print_base_struct_union (struct type *type, struct ui_file *stream,
 	      else
 		mangled_name = TYPE_FN_FIELD_PHYSNAME (f, j);
 
-	      demangled_name =
-		gdb_demangle (mangled_name,
-			      DMGL_ANSI | DMGL_PARAMS);
+	      gdb::unique_xmalloc_ptr<char> demangled_name
+		= gdb_demangle (mangled_name,
+				DMGL_ANSI | DMGL_PARAMS);
 	      if (demangled_name == NULL)
 		{
 		  /* In some cases (for instance with the HP
@@ -1340,9 +1339,9 @@  c_type_print_base_struct_union (struct type *type, struct ui_file *stream,
 		}
 	      else
 		{
-		  char *p;
-		  char *demangled_no_class
-		    = remove_qualifiers (demangled_name);
+		  const char *p;
+		  const char *demangled_no_class
+		    = remove_qualifiers (demangled_name.get ());
 
 		  /* Get rid of the `static' appended by the
 		     demangler.  */
@@ -1350,19 +1349,12 @@  c_type_print_base_struct_union (struct type *type, struct ui_file *stream,
 		  if (p != NULL)
 		    {
 		      int length = p - demangled_no_class;
-		      char *demangled_no_static;
-
-		      demangled_no_static
-			= (char *) xmalloc (length + 1);
-		      strncpy (demangled_no_static,
-			       demangled_no_class, length);
-		      *(demangled_no_static + length) = '\0';
-		      fputs_filtered (demangled_no_static, stream);
-		      xfree (demangled_no_static);
+		      std::string demangled_no_static (demangled_no_class,
+						       length);
+		      fputs_filtered (demangled_no_static.c_str (), stream);
 		    }
 		  else
 		    fputs_filtered (demangled_no_class, stream);
-		  xfree (demangled_name);
 		}
 
 	      fprintf_filtered (stream, ";\n");
diff --git a/gdb/cp-support.c b/gdb/cp-support.c
index fb4c8364ae0..367fb6a20bb 100644
--- a/gdb/cp-support.c
+++ b/gdb/cp-support.c
@@ -661,10 +661,9 @@  cp_canonicalize_string (const char *string)
 
 static std::unique_ptr<demangle_parse_info>
 mangled_name_to_comp (const char *mangled_name, int options,
-		      void **memory, char **demangled_p)
+		      void **memory,
+		      gdb::unique_xmalloc_ptr<char> *demangled_p)
 {
-  char *demangled_name;
-
   /* If it looks like a v3 mangled name, then try to go directly
      to trees.  */
   if (mangled_name[0] == '_' && mangled_name[1] == 'Z')
@@ -684,22 +683,20 @@  mangled_name_to_comp (const char *mangled_name, int options,
 
   /* If it doesn't, or if that failed, then try to demangle the
      name.  */
-  demangled_name = gdb_demangle (mangled_name, options);
+  gdb::unique_xmalloc_ptr<char> demangled_name = gdb_demangle (mangled_name,
+							       options);
   if (demangled_name == NULL)
    return NULL;
   
   /* If we could demangle the name, parse it to build the component
      tree.  */
   std::unique_ptr<demangle_parse_info> info
-    = cp_demangled_name_to_comp (demangled_name, NULL);
+    = cp_demangled_name_to_comp (demangled_name.get (), NULL);
 
   if (info == NULL)
-    {
-      xfree (demangled_name);
-      return NULL;
-    }
+    return NULL;
 
-  *demangled_p = demangled_name;
+  *demangled_p = std::move (demangled_name);
   return info;
 }
 
@@ -709,7 +706,7 @@  char *
 cp_class_name_from_physname (const char *physname)
 {
   void *storage = NULL;
-  char *demangled_name = NULL;
+  gdb::unique_xmalloc_ptr<char> demangled_name;
   gdb::unique_xmalloc_ptr<char> ret;
   struct demangle_component *ret_comp, *prev_comp, *cur_comp;
   std::unique_ptr<demangle_parse_info> info;
@@ -789,7 +786,6 @@  cp_class_name_from_physname (const char *physname)
     }
 
   xfree (storage);
-  xfree (demangled_name);
   return ret.release ();
 }
 
@@ -857,7 +853,7 @@  char *
 method_name_from_physname (const char *physname)
 {
   void *storage = NULL;
-  char *demangled_name = NULL;
+  gdb::unique_xmalloc_ptr<char> demangled_name;
   gdb::unique_xmalloc_ptr<char> ret;
   struct demangle_component *ret_comp;
   std::unique_ptr<demangle_parse_info> info;
@@ -875,7 +871,6 @@  method_name_from_physname (const char *physname)
     ret = cp_comp_to_string (ret_comp, 10);
 
   xfree (storage);
-  xfree (demangled_name);
   return ret.release ();
 }
 
@@ -1604,10 +1599,10 @@  report_failed_demangle (const char *name, bool core_dump_allowed,
 
 /* A wrapper for bfd_demangle.  */
 
-char *
+gdb::unique_xmalloc_ptr<char>
 gdb_demangle (const char *name, int options)
 {
-  char *result = NULL;
+  gdb::unique_xmalloc_ptr<char> result;
   int crash_signal = 0;
 
 #ifdef HAVE_WORKING_FORK
@@ -1636,7 +1631,7 @@  gdb_demangle (const char *name, int options)
 #endif
 
   if (crash_signal == 0)
-    result = bfd_demangle (NULL, name, options);
+    result.reset (bfd_demangle (NULL, name, options));
 
 #ifdef HAVE_WORKING_FORK
   if (catch_demangler_crashes)
diff --git a/gdb/cp-support.h b/gdb/cp-support.h
index 3102e7b1462..841ee4f5331 100644
--- a/gdb/cp-support.h
+++ b/gdb/cp-support.h
@@ -188,6 +188,6 @@  extern struct cmd_list_element *maint_cplus_cmd_list;
 
 /* A wrapper for bfd_demangle.  */
 
-char *gdb_demangle (const char *name, int options);
+gdb::unique_xmalloc_ptr<char> gdb_demangle (const char *name, int options);
 
 #endif /* CP_SUPPORT_H */
diff --git a/gdb/d-lang.c b/gdb/d-lang.c
index 6c9b730cf41..c712053a787 100644
--- a/gdb/d-lang.c
+++ b/gdb/d-lang.c
@@ -51,7 +51,7 @@  d_main_name (void)
 
 /* Implements the la_demangle language_defn routine for language D.  */
 
-char *
+gdb::unique_xmalloc_ptr<char>
 d_demangle (const char *symbol, int options)
 {
   return gdb_demangle (symbol, options | DMGL_DLANG);
@@ -126,8 +126,9 @@  class d_language : public language_defn
   }
 
   /* See language.h.  */
-  bool sniff_from_mangled_name (const char *mangled,
-				char **demangled) const override
+  bool sniff_from_mangled_name
+       (const char *mangled,
+	gdb::unique_xmalloc_ptr<char> *demangled) const override
   {
     *demangled = d_demangle (mangled, 0);
     return *demangled != NULL;
@@ -135,7 +136,8 @@  class d_language : public language_defn
 
   /* See language.h.  */
 
-  char *demangle_symbol (const char *mangled, int options) const override
+  gdb::unique_xmalloc_ptr<char> demangle_symbol (const char *mangled,
+						 int options) const override
   {
     return d_demangle (mangled, options);
   }
diff --git a/gdb/d-lang.h b/gdb/d-lang.h
index 96b002c717d..3a4c23febe2 100644
--- a/gdb/d-lang.h
+++ b/gdb/d-lang.h
@@ -62,7 +62,8 @@  extern int d_parse (struct parser_state *);
 
 extern const char *d_main_name (void);
 
-extern char *d_demangle (const char *mangled, int options);
+extern gdb::unique_xmalloc_ptr<char> d_demangle (const char *mangled,
+						 int options);
 
 extern const struct builtin_d_type *builtin_d_type (struct gdbarch *);
 
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 214810da183..35ca90ed361 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -10174,9 +10174,8 @@  dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu)
 	     to look up their definition from their declaration so
 	     the only disadvantage remains the minimal symbol variant
 	     `long name(params)' does not have the proper inferior type.  */
-	  demangled.reset (gdb_demangle (mangled,
-					 (DMGL_PARAMS | DMGL_ANSI
-					  | DMGL_RET_DROP)));
+	  demangled = gdb_demangle (mangled, (DMGL_PARAMS | DMGL_ANSI
+					      | DMGL_RET_DROP));
 	}
       if (demangled)
 	canon = demangled.get ();
diff --git a/gdb/f-lang.h b/gdb/f-lang.h
index 1ccdd3978ea..154edfdc29f 100644
--- a/gdb/f-lang.h
+++ b/gdb/f-lang.h
@@ -67,7 +67,8 @@  class f_language : public language_defn
 
   /* See language.h.  */
 
-  char *demangle_symbol (const char *mangled, int options) const override
+  gdb::unique_xmalloc_ptr<char> demangle_symbol (const char *mangled,
+						 int options) const override
   {
       /* We could support demangling here to provide module namespaces
 	 also for inferiors with only minimal symbol table (ELF symbols).
diff --git a/gdb/gdb-demangle.c b/gdb/gdb-demangle.c
index 24e92009d73..5382af84008 100644
--- a/gdb/gdb-demangle.c
+++ b/gdb/gdb-demangle.c
@@ -160,7 +160,6 @@  is_cplus_marker (int c)
 static void
 demangle_command (const char *args, int from_tty)
 {
-  char *demangled;
   const char *name;
   const char *arg_start;
   int processing_args = 1;
@@ -202,12 +201,10 @@  demangle_command (const char *args, int from_tty)
   else
     lang = current_language;
 
-  demangled = language_demangle (lang, name, DMGL_ANSI | DMGL_PARAMS);
+  gdb::unique_xmalloc_ptr<char> demangled
+    = language_demangle (lang, name, DMGL_ANSI | DMGL_PARAMS);
   if (demangled != NULL)
-    {
-      printf_filtered ("%s\n", demangled);
-      xfree (demangled);
-    }
+    printf_filtered ("%s\n", demangled.get ());
   else
     error (_("Can't demangle \"%s\""), name);
 }
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index 97f016fccd1..d58cfa02afb 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -3077,8 +3077,8 @@  check_stub_method (struct type *type, int method_id, int signature_id)
   struct gdbarch *gdbarch = type->arch ();
   struct fn_field *f;
   char *mangled_name = gdb_mangle_name (type, method_id, signature_id);
-  char *demangled_name = gdb_demangle (mangled_name,
-				       DMGL_PARAMS | DMGL_ANSI);
+  gdb::unique_xmalloc_ptr<char> demangled_name
+    = gdb_demangle (mangled_name, DMGL_PARAMS | DMGL_ANSI);
   char *argtypetext, *p;
   int depth = 0, argcount = 1;
   struct field *argtypes;
@@ -3086,7 +3086,7 @@  check_stub_method (struct type *type, int method_id, int signature_id)
 
   /* Make sure we got back a function string that we can use.  */
   if (demangled_name)
-    p = strchr (demangled_name, '(');
+    p = strchr (demangled_name.get (), '(');
   else
     p = NULL;
 
@@ -3177,8 +3177,6 @@  check_stub_method (struct type *type, int method_id, int signature_id)
 			argtypes, argcount, p[-2] == '.');
   mtype->set_is_stub (false);
   TYPE_FN_FIELD_STUB (f, signature_id) = 0;
-
-  xfree (demangled_name);
 }
 
 /* This is the external interface to check_stub_method, above.  This
diff --git a/gdb/gnu-v2-abi.c b/gdb/gnu-v2-abi.c
index c0200b273cd..cdcd3d5dd78 100644
--- a/gdb/gnu-v2-abi.c
+++ b/gdb/gnu-v2-abi.c
@@ -189,7 +189,7 @@  gnuv2_value_rtti_type (struct value *v, int *full, LONGEST *top, int *using_enc)
   struct type *rtti_type;
   CORE_ADDR vtbl;
   struct bound_minimal_symbol minsym;
-  char *demangled_name, *p;
+  char *p;
   const char *linkage_name;
   struct type *btype;
   struct type *known_type_vptr_basetype;
@@ -248,14 +248,15 @@  gnuv2_value_rtti_type (struct value *v, int *full, LONGEST *top, int *using_enc)
     return NULL;
 
   /* If we just skip the prefix, we get screwed by namespaces.  */
-  demangled_name=gdb_demangle(linkage_name,DMGL_PARAMS|DMGL_ANSI);
-  p = strchr (demangled_name, ' ');
+  gdb::unique_xmalloc_ptr<char> demangled_name
+    = gdb_demangle(linkage_name,DMGL_PARAMS|DMGL_ANSI);
+  p = strchr (demangled_name.get (), ' ');
   if (p)
     *p = '\0';
 
   /* Lookup the type for the name.  */
   /* FIXME: chastain/2003-11-26: block=NULL is bogus.  See pr gdb/1465.  */
-  rtti_type = cp_lookup_rtti_type (demangled_name, NULL);
+  rtti_type = cp_lookup_rtti_type (demangled_name.get (), NULL);
   if (rtti_type == NULL)
     return NULL;
 
diff --git a/gdb/gnu-v3-abi.c b/gdb/gnu-v3-abi.c
index c928afe6c34..748d5559797 100644
--- a/gdb/gnu-v3-abi.c
+++ b/gdb/gnu-v3-abi.c
@@ -644,17 +644,14 @@  gnuv3_print_method_ptr (const gdb_byte *contents,
 	 possible paths to the method based on the adjustment.  */
       if (physname)
 	{
-	  char *demangled_name = gdb_demangle (physname,
-					       DMGL_ANSI | DMGL_PARAMS);
+	  gdb::unique_xmalloc_ptr<char> demangled_name
+	    = gdb_demangle (physname, DMGL_ANSI | DMGL_PARAMS);
 
 	  fprintf_filtered (stream, "&virtual ");
 	  if (demangled_name == NULL)
 	    fputs_filtered (physname, stream);
 	  else
-	    {
-	      fputs_filtered (demangled_name, stream);
-	      xfree (demangled_name);
-	    }
+	    fputs_filtered (demangled_name.get (), stream);
 	  return;
 	}
     }
diff --git a/gdb/go-lang.c b/gdb/go-lang.c
index 72c5d8884d9..75cd38d51e8 100644
--- a/gdb/go-lang.c
+++ b/gdb/go-lang.c
@@ -333,12 +333,9 @@  unpack_mangled_go_symbol (const char *mangled_name,
    This demangler can't work in all situations,
    thus not too much effort is currently put into it.  */
 
-char *
+gdb::unique_xmalloc_ptr<char>
 go_language::demangle_symbol (const char *mangled_name, int options) const
 {
-  struct obstack tempbuf;
-  char *result;
-  char *name_buf;
   const char *package_name;
   const char *object_name;
   const char *method_type_package_name;
@@ -348,15 +345,16 @@  go_language::demangle_symbol (const char *mangled_name, int options) const
   if (mangled_name == NULL)
     return NULL;
 
-  name_buf = unpack_mangled_go_symbol (mangled_name,
-				       &package_name, &object_name,
-				       &method_type_package_name,
-				       &method_type_object_name,
-				       &method_type_is_pointer);
+  gdb::unique_xmalloc_ptr<char> name_buf
+    (unpack_mangled_go_symbol (mangled_name,
+			       &package_name, &object_name,
+			       &method_type_package_name,
+			       &method_type_object_name,
+			       &method_type_is_pointer));
   if (name_buf == NULL)
     return NULL;
 
-  obstack_init (&tempbuf);
+  auto_obstack tempbuf;
 
   /* Print methods as they appear in "method expressions".  */
   if (method_type_package_name != NULL)
@@ -380,10 +378,7 @@  go_language::demangle_symbol (const char *mangled_name, int options) const
     }
   obstack_grow_str0 (&tempbuf, "");
 
-  result = xstrdup ((const char *) obstack_finish (&tempbuf));
-  obstack_free (&tempbuf, NULL);
-  xfree (name_buf);
-  return result;
+  return make_unique_xstrdup ((const char *) obstack_finish (&tempbuf));
 }
 
 /* Given a Go symbol, return its package or NULL if unknown.
diff --git a/gdb/go-lang.h b/gdb/go-lang.h
index 3495d98d15d..3a726e7c3fb 100644
--- a/gdb/go-lang.h
+++ b/gdb/go-lang.h
@@ -94,8 +94,9 @@  class go_language : public language_defn
 
   /* See language.h.  */
 
-  bool sniff_from_mangled_name (const char *mangled,
-				char **demangled) const override
+  bool sniff_from_mangled_name
+       (const char *mangled, gdb::unique_xmalloc_ptr<char> *demangled)
+       const override
   {
     *demangled = demangle_symbol (mangled, 0);
     return *demangled != NULL;
@@ -103,7 +104,8 @@  class go_language : public language_defn
 
   /* See language.h.  */
 
-  char *demangle_symbol (const char *mangled, int options) const override;
+  gdb::unique_xmalloc_ptr<char> demangle_symbol (const char *mangled,
+						 int options) const override;
 
   /* See language.h.  */
 
diff --git a/gdb/language.c b/gdb/language.c
index cb28e638fc4..81bc2a5a8c6 100644
--- a/gdb/language.c
+++ b/gdb/language.c
@@ -551,7 +551,7 @@  skip_language_trampoline (struct frame_info *frame, CORE_ADDR pc)
    more flexible demangler for the languages that need it.
    FIXME: Sometimes the demangler is invoked when we don't know the
    language, so we can't use this everywhere.  */
-char *
+gdb::unique_xmalloc_ptr<char>
 language_demangle (const struct language_defn *current_language, 
 				const char *mangled, int options)
 {
@@ -771,7 +771,8 @@  class auto_or_unknown_language : public language_defn
 
   /* See language.h.  */
 
-  char *demangle_symbol (const char *mangled, int options) const override
+  gdb::unique_xmalloc_ptr<char> demangle_symbol (const char *mangled,
+						 int options) const override
   {
     /* The auto language just uses the C++ demangler.  */
     return gdb_demangle (mangled, options);
diff --git a/gdb/language.h b/gdb/language.h
index 69101bd4074..1ba0b9377e2 100644
--- a/gdb/language.h
+++ b/gdb/language.h
@@ -430,15 +430,16 @@  struct language_defn
 
      The resulting string should be of the form that will be
      installed into a symbol.  */
-  virtual bool sniff_from_mangled_name (const char *mangled,
-					char **demangled) const
+  virtual bool sniff_from_mangled_name
+       (const char *mangled, gdb::unique_xmalloc_ptr<char> *demangled) const
   {
     *demangled = nullptr;
     return false;
   }
 
   /* Return demangled language symbol version of MANGLED, or NULL.  */
-  virtual char *demangle_symbol (const char *mangled, int options) const
+  virtual gdb::unique_xmalloc_ptr<char> demangle_symbol (const char *mangled,
+							 int options) const
   {
     return nullptr;
   }
@@ -791,8 +792,9 @@  extern const char *language_str (enum language);
 extern CORE_ADDR skip_language_trampoline (struct frame_info *, CORE_ADDR pc);
 
 /* Return demangled language symbol, or NULL.  */
-extern char *language_demangle (const struct language_defn *current_language, 
-				const char *mangled, int options);
+extern gdb::unique_xmalloc_ptr<char> language_demangle
+     (const struct language_defn *current_language,
+      const char *mangled, int options);
 
 /* Return information about whether TYPE should be passed
    (and returned) by reference at the language level.  */
diff --git a/gdb/minsyms.c b/gdb/minsyms.c
index 33560e3c41c..5f4cf54c663 100644
--- a/gdb/minsyms.c
+++ b/gdb/minsyms.c
@@ -1473,10 +1473,11 @@  minimal_symbol_reader::install ()
 	       if (!msym->name_set)
 		 {
 		   /* This will be freed later, by compute_and_set_names.  */
-		   char *demangled_name
+		   gdb::unique_xmalloc_ptr<char> demangled_name
 		     = symbol_find_demangled_name (msym, msym->linkage_name ());
 		   msym->set_demangled_name
-		     (demangled_name, &m_objfile->per_bfd->storage_obstack);
+		     (demangled_name.release (),
+		      &m_objfile->per_bfd->storage_obstack);
 		   msym->name_set = 1;
 		 }
 	       /* This mangled_name_hash computation has to be outside of
diff --git a/gdb/objc-lang.c b/gdb/objc-lang.c
index 077ac772f79..bc3a7417982 100644
--- a/gdb/objc-lang.c
+++ b/gdb/objc-lang.c
@@ -251,8 +251,9 @@  class objc_language : public language_defn
   }
 
   /* See language.h.  */
-  bool sniff_from_mangled_name (const char *mangled,
-				char **demangled) const override
+  bool sniff_from_mangled_name
+       (const char *mangled, gdb::unique_xmalloc_ptr<char> *demangled)
+       const override
   {
     *demangled = demangle_symbol (mangled, 0);
     return *demangled != NULL;
@@ -260,7 +261,8 @@  class objc_language : public language_defn
 
   /* See language.h.  */
 
-  char *demangle_symbol (const char *mangled, int options) const override;
+  gdb::unique_xmalloc_ptr<char> demangle_symbol (const char *mangled,
+						 int options) const override;
 
   /* See language.h.  */
 
@@ -318,7 +320,7 @@  class objc_language : public language_defn
 
 /* See declaration of objc_language::demangle_symbol above.  */
 
-char *
+gdb::unique_xmalloc_ptr<char>
 objc_language::demangle_symbol (const char *mangled, int options) const
 {
   char *demangled, *cp;
@@ -376,7 +378,7 @@  objc_language::demangle_symbol (const char *mangled, int options) const
 
       *cp++ = ']';		/* closing right brace */
       *cp++ = 0;		/* string terminator */
-      return demangled;
+      return gdb::unique_xmalloc_ptr<char> (demangled);
     }
   else
     return nullptr;	/* Not an objc mangled name.  */
diff --git a/gdb/rust-lang.h b/gdb/rust-lang.h
index ea3f974c979..6962f45d7b8 100644
--- a/gdb/rust-lang.h
+++ b/gdb/rust-lang.h
@@ -84,8 +84,9 @@  class rust_language : public language_defn
 
   /* See language.h.  */
 
-  bool sniff_from_mangled_name (const char *mangled,
-				char **demangled) const override
+  bool sniff_from_mangled_name
+       (const char *mangled, gdb::unique_xmalloc_ptr<char> *demangled)
+       const override
   {
     *demangled = gdb_demangle (mangled, DMGL_PARAMS | DMGL_ANSI);
     return *demangled != NULL;
@@ -93,7 +94,8 @@  class rust_language : public language_defn
 
   /* See language.h.  */
 
-  char *demangle_symbol (const char *mangled, int options) const override
+  gdb::unique_xmalloc_ptr<char> demangle_symbol (const char *mangled,
+						 int options) const override
   {
     return gdb_demangle (mangled, options);
   }
diff --git a/gdb/symtab.c b/gdb/symtab.c
index e6851c31e27..b626277d9ea 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -815,11 +815,11 @@  create_demangled_names_hash (struct objfile_per_bfd_storage *per_bfd)
 
 /* See symtab.h  */
 
-char *
+gdb::unique_xmalloc_ptr<char>
 symbol_find_demangled_name (struct general_symbol_info *gsymbol,
 			    const char *mangled)
 {
-  char *demangled = NULL;
+  gdb::unique_xmalloc_ptr<char> demangled;
   int i;
 
   if (gsymbol->language () == language_unknown)
@@ -925,8 +925,8 @@  general_symbol_info::compute_and_set_names (gdb::string_view linkage_name,
 	linkage_name_copy = linkage_name;
 
       if (demangled_name.get () == nullptr)
-	 demangled_name.reset
-	   (symbol_find_demangled_name (this, linkage_name_copy.data ()));
+	 demangled_name
+	   = symbol_find_demangled_name (this, linkage_name_copy.data ());
 
       /* Suppose we have demangled_name==NULL, copy_name==0, and
 	 linkage_name_copy==linkage_name.  In this case, we already have the
@@ -1852,9 +1852,10 @@  demangle_for_lookup (const char *name, enum language lang,
      lookup, so we can always binary search.  */
   if (lang == language_cplus)
     {
-      char *demangled_name = gdb_demangle (name, DMGL_ANSI | DMGL_PARAMS);
+      gdb::unique_xmalloc_ptr<char> demangled_name
+	= gdb_demangle (name, DMGL_ANSI | DMGL_PARAMS);
       if (demangled_name != NULL)
-	return storage.set_malloc_ptr (demangled_name);
+	return storage.set_malloc_ptr (std::move (demangled_name));
 
       /* If we were given a non-mangled name, canonicalize it
 	 according to the language (so far only for C++).  */
@@ -1864,16 +1865,16 @@  demangle_for_lookup (const char *name, enum language lang,
     }
   else if (lang == language_d)
     {
-      char *demangled_name = d_demangle (name, 0);
+      gdb::unique_xmalloc_ptr<char> demangled_name = d_demangle (name, 0);
       if (demangled_name != NULL)
-	return storage.set_malloc_ptr (demangled_name);
+	return storage.set_malloc_ptr (std::move (demangled_name));
     }
   else if (lang == language_go)
     {
-      char *demangled_name
+      gdb::unique_xmalloc_ptr<char> demangled_name
 	= language_def (language_go)->demangle_symbol (name, 0);
       if (demangled_name != NULL)
-	return storage.set_malloc_ptr (demangled_name);
+	return storage.set_malloc_ptr (std::move (demangled_name));
     }
 
   return name;
diff --git a/gdb/symtab.h b/gdb/symtab.h
index 6a6cf8201bc..61f20b25a7b 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -592,8 +592,8 @@  extern CORE_ADDR get_symbol_address (const struct symbol *sym);
    then set the language appropriately.  The returned name is allocated
    by the demangler and should be xfree'd.  */
 
-extern char *symbol_find_demangled_name (struct general_symbol_info *gsymbol,
-					 const char *mangled);
+extern gdb::unique_xmalloc_ptr<char> symbol_find_demangled_name
+     (struct general_symbol_info *gsymbol, const char *mangled);
 
 /* Return true if NAME matches the "search" name of SYMBOL, according
    to the symbol's language.  */
diff --git a/gdb/utils.c b/gdb/utils.c
index f6f90d7365b..5486c337a3c 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -2345,8 +2345,6 @@  void
 fprintf_symbol_filtered (struct ui_file *stream, const char *name,
 			 enum language lang, int arg_mode)
 {
-  char *demangled;
-
   if (name != NULL)
     {
       /* If user wants to see raw output, no problem.  */
@@ -2356,12 +2354,9 @@  fprintf_symbol_filtered (struct ui_file *stream, const char *name,
 	}
       else
 	{
-	  demangled = language_demangle (language_def (lang), name, arg_mode);
-	  fputs_filtered (demangled ? demangled : name, stream);
-	  if (demangled != NULL)
-	    {
-	      xfree (demangled);
-	    }
+	  gdb::unique_xmalloc_ptr<char> demangled
+	    = language_demangle (language_def (lang), name, arg_mode);
+	  fputs_filtered (demangled ? demangled.get () : name, stream);
 	}
     }
 }