* C++/Java regressions
@ 2003-11-25 1:37 David Carlton
2003-11-25 1:48 ` The demangler was rewritten from scratch! Andrew Cagney
` (2 more replies)
0 siblings, 3 replies; 27+ messages in thread
From: David Carlton @ 2003-11-25 1:37 UTC (permalink / raw)
To: gdb, ian
I did a CVS update on GDB for the first time in 4 days, and I got the
following testsuite changes:
-PASS: gdb.cp/method.exp: continue to A::bar
+FAIL: gdb.cp/method.exp: continue to A::bar
-KFAIL: gdb.cp/templates.exp: ptype T5<int> (PRMS: gdb/1111)
-KFAIL: gdb.cp/templates.exp: ptype T5<int> (PRMS: gdb/1111)
+FAIL: gdb.cp/templates.exp: ptype T5<int>
+FAIL: gdb.cp/templates.exp: ptype t5i
PASS: gdb.java/jmisc1.exp: set language to "java"
+FAIL: gdb.java/jmisc1.exp: setting breakpoint at jmisc.main(java.lang.String[]) FAIL: gdb.java/jmisc1.exp: ptype jmisc
-PASS: gdb.java/jmisc1.exp: p args
-PASS: gdb.java/jmisc1.exp: p *args
-PASS: gdb.java/jmisc1.exp: break exit
-PASS: gdb.java/jmisc1.exp: continue to exit
+FAIL: gdb.java/jmisc1.exp: p args
+FAIL: gdb.java/jmisc1.exp: p *args
+FAIL: gdb.java/jmisc1.exp: break exit
+FAIL: gdb.java/jmisc1.exp: continue to exit (the program is no longer running)
Running ./gdb.java/jmisc2.exp ...
PASS: gdb.java/jmisc2.exp: set print sevenbit-strings
PASS: gdb.java/jmisc2.exp: set language to "java"
FAIL: gdb.java/jmisc2.exp: ptype jmisc
-PASS: gdb.java/jmisc2.exp: p args
-PASS: gdb.java/jmisc2.exp: p *args
+FAIL: gdb.java/jmisc2.exp: setting breakpoint at jmisc.main(java.lang.String[])+FAIL: gdb.java/jmisc2.exp: p args
+FAIL: gdb.java/jmisc2.exp: p *args
I haven't looked in detail; I tend to suspect the recent demangler
changes, but I could be wrong.
David Carlton
carlton@kealia.com
^ permalink raw reply [flat|nested] 27+ messages in thread
* The demangler was rewritten from scratch!
2003-11-25 1:37 C++/Java regressions David Carlton
@ 2003-11-25 1:48 ` Andrew Cagney
2003-11-25 3:58 ` C++/Java regressions Ian Lance Taylor
2003-11-26 4:04 ` Ian Lance Taylor
2 siblings, 0 replies; 27+ messages in thread
From: Andrew Cagney @ 2003-11-25 1:48 UTC (permalink / raw)
To: gdb; +Cc: David Carlton, ian
> I did a CVS update on GDB for the first time in 4 days, and I got the
> following testsuite changes:
Which reminds me. No problem with the theory but a definite heads up is
needed for GDB! :-)
Andrew
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: C++/Java regressions
2003-11-25 1:37 C++/Java regressions David Carlton
2003-11-25 1:48 ` The demangler was rewritten from scratch! Andrew Cagney
@ 2003-11-25 3:58 ` Ian Lance Taylor
2003-11-26 4:04 ` Ian Lance Taylor
2 siblings, 0 replies; 27+ messages in thread
From: Ian Lance Taylor @ 2003-11-25 3:58 UTC (permalink / raw)
To: David Carlton; +Cc: gdb
David Carlton <carlton@kealia.com> writes:
> I did a CVS update on GDB for the first time in 4 days, and I got the
> following testsuite changes:
I ran the gdb testsuite both before and after the demangler changes,
and they appeared to make no significant difference. I enclose the
diff of gdb.sum. I've continued to run the gdb testsuite for each
significant demangler change.
I'm not saying that the problem is not the demangler. I don't know
what the problem is. If you can give more information, I would be
happy to adjust the demangler.
Ian
--- gdb.sum.hold Thu Nov 20 12:51:15 2003
+++ gdb.sum Sat Nov 22 11:15:26 2003
@@ -1,4 +1,4 @@
-Test Run By ian on Tue Nov 18 22:52:40 2003
+Test Run By ian on Sat Nov 22 11:10:33 2003
Native configuration is i686-pc-linux-gnu
=== gdb tests ===
@@ -2973,7 +2973,7 @@
PASS: gdb.base/page.exp: q
Running ../../../src/gdb/testsuite/gdb.base/pc-fp.exp ...
PASS: gdb.base/pc-fp.exp: get value of $pc (0x8048489)
-PASS: gdb.base/pc-fp.exp: get value of $fp (0xbfffe788)
+PASS: gdb.base/pc-fp.exp: get value of $fp (0xbfffe388)
PASS: gdb.base/pc-fp.exp: display/i $pc
PASS: gdb.base/pc-fp.exp: display/w $fp
Running ../../../src/gdb/testsuite/gdb.base/pointers.exp ...
@@ -5635,7 +5635,7 @@
PASS: gdb.cp/cplusfuncs.exp: print &'overload1arg(short)'
PASS: gdb.cp/cplusfuncs.exp: print &'overload1arg(unsigned short)'
PASS: gdb.cp/cplusfuncs.exp: print &'overload1arg(int)'
-PASS: gdb.cp/cplusfuncs.exp: print &'overload1arg(unsigned)'
+PASS: gdb.cp/cplusfuncs.exp: print &'overload1arg(unsigned int)'
PASS: gdb.cp/cplusfuncs.exp: print &'overload1arg(long)'
PASS: gdb.cp/cplusfuncs.exp: print &'overload1arg(unsigned long)'
PASS: gdb.cp/cplusfuncs.exp: print &'overload1arg(float)'
@@ -5697,9 +5697,9 @@
PASS: gdb.cp/cplusfuncs.exp: print &'hairyfunc2'
PASS: gdb.cp/cplusfuncs.exp: print &'hairyfunc3'
PASS: gdb.cp/cplusfuncs.exp: print &'hairyfunc4'
-KFAIL: gdb.cp/cplusfuncs.exp: print &'hairyfunc5' (PRMS: gdb/19)
-KFAIL: gdb.cp/cplusfuncs.exp: print &'hairyfunc6' (PRMS: gdb/19)
-KFAIL: gdb.cp/cplusfuncs.exp: print &'hairyfunc7' (PRMS: gdb/19)
+PASS: gdb.cp/cplusfuncs.exp: print &'hairyfunc5'
+PASS: gdb.cp/cplusfuncs.exp: print &'hairyfunc6'
+PASS: gdb.cp/cplusfuncs.exp: print &'hairyfunc7'
PASS: gdb.cp/cplusfuncs.exp: info function for "operator\*("
PASS: gdb.cp/cplusfuncs.exp: info function for "operator%("
PASS: gdb.cp/cplusfuncs.exp: info function for "operator-("
@@ -9473,11 +9473,11 @@
PASS: gdb.threads/print-threads.exp: Hit kill breakpoint, 7 (slow with kill breakpoint)
PASS: gdb.threads/print-threads.exp: Hit thread_function breakpoint, 3 (slow with kill breakpoint)
PASS: gdb.threads/print-threads.exp: Hit kill breakpoint, 8 (slow with kill breakpoint)
-PASS: gdb.threads/print-threads.exp: Hit kill breakpoint, 9 (slow with kill breakpoint)
PASS: gdb.threads/print-threads.exp: Hit thread_function breakpoint, 4 (slow with kill breakpoint)
+PASS: gdb.threads/print-threads.exp: Hit kill breakpoint, 9 (slow with kill breakpoint)
PASS: gdb.threads/print-threads.exp: Hit kill breakpoint, 10 (slow with kill breakpoint)
-PASS: gdb.threads/print-threads.exp: Hit thread_function breakpoint, 5 (slow with kill breakpoint)
PASS: gdb.threads/print-threads.exp: Hit kill breakpoint, 11 (slow with kill breakpoint)
+PASS: gdb.threads/print-threads.exp: Hit thread_function breakpoint, 5 (slow with kill breakpoint)
KFAIL: gdb.threads/print-threads.exp: Running threads (slow with kill breakpoint) (zombie thread) (PRMS: gdb/1265)
Running ../../../src/gdb/testsuite/gdb.threads/pthreads.exp ...
PASS: gdb.threads/pthreads.exp: successfully compiled posix threads test case
@@ -9516,8 +9516,7 @@
PASS: gdb.threads/pthreads.exp: check backtrace from thread 2
PASS: gdb.threads/pthreads.exp: apply backtrace command to all three threads
PASS: gdb.threads/pthreads.exp: set break at common_routine in thread 2
-PASS: gdb.threads/pthreads.exp: continue to bkpt at common_routine in thread 2
-PASS: gdb.threads/pthreads.exp: backtrace from thread 2 bkpt in common_routine
+FAIL: gdb.threads/pthreads.exp: continue to bkpt at common_routine in thread 2
Running ../../../src/gdb/testsuite/gdb.threads/schedlock.exp ...
PASS: gdb.threads/schedlock.exp: successfully compiled posix threads test case
PASS: gdb.threads/schedlock.exp: shell stty intr '^C'
@@ -9562,9 +9561,9 @@
PASS: gdb.threads/schedlock.exp: listed args (4)
PASS: gdb.threads/schedlock.exp: other thread 0 didn't run
PASS: gdb.threads/schedlock.exp: other thread 1 didn't run
-PASS: gdb.threads/schedlock.exp: other thread 2 didn't run
-PASS: gdb.threads/schedlock.exp: other thread 3 didn't run
PASS: gdb.threads/schedlock.exp: current thread ran
+PASS: gdb.threads/schedlock.exp: other thread 3 didn't run
+PASS: gdb.threads/schedlock.exp: other thread 4 didn't run
PASS: gdb.threads/schedlock.exp: other thread 5 didn't run
PASS: gdb.threads/schedlock.exp: step to increment (locked 0)
PASS: gdb.threads/schedlock.exp: step to increment (locked 1)
@@ -9581,9 +9580,9 @@
PASS: gdb.threads/schedlock.exp: listed args (5)
PASS: gdb.threads/schedlock.exp: other thread 0 didn't run (stepping)
PASS: gdb.threads/schedlock.exp: other thread 1 didn't run (stepping)
-PASS: gdb.threads/schedlock.exp: other thread 2 didn't run (stepping)
-PASS: gdb.threads/schedlock.exp: other thread 3 didn't run (stepping)
PASS: gdb.threads/schedlock.exp: current thread stepped locked
+PASS: gdb.threads/schedlock.exp: other thread 3 didn't run (stepping)
+PASS: gdb.threads/schedlock.exp: other thread 4 didn't run (stepping)
PASS: gdb.threads/schedlock.exp: other thread 5 didn't run (stepping)
Running ../../../src/gdb/testsuite/gdb.threads/step.exp ...
Running ../../../src/gdb/testsuite/gdb.threads/step2.exp ...
@@ -9736,11 +9735,11 @@
=== gdb Summary ===
-# of expected passes 8994
-# of unexpected failures 293
+# of expected passes 8995
+# of unexpected failures 294
# of unexpected successes 1
# of expected failures 71
-# of known failures 11
+# of known failures 8
# of unresolved testcases 20
# of untested testcases 6
# of unsupported tests 4
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: C++/Java regressions
2003-11-25 1:37 C++/Java regressions David Carlton
2003-11-25 1:48 ` The demangler was rewritten from scratch! Andrew Cagney
2003-11-25 3:58 ` C++/Java regressions Ian Lance Taylor
@ 2003-11-26 4:04 ` Ian Lance Taylor
2003-11-26 15:32 ` Daniel Jacobowitz
2 siblings, 1 reply; 27+ messages in thread
From: Ian Lance Taylor @ 2003-11-26 4:04 UTC (permalink / raw)
To: David Carlton; +Cc: gdb
David Carlton <carlton@kealia.com> writes:
> -KFAIL: gdb.cp/templates.exp: ptype T5<int> (PRMS: gdb/1111)
> -KFAIL: gdb.cp/templates.exp: ptype T5<int> (PRMS: gdb/1111)
> +FAIL: gdb.cp/templates.exp: ptype T5<int>
> +FAIL: gdb.cp/templates.exp: ptype t5i
I looked into these, although I know that other people have looked
into them already. I recreated the problem with current gcc. It was
happening with the older gcc I was using before.
For me, the `ptype T5<int>' test fails because gdb prints `type =
namespace T5<int>'. I don't think this is because of the demangler.
I think it's because
1) gdb finds a DWARF entry for T5<int>::T5(int)
2) gdb creates a psymbol for this entry
3) gdb calls the possible namespace code in cp-namespace.c
4) that code enters the symbol `T5<int>' as a possible namespace
Then when gdb goes to look up T5<int>, it finds the DWARF psymbol for
the class itself, but it also finds that the symbol might be a
namespace. It then decides that it is a namespace.
I can avoid the problem with this patch, but I'm sure this is not
right approach.
Index: cp-namespace.c
===================================================================
RCS file: /cvs/src/src/gdb/cp-namespace.c,v
retrieving revision 1.7
diff -u -p -r1.7 cp-namespace.c
--- cp-namespace.c 13 Nov 2003 19:34:02 -0000 1.7
+++ cp-namespace.c 26 Nov 2003 03:55:58 -0000
@@ -675,7 +675,7 @@ static int
check_possible_namespace_symbols_loop (const char *name, int len,
struct objfile *objfile)
{
- if (name[len] == ':')
+ if (name[len] == ':' && memchr (name, '<', len) == NULL)
{
int done;
int next_len = len + 2;
The problem with t5i, besides some demangler changes which have
already been addressed, is that gdb doesn't recognize that a
constructor function is, in fact, a constructor. That's because the
code in c-typeprint.c does this:
char *method_name = TYPE_FN_FIELDLIST_NAME (type, i);
char *name = type_name_no_tag (type);
int is_constructor = name && strcmp (method_name, name) == 0;
and this:
char *physname = TYPE_FN_FIELD_PHYSNAME (f, j);
int is_full_physname_constructor =
is_constructor_name (physname)
|| is_destructor_name (physname)
|| method_name[0] == '~';
The first fails because name is "T5<int>" and method_name is "T5".
The second fails because this is dealing with debugging information,
and gcc does not emit any physical symbol name information for class
constructors.
This could be addressed by changing the simple test for is_constructor
to a more complex test which ignore the template arguments when
determining whether method_name was the same as name.
Ian
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: C++/Java regressions
2003-11-26 4:04 ` Ian Lance Taylor
@ 2003-11-26 15:32 ` Daniel Jacobowitz
2003-11-26 21:05 ` Ian Lance Taylor
0 siblings, 1 reply; 27+ messages in thread
From: Daniel Jacobowitz @ 2003-11-26 15:32 UTC (permalink / raw)
To: gdb
On Tue, Nov 25, 2003 at 11:04:41PM -0500, Ian Lance Taylor wrote:
> Then when gdb goes to look up T5<int>, it finds the DWARF psymbol for
> the class itself, but it also finds that the symbol might be a
> namespace. It then decides that it is a namespace.
That sounds like the bit that's wrong. If it found a psymbol for the
class why does it decide to call it a namespace?
> The problem with t5i, besides some demangler changes which have
> already been addressed, is that gdb doesn't recognize that a
> constructor function is, in fact, a constructor. That's because the
> code in c-typeprint.c does this:
>
> char *method_name = TYPE_FN_FIELDLIST_NAME (type, i);
> char *name = type_name_no_tag (type);
> int is_constructor = name && strcmp (method_name, name) == 0;
>
> and this:
>
> char *physname = TYPE_FN_FIELD_PHYSNAME (f, j);
> int is_full_physname_constructor =
> is_constructor_name (physname)
> || is_destructor_name (physname)
> || method_name[0] == '~';
>
> The first fails because name is "T5<int>" and method_name is "T5".
> The second fails because this is dealing with debugging information,
> and gcc does not emit any physical symbol name information for class
> constructors.
>
> This could be addressed by changing the simple test for is_constructor
> to a more complex test which ignore the template arguments when
> determining whether method_name was the same as name.
Yes, I have a patch sitting here (for some time) which does this. It
got mixed in with some other patches that aren't ready for prime-time
yet.
I'm considering a routine for canonicalization of C++ demangled names.
That's the only way we're going to get templates.exp to start working
robustly. For cv-qualifiers it's fairly easy, and most of what gets
mangled is to accomodate either space efficiency or linker character
sets so that's not all so important. "Unsigned" <-> "unsigned int" is
also easy. Template arguments can be a little harder so we may punt.
Perhaps next month.
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: C++/Java regressions
2003-11-26 15:32 ` Daniel Jacobowitz
@ 2003-11-26 21:05 ` Ian Lance Taylor
2003-11-26 21:11 ` David Carlton
2003-11-26 21:12 ` Daniel Jacobowitz
0 siblings, 2 replies; 27+ messages in thread
From: Ian Lance Taylor @ 2003-11-26 21:05 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: gdb
Daniel Jacobowitz <drow@mvista.com> writes:
> On Tue, Nov 25, 2003 at 11:04:41PM -0500, Ian Lance Taylor wrote:
> > Then when gdb goes to look up T5<int>, it finds the DWARF psymbol for
> > the class itself, but it also finds that the symbol might be a
> > namespace. It then decides that it is a namespace.
>
> That sounds like the bit that's wrong. If it found a psymbol for the
> class why does it decide to call it a namespace?
Good question. My guess is that it's because lookup_symbol_aux()
calls current_language->la_lookup_symbol_nonlocal() before it calls
lookup_symbol_aux_psymtabs(). If I force la_lookup_symbol_nonlocal()
to return NULL, then lookup_symbol_aux_psymtabs() finds the typedef,
and `ptype T5<int>' works more or less correctly.
One solution might be that when gdb finds that a symbol has a class
definition, it makes sure that it does not have a pseudo-namespace
definition.
> I'm considering a routine for canonicalization of C++ demangled names.
If it helps, that's more or less what my libiberty C++ demangler does.
It first translate the name into a simple tree structure, and then
walks the tree translating it into a string. I could expose the tree,
although it would have to be documented a bit better.
Ian
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: C++/Java regressions
2003-11-26 21:05 ` Ian Lance Taylor
@ 2003-11-26 21:11 ` David Carlton
2003-11-26 21:12 ` Daniel Jacobowitz
1 sibling, 0 replies; 27+ messages in thread
From: David Carlton @ 2003-11-26 21:11 UTC (permalink / raw)
To: Ian Lance Taylor; +Cc: Daniel Jacobowitz, gdb
On 26 Nov 2003 16:04:55 -0500, Ian Lance Taylor <ian@wasabisystems.com> said:
> Daniel Jacobowitz <drow@mvista.com> writes:
>> On Tue, Nov 25, 2003 at 11:04:41PM -0500, Ian Lance Taylor wrote:
>>> Then when gdb goes to look up T5<int>, it finds the DWARF psymbol
>>> for the class itself, but it also finds that the symbol might be a
>>> namespace. It then decides that it is a namespace.
>> That sounds like the bit that's wrong. If it found a psymbol for
>> the class why does it decide to call it a namespace?
> Good question. My guess is that it's because lookup_symbol_aux()
> calls current_language->la_lookup_symbol_nonlocal() before it calls
> lookup_symbol_aux_psymtabs(). If I force
> la_lookup_symbol_nonlocal() to return NULL, then
> lookup_symbol_aux_psymtabs() finds the typedef, and `ptype T5<int>'
> works more or less correctly.
Thanks for the investigation. Then I think that my latest patch
awaiting approval should fix this, if we're lucky - it treats C++
class symbols as global objects instead of static objects.
(Basically, we want to find the class before we ever reach the calls
to lookup_symbol_aux_{,p}symtabs in lookup_symbol_aux: it should be
found in the language-specific bit.) I'll double check to make sure
that's the issue, but I'm optimistic.
David Carlton
carlton@kealia.com
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: C++/Java regressions
2003-11-26 21:05 ` Ian Lance Taylor
2003-11-26 21:11 ` David Carlton
@ 2003-11-26 21:12 ` Daniel Jacobowitz
2003-11-26 21:32 ` Ian Lance Taylor
2003-11-30 2:57 ` Jim Blandy
1 sibling, 2 replies; 27+ messages in thread
From: Daniel Jacobowitz @ 2003-11-26 21:12 UTC (permalink / raw)
To: Ian Lance Taylor; +Cc: gdb
On Wed, Nov 26, 2003 at 04:04:55PM -0500, Ian Lance Taylor wrote:
> Daniel Jacobowitz <drow@mvista.com> writes:
>
> > On Tue, Nov 25, 2003 at 11:04:41PM -0500, Ian Lance Taylor wrote:
> > > Then when gdb goes to look up T5<int>, it finds the DWARF psymbol for
> > > the class itself, but it also finds that the symbol might be a
> > > namespace. It then decides that it is a namespace.
> >
> > That sounds like the bit that's wrong. If it found a psymbol for the
> > class why does it decide to call it a namespace?
>
> Good question. My guess is that it's because lookup_symbol_aux()
> calls current_language->la_lookup_symbol_nonlocal() before it calls
> lookup_symbol_aux_psymtabs(). If I force la_lookup_symbol_nonlocal()
> to return NULL, then lookup_symbol_aux_psymtabs() finds the typedef,
> and `ptype T5<int>' works more or less correctly.
>
> One solution might be that when gdb finds that a symbol has a class
> definition, it makes sure that it does not have a pseudo-namespace
> definition.
The pseudo-namespaces are always supposed to be shadowed by symbols.
From your explanation it looks like they're shadowing psymbols; but
since psymbols are supposed to behave identically to symbols (that's
the whole point), something is wrong.
I'll look at it if I get a chance before David Carlton does; this is
originally his code. Thanks for the investigation.
> > I'm considering a routine for canonicalization of C++ demangled names.
>
> If it helps, that's more or less what my libiberty C++ demangler does.
> It first translate the name into a simple tree structure, and then
> walks the tree translating it into a string. I could expose the tree,
> although it would have to be documented a bit better.
Oh, so it's already two-pass? If we could work out an API for the
tree, then GDB could build and supply trees to get a canonical form
back from the demangler. That has the added bonus of not needing to
post-process the demangler output (if we know that we've got a GNU v3
name and thus this demangler was used, of course - v2 would still need
to be parsed). That sounds like an ideal solution.
Do you have an opinion on the "A::bar const" DMGL_PARAMS issue that
Michael Chastain noticed, by the way?
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: C++/Java regressions
2003-11-26 21:12 ` Daniel Jacobowitz
@ 2003-11-26 21:32 ` Ian Lance Taylor
2003-12-01 16:45 ` Daniel Jacobowitz
2003-11-30 2:57 ` Jim Blandy
1 sibling, 1 reply; 27+ messages in thread
From: Ian Lance Taylor @ 2003-11-26 21:32 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: gdb
Daniel Jacobowitz <drow@mvista.com> writes:
> > > I'm considering a routine for canonicalization of C++ demangled names.
> >
> > If it helps, that's more or less what my libiberty C++ demangler does.
> > It first translate the name into a simple tree structure, and then
> > walks the tree translating it into a string. I could expose the tree,
> > although it would have to be documented a bit better.
>
> Oh, so it's already two-pass? If we could work out an API for the
> tree, then GDB could build and supply trees to get a canonical form
> back from the demangler. That has the added bonus of not needing to
> post-process the demangler output (if we know that we've got a GNU v3
> name and thus this demangler was used, of course - v2 would still need
> to be parsed). That sounds like an ideal solution.
It sounds workable to me. You may want to take a look at enum
d_comp_type and struct d_comp near the top of libiberty/cp-demangle.c,
and see if it is the type of thing you could imagine using.
> Do you have an opinion on the "A::bar const" DMGL_PARAMS issue that
> Michael Chastain noticed, by the way?
Yes, I think it should print A::bar without the const. I have the
patch in my sources, but I haven't checked it in yet.
Ian
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: C++/Java regressions
2003-11-26 21:12 ` Daniel Jacobowitz
2003-11-26 21:32 ` Ian Lance Taylor
@ 2003-11-30 2:57 ` Jim Blandy
2003-11-30 3:12 ` Daniel Jacobowitz
1 sibling, 1 reply; 27+ messages in thread
From: Jim Blandy @ 2003-11-30 2:57 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: Ian Lance Taylor, gdb
Daniel Jacobowitz <drow@mvista.com> writes:
> > If it helps, that's more or less what my libiberty C++ demangler does.
> > It first translate the name into a simple tree structure, and then
> > walks the tree translating it into a string. I could expose the tree,
> > although it would have to be documented a bit better.
>
> Oh, so it's already two-pass? If we could work out an API for the
> tree, then GDB could build and supply trees to get a canonical form
> back from the demangler. That has the added bonus of not needing to
> post-process the demangler output (if we know that we've got a GNU v3
> name and thus this demangler was used, of course - v2 would still need
> to be parsed). That sounds like an ideal solution.
I've been wanting something like this for a long time, too.
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: C++/Java regressions
2003-11-30 2:57 ` Jim Blandy
@ 2003-11-30 3:12 ` Daniel Jacobowitz
0 siblings, 0 replies; 27+ messages in thread
From: Daniel Jacobowitz @ 2003-11-30 3:12 UTC (permalink / raw)
To: Jim Blandy; +Cc: Ian Lance Taylor, gdb
On Sat, Nov 29, 2003 at 09:56:28PM -0500, Jim Blandy wrote:
>
> Daniel Jacobowitz <drow@mvista.com> writes:
> > > If it helps, that's more or less what my libiberty C++ demangler does.
> > > It first translate the name into a simple tree structure, and then
> > > walks the tree translating it into a string. I could expose the tree,
> > > although it would have to be documented a bit better.
> >
> > Oh, so it's already two-pass? If we could work out an API for the
> > tree, then GDB could build and supply trees to get a canonical form
> > back from the demangler. That has the added bonus of not needing to
> > post-process the demangler output (if we know that we've got a GNU v3
> > name and thus this demangler was used, of course - v2 would still need
> > to be parsed). That sounds like an ideal solution.
>
> I've been wanting something like this for a long time, too.
FYI, I'm in the middle (this evening) of writing the appropriate
parser.
It's reminding me how much I hate the grammar of C++, too.
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: C++/Java regressions
2003-11-26 21:32 ` Ian Lance Taylor
@ 2003-12-01 16:45 ` Daniel Jacobowitz
0 siblings, 0 replies; 27+ messages in thread
From: Daniel Jacobowitz @ 2003-12-01 16:45 UTC (permalink / raw)
To: gdb
On Wed, Nov 26, 2003 at 04:32:08PM -0500, Ian Lance Taylor wrote:
> Daniel Jacobowitz <drow@mvista.com> writes:
>
> > > > I'm considering a routine for canonicalization of C++ demangled names.
> > >
> > > If it helps, that's more or less what my libiberty C++ demangler does.
> > > It first translate the name into a simple tree structure, and then
> > > walks the tree translating it into a string. I could expose the tree,
> > > although it would have to be documented a bit better.
> >
> > Oh, so it's already two-pass? If we could work out an API for the
> > tree, then GDB could build and supply trees to get a canonical form
> > back from the demangler. That has the added bonus of not needing to
> > post-process the demangler output (if we know that we've got a GNU v3
> > name and thus this demangler was used, of course - v2 would still need
> > to be parsed). That sounds like an ideal solution.
>
> It sounds workable to me. You may want to take a look at enum
> d_comp_type and struct d_comp near the top of libiberty/cp-demangle.c,
> and see if it is the type of thing you could imagine using.
>
> > Do you have an opinion on the "A::bar const" DMGL_PARAMS issue that
> > Michael Chastain noticed, by the way?
>
> Yes, I think it should print A::bar without the const. I have the
> patch in my sources, but I haven't checked it in yet.
It's alive. For the curious, I've attached my current working source;
just run it through bison, and compile with -Isrc/include -liberty.
Obviously it's a long way from finished, but the basic functionality is
there, including a lot of things GDB couldn't handle before:
% ./c-names "foo::bar<1+2 + 3>::foo<signed int * const * volatile const>"
Result is foo::bar<((1) + (2)) + (3)>::foo<int* const* const volatile>
Look at that - it canonicalized the qualifiers, made the whitespace
consistent, parenthesized properly... all starting from something that
could have been user input and ending with something that could have
come out of the demangler and into our symbol table.
The only major grammar element that I'd like to include that isn't is
the leading :: on qualified names; I couldn't figure out how to resolve
the conflicts it generated. But the demangler never puts that out so
it's less than urgent.
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer
/* YACC parser for C expressions, for GDB.
Copyright 1986, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
1998, 1999, 2000, 2003
Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Parse a C expression from text in a string,
and return the result as a struct expression pointer.
That structure contains arithmetic operations in reverse polish,
with constants represented by operations that are followed by special data.
See expression.h for the details of the format.
What is important here is that it can be built up sequentially
during the process of parsing; the lower levels of the tree always
come first in the result.
Note that malloc's and realloc's in this file are transformed to
xmalloc and xrealloc respectively by the same sed command in the
makefile that remaps any other malloc/realloc inserted by the parser
generator. Doing this with #defines and trying to control the interaction
with include files (<malloc.h> and <stdlib.h> for example) just became
too messy, particularly when such includes can be inserted at random
times by the parser generator. */
%{
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
typedef long long LONGEST;
typedef unsigned long long ULONGEST;
typedef long double DOUBLEST;
#include "safe-ctype.h"
#include "../libiberty/cp-demangle.c"
extern char *lexptr, *prev_lexptr;
static struct d_comp *d_qualify (struct d_comp *, LONGEST);
static struct d_comp *d_int_type (int);
static struct d_comp *d_op_from_string (const char *opname);
static struct d_comp *d_unary (const char *opname, struct d_comp *);
static struct d_comp *d_binary (const char *opname, struct d_comp *, struct d_comp *);
/* Global state, ew. */
struct d_info *di;
static struct d_comp *result;
/* Ew ew, ew ew, ew ew ew. */
#define error printf
#define HOST_CHAR_BIT 8
#define NORETURN
#undef TARGET_INT_BIT
#define TARGET_INT_BIT 32
#undef TARGET_LONG_BIT
#define TARGET_LONG_BIT 32
#undef TARGET_LONG_LONG_BIT
#define TARGET_LONG_LONG_BIT 64
#define QUAL_CONST 1
#define QUAL_RESTRICT 2
#define QUAL_VOLATILE 4
#define INT_CHAR 1
#define INT_SHORT 2
#define INT_LONG 3
#define INT_LLONG 4
#define INT_SIGNED (1 << 3)
#define INT_UNSIGNED (2 << 3)
#define BINOP_ADD 1
#define BINOP_RSH 2
#define BINOP_LSH 3
#define BINOP_SUB 4
#define BINOP_MUL 5
#define BINOP_DIV 6
#define BINOP_REM 7
#define BINOP_BITWISE_IOR 8
#define BINOP_BITWISE_AND 9
#define BINOP_BITWISE_XOR 10
#define BINOP_END 11
/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
as well as gratuitiously global symbol names, so we can have multiple
yacc generated parsers in gdb. Note that these are only the variables
produced by yacc. If other parser generators (bison, byacc, etc) produce
additional global names that conflict at link time, then those parser
generators need to be fixed instead of adding those names to this list. */
#define yymaxdepth cpname_maxdepth
#define yyparse cpname_parse
#define yylex cpname_lex
#define yyerror cpname_error
#define yylval cpname_lval
#define yychar cpname_char
#define yydebug cpname_debug
#define yypact cpname_pact
#define yyr1 cpname_r1
#define yyr2 cpname_r2
#define yydef cpname_def
#define yychk cpname_chk
#define yypgo cpname_pgo
#define yyact cpname_act
#define yyexca cpname_exca
#define yyerrflag cpname_errflag
#define yynerrs cpname_nerrs
#define yyps cpname_ps
#define yypv cpname_pv
#define yys cpname_s
#define yy_yys cpname_yys
#define yystate cpname_state
#define yytmp cpname_tmp
#define yyv cpname_v
#define yy_yyv cpname_yyv
#define yyval cpname_val
#define yylloc cpname_lloc
#define yyreds cpname_reds /* With YYDEBUG defined */
#define yytoks cpname_toks /* With YYDEBUG defined */
#define yyname cpname_name /* With YYDEBUG defined */
#define yyrule cpname_rule /* With YYDEBUG defined */
#define yylhs cpname_yylhs
#define yylen cpname_yylen
#define yydefred cpname_yydefred
#define yydgoto cpname_yydgoto
#define yysindex cpname_yysindex
#define yyrindex cpname_yyrindex
#define yygindex cpname_yygindex
#define yytable cpname_yytable
#define yycheck cpname_yycheck
#ifndef YYDEBUG
#define YYDEBUG 1 /* Default to yydebug support */
#endif
int yyparse (void);
static int yylex (void);
void yyerror (char *);
%}
/* Although the yacc "value" of an expression is not used,
since the result is stored in the structure being created,
other node types do have values. */
%union
{
struct d_comp *comp;
struct {
struct d_comp *comp;
struct d_comp **last;
} nested;
LONGEST lval;
struct {
LONGEST val;
} typed_val_int;
struct {
DOUBLEST dval;
} typed_val_float;
int opcode;
}
%{
/* YYSTYPE gets defined by %union */
static int parse_number (char *, int, int, YYSTYPE *);
%}
%type <comp> exp exp1 type start operator qualified
%type <comp> unqualified_name template scope_id ext_name
%type <comp> template template_arg basic_exp
%type <comp> base_function typed_function qualified
%type <comp> builtin_type
%type <nested> nested_name template_params function_args
%type <lval> qualifier qualifiers qualifiers_opt
%type <lval> sign size int_type
%token <typed_val_int> INT
%token <typed_val_float> FLOAT
%token <comp> NAME
%type <comp> name
%token STRUCT CLASS UNION ENUM SIZEOF UNSIGNED COLONCOLON
%token TEMPLATE
%token ERROR
%token NEW DELETE OPERATOR
/* Special type cases, put in to allow the parser to distinguish different
legal basetypes. */
%token SIGNED_KEYWORD LONG SHORT INT_KEYWORD CONST_KEYWORD VOLATILE_KEYWORD DOUBLE_KEYWORD BOOL
%token ELLIPSIS RESTRICT VOID FLOAT_KEYWORD CHAR WCHAR_T
%token <opcode> ASSIGN_MODIFY
/* C++ */
%token TRUEKEYWORD
%token FALSEKEYWORD
%token COLONCOLONSTAR
%left ','
%right '=' ASSIGN_MODIFY
%right '?'
%left OROR
%left ANDAND
%left '|'
%left '^'
%left '&'
%left EQUAL NOTEQUAL
%left '<' '>' LEQ GEQ
%left LSH RSH
%left '@'
%left '+' '-'
%left '*' '/' '%'
%right UNARY INCREMENT DECREMENT
%right ARROW '.' '[' '('
%left COLONCOLON
\f
%%
start : type
{ result = $1; }
| qualified
{ result = $1; }
;
operator : OPERATOR NEW
{ $$ = d_op_from_string ("new"); }
| OPERATOR DELETE
{ $$ = d_op_from_string ("delete"); }
| OPERATOR NEW '[' ']'
{ $$ = d_op_from_string ("new[]"); }
| OPERATOR DELETE '[' ']'
{ $$ = d_op_from_string ("delete[]"); }
| OPERATOR '+'
{ $$ = d_op_from_string ("+"); }
| OPERATOR '-'
{ $$ = d_op_from_string ("-"); }
| OPERATOR '*'
{ $$ = d_op_from_string ("*"); }
| OPERATOR '/'
{ $$ = d_op_from_string ("/"); }
| OPERATOR '%'
{ $$ = d_op_from_string ("%"); }
| OPERATOR '^'
{ $$ = d_op_from_string ("^"); }
| OPERATOR '&'
{ $$ = d_op_from_string ("&"); }
| OPERATOR '|'
{ $$ = d_op_from_string ("|"); }
| OPERATOR '~'
{ $$ = d_op_from_string ("~"); }
| OPERATOR '!'
{ $$ = d_op_from_string ("!"); }
| OPERATOR '='
{ $$ = d_op_from_string ("="); }
| OPERATOR '<'
{ $$ = d_op_from_string ("<"); }
| OPERATOR '>'
{ $$ = d_op_from_string (">"); }
| OPERATOR ASSIGN_MODIFY
{ $$ = d_op_from_string ("FIXME"); }
| OPERATOR LSH
{ $$ = d_op_from_string ("<<"); }
| OPERATOR RSH
{ $$ = d_op_from_string (">>"); }
| OPERATOR EQUAL
{ $$ = d_op_from_string ("=="); }
| OPERATOR NOTEQUAL
{ $$ = d_op_from_string ("!="); }
| OPERATOR LEQ
{ $$ = d_op_from_string ("<="); }
| OPERATOR GEQ
{ $$ = d_op_from_string (">="); }
| OPERATOR ANDAND
{ $$ = d_op_from_string ("&&"); }
| OPERATOR OROR
{ $$ = d_op_from_string ("||"); }
| OPERATOR INCREMENT
{ $$ = d_op_from_string ("++"); }
| OPERATOR DECREMENT
{ $$ = d_op_from_string ("--"); }
| OPERATOR ','
{ $$ = d_op_from_string (","); }
| OPERATOR ARROW '*'
{ $$ = d_op_from_string ("*"); }
| OPERATOR ARROW
{ $$ = d_op_from_string ("->"); }
| OPERATOR '(' ')'
{ $$ = d_op_from_string ("->*"); }
| OPERATOR '[' ']'
{ $$ = d_op_from_string ("[]"); }
;
/* D_COMP_NAME */
/* This accepts certain invalid placements of '~'. */
unqualified_name: operator
| '~' NAME
{ $$ = d_make_dtor (di, gnu_v3_complete_object_dtor, $2); }
;
scope_id : NAME
| template
;
/* D_COMP_QUAL_NAME */
/* D_COMP_CTOR / D_COMP_DTOR ? */
name : nested_name scope_id
{ $$ = $1.comp; *$1.last = $2; }
| scope_id
;
ext_name : name
| nested_name unqualified_name
{ $$ = $1.comp; *$1.last = $2; }
| unqualified_name
;
nested_name : scope_id COLONCOLON
{ $$.comp = d_make_comp (di, D_COMP_QUAL_NAME, $1, $1);
d_right ($$.comp) = NULL;
$$.last = &d_right ($$.comp);
}
/* Not necessary in this context, and produces conflicts. */
/*
| COLONCOLON
{ }
*/
| nested_name scope_id COLONCOLON
{ $$.comp = $1.comp;
*$1.last = d_make_comp (di, D_COMP_QUAL_NAME, $2, $2);
d_right (*$1.last) = NULL;
$$.last = &d_right (*$1.last);
}
;
/* D_COMP_TEMPLATE */
/* D_COMP_TEMPLATE_ARGLIST */
template : NAME '<' template_params '>'
{ $$ = d_make_comp (di, D_COMP_TEMPLATE, $1, $3.comp); }
;
template_params : template_arg
{ $$.comp = d_make_comp (di, D_COMP_TEMPLATE_ARGLIST, $1, NULL);
$$.last = &d_right ($$.comp); }
| template_params ',' template_arg
{ $$.comp = $1.comp;
*$1.last = d_make_comp (di, D_COMP_TEMPLATE_ARGLIST, $3, NULL);
$$.last = &d_right (*$1.last);
}
;
/* Also an integral constant-expression of integral type, and a
pointer to member (?) */
template_arg : type
| '&' ext_name
{ $$ = d_make_comp (di, D_COMP_REFERENCE, $2, NULL); }
| '&' '(' ext_name ')'
{ $$ = d_make_comp (di, D_COMP_REFERENCE, $3, NULL); }
| basic_exp
;
/* D_COMP_ARGLIST */
base_function : ext_name '(' function_args ')'
{ $$ = d_make_comp (di, D_COMP_TYPED_NAME, $1,
d_make_comp (di, D_COMP_FUNCTION_TYPE, NULL, $3.comp)); }
| ext_name '(' ')'
{ $$ = d_make_comp (di, D_COMP_TYPED_NAME, $1,
d_make_comp (di, D_COMP_FUNCTION_TYPE, NULL, NULL)); }
;
function_args : type
{ $$.comp = d_make_comp (di, D_COMP_ARGLIST, $1, NULL);
$$.last = &d_right ($$.comp);
/* FIXME: Check for VOID and do nothing. */
}
| function_args ',' type
{ $$.comp = $1.comp;
*$1.last = d_make_comp (di, D_COMP_ARGLIST, $3, NULL);
$$.last = &d_right (*$1.last);
}
| function_args ',' ELLIPSIS
{ $$.comp = $1.comp;
*$1.last
= d_make_comp (di, D_COMP_ARGLIST,
d_make_builtin_type (di, &d_builtin_types['z' - 'a']),
NULL);
$$.last = &d_right (*$1.last);
}
;
/* D_COMP_TYPED_NAME */
typed_function : type base_function
{ $$ = $2; d_left (d_right ($2)) = $1; }
;
/* Should do something about D_COMP_VENDOR_TYPE_QUAL */
qualifiers_opt : /* epsilon */
{ $$ = 0; }
| qualifiers
{ $$ = $1; }
;
qualifier : RESTRICT
{ $$ = QUAL_RESTRICT; }
| VOLATILE_KEYWORD
{ $$ = QUAL_VOLATILE; }
| CONST_KEYWORD
{ $$ = QUAL_CONST; }
;
qualifiers : qualifier
{ $$ = $1; }
| qualifier qualifiers
{ $$ = $1 | $2; }
;
qualified : base_function qualifiers_opt
{ $$ = d_qualify ($1, $2); }
| typed_function qualifiers_opt
{ $$ = d_qualify ($1, $2); }
;
int_opt : /* */
{ }
| INT_KEYWORD
{ }
;
sign : SIGNED_KEYWORD
{ $$ = INT_SIGNED; }
| UNSIGNED
{ $$ = INT_UNSIGNED; }
;
size : CHAR
{ $$ = INT_CHAR; }
| LONG
{ $$ = INT_LONG; }
| SHORT
{ $$ = INT_SHORT; }
| LONG LONG
{ $$ = INT_LLONG; }
;
int_type : sign size int_opt
{ $$ = $1 | $2; }
| size sign int_opt
{ $$ = $1 | $2; }
| sign INT_KEYWORD size
{ $$ = $1 | $3; }
| size INT_KEYWORD sign
{ $$ = $1 | $3; }
| INT_KEYWORD sign size
{ $$ = $2 | $3; }
| INT_KEYWORD size sign
{ $$ = $2 | $3; }
| sign int_opt
{ $$ = $1; }
| INT_KEYWORD sign
{ $$ = $2; }
| size int_opt
{ $$ = $1; }
| INT_KEYWORD size
{ $$ = $2; }
| INT_KEYWORD
{ $$ = 0; }
;
builtin_type : int_type
{ $$ = d_int_type ($1); }
| FLOAT_KEYWORD
{ $$ = d_make_builtin_type (di, &d_builtin_types['f' - 'a']); }
| DOUBLE_KEYWORD
{ $$ = d_make_builtin_type (di, &d_builtin_types['d' - 'a']); }
| LONG DOUBLE_KEYWORD
{ $$ = d_make_builtin_type (di, &d_builtin_types['e' - 'a']); }
| BOOL
{ $$ = d_make_builtin_type (di, &d_builtin_types['b' - 'a']); }
| WCHAR_T
{ $$ = d_make_builtin_type (di, &d_builtin_types['w' - 'a']); }
| VOID
{ $$ = d_make_builtin_type (di, &d_builtin_types['v' - 'a']); }
;
type : builtin_type
| name
| qualifiers builtin_type
{ $$ = d_qualify ($2, $1); }
| qualifiers name
{ $$ = d_qualify ($2, $1); }
| type '*'
{ $$ = d_make_comp (di, D_COMP_POINTER, $1, NULL); }
| type '&'
{ $$ = d_make_comp (di, D_COMP_REFERENCE, $1, NULL); }
/* This ext_name and the one below for
pointer-to-member-function should normally be
"type" instead. That causes a reduce/reduce
conflict. Allow a few invalid inputs to keep life
simple. */
| ext_name '(' '*' ')' '(' function_args ')'
{ struct d_comp *funtype;
funtype = d_make_comp (di, D_COMP_FUNCTION_TYPE, $1, $6.comp);
$$ = d_make_comp (di, D_COMP_POINTER, funtype, NULL); }
| type name COLONCOLONSTAR
{ $$ = d_make_comp (di, D_COMP_PTRMEM_TYPE, $2, $1); }
| ext_name '(' name COLONCOLONSTAR ')' '(' function_args ')'
{ $$ = d_make_comp (di, D_COMP_PTRMEM_TYPE, $3,
d_make_comp (di, D_COMP_FUNCTION_TYPE,
$1, $7.comp));
}
| type qualifier
{ $$ = d_qualify ($1, $2); }
| type '[' ']'
{ $$ = d_make_comp (di, D_COMP_ARRAY_TYPE, $1, NULL); }
/* FIXME We don't respect L suffixes anywhere... do we need to? */
| type '[' INT ']'
{ struct d_comp *i;
/* FIXME: Blatant memory leak. */
char *buf = malloc (24);
sprintf (buf, "%d", (int) $3.val);
i = d_make_name (di, buf, strlen (buf));
$$ = d_make_comp (di, D_COMP_ARRAY_TYPE, $1,
d_make_comp (di, D_COMP_LITERAL, d_int_type (0), i));
}
;
basic_exp : exp
;
exp : '(' exp1 ')'
{ $$ = $2; }
;
/* Silly trick. Only allow '>' when parenthesized, in order to
handle conflict with templates. */
exp1 : exp
;
exp1 : exp '>' exp
{ $$ = d_binary (">", $1, $3); }
;
/* Expressions, not including the comma operator. */
exp : '-' exp %prec UNARY
{ $$ = d_unary ("-", $2); }
;
exp : '!' exp %prec UNARY
{ $$ = d_unary ("!", $2); }
;
exp : '~' exp %prec UNARY
{ $$ = d_unary ("~", $2); }
;
exp : '(' type ')' exp %prec UNARY
{ $$ = d_make_comp (di, D_COMP_UNARY,
d_make_comp (di, D_COMP_CAST, $2, NULL),
$4);
}
;
exp : builtin_type '(' exp1 ')' %prec UNARY
{ $$ = d_make_comp (di, D_COMP_UNARY,
d_make_comp (di, D_COMP_CAST, $1, NULL),
$3);
}
;
/* FIXME other C++-style-casts, including name ( exp1 ), which causes
conflicts above. This doesn't appear in the output of the demangler
however so punt for now. */
/* FIXME ._0 style anonymous names; anonymous namespaces */
/* Binary operators in order of decreasing precedence. */
exp : exp '*' exp
{ $$ = d_binary ("*", $1, $3); }
;
exp : exp '/' exp
{ $$ = d_binary ("/", $1, $3); }
;
exp : exp '%' exp
{ $$ = d_binary ("%", $1, $3); }
;
exp : exp '+' exp
{ $$ = d_binary ("+", $1, $3); }
;
exp : exp '-' exp
{ $$ = d_binary ("-", $1, $3); }
;
exp : exp LSH exp
{ $$ = d_binary ("<<", $1, $3); }
;
exp : exp RSH exp
{ $$ = d_binary (">>", $1, $3); }
;
exp : exp EQUAL exp
{ $$ = d_binary ("==", $1, $3); }
;
exp : exp NOTEQUAL exp
{ $$ = d_binary ("!=", $1, $3); }
;
exp : exp LEQ exp
{ $$ = d_binary ("<=", $1, $3); }
;
exp : exp GEQ exp
{ $$ = d_binary (">=", $1, $3); }
;
exp : exp '<' exp
{ $$ = d_binary ("<", $1, $3); }
;
exp : exp '&' exp
{ $$ = d_binary ("&", $1, $3); }
;
exp : exp '^' exp
{ $$ = d_binary ("^", $1, $3); }
;
exp : exp '|' exp
{ $$ = d_binary ("|", $1, $3); }
;
exp : exp ANDAND exp
{ $$ = d_binary ("&&", $1, $3); }
;
exp : exp OROR exp
{ $$ = d_binary ("||", $1, $3); }
;
exp : exp '?' exp ':' exp %prec '?'
{ $$ = d_make_comp (di, D_COMP_TRINARY, d_op_from_string ("?"),
d_make_comp (di, D_COMP_TRINARY_ARG1, $1,
d_make_comp (di, D_COMP_TRINARY_ARG2, $3, $5)));
}
;
exp : INT
{ struct d_comp *i;
/* FIXME: Blatant memory leak. */
char *buf = malloc (24);
sprintf (buf, "%d", (int) $1.val);
i = d_make_name (di, buf, strlen (buf));
$$ = d_make_comp (di, D_COMP_LITERAL, d_int_type (0), i);
}
;
/* Not generally allowed. */
exp : FLOAT
{ struct d_comp *i;
/* FIXME: Blatant memory leak. */
char *buf = malloc (24);
sprintf (buf, "%f", (double) $1.dval);
i = d_make_name (di, buf, strlen (buf));
$$ = d_make_comp (di, D_COMP_LITERAL,
d_make_builtin_type (di, &d_builtin_types['d' - 'a']),
i);
}
;
exp : SIZEOF '(' type ')' %prec UNARY
{ $$ = d_unary ("sizeof", $3); }
;
/* C++. */
exp : TRUEKEYWORD
{ struct d_comp *i;
i = d_make_name (di, "true", strlen ("true"));
$$ = d_make_comp (di, D_COMP_LITERAL,
d_make_builtin_type (di, &d_builtin_types['b' - 'a']),
i);
}
;
exp : FALSEKEYWORD
{ struct d_comp *i;
i = d_make_name (di, "false", strlen ("false"));
$$ = d_make_comp (di, D_COMP_LITERAL,
d_make_builtin_type (di, &d_builtin_types['b' - 'a']),
i);
}
;
/* end of C++. */
%%
/* */
struct d_comp *
d_qualify (struct d_comp *lhs, LONGEST qualifiers)
{
struct d_comp **inner_p;
enum d_comp_type type;
/* For now the order is CONST (innermost), VOLATILE, RESTRICT. */
#define HANDLE_QUAL(TYPE, QUAL) \
if ((qualifiers & QUAL) && (type != TYPE)) \
{ \
*inner_p = d_make_comp (di, TYPE, *inner_p, NULL); \
inner_p = &d_left (*inner_p); \
type = (*inner_p)->type; \
} \
else if (type == TYPE) \
{ \
inner_p = &d_left (*inner_p); \
type = (*inner_p)->type; \
}
inner_p = &lhs;
type = (*inner_p)->type;
HANDLE_QUAL (D_COMP_RESTRICT, QUAL_RESTRICT);
HANDLE_QUAL (D_COMP_VOLATILE, QUAL_VOLATILE);
HANDLE_QUAL (D_COMP_CONST, QUAL_CONST);
return lhs;
}
static struct d_comp *
d_int_type (int flags)
{
int i;
switch (flags)
{
case INT_SIGNED | INT_CHAR:
i = 0;
break;
case INT_CHAR:
i = 2;
break;
case INT_UNSIGNED | INT_CHAR:
i = 7;
break;
case 0:
case INT_SIGNED:
i = 8;
break;
case INT_UNSIGNED:
i = 9;
break;
case INT_LONG:
case INT_SIGNED | INT_LONG:
i = 11;
break;
case INT_UNSIGNED | INT_LONG:
i = 12;
break;
case INT_SHORT:
case INT_SIGNED | INT_SHORT:
i = 18;
break;
case INT_UNSIGNED | INT_SHORT:
i = 19;
break;
case INT_LLONG:
case INT_SIGNED | INT_LLONG:
i = 23;
break;
case INT_UNSIGNED | INT_LLONG:
i = 24;
break;
default:
return NULL;
}
return d_make_builtin_type (di, &d_builtin_types[i]);
}
static struct d_comp *
d_op_from_string (const char *opname)
{
const struct d_operator_info *i = d_operators;
while (1)
{
if (strcmp (i->name, opname) == 0)
break;
i++;
}
return d_make_operator (di, i);
}
static struct d_comp *
d_unary (const char *name, struct d_comp *lhs)
{
return d_make_comp (di, D_COMP_UNARY, d_op_from_string (name), lhs);
}
static struct d_comp *
d_binary (const char *name, struct d_comp *lhs, struct d_comp *rhs)
{
return d_make_comp (di, D_COMP_BINARY, d_op_from_string (name),
d_make_comp (di, D_COMP_BINARY_ARGS, lhs, rhs));
}
static const char *
target_charset (void)
{
return "foo";
}
static const char *
host_charset (void)
{
return "bar";
}
/* 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. */
/*** Needs some error checking for the float case ***/
static int
parse_number (p, len, parsed_float, putithere)
char *p;
int len;
int parsed_float;
YYSTYPE *putithere;
{
/* FIXME: Shouldn't these be unsigned? We don't deal with negative values
here, and we do kind of silly things like cast to unsigned. */
LONGEST n = 0;
LONGEST prevn = 0;
ULONGEST un;
int i = 0;
int c;
int base = 10;
int unsigned_p = 0;
/* Number of "L" suffixes encountered. */
int long_p = 0;
/* We have found a "L" or "U" suffix. */
int found_suffix = 0;
ULONGEST high_bit;
struct type *signed_type;
struct type *unsigned_type;
if (parsed_float)
{
/* It's a float since it contains a point or an exponent. */
char c;
int num = 0; /* number of tokens scanned by scanf */
char saved_char = p[len];
p[len] = 0; /* null-terminate the token */
if (sizeof (putithere->typed_val_float.dval) <= sizeof (float))
num = sscanf (p, "%g%c", (float *) &putithere->typed_val_float.dval,&c);
else if (sizeof (putithere->typed_val_float.dval) <= sizeof (double))
num = sscanf (p, "%lg%c", (double *) &putithere->typed_val_float.dval,&c);
else
{
#ifdef SCANF_HAS_LONG_DOUBLE
num = sscanf (p, "%Lg%c", &putithere->typed_val_float.dval,&c);
#else
/* Scan it into a double, then assign it to the long double.
This at least wins with values representable in the range
of doubles. */
double temp;
num = sscanf (p, "%lg%c", &temp,&c);
putithere->typed_val_float.dval = temp;
#endif
}
p[len] = saved_char; /* restore the input stream */
if (num != 1) /* check scanf found ONLY a float ... */
return ERROR;
/* See if it has `f' or `l' suffix (float or long double). */
c = TOLOWER (p[len - 1]);
#if 0
if (c == 'f')
putithere->typed_val_float.type = builtin_type_float;
else if (c == 'l')
putithere->typed_val_float.type = builtin_type_long_double;
else if (isdigit (c) || c == '.')
putithere->typed_val_float.type = builtin_type_double;
else
return ERROR;
#endif
return FLOAT;
}
/* Handle base-switching prefixes 0x, 0t, 0d, 0 */
if (p[0] == '0')
switch (p[1])
{
case 'x':
case 'X':
if (len >= 3)
{
p += 2;
base = 16;
len -= 2;
}
break;
case 't':
case 'T':
case 'd':
case 'D':
if (len >= 3)
{
p += 2;
base = 10;
len -= 2;
}
break;
default:
base = 8;
break;
}
while (len-- > 0)
{
c = *p++;
if (c >= 'A' && c <= 'Z')
c += 'a' - 'A';
if (c != 'l' && c != 'u')
n *= base;
if (c >= '0' && c <= '9')
{
if (found_suffix)
return ERROR;
n += i = c - '0';
}
else
{
if (base > 10 && c >= 'a' && c <= 'f')
{
if (found_suffix)
return ERROR;
n += i = c - 'a' + 10;
}
else if (c == 'l')
{
++long_p;
found_suffix = 1;
}
else if (c == 'u')
{
unsigned_p = 1;
found_suffix = 1;
}
else
return ERROR; /* Char not a digit */
}
if (i >= base)
return ERROR; /* Invalid digit in this base */
/* Portably test for overflow (only works for nonzero values, so make
a second check for zero). FIXME: Can't we just make n and prevn
unsigned and avoid this? */
if (c != 'l' && c != 'u' && (prevn >= n) && n != 0)
unsigned_p = 1; /* Try something unsigned */
/* Portably test for unsigned overflow.
FIXME: This check is wrong; for example it doesn't find overflow
on 0x123456789 when LONGEST is 32 bits. */
if (c != 'l' && c != 'u' && n != 0)
{
if ((unsigned_p && (ULONGEST) prevn >= (ULONGEST) n))
error ("Numeric constant too large.");
}
prevn = n;
}
/* An integer constant is an int, a long, or a long long. An L
suffix forces it to be long; an LL suffix forces it to be long
long. If not forced to a larger size, it gets the first type of
the above that it fits in. To figure out whether it fits, we
shift it right and see whether anything remains. Note that we
can't shift sizeof (LONGEST) * HOST_CHAR_BIT bits or more in one
operation, because many compilers will warn about such a shift
(which always produces a zero result). Sometimes TARGET_INT_BIT
or TARGET_LONG_BIT will be that big, sometimes not. To deal with
the case where it is we just always shift the value more than
once, with fewer bits each time. */
un = (ULONGEST)n >> 2;
if (long_p == 0
&& (un >> (TARGET_INT_BIT - 2)) == 0)
{
high_bit = ((ULONGEST)1) << (TARGET_INT_BIT-1);
/* A large decimal (not hex or octal) constant (between INT_MAX
and UINT_MAX) is a long or unsigned long, according to ANSI,
never an unsigned int, but this code treats it as unsigned
int. This probably should be fixed. GCC gives a warning on
such constants. */
#if 0
unsigned_type = builtin_type_unsigned_int;
signed_type = builtin_type_int;
#endif
}
else if (long_p <= 1
&& (un >> (TARGET_LONG_BIT - 2)) == 0)
{
high_bit = ((ULONGEST)1) << (TARGET_LONG_BIT-1);
#if 0
unsigned_type = builtin_type_unsigned_long;
signed_type = builtin_type_long;
#endif
}
else
{
int shift;
if (sizeof (ULONGEST) * HOST_CHAR_BIT < TARGET_LONG_LONG_BIT)
/* A long long does not fit in a LONGEST. */
shift = (sizeof (ULONGEST) * HOST_CHAR_BIT - 1);
else
shift = (TARGET_LONG_LONG_BIT - 1);
high_bit = (ULONGEST) 1 << shift;
#if 0
unsigned_type = builtin_type_unsigned_long_long;
signed_type = builtin_type_long_long;
#endif
}
putithere->typed_val_int.val = n;
/* If the high bit of the worked out type is set then this number
has to be unsigned. */
#if 0
if (unsigned_p || (n & high_bit))
{
putithere->typed_val_int.type = unsigned_type;
}
else
{
putithere->typed_val_int.type = signed_type;
}
#endif
return INT;
}
/* Print an error message saying that we couldn't make sense of a
\^mumble sequence in a string or character constant. START and END
indicate a substring of some larger string that contains the
erroneous backslash sequence, missing the initial backslash. */
static NORETURN int
no_control_char_error (const char *start, const char *end)
{
int len = end - start;
char *copy = alloca (end - start + 1);
memcpy (copy, start, len);
copy[len] = '\0';
error ("There is no control character `\\%s' in the `%s' character set.",
copy, target_charset ());
return 0;
}
static int
target_char_to_control_char (int c, int *ctrl_char)
{
*ctrl_char = (c & 037);
return 1;
}
static int
host_char_to_target (int c, int *ctrl_char)
{
*ctrl_char = c;
return 1;
}
static char backslashable[] = "abefnrtv";
static char represented[] = "\a\b\e\f\n\r\t\v";
/* Translate the backslash the way we would in the host character set. */
static int
c_parse_backslash (int host_char, int *target_char)
{
const char *ix;
ix = strchr (backslashable, host_char);
if (! ix)
return 0;
else
*target_char = represented[ix - backslashable];
return 1;
}
/* Parse a C escape sequence. STRING_PTR points to a variable
containing a pointer to the string to parse. That pointer
should point to the character after the \. That pointer
is updated past the characters we use. The value of the
escape sequence is returned.
A negative value means the sequence \ newline was seen,
which is supposed to be equivalent to nothing at all.
If \ is followed by a null character, we return a negative
value and leave the string pointer pointing at the null character.
If \ is followed by 000, we return 0 and leave the string pointer
after the zeros. A value of 0 does not mean end of string. */
static int
parse_escape (char **string_ptr)
{
int target_char;
int c = *(*string_ptr)++;
if (c_parse_backslash (c, &target_char))
return target_char;
else
switch (c)
{
case '\n':
return -2;
case 0:
(*string_ptr)--;
return 0;
case '^':
{
/* Remember where this escape sequence started, for reporting
errors. */
char *sequence_start_pos = *string_ptr - 1;
c = *(*string_ptr)++;
if (c == '?')
{
/* XXXCHARSET: What is `delete' in the host character set? */
c = 0177;
if (!host_char_to_target (c, &target_char))
error ("There is no character corresponding to `Delete' "
"in the target character set `%s'.", host_charset ());
return target_char;
}
else if (c == '\\')
target_char = parse_escape (string_ptr);
else
{
if (!host_char_to_target (c, &target_char))
no_control_char_error (sequence_start_pos, *string_ptr);
}
/* Now target_char is something like `c', and we want to find
its control-character equivalent. */
if (!target_char_to_control_char (target_char, &target_char))
no_control_char_error (sequence_start_pos, *string_ptr);
return target_char;
}
/* XXXCHARSET: we need to use isdigit and value-of-digit
methods of the host character set here. */
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
{
int i = c - '0';
int count = 0;
while (++count < 3)
{
c = (**string_ptr);
if (c >= '0' && c <= '7')
{
(*string_ptr)++;
i *= 8;
i += c - '0';
}
else
{
break;
}
}
return i;
}
default:
if (!host_char_to_target (c, &target_char))
error
("The escape sequence `\%c' is equivalent to plain `%c', which"
" has no equivalent\n" "in the `%s' character set.", c, c,
target_charset ());
return target_char;
}
}
struct token
{
char *operator;
int token;
int opcode;
};
static const struct token tokentab3[] =
{
{">>=", ASSIGN_MODIFY, BINOP_RSH},
{"<<=", ASSIGN_MODIFY, BINOP_LSH},
{"::*", COLONCOLONSTAR, 0} /* FIXME: Whitespace allowed in there */
};
static const struct token tokentab2[] =
{
{"+=", ASSIGN_MODIFY, BINOP_ADD},
{"-=", ASSIGN_MODIFY, BINOP_SUB},
{"*=", ASSIGN_MODIFY, BINOP_MUL},
{"/=", ASSIGN_MODIFY, BINOP_DIV},
{"%=", ASSIGN_MODIFY, BINOP_REM},
{"|=", ASSIGN_MODIFY, BINOP_BITWISE_IOR},
{"&=", ASSIGN_MODIFY, BINOP_BITWISE_AND},
{"^=", ASSIGN_MODIFY, BINOP_BITWISE_XOR},
{"++", INCREMENT, BINOP_END},
{"--", DECREMENT, BINOP_END},
{"->", ARROW, BINOP_END},
{"&&", ANDAND, BINOP_END},
{"||", OROR, BINOP_END},
{"::", COLONCOLON, BINOP_END},
{"<<", LSH, BINOP_END},
{">>", RSH, BINOP_END},
{"==", EQUAL, BINOP_END},
{"!=", NOTEQUAL, BINOP_END},
{"<=", LEQ, BINOP_END},
{">=", GEQ, BINOP_END}
};
/* Read one token, getting characters through lexptr. */
static int
yylex ()
{
int c;
int namelen;
unsigned int i;
char *tokstart;
char *tokptr;
int tempbufindex;
static char *tempbuf;
static int tempbufsize;
struct symbol * sym_class = NULL;
char * token_string = NULL;
int class_prefix = 0;
int unquoted_expr;
retry:
prev_lexptr = lexptr;
unquoted_expr = 1;
tokstart = lexptr;
/* See if it is a special token of length 3. */
for (i = 0; i < sizeof tokentab3 / sizeof tokentab3[0]; i++)
if (strncmp (tokstart, tokentab3[i].operator, 3) == 0)
{
lexptr += 3;
yylval.opcode = tokentab3[i].opcode;
return tokentab3[i].token;
}
/* See if it is a special token of length 2. */
for (i = 0; i < sizeof tokentab2 / sizeof tokentab2[0]; i++)
if (strncmp (tokstart, tokentab2[i].operator, 2) == 0)
{
lexptr += 2;
yylval.opcode = tokentab2[i].opcode;
return tokentab2[i].token;
}
switch (c = *tokstart)
{
case 0:
return 0;
case ' ':
case '\t':
case '\n':
lexptr++;
goto retry;
case '\'':
/* We either have a character constant ('0' or '\177' for example)
or we have a quoted symbol reference ('foo(int,int)' in C++
for example). */
lexptr++;
c = *lexptr++;
if (c == '\\')
c = parse_escape (&lexptr);
else if (c == '\'')
error ("Empty character constant.");
else if (! host_char_to_target (c, &c))
{
int toklen = lexptr - tokstart + 1;
char *tok = alloca (toklen + 1);
memcpy (tok, tokstart, toklen);
tok[toklen] = '\0';
error ("There is no character corresponding to %s in the target "
"character set `%s'.", tok, target_charset ());
}
yylval.typed_val_int.val = c;
#if 0
yylval.typed_val_int.type = builtin_type_char;
#endif
c = *lexptr++;
if (c != '\'')
error ("Invalid character constant.");
return INT;
case '(':
case ')':
case ',':
lexptr++;
return c;
case '.':
if (lexptr[1] == '.' && lexptr[2] == '.')
{
lexptr += 3;
return ELLIPSIS;
}
/* Might be a floating point number. */
if (lexptr[1] < '0' || lexptr[1] > '9')
goto symbol; /* Nope, must be a symbol. */
/* FALL THRU into number case. */
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
{
/* It's a number. */
int got_dot = 0, got_e = 0, toktype;
char *p = tokstart;
int hex = 0;
if (c == '0' && (p[1] == 'x' || p[1] == 'X'))
{
p += 2;
hex = 1;
}
else if (c == '0' && (p[1]=='t' || p[1]=='T' || p[1]=='d' || p[1]=='D'))
{
p += 2;
hex = 0;
}
for (;; ++p)
{
/* This test includes !hex because 'e' is a valid hex digit
and thus does not indicate a floating point number when
the radix is hex. */
if (!hex && !got_e && (*p == 'e' || *p == 'E'))
got_dot = got_e = 1;
/* This test does not include !hex, because a '.' always indicates
a decimal floating point number regardless of the radix. */
/* drow: Is that true in C99? */
else if (!got_dot && *p == '.')
got_dot = 1;
else if (got_e && (p[-1] == 'e' || p[-1] == 'E')
&& (*p == '-' || *p == '+'))
/* This is the sign of the exponent, not the end of the
number. */
continue;
/* We will take any letters or digits. parse_number will
complain if past the radix, or if L or U are not final. */
else if ((*p < '0' || *p > '9')
&& ((*p < 'a' || *p > 'z')
&& (*p < 'A' || *p > 'Z')))
break;
}
toktype = parse_number (tokstart, p - tokstart, got_dot|got_e, &yylval);
if (toktype == ERROR)
{
char *err_copy = (char *) alloca (p - tokstart + 1);
memcpy (err_copy, tokstart, p - tokstart);
err_copy[p - tokstart] = 0;
error ("Invalid number \"%s\".", err_copy);
}
lexptr = p;
return toktype;
}
case '+':
case '-':
case '*':
case '/':
case '%':
case '|':
case '&':
case '^':
case '~':
case '!':
case '@':
case '<':
case '>':
case '[':
case ']':
case '?':
case ':':
case '=':
case '{':
case '}':
symbol:
lexptr++;
return c;
case '"':
/* Build the gdb internal form of the input string in tempbuf,
translating any standard C escape forms seen. Note that the
buffer is null byte terminated *only* for the convenience of
debugging gdb itself and printing the buffer contents when
the buffer contains no embedded nulls. Gdb does not depend
upon the buffer being null byte terminated, it uses the length
string instead. This allows gdb to handle C strings (as well
as strings in other languages) with embedded null bytes */
tokptr = ++tokstart;
tempbufindex = 0;
do {
char *char_start_pos = tokptr;
/* Grow the static temp buffer if necessary, including allocating
the first one on demand. */
if (tempbufindex + 1 >= tempbufsize)
{
tempbuf = (char *) realloc (tempbuf, tempbufsize += 64);
}
switch (*tokptr)
{
case '\0':
case '"':
/* Do nothing, loop will terminate. */
break;
case '\\':
tokptr++;
c = parse_escape (&tokptr);
if (c == -1)
{
continue;
}
tempbuf[tempbufindex++] = c;
break;
default:
c = *tokptr++;
if (! host_char_to_target (c, &c))
{
int len = tokptr - char_start_pos;
char *copy = alloca (len + 1);
memcpy (copy, char_start_pos, len);
copy[len] = '\0';
error ("There is no character corresponding to `%s' "
"in the target character set `%s'.",
copy, target_charset ());
}
tempbuf[tempbufindex++] = c;
break;
}
} while ((*tokptr != '"') && (*tokptr != '\0'));
if (*tokptr++ != '"')
{
error ("Unterminated string in expression.");
}
tempbuf[tempbufindex] = '\0'; /* See note above */
#if 1
free (tempbuf);
error ("Unexpected string literal.");
#else
yylval.sval.ptr = tempbuf;
yylval.sval.length = tempbufindex;
lexptr = tokptr;
return (STRING);
#endif
}
if (!(c == '_' || c == '$'
|| (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')))
/* We must have come across a bad character (e.g. ';'). */
error ("Invalid character '%c' in expression.", c);
/* It's a name. See how long it is. */
namelen = 0;
for (c = tokstart[namelen];
(c == '_' || c == '$' || (c >= '0' && c <= '9')
|| (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));)
c = tokstart[++namelen];
lexptr += namelen;
tryname:
/* Catch specific keywords. Should be done with a data structure. */
switch (namelen)
{
case 8:
if (strncmp (tokstart, "operator", 8) == 0)
return OPERATOR;
if (strncmp (tokstart, "restrict", 8) == 0)
return RESTRICT;
if (strncmp (tokstart, "unsigned", 8) == 0)
return UNSIGNED;
if (strncmp (tokstart, "template", 8) == 0)
return TEMPLATE;
if (strncmp (tokstart, "volatile", 8) == 0)
return VOLATILE_KEYWORD;
break;
case 7:
if (strncmp (tokstart, "wchar_t", 7) == 0)
return WCHAR_T;
break;
case 6:
if (strncmp (tokstart, "delete", 6) == 0)
return DELETE;
if (strncmp (tokstart, "struct", 6) == 0)
return STRUCT;
if (strncmp (tokstart, "signed", 6) == 0)
return SIGNED_KEYWORD;
if (strncmp (tokstart, "sizeof", 6) == 0)
return SIZEOF;
if (strncmp (tokstart, "double", 6) == 0)
return DOUBLE_KEYWORD;
break;
case 5:
if (strncmp (tokstart, "false", 5) == 0)
return FALSEKEYWORD;
if (strncmp (tokstart, "class", 5) == 0)
return CLASS;
if (strncmp (tokstart, "union", 5) == 0)
return UNION;
if (strncmp (tokstart, "float", 5) == 0)
return FLOAT_KEYWORD;
if (strncmp (tokstart, "short", 5) == 0)
return SHORT;
if (strncmp (tokstart, "const", 5) == 0)
return CONST_KEYWORD;
break;
case 4:
if (strncmp (tokstart, "void", 4) == 0)
return VOID;
if (strncmp (tokstart, "bool", 4) == 0)
return BOOL;
if (strncmp (tokstart, "char", 4) == 0)
return BOOL;
if (strncmp (tokstart, "enum", 4) == 0)
return ENUM;
if (strncmp (tokstart, "long", 4) == 0)
return LONG;
if (strncmp (tokstart, "true", 4) == 0)
return TRUEKEYWORD;
break;
case 3:
if (strncmp (tokstart, "new", 3) == 0)
return NEW;
if (strncmp (tokstart, "int", 3) == 0)
return INT_KEYWORD;
break;
default:
break;
}
yylval.comp = d_make_name (di, tokstart, namelen);
return NAME;
}
void
yyerror (msg)
char *msg;
{
if (prev_lexptr)
lexptr = prev_lexptr;
error ("A %s in expression, near `%s'.", (msg ? msg : "error"), lexptr);
}
char *prev_lexptr;
char *lexptr;
int main(int argc, char **argv)
{
struct d_info myinfo;
int err = 0;
char *str;
lexptr = argv[1];
d_init_info (NULL, DMGL_PARAMS | DMGL_ANSI, 2 * strlen (lexptr), &myinfo);
di = &myinfo;
yyparse ();
str = d_print (DMGL_PARAMS | DMGL_ANSI, result, &err);
printf ("Result is %s\n", str);
return 0;
}
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: C++/Java regressions
@ 2003-11-26 22:48 Michael Elizabeth Chastain
0 siblings, 0 replies; 27+ messages in thread
From: Michael Elizabeth Chastain @ 2003-11-26 22:48 UTC (permalink / raw)
To: ian, mec.gnu; +Cc: drow, gdb
Hi Ian,
> I have probably lost the context of the question. I am only talking
> about the case where DMGL_PARAMS is not passed. In that case, the
> demangler will indeed print `Foo::method' for both of your examples.
> For that matter, it will also print `Foo::method' for `int method
> (int);'.
Ah, sorry, I am not providing enough context.
The context is this kind of message from gdb:
(gdb) continue
Continuing.
Breakpoint 3, A::bar(int) const (this=0xbffff770, arg=15) at /berman/fsf/_today_/source/gdb/HEAD/src/gdb/testsuite/gdb.cp/method.cc:44
(This output is from the old demangler).
gdb wants to print a nice message showing the name of the function and
its arguments. That's why gdb calls the demangler without DMGL_PARAMS
and then writes its own paramater list. But then that raises the
question of where the "const" goes.
The delicate part is that gdb doesn't mind losing the params,
because gdb is going to print the params itself manually. But I
do mind losing the "const" because gdb doesn't print its own "const".
> I think that is appropriate. Without DMGL_PARAMS, you can't
> distinguish any Foo::method overloaded based on parameter types. So
> it seems logical to me that you also shouldn't be able to distinguish
> overloading based on the method qualifier. And that is how the V2
> demangler behaved when DMGL_PARAMS was not passed.
>
> Does that make sense?
Totally.
I think the real issue is that us gdb folks need to sit down with some
use cases and figure out what we want to print in all situations. Then
translate that down to requests for enhanced demangler API's. But it's
lame of me to ask "can you tweak the demangler to produce one string
that co-incidentally looks nice for us". In a case like the above, I
think gdb really wants some kind of structured return value, and then
gdb can assemble the pieces any way it wants.
For now, I will be happy if the new demangler has no regressions
compared to the old demangler. And the new demangler already has
at least one bug fix shown by the gdb test suite. We can come back
with our structured API request when we are ready.
Michael C
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: C++/Java regressions
2003-11-26 22:28 ` Daniel Jacobowitz
@ 2003-11-26 22:34 ` Ian Lance Taylor
0 siblings, 0 replies; 27+ messages in thread
From: Ian Lance Taylor @ 2003-11-26 22:34 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: Michael Elizabeth Chastain, gdb
Daniel Jacobowitz <drow@mvista.com> writes:
> It does make sense, but I see Michael's concern. If you look at the
> complete GDB output in this case, you get roughly:
> Stopped at breakpoint 1, A::bar () for A::bar()
> Stopped at breakpoint 1, A::bar () for A::bar() const
> Stopped at breakpoint 1, A::bar (a = 1) for A::bar(int)
Ah.
> I still think the demangler should return A::bar. If we want GDB's
> output to be unambiguous then GDB is the right place to print the
> const. Without debug info we may not have it... but who really cares?
It's certainly easy for me to do it either way, and I doubt anybody
other than the GDB group really cares, so y'all just tell me what to
do.
Ian
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: C++/Java regressions
2003-11-26 22:21 ` Ian Lance Taylor
@ 2003-11-26 22:28 ` Daniel Jacobowitz
2003-11-26 22:34 ` Ian Lance Taylor
0 siblings, 1 reply; 27+ messages in thread
From: Daniel Jacobowitz @ 2003-11-26 22:28 UTC (permalink / raw)
To: Ian Lance Taylor; +Cc: Michael Elizabeth Chastain, gdb
On Wed, Nov 26, 2003 at 05:21:43PM -0500, Ian Lance Taylor wrote:
> mec.gnu@mindspring.com (Michael Elizabeth Chastain) writes:
>
> > ian> Yes, I think it should print A::bar without the const. I have the
> > ian> patch in my sources, but I haven't checked it in yet.
> >
> > But what about:
> >
> > class Foo
> > {
> > public:
> > int method ();
> > int method () const;
> > };
> >
> > If the name comes back as "Foo::method" then we have ambiguity
> > in gdb's output.
> >
> > I think the const looks ugly and the code that prints the function
> > name is also ugly. But I don't wanna print the same name for two
> > different methods.
>
> I have probably lost the context of the question. I am only talking
> about the case where DMGL_PARAMS is not passed. In that case, the
> demangler will indeed print `Foo::method' for both of your examples.
> For that matter, it will also print `Foo::method' for `int method
> (int);'.
>
> If DMGL_PARAMS is passed, then the demangler will print
> `Foo::method()' and `Foo::method() const' as usual.
>
> I think that is appropriate. Without DMGL_PARAMS, you can't
> distinguish any Foo::method overloaded based on parameter types. So
> it seems logical to me that you also shouldn't be able to distinguish
> overloading based on the method qualifier. And that is how the V2
> demangler behaved when DMGL_PARAMS was not passed.
>
> Does that make sense?
It does make sense, but I see Michael's concern. If you look at the
complete GDB output in this case, you get roughly:
Stopped at breakpoint 1, A::bar () for A::bar()
Stopped at breakpoint 1, A::bar () for A::bar() const
Stopped at breakpoint 1, A::bar (a = 1) for A::bar(int)
I still think the demangler should return A::bar. If we want GDB's
output to be unambiguous then GDB is the right place to print the
const. Without debug info we may not have it... but who really cares?
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: C++/Java regressions
2003-11-26 21:44 Michael Elizabeth Chastain
@ 2003-11-26 22:21 ` Ian Lance Taylor
2003-11-26 22:28 ` Daniel Jacobowitz
0 siblings, 1 reply; 27+ messages in thread
From: Ian Lance Taylor @ 2003-11-26 22:21 UTC (permalink / raw)
To: Michael Elizabeth Chastain; +Cc: drow, gdb
mec.gnu@mindspring.com (Michael Elizabeth Chastain) writes:
> ian> Yes, I think it should print A::bar without the const. I have the
> ian> patch in my sources, but I haven't checked it in yet.
>
> But what about:
>
> class Foo
> {
> public:
> int method ();
> int method () const;
> };
>
> If the name comes back as "Foo::method" then we have ambiguity
> in gdb's output.
>
> I think the const looks ugly and the code that prints the function
> name is also ugly. But I don't wanna print the same name for two
> different methods.
I have probably lost the context of the question. I am only talking
about the case where DMGL_PARAMS is not passed. In that case, the
demangler will indeed print `Foo::method' for both of your examples.
For that matter, it will also print `Foo::method' for `int method
(int);'.
If DMGL_PARAMS is passed, then the demangler will print
`Foo::method()' and `Foo::method() const' as usual.
I think that is appropriate. Without DMGL_PARAMS, you can't
distinguish any Foo::method overloaded based on parameter types. So
it seems logical to me that you also shouldn't be able to distinguish
overloading based on the method qualifier. And that is how the V2
demangler behaved when DMGL_PARAMS was not passed.
Does that make sense?
Ian
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: C++/Java regressions
@ 2003-11-26 21:44 Michael Elizabeth Chastain
2003-11-26 22:21 ` Ian Lance Taylor
0 siblings, 1 reply; 27+ messages in thread
From: Michael Elizabeth Chastain @ 2003-11-26 21:44 UTC (permalink / raw)
To: drow, ian; +Cc: gdb
ian> Yes, I think it should print A::bar without the const. I have the
ian> patch in my sources, but I haven't checked it in yet.
But what about:
class Foo
{
public:
int method ();
int method () const;
};
If the name comes back as "Foo::method" then we have ambiguity
in gdb's output.
I think the const looks ugly and the code that prints the function
name is also ugly. But I don't wanna print the same name for two
different methods.
Michael C
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: C++/Java regressions
2003-11-26 21:18 Michael Elizabeth Chastain
@ 2003-11-26 21:33 ` Ian Lance Taylor
0 siblings, 0 replies; 27+ messages in thread
From: Ian Lance Taylor @ 2003-11-26 21:33 UTC (permalink / raw)
To: Michael Elizabeth Chastain; +Cc: drow, gdb
mec.gnu@mindspring.com (Michael Elizabeth Chastain) writes:
> Briefly, the call tree is:
>
> lookup_symbol_aux
> current_language->la_lookup_symbol_nonlocal
> lookup_symbol_file
> lookup_symbol_static [1]
> lookup_symbol_aux_block
> lookup_symbol_global [2]
> lookup_possible_namespace_symbol [3]
> lookup_symbol_aux_symtabs [4]
> lookup_symbol_aux_psymtabs
>
> You are probably getting a hit at [3].
>
> Check the value of "block" in lookup_symbol_file. I bet that
> you have block=0. That prevents [1] from finding a match in the current
> static block.
Yes, block == 0. Sounds you like have the right analysis.
> I think the right fix is to pass a correct "block" to local_symbol_aux
> so that [1] can do its job properly.
I have no idea what this involves, myself.
Ian
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: C++/Java regressions
@ 2003-11-26 21:18 Michael Elizabeth Chastain
2003-11-26 21:33 ` Ian Lance Taylor
0 siblings, 1 reply; 27+ messages in thread
From: Michael Elizabeth Chastain @ 2003-11-26 21:18 UTC (permalink / raw)
To: drow, ian; +Cc: gdb
ian> Good question. My guess is that it's because lookup_symbol_aux()
ian> calls current_language->la_lookup_symbol_nonlocal() before it calls
ian> lookup_symbol_aux_psymtabs(). If I force la_lookup_symbol_nonlocal()
ian> to return NULL, then lookup_symbol_aux_psymtabs() finds the typedef,
ian> and `ptype T5<int>' works more or less correctly.
Have a look at
http://sources.redhat.com/gdb/bugs/1465
I just mailed in an analysis of a similar bug. It will take some
time for gnats to post it.
Briefly, the call tree is:
lookup_symbol_aux
current_language->la_lookup_symbol_nonlocal
lookup_symbol_file
lookup_symbol_static [1]
lookup_symbol_aux_block
lookup_symbol_global [2]
lookup_possible_namespace_symbol [3]
lookup_symbol_aux_symtabs [4]
lookup_symbol_aux_psymtabs
You are probably getting a hit at [3].
Check the value of "block" in lookup_symbol_file. I bet that
you have block=0. That prevents [1] from finding a match in the current
static block.
[4] is a kludge that looks in ALL static blocks. That's not good.
Before [3] came along as part of DavidC's namespace work,
[4] was happening all the time.
I think the right fix is to pass a correct "block" to local_symbol_aux
so that [1] can do its job properly.
Michael C
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: C++/Java regressions
2003-11-25 17:14 ` David Carlton
@ 2003-11-25 17:59 ` Daniel Jacobowitz
0 siblings, 0 replies; 27+ messages in thread
From: Daniel Jacobowitz @ 2003-11-25 17:59 UTC (permalink / raw)
To: gdb
On Tue, Nov 25, 2003 at 09:14:31AM -0800, David Carlton wrote:
> On Tue, 25 Nov 2003 12:06:32 -0500 (EST), mec.gnu@mindspring.com (Michael Elizabeth Chastain) said:
>
> > I asked:
>
> mec> What is the correct output when a breakpoint is taken on
> mec> "A::bar(int) const" ?
>
> Probably my first choice would be A::bar(int) const, and my second
> choice would be A::bar. A::bar const seems a bit weird to me. Having
> said that:
>
> > After some deliberation, I decided that I want the test script
> > to be liberal in what it accepts.
> ...
> > If someone wants to spend time on making gdb's output better here,
> > that is okay with me. But I decided that it's too low priority for
> > my attention and the list bandwidth.
>
> > David C is that okay with you?
>
> Yes, that's fine with me. What is important is that the breakpoint be
> set on the correct method, and that the continue reach the correct
> breakpoint. That is in fact happening; I don't really see the point
> of having a failing test there, or even a kfailing test.
This works for me too.
Meanwhile, fixing DMGL_PARAMS not to print the trailing const seems
like a reasonable change.
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: C++/Java regressions
2003-11-25 4:44 Michael Elizabeth Chastain
@ 2003-11-25 17:54 ` Ian Lance Taylor
0 siblings, 0 replies; 27+ messages in thread
From: Ian Lance Taylor @ 2003-11-25 17:54 UTC (permalink / raw)
To: Michael Elizabeth Chastain; +Cc: carlton, gdb
mec.gnu@mindspring.com (Michael Elizabeth Chastain) writes:
> For what it's worth, how would I file a demangler bug report?
> Do I just file it in gcc bugzilla, because the primary copy of
> libiberty lives in gcc?
Yes.
In the short run, you can just send bug reports to me, but in the long
run, and right now too if you prefer, gcc bugzilla is the best place.
Ian
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: C++/Java regressions
2003-11-25 17:06 Michael Elizabeth Chastain
@ 2003-11-25 17:14 ` David Carlton
2003-11-25 17:59 ` Daniel Jacobowitz
0 siblings, 1 reply; 27+ messages in thread
From: David Carlton @ 2003-11-25 17:14 UTC (permalink / raw)
To: Michael Elizabeth Chastain; +Cc: gdb
On Tue, 25 Nov 2003 12:06:32 -0500 (EST), mec.gnu@mindspring.com (Michael Elizabeth Chastain) said:
> I asked:
mec> What is the correct output when a breakpoint is taken on
mec> "A::bar(int) const" ?
Probably my first choice would be A::bar(int) const, and my second
choice would be A::bar. A::bar const seems a bit weird to me. Having
said that:
> After some deliberation, I decided that I want the test script
> to be liberal in what it accepts.
...
> If someone wants to spend time on making gdb's output better here,
> that is okay with me. But I decided that it's too low priority for
> my attention and the list bandwidth.
> David C is that okay with you?
Yes, that's fine with me. What is important is that the breakpoint be
set on the correct method, and that the continue reach the correct
breakpoint. That is in fact happening; I don't really see the point
of having a failing test there, or even a kfailing test.
David Carlton
carlton@kealia.com
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: C++/Java regressions
@ 2003-11-25 17:06 Michael Elizabeth Chastain
2003-11-25 17:14 ` David Carlton
0 siblings, 1 reply; 27+ messages in thread
From: Michael Elizabeth Chastain @ 2003-11-25 17:06 UTC (permalink / raw)
To: mec.gnu; +Cc: gdb, ian
[Ian might not need any more of this ...]
I asked:
mec> What is the correct output when a breakpoint is taken on
mec> "A::bar(int) const" ?
After some deliberation, I decided that I want the test script
to be liberal in what it accepts.
class A {
public:
...
int foo (int arg);
int bar (int arg) const;
};
When a breakpoint is taken on A::foo, the script currently accepts:
Breakpoint N, A::foo (this=...)
Breakpoint N, A::foo(int) (this=...)
When a breakpoint is taken on A::bar, the script currently accepts:
Breakpoint N, A::bar (this=...)
Breakpoint N, A::bar(int) const (this=...)
I am going to keep all these patterns and add another pattern to
accept what gdb is printing today:
Breakpoint N, A::bar const (this=...)
If someone wants to spend time on making gdb's output better here,
that is okay with me. But I decided that it's too low priority for
my attention and the list bandwidth.
David C is that okay with you?
Patch to follow.
Michael C
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: C++/Java regressions
@ 2003-11-25 15:33 Michael Elizabeth Chastain
0 siblings, 0 replies; 27+ messages in thread
From: Michael Elizabeth Chastain @ 2003-11-25 15:33 UTC (permalink / raw)
To: drow, mec.gnu; +Cc: carlton, gdb, ian
drow> The former, since ths has been the documented interface to the
drow> demangler forever.
Sounds good to me.
drow> I believe the GNU v2 demangler supported it.
Yes it does.
drow> But I thought we did everywhere - where aren't we that this caused
drow> a problem?
I don't know what's causing the problem with the java tests.
print_frame in stack.c is part of the problem with gdb.cp/method.exp.
It's intentionally omitting DMGL_PARAMS. But actually it's just
a precursor for some other code that I haven't find yet.
With v2, when DMGL_PARAMS is not set, the arguments don't get printed,
and the "const" modifier doesn't get printed either.
Breakpoint 3, A::bar (this=0xbffff770, arg=15) at ...
With the old v3 demangler, the args get printed even though we
didn't ask for them:
Breakpoint 3, A::bar(int) const (this=...)
With the new v3 demangler, the args do not get printed, but the
"const" attribute is printed:
Breakpoint 3, A::bar const (this=...)
So actually the old demangler was broken, and the new demangler is
doing what we ask it to do. Now we have to think about what we really
want to see.
What is the correct output when a breakpoint is taken on
"A::bar(int) const" ?
(This particular test accepts either "A::bar" or "A::bar(int) const",
but not "A::bar const". That's why the FAIL popped up. Just another
bit of ad-hoc matching. After we decide what should be printed,
I can change the test).
Michael C
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: C++/Java regressions
2003-11-25 14:49 Michael Elizabeth Chastain
@ 2003-11-25 15:06 ` Daniel Jacobowitz
0 siblings, 0 replies; 27+ messages in thread
From: Daniel Jacobowitz @ 2003-11-25 15:06 UTC (permalink / raw)
To: Michael Elizabeth Chastain; +Cc: carlton, gdb, ian
On Tue, Nov 25, 2003 at 09:49:50AM -0500, Michael Chastain wrote:
> Good morning,
>
> I see the same regressions that David does. This happened in all
> my gcc-3 configurations. If you want a specific configuration:
>
> target = native, host = i686-pc-linux-gnu, osversion = red-hat-8.0
> gdb = HEAD 2003-11-25 04:21:57 UTC
> gcc = 3.3.2
> binutils = 2.14
> glibc = 2.2.93-5-rh
> gformat = dwarf-2
> glevel = 2
>
> I have two issues.
>
> === Issue #1: the demangler changed its interface.
>
> The demangler used to return parameters all the time, but now it looks
> like it returns parameters only if DMGL_PARAMS is given.
>
> This change did not happen with "complete rewrite". It happened
> with the followup patch:
>
> 2003-11-22 Ian Lance Taylor <ian@wasabisystems.com>
>
> * cp-demangle.c (d_encoding): Add top_level parameter. Change all
> callers.
> (print_usage): Display new -p option.
> (long_options): Add --no-params.
> (main): Accept and handle -p.
>
> So the questions are:
>
> (A) Does gdb want to keep getting the parameters?
> (My answer: yes we do).
>
> (B) If we want the parameters, should we change gdb to set DMGL_PARAMS,
> or should we ask the demangler to keep giving us the parameters with
> our existing flags, which is usually just DMGL_ANSI? (My answer:
> let Ian tell us what the interface actually is, and then we'll adapt
> gdb to match).
The former, since ths has been the documented interface to the
demangler forever. I believe the GNU v2 demangler supported it. But I
thought we did everywhere - where aren't we that this caused a problem?
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: C++/Java regressions
@ 2003-11-25 14:49 Michael Elizabeth Chastain
2003-11-25 15:06 ` Daniel Jacobowitz
0 siblings, 1 reply; 27+ messages in thread
From: Michael Elizabeth Chastain @ 2003-11-25 14:49 UTC (permalink / raw)
To: carlton, gdb, ian
Good morning,
I see the same regressions that David does. This happened in all
my gcc-3 configurations. If you want a specific configuration:
target = native, host = i686-pc-linux-gnu, osversion = red-hat-8.0
gdb = HEAD 2003-11-25 04:21:57 UTC
gcc = 3.3.2
binutils = 2.14
glibc = 2.2.93-5-rh
gformat = dwarf-2
glevel = 2
I have two issues.
=== Issue #1: the demangler changed its interface.
The demangler used to return parameters all the time, but now it looks
like it returns parameters only if DMGL_PARAMS is given.
This change did not happen with "complete rewrite". It happened
with the followup patch:
2003-11-22 Ian Lance Taylor <ian@wasabisystems.com>
* cp-demangle.c (d_encoding): Add top_level parameter. Change all
callers.
(print_usage): Display new -p option.
(long_options): Add --no-params.
(main): Accept and handle -p.
So the questions are:
(A) Does gdb want to keep getting the parameters?
(My answer: yes we do).
(B) If we want the parameters, should we change gdb to set DMGL_PARAMS,
or should we ask the demangler to keep giving us the parameters with
our existing flags, which is usually just DMGL_ANSI? (My answer:
let Ian tell us what the interface actually is, and then we'll adapt
gdb to match).
=== Issue #2: "unsigned" versus "unsigned int"
The new demangler prints "unsigned int" in some places where the old
demangler prints "unsigned".
This is fine. I updated gdb.cp/templates.exp to accept "unsigned int".
Michael C
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: C++/Java regressions
@ 2003-11-25 4:44 Michael Elizabeth Chastain
2003-11-25 17:54 ` Ian Lance Taylor
0 siblings, 1 reply; 27+ messages in thread
From: Michael Elizabeth Chastain @ 2003-11-25 4:44 UTC (permalink / raw)
To: carlton, ian; +Cc: gdb
Hi Ian and David,
My last spin was with gdb HEAD checked out on 2003-11-21 06:25:07.
I got some new demangler code, because my gdb HEAD had
"715 tests, 18 failures" instead of the old "715 tests, 31 failures".
However I did not get the "cp-demangle.c: complete rewrite" version.
I didn't see any demangler-related changes in my results.
I'll fire up some scripts and see if I can see any difference now.
ian> I'm not saying that the problem is not the demangler. I don't know
ian> what the problem is. If you can give more information, I would be
ian> happy to adjust the demangler.
Totally reasonable.
For what it's worth, how would I file a demangler bug report?
Do I just file it in gcc bugzilla, because the primary copy of
libiberty lives in gcc?
ian> I enclose the diff of gdb.sum.
Cool! Just because I'm such a gdb test suite geek, I'll post a
little analysis of what you are seeing.
I'd like to keep improving the test suite so that
"diff gdb-1.sum gdb-2.sum" has less noise in it.
It has been getting better lately.
Michael C
-PASS: gdb.base/pc-fp.exp: get value of $fp (0xbfffe788)
+PASS: gdb.base/pc-fp.exp: get value of $fp (0xbfffe388)
The test name has a machine address in it, so it fluctuates a bit
from run to run (obviously).
-PASS: gdb.cp/cplusfuncs.exp: print &'overload1arg(unsigned)'
+PASS: gdb.cp/cplusfuncs.exp: print &'overload1arg(unsigned int)'
You changed the demangler.
-KFAIL: gdb.cp/cplusfuncs.exp: print &'hairyfunc5' (PRMS: gdb/19)
-KFAIL: gdb.cp/cplusfuncs.exp: print &'hairyfunc6' (PRMS: gdb/19)
-KFAIL: gdb.cp/cplusfuncs.exp: print &'hairyfunc7' (PRMS: gdb/19)
+PASS: gdb.cp/cplusfuncs.exp: print &'hairyfunc5'
+PASS: gdb.cp/cplusfuncs.exp: print &'hairyfunc6'
+PASS: gdb.cp/cplusfuncs.exp: print &'hairyfunc7'
You fixed a bug in the demangler (a very old bug, gdb/19).
Cool!
-PASS: gdb.threads/print-threads.exp: Hit kill breakpoint, 9 (slow with kill breakpoint)
PASS: gdb.threads/print-threads.exp: Hit thread_function breakpoint, 4 (slow with kill breakpoint)
+PASS: gdb.threads/print-threads.exp: Hit kill breakpoint, 9 (slow with kill breakpoint)
Non-determinism in the order of execution of thread tests.
-PASS: gdb.threads/print-threads.exp: Hit thread_function breakpoint, 5 (slow with kill breakpoint)
PASS: gdb.threads/print-threads.exp: Hit kill breakpoint, 11 (slow with kill breakpoint)
+PASS: gdb.threads/print-threads.exp: Hit thread_function breakpoint, 5 (slow with kill breakpoint)
Ditto.
-PASS: gdb.threads/pthreads.exp: continue to bkpt at common_routine in thread 2
-PASS: gdb.threads/pthreads.exp: backtrace from thread 2 bkpt in common_routine
+FAIL: gdb.threads/pthreads.exp: continue to bkpt at common_routine in thread 2
My understanding is that this is a real race condition between
gdb and the operating system. It happens about one time every
500 or so test runs for me. Daniel J knows more about this.
Whatever it is, it's not a demangler problem.
-PASS: gdb.threads/schedlock.exp: other thread 2 didn't run
-PASS: gdb.threads/schedlock.exp: other thread 3 didn't run
PASS: gdb.threads/schedlock.exp: current thread ran
+PASS: gdb.threads/schedlock.exp: other thread 3 didn't run
+PASS: gdb.threads/schedlock.exp: other thread 4 didn't run
More thread non-determinism, sigh. As long as they all pass it's
okay.
^ permalink raw reply [flat|nested] 27+ messages in thread
end of thread, other threads:[~2003-12-01 16:45 UTC | newest]
Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-11-25 1:37 C++/Java regressions David Carlton
2003-11-25 1:48 ` The demangler was rewritten from scratch! Andrew Cagney
2003-11-25 3:58 ` C++/Java regressions Ian Lance Taylor
2003-11-26 4:04 ` Ian Lance Taylor
2003-11-26 15:32 ` Daniel Jacobowitz
2003-11-26 21:05 ` Ian Lance Taylor
2003-11-26 21:11 ` David Carlton
2003-11-26 21:12 ` Daniel Jacobowitz
2003-11-26 21:32 ` Ian Lance Taylor
2003-12-01 16:45 ` Daniel Jacobowitz
2003-11-30 2:57 ` Jim Blandy
2003-11-30 3:12 ` Daniel Jacobowitz
2003-11-25 4:44 Michael Elizabeth Chastain
2003-11-25 17:54 ` Ian Lance Taylor
2003-11-25 14:49 Michael Elizabeth Chastain
2003-11-25 15:06 ` Daniel Jacobowitz
2003-11-25 15:33 Michael Elizabeth Chastain
2003-11-25 17:06 Michael Elizabeth Chastain
2003-11-25 17:14 ` David Carlton
2003-11-25 17:59 ` Daniel Jacobowitz
2003-11-26 21:18 Michael Elizabeth Chastain
2003-11-26 21:33 ` Ian Lance Taylor
2003-11-26 21:44 Michael Elizabeth Chastain
2003-11-26 22:21 ` Ian Lance Taylor
2003-11-26 22:28 ` Daniel Jacobowitz
2003-11-26 22:34 ` Ian Lance Taylor
2003-11-26 22:48 Michael Elizabeth Chastain
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox