Re: [RFA]: Java Inferior Call Take 2

Jeff Johnston
2004-07-06T21:47:11Z

[-- Attachment #1: Type: text/plain, Size: 2307 bytes --]

Daniel Jacobowitz wrote:
> On Wed, Jun 23, 2004 at 05:55:07PM -0400, Jeff Johnston wrote:
>
>>Daniel Jacobowitz wrote:
>>
>>>On Wed, Jun 23, 2004 at 12:05:59PM +0100, Andrew Haley wrote:
>>>
>>>
>>>>This patch is now in mainline. Is there anything else you need?
>>>
>>>
>>>Yes. Two sets of questions left, one for Jeff and one [plus a little
>>>bit] for you...
>>>
>>>
>>>Jeff, one test still fails: calling addprint. I think this is mostly a
>>>GDB problem rather than GCC. Before starting the program I see this:
>>>
>>
>>Let me take a look at it. It is not failing in my all-patches-applied
>>build. Perhaps in splitting the patches up, I screwed up and missed
>>something.
>
>
> Thanks.
>

Ok, I figured out what piece I left out and have remade the patch. I can't
remember where we are on this regarding the workaround for gcc debug-info, but
at least you will be able to run the test with the full functionality now.
Please let me know what is needed next as I want to move this forward.

-- Jeff J.

>
>>> - Should we suppress jvclass and <clinit> the way we do for C++
>>> artificial methods?
>>>
>>
>>Perhaps remove <clinit>, but jvclass() is the constructor. There could be
>>multiple constructors and as an end-user, I would want to see the various
>>prototypes. I can't speak for what C++ does.
>
>
> In C++, the debug information marks whether a constructor was written
> by the user (i.e. the type really contains a constructor) or by the
> compiler (i.e. implicit). I imagine Java's debug information has the
> same thing. For minimum confusion, we choose not to print the
> artificial methods in C++ types; I think we should do the same for
> Java.
>
> (This shouldn't affect breakpointing it for users who know the
> constructor exists.)
>
>
>
>>> - Why did printing of the type change? There's only one definition
>>> of jvclass in the debug info, and it's marked Java.
>>>
>>
>>There are checks in the code based on current language. The current
>>language does not start as java. If you manually change it via set
>>language java, you will see the same results before and after.
>
>
> Bleeeeeeech. Thanks for explaining; definitely not your problem, but
> definitely a bug. If we're printing a type we ought to be using the
> type's language.
>

[-- Attachment #2: java-inferior-call.patch2 --]
[-- Type: text/plain, Size: 15938 bytes --]

Index: dwarf2read.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2read.c,v
retrieving revision 1.151
diff -u -p -r1.151 dwarf2read.c
--- dwarf2read.c 7 May 2004 14:29:33 -0000 1.151
+++ dwarf2read.c 6 Jul 2004 21:42:45 -0000
@@ -788,7 +788,8 @@ static void read_type_die (struct die_in

static char *determine_prefix (struct die_info *die, struct dwarf2_cu *);

-static char *typename_concat (const char *prefix, const char *suffix);
+static char *typename_concat (const char *prefix, const char *suffix,
+ struct dwarf2_cu *);

static void read_typedef (struct die_info *, struct dwarf2_cu *);

@@ -1502,7 +1503,8 @@ scan_partial_symbols (struct partial_die
/* Functions used to compute the fully scoped name of a partial DIE.

Normally, this is simple. For C++, the parent DIE's fully scoped
- name is concatenated with "::" and the partial DIE's name.
+ name is concatenated with "::" and the partial DIE's name. For
+ Java, the same thing occurs except that "." is used instead of "::".
Enumerators are an exception; they use the scope of their parent
enumeration type, i.e. the name of the enumeration type is not
prepended to the enumerator.
@@ -1558,7 +1560,7 @@ partial_die_parent_scope (struct partial
parent->scope = parent->name;
else
parent->scope = obconcat (&cu->comp_unit_obstack, grandparent_scope,
- "::", parent->name);
+ cu->language == language_java ? "." : "::", parent->name);
}
else if (parent->tag == DW_TAG_enumeration_type)
/* Enumerators should not get the name of the enumeration as a prefix. */
@@ -1590,7 +1592,11 @@ partial_die_full_name (struct partial_di
if (parent_scope == NULL)
return NULL;
else
- return concat (parent_scope, "::", pdi->name, NULL);
+ {
+ if (cu->language == language_java)
+ return concat (parent_scope, ".", pdi->name, NULL);
+ return concat (parent_scope, "::", pdi->name, NULL);
+ }
}

static void
@@ -1708,14 +1714,16 @@ add_partial_symbol (struct partial_die_i
return;
add_psymbol_to_list (actual_name, strlen (actual_name),
STRUCT_DOMAIN, LOC_TYPEDEF,
- cu->language == language_cplus
+ (cu->language == language_cplus
+ || cu->language == language_java)
? &objfile->global_psymbols
: &objfile->static_psymbols,
0, (CORE_ADDR) 0, cu->language, objfile);

- if (cu->language == language_cplus)
+ if (cu->language == language_cplus
+ || cu->language == language_java)
{
- /* For C++, these implicitly act as typedefs as well. */
+ /* For C++ and Java, these implicitly act as typedefs as well. */
add_psymbol_to_list (actual_name, strlen (actual_name),
VAR_DOMAIN, LOC_TYPEDEF,
&objfile->global_psymbols,
@@ -1725,7 +1733,8 @@ add_partial_symbol (struct partial_die_i
case DW_TAG_enumerator:
add_psymbol_to_list (actual_name, strlen (actual_name),
VAR_DOMAIN, LOC_CONST,
- cu->language == language_cplus
+ (cu->language == language_cplus
+ || cu->language == language_java)
? &objfile->global_psymbols
: &objfile->static_psymbols,
0, (CORE_ADDR) 0, cu->language, objfile);
@@ -1805,7 +1814,8 @@ static void
guess_structure_name (struct partial_die_info *struct_pdi,
struct dwarf2_cu *cu)
{
- if (cu->language == language_cplus
+ if ((cu->language == language_cplus
+ || cu->language == language_java)
&& cu->has_namespace_info == 0
&& struct_pdi->has_children)
{
@@ -2460,7 +2470,8 @@ read_func_scope (struct die_info *die, s
if (name == NULL || !dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu))
return;

- if (cu->language == language_cplus)
+ if (cu->language == language_cplus
+ || cu->language == language_java)
{
struct die_info *spec_die = die_specification (die, cu);

@@ -3101,7 +3112,29 @@ dwarf2_add_member_fn (struct field_info
/* Get name of member function. */
attr = dwarf2_attr (die, DW_AT_name, cu);
if (attr && DW_STRING (attr))
- fieldname = DW_STRING (attr);
+ {
+ /* Note: C++ and Java currently differ in how the member function
+ name is stored in the debug info. For Java, the member name is
+ fully qualified with prototype while C++ just has the member
+ name. To get the Java member name, we strip off any dot qualifiers
+ and remove the trailing prototype. */
+ char *dot_index;
+ char *lparen;
+ fieldname = DW_STRING (attr);
+ if (cu->language == language_java)
+ {
+ dot_index = strchr (fieldname, '.');
+ while (dot_index)
+ {
+ fieldname = dot_index + 1;
+ dot_index = strchr (fieldname, '.');
+ }
+ lparen = strchr (fieldname + 1, '(');
+ if (lparen)
+ fieldname = obsavestring (fieldname, lparen - fieldname,
+ &objfile->objfile_obstack);
+ }
+ }
else
return;

@@ -3292,7 +3325,8 @@ read_structure_type (struct die_info *di
attr = dwarf2_attr (die, DW_AT_name, cu);
if (attr && DW_STRING (attr))
{
- if (cu->language == language_cplus)
+ if (cu->language == language_cplus
+ || cu->language == language_java)
{
char *new_prefix = determine_class_name (die, cu);
TYPE_TAG_NAME (type) = obsavestring (new_prefix,
@@ -3398,6 +3432,9 @@ read_structure_type (struct die_info *di
{
static const char vptr_name[] =
{'_', 'v', 'p', 't', 'r', '\0'};
+ static const char vtable_name[] =
+ {'v', 't', 'a', 'b', 'l', 'e', '\0'};
+
int i;

/* Our own class provides vtbl ptr. */
@@ -3407,10 +3444,18 @@ read_structure_type (struct die_info *di
{
char *fieldname = TYPE_FIELD_NAME (t, i);

- if ((strncmp (fieldname, vptr_name,
- strlen (vptr_name) - 1)
- == 0)
- && is_cplus_marker (fieldname[strlen (vptr_name)]))
+ if (cu->language == language_java
+ && (strncmp (fieldname, vtable_name,
+ strlen (vtable_name) - 1)
+ == 0))
+ {
+ TYPE_VPTR_FIELDNO (type) = i;
+ break;
+ }
+ else if ((strncmp (fieldname, vptr_name,
+ strlen (vptr_name) - 1)
+ == 0)
+ && is_cplus_marker (fieldname[strlen (vptr_name)]))
{
TYPE_VPTR_FIELDNO (type) = i;
break;
@@ -3502,7 +3547,9 @@ read_enumeration_type (struct die_info *
TYPE_TAG_NAME (type) = obconcat (&objfile->objfile_obstack,
processing_current_prefix,
processing_current_prefix[0] == '\0'
- ? "" : "::",
+ ? "" :
+ cu->language == language_java
+ ? "." : "::",
name);
}
else
@@ -3527,7 +3574,7 @@ read_enumeration_type (struct die_info *
}

/* Determine the name of the type represented by DIE, which should be
- a named C++ compound type. Return the name in question; the caller
+ a named C++ or Java compound type. Return the name in question; the caller
is responsible for xfree()'ing it. */

static char *
@@ -3573,7 +3620,8 @@ determine_class_name (struct die_info *d
{
const char *name = dwarf2_name (die, cu);
new_prefix = typename_concat (processing_current_prefix,
- name ? name : "<<anonymous>>");
+ name ? name : "<<anonymous>>",
+ cu);
}

if (back_to != NULL)
@@ -3810,7 +3858,10 @@ read_namespace (struct die_info *die, st
char *temp_name = alloca (strlen (previous_prefix)
+ 2 + strlen(name) + 1);
strcpy (temp_name, previous_prefix);
- strcat (temp_name, "::");
+ if (cu->language == language_java)
+ strcat (temp_name, ".");
+ else
+ strcat (temp_name, "::");
strcat (temp_name, name);

processing_current_prefix = temp_name;
@@ -4099,10 +4150,11 @@ read_subroutine_type (struct die_info *d
type = die_type (die, cu);
ftype = lookup_function_type (type);

- /* All functions in C++ have prototypes. */
+ /* All functions in C++ and Java have prototypes. */
attr = dwarf2_attr (die, DW_AT_prototyped, cu);
if ((attr && (DW_UNSND (attr) != 0))
- || cu->language == language_cplus)
+ || cu->language == language_cplus
+ || cu->language == language_java)
TYPE_FLAGS (ftype) |= TYPE_FLAG_PROTOTYPED;

if (die->child != NULL)
@@ -4753,7 +4805,8 @@ load_partial_dies (bfd *abfd, char *info
else if (building_psymtab)
add_psymbol_to_list (part_die->name, strlen (part_die->name),
VAR_DOMAIN, LOC_CONST,
- cu->language == language_cplus
+ (cu->language == language_cplus
+ || cu->language == language_java)
? &cu->objfile->global_psymbols
: &cu->objfile->static_psymbols,
0, (CORE_ADDR) 0, cu->language, cu->objfile);
@@ -6357,7 +6410,8 @@ new_symbol (struct die_info *die, struct
read_structure_type, and the correct name is saved in
the type. */

- if (cu->language == language_cplus)
+ if (cu->language == language_cplus
+ || cu->language == language_java)
{
struct type *type = SYMBOL_TYPE (sym);

@@ -6374,7 +6428,7 @@ new_symbol (struct die_info *die, struct
}

{
- /* NOTE: carlton/2003-11-10: C++ class symbols shouldn't
+ /* NOTE: carlton/2003-11-10: C++ and Java class symbols shouldn't
really ever be static objects: otherwise, if you try
to, say, break of a class's method and you're in a file
which doesn't mention that class, it won't work unless
@@ -6385,15 +6439,17 @@ new_symbol (struct die_info *die, struct
struct pending **list_to_add;

list_to_add = (cu->list_in_scope == &file_symbols
- && cu->language == language_cplus
+ && (cu->language == language_cplus
+ || cu->language == language_java)
? &global_symbols : cu->list_in_scope);

add_symbol_to_list (sym, list_to_add);

- /* The semantics of C++ state that "struct foo { ... }" also
+ /* The semantics of C++ and Java state that "struct foo { ... }" also
defines a typedef for "foo". Synthesize a typedef symbol so
that "ptype foo" works as expected. */
- if (cu->language == language_cplus)
+ if (cu->language == language_cplus
+ || cu->language == language_java)
{
struct symbol *typedef_sym = (struct symbol *)
obstack_alloc (&objfile->objfile_obstack,
@@ -6415,7 +6471,8 @@ new_symbol (struct die_info *die, struct
{
SYMBOL_LINKAGE_NAME (sym) = obconcat (&objfile->objfile_obstack,
processing_current_prefix,
- "::",
+ cu->language == language_java
+ ? "." : "::",
name);
}
SYMBOL_CLASS (sym) = LOC_TYPEDEF;
@@ -6434,7 +6491,8 @@ new_symbol (struct die_info *die, struct
{
SYMBOL_LINKAGE_NAME (sym) = obconcat (&objfile->objfile_obstack,
processing_current_prefix,
- "::",
+ cu->language == language_java
+ ? "." : "::",
name);
}
attr = dwarf2_attr (die, DW_AT_const_value, cu);
@@ -6449,7 +6507,8 @@ new_symbol (struct die_info *die, struct
struct pending **list_to_add;

list_to_add = (cu->list_in_scope == &file_symbols
- && cu->language == language_cplus
+ && (cu->language == language_cplus
+ || cu->language == language_java)
? &global_symbols : cu->list_in_scope);

add_symbol_to_list (sym, list_to_add);
@@ -6758,7 +6817,8 @@ determine_prefix (struct die_info *die,
{
struct die_info *parent;

- if (cu->language != language_cplus)
+ if (cu->language != language_cplus
+ && cu->language != language_java)
return NULL;

parent = die->parent;
@@ -6784,7 +6844,8 @@ determine_prefix (struct die_info *die,
char *parent_prefix = determine_prefix (parent, cu);
char *retval = typename_concat (parent_prefix,
namespace_name (parent, &dummy,
- cu));
+ cu),
+ cu);
xfree (parent_prefix);
return retval;
}
@@ -6818,11 +6879,11 @@ determine_prefix (struct die_info *die,
}

/* Return a newly-allocated string formed by concatenating PREFIX,
- "::", and SUFFIX, except that if PREFIX is NULL or the empty
+ "::" or ".", and SUFFIX, except that if PREFIX is NULL or the empty
string, just return a copy of SUFFIX. */

static char *
-typename_concat (const char *prefix, const char *suffix)
+typename_concat (const char *prefix, const char *suffix, struct dwarf2_cu *cu)
{
if (prefix == NULL || prefix[0] == '\0')
return xstrdup (suffix);
@@ -6831,7 +6892,10 @@ typename_concat (const char *prefix, con
char *retval = xmalloc (strlen (prefix) + 2 + strlen (suffix) + 1);

strcpy (retval, prefix);
- strcat (retval, "::");
+ if (cu->language == language_java)
+ strcat (retval, ".");
+ else
+ strcat (retval, "::");
strcat (retval, suffix);

return retval;
Index: jv-exp.y
===================================================================
RCS file: /cvs/src/src/gdb/jv-exp.y,v
retrieving revision 1.18
diff -u -p -r1.18 jv-exp.y
--- jv-exp.y 23 Nov 2003 20:41:17 -0000 1.18
+++ jv-exp.y 6 Jul 2004 21:42:45 -0000
@@ -446,13 +446,22 @@ FieldAccess:
/*| SUPER '.' SimpleName { FIXME } */
;

+FuncStart:
+ Name '('
+ { push_expression_name ($1); }
+;
+
MethodInvocation:
- Name '(' ArgumentList_opt ')'
- { error (_("Method invocation not implemented")); }
+ FuncStart
+ { start_arglist(); }
+ ArgumentList_opt ')'
+ { write_exp_elt_opcode (OP_FUNCALL);
+ write_exp_elt_longcst ((LONGEST) end_arglist ());
+ write_exp_elt_opcode (OP_FUNCALL); }
| Primary '.' SimpleName '(' ArgumentList_opt ')'
- { error (_("Method invocation not implemented")); }
+ { error (_("Form of method invocation not implemented")); }
| SUPER '.' SimpleName '(' ArgumentList_opt ')'
- { error (_("Method invocation not implemented")); }
+ { error (_("Form of method invocation not implemented")); }
;

ArrayAccess:
Index: symtab.c
===================================================================
RCS file: /cvs/src/src/gdb/symtab.c,v
retrieving revision 1.129
diff -u -p -r1.129 symtab.c
--- symtab.c 8 Apr 2004 21:18:13 -0000 1.129
+++ symtab.c 6 Jul 2004 21:42:45 -0000
@@ -932,7 +932,7 @@ lookup_symbol (const char *name, const s

modified_name = name;

- /* If we are using C++ language, demangle the name before doing a lookup, so
+ /* If we are using C++ or Java, demangle the name before doing a lookup, so
we can always binary search. */
if (current_language->la_language == language_cplus)
{
@@ -944,6 +944,17 @@ lookup_symbol (const char *name, const s
needtofreename = 1;
}
}
+ else if (current_language->la_language == language_java)
+ {
+ demangled_name = cplus_demangle (name,
+ DMGL_ANSI | DMGL_PARAMS | DMGL_JAVA);
+ if (demangled_name)
+ {
+ mangled_name = name;
+ modified_name = demangled_name;
+ needtofreename = 1;
+ }
+ }

if (case_sensitivity == case_sensitive_off)
{
Index: valarith.c
===================================================================
RCS file: /cvs/src/src/gdb/valarith.c,v
retrieving revision 1.22
diff -u -p -r1.22 valarith.c
--- valarith.c 1 Apr 2004 12:08:30 -0000 1.22
+++ valarith.c 6 Jul 2004 21:42:49 -0000
@@ -202,7 +202,10 @@ value_subscript (struct value *array, st
LONGEST index = value_as_long (idx);
if (index >= lowerbound && index <= upperbound)
return value_subscripted_rvalue (array, idx, lowerbound);
- warning ("array or string index out of range");
+ /* Emit warning unless we have an array of unknown size.
+ An array of unknown size has lowerbound 0 and upperbound -1. */
+ if (upperbound > -1)
+ warning ("array or string index out of range");
/* fall doing C stuff */
c_style = 1;
}