Commit 48711f4d by Tom Tromey Committed by Tom Tromey

Fix for PR java/1343, PR java/6336:

	* parse.y (make_nested_class_name): Remove extraneous `else'; fix
	formatting.  Changed return type.
	(anonymous_class_counter): Moved to top of file.
	(maybe_make_nested_class_name): Append number to class name for
	function-local classes.

From-SVN: r54173
parent e403d80d
2002-06-02 Tom Tromey <tromey@redhat.com>
Fix for PR java/1343, PR java/6336:
* parse.y (make_nested_class_name): Remove extraneous `else'; fix
formatting. Changed return type.
(anonymous_class_counter): Moved to top of file.
(maybe_make_nested_class_name): Append number to class name for
function-local classes.
2002-05-28 Zack Weinberg <zack@codesourcery.com> 2002-05-28 Zack Weinberg <zack@codesourcery.com>
* decl.c, jcf-parse.c, parse.y, typeck.c: Include real.h. * decl.c, jcf-parse.c, parse.y, typeck.c: Include real.h.
......
/* Parser grammar for quick source code scan of Java(TM) language programs. /* Parser grammar for quick source code scan of Java(TM) language programs.
Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc. Copyright (C) 1998, 1999, 2000, 2002 Free Software Foundation, Inc.
Contributed by Alexandre Petit-Bianco (apbianco@cygnus.com) Contributed by Alexandre Petit-Bianco (apbianco@cygnus.com)
This file is part of GNU CC. This file is part of GNU CC.
...@@ -43,6 +43,9 @@ definitions and other extensions. */ ...@@ -43,6 +43,9 @@ definitions and other extensions. */
#include "obstack.h" #include "obstack.h"
#include "toplev.h" #include "toplev.h"
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
extern char *input_filename; extern char *input_filename;
extern FILE *finput, *out; extern FILE *finput, *out;
...@@ -62,13 +65,9 @@ int lineno; ...@@ -62,13 +65,9 @@ int lineno;
static int absorber; static int absorber;
#define USE_ABSORBER absorber = 0 #define USE_ABSORBER absorber = 0
/* Keep track of the current class name and package name. */ /* Keep track of the current package name. */
static char *current_class;
static const char *package_name; static const char *package_name;
/* Keep track of the current inner class qualifier. */
static int current_class_length;
/* Keep track of whether things have be listed before. */ /* Keep track of whether things have be listed before. */
static int previous_output; static int previous_output;
...@@ -85,6 +84,22 @@ static int bracket_count; ...@@ -85,6 +84,22 @@ static int bracket_count;
/* Numbers anonymous classes */ /* Numbers anonymous classes */
static int anonymous_count; static int anonymous_count;
/* This is used to record the current class context. */
struct class_context
{
char *name;
struct class_context *next;
};
/* The global class context. */
static struct class_context *current_class_context;
/* A special constant used to represent an anonymous context. */
static const char *anonymous_context = "ANONYMOUS";
/* Count of method depth. */
static int method_depth;
/* Record a method declaration */ /* Record a method declaration */
struct method_declarator { struct method_declarator {
const char *method_name; const char *method_name;
...@@ -99,6 +114,9 @@ struct method_declarator { ...@@ -99,6 +114,9 @@ struct method_declarator {
} }
/* Two actions for this grammar */ /* Two actions for this grammar */
static int make_class_name_recursive PARAMS ((struct obstack *stack,
struct class_context *ctx));
static char *get_class_name PARAMS ((void));
static void report_class_declaration PARAMS ((const char *)); static void report_class_declaration PARAMS ((const char *));
static void report_main_declaration PARAMS ((struct method_declarator *)); static void report_main_declaration PARAMS ((struct method_declarator *));
static void push_class_context PARAMS ((const char *)); static void push_class_context PARAMS ((const char *));
...@@ -430,7 +448,10 @@ variable_initializer: ...@@ -430,7 +448,10 @@ variable_initializer:
/* 19.8.3 Productions from 8.4: Method Declarations */ /* 19.8.3 Productions from 8.4: Method Declarations */
method_declaration: method_declaration:
method_header method_body method_header
{ ++method_depth; }
method_body
{ --method_depth; }
; ;
method_header: method_header:
...@@ -923,10 +944,10 @@ class_instance_creation_expression: ...@@ -923,10 +944,10 @@ class_instance_creation_expression:
anonymous_class_creation: anonymous_class_creation:
NEW_TK class_type OP_TK CP_TK NEW_TK class_type OP_TK CP_TK
{ report_class_declaration (NULL); } { report_class_declaration (anonymous_context); }
class_body class_body
| NEW_TK class_type OP_TK argument_list CP_TK | NEW_TK class_type OP_TK argument_list CP_TK
{ report_class_declaration (NULL); } { report_class_declaration (anonymous_context); }
class_body class_body
; ;
...@@ -1155,58 +1176,100 @@ static void ...@@ -1155,58 +1176,100 @@ static void
push_class_context (name) push_class_context (name)
const char *name; const char *name;
{ {
/* If we already have CURRENT_CLASS set, we're in an inter struct class_context *ctx;
class. Mangle its name. */
if (current_class) ctx = (struct class_context *) xmalloc (sizeof (struct class_context));
{ ctx->name = (char *) name;
const char *p; ctx->next = current_class_context;
char anonymous [3]; current_class_context = ctx;
int additional_length;
/* NAME set to NULL indicates an anonymous class, which are named by
numbering them. */
if (!name)
{
sprintf (anonymous, "%d", ++anonymous_count);
p = anonymous;
}
else
p = name;
additional_length = strlen (p)+1; /* +1 for `$' */
current_class = xrealloc (current_class,
current_class_length + additional_length + 1);
current_class [current_class_length] = '$';
strcpy (&current_class [current_class_length+1], p);
current_class_length += additional_length;
}
else
{
if (!name)
return;
current_class_length = strlen (name);
current_class = xmalloc (current_class_length+1);
strcpy (current_class, name);
}
} }
static void static void
pop_class_context () pop_class_context ()
{ {
/* Go back to the last `$' and cut. */ struct class_context *ctx;
while (--current_class_length > 0
&& current_class [current_class_length] != '$') if (current_class_context == NULL)
; return;
if (current_class_length)
ctx = current_class_context->next;
if (current_class_context->name != anonymous_context)
free (current_class_context->name);
free (current_class_context);
current_class_context = ctx;
if (current_class_context == NULL)
anonymous_count = 0;
}
/* Recursively construct the class name. This is just a helper
function for get_class_name(). */
static int
make_class_name_recursive (stack, ctx)
struct obstack *stack;
struct class_context *ctx;
{
if (! ctx)
return 0;
make_class_name_recursive (stack, ctx->next);
/* Replace an anonymous context with the appropriate counter value. */
if (ctx->name == anonymous_context)
{ {
current_class = xrealloc (current_class, current_class_length+1); char buf[50];
current_class [current_class_length] = '\0'; ++anonymous_count;
sprintf (buf, "%d", anonymous_count);
ctx->name = xstrdup (buf);
} }
else
obstack_grow (stack, ctx->name, strlen (ctx->name));
obstack_1grow (stack, '$');
return ISDIGIT (ctx->name[0]);
}
/* Return a newly allocated string holding the name of the class. */
static char *
get_class_name ()
{
char *result;
int last_was_digit;
struct obstack name_stack;
obstack_init (&name_stack);
/* Duplicate the logic of parse.y:maybe_make_nested_class_name(). */
last_was_digit = make_class_name_recursive (&name_stack,
current_class_context->next);
if (! last_was_digit
&& method_depth
&& current_class_context->name != anonymous_context)
{ {
current_class = NULL; char buf[50];
anonymous_count = 0; ++anonymous_count;
sprintf (buf, "%d", anonymous_count);
obstack_grow (&name_stack, buf, strlen (buf));
obstack_1grow (&name_stack, '$');
} }
if (current_class_context->name == anonymous_context)
{
char buf[50];
++anonymous_count;
sprintf (buf, "%d", anonymous_count);
current_class_context->name = xstrdup (buf);
obstack_grow0 (&name_stack, buf, strlen (buf));
}
else
obstack_grow0 (&name_stack, current_class_context->name,
strlen (current_class_context->name));
result = xstrdup (obstack_finish (&name_stack));
obstack_free (&name_stack, NULL);
return result;
} }
/* Actions defined here */ /* Actions defined here */
...@@ -1220,17 +1283,21 @@ report_class_declaration (name) ...@@ -1220,17 +1283,21 @@ report_class_declaration (name)
push_class_context (name); push_class_context (name);
if (flag_dump_class) if (flag_dump_class)
{ {
char *name = get_class_name ();
if (!previous_output) if (!previous_output)
{ {
if (flag_list_filename) if (flag_list_filename)
fprintf (out, "%s: ", input_filename); fprintf (out, "%s: ", input_filename);
previous_output = 1; previous_output = 1;
} }
if (package_name) if (package_name)
fprintf (out, "%s.%s ", package_name, current_class); fprintf (out, "%s.%s ", package_name, name);
else else
fprintf (out, "%s ", current_class); fprintf (out, "%s ", name);
free (name);
} }
} }
...@@ -1247,14 +1314,16 @@ report_main_declaration (declarator) ...@@ -1247,14 +1314,16 @@ report_main_declaration (declarator)
&& declarator->args [0] == '[' && declarator->args [0] == '['
&& (! strcmp (declarator->args+1, "String") && (! strcmp (declarator->args+1, "String")
|| ! strcmp (declarator->args + 1, "java.lang.String")) || ! strcmp (declarator->args + 1, "java.lang.String"))
&& current_class) && current_class_context)
{ {
if (!previous_output) if (!previous_output)
{ {
char *name = get_class_name ();
if (package_name) if (package_name)
fprintf (out, "%s.%s ", package_name, current_class); fprintf (out, "%s.%s ", package_name, name);
else else
fprintf (out, "%s", current_class); fprintf (out, "%s", name);
free (name);
previous_output = 1; previous_output = 1;
} }
} }
...@@ -1274,7 +1343,7 @@ void reset_report () ...@@ -1274,7 +1343,7 @@ void reset_report ()
{ {
previous_output = 0; previous_output = 0;
package_name = NULL; package_name = NULL;
current_class = NULL; current_class_context = NULL;
complexity = 0; complexity = 0;
} }
......
...@@ -295,7 +295,7 @@ static int pop_current_osb PARAMS ((struct parser_ctxt *)); ...@@ -295,7 +295,7 @@ static int pop_current_osb PARAMS ((struct parser_ctxt *));
/* JDK 1.1 work. FIXME */ /* JDK 1.1 work. FIXME */
static tree maybe_make_nested_class_name PARAMS ((tree)); static tree maybe_make_nested_class_name PARAMS ((tree));
static void make_nested_class_name PARAMS ((tree)); static int make_nested_class_name PARAMS ((tree));
static void set_nested_class_simple_name_value PARAMS ((tree, int)); static void set_nested_class_simple_name_value PARAMS ((tree, int));
static void link_nested_class_to_enclosing PARAMS ((void)); static void link_nested_class_to_enclosing PARAMS ((void));
static tree resolve_inner_class PARAMS ((struct hash_table *, tree, tree *, static tree resolve_inner_class PARAMS ((struct hash_table *, tree, tree *,
...@@ -423,6 +423,10 @@ static tree currently_caught_type_list; ...@@ -423,6 +423,10 @@ static tree currently_caught_type_list;
`ctxp->current_loop'. */ `ctxp->current_loop'. */
static tree case_label_list; static tree case_label_list;
/* Anonymous class counter. Will be reset to 1 every time a non
anonymous class gets created. */
static int anonymous_class_counter = 1;
static tree src_parse_roots[1]; static tree src_parse_roots[1];
/* All classes seen from source code */ /* All classes seen from source code */
...@@ -3497,24 +3501,28 @@ check_class_interface_creation (is_interface, flags, raw_name, qualified_name, d ...@@ -3497,24 +3501,28 @@ check_class_interface_creation (is_interface, flags, raw_name, qualified_name, d
return 0; return 0;
} }
static void /* Construct a nested class name. If the final component starts with
a digit, return true. Otherwise return false. */
static int
make_nested_class_name (cpc_list) make_nested_class_name (cpc_list)
tree cpc_list; tree cpc_list;
{ {
tree name; tree name;
if (!cpc_list) if (!cpc_list)
return; return 0;
else
make_nested_class_name (TREE_CHAIN (cpc_list)); make_nested_class_name (TREE_CHAIN (cpc_list));
/* Pick the qualified name when dealing with the first upmost /* Pick the qualified name when dealing with the first upmost
enclosing class */ enclosing class */
name = (TREE_CHAIN (cpc_list) ? name = (TREE_CHAIN (cpc_list)
TREE_PURPOSE (cpc_list) : DECL_NAME (TREE_VALUE (cpc_list))); ? TREE_PURPOSE (cpc_list) : DECL_NAME (TREE_VALUE (cpc_list)));
obstack_grow (&temporary_obstack, obstack_grow (&temporary_obstack,
IDENTIFIER_POINTER (name), IDENTIFIER_LENGTH (name)); IDENTIFIER_POINTER (name), IDENTIFIER_LENGTH (name));
obstack_1grow (&temporary_obstack, '$'); obstack_1grow (&temporary_obstack, '$');
return ISDIGIT (IDENTIFIER_POINTER (name)[0]);
} }
/* Can't redefine a class already defined in an earlier scope. */ /* Can't redefine a class already defined in an earlier scope. */
...@@ -3723,7 +3731,20 @@ maybe_make_nested_class_name (name) ...@@ -3723,7 +3731,20 @@ maybe_make_nested_class_name (name)
if (CPC_INNER_P ()) if (CPC_INNER_P ())
{ {
make_nested_class_name (GET_CPC_LIST ()); /* If we're in a function, we must append a number to create the
nested class name. However, we don't do this if the class we
are constructing is anonymous, because in that case we'll
already have a number as the class name. */
if (! make_nested_class_name (GET_CPC_LIST ())
&& current_function_decl != NULL_TREE
&& ! ISDIGIT (IDENTIFIER_POINTER (name)[0]))
{
char buf[10];
sprintf (buf, "%d", anonymous_class_counter);
++anonymous_class_counter;
obstack_grow (&temporary_obstack, buf, strlen (buf));
obstack_1grow (&temporary_obstack, '$');
}
obstack_grow0 (&temporary_obstack, obstack_grow0 (&temporary_obstack,
IDENTIFIER_POINTER (name), IDENTIFIER_POINTER (name),
IDENTIFIER_LENGTH (name)); IDENTIFIER_LENGTH (name));
...@@ -3863,10 +3884,6 @@ create_interface (flags, id, super) ...@@ -3863,10 +3884,6 @@ create_interface (flags, id, super)
return decl; return decl;
} }
/* Anonymous class counter. Will be reset to 1 every time a non
anonymous class gets created. */
static int anonymous_class_counter = 1;
/* Patch anonymous class CLASS, by either extending or implementing /* Patch anonymous class CLASS, by either extending or implementing
DEP. */ DEP. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment