gdb: give deprecated command warning for aliases with a prefix
authorAndrew Burgess <andrew.burgess@embecosm.com>
Thu, 10 Dec 2020 13:19:40 +0000 (13:19 +0000)
committerAndrew Burgess <andrew.burgess@embecosm.com>
Fri, 11 Dec 2020 22:10:50 +0000 (22:10 +0000)
I noticed that deprecated aliases that have a prefix don't give a
deprecated command warning.  For example looking in mi/mi-main.c we
see this:

  c = add_alias_cmd ("target-async", "mi-async", class_run, 0, &setlist);
  deprecate_cmd (c, "set mi-async");
  c = add_alias_cmd ("target-async", "mi-async", class_run, 0, &showlist);
  deprecate_cmd (c, "show mi-async");

So both 'set target-async' and 'show target-async' are deprecated and
should be giving a warning, however, in use we see no warning given.

This is a consequence of how the code that should give this
warning (deprecated_cmd_warning) performs a second command lookup in
order to distinguish between aliases and real commands, and that the
code that calls this (lookup_cmd_1) strips off prefix commands as it
calls itself recursively.

As a result when we are considering an alias like 'set target-async'
we first enter lookup_cmd_1 with text = "set target-async", we spot
the 'set' command prefix and then recursively call lookup_cmd_1 with
text = "target-async".

We spot that 'target-async' is a known alias but that it is
deprecated, and so call deprecated_cmd_warning passing in the value of
text, which remember is now "target-async".

In deprecated_cmd_warning we again perform a command lookup starting
from the top-level cmdlist, but now we're trying to find just
"target-async", this fails (as this command requires the 'set' prefix,
and so no warning is given.

I resolved this issue by passing a command list to the function
deprecated_cmd_warning, this is the list in which the command can be
found.

A new test is added to cover this case.

However, there is an additional problem which will be addressed in a
subsequent patch.

Consider this GDB session:

  (gdb) define set xxx_yyy
  Type commands for definition of "set xxx_yyy".
  End with a line saying just "end".
  >echo in set xxx_yyy command\n
  >end
  (gdb) alias set qqq_aaa=set xxx_yyy
  (gdb) maintenance deprecate set qqq_aaa
  (gdb) set qqq_aaa
  Warning: 'qqq_aaa', an alias for the command 'xxx_yyy' is deprecated.
  No alternative known.

  in set xxx_yyy command
  (gdb)

Notice the warning mentions 'qqq_aaa' and 'xxx_yyy', I consider this
to be wrong.  I think the proper warning should read:

  (gdb) set qqq_aaa
  Warning: 'set qqq_aaa', an alias for the command 'set xxx_yyy' is deprecated.
  No alternative known.

With the 'set' prefixes added.  A later patch will resolve this
issue.

gdb/ChangeLog:

PR cli/15104
* cli/cli-decode.c (lookup_cmd_1): Pass command list to
deprecated_cmd_warning.
(deprecated_cmd_warning): Take extra parameter, call
lookup_cmd_composition_1 and pass new parameter through.
(lookup_cmd_composition_1): New function, takes implementation of
lookup_cmd_composition but with extra parameter.
(lookup_cmd_composition): Now calls lookup_cmd_composition_1
passing in cmdlist.
* command.h (deprecated_cmd_warning): Add extra parameter to
declaration.
* top.c (execute_command): Pass cmdlist to deprecated_cmd_warning.

gdb/testsuite/ChangeLog:

PR cli/15104
* gdb.base/commands.exp: Add additional tests.
* gdb.base/completion.exp: Add additional tests.

gdb/ChangeLog
gdb/cli/cli-decode.c
gdb/command.h
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.base/commands.exp
gdb/testsuite/gdb.base/completion.exp
gdb/top.c

index 0c6ced3c6c98fd24ba9b50fe3a97480ed1b97c0a..f01ba9951a0c11a2bd23804b6e41af6c8d096ace 100644 (file)
@@ -1,3 +1,18 @@
+2020-12-11  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       PR cli/15104
+       * cli/cli-decode.c (lookup_cmd_1): Pass command list to
+       deprecated_cmd_warning.
+       (deprecated_cmd_warning): Take extra parameter, call
+       lookup_cmd_composition_1 and pass new parameter through.
+       (lookup_cmd_composition_1): New function, takes implementation of
+       lookup_cmd_composition but with extra parameter.
+       (lookup_cmd_composition): Now calls lookup_cmd_composition_1
+       passing in cmdlist.
+       * command.h (deprecated_cmd_warning): Add extra parameter to
+       declaration.
+       * top.c (execute_command): Pass cmdlist to deprecated_cmd_warning.
+
 2020-12-11  Andrew Burgess  <andrew.burgess@embecosm.com>
 
        * cli/cli-decode.c (lookup_cmd_1): Move header comment into
index c62b8498060589b8f2919abe595a126aa83f07d4..dc83f5560e6ddfb7f8d1a97acdcd762c2295a577 100644 (file)
@@ -50,6 +50,12 @@ static void help_cmd_list (struct cmd_list_element *list,
 
 static void help_all (struct ui_file *stream);
 
+static int lookup_cmd_composition_1 (const char *text,
+                                    struct cmd_list_element **alias,
+                                    struct cmd_list_element **prefix_cmd,
+                                    struct cmd_list_element **cmd,
+                                    struct cmd_list_element *cur_list);
+
 /* Look up a command whose 'prefixlist' is KEY.  Return the command if found,
    otherwise return NULL.  */
 
@@ -1678,7 +1684,7 @@ lookup_cmd_1 (const char **text, struct cmd_list_element *clist,
        flags.  */
 
       if (found->deprecated_warn_user && !lookup_for_completion_p)
-       deprecated_cmd_warning (line);
+       deprecated_cmd_warning (line, clist);
 
       /* Return the default_args of the alias, not the default_args
         of the command it is pointing to.  */
@@ -1891,13 +1897,13 @@ lookup_cmd (const char **line, struct cmd_list_element *list,
    
 */
 void
-deprecated_cmd_warning (const char *text)
+deprecated_cmd_warning (const char *text, struct cmd_list_element *list)
 {
   struct cmd_list_element *alias = NULL;
   struct cmd_list_element *prefix_cmd = NULL;
   struct cmd_list_element *cmd = NULL;
 
-  if (!lookup_cmd_composition (text, &alias, &prefix_cmd, &cmd))
+  if (!lookup_cmd_composition_1 (text, &alias, &prefix_cmd, &cmd, list))
     /* Return if text doesn't evaluate to a command.  */
     return;
 
@@ -1949,8 +1955,7 @@ deprecated_cmd_warning (const char *text)
   cmd->deprecated_warn_user = 0;
 }
 
-
-/* Look up the contents of TEXT as a command in the command list 'cmdlist'.
+/* Look up the contents of TEXT as a command in the command list CUR_LIST.
    Return 1 on success, 0 on failure.
 
    If TEXT refers to an alias, *ALIAS will point to that alias.
@@ -1964,23 +1969,22 @@ deprecated_cmd_warning (const char *text)
    exist, they are NULL when we return.
 
 */
-int
-lookup_cmd_composition (const char *text,
-                       struct cmd_list_element **alias,
-                       struct cmd_list_element **prefix_cmd,
-                       struct cmd_list_element **cmd)
+
+static int
+lookup_cmd_composition_1 (const char *text,
+                         struct cmd_list_element **alias,
+                         struct cmd_list_element **prefix_cmd,
+                         struct cmd_list_element **cmd,
+                         struct cmd_list_element *cur_list)
 {
   char *command;
   int len, nfound;
-  struct cmd_list_element *cur_list;
   struct cmd_list_element *prev_cmd;
 
   *alias = NULL;
   *prefix_cmd = NULL;
   *cmd = NULL;
 
-  cur_list = cmdlist;
-
   text = skip_spaces (text);
 
   while (1)
@@ -2038,6 +2042,30 @@ lookup_cmd_composition (const char *text,
     }
 }
 
+/* Look up the contents of TEXT as a command in the command list 'cmdlist'.
+   Return 1 on success, 0 on failure.
+
+   If TEXT refers to an alias, *ALIAS will point to that alias.
+
+   If TEXT is a subcommand (i.e. one that is preceded by a prefix
+   command) set *PREFIX_CMD.
+
+   Set *CMD to point to the command TEXT indicates.
+
+   If any of *ALIAS, *PREFIX_CMD, or *CMD cannot be determined or do not
+   exist, they are NULL when we return.
+
+*/
+
+int
+lookup_cmd_composition (const char *text,
+                       struct cmd_list_element **alias,
+                       struct cmd_list_element **prefix_cmd,
+                       struct cmd_list_element **cmd)
+{
+  return lookup_cmd_composition_1 (text, alias, prefix_cmd, cmd, cmdlist);
+}
+
 /* Helper function for SYMBOL_COMPLETION_FUNCTION.  */
 
 /* Return a vector of char pointers which point to the different
index a6ddaa249059f75ae5850c276073969b5610eff5..9e61d19d0bd2da35694a7ab664dd20a83a87fbc4 100644 (file)
@@ -329,7 +329,7 @@ extern struct cmd_list_element *lookup_cmd_1
 extern struct cmd_list_element *deprecate_cmd (struct cmd_list_element *,
                                               const char * );
 
-extern void deprecated_cmd_warning (const char *);
+extern void deprecated_cmd_warning (const char *, struct cmd_list_element *);
 
 extern int lookup_cmd_composition (const char *text,
                                   struct cmd_list_element **alias,
index f2262f6b3c7d72d72c75b31f78be1d4455d07d2a..0eb3ce680e5e8abd662862bb1ebe3a441db3416a 100644 (file)
@@ -1,3 +1,9 @@
+2020-12-11  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       PR cli/15104
+       * gdb.base/commands.exp: Add additional tests.
+       * gdb.base/completion.exp: Add additional tests.
+
 2020-12-11  Andrew Burgess  <andrew.burgess@embecosm.com>
 
        * gdb.base/completion.exp: Add additional tests.
index 7ff57f774af04318db0dbc8e41c9a188b80e6116..19f712c46f31741ad2a422e3e736e60dfdf433ae 100644 (file)
@@ -689,6 +689,25 @@ proc_with_prefix deprecated_command_test {} {
     gdb_test "maintenance deprecate" \
            "\"maintenance deprecate\".*" \
            "deprecate with no arguments"
+
+    # Test that an alias with a prefix still gives a warning.
+    set file1 [standard_output_file xxx_yyy_cmd]
+    set fd [open "$file1" w]
+    puts $fd \
+"define set xxx_yyy
+echo in command xxx_yyy\\n
+end
+
+alias set qqq_aaa=set xxx_yyy
+maintenance deprecate set qqq_aaa"
+    close $fd
+    gdb_test_no_output "source $file1" \
+       "source file containing xxx_yyy command and its alias"
+    gdb_test "set qqq_aaa" \
+       "Warning: 'qqq_aaa', an alias for the command 'xxx_yyy' is deprecated\\.\r\n.*No alternative known\\..*" \
+       "deprecated alias with prefix give a warning"
+
+    file delete $file1
 }
 
 proc_with_prefix bp_deleted_in_command_test {} {
index 14d56a5cc19e6f3c778152084db550811b6b6b69..8000d52049167184bdfca2b06aad1a05b121cd3d 100644 (file)
@@ -968,3 +968,10 @@ foreach_with_prefix cmd { "watch" "awatch" "rwatch" } {
 gdb_test_no_output "alias xxx_yyy_zzz=break"
 gdb_test_no_output "maint deprecate xxx_yyy_zzz"
 test_gdb_complete_unique "xxx_yyy_" "xxx_yyy_zzz"
+
+# Check that tab completion of a deprecated alias with a prefix does
+# not display the warning about the alias being deprecated during tab
+# completion.
+gdb_test_no_output "alias set aaa_bbb_ccc=set debug"
+gdb_test_no_output "maint deprecate set aaa_bbb_ccc"
+test_gdb_complete_unique "set aaa_bbb_" "set aaa_bbb_ccc"
index e82828e48d701a47067fd79d72874604fe3bf683..b515bbfbd199805927645b0b8331166e30305ff8 100644 (file)
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -639,7 +639,7 @@ execute_command (const char *p, int from_tty)
       execute_cmd_pre_hook (c);
 
       if (c->deprecated_warn_user)
-       deprecated_cmd_warning (line);
+       deprecated_cmd_warning (line, cmdlist);
 
       /* c->user_commands would be NULL in the case of a python command.  */
       if (c->theclass == class_user && c->user_commands)