* [RFA] Add parsing support for C++ operators
@ 2009-11-11 0:51 Keith Seitz
2009-11-11 15:12 ` Tom Tromey
2009-11-21 5:17 ` Pedro Alves
0 siblings, 2 replies; 5+ messages in thread
From: Keith Seitz @ 2009-11-11 0:51 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 1306 bytes --]
Hi,
The attached patch adds support to the parser for C++ operators. This
has the additional benefit of negating the need to single-quote operator
names during parsing, e.g., "print &foo::operator delete[] (void*)" now
works.
Comments/questions/concerns?
Keith
ChangeLog
2009-11-10 Keith Seitz <keiths@redhat.com>
* c-expy. (operator_stoken): New function.
(OPERATOR): New token.
(NEW): New token.
(DELETE): New token.
(operator): New rule.
(name): Add operator.
(ident_tokens): Add "new", "delete", and "operator".
* gdbtypes.c (rank_one_type): Don't complain about
void pointer conversion badness if both types are
void pointers.
testsuite/ChangeLog
2009-11-10 Keith Seitz <keiths@redhat.com>
* gdb.cp/cplusfuncs.cc (class foo): Add operators
new[] and delete[].
* gdb.cp/cplusfuncs.exp (dm_type_void): Change to
"void".
(probe_demangler): Remove all single-quoting of
method and variable names.
(info_func_regexp): Remove the word "void" from any
occurrence of "(void)".
(print_addr_2): Remove all single-quoting of
method names.
(print_addr_2_kfail): Likewise.
(print_addr): Single-quote C function names before
passing to print_addr_2.
(test_paddr_operator_functions): Remove single-quoting
for method names.
Add tests for operator new[] and operator delete[].
[-- Attachment #2: cpp-operators.patch --]
[-- Type: text/plain, Size: 12258 bytes --]
? cl.cpp-operators
? cl.dwarf2_physname
Index: c-exp.y
===================================================================
RCS file: /cvs/src/src/gdb/c-exp.y,v
retrieving revision 1.64
diff -u -p -r1.64 c-exp.y
--- c-exp.y 10 Nov 2009 22:17:58 -0000 1.64
+++ c-exp.y 11 Nov 2009 00:49:48 -0000
@@ -157,6 +157,7 @@ void yyerror (char *);
%{
/* YYSTYPE gets defined by %union */
static int parse_number (char *, int, int, YYSTYPE *);
+static struct stoken operator_stoken (const char *);
%}
%type <voidval> exp exp1 type_exp start variable qualified_name lcurly
@@ -199,9 +200,12 @@ static int parse_number (char *, int, in
%token <ssym> NAME_OR_INT
+%token OPERATOR
%token STRUCT CLASS UNION ENUM SIZEOF UNSIGNED COLONCOLON
%token TEMPLATE
%token ERROR
+%token NEW DELETE
+%type <sval> operator
/* Special type cases, put in to allow the parser to distinguish different
legal basetypes. */
@@ -1132,10 +1136,129 @@ const_or_volatile_noopt: const_and_vol
{ push_type (tp_volatile); }
;
+operator: OPERATOR NEW
+ { $$ = operator_stoken (" new"); }
+ | OPERATOR DELETE
+ { $$ = operator_stoken (" delete"); }
+ | OPERATOR NEW '[' ']'
+ { $$ = operator_stoken (" new[]"); }
+ | OPERATOR DELETE '[' ']'
+ { $$ = operator_stoken (" delete[]"); }
+ | OPERATOR '+'
+ { $$ = operator_stoken ("+"); }
+ | OPERATOR '-'
+ { $$ = operator_stoken ("-"); }
+ | OPERATOR '*'
+ { $$ = operator_stoken ("*"); }
+ | OPERATOR '/'
+ { $$ = operator_stoken ("/"); }
+ | OPERATOR '%'
+ { $$ = operator_stoken ("%"); }
+ | OPERATOR '^'
+ { $$ = operator_stoken ("^"); }
+ | OPERATOR '&'
+ { $$ = operator_stoken ("&"); }
+ | OPERATOR '|'
+ { $$ = operator_stoken ("|"); }
+ | OPERATOR '~'
+ { $$ = operator_stoken ("~"); }
+ | OPERATOR '!'
+ { $$ = operator_stoken ("!"); }
+ | OPERATOR '='
+ { $$ = operator_stoken ("="); }
+ | OPERATOR '<'
+ { $$ = operator_stoken ("<"); }
+ | OPERATOR '>'
+ { $$ = operator_stoken (">"); }
+ | OPERATOR ASSIGN_MODIFY
+ { const char *op = "unknown";
+ switch ($2)
+ {
+ case BINOP_RSH:
+ op = ">>=";
+ break;
+ case BINOP_LSH:
+ op = "<<=";
+ break;
+ case BINOP_ADD:
+ op = "+=";
+ break;
+ case BINOP_SUB:
+ op = "-=";
+ break;
+ case BINOP_MUL:
+ op = "*=";
+ break;
+ case BINOP_DIV:
+ op = "/=";
+ break;
+ case BINOP_REM:
+ op = "%=";
+ break;
+ case BINOP_BITWISE_IOR:
+ op = "|=";
+ break;
+ case BINOP_BITWISE_AND:
+ op = "&=";
+ break;
+ case BINOP_BITWISE_XOR:
+ op = "^=";
+ break;
+ default:
+ break;
+ }
+
+ $$ = operator_stoken (op);
+ }
+ | OPERATOR LSH
+ { $$ = operator_stoken ("<<"); }
+ | OPERATOR RSH
+ { $$ = operator_stoken (">>"); }
+ | OPERATOR EQUAL
+ { $$ = operator_stoken ("=="); }
+ | OPERATOR NOTEQUAL
+ { $$ = operator_stoken ("!="); }
+ | OPERATOR LEQ
+ { $$ = operator_stoken ("<="); }
+ | OPERATOR GEQ
+ { $$ = operator_stoken (">="); }
+ | OPERATOR ANDAND
+ { $$ = operator_stoken ("&&"); }
+ | OPERATOR OROR
+ { $$ = operator_stoken ("||"); }
+ | OPERATOR INCREMENT
+ { $$ = operator_stoken ("++"); }
+ | OPERATOR DECREMENT
+ { $$ = operator_stoken ("--"); }
+ | OPERATOR ','
+ { $$ = operator_stoken (","); }
+ | OPERATOR ARROW_STAR
+ { $$ = operator_stoken ("->*"); }
+ | OPERATOR ARROW
+ { $$ = operator_stoken ("->"); }
+ | OPERATOR '(' ')'
+ { $$ = operator_stoken ("()"); }
+ | OPERATOR '[' ']'
+ { $$ = operator_stoken ("[]"); }
+ | OPERATOR ptype
+ { char *name;
+ long length;
+ struct ui_file *buf = mem_fileopen ();
+
+ c_print_type ($2, NULL, buf, -1, 0);
+ name = ui_file_xstrdup (buf, &length);
+ ui_file_delete (buf);
+ $$ = operator_stoken (name);
+ }
+ ;
+
+
+
name : NAME { $$ = $1.stoken; }
| BLOCKNAME { $$ = $1.stoken; }
| TYPENAME { $$ = $1.stoken; }
| NAME_OR_INT { $$ = $1.stoken; }
+ | operator { $$ = $1; }
;
name_not_typename : NAME
@@ -1151,6 +1274,23 @@ name_not_typename : NAME
%%
+/* Returns a stoken of the operator name given by OP (which does not
+ include the string "operator"). */
+static struct stoken
+operator_stoken (const char *op)
+{
+ static const char *operator_string = "operator";
+ struct stoken st = { NULL, 0 };
+ st.length = strlen (operator_string) + strlen (op);
+ st.ptr = malloc (st.length + 1);
+ strcpy (st.ptr, operator_string);
+ strcat (st.ptr, op);
+
+ /* The toplevel (c_parse) will free the memory allocated here. */
+ make_cleanup (free, st.ptr);
+ return st;
+};
+
/* Take care of parsing a number (anything that starts with a digit).
Set yylval and return the token type; update lexptr.
LEN is the number of characters in it. */
@@ -1729,6 +1869,9 @@ static const struct token ident_tokens[]
{"long", LONG, OP_NULL, 0},
{"true", TRUEKEYWORD, OP_NULL, 1},
{"int", INT_KEYWORD, OP_NULL, 0},
+ {"new", NEW, OP_NULL, 1},
+ {"delete", DELETE, OP_NULL, 1},
+ {"operator", OPERATOR, OP_NULL, 1},
{"and", ANDAND, BINOP_END, 1},
{"and_eq", ASSIGN_MODIFY, BINOP_BITWISE_AND, 1},
Index: gdbtypes.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbtypes.c,v
retrieving revision 1.176
diff -u -p -r1.176 gdbtypes.c
--- gdbtypes.c 2 Jul 2009 12:57:14 -0000 1.176
+++ gdbtypes.c 11 Nov 2009 00:49:49 -0000
@@ -2004,7 +2004,8 @@ rank_one_type (struct type *parm, struct
switch (TYPE_CODE (arg))
{
case TYPE_CODE_PTR:
- if (TYPE_CODE (TYPE_TARGET_TYPE (parm)) == TYPE_CODE_VOID)
+ if (TYPE_CODE (TYPE_TARGET_TYPE (parm)) == TYPE_CODE_VOID
+ && TYPE_CODE (TYPE_TARGET_TYPE (arg)) != TYPE_CODE_VOID)
return VOID_PTR_CONVERSION_BADNESS;
else
return rank_one_type (TYPE_TARGET_TYPE (parm),
Index: testsuite/gdb.cp/cplusfuncs.cc
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.cp/cplusfuncs.cc,v
retrieving revision 1.1
diff -u -p -r1.1 cplusfuncs.cc
--- testsuite/gdb.cp/cplusfuncs.cc 23 Aug 2003 03:55:59 -0000 1.1
+++ testsuite/gdb.cp/cplusfuncs.cc 11 Nov 2009 00:49:50 -0000
@@ -46,7 +46,9 @@ public:
void operator [] (foo&);
void operator () (foo&);
void* operator new (size_t) throw ();
+ void* operator new[] (size_t) throw ();
void operator delete (void *);
+ void operator delete[] (void *);
/**/ operator int ();
/**/ operator char* ();
@@ -115,7 +117,9 @@ void foo::operator ->* (foo& afoo) {
void foo::operator [] (foo& afoo) { afoo.ifoo = 0; }
void foo::operator () (foo& afoo) { afoo.ifoo = 0; }
void* foo::operator new (size_t ival) throw () { ival = 0; return 0; }
+void* foo::operator new[] (size_t ival) throw () { ival = 0; return 0; }
void foo::operator delete (void *ptr) { ptr = 0; }
+void foo::operator delete[] (void *ptr) { ptr = 0; }
/**/ foo::operator int () { return 0; }
/**/ foo::operator char* () { return 0; }
Index: testsuite/gdb.cp/cplusfuncs.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.cp/cplusfuncs.exp,v
retrieving revision 1.8
diff -u -p -r1.8 cplusfuncs.exp
--- testsuite/gdb.cp/cplusfuncs.exp 21 Sep 2009 19:46:15 -0000 1.8
+++ testsuite/gdb.cp/cplusfuncs.exp 11 Nov 2009 00:49:50 -0000
@@ -63,7 +63,7 @@ set dm_type_foo_ref "foo&"
set dm_type_int_star "int*"
set dm_type_long_star "long*"
set dm_type_unsigned_int "unsigned"
-set dm_type_void ""
+set dm_type_void "void"
set dm_type_void_star "void*"
proc probe_demangler { } {
@@ -78,7 +78,7 @@ proc probe_demangler { } {
global dm_type_void
global dm_type_void_star
- send_gdb "print &'foo::operator,(foo&)'\n"
+ send_gdb "print &foo::operator,(foo&)\n"
gdb_expect {
-re ".*foo::operator, \\(.*foo.*&.*\\).*\r\n$gdb_prompt $" {
# v2 demangler
@@ -97,7 +97,7 @@ proc probe_demangler { } {
}
}
- send_gdb "print &'dm_type_char_star'\n"
+ send_gdb "print &dm_type_char_star\n"
gdb_expect {
-re ".*dm_type_char_star\\(char \\*\\).*\r\n$gdb_prompt $" {
# v2 demangler
@@ -117,7 +117,7 @@ proc probe_demangler { } {
}
}
- send_gdb "print &'dm_type_foo_ref'\n"
+ send_gdb "print &dm_type_foo_ref\n"
gdb_expect {
-re ".*dm_type_foo_ref\\(foo &\\).*\r\n$gdb_prompt $" {
# v2 demangler
@@ -136,7 +136,7 @@ proc probe_demangler { } {
}
}
- send_gdb "print &'dm_type_int_star'\n"
+ send_gdb "print &dm_type_int_star\n"
gdb_expect {
-re ".*dm_type_int_star\\(int \\*\\).*\r\n$gdb_prompt $" {
# v2 demangler
@@ -155,7 +155,7 @@ proc probe_demangler { } {
}
}
- send_gdb "print &'dm_type_long_star'\n"
+ send_gdb "print &dm_type_long_star\n"
gdb_expect {
-re ".*dm_type_long_star\\(long \\*\\).*\r\n$gdb_prompt $" {
# v2 demangler
@@ -174,7 +174,7 @@ proc probe_demangler { } {
}
}
- send_gdb "print &'dm_type_unsigned_int'\n"
+ send_gdb "print &dm_type_unsigned_int\n"
gdb_expect {
-re ".*dm_type_unsigned_int\\(unsigned int\\).*\r\n$gdb_prompt $" {
# v2 demangler
@@ -193,7 +193,7 @@ proc probe_demangler { } {
}
}
- send_gdb "print &'dm_type_void'\n"
+ send_gdb "print &dm_type_void\n"
gdb_expect {
-re ".*dm_type_void\\(void\\).*\r\n$gdb_prompt $" {
# v2 demangler
@@ -212,7 +212,7 @@ proc probe_demangler { } {
}
}
- send_gdb "print &'dm_type_void_star'\n"
+ send_gdb "print &dm_type_void_star\n"
gdb_expect {
-re ".*dm_type_void_star\\(void \\*\\).*\r\n$gdb_prompt $" {
# v2 demangler
@@ -241,6 +241,7 @@ proc info_func_regexp { name demangled }
global gdb_prompt
send_gdb "info function $name\n"
+ set demangled [regsub {\\\(void\\\)} $demangled {\(\)}]
gdb_expect {
-re ".*File .*:\r\n(class |)$demangled\r\n.*$gdb_prompt $" {
pass "info function for \"$name\""
@@ -277,16 +278,16 @@ proc print_addr_2 { name good } {
set good_pattern [string_to_regexp $good]
- send_gdb "print &'$name'\n"
+ send_gdb "print &$name\n"
gdb_expect {
-re ".* = .* $hex <$good_pattern>\r\n$gdb_prompt $" {
- pass "print &'$name'"
+ pass "print &$name"
}
-re ".*$gdb_prompt $" {
- fail "print &'$name'"
+ fail "print &$name"
}
timeout {
- fail "print &'$name' (timeout)"
+ fail "print &$name (timeout)"
}
}
}
@@ -305,19 +306,19 @@ proc print_addr_2_kfail { name good bad
set good_pattern [string_to_regexp $good]
set bad_pattern [string_to_regexp $bad]
- send_gdb "print &'$name'\n"
+ send_gdb "print &$name\n"
gdb_expect {
-re ".* = .* $hex <$good_pattern>\r\n$gdb_prompt $" {
- pass "print &'$name'"
+ pass "print &$name"
}
-re ".* = .* $hex <$bad_pattern>\r\n$gdb_prompt $" {
- kfail $bugid "print &'$name'"
+ kfail $bugid "print &$name"
}
-re ".*$gdb_prompt $" {
- fail "print &'$name'"
+ fail "print &$name"
}
timeout {
- fail "print &'$name' (timeout)"
+ fail "print &$name (timeout)"
}
}
}
@@ -327,7 +328,12 @@ proc print_addr_2_kfail { name good bad
#
proc print_addr { name } {
- print_addr_2 "$name" "$name"
+ set expected [regsub {\(void\)} $name {()}]
+ if {[string first "::" $name] == -1} {
+ # C function -- must be qutoed
+ set name "'$name'"
+ }
+ print_addr_2 "$name" $expected
}
#
@@ -460,10 +466,13 @@ proc test_paddr_operator_functions {} {
print_addr "foo::operator\[\]($dm_type_foo_ref)"
print_addr "foo::operator()($dm_type_foo_ref)"
- gdb_test "print &'foo::operator new'" \
+ gdb_test "print &foo::operator new" \
" = .* $hex <foo::operator new\\(.*\\)(| static)>"
+ gdb_test "print &foo::operator new\[\]" \
+ " = .* $hex <foo::operator new\\\[\\\]\\(.*\\)(| static)>"
if { !$hp_aCC_compiler } {
print_addr "foo::operator delete($dm_type_void_star)"
+ print_addr "foo::operator delete[]($dm_type_void_star)"
} else {
gdb_test "print &'foo::operator delete($dm_type_void_star) static'" \
" = .*(0x\[0-9a-f\]+|) <foo::operator delete.*>"
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [RFA] Add parsing support for C++ operators
2009-11-11 0:51 [RFA] Add parsing support for C++ operators Keith Seitz
@ 2009-11-11 15:12 ` Tom Tromey
2009-11-11 16:47 ` Keith Seitz
2009-11-21 5:17 ` Pedro Alves
1 sibling, 1 reply; 5+ messages in thread
From: Tom Tromey @ 2009-11-11 15:12 UTC (permalink / raw)
To: Keith Seitz; +Cc: gdb-patches
>>>>> "Keith" == Keith Seitz <keiths@redhat.com> writes:
Keith> 2009-11-10 Keith Seitz <keiths@redhat.com>
Keith> * c-expy. (operator_stoken): New function.
Keith> (OPERATOR): New token.
Keith> (NEW): New token.
Keith> (DELETE): New token.
Keith> (operator): New rule.
Keith> (name): Add operator.
Keith> (ident_tokens): Add "new", "delete", and "operator".
Keith> * gdbtypes.c (rank_one_type): Don't complain about
Keith> void pointer conversion badness if both types are
Keith> void pointers.
Keith> + | OPERATOR ptype
Keith> + { char *name;
Keith> + long length;
Keith> + struct ui_file *buf = mem_fileopen ();
Keith> +
Keith> + c_print_type ($2, NULL, buf, -1, 0);
Keith> + name = ui_file_xstrdup (buf, &length);
Keith> + ui_file_delete (buf);
Keith> + $$ = operator_stoken (name);
This leaks 'name', you need a free after the call to operator_stoken.
Keith> + /* The toplevel (c_parse) will free the memory allocated here. */
Keith> + make_cleanup (free, st.ptr);
Keith> + return st;
On irc you expressed some doubt about this approach. It is fine.
This is ok with the above change. Thanks.
Tom
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [RFA] Add parsing support for C++ operators
2009-11-11 15:12 ` Tom Tromey
@ 2009-11-11 16:47 ` Keith Seitz
0 siblings, 0 replies; 5+ messages in thread
From: Keith Seitz @ 2009-11-11 16:47 UTC (permalink / raw)
To: tromey; +Cc: gdb-patches
On 11/11/2009 07:11 AM, Tom Tromey wrote:
>>>>>> "Keith" == Keith Seitz<keiths@redhat.com> writes:
> Keith> + | OPERATOR ptype
> Keith> + { char *name;
> Keith> + long length;
> Keith> + struct ui_file *buf = mem_fileopen ();
> Keith> +
> Keith> + c_print_type ($2, NULL, buf, -1, 0);
> Keith> + name = ui_file_xstrdup (buf,&length);
> Keith> + ui_file_delete (buf);
> Keith> + $$ = operator_stoken (name);
>
> This leaks 'name', you need a free after the call to operator_stoken.
Indeed! Overzealous pre-submission cleanup...
> This is ok with the above change. Thanks.
I have committed this patch. Thank you for reviewing it.
Keith
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [RFA] Add parsing support for C++ operators
2009-11-11 0:51 [RFA] Add parsing support for C++ operators Keith Seitz
2009-11-11 15:12 ` Tom Tromey
@ 2009-11-21 5:17 ` Pedro Alves
2009-11-21 19:05 ` Keith Seitz
1 sibling, 1 reply; 5+ messages in thread
From: Pedro Alves @ 2009-11-21 5:17 UTC (permalink / raw)
To: gdb-patches; +Cc: Keith Seitz
On Wednesday 11 November 2009 00:51:31, Keith Seitz wrote:
> + set expected [regsub {\(void\)} $name {()}]
> + set demangled [regsub {\\\(void\\\)} $demangled {\(\)}]
This syntax doesn't work on older tcl's:
ERROR: tcl error sourcing ../../../src/gdb/testsuite/gdb.cp/cplusfuncs.exp.
ERROR: wrong # args: should be "regsub ?switches? exp string subSpec varName"
while executing
"regsub {\(void\)} $name {()}"
(procedure "print_addr" line 2)
invoked from within
"print_addr "overload1arg($dm_type_void)""
:
I'm applying the fix below to use the old regsub syntax.
(this patch doesn't conflict with your pending patches)
Keith, I've found a similar issue in your new cpexprs.exp test.
I'm using this local change on top of your patch:
Index: src/gdb/testsuite/gdb.cp/cpexprs.exp
===================================================================
--- src.orig/gdb/testsuite/gdb.cp/cpexprs.exp 2009-11-21 01:26:00.000000000 +0000
+++ src/gdb/testsuite/gdb.cp/cpexprs.exp 2009-11-21 01:26:13.000000000 +0000
@@ -73,7 +73,7 @@ proc add {func type print lst} {
# An exception: since gdb canonicalizes C++ output,
# "(void)" must be mutated to "()".
- set print [regsub {\(void\)} $print {()}]
+ regsub {\(void\)} $print {()} print
--
Pedro Alves
2009-11-21 Pedro Alves <pedro@codesourcery.com>
* gdb.cp/cplusfuncs.exp (info_func_regexp, print_addr): Don't
assume new `regsub' syntax available.
---
gdb/testsuite/gdb.cp/cplusfuncs.exp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
Index: src/gdb/testsuite/gdb.cp/cplusfuncs.exp
===================================================================
--- src.orig/gdb/testsuite/gdb.cp/cplusfuncs.exp 2009-11-21 01:42:01.000000000 +0000
+++ src/gdb/testsuite/gdb.cp/cplusfuncs.exp 2009-11-21 01:43:25.000000000 +0000
@@ -241,7 +241,7 @@ proc info_func_regexp { name demangled }
global gdb_prompt
send_gdb "info function $name\n"
- set demangled [regsub {\\\(void\\\)} $demangled {\(\)}]
+ regsub {\\\(void\\\)} $demangled {\(\)} demangled
gdb_expect {
-re ".*File .*:\r\n(class |)$demangled\r\n.*$gdb_prompt $" {
pass "info function for \"$name\""
@@ -328,7 +328,7 @@ proc print_addr_2_kfail { name good bad
#
proc print_addr { name } {
- set expected [regsub {\(void\)} $name {()}]
+ regsub {\(void\)} $name {()} expected
if {[string first "::" $name] == -1} {
# C function -- must be qutoed
set name "'$name'"
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2009-11-21 19:05 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-11-11 0:51 [RFA] Add parsing support for C++ operators Keith Seitz
2009-11-11 15:12 ` Tom Tromey
2009-11-11 16:47 ` Keith Seitz
2009-11-21 5:17 ` Pedro Alves
2009-11-21 19:05 ` Keith Seitz
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox