From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 30902 invoked by alias); 21 Nov 2012 21:30:55 -0000 Received: (qmail 30893 invoked by uid 22791); 21 Nov 2012 21:30:53 -0000 X-SWARE-Spam-Status: No, hits=-6.0 required=5.0 tests=AWL,BAYES_00,KAM_STOCKGEN,KHOP_RCVD_UNTRUST,RCVD_IN_DNSWL_HI,RCVD_IN_HOSTKARMA_W,RP_MATCHES_RCVD,SPF_HELO_PASS X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 21 Nov 2012 21:30:45 +0000 Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id qALLUf8C022183 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 21 Nov 2012 16:30:45 -0500 Received: from barimba (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id qALLUJNg015120 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES128-SHA bits=128 verify=NO); Wed, 21 Nov 2012 16:30:34 -0500 From: Tom Tromey To: gdb-patches@sourceware.org Subject: RFC: fix PR c++/8888 Date: Wed, 21 Nov 2012 21:30:00 -0000 Message-ID: <87boeqlk45.fsf@fleche.redhat.com> MIME-Version: 1.0 Content-Type: text/plain Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2012-11/txt/msg00590.txt.bz2 This patch fixes PR c++/8888. The bug here is that when gdb is stopped in a method, then references to the enclosing class name find the constructor rather than the type. E.g., in the test case in the patch, when stopped in C::m, "print C::x" will fail. After investigating the problem for a while, I couldn't find a bad situation here other than the constructor problem. So, I made the fix specific to this case. There are actually two related failures, but I consider them different bugs -- in particular I think they need to be fixed in different spots. First, PR 14819, which I closed as a dup of 8888, but which actually exhibits two bugs. This patch partially fixes that PR, but in the PR, "print C::x" still fails, because this really means "print this->C::x"; but this shorthand isn't implemented in gdb. Second, you can take the test case from this patch and templatize it. Then "print C::x" fails, but shouldn't -- but in this case it is because "C" in this context should refer to the enclosing instance, another thing that gdb doesn't implement. I'm going to reopen 14819 and file a new bug for the other problem. Built and regtested on x86-64 Fedora 16. New test case included. Tom 2012-11-21 Tom Tromey PR c++/8888: * symtab.c (lookup_symbol_aux): If constructor is found, consider returning the type instead. * c-exp.y (classify_name): Check STRUCT_DOMAIN if no symbol found. 2012-11-21 Tom Tromey * gdb.cp/member-name.exp: New file. * gdb.cp/member-name.cc: New file. diff --git a/gdb/c-exp.y b/gdb/c-exp.y index 11eaadb..83175e0 100644 --- a/gdb/c-exp.y +++ b/gdb/c-exp.y @@ -2728,6 +2728,32 @@ classify_name (struct block *block) yylval.bval = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), STATIC_BLOCK); return FILENAME; } + + /* If we found a field of 'this', we might have erroneously + found a constructor where we wanted a type name. Handle this + case by noticing that we found a constructor and then look up + the type tag. */ + if (is_a_field_of_this) + { + unsigned int len; + struct symbol *block_sym = block_containing_function (block); + const char *block_name = SYMBOL_NATURAL_NAME (block_sym); + + len = cp_entire_prefix_len (block_name); + if (strncmp (block_name, copy, len) == 0) + { + is_a_field_of_this = 0; + sym = lookup_symbol (copy, block, STRUCT_DOMAIN, + &is_a_field_of_this); + if (sym != NULL) + { + yylval.tsym.type = SYMBOL_TYPE (sym); + return TYPENAME; + } + /* Restore the previous value and keep going. */ + is_a_field_of_this = 1; + } + } } if (sym && SYMBOL_CLASS (sym) == LOC_TYPEDEF) diff --git a/gdb/symtab.c b/gdb/symtab.c index 05943cf..b429f76 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -1308,7 +1308,10 @@ lookup_symbol_aux (const char *name, const struct block *block, langdef = language_def (language); - if (is_a_field_of_this != NULL) + /* Don't do this check if we are searching for a struct. It will + not be found by check_field, but will be found by other + means. */ + if (is_a_field_of_this != NULL && domain != STRUCT_DOMAIN) { struct symbol *sym = lookup_language_this (langdef, block); diff --git a/gdb/testsuite/gdb.cp/member-name.cc b/gdb/testsuite/gdb.cp/member-name.cc new file mode 100644 index 0000000..64afe68 --- /dev/null +++ b/gdb/testsuite/gdb.cp/member-name.cc @@ -0,0 +1,51 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2003-2004, 2007-2012 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 C +{ + static int x; + + struct inner + { + static int z; + }; + + int y; + + C () + { + // First breakpoint here + y = x + inner::z; + } + + int m () + { + // Second breakpoint here + return x - y; + } +}; + +int C::x = 23; +int C::inner::z = 0; + +int main () +{ + C c; + + return c.m(); +} diff --git a/gdb/testsuite/gdb.cp/member-name.exp b/gdb/testsuite/gdb.cp/member-name.exp new file mode 100644 index 0000000..d4b3740 --- /dev/null +++ b/gdb/testsuite/gdb.cp/member-name.exp @@ -0,0 +1,37 @@ +# Copyright 2012 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 . + +if { [skip_cplus_tests] } { continue } + +standard_testfile .cc + +if {[prepare_for_testing $testfile.exp $testfile $srcfile {debug c++}]} { + return -1 +} + +if ![runto_main] then { + perror "couldn't run to breakpoint" + return +} + +gdb_breakpoint ${srcfile}:[gdb_get_line_number "First breakpoint"] +gdb_continue_to_breakpoint "continue to first breakpoint" +gdb_test "print C::x" " = 23" "print C::x from first breakpoint" +gdb_test "print inner::z" " = 0" "print inner::z from first breakpoint" + +gdb_breakpoint ${srcfile}:[gdb_get_line_number "Second breakpoint"] +gdb_continue_to_breakpoint "continue to second breakpoint" +gdb_test "print C::x" " = 23" "print C::x from second breakpoint" +gdb_test "print inner::z" " = 0" "print inner::z from second breakpoint"