mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-12-03 04:12:10 +08:00
fix PR 17106
This fixes PR 17106, a regression in printing. The bug is that resolve_dynamic_type follows struct members and references, but doesn't consider the possibility of infinite recursion. This patch fixes the problem by limiting reference following to the topmost layer of calls -- that is, reference-typed struct members are never considered as being VLAs. Built and regtested on x86-64 Fedora 20. New test case included. 2014-07-14 Tom Tromey <tromey@redhat.com> PR exp/17106: * gdbtypes.c (is_dynamic_type_internal): New function, from is_dynamic_type. (is_dynamic_type): Rewrite. (resolve_dynamic_union): Use resolve_dynamic_type_internal. (resolve_dynamic_struct): Likewise. (resolve_dynamic_type_internal): New function, from resolve_dynamic_type. (resolve_dynamic_type): Rewrite. 2014-07-14 Tom Tromey <tromey@redhat.com> * gdb.cp/vla-cxx.cc: New file. * gdb.cp/vla-cxx.exp: New file.
This commit is contained in:
parent
548740d6bd
commit
d98b7a16a9
@ -1,3 +1,15 @@
|
||||
2014-07-14 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
PR exp/17106:
|
||||
* gdbtypes.c (is_dynamic_type_internal): New function, from
|
||||
is_dynamic_type.
|
||||
(is_dynamic_type): Rewrite.
|
||||
(resolve_dynamic_union): Use resolve_dynamic_type_internal.
|
||||
(resolve_dynamic_struct): Likewise.
|
||||
(resolve_dynamic_type_internal): New function, from
|
||||
resolve_dynamic_type.
|
||||
(resolve_dynamic_type): Rewrite.
|
||||
|
||||
2014-07-14 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
* target.c (target_require_runnable): Also check record_stratum.
|
||||
|
@ -1611,14 +1611,15 @@ stub_noname_complaint (void)
|
||||
complaint (&symfile_complaints, _("stub type has NULL name"));
|
||||
}
|
||||
|
||||
/* See gdbtypes.h. */
|
||||
/* Worker for is_dynamic_type. */
|
||||
|
||||
int
|
||||
is_dynamic_type (struct type *type)
|
||||
static int
|
||||
is_dynamic_type_internal (struct type *type, int top_level)
|
||||
{
|
||||
type = check_typedef (type);
|
||||
|
||||
if (TYPE_CODE (type) == TYPE_CODE_REF)
|
||||
/* We only want to recognize references at the outermost level. */
|
||||
if (top_level && TYPE_CODE (type) == TYPE_CODE_REF)
|
||||
type = check_typedef (TYPE_TARGET_TYPE (type));
|
||||
|
||||
switch (TYPE_CODE (type))
|
||||
@ -1632,9 +1633,9 @@ is_dynamic_type (struct type *type)
|
||||
|
||||
/* The array is dynamic if either the bounds are dynamic,
|
||||
or the elements it contains have a dynamic contents. */
|
||||
if (is_dynamic_type (TYPE_INDEX_TYPE (type)))
|
||||
if (is_dynamic_type_internal (TYPE_INDEX_TYPE (type), 0))
|
||||
return 1;
|
||||
return is_dynamic_type (TYPE_TARGET_TYPE (type));
|
||||
return is_dynamic_type_internal (TYPE_TARGET_TYPE (type), 0);
|
||||
}
|
||||
|
||||
case TYPE_CODE_STRUCT:
|
||||
@ -1644,7 +1645,7 @@ is_dynamic_type (struct type *type)
|
||||
|
||||
for (i = 0; i < TYPE_NFIELDS (type); ++i)
|
||||
if (!field_is_static (&TYPE_FIELD (type, i))
|
||||
&& is_dynamic_type (TYPE_FIELD_TYPE (type, i)))
|
||||
&& is_dynamic_type_internal (TYPE_FIELD_TYPE (type, i), 0))
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
@ -1653,6 +1654,18 @@ is_dynamic_type (struct type *type)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* See gdbtypes.h. */
|
||||
|
||||
int
|
||||
is_dynamic_type (struct type *type)
|
||||
{
|
||||
return is_dynamic_type_internal (type, 1);
|
||||
}
|
||||
|
||||
static struct type *resolve_dynamic_type_internal (struct type *type,
|
||||
CORE_ADDR addr,
|
||||
int top_level);
|
||||
|
||||
/* Given a dynamic range type (dyn_range_type), return a static version
|
||||
of that type. */
|
||||
|
||||
@ -1758,7 +1771,8 @@ resolve_dynamic_union (struct type *type, CORE_ADDR addr)
|
||||
if (field_is_static (&TYPE_FIELD (type, i)))
|
||||
continue;
|
||||
|
||||
t = resolve_dynamic_type (TYPE_FIELD_TYPE (resolved_type, i), addr);
|
||||
t = resolve_dynamic_type_internal (TYPE_FIELD_TYPE (resolved_type, i),
|
||||
addr, 0);
|
||||
TYPE_FIELD_TYPE (resolved_type, i) = t;
|
||||
if (TYPE_LENGTH (t) > max_len)
|
||||
max_len = TYPE_LENGTH (t);
|
||||
@ -1795,7 +1809,8 @@ resolve_dynamic_struct (struct type *type, CORE_ADDR addr)
|
||||
if (field_is_static (&TYPE_FIELD (type, i)))
|
||||
continue;
|
||||
|
||||
t = resolve_dynamic_type (TYPE_FIELD_TYPE (resolved_type, i), addr);
|
||||
t = resolve_dynamic_type_internal (TYPE_FIELD_TYPE (resolved_type, i),
|
||||
addr, 0);
|
||||
|
||||
/* This is a bit odd. We do not support a VLA in any position
|
||||
of a struct except for the last. GCC does have an extension
|
||||
@ -1823,15 +1838,16 @@ resolve_dynamic_struct (struct type *type, CORE_ADDR addr)
|
||||
return resolved_type;
|
||||
}
|
||||
|
||||
/* See gdbtypes.h */
|
||||
/* Worker for resolved_dynamic_type. */
|
||||
|
||||
struct type *
|
||||
resolve_dynamic_type (struct type *type, CORE_ADDR addr)
|
||||
static struct type *
|
||||
resolve_dynamic_type_internal (struct type *type, CORE_ADDR addr,
|
||||
int top_level)
|
||||
{
|
||||
struct type *real_type = check_typedef (type);
|
||||
struct type *resolved_type = type;
|
||||
|
||||
if (!is_dynamic_type (real_type))
|
||||
if (!is_dynamic_type_internal (real_type, top_level))
|
||||
return type;
|
||||
|
||||
switch (TYPE_CODE (type))
|
||||
@ -1839,7 +1855,8 @@ resolve_dynamic_type (struct type *type, CORE_ADDR addr)
|
||||
case TYPE_CODE_TYPEDEF:
|
||||
resolved_type = copy_type (type);
|
||||
TYPE_TARGET_TYPE (resolved_type)
|
||||
= resolve_dynamic_type (TYPE_TARGET_TYPE (type), addr);
|
||||
= resolve_dynamic_type_internal (TYPE_TARGET_TYPE (type), addr,
|
||||
top_level);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_REF:
|
||||
@ -1848,7 +1865,8 @@ resolve_dynamic_type (struct type *type, CORE_ADDR addr)
|
||||
|
||||
resolved_type = copy_type (type);
|
||||
TYPE_TARGET_TYPE (resolved_type)
|
||||
= resolve_dynamic_type (TYPE_TARGET_TYPE (type), target_addr);
|
||||
= resolve_dynamic_type_internal (TYPE_TARGET_TYPE (type),
|
||||
target_addr, top_level);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1872,6 +1890,14 @@ resolve_dynamic_type (struct type *type, CORE_ADDR addr)
|
||||
return resolved_type;
|
||||
}
|
||||
|
||||
/* See gdbtypes.h */
|
||||
|
||||
struct type *
|
||||
resolve_dynamic_type (struct type *type, CORE_ADDR addr)
|
||||
{
|
||||
return resolve_dynamic_type_internal (type, addr, 1);
|
||||
}
|
||||
|
||||
/* Find the real type of TYPE. This function returns the real type,
|
||||
after removing all layers of typedefs, and completing opaque or stub
|
||||
types. Completion changes the TYPE argument, but stripping of
|
||||
|
@ -1,3 +1,8 @@
|
||||
2014-07-14 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
* gdb.cp/vla-cxx.cc: New file.
|
||||
* gdb.cp/vla-cxx.exp: New file.
|
||||
|
||||
2014-07-14 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
* gdb.reverse/rerun-prec.c: New file.
|
||||
|
49
gdb/testsuite/gdb.cp/vla-cxx.cc
Normal file
49
gdb/testsuite/gdb.cp/vla-cxx.cc
Normal file
@ -0,0 +1,49 @@
|
||||
/* This testcase is part of GDB, the GNU debugger.
|
||||
|
||||
Copyright 2014 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 container;
|
||||
|
||||
struct element
|
||||
{
|
||||
container &c;
|
||||
|
||||
element(container &cc) : c (cc) { }
|
||||
};
|
||||
|
||||
struct container
|
||||
{
|
||||
element e;
|
||||
|
||||
container() : e(*this) { }
|
||||
};
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int z = 3;
|
||||
// Note that this is a GNU extension.
|
||||
int vla[z];
|
||||
typeof (vla) &vlaref (vla);
|
||||
typedef typeof (vla) &vlareftypedef;
|
||||
vlareftypedef vlaref2 (vla);
|
||||
container c;
|
||||
|
||||
for (int i = 0; i < z; ++i)
|
||||
vla[i] = 5 + 2 * i;
|
||||
|
||||
// vlas_filled
|
||||
return vla[2];
|
||||
}
|
35
gdb/testsuite/gdb.cp/vla-cxx.exp
Normal file
35
gdb/testsuite/gdb.cp/vla-cxx.exp
Normal file
@ -0,0 +1,35 @@
|
||||
# Copyright 2014 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/>.
|
||||
|
||||
standard_testfile .cc
|
||||
|
||||
if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } {
|
||||
return -1
|
||||
}
|
||||
|
||||
if ![runto_main] {
|
||||
return -1
|
||||
}
|
||||
|
||||
gdb_breakpoint [gdb_get_line_number "vlas_filled"]
|
||||
gdb_continue_to_breakpoint "vlas_filled"
|
||||
|
||||
gdb_test "print vla" " = \\{5, 7, 9\\}"
|
||||
gdb_test "print vlaref" " = \\(int \\(&\\)\\\[3\\\]\\) @$hex: \\{5, 7, 9\\}"
|
||||
# The ".*" here is because what gdb emits currently is "const
|
||||
# vlareftypedef", which seems incorrect -- and since that isn't the
|
||||
# bug being tested, it's better not to depend on the exact spelling.
|
||||
gdb_test "print vlaref2" " = \\(.*\\) @$hex: \\{5, 7, 9\\}"
|
||||
gdb_test "print c" " = \\{e = \\{c = @$hex\\}\\}"
|
Loading…
Reference in New Issue
Block a user