Patch: 1.4 assert facility

Tom Tromey tromey@redhat.com
Sun Apr 7 14:32:00 GMT 2002


When I was out of town I had some hacking time that I couldn't
productively use for the 3.1 release.  So I spent it hacking on things
more useful for the trunk.

This patch adds support for the JDK 1.4 `assert' keyword.  It also
adds most of the runtime support; all that is missing is wiring it
into the gij argument processing.  I haven't written that yet but I'll
do it eventually.

Tested on Debian Linux.  I rebuilt libgcj with this.  I also built a
couple small programs that use assert to make sure that the correct
code is generated.

The JDK javac compiler has support for "old-style" compilation, where
assert is not considered a keyword.  I didn't see this as critical, so
I didn't implement it.  If this is important I think it could be done
relatively simply in the lexer (I'd also need to add an additional
command-line option).  If you (meaning any Java-head) think we need
this, let me know.

Ok for the trunk?

Tom

Index: gcc/java/ChangeLog
from  Tom Tromey  <tromey@redhat.com>

	* jcf-write.c (generate_classfile): Use FIELD_SYNTHETIC.
	* parse-scan.y (statement_without_trailing_substatement): Added
	assert_statement.
	(assert_statement): New rule.
	* java-tree.h (struct lang_type) [assertions]: New field.
	(TYPE_USES_ASSERTIONS): New macro.
	(CLASS_USES_ASSERTIONS): Likewise.
	(FIELD_SYNTHETIC): New define.
	* lex.c (java_lval;): Added ASSERT_TK.
	* parse.y (ASSERT_TK): Added.
	(statement_without_trailing_substatement): Added assert_statement.
	(assert_statement): New rule.
	(build_assertion): New function.
	(maybe_generate_pre_expand_clinit): Create and initialize
	$assertionsDisabled.
	(lookup_package_type): Removed decl.
	* keyword.h: Rebuilt.
	* keyword.gperf (assert): New token.

Index: gcc/java/java-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/java-tree.h,v
retrieving revision 1.136.2.1
diff -u -r1.136.2.1 java-tree.h
--- gcc/java/java-tree.h 2002/02/28 11:42:10 1.136.2.1
+++ gcc/java/java-tree.h 2002/04/05 15:53:06
@@ -91,6 +91,7 @@
       CLASS_PUBLIC (in TYPE_DECL).
    2: METHOD_STATIC (in FUNCTION_DECL).
       (But note that FIELD_STATIC uses TREE_STATIC!)
+      FIELD_SYNTHETIC (in FIELD_DECL)
       CLASS_COMPLETE_P (in TYPE_DECL)
    3: METHOD_FINAL (in FUNCTION_DECL)
       FIELD_FINAL (in FIELD_DECL)
@@ -796,6 +797,9 @@
 /* A constructor that calls this. */
 #define DECL_INIT_CALLS_THIS(DECL) (DECL_LANG_SPECIFIC(DECL)->init_calls_this)
 
+/* True when DECL (a field) is Synthetic.  */
+#define FIELD_SYNTHETIC(DECL) DECL_LANG_FLAG_2 (DECL)
+
 /* True when DECL aliases an outer context local variable.  */
 #define FIELD_LOCAL_ALIAS(DECL) DECL_LANG_FLAG_6 (DECL)
 
@@ -995,6 +999,7 @@
 #define TYPE_PRIVATE_INNER_CLASS(T) (TYPE_LANG_SPECIFIC(T)->pic)
 #define TYPE_PROTECTED_INNER_CLASS(T) (TYPE_LANG_SPECIFIC(T)->poic)
 #define TYPE_STRICTFP(T) (TYPE_LANG_SPECIFIC(T)->strictfp)
+#define TYPE_USES_ASSERTIONS(T) (TYPE_LANG_SPECIFIC(T)->assertions)
 
 struct lang_type
 {
@@ -1015,6 +1020,7 @@
   unsigned pic:1;		/* Private Inner Class. */
   unsigned poic:1;		/* Protected Inner Class. */
   unsigned strictfp:1;		/* `strictfp' class.  */
+  unsigned assertions:1;	/* Any method uses `assert'.  */
 };
 
 #ifdef JAVA_USE_HANDLES
@@ -1300,6 +1306,7 @@
 #define CLASS_PRIVATE(DECL) (TYPE_PRIVATE_INNER_CLASS (TREE_TYPE (DECL)))
 #define CLASS_PROTECTED(DECL) (TYPE_PROTECTED_INNER_CLASS (TREE_TYPE (DECL)))
 #define CLASS_STRICTFP(DECL) (TYPE_STRICTFP (TREE_TYPE (DECL)))
+#define CLASS_USES_ASSERTIONS(DECL) (TYPE_USES_ASSERTIONS (TREE_TYPE (DECL)))
 
 /* @deprecated marker flag on methods, fields and classes */
 
Index: gcc/java/jcf-write.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/jcf-write.c,v
retrieving revision 1.99.2.1
diff -u -r1.99.2.1 jcf-write.c
--- gcc/java/jcf-write.c 2002/03/12 10:33:57 1.99.2.1
+++ gcc/java/jcf-write.c 2002/04/05 15:53:06
@@ -2925,7 +2925,7 @@
       if (have_value)
 	attr_count++;
 
-      if (FIELD_THISN (part) || FIELD_LOCAL_ALIAS (part))
+      if (FIELD_THISN (part) || FIELD_LOCAL_ALIAS (part) || FIELD_SYNTHETIC (part))
 	attr_count++;
 
       PUT2 (attr_count);  /* attributes_count */
@@ -2943,8 +2943,10 @@
 	  PUT4 (2); /* attribute_length */
 	  i = find_constant_index (init, state);  PUT2 (i);
 	}
-      /* Emit the "Synthetic" attribute for val$<x> and this$<n> fields. */
-      if (FIELD_THISN (part) || FIELD_LOCAL_ALIAS (part))
+      /* Emit the "Synthetic" attribute for val$<x> and this$<n>
+	 fields and other fields which need it.  */
+      if (FIELD_THISN (part) || FIELD_LOCAL_ALIAS (part)
+	  || FIELD_SYNTHETIC (part))
 	ptr = append_synthetic_attribute (state);
       fields_count++;
     }
Index: gcc/java/keyword.gperf
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/keyword.gperf,v
retrieving revision 1.7
diff -u -r1.7 keyword.gperf
--- gcc/java/keyword.gperf 2001/12/23 16:07:13 1.7
+++ gcc/java/keyword.gperf 2002/04/05 15:53:06
@@ -87,3 +87,4 @@
 true, TRUE_TK
 false, FALSE_TK
 null, NULL_TK
+assert, ASSERT_TK
Index: gcc/java/keyword.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/keyword.h,v
retrieving revision 1.8
diff -u -r1.8 keyword.h
--- gcc/java/keyword.h 2001/12/23 16:07:13 1.8
+++ gcc/java/keyword.h 2002/04/05 15:53:06
@@ -1,5 +1,5 @@
-/* C code produced by gperf version 2.7.2 */
-/* Command-line: gperf -L C -C -F ', 0' -p -t -j1 -i 1 -g -o -N java_keyword -k'1,4,$' keyword.gperf  */
+/* C code produced by gperf version 2.7 */
+/* Command-line: gperf -L C -C -F , 0 -p -t -j1 -i 1 -g -o -N java_keyword -k1,4,$ keyword.gperf  */
 /* Keyword definition for the GNU compiler for the Java(TM) language.
    Copyright (C) 1997, 1998 Free Software Foundation, Inc.
    Contributed by Alexandre Petit-Bianco (apbianco@cygnus.com)
@@ -35,20 +35,16 @@
 #endif
 const struct java_keyword *java_keyword	PARAMS ((const char *, unsigned int));
 
-#define TOTAL_KEYWORDS 51
+#define TOTAL_KEYWORDS 52
 #define MIN_WORD_LENGTH 2
 #define MAX_WORD_LENGTH 12
 #define MIN_HASH_VALUE 7
-#define MAX_HASH_VALUE 95
-/* maximum key range = 89, duplicates = 0 */
+#define MAX_HASH_VALUE 85
+/* maximum key range = 79, duplicates = 0 */
 
 #ifdef __GNUC__
 __inline
-#else
-#ifdef __cplusplus
-inline
 #endif
-#endif
 static unsigned int
 hash (str, len)
      register const char *str;
@@ -56,32 +52,32 @@
 {
   static const unsigned char asso_values[] =
     {
-      96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-      96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-      96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-      96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-      96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-      96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-      96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-      96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-      96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-      96, 96, 96, 96, 96, 96, 96,  9, 17,  3,
-       1,  1, 20, 13, 15, 29, 96, 21,  1, 96,
-      35, 39,  1, 96, 15,  6,  2,  1, 41, 17,
-      96,  7, 96, 96, 96, 96, 96, 96, 96, 96,
-      96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-      96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-      96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-      96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-      96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-      96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-      96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-      96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-      96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-      96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-      96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-      96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-      96, 96, 96, 96, 96, 96
+      86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+      86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+      86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+      86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+      86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+      86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+      86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+      86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+      86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+      86, 86, 86, 86, 86, 86, 86,  1, 34,  3,
+       1,  1, 18,  7, 21, 28, 86, 14,  1, 86,
+      18, 20, 37, 86, 15,  6,  2,  5, 40, 36,
+      86, 36, 86, 86, 86, 86, 86, 86, 86, 86,
+      86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+      86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+      86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+      86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+      86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+      86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+      86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+      86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+      86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+      86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+      86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+      86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+      86, 86, 86, 86, 86, 86
     };
   register int hval = len;
 
@@ -109,74 +105,69 @@
 {
   static const struct java_keyword wordlist[] =
     {
-      {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
-      {"", 0},
+      {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
       {"else", ELSE_TK},
       {"true", TRUE_TK},
       {"case", CASE_TK},
+      {"assert", ASSERT_TK},
+      {"default", DEFAULT_TK},
       {"", 0},
-      {"public", PUBLIC_TK},
-      {"try", TRY_TK},
-      {"protected", PROTECTED_TK},
+      {"abstract", ABSTRACT_TK},
       {"continue", CONTINUE_TK},
       {"extends", EXTENDS_TK},
       {"const", CONST_TK},
       {"static", STATIC_TK},
       {"this", THIS_TK},
-      {"default", DEFAULT_TK},
+      {"long", LONG_TK},
       {"class", CLASS_TK},
-      {"abstract", ABSTRACT_TK},
+      {"", 0},
       {"synchronized", SYNCHRONIZED_TK},
-      {"byte", BYTE_TK},
-      {"while", WHILE_TK},
-      {"double", DOUBLE_TK},
-      {"catch", CATCH_TK},
+      {"do", DO_TK},
+      {"null", NULL_TK},
+      {"final", FINAL_TK},
+      {"float", FLOAT_TK},
       {"super", SUPER_TK},
       {"short", SHORT_TK},
-      {"switch", SWITCH_TK},
-      {"package", PACKAGE_TK},
-      {"long", LONG_TK},
-      {"false", FALSE_TK},
       {"", 0},
+      {"false", FALSE_TK},
+      {"transient", TRANSIENT_TK},
+      {"catch", CATCH_TK},
       {"int", INT_TK},
-      {"final", FINAL_TK},
-      {"float", FLOAT_TK},
-      {"char", CHAR_TK},
+      {"throws", THROWS_TK},
+      {"switch", SWITCH_TK},
       {"for", FOR_TK},
+      {"char", CHAR_TK},
       {"", 0},
       {"interface", INTERFACE_TK},
-      {"null", NULL_TK},
-      {"do", DO_TK},
-      {"finally", FINALLY_TK},
-      {"strictfp", STRICT_TK},
-      {"", 0},
+      {"byte", BYTE_TK},
+      {"try", TRY_TK},
+      {"double", DOUBLE_TK},
+      {"while", WHILE_TK},
+      {"return", RETURN_TK},
       {"implements", IMPLEMENTS_TK},
       {"void", VOID_TK},
-      {"transient", TRANSIENT_TK},
-      {"", 0},
-      {"private", PRIVATE_TK},
+      {"public", PUBLIC_TK},
       {"if", IF_TK},
+      {"protected", PROTECTED_TK},
+      {"volatile", VOLATILE_TK},
+      {"goto", GOTO_TK},
+      {"", 0},
+      {"native", NATIVE_TK},
       {"break", BREAK_TK},
-      {"throws", THROWS_TK},
       {"", 0},
+      {"import", IMPORT_TK},
       {"new", NEW_TK},
-      {"", 0},
-      {"return", RETURN_TK},
-      {"", 0},
-      {"volatile", VOLATILE_TK},
-      {"boolean", BOOLEAN_TK},
       {"instanceof", INSTANCEOF_TK},
+      {"package", PACKAGE_TK},
+      {"boolean", BOOLEAN_TK},
       {"", 0},
+      {"finally", FINALLY_TK},
       {"throw", THROW_TK},
-      {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
-      {"", 0},
-      {"native", NATIVE_TK},
-      {"", 0}, {"", 0}, {"", 0}, {"", 0},
-      {"import", IMPORT_TK},
-      {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
+      {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
       {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
-      {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
-      {"goto", GOTO_TK}
+      {"strictfp", STRICT_TK},
+      {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
+      {"private", PRIVATE_TK}
     };
 
   if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
Index: gcc/java/lex.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/lex.c,v
retrieving revision 1.80.8.4
diff -u -r1.80.8.4 lex.c
--- gcc/java/lex.c 2002/03/29 19:31:09 1.80.8.4
+++ gcc/java/lex.c 2002/04/05 15:53:07
@@ -1635,6 +1635,7 @@
 	    case CATCH_TK:
 	    case THROW_TK:
 	    case INSTANCEOF_TK:
+	    case ASSERT_TK:
 	      BUILD_OPERATOR (kw->token);
 
 	    default:
Index: gcc/java/parse-scan.y
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/parse-scan.y,v
retrieving revision 1.21
diff -u -r1.21 parse-scan.y
--- gcc/java/parse-scan.y 2001/04/04 17:56:25 1.21
+++ gcc/java/parse-scan.y 2002/04/05 15:53:07
@@ -1,5 +1,5 @@
 /* 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.
@@ -162,6 +162,7 @@
 %token   SWITCH_TK       CONST_TK           TRY_TK
 %token   FOR_TK          NEW_TK             CONTINUE_TK
 %token   GOTO_TK         PACKAGE_TK         THIS_TK
+%token   ASSERT_TK
 
 %token   BYTE_TK         SHORT_TK           INT_TK            LONG_TK
 %token   CHAR_TK         INTEGRAL_TK
@@ -696,6 +697,7 @@
 |	synchronized_statement
 |	throw_statement
 |	try_statement
+|	assert_statement
 ;
 
 empty_statement:
@@ -849,6 +851,14 @@
 	THROW_TK expression SC_TK { ++complexity; }
 ;
 
+assert_statement:
+	ASSERT_TK expression REL_CL_TK expression SC_TK
+|	ASSERT_TK expression SC_TK
+|	ASSERT_TK error
+		{yyerror ("Missing term"); RECOVER;}
+|	ASSERT_TK expression error
+		{yyerror ("';' expected"); RECOVER;}
+;
 synchronized_statement:
 	synchronized OP_TK expression CP_TK block
 |	synchronized OP_TK expression CP_TK error
Index: gcc/java/parse.y
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/parse.y,v
retrieving revision 1.353.2.15
diff -u -r1.353.2.15 parse.y
--- gcc/java/parse.y 2002/03/29 22:29:52 1.353.2.15
+++ gcc/java/parse.y 2002/04/05 15:53:08
@@ -105,7 +105,6 @@
 static int check_pkg_class_access PARAMS ((tree, tree, bool));
 static void register_package PARAMS ((tree));
 static tree resolve_package PARAMS ((tree, tree *, tree *));
-static tree lookup_package_type PARAMS ((const char *, int));
 static tree resolve_class PARAMS ((tree, tree, tree, tree));
 static void declare_local_variables PARAMS ((int, tree, tree));
 static void dump_java_tree PARAMS ((enum tree_dump_index, tree));
@@ -219,6 +218,7 @@
 static tree patch_string_cst PARAMS ((tree));
 static tree patch_string PARAMS ((tree));
 static tree encapsulate_with_try_catch PARAMS ((int, tree, tree, tree));
+static tree build_assertion PARAMS ((int, tree, tree));
 static tree build_try_statement PARAMS ((int, tree, tree));
 static tree build_try_finally_statement PARAMS ((int, tree, tree));
 static tree patch_try_statement PARAMS ((tree));
@@ -500,6 +500,7 @@
 %token   SWITCH_TK       CONST_TK           TRY_TK
 %token   FOR_TK          NEW_TK             CONTINUE_TK
 %token   GOTO_TK         PACKAGE_TK         THIS_TK
+%token   ASSERT_TK
 
 %token   BYTE_TK         SHORT_TK           INT_TK            LONG_TK
 %token   CHAR_TK         INTEGRAL_TK
@@ -567,7 +568,8 @@
 			left_hand_side assignment for_header for_begin
 			constant_expression do_statement_begin empty_statement
 			switch_statement synchronized_statement throw_statement
-			try_statement switch_expression switch_block
+			try_statement assert_statement
+			switch_expression switch_block
 			catches catch_clause catch_clause_parameter finally
 			anonymous_class_creation trap_overflow_corner_case
 %type    <node>         return_statement break_statement continue_statement
@@ -584,7 +586,7 @@
 %token   <operator>     OP_TK OSB_TK DOT_TK THROW_TK INSTANCEOF_TK
 %type    <operator>	THIS_TK SUPER_TK RETURN_TK BREAK_TK CONTINUE_TK 
 %type	 <operator>     CASE_TK DEFAULT_TK TRY_TK CATCH_TK SYNCHRONIZED_TK
-%type	 <operator>     NEW_TK
+%type	 <operator>     NEW_TK ASSERT_TK
 
 %type	 <node>		method_body 
 	
@@ -1461,6 +1463,7 @@
 |	synchronized_statement
 |	throw_statement
 |	try_statement
+|	assert_statement
 ;
 
 empty_statement:
@@ -1846,6 +1849,21 @@
 		{yyerror ("';' expected"); RECOVER;}
 ;
 
+assert_statement:
+	ASSERT_TK expression REL_CL_TK expression SC_TK
+		{
+		  $$ = build_assertion ($1.location, $2, $4);
+		}
+|	ASSERT_TK expression SC_TK
+		{
+		  $$ = build_assertion ($1.location, $2, NULL_TREE);
+		}
+|	ASSERT_TK error
+		{yyerror ("Missing term"); RECOVER;}
+|	ASSERT_TK expression error
+		{yyerror ("';' expected"); RECOVER;}
+;
+
 synchronized_statement:
 	synchronized OP_TK expression CP_TK block
 		{ 
@@ -15208,6 +15226,78 @@
   CAN_COMPLETE_NORMALLY (node)
     = CAN_COMPLETE_NORMALLY (TREE_OPERAND (node, 1)) 
       || ! SWITCH_HAS_DEFAULT (node);
+  return node;
+}
+
+/* Assertions.  */
+
+/* Build an assertion expression for `assert CONDITION : VALUE'; VALUE
+   might be NULL_TREE.  */
+static tree
+build_assertion (location, condition, value)
+     int location;
+     tree condition, value;
+{
+  tree node;
+  tree klass = GET_CPC ();
+
+  if (! CLASS_USES_ASSERTIONS (klass))
+    {
+      tree field, classdollar, id, call;
+      tree class_type = TREE_TYPE (klass);
+
+      field = add_field (class_type,
+			 get_identifier ("$assertionsDisabled"),
+			 boolean_type_node,
+			 ACC_PRIVATE | ACC_STATIC | ACC_FINAL);
+      MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (field);
+      FIELD_SYNTHETIC (field) = 1;
+
+      if (!TYPE_DOT_CLASS (class_type))
+	build_dot_class_method (class_type);
+      classdollar = build_dot_class_method_invocation (class_type);
+
+      /* Call CLASS.desiredAssertionStatus().  */
+      id = build_wfl_node (get_identifier ("desiredAssertionStatus"));
+      call = build (CALL_EXPR, NULL_TREE, id, NULL_TREE, NULL_TREE);
+      call = make_qualified_primary (classdollar, call, location);
+      TREE_SIDE_EFFECTS (call) = 1;
+      DECL_INITIAL (field) = call;
+
+      /* Record the initializer in the initializer statement list.  */
+      call = build (MODIFY_EXPR, NULL_TREE, field, call);
+      TREE_CHAIN (call) = CPC_STATIC_INITIALIZER_STMT (ctxp);
+      SET_CPC_STATIC_INITIALIZER_STMT (ctxp, call);
+      MODIFY_EXPR_FROM_INITIALIZATION_P (call) = 1;
+
+      CLASS_USES_ASSERTIONS (klass) = 1;
+    }
+
+  if (value != NULL_TREE)
+    value = tree_cons (NULL_TREE, value, NULL_TREE);
+
+  node = build_wfl_node (get_identifier ("java"));
+  node = make_qualified_name (node, build_wfl_node (get_identifier ("lang")),
+			      location);
+  node = make_qualified_name (node, build_wfl_node (get_identifier ("AssertionError")),
+			      location);
+
+  node = build (NEW_CLASS_EXPR, NULL_TREE, node, value, NULL_TREE);
+  TREE_SIDE_EFFECTS (node) = 1;
+  /* It is too early to use BUILD_THROW.  */
+  node = build1 (THROW_EXPR, NULL_TREE, node);
+  TREE_SIDE_EFFECTS (node) = 1;
+
+  /* We invert the condition; if we just put NODE as the `else' part
+     then we generate weird-looking bytecode.  */
+  condition = build1 (TRUTH_NOT_EXPR, NULL_TREE, condition);
+  /* Check $assertionsDisabled.  */
+  condition
+    = build (TRUTH_ANDIF_EXPR, NULL_TREE,
+	     build1 (TRUTH_NOT_EXPR, NULL_TREE,
+		     build_wfl_node (get_identifier ("$assertionsDisabled"))),
+	     condition);
+  node = build_if_else_statement (location, condition, node, NULL_TREE);
   return node;
 }
 
Index: libjava/ChangeLog
from  Tom Tromey  <tromey@redhat.com>

	* java/lang/Class.h (Class::desiredAssertionStatus): Declare.
	(Class::getPackagePortion): Likewise.
	* java/lang/Class.java (desiredAssertionStatus): New method from
	Classpath.
	(getPackagePortion): Likewise.
	* java/lang/VMClassLoader.java (defaultAssertionStatus,
	packageAssertionStatus, classAssertionStatus): New methods from
	Classpath.
	* java/lang/ClassLoader.java (defaultAssertionStatus,
	systemPackageAssertionStatus, packageAssertionStatus,
	systemClassAssertionStatus, classAssertionStatus): New fields from
	Classpath.
	(setDefaultAssertionStatus, setPackageAssertionStatus,
	setClassAssertionStatus, clearAssertionStatus): New methods from
	Classpath.
	* Makefile.in: Rebuilt.
	* Makefile.am (core_java_source_files): Added AssertionError.java.
	* java/lang/AssertionError.java: New from Classpath.
	* java/lang/Throwable.java: Merged with Classpath.

Index: libjava/Makefile.am
===================================================================
RCS file: /cvs/gcc/gcc/libjava/Makefile.am,v
retrieving revision 1.202.2.8
diff -u -r1.202.2.8 Makefile.am
--- libjava/Makefile.am 2002/03/26 00:53:16 1.202.2.8
+++ libjava/Makefile.am 2002/04/05 15:53:09
@@ -1049,6 +1049,7 @@
 java/lang/ArithmeticException.java \
 java/lang/ArrayIndexOutOfBoundsException.java \
 java/lang/ArrayStoreException.java \
+java/lang/AssertionError.java \
 java/lang/Boolean.java \
 java/lang/Byte.java \
 java/lang/Character.java \
Index: libjava/Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/libjava/Makefile.in,v
retrieving revision 1.216.2.11
diff -u -r1.216.2.11 Makefile.in
--- libjava/Makefile.in 2002/03/27 16:40:17 1.216.2.11
+++ libjava/Makefile.in 2002/04/05 15:53:11
@@ -799,6 +799,7 @@
 java/lang/ArithmeticException.java \
 java/lang/ArrayIndexOutOfBoundsException.java \
 java/lang/ArrayStoreException.java \
+java/lang/AssertionError.java \
 java/lang/Boolean.java \
 java/lang/Byte.java \
 java/lang/Character.java \
@@ -2230,7 +2231,8 @@
 .deps/java/lang/AbstractMethodError.P \
 .deps/java/lang/ArithmeticException.P \
 .deps/java/lang/ArrayIndexOutOfBoundsException.P \
-.deps/java/lang/ArrayStoreException.P .deps/java/lang/Boolean.P \
+.deps/java/lang/ArrayStoreException.P .deps/java/lang/AssertionError.P \
+.deps/java/lang/Boolean.P \
 .deps/java/lang/Byte.P .deps/java/lang/CharSequence.P \
 .deps/java/lang/Character.P .deps/java/lang/Class.P \
 .deps/java/lang/ClassCastException.P \
Index: libjava/gcj/Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gcj/Makefile.in,v
retrieving revision 1.24.2.4
diff -u -r1.24.2.4 Makefile.in
--- libjava/gcj/Makefile.in 2002/03/27 16:40:27 1.24.2.4
+++ libjava/gcj/Makefile.in 2002/04/05 15:53:16
@@ -1,4 +1,4 @@
-# Makefile.in generated automatically by automake 1.4 from Makefile.am
+# Makefile.in generated automatically by automake 1.4-p4 from Makefile.am
 
 # Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
 # This Makefile.in is free software; the Free Software Foundation
@@ -257,7 +257,7 @@
 	@for file in $(DISTFILES); do \
 	  d=$(srcdir); \
 	  if test -d $$d/$$file; then \
-	    cp -pr $$/$$file $(distdir)/$$file; \
+	    cp -pr $$d/$$file $(distdir)/$$file; \
 	  else \
 	    test -f $(distdir)/$$file \
 	    || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
Index: libjava/include/Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/libjava/include/Makefile.in,v
retrieving revision 1.25.2.4
diff -u -r1.25.2.4 Makefile.in
--- libjava/include/Makefile.in 2002/03/27 16:40:28 1.25.2.4
+++ libjava/include/Makefile.in 2002/04/05 15:53:32
@@ -1,4 +1,4 @@
-# Makefile.in generated automatically by automake 1.4 from Makefile.am
+# Makefile.in generated automatically by automake 1.4-p4 from Makefile.am
 
 # Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
 # This Makefile.in is free software; the Free Software Foundation
@@ -238,7 +238,7 @@
 	@for file in $(DISTFILES); do \
 	  d=$(srcdir); \
 	  if test -d $$d/$$file; then \
-	    cp -pr $$/$$file $(distdir)/$$file; \
+	    cp -pr $$d/$$file $(distdir)/$$file; \
 	  else \
 	    test -f $(distdir)/$$file \
 	    || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
Index: libjava/java/lang/AssertionError.java
===================================================================
RCS file: AssertionError.java
diff -N AssertionError.java
--- /dev/null	Tue May  5 13:32:27 1998
+++ libjava/java/lang/AssertionError.java Fri Apr 5 07:53:37 2002
@@ -0,0 +1,148 @@
+/* AssertionError.java -- indication of a failed assertion
+   Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath 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, or (at your option)
+any later version.
+
+GNU Classpath 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 GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * An assertion error normally occurs as a result of the <code>assert</code>
+ * statement added in JDK 1.4, to indicate that an assertion failed. There
+ * are enough constructors to ensure that
+ * <code>new AssertionError(<em>expression</em)</code> will work for all
+ * espressions, regardless of type, as if the error message were given by
+ * the string <code>"" + <em>expression</em></code>. This extends Error,
+ * because you usually do not want to inadvertently trap an assertion failure.
+ *
+ * @author Eric Blake <ebb9@email.byu.edu>
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public class AssertionError extends Error
+{
+  /**
+   * Compatible with JDK 1.4+.
+   */
+  private static final long serialVersionUID = -5013299493970297370L;
+
+  /**
+   * Construct an AssertionError with no detail message.
+   */
+  public AssertionError()
+  {
+  }
+
+  /**
+   * Construct an AssertionError with the string conversion of the given
+   * object as its error message. If the object is a Throwable, it is also
+   * set as the cause of this error.
+   *
+   * @param msg the source of the error message
+   * @see Throwable#getCause()
+   */
+  public AssertionError(Object msg)
+  {
+    super("" + msg);
+    if (msg instanceof Throwable)
+      initCause((Throwable) msg);
+  }
+
+  /**
+   * Construct an AssertionError with the string conversion of the given
+   * boolean as its error message.
+   *
+   * @param msg the source of the error message
+   */
+  public AssertionError(boolean msg)
+  {
+    super(msg ? "true" : "false");
+  }
+
+  /**
+   * Construct an AssertionError with the string conversion of the given
+   * char as its error message.
+   *
+   * @param msg the source of the error message
+   */
+  public AssertionError(char msg)
+  {
+    super(String.valueOf(msg));
+  }
+
+  /**
+   * Construct an AssertionError with the string conversion of the given
+   * int as its error message.
+   *
+   * @param msg the source of the error message
+   */
+  public AssertionError(int msg)
+  {
+    super(Integer.toString(msg, 10));
+  }
+
+  /**
+   * Construct an AssertionError with the string conversion of the given
+   * long as its error message.
+   *
+   * @param msg the source of the error message
+   */
+  public AssertionError(long msg)
+  {
+    super(Long.toString(msg));
+  }
+
+  /**
+   * Construct an AssertionError with the string conversion of the given
+   * float as its error message.
+   *
+   * @param msg the source of the error message
+   */
+  public AssertionError(float msg)
+  {
+    super(Float.toString(msg));
+  }
+
+  /**
+   * Construct an AssertionError with the string conversion of the given
+   * double as its error message.
+   *
+   * @param msg the source of the error message
+   */
+  public AssertionError(double msg)
+  {
+    super(Double.toString(msg));
+  }
+}
Index: libjava/java/lang/Class.h
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/Class.h,v
retrieving revision 1.43
diff -u -r1.43 Class.h
--- libjava/java/lang/Class.h 2001/12/21 19:47:50 1.43
+++ libjava/java/lang/Class.h 2002/04/05 15:53:37
@@ -1,6 +1,6 @@
 // Class.h - Header file for java.lang.Class.  -*- c++ -*-
 
-/* Copyright (C) 1998, 1999, 2000, 2001  Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -210,6 +210,7 @@
 
   jobject newInstance (void);
   jstring toString (void);
+  jboolean desiredAssertionStatus (void);
 
   // FIXME: this probably shouldn't be public.
   jint size (void)
@@ -231,6 +232,8 @@
   void checkMemberAccess (jint flags);
 
   void initializeClass (void);
+
+  static jstring getPackagePortion (jstring);
 
   // Friend functions implemented in natClass.cc.
   friend _Jv_Method *_Jv_GetMethodLocal (jclass klass, _Jv_Utf8Const *name,
Index: libjava/java/lang/Class.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/Class.java,v
retrieving revision 1.11
diff -u -r1.11 Class.java
--- libjava/java/lang/Class.java 2001/04/25 15:45:12 1.11
+++ libjava/java/lang/Class.java 2002/04/05 15:53:37
@@ -1,6 +1,6 @@
 // Class.java - Representation of a Java class.
 
-/* Copyright (C) 1998, 1999, 2000  Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2002  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -217,6 +217,75 @@
     return (isInterface () ? "interface " : "class ") + getName ();
   }
 
+  /**
+   * Returns the desired assertion status of this class, if it were to be
+   * initialized at this moment. The class assertion status, if set, is
+   * returned; the backup is the default package status; then if there is
+   * a class loader, that default is returned; and finally the system default
+   * is returned. This method seldom needs calling in user code, but exists
+   * for compilers to implement the assert statement. Note that there is no
+   * guarantee that the result of this method matches the class's actual
+   * assertion status.
+   *
+   * @return the desired assertion status
+   * @see ClassLoader#setClassAssertionStatus(String, boolean)
+   * @see ClassLoader#setPackageAssertionStatus(String, boolean)
+   * @see ClassLoader#setDefaultAssertionStatus(boolean)
+   * @since 1.4
+   */
+  public boolean desiredAssertionStatus()
+  {
+    ClassLoader c = getClassLoader();
+    Object status;
+    if (c == null)
+      return VMClassLoader.defaultAssertionStatus();
+    if (c.classAssertionStatus != null)
+      synchronized (c)
+        {
+          status = c.classAssertionStatus.get(getName());
+          if (status != null)
+            return status.equals(Boolean.TRUE);
+        }
+    else
+      {
+        status = ClassLoader.systemClassAssertionStatus.get(getName());
+        if (status != null)
+          return status.equals(Boolean.TRUE);
+      }
+    if (c.packageAssertionStatus != null)
+      synchronized (c)
+        {
+          String name = getPackagePortion(getName());
+          if ("".equals(name))
+            status = c.packageAssertionStatus.get(null);
+          else
+            do
+              {
+                status = c.packageAssertionStatus.get(name);
+                name = getPackagePortion(name);
+              }
+            while (! "".equals(name) && status == null);
+          if (status != null)
+            return status.equals(Boolean.TRUE);
+        }
+    else
+      {
+        String name = getPackagePortion(getName());
+        if ("".equals(name))
+          status = ClassLoader.systemPackageAssertionStatus.get(null);
+        else
+          do
+            {
+              status = ClassLoader.systemPackageAssertionStatus.get(name);
+              name = getPackagePortion(name);
+            }
+          while (! "".equals(name) && status == null);
+        if (status != null)
+          return status.equals(Boolean.TRUE);
+      }
+    return c.defaultAssertionStatus;
+  }
+
   // Don't allow new classes to be made.
   private Class ()
   {
@@ -235,4 +304,18 @@
 
   // finalization
   protected native void finalize ();
+
+  /**
+   * Strip the last portion of the name (after the last dot).
+   *
+   * @param name the name to get package of
+   * @return the package name, or "" if no package
+   */
+  private static String getPackagePortion(String name)
+  {
+    int lastInd = name.lastIndexOf('.');
+    if (lastInd == -1)
+      return "";
+    return name.substring(0, lastInd);
+  }
 }
Index: libjava/java/lang/ClassLoader.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/ClassLoader.java,v
retrieving revision 1.16
diff -u -r1.16 ClassLoader.java
--- libjava/java/lang/ClassLoader.java 2001/12/07 23:34:12 1.16
+++ libjava/java/lang/ClassLoader.java 2002/04/05 15:53:37
@@ -1,6 +1,6 @@
 // ClassLoader.java - Define policies for loading Java classes.
 
-/* Copyright (C) 1998, 1999, 2000, 2001  Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -20,9 +20,7 @@
 import java.security.Permissions;
 import java.security.Policy;
 import java.security.ProtectionDomain;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Stack;
+import java.util.*;
 
 /**
  * The class <code>ClassLoader</code> is intended to be subclassed by
@@ -34,6 +32,47 @@
 
 public abstract class ClassLoader
 {
+  /**
+   * The desired assertion status of classes loaded by this loader, if not
+   * overridden by package or class instructions.
+   */
+  // Package visible for use by Class.
+  boolean defaultAssertionStatus = VMClassLoader.defaultAssertionStatus();
+
+  /**
+   * The command-line state of the package assertion status overrides. This
+   * map is never modified, so it does not need to be synchronized.
+   */
+  // Package visible for use by Class.
+  static final Map systemPackageAssertionStatus
+    = VMClassLoader.packageAssertionStatus();
+
+  /**
+   * The map of package assertion status overrides, or null if no package
+   * overrides have been specified yet. The values of the map should be
+   * Boolean.TRUE or Boolean.FALSE, and the unnamed package is represented
+   * by the null key. This map must be synchronized on this instance.
+   */
+  // Package visible for use by Class.
+  Map packageAssertionStatus;
+
+  /**
+   * The command-line state of the class assertion status overrides. This
+   * map is never modified, so it does not need to be synchronized.
+   */
+  // Package visible for use by Class.
+  static final Map systemClassAssertionStatus
+    = VMClassLoader.classAssertionStatus();
+
+  /**
+   * The map of class assertion status overrides, or null if no class
+   * overrides have been specified yet. The values of the map should be
+   * Boolean.TRUE or Boolean.FALSE. This map must be synchronized on this
+   * instance.
+   */
+  // Package visible for use by Class.
+  Map classAssertionStatus;
+
   private ClassLoader parent;
   private HashMap definedPackages = new HashMap();
 
@@ -576,5 +615,79 @@
   {
     // Default to returning null.  Derived classes implement this.
     return null;
+  }
+
+  /**
+   * Set the default assertion status for classes loaded by this classloader,
+   * used unless overridden by a package or class request.
+   *
+   * @param enabled true to set the default to enabled
+   * @see #setClassAssertionStatus(String, boolean)
+   * @see #setPackageAssertionStatus(String, boolean)
+   * @see #clearAssertionStatus()
+   * @since 1.4
+   */
+  public void setDefaultAssertionStatus(boolean enabled)
+  {
+    defaultAssertionStatus = enabled;
+  }
+
+  /**
+   * Set the default assertion status for packages, used unless overridden
+   * by a class request. This default also covers subpackages, unless they
+   * are also specified. The unnamed package should use null for the name.
+   *
+   * @param name the package (and subpackages) to affect
+   * @param enabled true to set the default to enabled
+   * @see #setDefaultAssertionStatus(String, boolean)
+   * @see #setClassAssertionStatus(String, boolean)
+   * @see #clearAssertionStatus()
+   * @since 1.4
+   */
+  public synchronized void setPackageAssertionStatus(String name,
+                                                     boolean enabled)
+  {
+    if (packageAssertionStatus == null)
+      packageAssertionStatus
+        = new HashMap(systemPackageAssertionStatus);
+    packageAssertionStatus.put(name, Boolean.valueOf(enabled));
+  }
+  
+  /**
+   * Set the default assertion status for a class. This only affects the
+   * status of top-level classes, any other string is harmless.
+   *
+   * @param name the class to affect
+   * @param enabled true to set the default to enabled
+   * @throws NullPointerException if name is null
+   * @see #setDefaultAssertionStatus(String, boolean)
+   * @see #setPackageAssertionStatus(String, boolean)
+   * @see #clearAssertionStatus()
+   * @since 1.4
+   */
+  public synchronized void setClassAssertionStatus(String name,
+                                                   boolean enabled)
+  {
+    if (classAssertionStatus == null)
+      classAssertionStatus = new HashMap(systemClassAssertionStatus);
+    // The toString() hack catches null, as required.
+    classAssertionStatus.put(name.toString(), Boolean.valueOf(enabled));
+  }
+  
+  /**
+   * Resets the default assertion status of this classloader, its packages
+   * and classes, all to false. This allows overriding defaults inherited
+   * from the command line.
+   *
+   * @see #setDefaultAssertionStatus(boolean)
+   * @see #setClassAssertionStatus(String, boolean)
+   * @see #setPackageAssertionStatus(String, boolean)
+   * @since 1.4
+   */
+  public synchronized void clearAssertionStatus()
+  {
+    defaultAssertionStatus = false;
+    packageAssertionStatus = new HashMap();
+    classAssertionStatus = new HashMap();
   }
 }
Index: libjava/java/lang/Throwable.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/Throwable.java,v
retrieving revision 1.10
diff -u -r1.10 Throwable.java
--- libjava/java/lang/Throwable.java 2001/02/24 03:52:49 1.10
+++ libjava/java/lang/Throwable.java 2002/04/05 15:53:38
@@ -1,6 +1,6 @@
 // Throwable.java - Superclass for all exceptions.
 
-/* Copyright (C) 1998, 1999  Free Software Foundation
+/* Copyright (C) 1998, 1999, 2002  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -18,16 +18,401 @@
 import java.io.IOException;
 
 /**
+ * Throwable is the superclass of all exceptions that can be raised.
+ *
+ * <p>There are two special cases: {@link Error} and {@link RuntimeException}:
+ * these two classes (and their subclasses) are considered unchecked
+ * exceptions, and are either frequent enough or catastrophic enough that you
+ * do not need to declare them in <code>throws</code> clauses.  Everything
+ * else is a checked exception, and is ususally a subclass of
+ * {@link Exception}; these exceptions have to be handled or declared.
+ *
+ * <p>Instances of this class are usually created with knowledge of the
+ * execution context, so that you can get a stack trace of the problem spot
+ * in the code.  Also, since JDK 1.4, Throwables participate in "exception
+ * chaining."  This means that one exception can be caused by another, and
+ * preserve the information of the original.
+ *
+ * <p>One reason this is useful is to wrap exceptions to conform to an
+ * interface.  For example, it would be bad design to require all levels
+ * of a program interface to be aware of the low-level exceptions thrown
+ * at one level of abstraction. Another example is wrapping a checked
+ * exception in an unchecked one, to communicate that failure occured
+ * while still obeying the method throws clause of a superclass.
+ *
+ * <p>A cause is assigned in one of two ways; but can only be assigned once
+ * in the lifetime of the Throwable.  There are new constructors added to
+ * several classes in the exception hierarchy that directly initialize the
+ * cause, or you can use the <code>initCause</code> method. This second
+ * method is especially useful if the superclass has not been retrofitted
+ * with new constructors:<br>
+ * <pre>
+ * try
+ *   {
+ *     lowLevelOp();
+ *   }
+ * catch (LowLevelException lle)
+ *   {
+ *     throw (HighLevelException) new HighLevelException().initCause(lle);
+ *   }
+ * </pre>
+ * Notice the cast in the above example; without it, your method would need
+ * a throws clase that declared Throwable, defeating the purpose of chainig
+ * your exceptions.
+ *
+ * <p>By convention, exception classes have two constructors: one with no
+ * arguments, and one that takes a String for a detail message.  Further,
+ * classes which are likely to be used in an exception chain also provide
+ * a constructor that takes a Throwable, with or without a detail message
+ * string.
+ *
+ * <p>Another 1.4 feature is the StackTrace, a means of reflection that
+ * allows the program to inspect the context of the exception, and which is
+ * serialized, so that remote procedure calls can correctly pass exceptions.
+ *
+ * @author Brian Jones
+ * @author John Keiser
+ * @author Mark Wielaard
+ * @author Eric Blake <ebb9@email.byu.edu>
  * @author Tom Tromey <tromey@cygnus.com>
- * @date October 30, 1998 
+ * @since 1.0
+ * @status still missing 1.4 functionality
  */
+public class Throwable extends Object implements Serializable
+{
+  /**
+   * Compatible with JDK 1.0+.
+   */
+  private static final long serialVersionUID = -3042686055658047285L;
 
-/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
- * "The Java Language Specification", ISBN 0-201-63451-1
- * Status: Sufficient for compiled code, but methods applicable to
- * bytecode not implemented.  JDK 1.1.
- */
+  /**
+   * The detail message.
+   *
+   * @serial specific details about the exception, may be null
+   */
+  private String detailMessage;
+
+  /**
+   * The cause of the throwable, including null for an unknown or non-chained
+   * cause. This may only be set once; so the field is set to
+   * <code>this</code> until initialized.
+   *
+   * @serial the cause, or null if unknown, or this if not yet set
+   * @since 1.4
+   */
+  private Throwable cause = this;
+
+  /**
+   * The stack trace, in a serialized form.
+   *
+   * @serial the elements of the stack trace; this is non-null, and has
+   *         no null entries
+   * @since 1.4
+   */
+  // FIXME: wrong type here.
+  private byte[] stackTrace;
+
+  // Setting this flag to false prevents fillInStackTrace() from running.
+  static boolean trace_enabled = true;
 
+  /**
+   * Instantiate this Throwable with an empty message. The cause remains
+   * uninitialized.  {@link #fillInStackTrace()} will be called to set
+   * up the stack trace.
+   */
+  public Throwable()
+  {
+    this((String) null);
+  }
+
+  /**
+   * Instantiate this Throwable with the given message. The cause remains
+   * uninitialized.  {@link #fillInStackTrace()} will be called to set
+   * up the stack trace.
+   *
+   * @param message the message to associate with the Throwable
+   */
+  public Throwable(String message)
+  {
+    fillInStackTrace();
+    detailMessage = message;
+  }
+
+  /**
+   * Instantiate this Throwable with the given message and cause. Note that
+   * the message is unrelated to the message of the cause.
+   * {@link #fillInStackTrace()} will be called to set up the stack trace.
+   *
+   * @param message the message to associate with the Throwable
+   * @param cause the cause, may be null
+   * @since 1.4
+   */
+  public Throwable(String message, Throwable cause)
+  {
+    this(message);
+    initCause(cause);
+  }
+
+  /**
+   * Instantiate this Throwable with the given cause. The message is then
+   * built as <code>cause == null ? null : cause.toString()</code>.
+   * {@link #fillInStackTrace()} will be called to set up the stack trace.
+   *
+   * @param cause the cause, may be null
+   * @since 1.4
+   */
+  public Throwable(Throwable cause)
+  {
+    this(cause == null ? null : cause.toString(), cause);
+  }
+
+  /**
+   * Get the message associated with this Throwable.
+   *
+   * @return the error message associated with this Throwable, may be null
+   */
+  public String getMessage()
+  {
+    return detailMessage;
+  }
+
+  /**
+   * Get a localized version of this Throwable's error message.
+   * This method must be overridden in a subclass of Throwable
+   * to actually produce locale-specific methods.  The Throwable
+   * implementation just returns getMessage().
+   *
+   * @return a localized version of this error message
+   * @see #getMessage()
+   * @since 1.1
+   */
+  public String getLocalizedMessage()
+  {
+    return getMessage();
+  }
+
+  /**
+   * Returns the cause of this exception, or null if the cause is not known
+   * or non-existant. This cause is initialized by the new constructors,
+   * or by calling initCause.
+   *
+   * @return the cause of this Throwable
+   * @since 1.4
+   */
+  public Throwable getCause()
+  {
+    return cause == this ? null : cause;
+  }
+
+  /**
+   * Initialize the cause of this Throwable.  This may only be called once
+   * during the object lifetime, including implicitly by chaining
+   * constructors.
+   *
+   * @param cause the cause of this Throwable, may be null
+   * @return this
+   * @throws IllegalArgumentException if cause is this (a Throwable can't be
+   *         its own cause!)
+   * @throws IllegalStateException if the cause has already been set
+   * @since 1.4
+   */
+  public Throwable initCause(Throwable cause)
+  {
+    if (cause == this)
+      throw new IllegalArgumentException();
+    if (this.cause != this)
+      throw new IllegalStateException();
+    this.cause = cause;
+    return this;
+  }
+
+  /**
+   * Get a human-readable representation of this Throwable. The detail message
+   * is retrieved by getLocalizedMessage().  Then, with a null detail
+   * message, this string is simply the object's class name; otherwise
+   * the string is <code>getClass().getName() + ": " + message</code>.
+   *
+   * @return a human-readable String represting this Throwable
+   */
+  public String toString()
+  {
+    String msg = getLocalizedMessage();
+    return getClass().getName() + (msg == null ? "" : ": " + msg);
+  }
+
+  /**
+   * Print a stack trace to the standard error stream. This stream is the
+   * current contents of <code>System.err</code>. The first line of output
+   * is the result of {@link #toString()}, and the remaining lines represent
+   * the data created by {@link #fillInStackTrace()}. While the format is
+   * unspecified, this implementation uses the suggested format, demonstrated
+   * by this example:<br>
+   * <pre>
+   * public class Junk
+   * {
+   *   public static void main(String args[])
+   *   {
+   *     try
+   *       {
+   *         a();
+   *       }
+   *     catch(HighLevelException e)
+   *       {
+   *         e.printStackTrace();
+   *       }
+   *   }
+   *   static void a() throws HighLevelException
+   *   {
+   *     try
+   *       {
+   *         b();
+   *       }
+   *     catch(MidLevelException e)
+   *       {
+   *         throw new HighLevelException(e);
+   *       }
+   *   }
+   *   static void b() throws MidLevelException
+   *   {
+   *     c();
+   *   }
+   *   static void c() throws MidLevelException
+   *   {
+   *     try
+   *       {
+   *         d();
+   *       }
+   *     catch(LowLevelException e)
+   *       {
+   *         throw new MidLevelException(e);
+   *       }
+   *   }
+   *   static void d() throws LowLevelException
+   *   {
+   *     e();
+   *   }
+   *   static void e() throws LowLevelException
+   *   {
+   *     throw new LowLevelException();
+   *   }
+   * }
+   * class HighLevelException extends Exception
+   * {
+   *   HighLevelException(Throwable cause) { super(cause); }
+   * }
+   * class MidLevelException extends Exception
+   * {
+   *   MidLevelException(Throwable cause)  { super(cause); }
+   * }
+   * class LowLevelException extends Exception
+   * {
+   * }
+   * </pre>
+   * <p>
+   * <pre>
+   *  HighLevelException: MidLevelException: LowLevelException
+   *          at Junk.a(Junk.java:13)
+   *          at Junk.main(Junk.java:4)
+   *  Caused by: MidLevelException: LowLevelException
+   *          at Junk.c(Junk.java:23)
+   *          at Junk.b(Junk.java:17)
+   *          at Junk.a(Junk.java:11)
+   *          ... 1 more
+   *  Caused by: LowLevelException
+   *          at Junk.e(Junk.java:30)
+   *          at Junk.d(Junk.java:27)
+   *          at Junk.c(Junk.java:21)
+   *          ... 3 more
+   * </pre>
+   */
+  public void printStackTrace()
+  {
+    printStackTrace(System.err);
+  }
+
+  /**
+   * Print a stack trace to the specified PrintStream. See
+   * {@link #printStackTrace()} for the sample format.
+   *
+   * @param s the PrintStream to write the trace to
+   */
+  public void printStackTrace(PrintStream s)
+  {
+    printStackTrace(new PrintWriter(s));
+  }
+
+  /**
+   * Print a stack trace to the specified PrintWriter. See
+   * {@link #printStackTrace()} for the sample format.
+   *
+   * @param w the PrintWriter to write the trace to
+   * @since 1.1
+   */
+  public void printStackTrace(PrintWriter w)
+  {
+    try
+      {
+	CPlusPlusDemangler cPlusPlusFilter = new CPlusPlusDemangler (w);
+	PrintWriter writer = new PrintWriter (cPlusPlusFilter);
+	printRawStackTrace (writer);	
+	writer.close ();
+	if (cPlusPlusFilter.written == 0) // The demangler has failed...
+	  printRawStackTrace (w);
+      }
+    catch (Exception e1)
+      {
+	printRawStackTrace (w);
+      }
+  }
+
+  /**
+   * Fill in the stack trace with the current execution stack.
+   * Normally used when rethrowing an exception, to strip
+   * off unnecessary extra stack frames.
+   *
+   * @return this same throwable
+   * @see #printStackTrace()
+   */
+  public native Throwable fillInStackTrace();
+
+  /**
+   * Provides access to the information printed in {@link #printStackTrace()}.
+   * The array is non-null, with no null entries, although the virtual
+   * machine is allowed to skip stack frames.  If the array is not 0-length,
+   * then slot 0 holds the information on the stack frame where the Throwable
+   * was created (or at least where <code>fillInStackTrace()</code> was
+   * called).
+   *
+   * @return an array of stack trace information, as available from the VM
+   * @since 1.4
+   */
+  // FIXME
+//   public StackTraceElement[] getStackTrace()
+//   {
+//     return stackTrace;
+//   }
+
+  /**
+   * Change the stack trace manually. This method is designed for remote
+   * procedure calls, which intend to alter the stack trace before or after
+   * serialization according to the context of the remote call.
+   *
+   * @param stackTrace the new trace to use
+   * @throws NullPointerException if stackTrace is null or has null elements
+   * @since 1.4
+   */
+  // FIXME: we don't yet have StackTraceElement.
+//   public void setStackTrace(StackTraceElement[] stackTrace)
+//   {
+//     for (int i = stackTrace.length; --i >= 0; )
+//       if (stackTrace[i] == null)
+//         throw new NullPointerException();
+//     this.stackTrace = stackTrace;
+//   }
+
+  private native final void printRawStackTrace (PrintWriter wr);
+}
+
 /* A CPlusPlusDemangler sits on top of a PrintWriter.  All input is
  * passed through the "c++filt" program (part of GNU binutils) which
  * demangles internal symbols to their C++ source form.
@@ -96,76 +481,4 @@
       {
       }
   }    
-}
-
-public class Throwable implements Serializable
-{
-  public native Throwable fillInStackTrace ();
-
-  public String getLocalizedMessage ()
-  {
-    return getMessage ();
-  }
-
-  public String getMessage ()
-  {
-    return detailMessage;
-  }
-
-  public void printStackTrace ()
-  {
-    printStackTrace (System.err);
-  }
-
-  public void printStackTrace (PrintStream ps)
-  {
-    PrintWriter writer = new PrintWriter (ps);
-    printStackTrace (writer);
-  }
-
-  public void printStackTrace (PrintWriter wr)
-  {
-    try
-      {
-	CPlusPlusDemangler cPlusPlusFilter = new CPlusPlusDemangler (wr);
-	PrintWriter writer = new PrintWriter (cPlusPlusFilter);
-	printRawStackTrace (writer);	
-	writer.close ();
-	if (cPlusPlusFilter.written == 0) // The demangler has failed...
-	  printRawStackTrace (wr);
-      }
-    catch (Exception e1)
-      {
-	printRawStackTrace (wr);
-      }
-  }
-
-  public Throwable ()
-  {
-    detailMessage = null;
-    fillInStackTrace ();
-  }
-
-  public Throwable (String message)
-  {
-    detailMessage = message;
-    fillInStackTrace ();
-  }
-
-  public String toString ()
-  {
-    return ((detailMessage == null)
-	    ? getClass().getName()
-	    : getClass().getName() + ": " + getMessage ());
-  }
-
-  private native final void printRawStackTrace (PrintWriter wr);
-  
-  // Name of this field comes from serialization spec.
-  private String detailMessage;
-
-  // Setting this flag to false prevents fillInStackTrace() from running.
-  static boolean trace_enabled = true;
-  private transient byte stackTrace[];
-  private static final long serialVersionUID = -3042686055658047285L;
 }
Index: libjava/java/lang/VMClassLoader.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/VMClassLoader.java,v
retrieving revision 1.5
diff -u -r1.5 VMClassLoader.java
--- libjava/java/lang/VMClassLoader.java 2001/10/26 01:51:04 1.5
+++ libjava/java/lang/VMClassLoader.java 2002/04/05 15:53:38
@@ -1,6 +1,6 @@
 /*
  * java.lang.ClassLoader: part of the Java Class Libraries project.
- * Copyright (C) 1998, 2001 Free Software Foundation
+ * Copyright (C) 1998, 2001, 2002 Free Software Foundation
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -20,6 +20,8 @@
 
 package java.lang;
 
+import java.util.*;
+
 /**
  * java.lang.VMClassLoader is a package-private helper for VMs to implement
  * on behalf of java.lang.ClassLoader.
@@ -59,4 +61,47 @@
      * @param type code for the primitive type.
      */
   static native Class getPrimitiveClass(char type);
+
+  /**
+   * The system default for assertion status. This is used for all system
+   * classes (those with a null ClassLoader), as well as the initial value for
+   * every ClassLoader's default assertion status.
+   *
+   * XXX - Not implemented yet; this requires native help.
+   *
+   * @return the system-wide default assertion status
+   */
+  static final boolean defaultAssertionStatus()
+  {
+    return true;
+  }
+
+  /**
+   * The system default for package assertion status. This is used for all
+   * ClassLoader's packageAssertionStatus defaults. It must be a map of
+   * package names to Boolean.TRUE or Boolean.FALSE, with the unnamed package
+   * represented as a null key.
+   *
+   * XXX - Not implemented yet; this requires native help.
+   *
+   * @return a (read-only) map for the default packageAssertionStatus
+   */
+  static final Map packageAssertionStatus()
+  {
+    return new HashMap();
+  }
+
+  /**
+   * The system default for class assertion status. This is used for all
+   * ClassLoader's classAssertionStatus defaults. It must be a map of
+   * class names to Boolean.TRUE or Boolean.FALSE
+   *
+   * XXX - Not implemented yet; this requires native help.
+   *
+   * @return a (read-only) map for the default classAssertionStatus
+   */
+  static final Map classAssertionStatus()
+  {
+    return new HashMap();
+  }
 }
Index: libjava/testsuite/Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/libjava/testsuite/Makefile.in,v
retrieving revision 1.35.2.4
diff -u -r1.35.2.4 Makefile.in
--- libjava/testsuite/Makefile.in 2002/03/27 16:40:30 1.35.2.4
+++ libjava/testsuite/Makefile.in 2002/04/05 15:53:53
@@ -1,4 +1,4 @@
-# Makefile.in generated automatically by automake 1.4 from Makefile.am
+# Makefile.in generated automatically by automake 1.4-p4 from Makefile.am
 
 # Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
 # This Makefile.in is free software; the Free Software Foundation
@@ -132,14 +132,10 @@
 AUTOMAKE_OPTIONS = foreign dejagnu
 
 # Setup the testing framework, if you have one
-EXPECT = `if [ -f $(top_builddir)/../expect/expect ] ; then \
-            echo $(top_builddir)/../expect/expect ; \
-          else echo expect ; fi`
+EXPECT = `if [ -f $(top_builddir)/../expect/expect ] ; then             echo $(top_builddir)/../expect/expect ;           else echo expect ; fi`
 
 
-RUNTEST = `if [ -f $(top_srcdir)/../dejagnu/runtest ] ; then \
-	       echo $(top_srcdir)/../dejagnu/runtest ; \
-	    else echo runtest; fi`
+RUNTEST = `if [ -f $(top_srcdir)/../dejagnu/runtest ] ; then 	       echo $(top_srcdir)/../dejagnu/runtest ; 	    else echo runtest; fi`
 
 
 RUNTESTFLAGS = @AM_RUNTESTFLAGS@
@@ -178,7 +174,7 @@
 	@for file in $(DISTFILES); do \
 	  d=$(srcdir); \
 	  if test -d $$d/$$file; then \
-	    cp -pr $$/$$file $(distdir)/$$file; \
+	    cp -pr $$d/$$file $(distdir)/$$file; \
 	  else \
 	    test -f $(distdir)/$$file \
 	    || ln $$d/$$file $(distdir)/$$file 2> /dev/null \



More information about the Gcc-patches mailing list