From 9ef6d4a1b48ea1f5693aa270b8b768146a31b9e9 Mon Sep 17 00:00:00 2001 From: Andrew Burgess Date: Thu, 10 Dec 2020 13:19:40 +0000 Subject: [PATCH] gdb: give deprecated command warning for aliases with a prefix 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 | 15 ++++++++ gdb/cli/cli-decode.c | 54 ++++++++++++++++++++------- gdb/command.h | 2 +- gdb/testsuite/ChangeLog | 6 +++ gdb/testsuite/gdb.base/commands.exp | 19 ++++++++++ gdb/testsuite/gdb.base/completion.exp | 7 ++++ gdb/top.c | 2 +- 7 files changed, 90 insertions(+), 15 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 0c6ced3c6c9..f01ba9951a0 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,18 @@ +2020-12-11 Andrew Burgess + + 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 * cli/cli-decode.c (lookup_cmd_1): Move header comment into diff --git a/gdb/cli/cli-decode.c b/gdb/cli/cli-decode.c index c62b8498060..dc83f5560e6 100644 --- a/gdb/cli/cli-decode.c +++ b/gdb/cli/cli-decode.c @@ -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 diff --git a/gdb/command.h b/gdb/command.h index a6ddaa24905..9e61d19d0bd 100644 --- a/gdb/command.h +++ b/gdb/command.h @@ -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, diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index f2262f6b3c7..0eb3ce680e5 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2020-12-11 Andrew Burgess + + PR cli/15104 + * gdb.base/commands.exp: Add additional tests. + * gdb.base/completion.exp: Add additional tests. + 2020-12-11 Andrew Burgess * gdb.base/completion.exp: Add additional tests. diff --git a/gdb/testsuite/gdb.base/commands.exp b/gdb/testsuite/gdb.base/commands.exp index 7ff57f774af..19f712c46f3 100644 --- a/gdb/testsuite/gdb.base/commands.exp +++ b/gdb/testsuite/gdb.base/commands.exp @@ -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 {} { diff --git a/gdb/testsuite/gdb.base/completion.exp b/gdb/testsuite/gdb.base/completion.exp index 14d56a5cc19..8000d520491 100644 --- a/gdb/testsuite/gdb.base/completion.exp +++ b/gdb/testsuite/gdb.base/completion.exp @@ -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" diff --git a/gdb/top.c b/gdb/top.c index e82828e48d7..b515bbfbd19 100644 --- 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) -- 2.30.2