Fix infinite recursion when printing static member with typedef

The original problem was fixed (see related PR 22242). But using a typedef
as the declared type for a static member variable, as commented in this PR,
is still causing gdb to get into infinite loop when printing the static
member's value. This problem can be reproduced as follows:

% cat t.cc
class A {
    typedef A type;
public:
    bool operator==(const type& other) { return true; }

    static const type INSTANCE;
};

const A A::INSTANCE;

int main() {
    A a;
    if (a == A::INSTANCE) {
        return -1;
    }
    return 0;
}
% g++ -g t.cc
% gdb -ex "start" -ex "p a" a.out

The fix is rather trivial - in cp_print_static_field(), should call
check_typedef() to get the static member's real type and use it to
check whether it's a struct or an array.

As Simon suggested, I've added a new test case to the testsuite
and am passing the original type, not the real type, as argument
to both cp_print_value_fields() and val_print().

Re-tested on both aarch64-linux-gnu and amd64-linux-gnu. No regressions.
This commit is contained in:
Weimin Pan 2018-03-28 13:23:48 -06:00
parent 3d6b3b8221
commit 79f1873171
5 changed files with 105 additions and 3 deletions

View File

@ -1,3 +1,9 @@
2018-03-30 Weimin Pan <weimin.pan@oracle.com>
PR gdb/16959
* cp-valprint.c: (cp_print_static_field) Fix infinite recursion when
printing static type.
2018-04-01 Tom Tromey <tom@tromey.com>
* rs6000-nat.c (rs6000_ptrace_ldinfo): Return a byte_vector.
@ -7,6 +13,13 @@
* common/gdb_vecs.h (char_ptr): Remove.
* tracepoint.c (encode_actions_1): Remove usage of char_ptr.
=======
2018-03-30 Weimin Pan <weimin.pan@oracle.com>
PR gdb/16959
* cp-valprint.c: (cp_print_static_field) Fix infinite recursion when
printing static type.
>>>>>>> Fix infinite recursion when printing static member with typedef
2018-03-30 Simon Marchi <simon.marchi@polymtl.ca>
@ -2079,6 +2092,13 @@
* rs6000-tdep.c (ppc_insns_match_pattern): Make pattern const.
Correct insns description.
* ppc-tdep.h (ppc_insns_match_pattern): Update prototype.
=======
2018-02-07 Weimin Pan <weimin.pan@oracle.com>
PR gdb/16959
* cp-valprint.c: (cp_print_static_field) Fix infinite recursion when
printing static type.
>>>>>>> Fix infinite recursion when printing static member with typedef
2018-01-24 Pedro Alves <palves@redhat.com>

View File

@ -633,7 +633,8 @@ cp_print_static_field (struct type *type,
return;
}
if (TYPE_CODE (type) == TYPE_CODE_STRUCT)
struct type *real_type = check_typedef (type);
if (TYPE_CODE (real_type) == TYPE_CODE_STRUCT)
{
CORE_ADDR *first_dont_print;
CORE_ADDR addr;
@ -658,7 +659,6 @@ cp_print_static_field (struct type *type,
addr = value_address (val);
obstack_grow (&dont_print_statmem_obstack, (char *) &addr,
sizeof (CORE_ADDR));
type = check_typedef (type);
cp_print_value_fields (type, value_enclosing_type (val),
value_embedded_offset (val), addr,
stream, recurse, val,
@ -666,7 +666,7 @@ cp_print_static_field (struct type *type,
return;
}
if (TYPE_CODE (type) == TYPE_CODE_ARRAY)
if (TYPE_CODE (real_type) == TYPE_CODE_ARRAY)
{
struct type **first_dont_print;
int i;

View File

@ -1,3 +1,8 @@
2018-03-30 Weimin Pan <weimin.pan@oracle.com>
* gdb.cp/static-typedef-print.exp: New file.
* gdb.cp/static-typedef-print.cc: New file.
2018-03-27 Joel Brobecker <brobecker@adacore.com>
* gdb.ada/varsize_limit: New testcase.
@ -298,6 +303,12 @@
on break.c:47 was actually inserted when debugging the version
compiled at -O2 and use it in the expected output of the "info
break" test performed soon after.
=======
2018-03-20 Weimin Pan <weimin.pan@oracle.com>
* gdb.cp/static-typedef-print.exp: New file.
* gdb.cp/static-typedef-print.cc: New file.
>>>>>>> Fix infinite recursion when printing static member with typedef
2018-01-22 Pedro Alves <palves@redhat.com>
Sergio Durigan Junior <sergiodj@redhat.com>

View File

@ -0,0 +1,34 @@
/* This testcase is part of GDB, the GNU debugger.
Copyright 2018 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/>. */
class A {
typedef A type;
public:
bool operator==(const type& other) { return true; }
static const type INSTANCE;
};
const A A::INSTANCE = {};
int main() {
A a;
if (a == A::INSTANCE) {
return -1;
}
return 0;
}

View File

@ -0,0 +1,37 @@
# Copyright 2018 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 [get_compiler_info "c++"] {
return -1
}
if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug c++}]} {
return -1
}
clean_restart $testfile
if ![runto_main] {
untested "could not run to main"
return -1
}
gdb_test "print a" \
"static INSTANCE = <same as static member of an already seen type>}}.*" \
"print static member"