]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
class.c (common_enclosing_context_p): New function.
authorAlexandre Petit-Bianco <apbianco@cygnus.com>
Thu, 1 Jun 2000 07:44:58 +0000 (07:44 +0000)
committerAlexandre Petit-Bianco <apbianco@gcc.gnu.org>
Thu, 1 Jun 2000 07:44:58 +0000 (00:44 -0700)
2000-04-24  Alexandre Petit-Bianco  <apbianco@cygnus.com>

* class.c (common_enclosing_context_p): New function.
* java-tree.h (common_enclosing_context_p): Added prototype.
* parse.h (INNER_ENCLOSING_SCOPE_CHECK): Relaxed test to allow
classes sharing an outer context with the current instance.
* parse.y (build_access_to_thisn): Fixed leading comment.
(verify_constructor_super): New local `supper_inner'. Skip
enclosing context argument in the case of inner class constructors.
(patch_method_invocation): Insert proper context as second
parameter to pure inner class constructor super invocations.

This fixes the Java PR #177.

From-SVN: r34332

gcc/java/ChangeLog
gcc/java/class.c
gcc/java/java-tree.h
gcc/java/parse.c
gcc/java/parse.h
gcc/java/parse.y

index 9fdc4f0ed5290dd311a6d45980547366df2c4266..7bd5521fa85c9871961792653f94781dd267e8ad 100644 (file)
@@ -200,6 +200,18 @@ Wed Apr 26 14:29:33 2000  Alexandre Petit-Bianco  <apbianco@cygnus.com>
 
        * parse.y (register_incomplete_type): Handle JDEP_ANONYMOUS.
 
+2000-04-24  Alexandre Petit-Bianco  <apbianco@cygnus.com>
+
+       * class.c (common_enclosing_context_p): New function.
+       * java-tree.h (common_enclosing_context_p): Added prototype.
+       * parse.h (INNER_ENCLOSING_SCOPE_CHECK): Relaxed test to allow
+       classes sharing an outer context with the current instance.
+       * parse.y (build_access_to_thisn): Fixed leading comment.
+       (verify_constructor_super): New local `supper_inner'. Skip
+       enclosing context argument in the case of inner class constructors.
+       (patch_method_invocation): Insert proper context as second
+       parameter to pure inner class constructor super invocations.
+
 Mon Apr 24 14:59:36 2000  Alexandre Petit-Bianco  <apbianco@cygnus.com>
 
        * parse.y (end_class_declaration): Reset the interface number
index 21232e7f2d2e41234534814232b3245a77f5067f..dcc544846d1ddb552c3333d6469f43957dd5ee2c 100644 (file)
@@ -486,6 +486,30 @@ enclosing_context_p (type1, type2)
   return 0;
 }
 
+/* Return 1 iff there exists a common enclosing context between TYPE1
+   and TYPE2.  */
+
+int common_enclosing_context_p (type1, type2)
+     tree type1, type2;
+{
+  if (!PURE_INNER_CLASS_TYPE_P (type1) && !PURE_INNER_CLASS_TYPE_P (type2))
+    return 0;
+  
+  for (type1 = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (type1))); type1; 
+       type1 = (PURE_INNER_CLASS_TYPE_P (type1) ?
+               TREE_TYPE (DECL_CONTEXT (TYPE_NAME (type1))) : NULL_TREE))
+    {
+      tree current;
+      for (current = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (type2))); current;
+          current = (PURE_INNER_CLASS_TYPE_P (current) ?
+                     TREE_TYPE (DECL_CONTEXT (TYPE_NAME (current))) : 
+                     NULL_TREE))
+       if (type1 == current)
+         return 1;
+    }
+  return 0;
+}
+
 static void
 add_interface_do (basetype_vec, interface_class, i)
      tree basetype_vec, interface_class;
index a05573f12e17e66e377ebcff765b9084ce296808..8f2b2c825031deb3f85e0e17b7ad379317860ebe 100644 (file)
@@ -696,6 +696,7 @@ extern void set_super_info PARAMS ((int, tree, tree, int));
 extern int get_access_flags_from_decl PARAMS ((tree));
 extern int interface_of_p PARAMS ((tree, tree));
 extern int inherits_from_p PARAMS ((tree, tree));
+extern int common_enclosing_context_p PARAMS ((tree, tree));
 extern int enclosing_context_p PARAMS ((tree, tree));
 extern void complete_start_java_method PARAMS ((tree));
 extern tree build_result_decl PARAMS ((tree));
index b01055a5e903e041d26e41ff23e953d8d0e33768..2f77d7497dbacfe05fe3e1a414d42f56457f2eb2 100644 (file)
@@ -10642,7 +10642,7 @@ build_access_to_thisn (from, to, lc)
 
 /* Build an access function to the this$<n> local to TYPE. NULL_TREE
    is returned if nothing needs to be generated. Otherwise, the method
-   generated, fully walked and a method decl is returned.  
+   generated and a method decl is returned.  
 
    NOTE: These generated methods should be declared in a class file
    attribute so that they can't be referred to directly.  */
@@ -10985,6 +10985,7 @@ verify_constructor_super (mdecl)
      tree mdecl;
 {
   tree class = CLASSTYPE_SUPER (current_class);
+  int super_inner = PURE_INNER_CLASS_TYPE_P (class);
   tree sdecl;
 
   if (!class)
@@ -10997,10 +10998,11 @@ verify_constructor_super (mdecl)
       for (sdecl = TYPE_METHODS (class); sdecl; sdecl = TREE_CHAIN (sdecl))
        if (DECL_CONSTRUCTOR_P (sdecl))
          {
-           tree arg_type;
-           for (arg_type = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (sdecl)));
-                arg_type != end_params_node && 
-                  mdecl_arg_type != end_params_node;
+           tree arg_type = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (sdecl)));
+           if (super_inner)
+             arg_type = TREE_CHAIN (arg_type);
+           for (; (arg_type != end_params_node 
+                   && mdecl_arg_type != end_params_node);
                 arg_type = TREE_CHAIN (arg_type), 
                 mdecl_arg_type = TREE_CHAIN (mdecl_arg_type))
              if (TREE_VALUE (arg_type) != TREE_VALUE (mdecl_arg_type))
@@ -11015,9 +11017,10 @@ verify_constructor_super (mdecl)
     {
       for (sdecl = TYPE_METHODS (class); sdecl; sdecl = TREE_CHAIN (sdecl))
        {
-         if (DECL_CONSTRUCTOR_P (sdecl)
-             && TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (sdecl))) 
-                == end_params_node)
+         tree arg = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (sdecl)));
+         if (super_inner)
+           arg = TREE_CHAIN (arg);
+         if (DECL_CONSTRUCTOR_P (sdecl) && arg == end_params_node)
            return 0;
        }
     }
@@ -12286,6 +12289,30 @@ patch_method_invocation (patch, primary, where, is_static, ret_decl)
        args = tree_cons (NULL_TREE, integer_zero_node, args);
     }
 
+  /* This handles the situation where a constructor invocation needs
+     to have an enclosing context passed as a second parameter (the
+     constructor is one of an inner class. We extract it from the
+     current function.  */
+  if (is_super_init && PURE_INNER_CLASS_TYPE_P (DECL_CONTEXT (list)))
+    {
+      tree enclosing_decl = DECL_CONTEXT (TYPE_NAME (current_class));
+      tree extra_arg;
+
+      if (ANONYMOUS_CLASS_P (current_class) || !DECL_CONTEXT (enclosing_decl))
+       {
+         extra_arg = DECL_FUNCTION_BODY (current_function_decl);
+         extra_arg = TREE_CHAIN (BLOCK_EXPR_DECLS (extra_arg));
+       }
+      else
+       {
+         tree dest = TREE_TYPE (DECL_CONTEXT (enclosing_decl));
+         extra_arg = 
+           build_access_to_thisn (TREE_TYPE (enclosing_decl), dest, 0);
+         extra_arg = java_complete_tree (extra_arg);
+       }
+      args = tree_cons (NULL_TREE, extra_arg, args);
+    }
+
   is_static_flag = METHOD_STATIC (list);
   if (! METHOD_STATIC (list) && this_arg != NULL_TREE)
     args = tree_cons (NULL_TREE, this_arg, args);
index 4ffee796e4158ca8ffb5c4855916f8baa8330ca0..24b0b9b82804d26e5036621497d86afb2b4923da 100644 (file)
@@ -822,15 +822,17 @@ struct parser_ctxt {
 
 /* Make sure that innerclass T sits in an appropriate enclosing
    context.  */
-#define INNER_ENCLOSING_SCOPE_CHECK(T)                                 \
-  (INNER_CLASS_TYPE_P ((T)) && !ANONYMOUS_CLASS_P ((T))                        \
-   && ((current_this                                                   \
-       /* We have a this and it's not the right one */                 \
-       && (DECL_CONTEXT (TYPE_NAME ((T)))                              \
-           != TYPE_NAME (TREE_TYPE (TREE_TYPE (current_this))))        \
-       && !inherits_from_p (TREE_TYPE (TREE_TYPE (current_this)),      \
-                            TREE_TYPE (DECL_CONTEXT (TYPE_NAME (T))))) \
-       /* We don't have a this. */                                     \
+#define INNER_ENCLOSING_SCOPE_CHECK(T)                                       \
+  (INNER_CLASS_TYPE_P ((T)) && !ANONYMOUS_CLASS_P ((T))                              \
+   && ((current_this                                                         \
+       /* We have a this and it's not the right one */                       \
+       && (DECL_CONTEXT (TYPE_NAME ((T)))                                    \
+           != TYPE_NAME (TREE_TYPE (TREE_TYPE (current_this))))              \
+       && !inherits_from_p (TREE_TYPE (TREE_TYPE (current_this)),            \
+                            TREE_TYPE (DECL_CONTEXT (TYPE_NAME (T))))        \
+        && !common_enclosing_context_p (TREE_TYPE (TREE_TYPE (current_this)), \
+                                       (T)))                                 \
+       /* We don't have a this. */                                           \
        || !current_this))
 
 /* Push macro. First argument to PUSH_CPC is a DECL_TYPE, second
index e14ec75ae9499521fb72ae3a0595230f3e930d49..83cd49edfd6ef616a14f40843ca0edccb9a37866 100644 (file)
@@ -7944,7 +7944,7 @@ build_access_to_thisn (from, to, lc)
 
 /* Build an access function to the this$<n> local to TYPE. NULL_TREE
    is returned if nothing needs to be generated. Otherwise, the method
-   generated, fully walked and a method decl is returned.  
+   generated and a method decl is returned.  
 
    NOTE: These generated methods should be declared in a class file
    attribute so that they can't be referred to directly.  */
@@ -8287,6 +8287,7 @@ verify_constructor_super (mdecl)
      tree mdecl;
 {
   tree class = CLASSTYPE_SUPER (current_class);
+  int super_inner = PURE_INNER_CLASS_TYPE_P (class);
   tree sdecl;
 
   if (!class)
@@ -8299,10 +8300,11 @@ verify_constructor_super (mdecl)
       for (sdecl = TYPE_METHODS (class); sdecl; sdecl = TREE_CHAIN (sdecl))
        if (DECL_CONSTRUCTOR_P (sdecl))
          {
-           tree arg_type;
-           for (arg_type = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (sdecl)));
-                arg_type != end_params_node && 
-                  mdecl_arg_type != end_params_node;
+           tree arg_type = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (sdecl)));
+           if (super_inner)
+             arg_type = TREE_CHAIN (arg_type);
+           for (; (arg_type != end_params_node 
+                   && mdecl_arg_type != end_params_node);
                 arg_type = TREE_CHAIN (arg_type), 
                 mdecl_arg_type = TREE_CHAIN (mdecl_arg_type))
              if (TREE_VALUE (arg_type) != TREE_VALUE (mdecl_arg_type))
@@ -8317,9 +8319,10 @@ verify_constructor_super (mdecl)
     {
       for (sdecl = TYPE_METHODS (class); sdecl; sdecl = TREE_CHAIN (sdecl))
        {
-         if (DECL_CONSTRUCTOR_P (sdecl)
-             && TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (sdecl))) 
-                == end_params_node)
+         tree arg = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (sdecl)));
+         if (super_inner)
+           arg = TREE_CHAIN (arg);
+         if (DECL_CONSTRUCTOR_P (sdecl) && arg == end_params_node)
            return 0;
        }
     }
@@ -9588,6 +9591,30 @@ patch_method_invocation (patch, primary, where, is_static, ret_decl)
        args = tree_cons (NULL_TREE, integer_zero_node, args);
     }
 
+  /* This handles the situation where a constructor invocation needs
+     to have an enclosing context passed as a second parameter (the
+     constructor is one of an inner class. We extract it from the
+     current function.  */
+  if (is_super_init && PURE_INNER_CLASS_TYPE_P (DECL_CONTEXT (list)))
+    {
+      tree enclosing_decl = DECL_CONTEXT (TYPE_NAME (current_class));
+      tree extra_arg;
+
+      if (ANONYMOUS_CLASS_P (current_class) || !DECL_CONTEXT (enclosing_decl))
+       {
+         extra_arg = DECL_FUNCTION_BODY (current_function_decl);
+         extra_arg = TREE_CHAIN (BLOCK_EXPR_DECLS (extra_arg));
+       }
+      else
+       {
+         tree dest = TREE_TYPE (DECL_CONTEXT (enclosing_decl));
+         extra_arg = 
+           build_access_to_thisn (TREE_TYPE (enclosing_decl), dest, 0);
+         extra_arg = java_complete_tree (extra_arg);
+       }
+      args = tree_cons (NULL_TREE, extra_arg, args);
+    }
+
   is_static_flag = METHOD_STATIC (list);
   if (! METHOD_STATIC (list) && this_arg != NULL_TREE)
     args = tree_cons (NULL_TREE, this_arg, args);