diff --git a/gdb/ChangeLog b/gdb/ChangeLog index bdb1db961ac..d6204a297eb 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,9 @@ +2020-05-15 Philippe Waroquiers + + * unittests/command-def-selftests.c (traverse_command_structure): + Verify all commands of a list have the same prefix command and + that only the top cmdlist commands have a null prefix. + 2020-05-15 Philippe Waroquiers * cli/cli-decode.c (lookup_cmd_for_prefix): Return the aliased command diff --git a/gdb/unittests/command-def-selftests.c b/gdb/unittests/command-def-selftests.c index db70743b3f4..2146f8028d8 100644 --- a/gdb/unittests/command-def-selftests.c +++ b/gdb/unittests/command-def-selftests.c @@ -106,20 +106,26 @@ help_doc_invariants_tests () namespace command_structure_tests { +/* Nr of commands in which a duplicated list is found. */ unsigned int nr_duplicates = 0; +/* Nr of commands in a list having no valid prefix cmd. */ +unsigned int nr_invalid_prefixcmd = 0; /* A map associating a list with the prefix leading to it. */ std::map lists; /* Store each command list in lists, associated with the prefix to reach it. A - list must only be found once. */ + list must only be found once. + + Verifies that all elements of the list have the same non-null prefix + command. */ static void traverse_command_structure (struct cmd_list_element **list, const char *prefix) { - struct cmd_list_element *c; + struct cmd_list_element *c, *prefixcmd; auto dupl = lists.find (list); if (dupl != lists.end ()) @@ -137,6 +143,13 @@ traverse_command_structure (struct cmd_list_element **list, lists.insert ({list, prefix}); + /* All commands of *list must have a prefix command equal to PREFIXCMD, + the prefix command of the first command. */ + if (*list == nullptr) + prefixcmd = nullptr; /* A prefix command with an empty subcommand list. */ + else + prefixcmd = (*list)->prefix; + /* Walk through the commands. */ for (c = *list; c; c = c->next) { @@ -148,6 +161,23 @@ traverse_command_structure (struct cmd_list_element **list, passing the right prefix in. */ traverse_command_structure (c->prefixlist, c->prefixname); } + if (prefixcmd != c->prefix + || (prefixcmd == nullptr && *list != cmdlist)) + { + if (c->prefix == nullptr) + fprintf_filtered (gdb_stdout, + "list %p reachable via prefix '%s'." + " command '%s' has null prefixcmd\n", + list, + prefix, c->name); + else + fprintf_filtered (gdb_stdout, + "list %p reachable via prefix '%s'." + " command '%s' has a different prefixcmd\n", + list, + prefix, c->name); + nr_invalid_prefixcmd++; + } } } @@ -157,12 +187,15 @@ static void command_structure_invariants_tests () { nr_duplicates = 0; + nr_invalid_prefixcmd = 0; + traverse_command_structure (&cmdlist, ""); /* Release memory, be ready to be re-run. */ lists.clear (); SELF_CHECK (nr_duplicates == 0); + SELF_CHECK (nr_invalid_prefixcmd == 0); } }