diff options
author | Tom Tromey <tromey@redhat.com> | 2013-11-04 12:38:10 -0700 |
---|---|---|
committer | Tom Tromey <tromey@redhat.com> | 2013-11-15 08:43:14 -0700 |
commit | 805e1f190887b3b7dea3fd157d58bc25effcf688 (patch) | |
tree | e384f11e3c9596419f0ca2588c8e2e90d32c8299 /gdb/c-exp.y | |
parent | ad8ecc8114ce17e4f8f118606225f1002d7faec2 (diff) | |
download | gdb-805e1f190887b3b7dea3fd157d58bc25effcf688.zip gdb-805e1f190887b3b7dea3fd157d58bc25effcf688.tar.gz gdb-805e1f190887b3b7dea3fd157d58bc25effcf688.tar.bz2 |
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.
Diffstat (limited to 'gdb/c-exp.y')
-rw-r--r-- | gdb/c-exp.y | 53 |
1 files changed, 35 insertions, 18 deletions
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); |