There is existing logic in C/C++ expression parsing to avoid classifying
names as a filename when they are a field on the this object. This
change extends this logic to also avoid classifying names after a
struct-op (-> or .) as a filename, which otherwise causes a syntax
error.
Thus, it is now possible in the file
#include <map>
struct D {
void map();
}
D d;
to call
(gdb) print d.map()
where previously this would have been a syntax error.
Tested on gdb.cp/*.exp
gdb/ChangeLog:
* c-exp.y (lex_one_token, classify_name, yylex): Don't classify
names after a structop as a filename
gdb/testsuite/ChangeLog:
* gdb.cp/filename.cc, gdb.cp/filename.exp: Test that member
functions with the same name as an include file are parsed
correctly.
---
gdb/ChangeLog | 5 +++++
gdb/c-exp.y | 24 +++++++++++++-----------
gdb/testsuite/ChangeLog | 6 ++++++
gdb/testsuite/gdb.cp/filename.cc | 15 ++++++++++++++-
gdb/testsuite/gdb.cp/filename.exp | 10 ++++++++--
gdb/varobj.c | 1 -
6 files changed, 46 insertions(+), 15 deletions(-)
@@ -1,3 +1,8 @@
+2018-01-24 Leszek Swirski <leszeks@google.com>
+
+ * c-exp.y (lex_one_token, classify_name, yylex): Don't classify
+ names after a structop as a filename
+
2018-01-23 Philipp Rudo <prudo@linux.vnet.ibm.com>
* s390-linux-tdep.c (s390_record_address_mask)
@@ -2447,8 +2447,7 @@ static struct macro_scope *expression_macro_scope;
static int saw_name_at_eof;
/* This is set if the previously-returned token was a structure
- operator -- either '.' or ARROW. This is used only when parsing to
- do field name completion. */
+ operator -- either '.' or ARROW. */
static int last_was_structop;
/* Read one token, getting characters through lexptr. */
@@ -2505,7 +2504,7 @@ lex_one_token (struct parser_state *par_state, int *is_quoted_name)
lexptr += 2;
yylval.opcode = tokentab2[i].opcode;
- if (parse_completion && tokentab2[i].token == ARROW)
+ if (tokentab2[i].token == ARROW)
last_was_structop = 1;
return tokentab2[i].token;
}
@@ -2569,8 +2568,7 @@ lex_one_token (struct parser_state *par_state, int *is_quoted_name)
/* Might be a floating point number. */
if (lexptr[1] < '0' || lexptr[1] > '9')
{
- if (parse_completion)
- last_was_structop = 1;
+ last_was_structop = 1;
goto symbol; /* Nope, must be a symbol. */
}
/* FALL THRU into number case. */
@@ -2863,7 +2861,7 @@ auto_obstack name_obstack;
static int
classify_name (struct parser_state *par_state, const struct block *block,
- int is_quoted_name)
+ int is_quoted_name, int is_after_structop)
{
struct block_symbol bsym;
char *copy;
@@ -2907,11 +2905,13 @@ classify_name (struct parser_state *par_state, const struct block *block,
}
}
- /* If we found a field, then we want to prefer it over a
+ /* If we found a field on the "this" object, or we are looking
+ up a field on a struct, 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)
+ if ((is_a_field_of_this.type == NULL && !is_after_structop)
+ || is_quoted_name)
{
/* See if it's a file name. */
struct symtab *symtab;
@@ -2992,7 +2992,7 @@ classify_inner_name (struct parser_state *par_state,
char *copy;
if (context == NULL)
- return classify_name (par_state, block, 0);
+ return classify_name (par_state, block, 0, 0);
type = check_typedef (context);
if (!type_aggregate_p (type))
@@ -3062,7 +3062,7 @@ static int
yylex (void)
{
token_and_value current;
- int first_was_coloncolon, last_was_coloncolon;
+ int first_was_coloncolon, last_was_coloncolon, last_lex_was_structop;
struct type *context_type = NULL;
int last_to_examine, next_to_examine, checkpoint;
const struct block *search_block;
@@ -3072,13 +3072,15 @@ yylex (void)
goto do_pop;
popping = 0;
+ last_lex_was_structop = last_was_structop;
+
/* 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 (pstate, &is_quoted_name);
if (current.token == NAME)
current.token = classify_name (pstate, expression_context_block,
- is_quoted_name);
+ is_quoted_name, last_lex_was_structop);
if (parse_language (pstate)->la_language != language_cplus
|| (current.token != TYPENAME && current.token != COLONCOLON
&& current.token != FILENAME))
@@ -1,3 +1,9 @@
+2018-01-24 Leszek Swirski <leszeks@google.com>
+
+ * gdb.cp/filename.cc, gdb.cp/filename.exp: Test that member
+ functions with the same name as an include file are parsed
+ correctly.
+
2018-01-22 Pedro Alves <palves@redhat.com>
Sergio Durigan Junior <sergiodj@redhat.com>
@@ -26,11 +26,24 @@ public:
}
void m() {
- /* stop here */
+ /* stop here 1 */
}
};
+class D {
+public:
+ int includefile();
+};
+
+int D::includefile() {
+ return 24;
+}
+
int main() {
C c;
c.m();
+
+ D d;
+ D* pd = &d;
+ /* stop here 2 */
}
@@ -26,8 +26,14 @@ if ![runto_main] then {
continue
}
-gdb_breakpoint [gdb_get_line_number "stop here"]
-gdb_continue_to_breakpoint "stop here"
+gdb_breakpoint [gdb_get_line_number "stop here 1"]
+gdb_continue_to_breakpoint "stop here 1"
gdb_test "print includefile\[0\]" " = 23"
gdb_test "print 'includefile'::some_global" " = 27"
+
+gdb_breakpoint [gdb_get_line_number "stop here 2"]
+gdb_continue_to_breakpoint "stop here 2"
+
+gdb_test "print d.includefile()" " = 24"
+gdb_test "print pd->includefile()" " = 24"
@@ -2274,7 +2274,6 @@ varobj_formatted_print_options (struct value_print_options *opts,
{
get_formatted_print_options (opts, format_code[(int) format]);
opts->deref_ref = 0;
- opts->raw = 1;
}
std::string