diff --git a/gdb/NEWS b/gdb/NEWS
index edcc9c951a0..6d700d1cf32 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -10,6 +10,9 @@
* Support for Pointer Authentication on AArch64 Linux.
+* Two new convernience functions $_cimag and $_creal that extract the
+ imaginary and real parts respectively from complex numbers.
+
*** Changes in GDB 8.3
* GDB and GDBserver now support access to additional registers on
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 4c1d5e8294f..6dda71d83c0 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -11390,6 +11390,17 @@
Visiting node of type NODE_INTEGER
@end smallexample
+@item $_cimag(@var{value})
+@item $_creal(@var{value})
+@findex $_cimag@r{, convenience function}
+@findex $_creal@r{, convenience function}
+Return the imaginary (@code{$_cimag}) or real (@code{$_creal}) part of
+the complex number @var{value}.
+
+The type of the imaginary or real part depends on the type of the
+complex number, e.g., using @code{$_cimag} on a @code{float complex}
+will return an imaginary part of type @code{float}.
+
@end table
@value{GDBN} provides the ability to list and get help on
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 658c86264bf..e742931ad53 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -17530,6 +17530,40 @@ dwarf2_init_integer_type (struct dwarf2_cu *cu, struct objfile *objfile,
return type;
}
+/* Initialise and return a floating point type of size BITS suitable for
+ use as a component of a complex number. The NAME_HINT is passed through
+ when initialising the floating point type and is the name of the complex
+ type.
+
+ As DWARF doesn't currently provide an explicit name for the components
+ of a complex number, but it can be helpful to have these components
+ named, we try to select a suitable name based on the size of the
+ component. */
+static struct type *
+dwarf2_init_complex_target_type (struct dwarf2_cu *cu,
+ struct objfile *objfile,
+ int bits, const char *name_hint)
+{
+ gdbarch *gdbarch = get_objfile_arch (objfile);
+ struct type *tt = nullptr;
+
+ switch (bits)
+ {
+ case 32:
+ tt = builtin_type (gdbarch)->builtin_float;
+ break;
+ case 64:
+ tt = builtin_type (gdbarch)->builtin_double;
+ break;
+ case 128:
+ tt = builtin_type (gdbarch)->builtin_long_double;
+ break;
+ }
+
+ const char *name = (tt == nullptr) ? nullptr : TYPE_NAME (tt);
+ return dwarf2_init_float_type (objfile, bits, name, name_hint);
+}
+
/* Find a representation of a given base type and install
it in the TYPE field of the die. */
@@ -17569,7 +17603,7 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
type = init_boolean_type (objfile, bits, 1, name);
break;
case DW_ATE_complex_float:
- type = dwarf2_init_float_type (objfile, bits / 2, NULL, name);
+ type = dwarf2_init_complex_target_type (cu, objfile, bits / 2, name);
type = init_complex_type (objfile, name, type);
break;
case DW_ATE_decimal_float:
diff --git a/gdb/testsuite/gdb.base/complex-parts.c b/gdb/testsuite/gdb.base/complex-parts.c
new file mode 100644
index 00000000000..243caee0695
--- /dev/null
+++ b/gdb/testsuite/gdb.base/complex-parts.c
@@ -0,0 +1,50 @@
+/* Copyright 2019 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see . */
+
+/* Unlike the other 'complex.c' test, this one uses the "standard" header
+ file to pull in the complex types. The testing is around printing the
+ complex numbers, and using the convenience function $_cimag and $_creal
+ to extract the parts of the complex numbers. */
+
+#include
+
+void
+keep_around (volatile void *ptr)
+{
+ asm ("" ::: "memory");
+}
+
+int
+main (void)
+{
+ double complex z1 = 1.5 + 4.5 * I;
+ float complex z2 = 2.5 - 5.5 * I;
+ long double complex z3 = 3.5 + 6.5 * I;
+
+ double d1 = 1.5;
+ float f1 = 2.5;
+ int i1 = 3;
+
+ keep_around (&z1);
+ keep_around (&z2);
+ keep_around (&z3);
+ keep_around (&d1);
+ keep_around (&f1);
+ keep_around (&i1);
+
+ return 0; /* Break Here. */
+}
diff --git a/gdb/testsuite/gdb.base/complex-parts.exp b/gdb/testsuite/gdb.base/complex-parts.exp
new file mode 100644
index 00000000000..ce8f4277a8b
--- /dev/null
+++ b/gdb/testsuite/gdb.base/complex-parts.exp
@@ -0,0 +1,62 @@
+# Copyright 2019 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+standard_testfile
+
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile debug]} {
+ return -1
+}
+
+if { ![runto_main] } then {
+ fail "can't run to main"
+ return 0
+}
+
+gdb_breakpoint [gdb_get_line_number "Break Here"]
+gdb_continue_to_breakpoint "breakpt" ".* Break Here\\. .*"
+
+gdb_test "p z1" " = 1.5 \\+ 4.5 \\* I"
+gdb_test "p z2" " = 2.5 \\+ -5.5 \\* I"
+gdb_test "p z3" " = 3.5 \\+ 6.5 \\* I"
+
+gdb_test "ptype z1" " = complex double"
+gdb_test "ptype z2" " = complex float"
+gdb_test "ptype z3" " = complex long double"
+
+gdb_test "p \$_cimag (z1)" " = 4.5"
+gdb_test "ptype \$" " = double"
+
+gdb_test "p \$_cimag (z2)" " = -5.5"
+gdb_test "ptype \$" " = float"
+
+gdb_test "p \$_cimag (z3)" " = 6.5"
+gdb_test "ptype \$" " = long double"
+
+gdb_test "p \$_creal (z1)" " = 1.5"
+gdb_test "ptype \$" " = double"
+
+gdb_test "p \$_creal (z2)" " = 2.5"
+gdb_test "ptype \$" " = float"
+
+gdb_test "p \$_creal (z3)" " = 3.5"
+gdb_test "ptype \$" " = long double"
+
+gdb_test "p \$_cimag (d1)" "expected a complex number"
+gdb_test "p \$_cimag (f1)" "expected a complex number"
+gdb_test "p \$_cimag (i1)" "expected a complex number"
+
+gdb_test "p \$_creal (d1)" "expected a complex number"
+gdb_test "p \$_creal (f1)" "expected a complex number"
+gdb_test "p \$_creal (i1)" "expected a complex number"
diff --git a/gdb/testsuite/gdb.base/default.exp b/gdb/testsuite/gdb.base/default.exp
index ece1428e617..bdae0d471e7 100644
--- a/gdb/testsuite/gdb.base/default.exp
+++ b/gdb/testsuite/gdb.base/default.exp
@@ -601,6 +601,8 @@ set show_conv_list \
{$_probe_arg9 = } \
{$_probe_arg10 = } \
{$_probe_arg11 = } \
+ {$_cimag = } \
+ {$_creal = } \
{$_isvoid = } \
}
if ![skip_python_tests] {
diff --git a/gdb/value.c b/gdb/value.c
index dc297dfe0f9..d011b396986 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -3933,6 +3933,44 @@ isvoid_internal_fn (struct gdbarch *gdbarch,
return value_from_longest (builtin_type (gdbarch)->builtin_int, ret);
}
+/* Implementation of the convenience function $_cimag. Extracts the
+ real part from a complex number. */
+
+static struct value *
+creal_internal_fn (struct gdbarch *gdbarch,
+ const struct language_defn *language,
+ void *cookie, int argc, struct value **argv)
+{
+ if (argc != 1)
+ error (_("You must provide one argument for $_creal."));
+
+ value *cval = argv[0];
+ type *ctype = check_typedef (value_type (cval));
+ if (TYPE_CODE (ctype) != TYPE_CODE_COMPLEX)
+ error (_("expected a complex number"));
+ return value_from_component (cval, TYPE_TARGET_TYPE (ctype), 0);
+}
+
+/* Implementation of the convenience function $_cimag. Extracts the
+ imaginary part from a complex number. */
+
+static struct value *
+cimag_internal_fn (struct gdbarch *gdbarch,
+ const struct language_defn *language,
+ void *cookie, int argc,
+ struct value **argv)
+{
+ if (argc != 1)
+ error (_("You must provide one argument for $_cimag."));
+
+ value *cval = argv[0];
+ type *ctype = check_typedef (value_type (cval));
+ if (TYPE_CODE (ctype) != TYPE_CODE_COMPLEX)
+ error (_("expected a complex number"));
+ return value_from_component (cval, TYPE_TARGET_TYPE (ctype),
+ TYPE_LENGTH (TYPE_TARGET_TYPE (ctype)));
+}
+
#if GDB_SELF_TEST
namespace selftests
{
@@ -4114,6 +4152,20 @@ Usage: $_isvoid (expression)\n\
Return 1 if the expression is void, zero otherwise."),
isvoid_internal_fn, NULL);
+ add_internal_function ("_creal", _("\
+Extract the real part of a complex number.\n\
+Usage: $_creal (expression)\n\
+Return the real part of a complex number, the type depends on the\n\
+type of a complex number."),
+ creal_internal_fn, NULL);
+
+ add_internal_function ("_cimag", _("\
+Extract the imaginary part of a complex number.\n\
+Usage: $_cimag (expression)\n\
+Return the imaginary part of a complex number, the type depends on the\n\
+type of a complex number."),
+ cimag_internal_fn, NULL);
+
add_setshow_zuinteger_unlimited_cmd ("max-value-size",
class_support, &max_value_size, _("\
Set maximum sized value gdb will load from the inferior."), _("\