]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gdb: use std::string vector for macro definition
authorSimon Marchi <simon.marchi@efficios.com>
Wed, 24 Jul 2024 19:07:14 +0000 (15:07 -0400)
committerSimon Marchi <simon.marchi@efficios.com>
Tue, 30 Jul 2024 12:52:57 +0000 (08:52 -0400)
Use std::vector<std::string> when defining macros, to avoid the manual
memory management.

With the use of std::vector, the separate `int argc` parameter is no
longer needed, we can use the size of the vector instead.  However, for
some functions, this parameter had a dual function.  For object-like
macros, it was interpreted as a `macro_special_kind` enum.  For these
functions, remove `argc`, but add a new `special_kind` parameter.

Change-Id: Ice76a6863dfe598335e3b8d5d077513e50975cc5
Approved-By: Tom de Vries <tdevries@suse.de>
gdb/dwarf2/macro.c
gdb/macrocmd.c
gdb/macrotab.c
gdb/macrotab.h

index bc781c2cb92eb96cd468e0b079568abf4b4eabf7..b2bf95d680bedf56924eb5a38b4321330eacb703 100644 (file)
@@ -160,9 +160,7 @@ parse_macro_definition (struct macro_source_file *file, int line,
   /* It's a function-like macro.  */
   gdb_assert (*p == '(');
   std::string name (body, p - body);
-  int argc = 0;
-  int argv_size = 1;
-  char **argv = XNEWVEC (char *, argv_size);
+  std::vector<std::string> argv;
 
   p++;
 
@@ -180,16 +178,7 @@ parse_macro_definition (struct macro_source_file *file, int line,
       if (! *p || p == arg_start)
        dwarf2_macro_malformed_definition_complaint (body);
       else
-       {
-         /* Make sure argv has room for the new argument.  */
-         if (argc >= argv_size)
-           {
-             argv_size *= 2;
-             argv = XRESIZEVEC (char *, argv, argv_size);
-           }
-
-         argv[argc++] = savestring (arg_start, p - arg_start);
-       }
+       argv.emplace_back (arg_start, p);
 
       p = consume_improper_spaces (p, body);
 
@@ -208,16 +197,12 @@ parse_macro_definition (struct macro_source_file *file, int line,
 
       if (*p == ' ')
        /* Perfectly formed definition, no complaints.  */
-       macro_define_function (file, line, name.c_str (),
-                              argc, (const char **) argv,
-                              p + 1);
+       macro_define_function (file, line, name.c_str (), argv, p + 1);
       else if (*p == '\0')
        {
          /* Complain, but do define it.  */
          dwarf2_macro_malformed_definition_complaint (body);
-         macro_define_function (file, line, name.c_str (),
-                                argc, (const char **) argv,
-                                p);
+         macro_define_function (file, line, name.c_str (), argv, p);
        }
       else
        /* Just complain.  */
@@ -226,11 +211,6 @@ parse_macro_definition (struct macro_source_file *file, int line,
   else
     /* Just complain.  */
     dwarf2_macro_malformed_definition_complaint (body);
-
-  for (int i = 0; i < argc; i++)
-    xfree (argv[i]);
-
-  xfree (argv);
 }
 
 /* Skip some bytes from BYTES according to the form given in FORM.
index 6cf3a0d8bf18558259407cfebff7a317818bb10f..2da5a5bcf929fa15b2be56adc9b61623cdd68dcf 100644 (file)
@@ -271,18 +271,17 @@ skip_ws (const char **expp)
 }
 
 /* Try to find the bounds of an identifier.  If an identifier is
-   found, returns a newly allocated string; otherwise returns NULL.
+   found, return it; otherwise return an empty string.
+
    EXPP is a pointer to an input string; it is updated to point to the
    text following the identifier.  If IS_PARAMETER is true, this
    function will also allow "..." forms as used in varargs macro
    parameters.  */
 
-static gdb::unique_xmalloc_ptr<char>
+static std::string
 extract_identifier (const char **expp, int is_parameter)
 {
-  char *result;
   const char *p = *expp;
-  unsigned int len;
 
   if (is_parameter && startswith (p, "..."))
     {
@@ -291,67 +290,39 @@ extract_identifier (const char **expp, int is_parameter)
   else
     {
       if (! *p || ! macro_is_identifier_nondigit (*p))
-       return NULL;
+       return {};
+
       for (++p;
           *p && (macro_is_identifier_nondigit (*p) || macro_is_digit (*p));
           ++p)
        ;
     }
 
-  if (is_parameter && startswith (p, "..."))      
+  if (is_parameter && startswith (p, "..."))
     p += 3;
 
-  len = p - *expp;
-  result = (char *) xmalloc (len + 1);
-  memcpy (result, *expp, len);
-  result[len] = '\0';
-  *expp += len;
-  return gdb::unique_xmalloc_ptr<char> (result);
-}
+  std::string result (*expp, p);
+  *expp = p;
 
-struct temporary_macro_definition : public macro_definition
-{
-  temporary_macro_definition ()
-  {
-    table = nullptr;
-    kind = macro_object_like;
-    argc = 0;
-    argv = nullptr;
-    replacement = nullptr;
-  }
-
-  ~temporary_macro_definition ()
-  {
-    int i;
-
-    for (i = 0; i < argc; ++i)
-      xfree ((char *) argv[i]);
-    xfree ((char *) argv);
-    /* Note that the 'replacement' field is not allocated.  */
-  }
-};
+  return result;
+}
 
 static void
 macro_define_command (const char *exp, int from_tty)
 {
-  temporary_macro_definition new_macro;
-
   if (!exp)
     error (_("usage: macro define NAME[(ARGUMENT-LIST)] [REPLACEMENT-LIST]"));
 
   skip_ws (&exp);
-  gdb::unique_xmalloc_ptr<char> name = extract_identifier (&exp, 0);
-  if (name == NULL)
+
+  std::string name = extract_identifier (&exp, 0);
+  if (name.empty ())
     error (_("Invalid macro name."));
+
   if (*exp == '(')
     {
       /* Function-like macro.  */
-      int alloced = 5;
-      char **argv = XNEWVEC (char *, alloced);
-
-      new_macro.kind = macro_function_like;
-      new_macro.argc = 0;
-      new_macro.argv = (const char * const *) argv;
+      std::vector<std::string> argv;
 
       /* Skip the '(' and whitespace.  */
       ++exp;
@@ -359,23 +330,13 @@ macro_define_command (const char *exp, int from_tty)
 
       while (*exp != ')')
        {
-         int i;
-
-         if (new_macro.argc == alloced)
-           {
-             alloced *= 2;
-             argv = (char **) xrealloc (argv, alloced * sizeof (char *));
-             /* Must update new_macro as well...  */
-             new_macro.argv = (const char * const *) argv;
-           }
-         argv[new_macro.argc] = extract_identifier (&exp, 1).release ();
-         if (! argv[new_macro.argc])
+         argv.emplace_back (extract_identifier (&exp, 1));
+         if (argv.back ().empty ())
            error (_("Macro is missing an argument."));
-         ++new_macro.argc;
 
-         for (i = new_macro.argc - 2; i >= 0; --i)
+         for (const auto &other_arg : argv)
            {
-             if (! strcmp (argv[i], argv[new_macro.argc - 1]))
+             if (&other_arg != &argv.back () && other_arg == argv.back ())
                error (_("Two macro arguments with identical names."));
            }
 
@@ -388,18 +349,18 @@ macro_define_command (const char *exp, int from_tty)
          else if (*exp != ')')
            error (_("',' or ')' expected at end of macro arguments."));
        }
+
       /* Skip the closing paren.  */
       ++exp;
       skip_ws (&exp);
 
-      macro_define_function (macro_main (macro_user_macros), -1, name.get (),
-                            new_macro.argc, (const char **) new_macro.argv,
-                            exp);
+      macro_define_function (macro_main (macro_user_macros), -1, name.c_str (),
+                            argv, exp);
     }
   else
     {
       skip_ws (&exp);
-      macro_define_object (macro_main (macro_user_macros), -1, name.get (),
+      macro_define_object (macro_main (macro_user_macros), -1, name.c_str (),
                           exp);
     }
 }
@@ -412,10 +373,12 @@ macro_undef_command (const char *exp, int from_tty)
     error (_("usage: macro undef NAME"));
 
   skip_ws (&exp);
-  gdb::unique_xmalloc_ptr<char> name = extract_identifier (&exp, 0);
-  if (name == nullptr)
+
+  std::string name = extract_identifier (&exp, 0);
+  if (name.empty ())
     error (_("Invalid macro name."));
-  macro_undef (macro_main (macro_user_macros), -1, name.get ());
+
+  macro_undef (macro_main (macro_user_macros), -1, name.c_str ());
 }
 
 
index 3a7f792c097a0394073745065ddacf57ae327226..81fe16576730313d0e5a3bc0554f6c702eeff816 100644 (file)
@@ -545,10 +545,10 @@ macro_lookup_inclusion (struct macro_source_file *source, const char *name)
 
 /* Construct a definition for a macro in table T.  Cache all strings,
    and the macro_definition structure itself, in T's bcache.  */
-static struct macro_definition *
-new_macro_definition (struct macro_table *t,
-                     enum macro_kind kind,
-                     int argc, const char **argv,
+static macro_definition *
+new_macro_definition (macro_table *t, macro_kind kind,
+                     macro_special_kind special_kind,
+                     const std::vector<std::string> &argv,
                      const char *replacement)
 {
   struct macro_definition *d
@@ -558,22 +558,24 @@ new_macro_definition (struct macro_table *t,
   d->table = t;
   d->kind = kind;
   d->replacement = macro_bcache_str (t, replacement);
-  d->argc = argc;
 
   if (kind == macro_function_like)
     {
-      int i;
-      const char **cached_argv;
-      int cached_argv_size = argc * sizeof (*cached_argv);
+      d->argc = argv.size ();
 
       /* Bcache all the arguments.  */
-      cached_argv = (const char **) alloca (cached_argv_size);
-      for (i = 0; i < argc; i++)
-       cached_argv[i] = macro_bcache_str (t, argv[i]);
+      int i = 0;
+      int cached_argv_size = argv.size () * sizeof (const char *);
+      const char **cached_argv = (const char **) alloca (cached_argv_size);
+
+      for (const auto &arg : argv)
+       cached_argv[i++] = macro_bcache_str (t, arg.c_str ());
 
       /* Now bcache the array of argument pointers itself.  */
       d->argv = macro_bcache (t, cached_argv, cached_argv_size);
     }
+  else
+    d->argc = special_kind;
 
   /* We don't bcache the entire definition structure because it's got
      a pointer to the macro table in it; since each compilation unit
@@ -677,13 +679,12 @@ find_definition (const char *name,
 
 /* If NAME already has a definition in scope at LINE in SOURCE, return
    the key.  If the old definition is different from the definition
-   given by KIND, ARGC, ARGV, and REPLACEMENT, complain, too.
-   Otherwise, return zero.  (ARGC and ARGV are meaningless unless KIND
+   given by KIND, ARGV, and REPLACEMENT, complain, too.
+   Otherwise, return nullptr.  (ARGV is meaningless unless KIND
    is `macro_function_like'.)  */
-static struct macro_key *
-check_for_redefinition (struct macro_source_file *source, int line,
-                       const char *name, enum macro_kind kind,
-                       int argc, const char **argv,
+static macro_key *
+check_for_redefinition (macro_source_file *source, int line, const char *name,
+                       macro_kind kind, const std::vector<std::string> &argv,
                        const char *replacement)
 {
   splay_tree_node n = find_definition (name, source, line);
@@ -708,14 +709,14 @@ check_for_redefinition (struct macro_source_file *source, int line,
        same = 0;
       else if (kind == macro_function_like)
        {
-         if (argc != found_def->argc)
+         if (argv.size () != found_def->argc)
            same = 0;
          else
            {
-             int i;
+             int i = 0;
 
-             for (i = 0; i < argc; i++)
-               if (strcmp (argv[i], found_def->argv[i]))
+             for (const auto &arg : argv)
+               if (arg != found_def->argv[i++])
                  same = 0;
            }
        }
@@ -739,15 +740,18 @@ check_for_redefinition (struct macro_source_file *source, int line,
 }
 
 /* A helper function to define a new object-like or function-like macro
-   according to KIND.  When KIND is macro_object_like,
-   the macro_special_kind must be provided as ARGC, and ARGV must be NULL.
-   When KIND is macro_function_like, ARGC and ARGV are giving the function
-   arguments.  */
+   according to KIND.
+
+   When KIND is macro_object_like, the possible special kind is given by
+   SPECIAL_KIND, and ARGV is meaningless.
+
+   When KIND is macro_function_like, ARGV gives the macro argument names, and
+   SPECIAL_KIND is meaningless.  */
 
 static void
-macro_define_internal (struct macro_source_file *source, int line,
-                      const char *name, enum macro_kind kind,
-                      int argc, const char **argv,
+macro_define_internal (macro_source_file *source, int line, const char *name,
+                      macro_kind kind, macro_special_kind special_kind,
+                      const std::vector<std::string> &argv,
                       const char *replacement)
 {
   struct macro_table *t = source->table;
@@ -755,10 +759,7 @@ macro_define_internal (struct macro_source_file *source, int line,
   struct macro_definition *d;
 
   if (! t->redef_ok)
-    k = check_for_redefinition (source, line,
-                               name, kind,
-                               argc, argv,
-                               replacement);
+    k = check_for_redefinition (source, line, name, kind, argv, replacement);
 
   /* If we're redefining a symbol, and the existing key would be
      identical to our new key, then the splay_tree_insert function
@@ -774,7 +775,7 @@ macro_define_internal (struct macro_source_file *source, int line,
     return;
 
   k = new_macro_key (t, name, source, line);
-  d = new_macro_definition (t, kind, argc, argv, replacement);
+  d = new_macro_definition (t, kind, special_kind, argv, replacement);
   splay_tree_insert (t->definitions, (splay_tree_key) k, (splay_tree_value) d);
 }
 
@@ -785,10 +786,8 @@ macro_define_object_internal (struct macro_source_file *source, int line,
                              const char *name, const char *replacement,
                              enum macro_special_kind special_kind)
 {
-  macro_define_internal (source, line,
-                        name, macro_object_like,
-                        special_kind, NULL,
-                        replacement);
+  macro_define_internal (source, line, name, macro_object_like, special_kind,
+                        {}, replacement);
 }
 
 void
@@ -811,14 +810,12 @@ macro_define_special (struct macro_table *table)
 }
 
 void
-macro_define_function (struct macro_source_file *source, int line,
-                      const char *name, int argc, const char **argv,
+macro_define_function (macro_source_file *source, int line, const char *name,
+                      const std::vector<std::string> &argv,
                       const char *replacement)
 {
-  macro_define_internal (source, line,
-                        name, macro_function_like,
-                        argc, argv,
-                        replacement);
+  macro_define_internal (source, line, name, macro_function_like,
+                        macro_ordinary, argv, replacement);
 }
 
 void
index 789beed0476cf02820613e5f28470f0870a3a39c..d5015954f2035c66e852f0230bd3652739ae4554 100644 (file)
@@ -242,26 +242,23 @@ struct macro_source_file *macro_lookup_inclusion
    Record in SOURCE's macro table that, at line number LINE in SOURCE,
    we #defined a preprocessor symbol named NAME, whose replacement
    string is REPLACEMENT.  This function makes copies of NAME and
-   REPLACEMENT; the caller is responsible for freeing them.  */
+   REPLACEMENT.  */
 void macro_define_object (struct macro_source_file *source, int line,
                          const char *name, const char *replacement);
 
 
-/* Record an function-like #definition (i.e., one with a parameter list).
+/* Record a function-like #definition (i.e., one with a parameter list).
 
    Record in SOURCE's macro table that, at line number LINE in SOURCE,
-   we #defined a preprocessor symbol named NAME, with ARGC arguments
-   whose names are given in ARGV, whose replacement string is REPLACEMENT.  If
-   the macro takes a variable number of arguments, then ARGC should be
-   one greater than the number of named arguments, and ARGV[ARGC-1]
-   should be the string "...".  This function makes its own copies of
-   NAME, ARGV, and REPLACEMENT; the caller is responsible for freeing
-   them.  */
-void macro_define_function (struct macro_source_file *source, int line,
-                           const char *name, int argc, const char **argv,
+   we #defined a preprocessor symbol named NAME, with argument names given by
+   ARGV, whose replacement string is REPLACEMENT.  If the macro takes a variable
+   number of arguments, then the last element of ARGV should be the string
+   "...".  This function makes copies of NAME, ARGV, and REPLACEMENT.  */
+void macro_define_function (macro_source_file *source, int line,
+                           const char *name,
+                           const std::vector<std::string> &argv,
                            const char *replacement);
 
-
 /* Record an #undefinition.
    Record in SOURCE's macro table that, at line number LINE in SOURCE,
    we removed the definition for the preprocessor symbol named NAME.  */