aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPedro Alves <pedro@palves.net>2022-04-29 23:21:18 +0100
committerPedro Alves <pedro@palves.net>2022-05-10 14:16:21 +0100
commitc7d029ea9cc566b8d3c50b08ef12d98394adf1b1 (patch)
treeb764ed0b4568b7b62539f699a1549a452b8d1760
parent1c6fbf42e5bd3045a41ad32c5efbc2ab8ca5e941 (diff)
downloadgdb-c7d029ea9cc566b8d3c50b08ef12d98394adf1b1.zip
gdb-c7d029ea9cc566b8d3c50b08ef12d98394adf1b1.tar.gz
gdb-c7d029ea9cc566b8d3c50b08ef12d98394adf1b1.tar.bz2
Fix "b f(std::string)" when current language is C
If you try to set a breakpoint at a function such as "b f(std::string)", and the current language is C, the breakpoint fails to be set, like so: (gdb) set language c break f(std::string) Function "f(std::string)" not defined. Make breakpoint pending on future shared library load? (y or [n]) n (gdb) The problem is that the code in GDB that expands the std::string typedef hits this in c-typeprint.c: /* If we have "typedef struct foo {. . .} bar;" do we want to print it as "struct foo" or as "bar"? Pick the latter for C++, because C++ folk tend to expect things like "class5 *foo" rather than "struct class5 *foo". We rather arbitrarily choose to make language_minimal work in a C-like way. */ if (language == language_c || language == language_minimal) { if (type->code () == TYPE_CODE_UNION) gdb_printf (stream, "union "); else if (type->code () == TYPE_CODE_STRUCT) { if (type->is_declared_class ()) gdb_printf (stream, "class "); else gdb_printf (stream, "struct "); } else if (type->code () == TYPE_CODE_ENUM) gdb_printf (stream, "enum "); } I.e., std::string is expanded to "class std::..." instead of just "std::...", and then the "f(class std::..." symbol doesn't exist. Fix this by making cp-support.c:inspect_type print the expanded typedef type using the language of the symbol whose type we're expanding the typedefs for -- in the example in question, the "std::string" typedef symbol, which is a C++ symbol. Use type_print_raw_options as it seems to me that in this scenario we always want raw types, to match the real symbol names. Adjust the gdb.cp/break-f-std-string.exp testcase to try setting a breakpoint at "f(std::string)" in both C and C++. Change-Id: Ib54fab4cf0fd307bfd55bf1dd5056830096a653b
-rw-r--r--gdb/cp-support.c10
-rw-r--r--gdb/testsuite/gdb.cp/break-f-std-string.exp13
2 files changed, 19 insertions, 4 deletions
diff --git a/gdb/cp-support.c b/gdb/cp-support.c
index 71c1463..807c944 100644
--- a/gdb/cp-support.c
+++ b/gdb/cp-support.c
@@ -41,6 +41,7 @@
#include <atomic>
#include "event-top.h"
#include "run-on-main-thread.h"
+#include "typeprint.h"
#define d_left(dc) (dc)->u.s_binary.left
#define d_right(dc) (dc)->u.s_binary.right
@@ -229,7 +230,14 @@ inspect_type (struct demangle_parse_info *info,
string_file buf;
try
{
- type_print (type, "", &buf, -1);
+ /* Avoid using the current language. If the language is
+ C, and TYPE is a struct/class, the printed type is
+ prefixed with "struct " or "class ", which we don't
+ want when we're expanding a C++ typedef. Print using
+ the type symbol's language to expand a C++ typedef
+ the C++ way even if the current language is C. */
+ const language_defn *lang = language_def (sym->language ());
+ lang->print_type (type, "", &buf, -1, 0, &type_print_raw_options);
}
/* If type_print threw an exception, there is little point
in continuing, so just bow out gracefully. */
diff --git a/gdb/testsuite/gdb.cp/break-f-std-string.exp b/gdb/testsuite/gdb.cp/break-f-std-string.exp
index 0869912..e222bae 100644
--- a/gdb/testsuite/gdb.cp/break-f-std-string.exp
+++ b/gdb/testsuite/gdb.cp/break-f-std-string.exp
@@ -93,10 +93,17 @@ proc test {cxx11_abi} {
}
}
- gdb_test "break f($type)" "$srcfile, line $::decimal\\."
+ # GDB should be able to expand the std::string typedef in the
+ # function prototype using C++ logic even if the current language
+ # is C.
+ foreach_with_prefix lang {"c" "c++"} {
+ gdb_test_no_output "set language $lang"
- if { $realtype != "" } {
- gdb_test "break f($realtype)" "$srcfile, line $::decimal\\."
+ gdb_test "break f($type)" "$srcfile, line $::decimal\\."
+
+ if { $realtype != "" } {
+ gdb_test "break f($realtype)" "$srcfile, line $::decimal\\."
+ }
}
}