OSDN Git Service

* config/rs6000/darwin.h (SUBTARGET_OVERRIDE_OPTIONS): Use %qs
[pf3gnuchains/gcc-fork.git] / gcc / java / verify.c
index aaf7e4d..fdc2721 100644 (file)
@@ -89,23 +89,23 @@ check_pending_block (tree target_label)
 
   if (current_subr == NULL_TREE)
     {
-      if (LABEL_IN_SUBR (target_label))
-       return "might transfer control into subroutine";
+/*       if (LABEL_IN_SUBR (target_label)) */
+/*     return "might transfer control into subroutine"; */
     }
   else
     {
       if (LABEL_IN_SUBR (target_label))
        {
-         if (LABEL_SUBR_START (target_label) != current_subr)
-           return "transfer out of subroutine";
+/*       if (LABEL_SUBR_START (target_label) != current_subr) */
+/*         return "transfer out of subroutine"; */
        }
       else if (! LABEL_VERIFIED (target_label))
        {
          LABEL_IN_SUBR (target_label) = 1;
          LABEL_SUBR_START (target_label) = current_subr;
        }
-      else
-       return "transfer out of subroutine";
+/*       else */
+/*     return "transfer out of subroutine"; */
     }
   return NULL;
 }
@@ -126,6 +126,54 @@ subroutine_nesting (tree label)
   return nesting;
 }
 
+static tree
+defer_merging (tree type1, tree type2)
+{
+  /* FIXME: This is just a placeholder until we replace the verifier
+     altogether.  We really need to ouput a type assertion for all of
+     the types, every time they are used.  */
+  return object_ptr_type_node;
+
+  if (TREE_CODE (type1) == POINTER_TYPE)
+    type1 = TREE_TYPE (type1);
+  if (TREE_CODE (type2) == POINTER_TYPE)
+    type2 = TREE_TYPE (type2);
+
+  if (TREE_CODE (type1) == RECORD_TYPE && TREE_CODE (type2) == RECORD_TYPE)
+    {
+      tree list = build_tree_list (type1, NULL_TREE);
+      list = tree_cons (type2, NULL_TREE, list);
+      return list;
+    }
+
+  if (TREE_CODE (type1) == TREE_LIST && TREE_CODE (type2) == TREE_LIST)
+    {
+      return chainon (copy_list (type1), copy_list (type2));
+    }
+
+  if (TREE_CODE (type1) == TREE_LIST && TREE_CODE (type2) == RECORD_TYPE)
+    {
+      tree tmp = type1;
+      do
+       {
+         if (TREE_PURPOSE (tmp) == type2)
+           return type1;
+         tmp = TREE_CHAIN (tmp);
+       }
+      while (tmp);
+
+      return tree_cons (type2, NULL_TREE, copy_list (type1));
+    }
+
+  if (TREE_CODE (type2) == TREE_LIST && TREE_CODE (type1) == RECORD_TYPE)
+    {
+      return defer_merging (type2, type1);
+    }
+
+  abort ();
+}
+
+
 /* Return the "merged" types of TYPE1 and TYPE2.
    If either is primitive, the other must match (after promotion to int).
    For reference types, return the common super-class.
@@ -138,7 +186,11 @@ merge_types (tree type1, tree type2)
     return type1;
   if (type1 == TYPE_UNKNOWN || type2 == TYPE_UNKNOWN
       || type1 == TYPE_RETURN_ADDR || type2 == TYPE_RETURN_ADDR)
-    return TYPE_UNKNOWN;
+    return TYPE_UNKNOWN;  
+
+  if (TREE_CODE (type1) == TREE_LIST || TREE_CODE (type2) == TREE_LIST)
+    return defer_merging (type1, type2);
+
   if (TREE_CODE (type1) == POINTER_TYPE && TREE_CODE (type2) == POINTER_TYPE)
     {
       int depth1, depth2;
@@ -153,6 +205,9 @@ merge_types (tree type1, tree type2)
       tt1 = TREE_TYPE (type1);
       tt2 = TREE_TYPE (type2);
 
+      if (TYPE_DUMMY (tt1) || TYPE_DUMMY (tt2))
+       return defer_merging (tt1, tt2);
+      
       /* If tt{1,2} haven't been properly loaded, now is a good time
          to do it. */
       if (!TYPE_SIZE (tt1))
@@ -193,31 +248,10 @@ merge_types (tree type1, tree type2)
          return object_ptr_type_node;
        }
 
-      if (CLASS_INTERFACE (TYPE_NAME (tt1)))
-       {
-         /* FIXME: should see if two interfaces have a common
-            superinterface.  */
-         if (CLASS_INTERFACE (TYPE_NAME (tt2)))
-           {
-             /* This is a kludge, but matches what Sun's verifier does.
-                It can be tricked, but is safe as long as type errors
-                (i.e. interface method calls) are caught at run-time. */
-             return object_ptr_type_node;
-           }
-         else
-           {
-             if (can_widen_reference_to (tt2, tt1))
-               return type1;
-             else
-               return object_ptr_type_node;
-           }
-       }
-      else if (CLASS_INTERFACE (TYPE_NAME (tt2)))
+      if (CLASS_INTERFACE (TYPE_NAME (tt1))
+         || (CLASS_INTERFACE (TYPE_NAME (tt2))))
        {
-         if (can_widen_reference_to (tt1, tt2))
-           return type2;
-         else
-           return object_ptr_type_node;
+         return object_ptr_type_node;
        }
 
       type1 = tt1;
@@ -675,6 +709,8 @@ verify_jvm_instructions (JCF* jcf, const unsigned char *byte_ops, long length)
          VERIFICATION_ERROR_WITH_INDEX
            ("invalid local variable index %d in load");
        tmp = type_map[index];
+       if (TREE_CODE (tmp) != TREE_LIST)
+         {
        if (tmp == TYPE_UNKNOWN)
          VERIFICATION_ERROR_WITH_INDEX
            ("loading local variable %d which has unknown type");
@@ -688,6 +724,7 @@ verify_jvm_instructions (JCF* jcf, const unsigned char *byte_ops, long length)
                : type != tmp))
          VERIFICATION_ERROR_WITH_INDEX
            ("loading local variable %d which has invalid type");
+         }
        PUSH_TYPE (tmp);
        goto note_used;
        case OPCODE_istore:  type = int_type_node;  goto general_store;
@@ -736,7 +773,7 @@ verify_jvm_instructions (JCF* jcf, const unsigned char *byte_ops, long length)
        prev_eh_ranges = NULL_EH_RANGE;
 
        /* Allocate decl for this variable now, so we get a temporary
-!         that survives the whole method. */
+          that survives the whole method. */
        find_local_variable (index, type, oldpc);
 
         if (TYPE_IS_WIDE (type))
@@ -1092,6 +1129,10 @@ verify_jvm_instructions (JCF* jcf, const unsigned char *byte_ops, long length)
            if (! CLASS_LOADED_P (self_type))
              load_class (self_type, 1);
 
+           if (TYPE_DUMMY (self_type) && op_code == OPCODE_invokeinterface)
+             /* Assume we are an interface.  */
+             CLASS_INTERFACE (TYPE_NAME (self_type)) = 1;
+
            self_is_interface = CLASS_INTERFACE (TYPE_NAME (self_type));
            method_name = COMPONENT_REF_NAME (&current_jcf->cpool, index);
            method_type = parse_signature_string ((const unsigned char *) IDENTIFIER_POINTER (sig),
@@ -1129,7 +1170,6 @@ verify_jvm_instructions (JCF* jcf, const unsigned char *byte_ops, long length)
                  if (!nargs || notZero)
                      VERIFICATION_ERROR 
                        ("invalid argument number in invokeinterface");
-
                  /* If we verify/resolve the constant pool, as we should,
                     this test (and the one just following) are redundant.  */
                  if (! self_is_interface)