From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 21606 invoked by alias); 4 Nov 2013 21:17:03 -0000 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 Received: (qmail 21567 invoked by uid 89); 4 Nov 2013 21:17:02 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.8 required=5.0 tests=AWL,BAYES_50,KAM_STOCKGEN,RDNS_NONE,SPF_HELO_PASS,SPF_PASS,URIBL_BLOCKED autolearn=no version=3.3.2 X-HELO: mx1.redhat.com Received: from Unknown (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 04 Nov 2013 21:17:00 +0000 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id rA4LGqhF024579 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 4 Nov 2013 16:16:53 -0500 Received: from barimba.redhat.com (ovpn-113-94.phx2.redhat.com [10.3.113.94]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id rA4LGqlC016717; Mon, 4 Nov 2013 16:16:52 -0500 From: Tom Tromey To: gdb-patches@sourceware.org Cc: Tom Tromey Subject: [PATCH] fix PR c++/16117 Date: Mon, 04 Nov 2013 22:21:00 -0000 Message-Id: <1383599806-19444-1-git-send-email-tromey@redhat.com> X-SW-Source: 2013-11/txt/msg00066.txt.bz2 This patch fixes PR c++/16117. gdb has an extension so that users can use expressions like FILE::NAME to choose a variable of the given name from the given file. The bug is that this extension takes precedence over ordinary C++ expressions of the same form. You might think this is merely hypothetical, but now that C++ headers commonly do not use an extension, it is more common. This patch fixes the bug by making two related changes. First, it changes gdb to prefer the ordinary C++ meaning of a symbol over the extended meaning. Second, it arranges for single-quoting of the symbol to indicate a preference for the extension. Built and regtested on x86-64 Fedora 18. New test case included. 2013-11-04 Tom Tromey PR c++/16117: * c-exp.y (lex_one_token): Add "is_quoted_name" argument. (classify_name): Likewise. Prefer a field of "this" over a filename. (classify_inner_name, yylex): Update. 2013-11-04 Tom Tromey * gdb.texinfo (Variables): Note gdb rules for ambiguous cases. Add example. 2013-11-04 Tom Tromey * gdb.cp/includefile: New file. * gdb.cp/filename.exp: New file. * gdb.cp/filename.cc: New file. --- gdb/ChangeLog | 8 ++++++ gdb/c-exp.y | 53 ++++++++++++++++++++++++++------------- gdb/doc/ChangeLog | 5 ++++ gdb/doc/gdb.texinfo | 22 ++++++++++++---- gdb/testsuite/ChangeLog | 6 +++++ gdb/testsuite/gdb.cp/filename.cc | 36 ++++++++++++++++++++++++++ gdb/testsuite/gdb.cp/filename.exp | 37 +++++++++++++++++++++++++++ gdb/testsuite/gdb.cp/includefile | 18 +++++++++++++ 8 files changed, 162 insertions(+), 23 deletions(-) create mode 100644 gdb/testsuite/gdb.cp/filename.cc create mode 100644 gdb/testsuite/gdb.cp/filename.exp create mode 100644 gdb/testsuite/gdb.cp/includefile diff --git a/gdb/c-exp.y b/gdb/c-exp.y index 77713dd..fecfd15 100644 --- a/gdb/c-exp.y +++ b/gdb/c-exp.y @@ -2415,7 +2415,7 @@ static int last_was_structop; /* Read one token, getting characters through lexptr. */ static int -lex_one_token (void) +lex_one_token (int *is_quoted_name) { int c; int namelen; @@ -2425,6 +2425,7 @@ lex_one_token (void) char *copy; last_was_structop = 0; + *is_quoted_name = 0; retry: @@ -2669,6 +2670,8 @@ lex_one_token (void) { ++tokstart; namelen = lexptr - tokstart - 1; + *is_quoted_name = 1; + goto tryname; } else if (host_len > 1) @@ -2813,10 +2816,11 @@ static struct obstack name_obstack; /* Classify a NAME token. The contents of the token are in `yylval'. Updates yylval and returns the new token type. BLOCK is the block - in which lookups start; this can be NULL to mean the global - scope. */ + in which lookups start; this can be NULL to mean the global scope. + IS_QUOTED_NAME is non-zero if the name token was originally quoted + in single quotes. */ static int -classify_name (const struct block *block) +classify_name (const struct block *block, int is_quoted_name) { struct symbol *sym; char *copy; @@ -2840,16 +2844,6 @@ classify_name (const struct block *block) } else if (!sym) { - /* See if it's a file name. */ - struct symtab *symtab; - - symtab = lookup_symtab (copy); - if (symtab) - { - 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 @@ -2869,6 +2863,24 @@ classify_name (const struct block *block) return TYPENAME; } } + + /* If we found a field, then we want to prefer it over a + filename. However, if the name was quoted, then it is better + to check for a filename or a block, since this is the only + way the user has of requiring the extension to be used. */ + if (is_a_field_of_this.type == NULL || is_quoted_name) + { + /* See if it's a file name. */ + struct symtab *symtab; + + symtab = lookup_symtab (copy); + if (symtab) + { + yylval.bval = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), + STATIC_BLOCK); + return FILENAME; + } + } } if (sym && SYMBOL_CLASS (sym) == LOC_TYPEDEF) @@ -2938,7 +2950,7 @@ classify_inner_name (const struct block *block, struct type *context) char *copy; if (context == NULL) - return classify_name (block); + return classify_name (block, 0); type = check_typedef (context); if (TYPE_CODE (type) != TYPE_CODE_STRUCT @@ -2986,6 +2998,7 @@ yylex (void) struct type *context_type = NULL; int last_to_examine, next_to_examine, checkpoint; const struct block *search_block; + int is_quoted_name; if (popping && !VEC_empty (token_and_value, token_fifo)) goto do_pop; @@ -2994,9 +3007,9 @@ yylex (void) /* Read the first token and decide what to do. Most of the subsequent code is C++-only; but also depends on seeing a "::" or name-like token. */ - current.token = lex_one_token (); + current.token = lex_one_token (&is_quoted_name); if (current.token == NAME) - current.token = classify_name (expression_context_block); + current.token = classify_name (expression_context_block, is_quoted_name); if (parse_language->la_language != language_cplus || (current.token != TYPENAME && current.token != COLONCOLON && current.token != FILENAME)) @@ -3009,7 +3022,11 @@ yylex (void) last_was_coloncolon = current.token == COLONCOLON; while (1) { - current.token = lex_one_token (); + int ignore; + + /* We ignore quoted names other than the very first one. + Subsequent ones do not have any special meaning. */ + current.token = lex_one_token (&ignore); current.value = yylval; VEC_safe_push (token_and_value, token_fifo, ¤t); diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 28e6ff9..9737355 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -8322,11 +8322,23 @@ $4 = 0 @end smallexample @cindex C@t{++} scope resolution -These uses of @samp{::} are very rarely in conflict with the very similar -use of the same notation in C@t{++}. @value{GDBN} also supports use of the C@t{++} -scope resolution operator in @value{GDBN} expressions. -@c FIXME: Um, so what happens in one of those rare cases where it's in -@c conflict?? --mew +These uses of @samp{::} are very rarely in conflict with the very +similar use of the same notation in C@t{++}. When they are in +conflict, the C@t{++} meaning takes precedence; however, this can be +overridden by quoting the file or function name. + +For example, suppose the program is stopped in a method of a class +that has a field named ``includefile'', and there is also an include +file named ``includefile'' that defines a variable, ``some_global''. + +@smallexample +(@value{GDBP}) p includefile +$1 = 23 +(@value{GDBP}) p includefile::some_global +A syntax error in expression, near `'. +(@value{GDBP}) p 'includefile'::some_global +$2 = 27 +@end smallexample @cindex wrong values @cindex variable values, wrong diff --git a/gdb/testsuite/gdb.cp/filename.cc b/gdb/testsuite/gdb.cp/filename.cc new file mode 100644 index 0000000..716f48b --- /dev/null +++ b/gdb/testsuite/gdb.cp/filename.cc @@ -0,0 +1,36 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2013 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 . */ + +#include "includefile" + +class C { +public: + int includefile[1]; + + C() { + includefile[0] = 23; + } + + void m() { + /* stop here */ + } +}; + +int main() { + C c; + c.m(); +} diff --git a/gdb/testsuite/gdb.cp/filename.exp b/gdb/testsuite/gdb.cp/filename.exp new file mode 100644 index 0000000..943cdc6 --- /dev/null +++ b/gdb/testsuite/gdb.cp/filename.exp @@ -0,0 +1,37 @@ +# Copyright 2013 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 [get_compiler_info "c++"] { + return -1 +} + +if {[prepare_for_testing $testfile.exp $testfile $srcfile {debug c++}]} { + return -1 +} + +if ![runto_main] then { + perror "couldn't run to main" + continue +} + +gdb_breakpoint [gdb_get_line_number "stop here"] +gdb_continue_to_breakpoint "stop here" + +gdb_test "print includefile\[0\]" " = 23" +gdb_test "print 'includefile'::some_global" " = 27" diff --git a/gdb/testsuite/gdb.cp/includefile b/gdb/testsuite/gdb.cp/includefile new file mode 100644 index 0000000..9dfa787 --- /dev/null +++ b/gdb/testsuite/gdb.cp/includefile @@ -0,0 +1,18 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2013 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 . */ + +int some_global = 27; -- 1.8.1.4