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>
* decl.c, jcf-parse.c, parse.y, typeck.c: Include real.h.
......
/* 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)
This file is part of GNU CC.
......@@ -43,6 +43,9 @@ definitions and other extensions. */
#include "obstack.h"
#include "toplev.h"
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
extern char *input_filename;
extern FILE *finput, *out;
......@@ -62,13 +65,9 @@ int lineno;
static int absorber;
#define USE_ABSORBER absorber = 0
/* Keep track of the current class name and package name. */
static char *current_class;
/* Keep track of the current 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. */
static int previous_output;
......@@ -85,6 +84,22 @@ static int bracket_count;
/* Numbers anonymous classes */
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 */
struct method_declarator {
const char *method_name;
......@@ -99,6 +114,9 @@ struct method_declarator {
}
/* 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_main_declaration PARAMS ((struct method_declarator *));
static void push_class_context PARAMS ((const char *));
......@@ -430,7 +448,10 @@ variable_initializer:
/* 19.8.3 Productions from 8.4: Method Declarations */
method_declaration:
method_header method_body
method_header
{ ++method_depth; }
method_body
{ --method_depth; }
;
method_header:
......@@ -923,10 +944,10 @@ class_instance_creation_expression:
anonymous_class_creation:
NEW_TK class_type OP_TK CP_TK
{ report_class_declaration (NULL); }
{ report_class_declaration (anonymous_context); }
class_body
| NEW_TK class_type OP_TK argument_list CP_TK
{ report_class_declaration (NULL); }
{ report_class_declaration (anonymous_context); }
class_body
;
......@@ -1155,58 +1176,100 @@ static void
push_class_context (name)
const char *name;
{
/* If we already have CURRENT_CLASS set, we're in an inter
class. Mangle its name. */
if (current_class)
{
const char *p;
char anonymous [3];
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);
}
struct class_context *ctx;
ctx = (struct class_context *) xmalloc (sizeof (struct class_context));
ctx->name = (char *) name;
ctx->next = current_class_context;
current_class_context = ctx;
}
static void
pop_class_context ()
{
/* Go back to the last `$' and cut. */
while (--current_class_length > 0
&& current_class [current_class_length] != '$')
;
if (current_class_length)
struct class_context *ctx;
if (current_class_context == NULL)
return;
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);
current_class [current_class_length] = '\0';
char buf[50];
++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;
anonymous_count = 0;
char buf[50];
++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 */
......@@ -1220,17 +1283,21 @@ report_class_declaration (name)
push_class_context (name);
if (flag_dump_class)
{
char *name = get_class_name ();
if (!previous_output)
{
if (flag_list_filename)
fprintf (out, "%s: ", input_filename);
previous_output = 1;
}
if (package_name)
fprintf (out, "%s.%s ", package_name, current_class);
fprintf (out, "%s.%s ", package_name, name);
else
fprintf (out, "%s ", current_class);
fprintf (out, "%s ", name);
free (name);
}
}
......@@ -1247,14 +1314,16 @@ report_main_declaration (declarator)
&& declarator->args [0] == '['
&& (! strcmp (declarator->args+1, "String")
|| ! strcmp (declarator->args + 1, "java.lang.String"))
&& current_class)
&& current_class_context)
{
if (!previous_output)
{
char *name = get_class_name ();
if (package_name)
fprintf (out, "%s.%s ", package_name, current_class);
fprintf (out, "%s.%s ", package_name, name);
else
fprintf (out, "%s", current_class);
fprintf (out, "%s", name);
free (name);
previous_output = 1;
}
}
......@@ -1274,7 +1343,7 @@ void reset_report ()
{
previous_output = 0;
package_name = NULL;
current_class = NULL;
current_class_context = NULL;
complexity = 0;
}
......
......@@ -295,7 +295,7 @@ static int pop_current_osb PARAMS ((struct parser_ctxt *));
/* JDK 1.1 work. FIXME */
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 link_nested_class_to_enclosing PARAMS ((void));
static tree resolve_inner_class PARAMS ((struct hash_table *, tree, tree *,
......@@ -423,6 +423,10 @@ static tree currently_caught_type_list;
`ctxp->current_loop'. */
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];
/* All classes seen from source code */
......@@ -3497,24 +3501,28 @@ check_class_interface_creation (is_interface, flags, raw_name, qualified_name, d
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)
tree cpc_list;
{
tree name;
if (!cpc_list)
return;
else
make_nested_class_name (TREE_CHAIN (cpc_list));
return 0;
make_nested_class_name (TREE_CHAIN (cpc_list));
/* Pick the qualified name when dealing with the first upmost
enclosing class */
name = (TREE_CHAIN (cpc_list) ?
TREE_PURPOSE (cpc_list) : DECL_NAME (TREE_VALUE (cpc_list)));
name = (TREE_CHAIN (cpc_list)
? TREE_PURPOSE (cpc_list) : DECL_NAME (TREE_VALUE (cpc_list)));
obstack_grow (&temporary_obstack,
IDENTIFIER_POINTER (name), IDENTIFIER_LENGTH (name));
obstack_1grow (&temporary_obstack, '$');
return ISDIGIT (IDENTIFIER_POINTER (name)[0]);
}
/* Can't redefine a class already defined in an earlier scope. */
......@@ -3723,7 +3731,20 @@ maybe_make_nested_class_name (name)
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,
IDENTIFIER_POINTER (name),
IDENTIFIER_LENGTH (name));
......@@ -3863,10 +3884,6 @@ create_interface (flags, id, super)
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
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