summaryrefslogtreecommitdiff
path: root/gdb/testsuite
diff options
context:
space:
mode:
authorPedro Alves <palves@redhat.com>2017-09-04 20:21:16 +0100
committerPedro Alves <palves@redhat.com>2017-09-04 20:21:16 +0100
commite68cb8e00166d2f8a9e23c60f68bec04ef0a90f0 (patch)
treee48a76cc097b0c54ae9dd04badc39302ad7e2882 /gdb/testsuite
parent858be34c5a03bb8973679ebf00d360182434dc00 (diff)
downloadbinutils-gdb-e68cb8e00166d2f8a9e23c60f68bec04ef0a90f0.tar.gz
Handle "p 'S::method()::static_var'" (quoted) in symbol lookup
While the previous commit made "p method()::static_var" (no single-quotes) Just Work, if users (or frontends) try wrapping the expression with quotes, they'll get: (gdb) p 'S::method()::static_var' 'S::method()::static_var' has unknown type; cast it to its declared type even if we _do_ have debug info for that variable. That's better than the bogus/confusing value what GDB would print before the stop-assuming-int patch: (gdb) p 'S::method()::static_var' $1 = 1 but I think it'd still be nice to make this case Just Work too. In this case, due to the quoting, the C/C++ parser (c-exp.y) interprets the whole expression/string as a single symbol name, and we end up calling lookup_symbol on that name. There's no debug symbol with that fully-qualified name, but since the compiler gives the static variable a mangled linkage name exactly like the above, it appears in the mininal symbols: $ nm -A local-static | c++filt | grep static_var local-static:0000000000601040 d S::method()::static_var ... and that's what GDB happens to find/print. This only happens in C++, note, since for C the compiler uses different linkage names: local-static-c:0000000000601040 d static_var.1848 So while (in C++, not C) function local static variables are given a mangled name that demangles to the same syntax that GDB documents/expects as the way to access function local statics, there's no global symbol in the debug info with that name at all. The debug info for a static local variable for a non-inline function looks like this: <1><2a1>: Abbrev Number: 19 (DW_TAG_subprogram) ... <2><2f7>: Abbrev Number: 20 (DW_TAG_variable) <2f8> DW_AT_name : (indirect string, offset: 0x4e9): static_var <2fc> DW_AT_decl_file : 1 <2fd> DW_AT_decl_line : 64 <2fe> DW_AT_type : <0x25> <302> DW_AT_location : 9 byte block: 3 40 10 60 0 0 0 0 0 (DW_OP_addr: 601040) and for an inline function, it looks like this (linkage name run through c++filt for convenience): <2><21b>: Abbrev Number: 16 (DW_TAG_variable) <21c> DW_AT_name : (indirect string, offset: 0x21a): static_var <220> DW_AT_decl_file : 1 <221> DW_AT_decl_line : 48 <222> DW_AT_linkage_name: (indirect string, offset: 0x200): S::inline_method()::static_var <226> DW_AT_type : <0x25> <22a> DW_AT_external : 1 <22a> DW_AT_location : 9 byte block: 3 a0 10 60 0 0 0 0 0 (DW_OP_addr: 6010a0) (The inline case makes the variable external so that the linker can merge the different inlined copies. It seems like GCC never outputs the linkage name for non-extern globals.) When we read the DWARF, we record the static_var variable as a regular variable of the containing function's block. This makes stopping in the function and printing the variable as usual. The variable just so happens to have a memory address as location. So one way to make "p 'S::method()::static_var'" work would be to record _two_ copies of the symbols for these variables. One in the function's scope/block, with "static_var" as name, as we currently do, and another in the static or global blocks (depending on whether the symbol is external), with a fully-qualified name. I wrote a prototype patch for that, and it works. For the non-inline case above, since the debug info doesn't point to the linkage same, that patch built the physname of the static local variable as the concat of the physname of the containing function, plus "::", plus the variable's name. We could make that approach work for C too, though it kind of feels awkward to record fake symbol names like that in C. The other approach I tried is to change the C++ symbol lookup routines instead. This is the approach this commit takes. We can already lookup up symbol in namespaces and classes, so this feels like a good fit, and was easy enough. The advantage is that this doesn't require recording extra symbols. The test in gdb.cp/m-static.exp that exposed the need for this is removed, since the same functionality is now covered by gdb.cp/local-static.exp. gdb/ChangeLog: 2017-09-04 Pedro Alves <palves@redhat.com> * cp-namespace.c (cp_search_static_and_baseclasses): Handle function/method scopes; lookup the nested name as a function local static variable. gdb/testsuite/ChangeLog: 2017-09-04 Pedro Alves <palves@redhat.com> * gdb.base/local-static.exp: Also test with class::method::variable wholly quoted. * gdb.cp/m-static.exp (class::method::variable): Remove test.
Diffstat (limited to 'gdb/testsuite')
-rw-r--r--gdb/testsuite/ChangeLog6
-rw-r--r--gdb/testsuite/gdb.cp/local-static.exp12
-rw-r--r--gdb/testsuite/gdb.cp/m-static.exp5
3 files changed, 18 insertions, 5 deletions
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 58ff7f3468a..ddea68bd53e 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,11 @@
2017-09-04 Pedro Alves <palves@redhat.com>
+ * gdb.base/local-static.exp: Also test with
+ class::method::variable wholly quoted.
+ * gdb.cp/m-static.exp (class::method::variable): Remove test.
+
+2017-09-04 Pedro Alves <palves@redhat.com>
+
* gdb.base/local-static.c: New.
* gdb.base/local-static.cc: New.
* gdb.base/local-static.exp: New.
diff --git a/gdb/testsuite/gdb.cp/local-static.exp b/gdb/testsuite/gdb.cp/local-static.exp
index ba0c5ef13e5..581efa396aa 100644
--- a/gdb/testsuite/gdb.cp/local-static.exp
+++ b/gdb/testsuite/gdb.cp/local-static.exp
@@ -95,6 +95,11 @@ proc do_test {lang} {
#
# 'func()'::var
# func()::var
+ # 'func()::var'
+ #
+ # In C++, the latter case makes sure that symbol lookup finds the
+ # debug symbol instead of the minimal symbol with that exact same
+ # name.
foreach scope_line $scopes_list {
set scope [lindex $scope_line 0]
@@ -105,6 +110,13 @@ proc do_test {lang} {
gdb_test "print '${scope}'::${var_prefix}_${var}" $print_re
gdb_test "print ${scope}::${var_prefix}_${var}" $print_re
+
+ set sym "${scope}::${var_prefix}_${var}"
+ if {$lang == "c++"} {
+ gdb_test "print '${sym}'" $print_re
+ } else {
+ gdb_test "print '${sym}'" "No symbol \"$sym\" in current context\\."
+ }
}
}
diff --git a/gdb/testsuite/gdb.cp/m-static.exp b/gdb/testsuite/gdb.cp/m-static.exp
index eeb88e978fb..10239a3b751 100644
--- a/gdb/testsuite/gdb.cp/m-static.exp
+++ b/gdb/testsuite/gdb.cp/m-static.exp
@@ -52,11 +52,6 @@ gdb_continue_to_breakpoint "end of constructors"
# One.
-# simple object, static const int, accessing via 'class::method::variable'
-# Regression test for PR c++/15203 and PR c++/15210
-gdb_test "print (int) 'gnu_obj_1::method()::sintvar'" "\\$\[0-9\]+ = 4" \
- "simple object, static int, accessing via 'class::method::variable'"
-
# simple object, static const bool
gdb_test "print test1.test" "\\$\[0-9\]* = true" "simple object, static const bool"