fix PR c++/16117
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-15 Tom Tromey <tromey@redhat.com> 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-15 Tom Tromey <tromey@redhat.com> * gdb.texinfo (Variables): Note gdb rules for ambiguous cases. Add example. 2013-11-15 Tom Tromey <tromey@redhat.com> * gdb.cp/includefile: New file. * gdb.cp/filename.exp: New file. * gdb.cp/filename.cc: New file.
This commit is contained in:
parent
ad8ecc8114
commit
805e1f1908
|
@ -1,3 +1,11 @@
|
|||
2013-11-15 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
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-15 Joel Brobecker <brobecker@adacore.com>
|
||||
|
||||
* dwarf2expr.h (struct dwarf_expr_context_funcs) <read_reg>:
|
||||
|
|
53
gdb/c-exp.y
53
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);
|
||||
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2013-11-15 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
* gdb.texinfo (Variables): Note gdb rules for ambiguous cases.
|
||||
Add example.
|
||||
|
||||
2013-11-14 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
* gdb.texinfo (Breakpoints In Python): Replace "as" with "in".
|
||||
|
|
|
@ -8324,11 +8324,24 @@ $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 with single quotes.
|
||||
|
||||
For example, suppose the program is stopped in a method of a class
|
||||
that has a field named @code{includefile}, and there is also an
|
||||
include file named @file{includefile} that defines a variable,
|
||||
@code{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
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2013-11-15 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
* gdb.cp/includefile: New file.
|
||||
* gdb.cp/filename.exp: New file.
|
||||
* gdb.cp/filename.cc: New file.
|
||||
|
||||
2013-11-15 Doug Evans <xdje42@gmail.com>
|
||||
|
||||
* gdb.python/py-breakpoint.exp: Make tests have unique names.
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "includefile"
|
||||
|
||||
class C {
|
||||
public:
|
||||
int includefile[1];
|
||||
|
||||
C() {
|
||||
includefile[0] = 23;
|
||||
}
|
||||
|
||||
void m() {
|
||||
/* stop here */
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
C c;
|
||||
c.m();
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
# 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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 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"
|
|
@ -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 <http://www.gnu.org/licenses/>. */
|
||||
|
||||
int some_global = 27;
|
Loading…
Reference in New Issue