From: Tom Tromey <tromey@redhat.com>
To: gdb-patches@sourceware.org
Subject: RFC: fix PR symtab/11464
Date: Thu, 10 Jan 2013 19:51:00 -0000 [thread overview]
Message-ID: <87hamovmu7.fsf@fleche.redhat.com> (raw)
This patch fixes PR symtab/11464.
The bug is that using a quoted destructor in an expression crashes gdb.
The example from the PR is: ptype gnu_obj_1::'~gnu_obj_1'
This is odd, but of course shouldn't crash.
The basic problem was that when yylex and classify_inner_name were
updated to handle NAME in addition to TYPENAME, nothing was done to
ensure that the value of yylval seen by classify_inner_name actually had
a valid 'tsym.type' field. And, in this case, it doesn't.
The patch fixes this by making some state more explicit. I think this
is a plus -- really the whole lexer could use a cleanup along these
lines, removing most uses of yylval, ensuring that the proper union
fields are always used, etc. But, I didn't go that far.
Built and regtested on x86-64 Fedora 16.
A new test case, from the PR, is included -- I didn't include the full
patch from the PR as it also covers a couple of unrelated bugs.
Tom
2013-01-10 Tom Tromey <tromey@redhat.com>
PR symtab/11464:
* c-exp.y (lex_one_token): Initialize other fields of yylval on
NAME return.
(classify_inner_name): Remove 'first_name' argument, add
'context'. Remove unused variable.
(yylex): Explicitly maintain the context type. Exit loop earlier
if NAME result is seen.
2013-01-10 Tom Tromey <tromey@redhat.com>
* gdb.cp/m-static.cc (gnu_obj_1::~gnu_obj_1): New destructor.
* gdb.cp/m-static.exp: Add tests to print quoted destructor.
diff --git a/gdb/c-exp.y b/gdb/c-exp.y
index 9847120..9ef4b39 100644
--- a/gdb/c-exp.y
+++ b/gdb/c-exp.y
@@ -2719,6 +2719,10 @@ lex_one_token (void)
if (parse_completion && *lexptr == '\0')
saw_name_at_eof = 1;
+
+ yylval.ssym.stoken = yylval.sval;
+ yylval.ssym.sym = NULL;
+ yylval.ssym.is_a_field_of_this = 0;
return NAME;
}
@@ -2859,26 +2863,26 @@ classify_name (const struct block *block)
}
/* Like classify_name, but used by the inner loop of the lexer, when a
- name might have already been seen. FIRST_NAME is true if the token
- in `yylval' is the first component of a name, false otherwise. */
+ name might have already been seen. CONTEXT is the context type, or
+ NULL if this is the first component of a name. */
static int
-classify_inner_name (const struct block *block, int first_name)
+classify_inner_name (const struct block *block, struct type *context)
{
- struct type *type, *new_type;
+ struct type *type;
char *copy;
- if (first_name)
+ if (context == NULL)
return classify_name (block);
- type = check_typedef (yylval.tsym.type);
+ type = check_typedef (context);
if (TYPE_CODE (type) != TYPE_CODE_STRUCT
&& TYPE_CODE (type) != TYPE_CODE_UNION
&& TYPE_CODE (type) != TYPE_CODE_NAMESPACE)
return ERROR;
- copy = copy_name (yylval.tsym.stoken);
- yylval.ssym.sym = cp_lookup_nested_symbol (yylval.tsym.type, copy, block);
+ copy = copy_name (yylval.ssym.stoken);
+ yylval.ssym.sym = cp_lookup_nested_symbol (type, copy, block);
if (yylval.ssym.sym == NULL)
return ERROR;
@@ -2893,7 +2897,6 @@ classify_inner_name (const struct block *block, int first_name)
return TYPENAME;
default:
- yylval.ssym.is_a_field_of_this = 0;
return NAME;
}
internal_error (__FILE__, __LINE__, _("not reached"));
@@ -2915,6 +2918,7 @@ yylex (void)
{
token_and_value current;
int first_was_coloncolon, last_was_coloncolon, first_iter;
+ struct type *context_type = NULL;
if (popping && !VEC_empty (token_and_value, token_fifo))
{
@@ -2936,7 +2940,10 @@ yylex (void)
last_was_coloncolon = first_was_coloncolon;
obstack_free (&name_obstack, obstack_base (&name_obstack));
if (!last_was_coloncolon)
- obstack_grow (&name_obstack, yylval.sval.ptr, yylval.sval.length);
+ {
+ obstack_grow (&name_obstack, yylval.sval.ptr, yylval.sval.length);
+ context_type = yylval.tsym.type;
+ }
current.value = yylval;
first_iter = 1;
while (1)
@@ -2953,7 +2960,7 @@ yylex (void)
classification = classify_inner_name (first_was_coloncolon
? NULL
: expression_context_block,
- first_iter);
+ context_type);
/* We keep going until we either run out of names, or until
we have a qualified name which is not a type. */
if (classification != TYPENAME && classification != NAME)
@@ -2964,7 +2971,7 @@ yylex (void)
}
/* Update the partial name we are constructing. */
- if (!first_iter)
+ if (context_type != NULL)
{
/* We don't want to put a leading "::" into the name. */
obstack_grow_str (&name_obstack, "::");
@@ -2978,6 +2985,11 @@ yylex (void)
current.token = classification;
last_was_coloncolon = 0;
+
+ if (classification == NAME)
+ break;
+
+ context_type = yylval.tsym.type;
}
else if (next.token == COLONCOLON && !last_was_coloncolon)
last_was_coloncolon = 1;
diff --git a/gdb/testsuite/gdb.cp/m-static.cc b/gdb/testsuite/gdb.cp/m-static.cc
index e9dce18..8472988 100644
--- a/gdb/testsuite/gdb.cp/m-static.cc
+++ b/gdb/testsuite/gdb.cp/m-static.cc
@@ -17,6 +17,7 @@ protected:
public:
gnu_obj_1(antiquities a, long l) {}
+ ~gnu_obj_1() {}
long method ()
{
diff --git a/gdb/testsuite/gdb.cp/m-static.exp b/gdb/testsuite/gdb.cp/m-static.exp
index 38d2498..ae4b2ad 100644
--- a/gdb/testsuite/gdb.cp/m-static.exp
+++ b/gdb/testsuite/gdb.cp/m-static.exp
@@ -64,6 +64,14 @@ gdb_test "print test1.key2" "\\$\[0-9\]* = 77" "simple object, static long"
# simple object, static enum
gdb_test "print test1.value" "\\$\[0-9\]* = oriental" "simple object, static enum"
+gdb_test "print test1.'~gnu_obj_1'" \
+ { = {void \(gnu_obj_1 \*( const)?, int\)} 0x[0-9a-f]+ <gnu_obj_1::~gnu_obj_1\(\)>} \
+ "simple object instance, print quoted destructor"
+
+gdb_test "ptype gnu_obj_1::'~gnu_obj_1'" \
+ {type = void \(gnu_obj_1 \* const\)} \
+ "simple object class, ptype quoted destructor"
+
# Two.
# derived template object, base static const bool
next reply other threads:[~2013-01-10 19:51 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-01-10 19:51 Tom Tromey [this message]
2013-02-03 5:45 ` Jan Kratochvil
2013-02-04 16:33 ` Tom Tromey
2013-02-04 21:47 ` Tom Tromey
2013-02-07 19:15 ` Jan Kratochvil
2013-02-11 20:28 ` Tom Tromey
2013-02-11 20:39 ` Jan Kratochvil
2013-02-11 20:45 ` Tom Tromey
2013-02-11 20:58 ` Jan Kratochvil
2013-02-12 20:20 ` Tom Tromey
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87hamovmu7.fsf@fleche.redhat.com \
--to=tromey@redhat.com \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox