diff options
author | Pedro Alves <palves@redhat.com> | 2017-09-04 20:21:15 +0100 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2017-09-04 20:21:15 +0100 |
commit | 858be34c5a03bb8973679ebf00d360182434dc00 (patch) | |
tree | f8f2ee3b71ccc4b20b8501a00b113975b4c48013 /gdb/testsuite | |
parent | dd5901a6a5bba75f3dee49f9a27640eedad90afe (diff) | |
download | binutils-gdb-858be34c5a03bb8973679ebf00d360182434dc00.tar.gz |
Handle "p S::method()::static_var" in the C++ parser
This commit makes "print S::method()::static_var" actually find the
debug symbol for static_var. Currently, you get:
(gdb) print S::method()::static_var
A syntax error in expression, near `'.
Quoting the whole string would seemingly work before the previous
patch that made GDB stop assuming int for no-debug-info variables:
(gdb) p 'S::method()::static_var'
$1 = 1
... except that's incorrect output, because:
(gdb) ptype 'S::method()::static_var'
type = <data variable, no debug info>
The way to make it work correctly currently is by quoting the
function/method part, like this:
(gdb) print 'S::method()'::static_var
$1 = {i1 = 1, i2 = 2, i3 = 3}
(gdb) ptype 'S::method()'::static_var
type = struct aggregate {
int i1;
int i2;
int i3;
}
At least after the "stop assuming int" patch, this is what we
now get:
(gdb) p 'S::method()::static_var'
'S::method()::static_var' has unknown type; cast it to its declared type
(gdb) p (struct aggregate) 'S::method()::static_var'
$1 = {i1 = 1, i2 = 2, i3 = 3}
However, IMO, users shouldn't really have to care about any of this.
GDB should Just Work, without quoting, IMO.
So here's a patch that implements support for that in the C++ parser.
With this patch, you now get:
(gdb) p S::method()::S_M_s_var_aggregate
$1 = {i1 = 1, i2 = 2, i3 = 3}
(gdb) ptype S::method()::S_M_s_var_aggregate
type = struct aggregate {
int i1;
int i2;
int i3;
}
gdb/ChangeLog:
2017-09-04 Pedro Alves <palves@redhat.com>
(%type <voidval>): Add function_method.
* c-exp.y (exp): New production for calls with no arguments.
(function_method, function_method_void_or_typelist): New
productions.
(exp): New production for "method()::static_var".
* eval.c (evaluate_subexp_standard): Handle OP_FUNC_STATIC_VAR.
* expprint.c (print_subexp_standard, dump_subexp_body_standard):
Handle OP_FUNC_STATIC_VAR.
* parse.c (operator_length_standard):
Handle OP_FUNC_STATIC_VAR.
* std-operator.def (OP_FUNC_STATIC_VAR): New.
gdb/testsuite/ChangeLog:
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.
Diffstat (limited to 'gdb/testsuite')
-rw-r--r-- | gdb/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gdb/testsuite/gdb.cp/local-static.c | 142 | ||||
-rw-r--r-- | gdb/testsuite/gdb.cp/local-static.cc | 1 | ||||
-rw-r--r-- | gdb/testsuite/gdb.cp/local-static.exp | 136 |
4 files changed, 285 insertions, 0 deletions
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 072423deb79..58ff7f3468a 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.c: New. + * gdb.base/local-static.cc: New. + * gdb.base/local-static.exp: New. + +2017-09-04 Pedro Alves <palves@redhat.com> + * gdb.asm/asm-source.exp: Add casts to int. * gdb.base/nodebug.c (dataglobal8, dataglobal32_1, dataglobal32_2) (dataglobal64_1, dataglobal64_2): New globals. diff --git a/gdb/testsuite/gdb.cp/local-static.c b/gdb/testsuite/gdb.cp/local-static.c new file mode 100644 index 00000000000..5bfff8d662d --- /dev/null +++ b/gdb/testsuite/gdb.cp/local-static.c @@ -0,0 +1,142 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2002-2017 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/>. */ + +struct aggregate +{ + int i1; + int i2; + int i3; +}; + +void keepalive_float (double *var) { } +void keepalive_int (int *var) { } +void keepalive_aggregate (struct aggregate *var) { } + +#define PREFIXIFY(PREFIX, VAR) \ + PREFIX ## _ ## VAR + +#define DEF_STATICS(PREFIX) \ + static int PREFIXIFY(PREFIX, s_var_int) = 4; \ + static double PREFIXIFY(PREFIX, s_var_float) = 3.14f; \ + static struct aggregate PREFIXIFY(PREFIX, s_var_aggregate) \ + = { 1, 2, 3 }; \ + \ + keepalive_int (&PREFIXIFY(PREFIX, s_var_int)); \ + keepalive_float (&PREFIXIFY(PREFIX, s_var_float)); \ + keepalive_aggregate (&PREFIXIFY(PREFIX, s_var_aggregate)); + +#ifdef __cplusplus + +struct S +{ + void inline_method () + { + DEF_STATICS (S_IM); + } + static void static_inline_method () + { + DEF_STATICS (S_SIM); + } + + void method (); + static void static_method (); +}; + +S s; + +void +S::method () +{ + DEF_STATICS (S_M); +} + +void +S::static_method () +{ + DEF_STATICS (S_SM); +} + +template <typename T> +struct S2 +{ + void method (); + static void static_method (); + + void inline_method () + { + DEF_STATICS (S2_IM); + } + + static void static_inline_method () + { + DEF_STATICS (S2_SIM); + } +}; + +template<typename T> +void +S2<T>::method () +{ + DEF_STATICS (S2_M); +} + +template<typename T> +void +S2<T>::static_method () +{ + DEF_STATICS (S2_SM); +} + +S2<int> s2; + +#endif + +void +free_func (void) +{ + DEF_STATICS (FF); +} + +static inline void +free_inline_func (void) +{ + DEF_STATICS (FIF); +} + +int +main () +{ + for (int i = 0; i < 1000; i++) + { + free_func (); + free_inline_func (); + +#ifdef __cplusplus + s.method (); + s.inline_method (); + S::static_method (); + S::static_inline_method (); + + s2.method (); + s2.inline_method (); + S2<int>::static_method (); + S2<int>::static_inline_method (); +#endif + } + + return 0; +} diff --git a/gdb/testsuite/gdb.cp/local-static.cc b/gdb/testsuite/gdb.cp/local-static.cc new file mode 100644 index 00000000000..f2bffbef3a9 --- /dev/null +++ b/gdb/testsuite/gdb.cp/local-static.cc @@ -0,0 +1 @@ +#include "local-static.c" diff --git a/gdb/testsuite/gdb.cp/local-static.exp b/gdb/testsuite/gdb.cp/local-static.exp new file mode 100644 index 00000000000..ba0c5ef13e5 --- /dev/null +++ b/gdb/testsuite/gdb.cp/local-static.exp @@ -0,0 +1,136 @@ +# Copyright 2017 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/>. + +# Tests for function local static variables, both C and C++. + +# This file is part of the gdb testsuite. + +standard_testfile .c + +# A list of scopes that have the static variables that we want to +# print. Each entry has, in order, the scope/function name, and the +# prefix used by the static variables. (The prefix exists to make it +# easier to debug the test if something goes wrong.) + + #SCOPE #PREFIX +set cxx_scopes_list { + {"S::method()" "S_M"} + {"S::static_method()" "S_SM"} + {"S::inline_method()" "S_IM"} + {"S::static_inline_method()" "S_SIM"} + {"S2<int>::method()" "S2_M"} + {"S2<int>::static_method()" "S2_SM"} + {"S2<int>::inline_method()" "S2_IM"} + {"S2<int>::static_inline_method()" "S2_SIM"} + {"free_func()" "FF"} + {"free_inline_func()" "FIF"} +} + +set c_scopes_list { + {"free_func" "FF"} + {"free_inline_func" "FIF"} +} + +# A list of all the static varibles defined in each scope. The first +# column is the name of the variable, without the prefix, and the +# second column is a regex matching what printing the variable should +# output. + + #VAR #PRINT +set vars_list { + {"s_var_int" " = 4"} + {"s_var_float" " = 3.14.*"} + {"s_var_aggregate" " = \\{i1 = 1, i2 = 2, i3 = 3\\}"} +} + +proc do_test {lang} { + global c_scopes_list + global cxx_scopes_list + global vars_list + global srcfile testfile + + set options {debug} + + if {$lang == "c++"} { + if { [skip_cplus_tests] } { + return + } + lappend options $lang + set src ${srcfile}c + } else { + set src ${srcfile} + } + + if {[prepare_for_testing "failed to prepare" $testfile-$lang \ + [list $src] $options]} { + return -1 + } + + if ![runto_main] then { + fail "couldn't run to breakpoint" + return + } + + gdb_test "show language" " currently [string_to_regexp $lang]\"\\." + + if {$lang == "c"} { + set scopes_list $c_scopes_list + } else { + set scopes_list $cxx_scopes_list + } + + # Print each variable using these syntaxes: + # + # 'func()'::var + # func()::var + + foreach scope_line $scopes_list { + set scope [lindex $scope_line 0] + set var_prefix [lindex $scope_line 1] + foreach var_line $vars_list { + set var [lindex $var_line 0] + set print_re [lindex $var_line 1] + + gdb_test "print '${scope}'::${var_prefix}_${var}" $print_re + gdb_test "print ${scope}::${var_prefix}_${var}" $print_re + } + } + + # Now run to each function, and print its variables using the + # localy-visible name. + foreach scope_line $scopes_list { + set scope [lindex $scope_line 0] + set var_prefix [lindex $scope_line 1] + + with_test_prefix "$scope" { + delete_breakpoints + gdb_breakpoint "$scope" + gdb_continue_to_breakpoint "$scope" + + foreach var_line $vars_list { + set var [lindex $var_line 0] + set print_re [lindex $var_line 1] + + gdb_test "print ${var_prefix}_${var}" $print_re + } + } + } +} + +foreach lang {"c" "c++"} { + with_test_prefix $lang { + do_test $lang + } +} |