From patchwork Thu Jul 3 17:00:59 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Tromey X-Patchwork-Id: 1906 Received: (qmail 8068 invoked by alias); 3 Jul 2014 17:01:24 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 8036 invoked by uid 89); 3 Jul 2014 17:01:19 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.8 required=5.0 tests=AWL, BAYES_00, SPF_HELO_PASS, SPF_PASS, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Thu, 03 Jul 2014 17:01:11 +0000 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s63H18LZ020668 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Thu, 3 Jul 2014 13:01:09 -0400 Received: from barimba.redhat.com (ovpn-113-95.phx2.redhat.com [10.3.113.95]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s63H162c023348; Thu, 3 Jul 2014 13:01:06 -0400 From: Tom Tromey To: gdb-patches@sourceware.org Cc: Tom Tromey Subject: [PATCH] fix PR 17106 Date: Thu, 3 Jul 2014 11:00:59 -0600 Message-Id: <1404406859-6886-1-git-send-email-tromey@redhat.com> 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-03 Tom Tromey 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-03 Tom Tromey * gdb.cp/vla-cxx.cc: New file. * gdb.cp/vla-cxx.exp: New file. --- gdb/ChangeLog | 12 +++++++++ gdb/gdbtypes.c | 56 +++++++++++++++++++++++++++++----------- gdb/testsuite/ChangeLog | 5 ++++ gdb/testsuite/gdb.cp/vla-cxx.cc | 49 +++++++++++++++++++++++++++++++++++ gdb/testsuite/gdb.cp/vla-cxx.exp | 35 +++++++++++++++++++++++++ 5 files changed, 142 insertions(+), 15 deletions(-) create mode 100644 gdb/testsuite/gdb.cp/vla-cxx.cc create mode 100644 gdb/testsuite/gdb.cp/vla-cxx.exp diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index d0c002f..e99a2f3 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -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 diff --git a/gdb/testsuite/gdb.cp/vla-cxx.cc b/gdb/testsuite/gdb.cp/vla-cxx.cc new file mode 100644 index 0000000..ea75df2 --- /dev/null +++ b/gdb/testsuite/gdb.cp/vla-cxx.cc @@ -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 . */ + +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]; +} diff --git a/gdb/testsuite/gdb.cp/vla-cxx.exp b/gdb/testsuite/gdb.cp/vla-cxx.exp new file mode 100644 index 0000000..1ff815e --- /dev/null +++ b/gdb/testsuite/gdb.cp/vla-cxx.exp @@ -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 . + +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\\}\\}"