Based on the discussion at:
authorSergio Durigan Junior <sergiodj@redhat.com>
Mon, 16 Sep 2013 17:47:30 +0000 (17:47 +0000)
committerSergio Durigan Junior <sergiodj@redhat.com>
Mon, 16 Sep 2013 17:47:30 +0000 (17:47 +0000)
<https://sourceware.org/ml/gdb-patches/2013-09/msg00301.html>
<https://sourceware.org/ml/gdb-patches/2013-09/msg00383.html>

This patch adds a new convenience function called $_isvoid, whose
only purpose is to check whether an expression is void or not.
This became necessary because the new convenience variable
$_exitsignal (not yet approved) has a mutual exclusive behavior
with $_exitcode, i.e., when one is "defined" (i.e., non-void),
the other is cleared (i.e., becomes void).  Doug wanted a way to
identify which variable to use, and checking for voidness is the
obvious solution.

It is worth mentioning that my first attempt, after a conversation with
Doug, was to actually implement a new $_isdefined() convenience
function.  I would do that (for convenience variables) by calling
lookup_only_internalvar.  However, I found a few problems:

- Whenever I called $_isdefined ($variable), $variable became defined
  (with a void value), and $_isdefined always returned true.

- Then, I tried to implement $_isdefined ("variable"), and do the "$" +
  "variable" inside GDB, thus making it impossible for GDB to create the
  convenience variable.  However, it was hard to extract the string
  without having to mess with values and their idiossincrasies.
  Therefore, I decided to abandon this attempt (specially because I
  didn't want to spend too much time struggling with it).

Anyway, after talking to Doug again we decided that it would be easier
to implement $_isvoid, and this will probably help in cases like
<http://stackoverflow.com/questions/3744554/testing-if-a-gdb-convenience-variable-is-defined>.

I wrote a NEWS entry for it, and some new lines on the documentation.

gdb/
2013-09-16  Sergio Durigan Junior  <sergiodj@redhat.com>

* NEWS: Mention new convenience function $_isvoid.
* value.c (isvoid_internal_fn): New function.
(_initialize_values): Add new convenience function $_isvoid.

gdb/doc/
2013-09-16  Sergio Durigan Junior  <sergiodj@redhat.com>

* gdb.texinfo (Convenience Functions): Mention new convenience
function $_isvoid.

gdb/testsuite/
2013-09-16  Sergio Durigan Junior  <sergiodj@redhat.com>

* gdb.base/gdbvars.c (foo_void): New function.
(foo_int): Likewise.
* gdb.base/gdbvars.exp (test_convenience_functions): New
function.  Call it.

gdb/ChangeLog
gdb/NEWS
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.base/gdbvars.c
gdb/testsuite/gdb.base/gdbvars.exp
gdb/value.c

index b52ecb02c1b57dff7f092d0a552bbfb44d5e83b6..4885ccd4878762f37873cf2b3b885552cb347dd0 100644 (file)
@@ -1,3 +1,9 @@
+2013-09-16  Sergio Durigan Junior  <sergiodj@redhat.com>
+
+       * NEWS: Mention new convenience function $_isvoid.
+       * value.c (isvoid_internal_fn): New function.
+       (_initialize_values): Add new convenience function $_isvoid.
+
 2013-09-16  Pierre Muller  <muller@sourceware.org>
 
        * arm-linux-tdep.c: Add "elf/common.h" header.
index 5eb046b306dd32fc5ca8802d07897e08e01bda16..af06a2187a6bd7c802996f05d7959589607bff08 100644 (file)
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -3,6 +3,14 @@
 
 *** Changes since GDB 7.6
 
+* New convenience function "$_isvoid", to check whether an expression
+  is void.  A void expression is an expression where the type of the
+  result is "void".  For example, some convenience variables may be
+  "void" when evaluated (e.g., "$_exitcode" before the execution of
+  the program being debugged; or an undefined convenience variable).
+  Another example, when calling a function whose return type is
+  "void".
+
 * The "maintenance print objfiles" command now takes an optional regexp.
 
 * The "catch syscall" command now works on arm*-linux* targets.
index 3e07eaa3c321460816023730636eab12ee49bfe1..e183332fb9aef00abe82f4c511293f715fddf8ea 100644 (file)
@@ -1,3 +1,8 @@
+2013-09-16  Sergio Durigan Junior  <sergiodj@redhat.com>
+
+       * gdb.texinfo (Convenience Functions): Mention new convenience
+       function $_isvoid.
+
 2013-09-13  Andreas Arnez  <arnez@linux.vnet.ibm.com>
 
        * gdb.texinfo (Decimal Floating Point format): Mention S/390.
index a8c854e3745321de21893c9d805dc8c5abe47b48..65f63e4a9b7e897b3c2545b46a935249441caec4 100644 (file)
@@ -9800,6 +9800,69 @@ function can be used in an expression just like an ordinary function;
 however, a convenience function is implemented internally to
 @value{GDBN}.
 
+These functions do not require @value{GDBN} to be configured with
+@code{Python} support, which means that they are always available.
+
+@table @code
+
+@item $_isvoid (@var{expr})
+@findex $_isvoid@r{, convenience function}
+Return one if the expression @var{expr} is @code{void}.  Otherwise it
+returns zero.
+
+A @code{void} expression is an expression where the type of the result
+is @code{void}.  For example, you can examine a convenience variable
+(see @ref{Convenience Vars,, Convenience Variables}) to check whether
+it is @code{void}:
+
+@smallexample
+(@value{GDBP}) print $_exitcode
+$1 = void
+(@value{GDBP}) print $_isvoid ($_exitcode)
+$2 = 1
+(@value{GDBP}) run
+Starting program: ./a.out
+[Inferior 1 (process 29572) exited normally]
+(@value{GDBP}) print $_exitcode
+$3 = 0
+(@value{GDBP}) print $_isvoid ($_exitcode)
+$4 = 0
+@end smallexample
+
+In the example above, we used @code{$_isvoid} to check whether
+@code{$_exitcode} is @code{void} before and after the execution of the
+program being debugged.  Before the execution there is no exit code to
+be examined, therefore @code{$_exitcode} is @code{void}.  After the
+execution the program being debugged returned zero, therefore
+@code{$_exitcode} is zero, which means that it is not @code{void}
+anymore.
+
+The @code{void} expression can also be a call of a function from the
+program being debugged.  For example, given the following function:
+
+@smallexample
+void
+foo (void)
+@{
+@}
+@end smallexample
+
+The result of calling it inside @value{GDBN} is @code{void}:
+
+@smallexample
+(@value{GDBP}) print foo ()
+$1 = void
+(@value{GDBP}) print $_isvoid (foo ())
+$2 = 1
+(@value{GDBP}) set $v = foo ()
+(@value{GDBP}) print $v
+$3 = void
+(@value{GDBP}) print $_isvoid ($v)
+$4 = 1
+@end smallexample
+
+@end table
+
 These functions require @value{GDBN} to be configured with
 @code{Python} support.
 
index ae1c5d1c33771644370763a71c286014eb565b97..a9e830d46e044f26c518493582f8f868bbb02aa6 100644 (file)
@@ -1,3 +1,10 @@
+2013-09-16  Sergio Durigan Junior  <sergiodj@redhat.com>
+
+       * gdb.base/gdbvars.c (foo_void): New function.
+       (foo_int): Likewise.
+       * gdb.base/gdbvars.exp (test_convenience_functions): New
+       function.  Call it.
+
 2013-09-13  Andreas Arnez  <arnez@linux.vnet.ibm.com>
 
        * gdb.arch/s390-tdbregs.c: New file.
index aa3b4d831f93bc2682e838c46be7c27777ab635f..352a76b584f02dcb943b071eadcd3a57cd5111af 100644 (file)
@@ -4,6 +4,17 @@ typedef void *ptr;
 
 ptr p = &p;
 
+static void
+foo_void (void)
+{
+}
+
+static int
+foo_int (void)
+{
+  return 0;
+}
+
 int
 main ()
 {
index 23a6758bcaeca6e1908157fc4c5fc3ec813bcc76..85aaca040d80c5b28b2d67a8bc64c98a03f594f9 100644 (file)
@@ -54,6 +54,34 @@ proc test_convenience_variables {} {
        "Print contents of uninitialized convenience variable"
 }
 
+proc test_convenience_functions {} {
+    gdb_test "print \$_isvoid" " = <internal function _isvoid>" \
+       "Print internal function \$_isvoid"
+
+    gdb_test "print \$isvoid_foo" " = void" \
+       "Print void convenience variable"
+
+    gdb_test "print \$_isvoid (\$isvoid_foo)" " = 1" \
+       "Check whether void convenience variable is void"
+
+    gdb_test_no_output "set \$isvoid_foo = 1" \
+       "Set void convenience variable to 1"
+
+    gdb_test "print \$_isvoid (\$isvoid_foo)" " = 0" \
+       "Check whether non-void convenience variable is void"
+
+    # For the next test, we need the inferior to be running.
+    if { ![runto_main] } {
+       return -1
+    }
+
+    gdb_test "print \$_isvoid (foo_void ())" " = 1" \
+       "Check whether void function is void"
+
+    gdb_test "print \$_isvoid (foo_int ())" " = 0" \
+       "Check whether non-void function is void"
+}
+
 proc test_value_history {} {
     global gdb_prompt
 
@@ -114,4 +142,5 @@ gdb_test_no_output "set print sevenbit-strings"
 
 test_value_history
 test_convenience_variables
+test_convenience_functions
 test_with_program
index 42a8d2fe4b5ed3cc18ec5389bb1d5379b98aacec..edbfc70fcc8105e818b1f6f8304f0c39ab73d888 100644 (file)
@@ -3584,6 +3584,23 @@ value_fetch_lazy (struct value *val)
   return 0;
 }
 
+/* Implementation of the convenience function $_isvoid.  */
+
+static struct value *
+isvoid_internal_fn (struct gdbarch *gdbarch,
+                   const struct language_defn *language,
+                   void *cookie, int argc, struct value **argv)
+{
+  int ret;
+
+  if (argc != 1)
+    error (_("You must provide one parameter for $_isvoid."));
+
+  ret = TYPE_CODE (value_type (argv[0])) == TYPE_CODE_VOID;
+
+  return value_from_longest (builtin_type (gdbarch)->builtin_int, ret);
+}
+
 void
 _initialize_values (void)
 {
@@ -3616,4 +3633,10 @@ VARIABLE is already initialized."));
   add_prefix_cmd ("function", no_class, function_command, _("\
 Placeholder command for showing help on convenience functions."),
                  &functionlist, "function ", 0, &cmdlist);
+
+  add_internal_function ("_isvoid", _("\
+Check whether an expression is void.\n\
+Usage: $_isvoid (expression)\n\
+Return 1 if the expression is void, zero otherwise."),
+                        isvoid_internal_fn, NULL);
 }