OSDN Git Service

* g++.old-deja/g++.other/dwarf2-1.C: Move...
[pf3gnuchains/gcc-fork.git] / gcc / java / parse.y
index acf00d9..eecb8ad 100644 (file)
@@ -1,6 +1,6 @@
 /* Source code parsing and tree node generation for the GNU compiler
    for the Java(TM) language.
-   Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
    Contributed by Alexandre Petit-Bianco (apbianco@cygnus.com)
 
 This file is part of GNU CC.
@@ -108,6 +108,7 @@ static tree resolve_package PARAMS ((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));
 static void source_start_java_method PARAMS ((tree));
 static void source_end_java_method PARAMS ((void));
 static tree find_name_in_single_imports PARAMS ((tree));
@@ -242,7 +243,7 @@ static tree build_instinit_invocation PARAMS ((tree));
 static void fix_constructors PARAMS ((tree));
 static tree build_alias_initializer_parameter_list PARAMS ((int, tree,
                                                            tree, int *));
-static void craft_constructor PARAMS ((tree, tree));
+static tree craft_constructor PARAMS ((tree, tree));
 static int verify_constructor_super PARAMS ((tree));
 static tree create_artificial_method PARAMS ((tree, int, tree, tree, tree));
 static void start_artificial_method_body PARAMS ((tree));
@@ -420,7 +421,7 @@ static tree currently_caught_type_list;
    `ctxp->current_loop'.  */
 static tree case_label_list; 
 
-static tree src_parse_roots[1] = { NULL_TREE };
+static tree src_parse_roots[1];
 
 /* All classes seen from source code */
 #define gclass_list src_parse_roots[0]
@@ -481,8 +482,8 @@ static tree src_parse_roots[1] = { NULL_TREE };
 %token   PUBLIC_TK       PRIVATE_TK         PROTECTED_TK
 %token   STATIC_TK       FINAL_TK           SYNCHRONIZED_TK
 %token   VOLATILE_TK     TRANSIENT_TK       NATIVE_TK
-%token   PAD_TK          ABSTRACT_TK        MODIFIER_TK
-%token   STRICT_TK
+%token   PAD_TK          ABSTRACT_TK        STRICT_TK
+%token   MODIFIER_TK
 
 /* Keep those two in order, too */
 %token   DECR_TK INCR_TK
@@ -4060,6 +4061,9 @@ end_class_declaration (resume)
      popped by a resume. */
   int no_error_occurred = ctxp->next && GET_CPC () != error_mark_node;
 
+  if (GET_CPC () != error_mark_node)
+    dump_java_tree (TDI_class, GET_CPC ());
+
   java_parser_context_pop_initialized_field ();
   POP_CPC ();
   if (resume && no_error_occurred)
@@ -4539,7 +4543,8 @@ method_header (flags, type, mdecl, throws)
       ABSTRACT_CHECK (flags, ACC_STATIC, id, "Static");
       ABSTRACT_CHECK (flags, ACC_FINAL, id, "Final");
       ABSTRACT_CHECK (flags, ACC_NATIVE, id, "Native");
-      ABSTRACT_CHECK (flags, ACC_SYNCHRONIZED,id, "Synchronized");
+      ABSTRACT_CHECK (flags, ACC_SYNCHRONIZED, id, "Synchronized");
+      ABSTRACT_CHECK (flags, ACC_STRICT, id, "Strictfp");
       if (!CLASS_ABSTRACT (TYPE_NAME (this_class))
          && !CLASS_INTERFACE (TYPE_NAME (this_class)))
        parse_error_context 
@@ -4565,6 +4570,7 @@ method_header (flags, type, mdecl, throws)
          JCONSTRUCTOR_CHECK (flags, ACC_FINAL, id, "final");
          JCONSTRUCTOR_CHECK (flags, ACC_NATIVE, id, "native");
          JCONSTRUCTOR_CHECK (flags, ACC_SYNCHRONIZED, id, "synchronized");
+         JCONSTRUCTOR_CHECK (flags, ACC_STRICT, id, "strictfp");
        }
       /* If we found error here, we don't consider it's OK to tread
         the method definition as a constructor, for the rest of this
@@ -5064,12 +5070,12 @@ parser_check_super_interface (super_decl, this_decl, this_wfl)
   if (!CLASS_INTERFACE (super_decl))
     {
       parse_error_context 
-       (this_wfl, "Can't use %s `%s' to implement/extend %s `%s'",
-        (TYPE_ARRAY_P (super_type) ? "array" : "class"),
-        IDENTIFIER_POINTER (DECL_NAME (super_decl)),
+       (this_wfl, "%s `%s' can't implement/extend %s `%s'",
         (CLASS_INTERFACE (TYPE_NAME (TREE_TYPE (this_decl))) ? 
-         "interface" : "class"),
-        IDENTIFIER_POINTER (DECL_NAME (this_decl)));
+         "Interface" : "Class"),
+        IDENTIFIER_POINTER (DECL_NAME (this_decl)),
+        (TYPE_ARRAY_P (super_type) ? "array" : "class"),
+        IDENTIFIER_POINTER (DECL_NAME (super_decl)));
       return 1;
     }
 
@@ -5394,7 +5400,7 @@ build_alias_initializer_parameter_list (mode, class_type, parm, artificial)
    where found. ARGS is non NULL when a special signature must be
    enforced. This is the case for anonymous classes.  */
 
-static void
+static tree
 craft_constructor (class_decl, args)
      tree class_decl, args;
 {
@@ -5443,6 +5449,7 @@ craft_constructor (class_decl, args)
   /* Now, mark the artificial parameters. */
   DECL_FUNCTION_NAP (decl) = artificial;
   DECL_FUNCTION_SYNTHETIC_CTOR (decl) = DECL_CONSTRUCTOR_P (decl) = 1;
+  return decl;
 }
 
 
@@ -5739,6 +5746,7 @@ do_resolve_class (enclosing, class_type, decl, cl)
 {
   tree new_class_decl = NULL_TREE, super = NULL_TREE;
   tree saved_enclosing_type = enclosing ? TREE_TYPE (enclosing) : NULL_TREE;
+  tree decl_result;
   struct hash_table _ht, *circularity_hash = &_ht;
 
   /* This hash table is used to register the classes we're going
@@ -5835,9 +5843,32 @@ do_resolve_class (enclosing, class_type, decl, cl)
       if (check_pkg_class_access (TYPE_NAME (class_type), cl, true))
         return NULL_TREE;
     }
-  
+
   /* 6- Last call for a resolution */
-  return IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type));
+  decl_result = IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type));
+
+  /* The final lookup might have registered a.b.c into a.b$c If we
+     failed at the first lookup, progressively change the name if
+     applicable and use the matching DECL instead. */
+  if (!decl_result && QUALIFIED_P (TYPE_NAME (class_type)))
+    {
+      tree name = TYPE_NAME (class_type);
+      char *separator;
+      do {
+
+       /* Reach the last '.', and if applicable, replace it by a `$' and
+          see if this exists as a type. */
+       if ((separator = strrchr (IDENTIFIER_POINTER (name), '.')))
+         {
+           int c = *separator;
+           *separator = '$';
+           name = get_identifier (IDENTIFIER_POINTER (name));
+           *separator = c;
+           decl_result = IDENTIFIER_CLASS_VALUE (name);
+         }
+      } while (!decl_result && separator);
+    }
+  return decl_result;
 }
 
 static tree
@@ -7391,6 +7422,24 @@ end_artificial_method_body (mdecl)
   exit_block ();
 }
 
+/* Dump a tree of some kind.  This is a convenience wrapper for the
+   dump_* functions in tree-dump.c.  */
+static void
+dump_java_tree (phase, t)
+     enum tree_dump_index phase;
+     tree t;
+{
+  FILE *stream;
+  int flags;
+
+  stream = dump_begin (phase, &flags);
+  if (stream)
+    {
+      dump_node (t, flags, stream);
+      dump_end (phase, stream);
+    }
+}
+
 /* Terminate a function and expand its body.  */
 
 static void
@@ -7410,6 +7459,10 @@ source_end_java_method ()
   if (BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (fndecl)) == empty_stmt_node)
     BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (fndecl)) = NULL_TREE;
 
+  /* We've generated all the trees for this function, and it has been
+     patched.  Dump it to a file if the user requested it.  */
+  dump_java_tree (TDI_original, fndecl);
+
   /* Generate function's code */
   if (BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (fndecl))
       && ! flag_emit_class_files
@@ -7697,7 +7750,9 @@ java_complete_expand_methods (class_decl)
 
       if (METHOD_NATIVE (decl))
        {
-         tree body = build_jni_stub (decl);
+         tree body;
+         current_function_decl = decl;
+         body = build_jni_stub (decl);
          BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (decl)) = body;
        }
 
@@ -8493,7 +8548,7 @@ build_access_to_thisn (from, to, lc)
 {
   tree access = NULL_TREE;
 
-  while (from != to)
+  while (from != to && PURE_INNER_CLASS_TYPE_P (from))
     {
       if (!access)
         {
@@ -8513,8 +8568,8 @@ build_access_to_thisn (from, to, lc)
          access = make_qualified_primary (cn, access, lc);
        }
 
-      /* if FROM isn't an inter class, that's fine, we've done
-         enough. What we're looking for can be accessed from there. */
+      /* If FROM isn't an inner class, that's fine, we've done enough.
+         What we're looking for can be accessed from there.  */
       from = DECL_CONTEXT (TYPE_NAME (from));
       if (!from)
        break;
@@ -8935,8 +8990,7 @@ java_expand_classes ()
   java_layout_classes ();
   java_parse_abort_on_error ();
 
-  cur_ctxp = ctxp_for_generation;
-  for (; cur_ctxp; cur_ctxp = cur_ctxp->next)
+  for (cur_ctxp = ctxp_for_generation; cur_ctxp; cur_ctxp = cur_ctxp->next)
     {
       ctxp = cur_ctxp;
       input_filename = ctxp->filename;
@@ -8946,9 +9000,11 @@ java_expand_classes ()
     }
   input_filename = main_input_filename;
 
-  /* Find anonymous classes and expand their constructor, now they
-     have been fixed. */
-  for (cur_ctxp = ctxp_for_generation;  cur_ctxp;  cur_ctxp = cur_ctxp->next)
+
+  /* Find anonymous classes and expand their constructor. This extra pass is
+     neccessary because the constructor itself is only generated when the
+     method in which it is defined is expanded. */
+  for (cur_ctxp = ctxp_for_generation; cur_ctxp; cur_ctxp = cur_ctxp->next)
     {
       tree current;
       ctxp = cur_ctxp;
@@ -8965,7 +9021,7 @@ java_expand_classes ()
                      restore_line_number_status (1);
                      java_complete_expand_method (d);
                      restore_line_number_status (0);
-                     break;    /* We now there are no other ones */
+                     break;    /* There is only one constructor. */
                    }
                }
            }
@@ -8981,7 +9037,26 @@ java_expand_classes ()
     return;
 
   /* Now things are stable, go for generation of the class data. */
-  for (cur_ctxp = ctxp_for_generation;  cur_ctxp;  cur_ctxp = cur_ctxp->next)
+
+  /* We pessimistically marked all fields external until we knew
+     what set of classes we were planning to compile.  Now mark
+     those that will be generated locally as not external.  */
+  for (cur_ctxp = ctxp_for_generation; cur_ctxp; cur_ctxp = cur_ctxp->next)
+    {
+      tree current;
+      ctxp = cur_ctxp;
+      for (current = ctxp->class_list; current; current = TREE_CHAIN (current))
+       {
+         tree class = TREE_TYPE (current);
+         tree field;
+         for (field = TYPE_FIELDS (class); field ; field = TREE_CHAIN (field))
+           if (FIELD_STATIC (field))
+             DECL_EXTERNAL (field) = 0;
+       }
+    }
+
+  /* Compile the classes.  */
+  for (cur_ctxp = ctxp_for_generation; cur_ctxp; cur_ctxp = cur_ctxp->next)
     {
       tree current;
       ctxp = cur_ctxp;
@@ -10466,9 +10541,9 @@ patch_method_invocation (patch, primary, where, from_super,
       /* Generate the code used to initialize fields declared with an
         initialization statement and build a compound statement along
         with the super constructor invocation. */
+      CAN_COMPLETE_NORMALLY (patch) = 1;
       patch = build (COMPOUND_EXPR, void_type_node, patch,
                     java_complete_tree (finit_call));
-      CAN_COMPLETE_NORMALLY (patch) = 1;
     }
   return patch;
 }
@@ -10599,7 +10674,6 @@ patch_invoke (patch, method, args)
     func = method;
   else
     {
-      tree signature = build_java_signature (TREE_TYPE (method));
       switch (invocation_mode (method, CALL_USING_SUPER (patch)))
        {
        case INVOKE_VIRTUAL:
@@ -10624,9 +10698,12 @@ patch_invoke (patch, method, args)
 
        case INVOKE_SUPER:
        case INVOKE_STATIC:
-         func = build_known_method_ref (method, TREE_TYPE (method),
-                                        DECL_CONTEXT (method),
-                                        signature, args);
+         {
+           tree signature = build_java_signature (TREE_TYPE (method));
+           func = build_known_method_ref (method, TREE_TYPE (method),
+                                          DECL_CONTEXT (method),
+                                          signature, args);
+         }
          break;
 
        case INVOKE_INTERFACE:
@@ -10645,6 +10722,7 @@ patch_invoke (patch, method, args)
   TREE_TYPE (patch) = TREE_TYPE (TREE_TYPE (method));
   TREE_OPERAND (patch, 0) = func;
   TREE_OPERAND (patch, 1) = args;
+  patch = check_for_builtin (method, patch);
   original_call = patch;
 
   /* We're processing a `new TYPE ()' form. New is called and its
@@ -10780,7 +10858,14 @@ lookup_method_invoke (lc, cl, class, name, arg_list)
      know the arguments' types. */
 
   if (lc && ANONYMOUS_CLASS_P (class))
-    craft_constructor (TYPE_NAME (class), atl);
+    {
+      tree saved_current_class;
+      tree mdecl = craft_constructor (TYPE_NAME (class), atl);
+      saved_current_class = current_class;
+      current_class = class;
+      fix_constructors (mdecl);
+      current_class = saved_current_class;
+    }
 
   /* Find all candidates and then refine the list, searching for the
      most specific method. */
@@ -11201,11 +11286,17 @@ qualify_ambiguous_name (id)
 
     else if (code == INTEGER_CST)
       name = qual_wfl;
-    
+
     else if (code == CONVERT_EXPR &&
             TREE_CODE (TREE_OPERAND (qual_wfl, 0)) == EXPR_WITH_FILE_LOCATION)
       name = TREE_OPERAND (qual_wfl, 0);
-    
+
+    else if (code == CONVERT_EXPR
+            && TREE_CODE (TREE_OPERAND (qual_wfl, 0)) == CALL_EXPR
+            && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (qual_wfl, 0), 0))
+                == EXPR_WITH_FILE_LOCATION))
+      name = TREE_OPERAND (TREE_OPERAND (qual_wfl, 0), 0);
+
     else if ((code == ARRAY_REF || code == CALL_EXPR || code == MODIFY_EXPR) &&
             TREE_CODE (TREE_OPERAND (qual_wfl, 0)) == EXPR_WITH_FILE_LOCATION)
       name = EXPR_WFL_NODE (TREE_OPERAND (qual_wfl, 0));
@@ -12029,6 +12120,8 @@ java_complete_lhs (node)
       else
        {
          node = patch_assignment (node, wfl_op1);
+         if (node == error_mark_node)
+           return error_mark_node;
          /* Reorganize the tree if necessary. */
          if (flag && (!JREFERENCE_TYPE_P (TREE_TYPE (node)) 
                       || JSTRING_P (TREE_TYPE (node))))
@@ -12534,9 +12627,8 @@ patch_assignment (node, wfl_op1)
     {
       lhs_type = TREE_TYPE (lvalue);
     }
-  /* Or Lhs can be a array access. Should that be lvalue ? FIXME +
-     comment on reason why */
-  else if (TREE_CODE (wfl_op1) == ARRAY_REF)
+  /* Or Lhs can be an array access. */
+  else if (TREE_CODE (lvalue) == ARRAY_REF)
     {
       lhs_type = TREE_TYPE (lvalue);
       lvalue_from_array = 1;
@@ -12638,80 +12730,32 @@ patch_assignment (node, wfl_op1)
       && lvalue_from_array 
       && JREFERENCE_TYPE_P (TYPE_ARRAY_ELEMENT (lhs_type)))
     {
-      tree check;
-      tree base = lvalue;
+      tree array, store_check, base, index_expr;
+      
+      /* Save RHS so that it doesn't get re-evaluated by the store check. */ 
+      new_rhs = save_expr (new_rhs);
 
-      /* We need to retrieve the right argument for
-         _Jv_CheckArrayStore.  This is somewhat complicated by bounds
-         and null pointer checks, both of which wrap the operand in
-         one layer of COMPOUND_EXPR.  */
-      if (TREE_CODE (lvalue) == COMPOUND_EXPR)
-       base = TREE_OPERAND (lvalue, 0);
-      else
+      /* Get the INDIRECT_REF. */
+      array = TREE_OPERAND (TREE_OPERAND (lvalue, 0), 0);
+      /* Get the array pointer expr. */
+      array = TREE_OPERAND (array, 0);
+      store_check = build_java_arraystore_check (array, new_rhs);
+      
+      index_expr = TREE_OPERAND (lvalue, 1);
+      
+      if (TREE_CODE (index_expr) == COMPOUND_EXPR)
        {
-          tree op = TREE_OPERAND (base, 0);
-         
-          /* We can have a SAVE_EXPR here when doing String +=.  */
-          if (TREE_CODE (op) == SAVE_EXPR)
-            op = TREE_OPERAND (op, 0);
-         /* We can have a COMPOUND_EXPR here when doing bounds check. */
-         if (TREE_CODE (op) == COMPOUND_EXPR)
-           op = TREE_OPERAND (op, 1);
-         base = TREE_OPERAND (op, 0);
-         /* Strip the last PLUS_EXPR to obtain the base. */
-         if (TREE_CODE (base) == PLUS_EXPR)
-           base = TREE_OPERAND (base, 0);
-       }
-
-      /* Build the invocation of _Jv_CheckArrayStore */
-      new_rhs = save_expr (new_rhs);
-      check = build (CALL_EXPR, void_type_node,
-                    build_address_of (soft_checkarraystore_node),
-                    tree_cons (NULL_TREE, base,
-                               build_tree_list (NULL_TREE, new_rhs)),
-                    NULL_TREE);
-      TREE_SIDE_EFFECTS (check) = 1;
-
-      /* We have to decide on an insertion point */
-      if (TREE_CODE (lvalue) == COMPOUND_EXPR)
-       {
-         tree t;
-         if (flag_bounds_check)
-           {
-             t = TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (lvalue, 1), 0), 0);
-             TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (lvalue, 1), 0), 0) =
-               build (COMPOUND_EXPR, void_type_node, t, check);
-           }
-         else
-           TREE_OPERAND (lvalue, 1) = build (COMPOUND_EXPR, lhs_type,
-                                             check, TREE_OPERAND (lvalue, 1));
+         /* A COMPOUND_EXPR here is a bounds check. The bounds check must 
+            happen before the store check, so prepare to insert the store
+            check within the second operand of the existing COMPOUND_EXPR. */
+         base = index_expr;
        }
-      else if (flag_bounds_check)
-       {
-          tree hook = lvalue;
-          tree compound = TREE_OPERAND (lvalue, 0);
-          tree bound_check, new_compound;
-
-          if (TREE_CODE (compound) == SAVE_EXPR)
-            {
-              compound = TREE_OPERAND (compound, 0);
-              hook = TREE_OPERAND (hook, 0);
-            }
-
-          /* Find the array bound check, hook the original array access. */
-          bound_check = TREE_OPERAND (compound, 0);
-          TREE_OPERAND (hook, 0) = TREE_OPERAND (compound, 1);
-
-         /* Make sure the bound check will happen before the store check */
-          new_compound =
-            build (COMPOUND_EXPR, void_type_node, bound_check, check);
-
-          /* Re-assemble the augmented array access. */
-          lvalue = build (COMPOUND_EXPR, TREE_TYPE (lvalue),
-                         new_compound, lvalue);
-        }
       else
-        lvalue = build (COMPOUND_EXPR, TREE_TYPE (lvalue), check, lvalue);
+        base = lvalue;
+      
+      index_expr = TREE_OPERAND (base, 1);
+      TREE_OPERAND (base, 1) = build (COMPOUND_EXPR, TREE_TYPE (index_expr), 
+                                     store_check, index_expr);
     }
 
   /* Final locals can be used as case values in switch
@@ -12780,12 +12824,6 @@ try_builtin_assignconv (wfl_op1, lhs_type, rhs)
        new_rhs = rhs;
     }
 
-  /* Zero accepted everywhere */
-  else if (TREE_CODE (rhs) == INTEGER_CST 
-      && TREE_INT_CST_HIGH (rhs) == 0 && TREE_INT_CST_LOW (rhs) == 0
-      && JPRIMITIVE_TYPE_P (rhs_type))
-    new_rhs = convert (lhs_type, rhs);
-
   /* 5.1.1 Try Identity Conversion,
      5.1.2 Try Widening Primitive Conversion */
   else if (valid_builtin_assignconv_identity_widening_p (lhs_type, rhs_type))
@@ -15157,8 +15195,8 @@ patch_switch_statement (node)
                = EXPR_WFL_LINECOL (TREE_PURPOSE (iter));
              /* The case_label_list is in reverse order, so print the
                 outer label first.  */
-             parse_error_context (wfl_operator, "duplicate case label: `%d'",
-                                  subval);
+             parse_error_context (wfl_operator, "duplicate case label: `"
+                                  HOST_WIDE_INT_PRINT_DEC "'", subval);
              EXPR_WFL_LINECOL (wfl_operator)
                = EXPR_WFL_LINECOL (TREE_PURPOSE (subiter));
              parse_error_context (wfl_operator, "original label is here");
@@ -15974,7 +16012,7 @@ void
 init_src_parse ()
 {
   /* Register roots with the garbage collector.  */
-  ggc_add_tree_root (src_parse_roots, sizeof (src_parse_roots) / sizeof(tree));
+  ggc_add_tree_root (src_parse_roots, ARRAY_SIZE (src_parse_roots));
 }
 
 \f