"otherwise check the auto-load sub-commands."));
 
   for (list = *auto_load_set_cmdlist_get (); list != NULL; list = list->next)
-    if (list->var_type == var_boolean)
+    if (list->var->type () == var_boolean)
       {
        gdb_assert (list->type == set_cmd);
        do_set_command (args, from_tty, list);
 
                                cmd_list_element *c)
 {
   gdb_assert (c->type == set_cmd);
-  gdb_assert (c->var_type == var_boolean);
-  gdb_assert (c->var != nullptr);
+  gdb_assert (c->var.has_value ());
+  gdb_assert (c->var->type () == var_boolean);
 
 #ifndef GDB_PRINT_INTERNAL_BACKTRACE
-  bool *var_ptr = (bool *) c->var;
-
-  if (*var_ptr)
+  if (c->var->get<bool> ())
     {
-      *var_ptr = false;
+      c->var->set<bool> (false);
       error (_("support for this feature is not compiled into GDB"));
     }
 #endif
 
                                          /*ignore_help_classes=*/ 1);
   gdb_assert (set_cmd != nullptr);
 
-  if (set_cmd->var == nullptr)
+  if (!set_cmd->var.has_value ())
     error (_("Cannot use this setting with the \"with\" command"));
 
   std::string temp_value
   if (nested_cmd == nullptr)
     nested_cmd = skip_spaces (delim + 2);
 
-  std::string org_value = get_setshow_command_value_string (set_cmd);
+  gdb_assert (set_cmd->var.has_value ());
+  std::string org_value = get_setshow_command_value_string (*set_cmd->var);
 
   /* Tweak the setting to the new temporary value.  */
   do_set_command (temp_value.c_str (), from_tty, set_cmd);
 /* Builds a value from the show CMD.  */
 
 static struct value *
-value_from_setting (const cmd_list_element *cmd, struct gdbarch *gdbarch)
+value_from_setting (const setting &var, struct gdbarch *gdbarch)
 {
-  switch (cmd->var_type)
+  switch (var.type ())
     {
     case var_integer:
-      if (*(int *) cmd->var == INT_MAX)
+      if (var.get<int> () == INT_MAX)
        return value_from_longest (builtin_type (gdbarch)->builtin_int,
                                   0);
       else
        return value_from_longest (builtin_type (gdbarch)->builtin_int,
-                                  *(int *) cmd->var);
+                                  var.get<int> ());
     case var_zinteger:
       return value_from_longest (builtin_type (gdbarch)->builtin_int,
-                                *(int *) cmd->var);
+                                var.get<int> ());
     case var_boolean:
       return value_from_longest (builtin_type (gdbarch)->builtin_int,
-                                *(bool *) cmd->var ? 1 : 0);
+                                var.get<bool> () ? 1 : 0);
     case var_zuinteger_unlimited:
       return value_from_longest (builtin_type (gdbarch)->builtin_int,
-                                *(int *) cmd->var);
+                                var.get<int> ());
     case var_auto_boolean:
       {
        int val;
 
-       switch (*(enum auto_boolean*) cmd->var)
+       switch (var.get<enum auto_boolean> ())
          {
          case AUTO_BOOLEAN_TRUE:
            val = 1;
                                   val);
       }
     case var_uinteger:
-      if (*(unsigned int *) cmd->var == UINT_MAX)
+      if (var.get<unsigned int> () == UINT_MAX)
        return value_from_ulongest
          (builtin_type (gdbarch)->builtin_unsigned_int, 0);
       else
        return value_from_ulongest
          (builtin_type (gdbarch)->builtin_unsigned_int,
-          *(unsigned int *) cmd->var);
+          var.get<unsigned int> ());
     case var_zuinteger:
       return value_from_ulongest (builtin_type (gdbarch)->builtin_unsigned_int,
-                                 *(unsigned int *) cmd->var);
+                                 var.get<unsigned int> ());
     case var_string:
     case var_string_noescape:
     case var_optional_filename:
     case var_filename:
     case var_enum:
-      if (*(char **) cmd->var)
-       return value_cstring (*(char **) cmd->var, strlen (*(char **) cmd->var),
-                             builtin_type (gdbarch)->builtin_char);
-      else
-       return value_cstring ("", 1,
-                             builtin_type (gdbarch)->builtin_char);
+      {
+       const char *value;
+       if (var.type () == var_enum)
+         value = var.get<const char *> ();
+       else
+         value = var.get<char *> ();
+
+       if (value != nullptr)
+         return value_cstring (value, strlen (value),
+                               builtin_type (gdbarch)->builtin_char);
+       else
+         return value_cstring ("", 1,
+                               builtin_type (gdbarch)->builtin_char);
+      }
     default:
       gdb_assert_not_reached ("bad var_type");
     }
                         const struct language_defn *language,
                         void *cookie, int argc, struct value **argv)
 {
-  return value_from_setting (setting_cmd ("$_gdb_setting", showlist,
-                                         argc, argv),
-                            gdbarch);
+  cmd_list_element *show_cmd
+    = setting_cmd ("$_gdb_setting", showlist, argc, argv);
+
+  gdb_assert (show_cmd->var.has_value ());
+
+  return value_from_setting (*show_cmd->var, gdbarch);
 }
 
 /* Implementation of the convenience function $_gdb_maint_setting.  */
                               const struct language_defn *language,
                               void *cookie, int argc, struct value **argv)
 {
-  return value_from_setting (setting_cmd ("$_gdb_maint_setting",
-                                         maintenance_show_cmdlist,
-                                         argc, argv),
-                            gdbarch);
+  cmd_list_element *show_cmd
+    = setting_cmd ("$_gdb_maint_setting", maintenance_show_cmdlist, argc, argv);
+
+  gdb_assert (show_cmd->var.has_value ());
+
+  return value_from_setting (*show_cmd->var, gdbarch);
 }
 
 /* Builds a string value from the show CMD.  */
 
 static struct value *
-str_value_from_setting (const cmd_list_element *cmd, struct gdbarch *gdbarch)
+str_value_from_setting (const setting &var, struct gdbarch *gdbarch)
 {
-  switch (cmd->var_type)
+  switch (var.type ())
     {
     case var_integer:
     case var_zinteger:
     case var_uinteger:
     case var_zuinteger:
       {
-       std::string cmd_val = get_setshow_command_value_string (cmd);
+       std::string cmd_val = get_setshow_command_value_string (var);
 
        return value_cstring (cmd_val.c_str (), cmd_val.size (),
                              builtin_type (gdbarch)->builtin_char);
     case var_enum:
       /* For these cases, we do not use get_setshow_command_value_string,
         as this function handle some characters specially, e.g. by
-        escaping quotes.  So, we directly use the cmd->var string value,
-        similarly to the value_from_setting code for these cases.  */
-      if (*(char **) cmd->var)
-       return value_cstring (*(char **) cmd->var, strlen (*(char **) cmd->var),
-                             builtin_type (gdbarch)->builtin_char);
-      else
-       return value_cstring ("", 1,
-                             builtin_type (gdbarch)->builtin_char);
+        escaping quotevar.  So, we directly use the var string value,
+        similarly to the value_from_setting code for these casevar.  */
+      {
+       const char *value;
+       if (var.type () == var_enum)
+         value = var.get<const char *> ();
+       else
+         value = var.get<char *> ();
 
+       if (value != nullptr)
+         return value_cstring (value, strlen (value),
+                               builtin_type (gdbarch)->builtin_char);
+       else
+         return value_cstring ("", 1,
+                               builtin_type (gdbarch)->builtin_char);
+      }
     default:
       gdb_assert_not_reached ("bad var_type");
     }
                             const struct language_defn *language,
                             void *cookie, int argc, struct value **argv)
 {
-  return str_value_from_setting (setting_cmd ("$_gdb_setting_str",
-                                             showlist, argc, argv),
-                                gdbarch);
+  cmd_list_element *show_cmd
+    = setting_cmd ("$_gdb_setting_str", showlist, argc, argv);
+
+  gdb_assert (show_cmd->var.has_value ());
+
+  return str_value_from_setting (*show_cmd->var, gdbarch);
 }
 
 
                                   const struct language_defn *language,
                                   void *cookie, int argc, struct value **argv)
 {
-  return str_value_from_setting (setting_cmd ("$_gdb_maint_setting_str",
-                                             maintenance_show_cmdlist,
-                                             argc, argv),
-                                gdbarch);
+  cmd_list_element *show_cmd
+    = setting_cmd ("$_gdb_maint_setting_str", maintenance_show_cmdlist, argc,
+                  argv);
+
+  gdb_assert (show_cmd->var.has_value ());
+
+  return str_value_from_setting (*show_cmd->var, gdbarch);
 }
 
 void _initialize_cli_cmds ();
 
                     enum cmd_types type,
                     enum command_class theclass,
                     var_types var_type,
-                    void *var,
+                    const setting::erased_args &arg,
                     const char *doc,
                     struct cmd_list_element **list)
 {
 
   gdb_assert (type == set_cmd || type == show_cmd);
   c->type = type;
-  c->var_type = var_type;
-  c->var = var;
+  c->var.emplace (var_type, arg);
+
   /* This needs to be something besides NULL so that this isn't
      treated as a help class.  */
   c->func = empty_func;
    Return the newly created set and show commands.  */
 
 static set_show_commands
-add_setshow_cmd_full (const char *name,
-                     enum command_class theclass,
-                     var_types var_type, void *var,
-                     const char *set_doc, const char *show_doc,
-                     const char *help_doc,
-                     cmd_func_ftype *set_func,
-                     show_value_ftype *show_func,
-                     struct cmd_list_element **set_list,
-                     struct cmd_list_element **show_list)
+add_setshow_cmd_full_erased (const char *name,
+                            enum command_class theclass,
+                            var_types var_type,
+                            const setting::erased_args &args,
+                            const char *set_doc, const char *show_doc,
+                            const char *help_doc,
+                            cmd_func_ftype *set_func,
+                            show_value_ftype *show_func,
+                            struct cmd_list_element **set_list,
+                            struct cmd_list_element **show_list)
 {
   struct cmd_list_element *set;
   struct cmd_list_element *show;
       full_set_doc = xstrdup (set_doc);
       full_show_doc = xstrdup (show_doc);
     }
-  set = add_set_or_show_cmd (name, set_cmd, theclass, var_type, var,
+  set = add_set_or_show_cmd (name, set_cmd, theclass, var_type, args,
                             full_set_doc, set_list);
   set->doc_allocated = 1;
 
   if (set_func != NULL)
     set->func = set_func;
 
-  show = add_set_or_show_cmd (name, show_cmd, theclass, var_type, var,
+  show = add_set_or_show_cmd (name, show_cmd, theclass, var_type, args,
                              full_show_doc, show_list);
   show->doc_allocated = 1;
   show->show_value_func = show_func;
   return {set, show};
 }
 
+template<typename T>
+static set_show_commands
+add_setshow_cmd_full (const char *name,
+                     enum command_class theclass,
+                     var_types var_type, T *var,
+                     const char *set_doc, const char *show_doc,
+                     const char *help_doc,
+                     cmd_func_ftype *set_func,
+                     show_value_ftype *show_func,
+                     struct cmd_list_element **set_list,
+                     struct cmd_list_element **show_list)
+{
+  auto erased_args
+    = setting::erase_args (var_type, var);
+
+  return add_setshow_cmd_full_erased (name,
+                                     theclass,
+                                     var_type, erased_args,
+                                     set_doc, show_doc,
+                                     help_doc,
+                                     set_func,
+                                     show_func,
+                                     set_list,
+                                     show_list);
+}
+
 /* Add element named NAME to command list LIST (the list for set or
    some sublist thereof).  CLASS is as in add_cmd.  ENUMLIST is a list
    of strings which may follow NAME.  VAR is address of the variable
                      struct cmd_list_element **show_list)
 {
   set_show_commands commands
-    =  add_setshow_cmd_full (name, theclass, var_enum, var,
-                            set_doc, show_doc, help_doc,
-                            set_func, show_func,
-                            set_list, show_list);
+    =  add_setshow_cmd_full<const char *> (name, theclass, var_enum, var,
+                                          set_doc, show_doc, help_doc,
+                                          set_func, show_func,
+                                          set_list, show_list);
   commands.set->enums = enumlist;
   return commands;
 }
                              struct cmd_list_element **show_list)
 {
   set_show_commands commands
-    = add_setshow_cmd_full (name, theclass, var_auto_boolean, var,
-                           set_doc, show_doc, help_doc,
-                           set_func, show_func,
-                           set_list, show_list);
+    = add_setshow_cmd_full<enum auto_boolean> (name, theclass,
+                                              var_auto_boolean,var,
+                                              set_doc, show_doc, help_doc,
+                                              set_func, show_func,
+                                              set_list, show_list);
 
   commands.set->enums = auto_boolean_enums;
 
                         struct cmd_list_element **show_list)
 {
   set_show_commands commands
-    = add_setshow_cmd_full (name, theclass, var_boolean, var,
-                           set_doc, show_doc, help_doc,
-                           set_func, show_func,
-                           set_list, show_list);
+    = add_setshow_cmd_full<bool> (name, theclass, var_boolean, var,
+                                 set_doc, show_doc, help_doc,
+                                 set_func, show_func,
+                                 set_list, show_list);
 
   commands.set->enums = boolean_enums;
 
                          struct cmd_list_element **show_list)
 {
   set_show_commands commands
-    = add_setshow_cmd_full (name, theclass, var_filename, var,
-                           set_doc, show_doc, help_doc,
-                           set_func, show_func,
-                           set_list, show_list);
+    = add_setshow_cmd_full<char *> (name, theclass, var_filename, var,
+                                   set_doc, show_doc, help_doc,
+                                   set_func, show_func,
+                                   set_list, show_list);
 
   set_cmd_completer (commands.set, filename_completer);
 
                        struct cmd_list_element **show_list)
 {
   set_show_commands commands
-    = add_setshow_cmd_full (name, theclass, var_string, var,
-                           set_doc, show_doc, help_doc,
-                           set_func, show_func,
-                           set_list, show_list);
+    = add_setshow_cmd_full<char *> (name, theclass, var_string, var,
+                                   set_doc, show_doc, help_doc,
+                                   set_func, show_func,
+                                   set_list, show_list);
 
   /* Disable the default symbol completer.  */
   set_cmd_completer (commands.set, nullptr);
                                 struct cmd_list_element **show_list)
 {
   set_show_commands commands
-    = add_setshow_cmd_full (name, theclass, var_string_noescape, var,
-                           set_doc, show_doc, help_doc,
-                           set_func, show_func,
-                           set_list, show_list);
+    = add_setshow_cmd_full<char *> (name, theclass, var_string_noescape, var,
+                                   set_doc, show_doc, help_doc, set_func,
+                                   show_func, set_list, show_list);
 
   /* Disable the default symbol completer.  */
   set_cmd_completer (commands.set, nullptr);
                                   struct cmd_list_element **show_list)
 {
   set_show_commands commands
-    = add_setshow_cmd_full (name, theclass, var_optional_filename, var,
-                           set_doc, show_doc, help_doc,
-                           set_func, show_func,
-                           set_list, show_list);
-               
+    = add_setshow_cmd_full<char *> (name, theclass, var_optional_filename,
+                                   var, set_doc, show_doc, help_doc,
+                                   set_func, show_func, set_list, show_list);
+
   set_cmd_completer (commands.set, filename_completer);
 
   return commands;
                         struct cmd_list_element **show_list)
 {
   set_show_commands commands
-    = add_setshow_cmd_full (name, theclass, var_integer, var,
-                           set_doc, show_doc, help_doc,
-                           set_func, show_func,
-                           set_list, show_list);
+    = add_setshow_cmd_full<int> (name, theclass, var_integer, var, set_doc,
+                                show_doc, help_doc, set_func, show_func,
+                                set_list, show_list);
 
   set_cmd_completer (commands.set, integer_unlimited_completer);
 
                          struct cmd_list_element **show_list)
 {
   set_show_commands commands
-    = add_setshow_cmd_full (name, theclass, var_uinteger, var,
-                           set_doc, show_doc, help_doc,
-                           set_func, show_func,
-                           set_list, show_list);
+    = add_setshow_cmd_full<unsigned int> (name, theclass, var_uinteger, var,
+                                         set_doc, show_doc, help_doc,
+                                         set_func, show_func,
+                                         set_list, show_list);
 
   set_cmd_completer (commands.set, integer_unlimited_completer);
 
                          struct cmd_list_element **set_list,
                          struct cmd_list_element **show_list)
 {
-  return add_setshow_cmd_full (name, theclass, var_zinteger, var,
-                              set_doc, show_doc, help_doc,
-                              set_func, show_func,
-                              set_list, show_list);
+  return add_setshow_cmd_full<int> (name, theclass, var_zinteger, var,
+                                   set_doc, show_doc, help_doc,
+                                   set_func, show_func,
+                                   set_list, show_list);
 }
 
 set_show_commands
                                     struct cmd_list_element **show_list)
 {
   set_show_commands commands
-    = add_setshow_cmd_full (name, theclass, var_zuinteger_unlimited, var,
-                           set_doc, show_doc, help_doc,
-                           set_func, show_func,
-                           set_list, show_list);
+    = add_setshow_cmd_full<int> (name, theclass, var_zuinteger_unlimited, var,
+                                set_doc, show_doc, help_doc, set_func,
+                                show_func, set_list, show_list);
 
   set_cmd_completer (commands.set, integer_unlimited_completer);
 
                           struct cmd_list_element **set_list,
                           struct cmd_list_element **show_list)
 {
-  return add_setshow_cmd_full (name, theclass, var_zuinteger, var,
-                              set_doc, show_doc, help_doc,
-                              set_func, show_func,
-                              set_list, show_list);
+  return add_setshow_cmd_full<unsigned int> (name, theclass, var_zuinteger,
+                                            var, set_doc, show_doc, help_doc,
+                                            set_func, show_func, set_list,
+                                            show_list);
 }
 
 /* Remove the command named NAME from the command list.  Return the
 
       allow_unknown (0),
       abbrev_flag (0),
       type (not_set_cmd),
-      var_type (var_boolean),
       doc (doc_)
   {
     memset (&function, 0, sizeof (function));
      or "show").  */
   ENUM_BITFIELD (cmd_types) type : 2;
 
-  /* What kind of variable is *VAR?  */
-  ENUM_BITFIELD (var_types) var_type : 4;
-
   /* Function definition of this command.  NULL for command class
      names and for help topics that are not really commands.  NOTE:
      cagney/2002-02-02: This function signature is evolving.  For
      used to finalize the CONTEXT field, if needed.  */
   void (*destroyer) (struct cmd_list_element *self, void *context) = nullptr;
 
-  /* Pointer to variable affected by "set" and "show".  Doesn't
-     matter if type is not_set.  */
-  void *var = nullptr;
+  /* Setting affected by "set" and "show".  Not used if type is not_set_cmd.  */
+  gdb::optional<setting> var;
 
   /* Pointer to NULL terminated list of enumerated values (like
      argv).  */
 
   /* If there's no command or value, don't try to print it out.  */
   if (c == NULL || value == NULL)
     return;
+
   /* Print doc minus "Show " at start.  Tell print_doc_line that
      this is for a 'show value' prefix.  */
   print_doc_line (gdb_stdout, c->doc + 5, true);
-  switch (c->var_type)
+
+  gdb_assert (c->var.has_value ());
+
+  switch (c->var->type ())
     {
     case var_string:
     case var_string_noescape:
     case var_enum:
       printf_filtered ((" is \"%s\".\n"), value);
       break;
+
     default:
       printf_filtered ((" is %s.\n"), value);
       break;
   if (arg == NULL)
     arg = "";
 
-  switch (c->var_type)
+  gdb_assert (c->var.has_value ());
+
+  switch (c->var->type ())
     {
     case var_string:
       {
        *q++ = '\0';
        newobj = (char *) xrealloc (newobj, q - newobj);
 
-       if (*(char **) c->var == NULL
-           || strcmp (*(char **) c->var, newobj) != 0)
+       char * const var = c->var->get<char *> ();
+       if (var == nullptr
+           || strcmp (var, newobj) != 0)
          {
-           xfree (*(char **) c->var);
-           *(char **) c->var = newobj;
+           xfree (var);
+           c->var->set<char *> (newobj);
 
            option_changed = true;
          }
       }
       break;
     case var_string_noescape:
-      if (*(char **) c->var == NULL || strcmp (*(char **) c->var, arg) != 0)
-       {
-         xfree (*(char **) c->var);
-         *(char **) c->var = xstrdup (arg);
+      {
+       char * const var = c->var->get<char *> ();
+       if (var == nullptr
+           || strcmp (var, arg) != 0)
+         {
+           xfree (var);
+           c->var->set<char *> (xstrdup (arg));
 
-         option_changed = true;
-       }
+           option_changed = true;
+         }
+      }
       break;
     case var_filename:
       if (*arg == '\0')
        else
          val = xstrdup ("");
 
-       if (*(char **) c->var == NULL
-           || strcmp (*(char **) c->var, val) != 0)
+       char * const var = c->var->get<char *> ();
+       if (var == nullptr
+           || strcmp (var, val) != 0)
          {
-           xfree (*(char **) c->var);
-           *(char **) c->var = val;
+           xfree (var);
+           c->var->set<char *> (val);
 
            option_changed = true;
          }
 
        if (val < 0)
          error (_("\"on\" or \"off\" expected."));
-       if (val != *(bool *) c->var)
+       if (val != c->var->get<bool> ())
          {
-           *(bool *) c->var = val;
+           c->var->set<bool> (val);
 
            option_changed = true;
          }
       {
        enum auto_boolean val = parse_auto_binary_operation (arg);
 
-       if (*(enum auto_boolean *) c->var != val)
+       if (c->var->get<enum auto_boolean> () != val)
          {
-           *(enum auto_boolean *) c->var = val;
+           c->var->set<enum auto_boolean> (val);
 
            option_changed = true;
          }
     case var_uinteger:
     case var_zuinteger:
       {
-       unsigned int val = parse_cli_var_uinteger (c->var_type, &arg, true);
+       unsigned int val
+         = parse_cli_var_uinteger (c->var->type (), &arg, true);
 
-       if (*(unsigned int *) c->var != val)
+       if (c->var->get<unsigned int> () != val)
          {
-           *(unsigned int *) c->var = val;
+           c->var->set<unsigned int> (val);
 
            option_changed = true;
          }
 
        if (*arg == '\0')
          {
-           if (c->var_type == var_integer)
+           if (c->var->type () == var_integer)
              error_no_arg (_("integer to set it to, or \"unlimited\"."));
            else
              error_no_arg (_("integer to set it to."));
          }
 
-       if (c->var_type == var_integer && is_unlimited_literal (&arg, true))
+       if (c->var->type () == var_integer && is_unlimited_literal (&arg, true))
          val = 0;
        else
          val = parse_and_eval_long (arg);
 
-       if (val == 0 && c->var_type == var_integer)
+       if (val == 0 && c->var->type () == var_integer)
          val = INT_MAX;
        else if (val < INT_MIN
                 /* For var_integer, don't let the user set the value
                    to INT_MAX directly, as that exposes an
                    implementation detail to the user interface.  */
-                || (c->var_type == var_integer && val >= INT_MAX)
-                || (c->var_type == var_zinteger && val > INT_MAX))
+                || (c->var->type () == var_integer && val >= INT_MAX)
+                || (c->var->type () == var_zinteger && val > INT_MAX))
          error (_("integer %s out of range"), plongest (val));
 
-       if (*(int *) c->var != val)
+       if (c->var->get<int> () != val)
          {
-           *(int *) c->var = val;
+           c->var->set<int> (val);
 
            option_changed = true;
          }
-       break;
       }
+      break;
     case var_enum:
       {
        const char *end_arg = arg;
        if (*after != '\0')
          error (_("Junk after item \"%.*s\": %s"), len, arg, after);
 
-       if (*(const char **) c->var != match)
+       if (c->var->get<const char *> () != match)
          {
-           *(const char **) c->var = match;
+           c->var->set<const char *> (match);
 
            option_changed = true;
          }
       {
        int val = parse_cli_var_zuinteger_unlimited (&arg, true);
 
-       if (*(int *) c->var != val)
+       if (c->var->get<int> () != val)
          {
-           *(int *) c->var = val;
+           c->var->set<int> (val);
            option_changed = true;
          }
       }
 
       xfree (cmds);
 
-      switch (c->var_type)
+      switch (c->var->type ())
        {
        case var_string:
        case var_string_noescape:
        case var_filename:
        case var_optional_filename:
        case var_enum:
-         gdb::observers::command_param_changed.notify (name, *(char **) c->var);
+         {
+           const char *var;
+           if (c->var->type () == var_enum)
+             var = c->var->get<const char *> ();
+           else
+             var = c->var->get<char *> ();
+           gdb::observers::command_param_changed.notify (name, var);
+         }
          break;
        case var_boolean:
          {
-           const char *opt = *(bool *) c->var ? "on" : "off";
+           const char *opt = c->var->get<bool> () ? "on" : "off";
 
            gdb::observers::command_param_changed.notify (name, opt);
          }
          break;
        case var_auto_boolean:
          {
-           const char *s = auto_boolean_enums[*(enum auto_boolean *) c->var];
+           const char *s
+             = auto_boolean_enums[c->var->get<enum auto_boolean> ()];
 
            gdb::observers::command_param_changed.notify (name, s);
          }
          {
            char s[64];
 
-           xsnprintf (s, sizeof s, "%u", *(unsigned int *) c->var);
+           xsnprintf (s, sizeof s, "%u", c->var->get<unsigned int> ());
            gdb::observers::command_param_changed.notify (name, s);
          }
          break;
          {
            char s[64];
 
-           xsnprintf (s, sizeof s, "%d", *(int *) c->var);
+           xsnprintf (s, sizeof s, "%d", c->var->get<int> ());
            gdb::observers::command_param_changed.notify (name, s);
          }
          break;
 /* See cli/cli-setshow.h.  */
 
 std::string
-get_setshow_command_value_string (const cmd_list_element *c)
+get_setshow_command_value_string (const setting &var)
 {
   string_file stb;
 
-  switch (c->var_type)
+  switch (var.type ())
     {
     case var_string:
-      if (*(char **) c->var)
-       stb.putstr (*(char **) c->var, '"');
+      {
+       char *value = var.get<char *> ();
+
+       if (value != nullptr)
+         stb.putstr (value, '"');
+      }
       break;
     case var_string_noescape:
     case var_optional_filename:
     case var_filename:
     case var_enum:
-      if (*(char **) c->var)
-       stb.puts (*(char **) c->var);
+      {
+       const char *value;
+       if (var.type () == var_enum)
+         value = var.get<const char *> ();
+       else
+         value = var.get<char *> ();
+
+       if (value != nullptr)
+         stb.puts (value);
+      }
       break;
     case var_boolean:
-      stb.puts (*(bool *) c->var ? "on" : "off");
+      stb.puts (var.get<bool> () ? "on" : "off");
       break;
     case var_auto_boolean:
-      switch (*(enum auto_boolean*) c->var)
+      switch (var.get<enum auto_boolean> ())
        {
        case AUTO_BOOLEAN_TRUE:
          stb.puts ("on");
       break;
     case var_uinteger:
     case var_zuinteger:
-      if (c->var_type == var_uinteger
-         && *(unsigned int *) c->var == UINT_MAX)
-       stb.puts ("unlimited");
-      else
-       stb.printf ("%u", *(unsigned int *) c->var);
+      {
+       const unsigned int value = var.get<unsigned int> ();
+
+       if (var.type () == var_uinteger
+           && value == UINT_MAX)
+         stb.puts ("unlimited");
+       else
+         stb.printf ("%u", value);
+      }
       break;
     case var_integer:
     case var_zinteger:
-      if (c->var_type == var_integer
-         && *(int *) c->var == INT_MAX)
-       stb.puts ("unlimited");
-      else
-       stb.printf ("%d", *(int *) c->var);
+      {
+       const int value = var.get<int> ();
+
+       if (var.type () == var_integer
+           && value == INT_MAX)
+         stb.puts ("unlimited");
+       else
+         stb.printf ("%d", value);
+      }
       break;
     case var_zuinteger_unlimited:
       {
-       if (*(int *) c->var == -1)
+       const int value = var.get<int> ();
+       if (value == -1)
          stb.puts ("unlimited");
        else
-         stb.printf ("%d", *(int *) c->var);
+         stb.printf ("%d", value);
       }
       break;
     default:
   struct ui_out *uiout = current_uiout;
 
   gdb_assert (c->type == show_cmd);
+  gdb_assert (c->var.has_value ());
 
-  std::string val = get_setshow_command_value_string (c);
+  std::string val = get_setshow_command_value_string (*c->var);
 
   /* FIXME: cagney/2005-02-10: There should be MI and CLI specific
      versions of code to print the value out.  */
 
 extern void do_show_command (const char *arg, int from_tty,
                             struct cmd_list_element *c);
 
-/* Get a string version of C's current value.  */
-extern std::string get_setshow_command_value_string (const cmd_list_element *c);
+/* Get a string version of VAR's value.  */
+extern std::string get_setshow_command_value_string (const setting &var);
 
 extern void cmd_show_list (struct cmd_list_element *list, int from_tty);
 
 
   }
 var_types;
 
+/* Return true if a setting of type VAR_TYPE is backed with type T.
+
+   This function is left without definition intentionally.  This template is
+   specialized for all valid types that are used to back var_types.  Therefore
+   if one tries to instantiate this un-specialized template it means the T
+   parameter is not a type used to back a var_type and it is most likely a
+   programming error.  */
+template<typename T>
+bool var_type_uses (var_types var_type) = delete;
+
+/* Return true if a setting of type T is backed by a bool variable.  */
+template<>
+inline bool var_type_uses<bool> (var_types t)
+{
+  return t == var_boolean;
+};
+
+/* Return true if a setting of type T is backed by a auto_boolean variable.
+*/
+template<>
+inline bool var_type_uses<enum auto_boolean> (var_types t)
+{
+  return t == var_auto_boolean;
+}
+
+/* Return true if a setting of type T is backed by an unsigned int variable.
+*/
+template<>
+inline bool var_type_uses<unsigned int> (var_types t)
+{
+  return (t == var_uinteger || t == var_zinteger || t == var_zuinteger);
+}
+
+/* Return true if a setting of type T is backed by an int variable.  */
+template<>
+inline bool var_type_uses<int> (var_types t)
+{
+  return (t == var_integer || t == var_zinteger
+         || t == var_zuinteger_unlimited);
+}
+
+/* Return true if a setting of type T is backed by a char * variable.  */
+template<>
+inline bool var_type_uses<char *> (var_types t)
+{
+  return (t == var_string || t == var_string_noescape
+         || t == var_optional_filename || t == var_filename);
+}
+
+/* Return true if a setting of type T is backed by a const char * variable.
+*/
+template<>
+inline bool var_type_uses<const char *> (var_types t)
+{
+  return t == var_enum;
+}
+
+/* Interface for getting and setting a setting's value.
+
+   The underlying data can be of any VAR_TYPES type.  */
+struct setting
+{
+  /* Create a setting backed by a variable of type T.
+
+     Type T must match the var type VAR_TYPE (see VAR_TYPE_USES).  */
+  template<typename T>
+  setting (var_types var_type, T *var)
+    : m_var_type (var_type), m_var (var)
+  {
+    gdb_assert (var != nullptr);
+    gdb_assert (var_type_uses<T> (var_type));
+  }
+
+  /* A setting can also be constructed with a pre-validated
+     type-erased variable.  Use the following function to
+     validate & type-erase said variable/function pointers.  */
+
+  struct erased_args
+  {
+    void *var;
+  };
+
+  template<typename T>
+  static erased_args erase_args (var_types var_type, T *var)
+  {
+    gdb_assert (var_type_uses<T> (var_type));
+
+    return {var};
+  }
+
+  /* Create a setting backed by pre-validated type-erased args.
+     ERASED_VAR's fields' real types must match the var type VAR_TYPE
+     (see VAR_TYPE_USES).  */
+  setting (var_types var_type, const erased_args &args)
+    : m_var_type (var_type),
+      m_var (args.var)
+  {
+  }
+
+  /* Access the type of the current setting.  */
+  var_types type () const
+  {
+    return m_var_type;
+  }
+
+  /* Return the current value.
+
+     The template parameter T is the type of the variable used to store the
+     setting.  */
+  template<typename T>
+  const T &get () const
+  {
+    gdb_assert (var_type_uses<T> (m_var_type));
+    gdb_assert (m_var != nullptr);
+
+    return *static_cast<const T *> (m_var);
+  }
+
+  /* Sets the value of the setting to V.
+
+     The template parameter T indicates the type of the variable used to
+     store the setting.
+
+     The var_type of the setting must match T.  */
+  template<typename T>
+  void set (const T &v)
+  {
+    /* Check that the current instance is of one of the supported types for
+       this instantiation.  */
+    gdb_assert (var_type_uses<T> (m_var_type));
+
+    *static_cast<T *> (m_var) = v;
+  }
+
+private:
+  /* The type of the variable M_VAR is pointing to.  */
+  var_types m_var_type;
+
+  /* Pointer to the enclosed variable.  The type of the variable is encoded
+     in M_VAR_TYPE.  */
+  void *m_var;
+};
+
 /* This structure records one command'd definition.  */
 struct cmd_list_element;
 
 
   SCM containing_scm;
 };
 
+/* Wraps a setting around an existing param_smob.  This abstraction
+   is used to manipulate the value in S->VALUE in a type safe manner using
+   the setting interface.  */
+
+static setting
+make_setting (param_smob *s)
+{
+
+  if (var_type_uses<bool> (s->type))
+    return setting (s->type, &s->value.boolval);
+  else if (var_type_uses<int> (s->type))
+    return setting (s->type, &s->value.intval);
+  else if (var_type_uses<auto_boolean> (s->type))
+    return setting (s->type, &s->value.autoboolval);
+  else if (var_type_uses<unsigned int> (s->type))
+    return setting (s->type, &s->value.uintval);
+  else if (var_type_uses<char *> (s->type))
+    return setting (s->type, &s->value.stringval);
+  else if (var_type_uses<const char *> (s->type))
+    return setting (s->type, &s->value.cstringval);
+  else
+    gdb_assert_not_reached ("unhandled var type");
+}
+
 static const char param_smob_name[] = "gdb:parameter";
 
 /* The tag Guile knows the param smob by.  */
 
 static int pascm_is_valid (param_smob *);
 static const char *pascm_param_type_name (enum var_types type);
-static SCM pascm_param_value (enum var_types type, void *var,
-                             int arg_pos, const char *func_name);
+static SCM pascm_param_value (const setting &var, int arg_pos,
+                             const char *func_name);
 \f
 /* Administrivia for parameter smobs.  */
 
 
   gdbscm_printf (port, " %s ", pascm_param_type_name (p_smob->type));
 
-  value = pascm_param_value (p_smob->type, &p_smob->value,
-                            GDBSCM_ARG_NONE, NULL);
+  value = pascm_param_value (make_setting (p_smob), GDBSCM_ARG_NONE, NULL);
   scm_display (value, port);
 
   scm_puts (">", port);
                                       show_doc, help_doc, set_func, show_func,
                                       set_list, show_list);
       /* Initialize the value, just in case.  */
-      self->value.cstringval = self->enumeration[0];
+      make_setting (self).set<const char *> (self->enumeration[0]);
       break;
 
     default:
 }
 
 /* Return the value of a gdb parameter as a Scheme value.
-   If TYPE is not supported, then a <gdb:exception> object is returned.  */
+   If the var_type of VAR is not supported, then a <gdb:exception> object is
+   returned.  */
 
 static SCM
-pascm_param_value (enum var_types type, void *var,
-                  int arg_pos, const char *func_name)
+pascm_param_value (const setting &var, int arg_pos, const char *func_name)
 {
   /* Note: We *could* support var_integer here in case someone is trying to get
      the value of a Python-created parameter (which is the only place that
      still supports var_integer).  To further discourage its use we do not.  */
 
-  switch (type)
+  switch (var.type ())
     {
     case var_string:
     case var_string_noescape:
     case var_filename:
     case var_enum:
       {
-       const char *str = *(char **) var;
+       const char *str;
+       if (var.type () == var_enum)
+         str = var.get<const char *> ();
+       else
+         str = var.get<char *> ();
 
-       if (str == NULL)
+       if (str == nullptr)
          str = "";
        return gdbscm_scm_from_host_string (str, strlen (str));
       }
 
     case var_boolean:
       {
-       if (* (bool *) var)
+       if (var.get<bool> ())
          return SCM_BOOL_T;
        else
          return SCM_BOOL_F;
 
     case var_auto_boolean:
       {
-       enum auto_boolean ab = * (enum auto_boolean *) var;
+       enum auto_boolean ab = var.get<enum auto_boolean> ();
 
        if (ab == AUTO_BOOLEAN_TRUE)
          return SCM_BOOL_T;
       }
 
     case var_zuinteger_unlimited:
-      if (* (int *) var == -1)
+      if (var.get<int> () == -1)
        return unlimited_keyword;
-      gdb_assert (* (int *) var >= 0);
+      gdb_assert (var.get<int> () >= 0);
       /* Fall through.  */
     case var_zinteger:
-      return scm_from_int (* (int *) var);
+      return scm_from_int (var.get<int> ());
 
     case var_uinteger:
-      if (* (unsigned int *) var == UINT_MAX)
+      if (var.get<unsigned int> ()== UINT_MAX)
        return unlimited_keyword;
       /* Fall through.  */
     case var_zuinteger:
-      return scm_from_uint (* (unsigned int *) var);
+      return scm_from_uint (var.get<unsigned int> ());
 
     default:
       break;
     }
 
   return gdbscm_make_out_of_range_error (func_name, arg_pos,
-                                        scm_from_int (type),
+                                        scm_from_int (var.type ()),
                                         _("program error: unhandled type"));
 }
 
-/* Set the value of a parameter of type TYPE in VAR from VALUE.
+/* Set the value of a parameter of type P_SMOB->TYPE in P_SMOB->VAR from VALUE.
    ENUMERATION is the list of enum values for enum parameters, otherwise NULL.
    Throws a Scheme exception if VALUE_SCM is invalid for TYPE.  */
 
 static void
-pascm_set_param_value_x (enum var_types type, union pascm_variable *var,
+pascm_set_param_value_x (param_smob *p_smob,
                         const char * const *enumeration,
                         SCM value, int arg_pos, const char *func_name)
 {
-  switch (type)
+  setting var = make_setting (p_smob);
+
+  switch (var.type ())
     {
     case var_string:
     case var_string_noescape:
     case var_optional_filename:
     case var_filename:
       SCM_ASSERT_TYPE (scm_is_string (value)
-                      || (type != var_filename
+                      || (var.type () != var_filename
                           && gdbscm_is_false (value)),
                       value, arg_pos, func_name,
                       _("string or #f for non-PARAM_FILENAME parameters"));
       if (gdbscm_is_false (value))
        {
-         xfree (var->stringval);
-         if (type == var_optional_filename)
-           var->stringval = xstrdup ("");
+         xfree (var.get<char *> ());
+         if (var.type () == var_optional_filename)
+           var.set<char *> (xstrdup (""));
          else
-           var->stringval = NULL;
+           var.set<char *> (nullptr);
        }
       else
        {
          SCM exception;
 
          gdb::unique_xmalloc_ptr<char> string
-           = gdbscm_scm_to_host_string (value, NULL, &exception);
-         if (string == NULL)
+           = gdbscm_scm_to_host_string (value, nullptr, &exception);
+         if (string == nullptr)
            gdbscm_throw (exception);
-         xfree (var->stringval);
-         var->stringval = string.release ();
+         xfree (var.get<char *> ());
+         var.set<char *> (string.release ());
        }
       break;
 
        SCM_ASSERT_TYPE (scm_is_string (value), value, arg_pos, func_name,
                       _("string"));
        gdb::unique_xmalloc_ptr<char> str
-         = gdbscm_scm_to_host_string (value, NULL, &exception);
-       if (str == NULL)
+         = gdbscm_scm_to_host_string (value, nullptr, &exception);
+       if (str == nullptr)
          gdbscm_throw (exception);
        for (i = 0; enumeration[i]; ++i)
          {
            if (strcmp (enumeration[i], str.get ()) == 0)
              break;
          }
-       if (enumeration[i] == NULL)
+       if (enumeration[i] == nullptr)
          {
            gdbscm_out_of_range_error (func_name, arg_pos, value,
                                       _("not member of enumeration"));
          }
-       var->cstringval = enumeration[i];
+       var.set<const char *> (enumeration[i]);
        break;
       }
 
     case var_boolean:
       SCM_ASSERT_TYPE (gdbscm_is_bool (value), value, arg_pos, func_name,
                       _("boolean"));
-      var->boolval = gdbscm_is_true (value);
+      var.set<bool> (gdbscm_is_true (value));
       break;
 
     case var_auto_boolean:
                       value, arg_pos, func_name,
                       _("boolean or #:auto"));
       if (scm_is_eq (value, auto_keyword))
-       var->autoboolval = AUTO_BOOLEAN_AUTO;
+       var.set<enum auto_boolean> (AUTO_BOOLEAN_AUTO);
       else if (gdbscm_is_true (value))
-       var->autoboolval = AUTO_BOOLEAN_TRUE;
+       var.set<enum auto_boolean> (AUTO_BOOLEAN_TRUE);
       else
-       var->autoboolval = AUTO_BOOLEAN_FALSE;
+       var.set<enum auto_boolean> (AUTO_BOOLEAN_FALSE);
       break;
 
     case var_zinteger:
     case var_uinteger:
     case var_zuinteger:
     case var_zuinteger_unlimited:
-      if (type == var_uinteger
-         || type == var_zuinteger_unlimited)
+      if (var.type () == var_uinteger
+         || var.type () == var_zuinteger_unlimited)
        {
          SCM_ASSERT_TYPE (gdbscm_is_bool (value)
                           || scm_is_eq (value, unlimited_keyword),
                           _("integer or #:unlimited"));
          if (scm_is_eq (value, unlimited_keyword))
            {
-             if (type == var_uinteger)
-               var->intval = UINT_MAX;
+             if (var.type () == var_uinteger)
+               var.set<unsigned int> (UINT_MAX);
              else
-               var->intval = -1;
+               var.set<int> (-1);
              break;
            }
        }
                           _("integer"));
        }
 
-      if (type == var_uinteger
-         || type == var_zuinteger)
+      if (var.type () == var_uinteger
+         || var.type () == var_zuinteger)
        {
          unsigned int u = scm_to_uint (value);
 
-         if (type == var_uinteger && u == 0)
+         if (var.type () == var_uinteger && u == 0)
            u = UINT_MAX;
-         var->uintval = u;
+         var.set<unsigned int> (u);
        }
       else
        {
          int i = scm_to_int (value);
 
-         if (type == var_zuinteger_unlimited && i < -1)
+         if (var.type () == var_zuinteger_unlimited && i < -1)
            {
              gdbscm_out_of_range_error (func_name, arg_pos, value,
                                         _("must be >= -1"));
            }
-         var->intval = i;
+         var.set<int> (i);
        }
       break;
 
          if (gdbscm_is_exception (initial_value_scm))
            gdbscm_throw (initial_value_scm);
        }
-      pascm_set_param_value_x (p_smob->type, &p_smob->value, enum_list,
+      pascm_set_param_value_x (p_smob, enum_list,
                               initial_value_scm,
                               initial_value_arg_pos, FUNC_NAME);
     }
       param_smob *p_smob = pascm_get_param_smob_arg_unsafe (self, SCM_ARG1,
                                                            FUNC_NAME);
 
-      return pascm_param_value (p_smob->type, &p_smob->value,
-                               SCM_ARG1, FUNC_NAME);
+      return pascm_param_value (make_setting (p_smob), SCM_ARG1, FUNC_NAME);
     }
   else
     {
          gdbscm_out_of_range_error (FUNC_NAME, SCM_ARG1, self,
                                     _("parameter not found"));
        }
-      if (cmd->var == NULL)
+
+      if (!cmd->var.has_value ())
        {
          gdbscm_out_of_range_error (FUNC_NAME, SCM_ARG1, self,
                                     _("not a parameter"));
        }
 
-      return pascm_param_value (cmd->var_type, cmd->var, SCM_ARG1, FUNC_NAME);
+      return pascm_param_value (*cmd->var, SCM_ARG1, FUNC_NAME);
     }
 }
 
   param_smob *p_smob = pascm_get_param_smob_arg_unsafe (self, SCM_ARG1,
                                                        FUNC_NAME);
 
-  pascm_set_param_value_x (p_smob->type, &p_smob->value, p_smob->enumeration,
+  pascm_set_param_value_x (p_smob, p_smob->enumeration,
                           value, SCM_ARG2, FUNC_NAME);
 
   return SCM_UNSPECIFIED;
 
     error (_("Bad value for 'mt set per-command no'."));
 
   for (list = per_command_setlist; list != NULL; list = list->next)
-    if (list->var_type == var_boolean)
+    if (list->var->type () == var_boolean)
       {
        gdb_assert (list->type == set_cmd);
        do_set_command (args, from_tty, list);
 
   const char **enumeration;
 };
 
+/* Wraps a setting around an existing parmpy_object.  This abstraction
+   is used to manipulate the value in S->VALUE in a type safe manner using
+   the setting interface.  */
+
+static setting
+make_setting (parmpy_object *s)
+{
+
+  if (var_type_uses<bool> (s->type))
+    return setting (s->type, &s->value.boolval);
+  else if (var_type_uses<int> (s->type))
+    return setting (s->type, &s->value.intval);
+  else if (var_type_uses<auto_boolean> (s->type))
+    return setting (s->type, &s->value.autoboolval);
+  else if (var_type_uses<unsigned int> (s->type))
+    return setting (s->type, &s->value.uintval);
+  else if (var_type_uses<char *> (s->type))
+    return setting (s->type, &s->value.stringval);
+  else if (var_type_uses<const char *> (s->type))
+    return setting (s->type, &s->value.cstringval);
+  else
+    gdb_assert_not_reached ("unhandled var type");
+}
+
 extern PyTypeObject parmpy_object_type
     CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("parmpy_object");
 
     {
       parmpy_object *self = (parmpy_object *) obj;
 
-      return gdbpy_parameter_value (self->type, &self->value);
+      return gdbpy_parameter_value (make_setting (self));
     }
 
   return PyObject_GenericGetAttr (obj, attr_name);
 
 PyObject *gdbpy_selected_thread (PyObject *self, PyObject *args);
 PyObject *gdbpy_selected_inferior (PyObject *self, PyObject *args);
 PyObject *gdbpy_string_to_argv (PyObject *self, PyObject *args);
-PyObject *gdbpy_parameter_value (enum var_types type, void *var);
+PyObject *gdbpy_parameter_value (const setting &var);
 gdb::unique_xmalloc_ptr<char> gdbpy_parse_command_name
   (const char *name, struct cmd_list_element ***base_list,
    struct cmd_list_element **start_list);
 
    NULL (and set a Python exception) on error.  Helper function for
    get_parameter.  */
 PyObject *
-gdbpy_parameter_value (enum var_types type, void *var)
+gdbpy_parameter_value (const setting &var)
 {
-  switch (type)
+  switch (var.type ())
     {
     case var_string:
     case var_string_noescape:
     case var_filename:
     case var_enum:
       {
-       const char *str = *(char **) var;
+       const char *str;
+        if (var.type () == var_enum)
+          str = var.get<const char *> ();
+        else
+          str = var.get<char *> ();
 
-       if (! str)
+       if (str == nullptr)
          str = "";
        return host_string_to_python_string (str).release ();
       }
 
     case var_boolean:
       {
-       if (* (bool *) var)
+       if (var.get<bool> ())
          Py_RETURN_TRUE;
        else
          Py_RETURN_FALSE;
 
     case var_auto_boolean:
       {
-       enum auto_boolean ab = * (enum auto_boolean *) var;
+       enum auto_boolean ab = var.get<enum auto_boolean> ();
 
        if (ab == AUTO_BOOLEAN_TRUE)
          Py_RETURN_TRUE;
       }
 
     case var_integer:
-      if ((* (int *) var) == INT_MAX)
+      if (var.get<int> () == INT_MAX)
        Py_RETURN_NONE;
       /* Fall through.  */
     case var_zinteger:
     case var_zuinteger_unlimited:
-      return gdb_py_object_from_longest (* (int *) var).release ();
+      return gdb_py_object_from_longest (var.get<int> ()).release ();
 
     case var_uinteger:
       {
-       unsigned int val = * (unsigned int *) var;
+       unsigned int val = var.get<unsigned int> ();
 
        if (val == UINT_MAX)
          Py_RETURN_NONE;
 
     case var_zuinteger:
       {
-       unsigned int val = * (unsigned int *) var;
+       unsigned int val = var.get<unsigned int> ();
        return gdb_py_object_from_ulongest (val).release ();
       }
     }
     return PyErr_Format (PyExc_RuntimeError,
                         _("Could not find parameter `%s'."), arg);
 
-  if (! cmd->var)
+  if (!cmd->var.has_value ())
     return PyErr_Format (PyExc_RuntimeError,
                         _("`%s' is not a parameter."), arg);
-  return gdbpy_parameter_value (cmd->var_type, cmd->var);
+
+  return gdbpy_parameter_value (*cmd->var);
 }
 
 /* Wrapper for target_charset.  */
 
                                 const char *value)
 {
   struct packet_config *packet;
+  gdb_assert (c->var.has_value ());
 
   for (packet = remote_protocol_packets;
        packet < &remote_protocol_packets[PACKET_MAX];
        packet++)
     {
-      if (&packet->detect == c->var)
+      if (&packet->detect == &c->var->get<enum auto_boolean> ())
        {
          show_packet_config_cmd (packet);
          return;