* [PATCH v2] Do not classify C struct members as a filename
@ 2018-01-24 16:51 Leszek Swirski via gdb-patches
2018-01-25 2:39 ` Simon Marchi
2018-01-25 16:00 ` [PATCH v2] " Tom Tromey
0 siblings, 2 replies; 9+ messages in thread
From: Leszek Swirski via gdb-patches @ 2018-01-24 16:51 UTC (permalink / raw)
To: gdb-patches; +Cc: Leszek Swirski
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.
---
Removed an accidental unrelated change in varobj.c
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 ++++++++--
5 files changed, 46 insertions(+), 14 deletions(-)
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 2b6d1d6d6b..17a5a84b0c 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -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)
diff --git a/gdb/c-exp.y b/gdb/c-exp.y
index 0482e85ce8..f8c5529551 100644
--- a/gdb/c-exp.y
+++ b/gdb/c-exp.y
@@ -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))
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 0f02f4a97f..903d9f4cb6 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -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>
diff --git a/gdb/testsuite/gdb.cp/filename.cc b/gdb/testsuite/gdb.cp/filename.cc
index 45edf4efe9..0600c67a75 100644
--- a/gdb/testsuite/gdb.cp/filename.cc
+++ b/gdb/testsuite/gdb.cp/filename.cc
@@ -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 */
}
diff --git a/gdb/testsuite/gdb.cp/filename.exp b/gdb/testsuite/gdb.cp/filename.exp
index 971ffe715f..67583cc67c 100644
--- a/gdb/testsuite/gdb.cp/filename.exp
+++ b/gdb/testsuite/gdb.cp/filename.exp
@@ -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"
--
2.16.0.rc1.238.g530d649a79-goog
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2] Do not classify C struct members as a filename
2018-01-24 16:51 [PATCH v2] Do not classify C struct members as a filename Leszek Swirski via gdb-patches
@ 2018-01-25 2:39 ` Simon Marchi
2018-01-25 10:04 ` Leszek Swirski via gdb-patches
2018-01-25 16:00 ` [PATCH v2] " Tom Tromey
1 sibling, 1 reply; 9+ messages in thread
From: Simon Marchi @ 2018-01-25 2:39 UTC (permalink / raw)
To: Leszek Swirski; +Cc: gdb-patches
On 2018-01-24 11:51, Leszek Swirski via gdb-patches wrote:
> 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
Hi Leszek,
I was able to reproduce the problem and confirmed that the patch fixes
it. I'm not very strong in the lexing/parsing area, but the change in
c-exp.y makes sense to me. I'd like to give others a chance to comment,
so let's wait a few days. If nobody answer, we can merge it. One nit,
since we are now using C++, can you use bool instead of int? It won't
match the old surrounding code, but that's a good reason to modernize
the existing code later :).
Do you know if we have a test for the same thing, but with the "this"
pointer (which was already worked before this patch)? If not, it would
be nice to add it to the test as well. You could add a call to
D::includefile and continue/break there. From there, you could test
calling this->includefile().
Simon
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2] Do not classify C struct members as a filename
2018-01-25 2:39 ` Simon Marchi
@ 2018-01-25 10:04 ` Leszek Swirski via gdb-patches
2018-01-25 14:52 ` Simon Marchi
0 siblings, 1 reply; 9+ messages in thread
From: Leszek Swirski via gdb-patches @ 2018-01-25 10:04 UTC (permalink / raw)
To: Simon Marchi; +Cc: gdb-patches
>
> I was able to reproduce the problem and confirmed that the patch fixes
> it. I'm not very strong in the lexing/parsing area, but the change in
> c-exp.y makes sense to me. I'd like to give others a chance to comment, so
> let's wait a few days. If nobody answer, we can merge it. One nit, since
> we are now using C++, can you use bool instead of int? It won't match the
> old surrounding code, but that's a good reason to modernize the existing
> code later :).
>
> Do you know if we have a test for the same thing, but with the "this"
> pointer (which was already worked before this patch)? If not, it would be
> nice to add it to the test as well. You could add a call to D::includefile
> and continue/break there. From there, you could test calling
> this->includefile().
Hi Simon, thanks for taking a look.
Sure, I can update the tests (I'll add some tests for checking
"c.includefile" while I'm at it) and change the int to a bool. I'm not 100%
sure on the procedure here, do you want me to upload a v3 as a new thread?
- Leszek
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2] Do not classify C struct members as a filename
2018-01-25 10:04 ` Leszek Swirski via gdb-patches
@ 2018-01-25 14:52 ` Simon Marchi
2018-01-25 15:09 ` [PATCH v3] " Leszek Swirski via gdb-patches
0 siblings, 1 reply; 9+ messages in thread
From: Simon Marchi @ 2018-01-25 14:52 UTC (permalink / raw)
To: Leszek Swirski; +Cc: gdb-patches
On 2018-01-25 05:03, Leszek Swirski via gdb-patches wrote:
> Hi Simon, thanks for taking a look.
>
> Sure, I can update the tests (I'll add some tests for checking
> "c.includefile" while I'm at it) and change the int to a bool. I'm not
> 100%
> sure on the procedure here, do you want me to upload a v3 as a new
> thread?
>
> - Leszek
Hi Leszek,
Yes, sending a v3 would be ideal. It's usually a new thread (as in
there is no "Re:"), but some people like to use git-send-email's
--in-reply-to option to refer to the previous version, so that the
different versions thread nicely in email clients. It's up to you.
Simon
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v3] Do not classify C struct members as a filename
2018-01-25 14:52 ` Simon Marchi
@ 2018-01-25 15:09 ` Leszek Swirski via gdb-patches
0 siblings, 0 replies; 9+ messages in thread
From: Leszek Swirski via gdb-patches @ 2018-01-25 15:09 UTC (permalink / raw)
To: gdb-patches; +Cc: Simon Marchi, Leszek Swirski
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.
---
Updated ints to bools (including some opportunistic updates of existing
arguments), and expanded test.
gdb/ChangeLog | 5 +++++
gdb/c-exp.y | 43 +++++++++++++++++++++------------------
gdb/testsuite/ChangeLog | 6 ++++++
gdb/testsuite/gdb.cp/filename.cc | 22 +++++++++++++++++++-
gdb/testsuite/gdb.cp/filename.exp | 20 ++++++++++++++++--
5 files changed, 73 insertions(+), 23 deletions(-)
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 2b6d1d6d6b..17a5a84b0c 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -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)
diff --git a/gdb/c-exp.y b/gdb/c-exp.y
index 0482e85ce8..5802a6d746 100644
--- a/gdb/c-exp.y
+++ b/gdb/c-exp.y
@@ -2447,24 +2447,23 @@ 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. */
-static int last_was_structop;
+ operator -- either '.' or ARROW. */
+static bool last_was_structop;
/* Read one token, getting characters through lexptr. */
static int
-lex_one_token (struct parser_state *par_state, int *is_quoted_name)
+lex_one_token (struct parser_state *par_state, bool *is_quoted_name)
{
int c;
int namelen;
unsigned int i;
const char *tokstart;
- int saw_structop = last_was_structop;
+ bool saw_structop = last_was_structop;
char *copy;
- last_was_structop = 0;
- *is_quoted_name = 0;
+ last_was_structop = false;
+ *is_quoted_name = false;
retry:
@@ -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 = true;
goto symbol; /* Nope, must be a symbol. */
}
/* FALL THRU into number case. */
@@ -2711,7 +2709,7 @@ lex_one_token (struct parser_state *par_state, int *is_quoted_name)
{
++tokstart;
namelen = lexptr - tokstart - 1;
- *is_quoted_name = 1;
+ *is_quoted_name = true;
goto tryname;
}
@@ -2859,11 +2857,12 @@ auto_obstack name_obstack;
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.
IS_QUOTED_NAME is non-zero if the name token was originally quoted
- in single quotes. */
+ in single quotes. IS_AFTER_STRUCTOP is true if this name follows
+ a structure operator -- either '.' or ARROW */
static int
classify_name (struct parser_state *par_state, const struct block *block,
- int is_quoted_name)
+ bool is_quoted_name, bool is_after_structop)
{
struct block_symbol bsym;
char *copy;
@@ -2907,11 +2906,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 +2993,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, false, false);
type = check_typedef (context);
if (!type_aggregate_p (type))
@@ -3066,19 +3067,21 @@ yylex (void)
struct type *context_type = NULL;
int last_to_examine, next_to_examine, checkpoint;
const struct block *search_block;
- int is_quoted_name;
+ bool is_quoted_name, last_lex_was_structop;
if (popping && !VEC_empty (token_and_value, token_fifo))
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))
@@ -3091,7 +3094,7 @@ yylex (void)
last_was_coloncolon = current.token == COLONCOLON;
while (1)
{
- int ignore;
+ bool ignore;
/* We ignore quoted names other than the very first one.
Subsequent ones do not have any special meaning. */
@@ -3242,7 +3245,7 @@ c_parse (struct parser_state *par_state)
parser_debug);
/* Initialize some state used by the lexer. */
- last_was_structop = 0;
+ last_was_structop = false;
saw_name_at_eof = 0;
VEC_free (token_and_value, token_fifo);
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 0f02f4a97f..903d9f4cb6 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -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>
diff --git a/gdb/testsuite/gdb.cp/filename.cc b/gdb/testsuite/gdb.cp/filename.cc
index 45edf4efe9..d33ef78bcb 100644
--- a/gdb/testsuite/gdb.cp/filename.cc
+++ b/gdb/testsuite/gdb.cp/filename.cc
@@ -26,11 +26,31 @@ public:
}
void m() {
- /* stop here */
+ /* stop inside C */
}
};
+class D {
+public:
+ int includefile();
+
+ void m() {
+ /* stop inside D */
+ }
+};
+
+int D::includefile() {
+ return 24;
+}
+
int main() {
C c;
+ C* pc = &c;
c.m();
+
+ D d;
+ D* pd = &d;
+ d.m();
+
+ /* stop outside */
}
diff --git a/gdb/testsuite/gdb.cp/filename.exp b/gdb/testsuite/gdb.cp/filename.exp
index 971ffe715f..208179e7ca 100644
--- a/gdb/testsuite/gdb.cp/filename.exp
+++ b/gdb/testsuite/gdb.cp/filename.exp
@@ -26,8 +26,24 @@ 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 inside C"]
+gdb_continue_to_breakpoint "stop inside C"
gdb_test "print includefile\[0\]" " = 23"
+gdb_test "print this->includefile\[0\]" " = 23"
gdb_test "print 'includefile'::some_global" " = 27"
+
+gdb_breakpoint [gdb_get_line_number "stop inside D"]
+gdb_continue_to_breakpoint "stop inside D"
+
+gdb_test "print includefile()" " = 24"
+gdb_test "print this->includefile()" " = 24"
+gdb_test "print 'includefile'::some_global" " = 27"
+
+gdb_breakpoint [gdb_get_line_number "stop outside"]
+gdb_continue_to_breakpoint "stop outside"
+
+gdb_test "print c.includefile\[0\]" " = 23"
+gdb_test "print pc->includefile\[0\]" " = 23"
+gdb_test "print d.includefile()" " = 24"
+gdb_test "print pd->includefile()" " = 24"
--
2.16.0.rc1.238.g530d649a79-goog
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2] Do not classify C struct members as a filename
2018-01-24 16:51 [PATCH v2] Do not classify C struct members as a filename Leszek Swirski via gdb-patches
2018-01-25 2:39 ` Simon Marchi
@ 2018-01-25 16:00 ` Tom Tromey
2018-01-25 16:20 ` [PATCH v4] " Leszek Swirski via gdb-patches
2018-01-25 16:39 ` [PATCH v2] " Leszek Swirski via gdb-patches
1 sibling, 2 replies; 9+ messages in thread
From: Tom Tromey @ 2018-01-25 16:00 UTC (permalink / raw)
To: Leszek Swirski via gdb-patches; +Cc: Leszek Swirski
>>>>> "Leszek" == Leszek Swirski via gdb-patches <gdb-patches@sourceware.org> writes:
Leszek> There is existing logic in C/C++ expression parsing to avoid classifying
Leszek> names as a filename when they are a field on the this object. This
Leszek> change extends this logic to also avoid classifying names after a
Leszek> struct-op (-> or .) as a filename, which otherwise causes a syntax
Leszek> error.
Nice, thanks for doing this.
Leszek> - if (parse_completion && tokentab2[i].token == ARROW)
Leszek> + if (tokentab2[i].token == ARROW)
Leszek> - if (parse_completion)
Leszek> - last_was_structop = 1;
Leszek> + last_was_structop = 1;
This change makes sense (and thanks for updating that comment as well),
but I wonder whether this changes the behavior in some case. Elsewhere
in lex_one_token there is a check of saw_structop:
else if (saw_structop)
return COMPLETE;
Previously this return could only be taken if parse_completion was set,
but now I think it could be taken in other situations.
So, I suspect "parse_completion &&" should be stuck in there.
Tom
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v4] Do not classify C struct members as a filename
2018-01-25 16:00 ` [PATCH v2] " Tom Tromey
@ 2018-01-25 16:20 ` Leszek Swirski via gdb-patches
2018-02-02 3:35 ` Simon Marchi
2018-01-25 16:39 ` [PATCH v2] " Leszek Swirski via gdb-patches
1 sibling, 1 reply; 9+ messages in thread
From: Leszek Swirski via gdb-patches @ 2018-01-25 16:20 UTC (permalink / raw)
To: gdb-patches; +Cc: Simon Marchi, Tom Tromey, Leszek Swirski
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.
---
Fix completion token to only appear on completion.
gdb/ChangeLog | 5 +++++
gdb/c-exp.y | 45 +++++++++++++++++++++------------------
gdb/testsuite/ChangeLog | 6 ++++++
gdb/testsuite/gdb.cp/filename.cc | 22 ++++++++++++++++++-
gdb/testsuite/gdb.cp/filename.exp | 20 +++++++++++++++--
5 files changed, 74 insertions(+), 24 deletions(-)
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 2b6d1d6d6b..17a5a84b0c 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -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)
diff --git a/gdb/c-exp.y b/gdb/c-exp.y
index 0482e85ce8..8f0aa00f52 100644
--- a/gdb/c-exp.y
+++ b/gdb/c-exp.y
@@ -2447,24 +2447,23 @@ 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. */
-static int last_was_structop;
+ operator -- either '.' or ARROW. */
+static bool last_was_structop;
/* Read one token, getting characters through lexptr. */
static int
-lex_one_token (struct parser_state *par_state, int *is_quoted_name)
+lex_one_token (struct parser_state *par_state, bool *is_quoted_name)
{
int c;
int namelen;
unsigned int i;
const char *tokstart;
- int saw_structop = last_was_structop;
+ bool saw_structop = last_was_structop;
char *copy;
- last_was_structop = 0;
- *is_quoted_name = 0;
+ last_was_structop = false;
+ *is_quoted_name = false;
retry:
@@ -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;
}
@@ -2529,7 +2528,7 @@ lex_one_token (struct parser_state *par_state, int *is_quoted_name)
saw_name_at_eof = 0;
return COMPLETE;
}
- else if (saw_structop)
+ else if (parse_completion && saw_structop)
return COMPLETE;
else
return 0;
@@ -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 = true;
goto symbol; /* Nope, must be a symbol. */
}
/* FALL THRU into number case. */
@@ -2711,7 +2709,7 @@ lex_one_token (struct parser_state *par_state, int *is_quoted_name)
{
++tokstart;
namelen = lexptr - tokstart - 1;
- *is_quoted_name = 1;
+ *is_quoted_name = true;
goto tryname;
}
@@ -2859,11 +2857,12 @@ auto_obstack name_obstack;
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.
IS_QUOTED_NAME is non-zero if the name token was originally quoted
- in single quotes. */
+ in single quotes. IS_AFTER_STRUCTOP is true if this name follows
+ a structure operator -- either '.' or ARROW */
static int
classify_name (struct parser_state *par_state, const struct block *block,
- int is_quoted_name)
+ bool is_quoted_name, bool is_after_structop)
{
struct block_symbol bsym;
char *copy;
@@ -2907,11 +2906,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 +2993,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, false, false);
type = check_typedef (context);
if (!type_aggregate_p (type))
@@ -3066,19 +3067,21 @@ yylex (void)
struct type *context_type = NULL;
int last_to_examine, next_to_examine, checkpoint;
const struct block *search_block;
- int is_quoted_name;
+ bool is_quoted_name, last_lex_was_structop;
if (popping && !VEC_empty (token_and_value, token_fifo))
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))
@@ -3091,7 +3094,7 @@ yylex (void)
last_was_coloncolon = current.token == COLONCOLON;
while (1)
{
- int ignore;
+ bool ignore;
/* We ignore quoted names other than the very first one.
Subsequent ones do not have any special meaning. */
@@ -3242,7 +3245,7 @@ c_parse (struct parser_state *par_state)
parser_debug);
/* Initialize some state used by the lexer. */
- last_was_structop = 0;
+ last_was_structop = false;
saw_name_at_eof = 0;
VEC_free (token_and_value, token_fifo);
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 0f02f4a97f..903d9f4cb6 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -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>
diff --git a/gdb/testsuite/gdb.cp/filename.cc b/gdb/testsuite/gdb.cp/filename.cc
index 45edf4efe9..d33ef78bcb 100644
--- a/gdb/testsuite/gdb.cp/filename.cc
+++ b/gdb/testsuite/gdb.cp/filename.cc
@@ -26,11 +26,31 @@ public:
}
void m() {
- /* stop here */
+ /* stop inside C */
}
};
+class D {
+public:
+ int includefile();
+
+ void m() {
+ /* stop inside D */
+ }
+};
+
+int D::includefile() {
+ return 24;
+}
+
int main() {
C c;
+ C* pc = &c;
c.m();
+
+ D d;
+ D* pd = &d;
+ d.m();
+
+ /* stop outside */
}
diff --git a/gdb/testsuite/gdb.cp/filename.exp b/gdb/testsuite/gdb.cp/filename.exp
index 971ffe715f..208179e7ca 100644
--- a/gdb/testsuite/gdb.cp/filename.exp
+++ b/gdb/testsuite/gdb.cp/filename.exp
@@ -26,8 +26,24 @@ 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 inside C"]
+gdb_continue_to_breakpoint "stop inside C"
gdb_test "print includefile\[0\]" " = 23"
+gdb_test "print this->includefile\[0\]" " = 23"
gdb_test "print 'includefile'::some_global" " = 27"
+
+gdb_breakpoint [gdb_get_line_number "stop inside D"]
+gdb_continue_to_breakpoint "stop inside D"
+
+gdb_test "print includefile()" " = 24"
+gdb_test "print this->includefile()" " = 24"
+gdb_test "print 'includefile'::some_global" " = 27"
+
+gdb_breakpoint [gdb_get_line_number "stop outside"]
+gdb_continue_to_breakpoint "stop outside"
+
+gdb_test "print c.includefile\[0\]" " = 23"
+gdb_test "print pc->includefile\[0\]" " = 23"
+gdb_test "print d.includefile()" " = 24"
+gdb_test "print pd->includefile()" " = 24"
--
2.16.0.rc1.238.g530d649a79-goog
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2] Do not classify C struct members as a filename
2018-01-25 16:00 ` [PATCH v2] " Tom Tromey
2018-01-25 16:20 ` [PATCH v4] " Leszek Swirski via gdb-patches
@ 2018-01-25 16:39 ` Leszek Swirski via gdb-patches
1 sibling, 0 replies; 9+ messages in thread
From: Leszek Swirski via gdb-patches @ 2018-01-25 16:39 UTC (permalink / raw)
To: Tom Tromey; +Cc: Leszek Swirski via gdb-patches
> This change makes sense (and thanks for updating that comment as well),
> but I wonder whether this changes the behavior in some case. Elsewhere
> in lex_one_token there is a check of saw_structop:
>
> else if (saw_structop)
> return COMPLETE;
>
> Previously this return could only be taken if parse_completion was set,
> but now I think it could be taken in other situations.
>
> So, I suspect "parse_completion &&" should be stuck in there.
Nice catch, thanks! I looked at the other users of saw_structop and
last_was_structop, and it looks like this is the only location that
needs an update. PTAL at v4.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v4] Do not classify C struct members as a filename
2018-01-25 16:20 ` [PATCH v4] " Leszek Swirski via gdb-patches
@ 2018-02-02 3:35 ` Simon Marchi
0 siblings, 0 replies; 9+ messages in thread
From: Simon Marchi @ 2018-02-02 3:35 UTC (permalink / raw)
To: Leszek Swirski, gdb-patches; +Cc: Tom Tromey
On 2018-01-25 11:20 AM, Leszek Swirski wrote:
> 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.
> ---
>
> Fix completion token to only appear on completion.
>
> gdb/ChangeLog | 5 +++++
> gdb/c-exp.y | 45 +++++++++++++++++++++------------------
> gdb/testsuite/ChangeLog | 6 ++++++
> gdb/testsuite/gdb.cp/filename.cc | 22 ++++++++++++++++++-
> gdb/testsuite/gdb.cp/filename.exp | 20 +++++++++++++++--
> 5 files changed, 74 insertions(+), 24 deletions(-)
Thanks for the update, I have pushed it.
Simon
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2018-02-02 3:35 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-24 16:51 [PATCH v2] Do not classify C struct members as a filename Leszek Swirski via gdb-patches
2018-01-25 2:39 ` Simon Marchi
2018-01-25 10:04 ` Leszek Swirski via gdb-patches
2018-01-25 14:52 ` Simon Marchi
2018-01-25 15:09 ` [PATCH v3] " Leszek Swirski via gdb-patches
2018-01-25 16:00 ` [PATCH v2] " Tom Tromey
2018-01-25 16:20 ` [PATCH v4] " Leszek Swirski via gdb-patches
2018-02-02 3:35 ` Simon Marchi
2018-01-25 16:39 ` [PATCH v2] " Leszek Swirski via gdb-patches
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).