This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[patch] Support C++11 rvalue (move constructor)
- From: Jan Kratochvil <jan dot kratochvil at redhat dot com>
- To: gdb-patches at sourceware dot org
- Date: Sat, 12 Oct 2013 17:28:36 +0200
- Subject: [patch] Support C++11 rvalue (move constructor)
- Authentication-results: sourceware.org; auth=none
Hi,
currently one cannot debug C++11 move constructors, one gets:
# in C::C (C &&o)
(gdb) print o
$1 = <unknown type in .../testsuite/gdb.cp/rvalue, CU 0x0, DIE 0x1f6c>
This fix is easy but it handles && rvalue reference like & lvalue reference.
Therefore there is a KFAIL in the testcase for it. I do not think GDB needs
to handle && differently - except for displaying && instead of &.
Implementing proper && into inferior type system means:
(1) Either add TYPE_CODE_RVALUE_REF besides TYPE_CODE_REF which is pretty
tedious - TYPE_CODE_REF is referenced in 155 GDB LoCs - due to missing
types virtualization. In almost all cases one will do:
- if (TYPE_CODE (t) == TYPE_CODE_REF)
+ if (TYPE_CODE (t) == TYPE_CODE_REF
+ || TYPE_CODE (t) == TYPE_CODE_RVALUE_REF)
or to add new main_type::flag_ref_is_rvalue valid only for TYPE_CODE_REF
but that is sure not a clean implementation.
(2) One would need to add type.rvalue_reference_type
(besides type.reference_type) to prevent leaks of types.
This would mean increasing the current sizeof (struct type) 40 -> 48.
The proper solution is to rather implement reference counting or garbage
collecting of types and merge struct type into struct main_type.
Anyway currently I find the patch below as a good enough hack as currently
I find it a bit blocker when using C++11.
Thanks,
Jan
gdb/
2013-10-12 Jan Kratochvil <jan.kratochvil@redhat.com>
PR c++/16043
* c-exp.y (ptr_operator): Handle also ANDAND as tp_reference.
* dwarf2read.c (process_die): Skip also DW_TAG_rvalue_reference_type.
(read_type_die_1): Handle also DW_TAG_rvalue_reference_type.
* gdbtypes.h (enum type_code): Extend comment for TYPE_CODE_REF.
(struct type): Extend comment for reference_type.
gdb/testsuite/
2013-10-12 Jan Kratochvil <jan.kratochvil@redhat.com>
* gdb.cp/rvalue.cc: New file.
* gdb.cp/rvalue.exp: New file.
diff --git a/gdb/c-exp.y b/gdb/c-exp.y
index 77713dd..653a5ad 100644
--- a/gdb/c-exp.y
+++ b/gdb/c-exp.y
@@ -1115,6 +1115,10 @@ ptr_operator:
{ insert_type (tp_reference); }
| '&' ptr_operator
{ insert_type (tp_reference); }
+ | ANDAND
+ { insert_type (tp_reference); }
+ | ANDAND ptr_operator
+ { insert_type (tp_reference); }
;
ptr_operator_ts: ptr_operator
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index aa109e0..47b1cb5 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -7990,6 +7990,7 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
case DW_TAG_pointer_type:
case DW_TAG_ptr_to_member_type:
case DW_TAG_reference_type:
+ case DW_TAG_rvalue_reference_type:
case DW_TAG_string_type:
break;
@@ -18010,6 +18011,7 @@ read_type_die_1 (struct die_info *die, struct dwarf2_cu *cu)
this_type = read_tag_ptr_to_member_type (die, cu);
break;
case DW_TAG_reference_type:
+ case DW_TAG_rvalue_reference_type:
this_type = read_tag_reference_type (die, cu);
break;
case DW_TAG_const_type:
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index 5e8d1e7..d5e2b7a 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -129,7 +129,8 @@ enum type_code
by the Itanium C++ ABI (used by GCC on all platforms). */
TYPE_CODE_MEMBERPTR,
- TYPE_CODE_REF, /* C++ Reference types */
+ TYPE_CODE_REF, /* C++ Reference types
+ (both lvalue & and rvalue &&) */
TYPE_CODE_CHAR, /* *real* character type */
@@ -657,7 +658,7 @@ struct type
struct type *pointer_type;
- /* C++: also need a reference type. */
+ /* C++: also need a reference type (both for lvalue & and rvalue &&). */
struct type *reference_type;
diff --git a/gdb/testsuite/gdb.cp/rvalue.cc b/gdb/testsuite/gdb.cp/rvalue.cc
new file mode 100644
index 0000000..7a78b97
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/rvalue.cc
@@ -0,0 +1,38 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2013 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 <http://www.gnu.org/licenses/>. */
+
+#include <memory>
+
+class C
+{
+public:
+ C () {}
+ C (C &&o);
+ int i = 42;
+};
+
+C::C (C &&o)
+{
+ i = o.i; /* o-is-ready */
+}
+
+int
+main()
+{
+ C a;
+ C b (std::move (a)); /* a-is-ready */
+}
diff --git a/gdb/testsuite/gdb.cp/rvalue.exp b/gdb/testsuite/gdb.cp/rvalue.exp
new file mode 100644
index 0000000..df3536b
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/rvalue.exp
@@ -0,0 +1,53 @@
+# Copyright 2013 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 <http://www.gnu.org/licenses/>.
+
+if { [skip_cplus_tests] } { continue }
+
+standard_testfile .cc
+
+if {[prepare_for_testing $testfile.exp $testfile \
+ $srcfile {debug c++ additional_flags=-std=c++11}]} {
+ return -1
+}
+
+if ![runto_main] {
+ retur -1
+}
+
+gdb_breakpoint [gdb_get_line_number "a-is-ready"]
+gdb_continue_to_breakpoint "a-is-ready" ".* a-is-ready .*"
+
+set test "print (struct C &&) a"
+gdb_test_multiple $test $test {
+ -re " = \\(C &&\\) @0x\[0-9a-f\]+: {i = 42}\r\n$gdb_prompt $" {
+ pass $test
+ }
+ -re " = \\(C &\\) @0x\[0-9a-f\]+: {i = 42}\r\n$gdb_prompt $" {
+ kfail c++/16043 $test
+ }
+}
+
+gdb_breakpoint [gdb_get_line_number "o-is-ready"]
+gdb_continue_to_breakpoint "o-is-ready" ".* o-is-ready .*"
+
+set test "print o"
+gdb_test_multiple $test $test {
+ -re " = \\(C &&\\) @0x\[0-9a-f\]+: {i = 42}\r\n$gdb_prompt $" {
+ pass $test
+ }
+ -re " = \\(C &\\) @0x\[0-9a-f\]+: {i = 42}\r\n$gdb_prompt $" {
+ kfail c++/16043 $test
+ }
+}