OSDN Git Service

2000-07-21 Alexandre Petit-Bianco <apbianco@cygnus.com>
[pf3gnuchains/gcc-fork.git] / gcc / java / parse.y
index da0a219..0aded25 100644 (file)
@@ -81,7 +81,7 @@ static tree  find_field PARAMS ((tree, tree));
 static tree lookup_field_wrapper PARAMS ((tree, tree));
 static int   duplicate_declaration_error_p PARAMS ((tree, tree, tree));
 static void  register_fields PARAMS ((int, tree, tree));
-static tree parser_qualified_classname PARAMS ((int, tree));
+static tree parser_qualified_classname PARAMS ((tree));
 static int  parser_check_super PARAMS ((tree, tree, tree));
 static int  parser_check_super_interface PARAMS ((tree, tree, tree));
 static void check_modifiers_consistency PARAMS ((int));
@@ -642,6 +642,11 @@ name:
 
 simple_name:
        identifier              /* Default rule */
+       {
+         if (strchr (IDENTIFIER_POINTER (EXPR_WFL_NODE ($$)), '$'))
+           parse_error_context ($$, "Invalid type name `%s'",
+                                IDENTIFIER_POINTER (EXPR_WFL_NODE ($$)));
+       }
 ;
 
 qualified_name:
@@ -3471,8 +3476,8 @@ find_as_inner_class (enclosing, name, cl)
     {
       tree acc = NULL_TREE, decl = NULL_TREE, ptr;
 
-      for(qual = EXPR_WFL_QUALIFICATION (cl); qual && !decl; 
-         qual = TREE_CHAIN (qual))
+      for (qual = EXPR_WFL_QUALIFICATION (cl); qual && !decl; 
+          qual = TREE_CHAIN (qual))
        {
          acc = merge_qualified_name (acc, 
                                      EXPR_WFL_NODE (TREE_PURPOSE (qual)));
@@ -3492,7 +3497,18 @@ find_as_inner_class (enclosing, name, cl)
   else
     qual = build_tree_list (build_expr_wfl (name, NULL, 0, 0), NULL_TREE);
 
-  return find_as_inner_class_do (qual, enclosing);
+  if (!(to_return = find_as_inner_class_do (qual, enclosing)))
+    {
+      /* It might be the case that the enclosing class was loaded as
+        bytecode, in which case it will be missing the
+        DECL_INNER_CLASS_LIST. We build a fully qualified internal
+        innerclass name and we try to load it. */
+      tree fqin = identifier_subst (name, "", '.', '$', "");
+      tree ptr;
+      BUILD_PTR_FROM_NAME (ptr, fqin);
+      to_return = resolve_class (NULL_TREE, ptr, NULL_TREE, cl);
+    }
+  return to_return;
 }
 
 /* We go inside the list of sub classes and try to find a way
@@ -3649,7 +3665,7 @@ create_interface (flags, id, super)
      tree id, super;
 {
   tree raw_name = EXPR_WFL_NODE (id);
-  tree q_name = parser_qualified_classname (flags & ACC_STATIC, raw_name);
+  tree q_name = parser_qualified_classname (raw_name);
   tree decl = IDENTIFIER_CLASS_VALUE (q_name);
 
   EXPR_WFL_NODE (id) = q_name; /* Keep source location, even if refined. */
@@ -3784,7 +3800,7 @@ create_class (flags, id, super, interfaces)
   tree class_id, decl;
   tree super_decl_type;
 
-  class_id = parser_qualified_classname (0, raw_name);
+  class_id = parser_qualified_classname (raw_name);
   decl = IDENTIFIER_CLASS_VALUE (class_id);
   EXPR_WFL_NODE (id) = class_id;
 
@@ -3840,13 +3856,6 @@ create_class (flags, id, super, interfaces)
   CLASS_COMPLETE_P (decl) = 1;
   add_superinterfaces (decl, interfaces);
 
-  /* If the class is a top level inner class, install an alias. */
-  if (INNER_CLASS_DECL_P (decl) && CLASS_STATIC (decl))
-    {
-      tree alias = parser_qualified_classname (1, raw_name);
-      IDENTIFIER_GLOBAL_VALUE (alias) = decl;
-    }
-
   /* Add the private this$<n> field, Replicate final locals still in
      scope as private final fields mangled like val$<local_name>.
      This doesn't not occur for top level (static) inner classes. */
@@ -4297,7 +4306,7 @@ method_header (flags, type, mdecl, throws)
          && !CLASS_INTERFACE (TYPE_NAME (this_class)))
        parse_error_context 
          (id, "Class `%s' must be declared abstract to define abstract method `%s'", 
-          IDENTIFIER_POINTER (DECL_NAME (ctxp->current_parsed_class)),
+          IDENTIFIER_POINTER (DECL_NAME (GET_CPC ())),
           IDENTIFIER_POINTER (EXPR_WFL_NODE (id)));
     }
 
@@ -4786,14 +4795,12 @@ unresolved_type_p (wfl, returned)
    qualification from the current package definition. */
 
 static tree
-parser_qualified_classname (is_static, name)
-     int is_static;
+parser_qualified_classname (name)
      tree name;
 {
   tree nested_class_name;
 
-  if (!is_static 
-      && (nested_class_name = maybe_make_nested_class_name (name)))
+  if ((nested_class_name = maybe_make_nested_class_name (name)))
     return nested_class_name;
 
   if (ctxp->package)
@@ -5208,7 +5215,8 @@ jdep_resolve_class (dep)
   if (!decl)
     complete_class_report_errors (dep);
 
-  check_inner_class_access (decl, JDEP_ENCLOSING (dep), JDEP_WFL (dep));
+  if (PURE_INNER_CLASS_DECL_P (decl))
+    check_inner_class_access (decl, JDEP_ENCLOSING (dep), JDEP_WFL (dep));
   return decl;
 }
 
@@ -5447,6 +5455,15 @@ do_resolve_class (enclosing, class_type, decl, cl)
       if ((new_class_decl = find_as_inner_class (enclosing, class_type, cl)))
         return new_class_decl;
 
+      /* Explore enclosing contexts. */
+      while (INNER_CLASS_DECL_P (enclosing))
+       {
+         enclosing = DECL_CONTEXT (enclosing);
+         if ((new_class_decl = find_as_inner_class (enclosing, 
+                                                    class_type, cl)))
+           return new_class_decl;
+       }
+
       /* Now go to the upper classes, bail out if necessary. */
       enclosing = CLASSTYPE_SUPER (TREE_TYPE (enclosing));
       if (!enclosing || enclosing == object_type_node)
@@ -5459,9 +5476,7 @@ do_resolve_class (enclosing, class_type, decl, cl)
        }
 
       if (TREE_CODE (enclosing) == IDENTIFIER_NODE)
-       {
-         BUILD_PTR_FROM_NAME (name, enclosing);
-       }
+       BUILD_PTR_FROM_NAME (name, enclosing);
       else
        name = enclosing;
       enclosing = do_resolve_class (NULL, name, NULL, NULL);
@@ -6783,22 +6798,37 @@ lookup_package_type (name, from)
 }
 
 static void
-check_inner_class_access (decl, enclosing_type, cl)
-     tree decl, enclosing_type, cl;
+check_inner_class_access (decl, enclosing_decl, cl)
+     tree decl, enclosing_decl, cl;
 {
+  int access = 0;
+
   /* We don't issue an error message when CL is null. CL can be null
-     as a result of processing a JDEP crafted by
-     source_start_java_method for the purpose of patching its parm
-     decl. But the error would have been already trapped when fixing
-     the method's signature. */
-  if (!(cl && PURE_INNER_CLASS_DECL_P (decl) && CLASS_PRIVATE (decl))
-      || (PURE_INNER_CLASS_DECL_P (enclosing_type)
-         && common_enclosing_context_p (TREE_TYPE (enclosing_type), 
-                                         TREE_TYPE (decl)))
-      || enclosing_context_p (TREE_TYPE (enclosing_type), TREE_TYPE (decl)))
+     as a result of processing a JDEP crafted by source_start_java_method
+     for the purpose of patching its parm decl. But the error would
+     have been already trapped when fixing the method's signature.
+     DECL can also be NULL in case of earlier errors. */
+  if (!decl || !cl)
+    return;
+
+  /* We grant access to private and protected inner classes if the
+     location from where we're trying to access DECL is an enclosing
+     context for DECL or if both have a common enclosing context. */
+  if (CLASS_PRIVATE (decl))
+    access = 1;
+  if (CLASS_PROTECTED (decl))
+    access = 2;
+  if (!access)
+    return;
+      
+  if (common_enclosing_context_p (TREE_TYPE (enclosing_decl),
+                                 TREE_TYPE (decl))
+      || enclosing_context_p (TREE_TYPE (enclosing_decl),
+                             TREE_TYPE (decl)))
     return;
 
-  parse_error_context (cl, "Can't access nested %s %s. Only public classes and interfaces in other packages can be accessed",
+  parse_error_context (cl, "Can't access %s nested %s %s. Only public classes and interfaces in other packages can be accessed",
+                      (access == 1 ? "private" : "protected"),
                       (CLASS_INTERFACE (decl) ? "interface" : "class"),
                       lang_printable_name (decl, 0));
 }
@@ -7461,7 +7491,7 @@ maybe_generate_pre_expand_clinit (class_type)
       /* We build the assignment expression that will initialize the
         field to its value. There are strict rules on static
         initializers (8.5). FIXME */
-      if (TREE_CODE (stmt) != BLOCK)
+      if (TREE_CODE (stmt) != BLOCK && stmt != empty_stmt_node)
        stmt = build_debugable_stmt (EXPR_WFL_LINECOL (stmt), stmt);
       java_method_add_stmt (mdecl, stmt);
     }
@@ -8749,10 +8779,13 @@ resolve_field_access (qual_wfl, field_decl, field_type)
       if (!type_found)
        type_found = DECL_CONTEXT (decl);
       is_static = JDECL_P (decl) && FIELD_STATIC (decl);
-      if (FIELD_FINAL (decl) 
+      if (FIELD_FINAL (decl) && FIELD_STATIC (decl)
          && JPRIMITIVE_TYPE_P (TREE_TYPE (decl))
          && DECL_INITIAL (decl))
        {
+         /* When called on a FIELD_DECL of the right (primitive)
+            type, java_complete_tree will try to substitue the decl
+            for it's initial value. */
          field_ref = java_complete_tree (decl);
          static_final_found = 1;
        }
@@ -8998,9 +9031,19 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
              *where_found = decl = current_this;
              *type_found = type = QUAL_DECL_TYPE (decl);
            }
-         /* We're trying to access the this from somewhere else... */
+         /* We're trying to access the this from somewhere else. Make sure
+            it's allowed before doing so. */
          else
            {
+             if (!enclosing_context_p (type, current_class))
+               {
+                 char *p  = xstrdup (lang_printable_name (type, 0));
+                 parse_error_context (qual_wfl, "Can't use variable `%s.this': type `%s' isn't an outer type of type `%s'", 
+                                      p, p, 
+                                      lang_printable_name (current_class, 0));
+                 free (p);
+                 return 1;
+               }
              *where_found = decl = build_current_thisn (type);
              from_qualified_this = 1;
            }
@@ -9166,6 +9209,24 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
              
              field_decl = lookup_field_wrapper (type,
                                                 EXPR_WFL_NODE (qual_wfl));
+
+             /* Maybe what we're trying to access an inner class. */
+             if (!field_decl)
+               {
+                 tree ptr, inner_decl;
+
+                 BUILD_PTR_FROM_NAME (ptr, EXPR_WFL_NODE (qual_wfl));
+                 inner_decl = resolve_class (decl, ptr, NULL_TREE, qual_wfl);
+                 if (inner_decl)
+                   {
+                     check_inner_class_access (inner_decl, decl, qual_wfl); 
+                     type = TREE_TYPE (inner_decl);
+                     decl = inner_decl;
+                     from_type = 1;
+                     continue;
+                   }
+               }
+
              if (field_decl == NULL_TREE)
                {
                  parse_error_context 
@@ -9280,7 +9341,8 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
 }
 
 /* 6.6 Qualified name and access control. Returns 1 if MEMBER (a decl)
-   can't be accessed from REFERENCE (a record type). */
+   can't be accessed from REFERENCE (a record type). This should be
+   used when decl is a field or a method.*/
 
 static int
 not_accessible_p (reference, member, from_super)
@@ -9289,6 +9351,10 @@ not_accessible_p (reference, member, from_super)
 {
   int access_flag = get_access_flags_from_decl (member);
 
+  /* Inner classes are processed by check_inner_class_access */
+  if (INNER_CLASS_TYPE_P (reference))
+    return 0;
+
   /* Access always granted for members declared public */
   if (access_flag & ACC_PUBLIC)
     return 0;
@@ -9307,7 +9373,17 @@ not_accessible_p (reference, member, from_super)
        return 0;
 
       /* Otherwise, access is granted if occuring from the class where
-        member is declared or a subclass of it */
+        member is declared or a subclass of it. Find the right
+        context to perform the check */
+      if (PURE_INNER_CLASS_TYPE_P (reference))
+        {
+          while (INNER_CLASS_TYPE_P (reference))
+            {
+              if (inherits_from_p (reference, DECL_CONTEXT (member)))
+                return 0;
+              reference = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (reference)));
+            }
+        }
       if (inherits_from_p (reference, DECL_CONTEXT (member)))
        return 0;
       return 1;
@@ -9315,8 +9391,7 @@ not_accessible_p (reference, member, from_super)
 
   /* Check access on private members. Access is granted only if it
      occurs from within the class in which it is declared. Exceptions
-     are accesses from inner-classes. This section is probably not
-     complete. FIXME */
+     are accesses from inner-classes. */
   if (access_flag & ACC_PRIVATE)
     return (current_class == DECL_CONTEXT (member) ? 0 : 
            (INNER_CLASS_TYPE_P (current_class) ? 0 : 1));
@@ -9640,7 +9715,7 @@ patch_method_invocation (patch, primary, where, is_static, ret_decl)
             
             maybe_use_access_method returns a non zero value if the
             this_arg has to be moved into the (then generated) stub
-            argument list. In the mean time, the selected function
+            argument list. In the meantime, the selected function
             might have be replaced by a generated stub. */
          if (maybe_use_access_method (is_super_init, &list, &this_arg))
            args = tree_cons (NULL_TREE, this_arg, args);
@@ -9808,7 +9883,7 @@ maybe_use_access_method (is_super_init, mdecl, this_arg)
   if (non_static_context)
     {
       ctx = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (current_class)));
-      if (ctx == DECL_CONTEXT (md))
+      if (inherits_from_p (ctx, DECL_CONTEXT (md)))
        {
          ta = build_current_thisn (current_class);
          ta = build_wfl_node (ta);
@@ -9819,7 +9894,7 @@ maybe_use_access_method (is_super_init, mdecl, this_arg)
          while (type)
            {
              maybe_build_thisn_access_method (type);
-             if (type == DECL_CONTEXT (md))
+             if (inherits_from_p (type, DECL_CONTEXT (md)))
                {
                  ta = build_access_to_thisn (ctx, type, 0);
                  break;
@@ -10123,7 +10198,7 @@ find_applicable_accessible_methods_list (lc, class, name, arglist)
     
   search_not_done++;
   hash_lookup (searched_classes, 
-              (const hash_table_key) class, TRUE, NULL);
+              (const hash_table_key) class, TRUE, NULL);
 
   if (!CLASS_LOADED_P (class) && !CLASS_FROM_SOURCE_P (class))
     {
@@ -10277,19 +10352,27 @@ find_most_specific_methods_list (list)
 
       for (method = list; method; method = TREE_CHAIN (method))
        {
+         tree method_v, current_v;
          /* Don't test a method against itself */
          if (method == current)
            continue;
 
-         /* Compare arguments and location where method where declared */
-         if (argument_types_convertible (TREE_VALUE (method), 
-                                         TREE_VALUE (current))
-             && valid_method_invocation_conversion_p 
-                  (DECL_CONTEXT (TREE_VALUE (method)), 
-                   DECL_CONTEXT (TREE_VALUE (current))))
+         method_v = TREE_VALUE (method);
+         current_v = TREE_VALUE (current);
+
+         /* Compare arguments and location where methods where declared */
+         if (argument_types_convertible (method_v, current_v))
            {
-             int v = ++DECL_SPECIFIC_COUNT (TREE_VALUE (current));
-             max = (v > max ? v : max);
+             if (valid_method_invocation_conversion_p 
+                 (DECL_CONTEXT (method_v), DECL_CONTEXT (current_v))
+                 || (INNER_CLASS_TYPE_P (DECL_CONTEXT (current_v))
+                     && enclosing_context_p (DECL_CONTEXT (method_v),
+                                             DECL_CONTEXT (current_v))))
+               {
+                 int v = (DECL_SPECIFIC_COUNT (current_v) += 
+                   (INNER_CLASS_TYPE_P (DECL_CONTEXT (current_v)) ? 2 : 1));
+                 max = (v > max ? v : max);
+               }
            }
        }
     }
@@ -10626,8 +10709,8 @@ java_complete_tree (node)
      tree node;
 {
   node = java_complete_lhs (node);
-  if (TREE_CODE (node) == VAR_DECL && FIELD_STATIC (node)
-      && FIELD_FINAL (node) && DECL_INITIAL (node) != NULL_TREE
+  if (JDECL_P (node) && FIELD_STATIC (node) && FIELD_FINAL (node) 
+      && DECL_INITIAL (node) != NULL_TREE
       && !flag_emit_xref)
     {
       tree value = DECL_INITIAL (node);
@@ -10917,7 +11000,7 @@ java_complete_lhs (node)
       else
        node = patch_switch_statement (node);
 
-      if (TREE_OPERAND (node, 0) == error_mark_node)
+      if (node == error_mark_node || TREE_OPERAND (node, 0) == error_mark_node)
        nn = error_mark_node;
       else
        {
@@ -11137,7 +11220,8 @@ java_complete_lhs (node)
                  (type == string_ptr_type_node && ! flag_emit_class_files))
                return empty_stmt_node;
            }
-         DECL_INITIAL (nn) = NULL_TREE;
+         if (! flag_emit_class_files)
+           DECL_INITIAL (nn) = NULL_TREE;
        }
       wfl_op2 = TREE_OPERAND (node, 1);
 
@@ -12077,7 +12161,6 @@ valid_ref_assignconv_cast_p (source, dest, cast)
       if (TYPE_CLASS_P (dest))
        return  (source == dest 
                 || inherits_from_p (source, dest)
-                || enclosing_context_p (source, dest)
                 || (cast && inherits_from_p (dest, source)));
       if (TYPE_INTERFACE_P (dest))
        {
@@ -13257,7 +13340,7 @@ resolve_type_during_patch (type)
 {
   if (unresolved_type_p (type, NULL))
     {
-      tree type_decl = resolve_no_layout (EXPR_WFL_NODE (type), NULL_TREE);
+      tree type_decl = resolve_no_layout (EXPR_WFL_NODE (type), type);
       if (!type_decl)
        {
          parse_error_context (type, 
@@ -14799,12 +14882,9 @@ fold_constant_for_init (node, context)
   tree op0, op1, val;
   enum tree_code code = TREE_CODE (node);
 
-  if (code == STRING_CST)
+  if (code == STRING_CST || code == INTEGER_CST || code == REAL_CST)
     return node;
 
-  if (code == INTEGER_CST || code == REAL_CST)
-    return convert (TREE_TYPE (context), node);
-
   switch (code)
     {
     case PLUS_EXPR: