OSDN Git Service

(struct function): Make frame_offset be HOST_WIDE_INT.
[pf3gnuchains/gcc-fork.git] / gcc / cp / method.c
index 8d1bba7..c7e3a87 100644 (file)
@@ -62,10 +62,6 @@ static char *scratch_firstobj;
 # define OB_FINISH() (obstack_1grow (&scratch_obstack, '\0'))
 # define OB_LAST() (obstack_next_free (&scratch_obstack)[-1])
 
-#ifdef NO_AUTO_OVERLOAD
-int is_overloaded ();
-#endif
-
 void
 init_method ()
 {
@@ -149,6 +145,7 @@ do_inline_function_hair (type, friend_list)
 \f
 /* Report an argument type mismatch between the best declared function
    we could find and the current argument list that we have.  */
+
 void
 report_type_mismatch (cp, parmtypes, name_kind)
      struct candidate *cp;
@@ -257,6 +254,7 @@ static int nofold;
   } while (0)
 
 /* Code to concatenate an asciified integer to a string.  */
+
 static
 #ifdef __GNUC__
 __inline
@@ -351,7 +349,8 @@ build_overload_nested_name (decl)
     build_overload_identifier (decl);
 }
 
-/* Encoding for an INTEGER_CST value. */
+/* Encoding for an INTEGER_CST value.  */
+
 static void
 build_overload_int (value)
      tree value;
@@ -366,7 +365,7 @@ build_overload_int (value)
        OB_PUTC ('_');
       return;
     }
-  else if (current_template_parms
+  else if (processing_template_decl
           && TREE_CODE (value) != INTEGER_CST)
     /* We don't ever want this output, but it's inconvenient not to
        be able to build the string.  This should cause assembler
@@ -379,7 +378,7 @@ build_overload_int (value)
     }
 
   my_friendly_assert (TREE_CODE (value) == INTEGER_CST, 243);
-  if (TYPE_PRECISION (value) == 2 * HOST_BITS_PER_WIDE_INT)
+  if (TYPE_PRECISION (TREE_TYPE (value)) == 2 * HOST_BITS_PER_WIDE_INT)
     {
       if (tree_int_cst_lt (value, integer_zero_node))
        {
@@ -495,7 +494,7 @@ build_overload_value (type, value)
        {
          if (TREE_CODE (value) == CONSTRUCTOR)
            {
-             /* This is dangerous code, crack built up pointer to members. */
+             /* This is dangerous code, crack built up pointer to members.  */
              tree args = CONSTRUCTOR_ELTS (value);
              tree a1 = TREE_VALUE (args);
              tree a2 = TREE_VALUE (TREE_CHAIN (args));
@@ -667,7 +666,14 @@ build_overload_name (parmtypes, begin, end)
 
          if (TREE_USED (parmtype))
            {
+#if 0
+             /* We can turn this on at some point when we want
+                improved symbol mangling.  */
+             nrepeats++;
+#else
+             /* This is bug compatible with 2.7.x  */
              flush_repeats (parmtype);
+#endif
              goto next;
            }
 
@@ -872,7 +878,7 @@ build_overload_name (parmtypes, begin, end)
              {
                tree context = name;
 
-               /* If DECL_ASSEMBLER_NAME has been set properly, use it. */
+               /* If DECL_ASSEMBLER_NAME has been set properly, use it.  */
                if (DECL_ASSEMBLER_NAME (context) != DECL_NAME (context))
                  {
                    OB_PUTID (DECL_ASSEMBLER_NAME (context));
@@ -942,7 +948,7 @@ build_overload_name (parmtypes, begin, end)
       if (nrepeats)
        flush_repeats (typevec[maxtype-1]);
 
-      /* To get here, parms must end with `...'. */
+      /* To get here, parms must end with `...'.  */
       OB_PUTC ('e');
     }
 
@@ -970,6 +976,7 @@ build_static_name (basetype, name)
    FOR_METHOD is 1 if this overload is being performed
    for a method, rather than a function type.  It is 2 if
    this overload is being performed for a constructor.  */
+
 tree
 build_decl_overload (dname, parms, for_method)
      tree dname;
@@ -1054,6 +1061,7 @@ build_decl_overload (dname, parms, for_method)
 }
 
 /* Build an overload name for the type expression TYPE.  */
+
 tree
 build_typename_overload (type)
      tree type;
@@ -1085,54 +1093,17 @@ build_overload_with_type (name, type)
   return get_identifier (obstack_base (&scratch_obstack));
 }
 
-/* Top-level interface to explicit overload requests. Allow NAME
-   to be overloaded. Error if NAME is already declared for the current
-   scope. Warning if function is redundantly overloaded. */
-
-void
-declare_overloaded (name)
-     tree name;
-{
-#ifdef NO_AUTO_OVERLOAD
-  if (is_overloaded (name))
-    warning ("function `%s' already declared overloaded",
-            IDENTIFIER_POINTER (name));
-  else if (IDENTIFIER_GLOBAL_VALUE (name))
-    error ("overloading function `%s' that is already defined",
-          IDENTIFIER_POINTER (name));
-  else
-    {
-      TREE_OVERLOADED (name) = 1;
-      IDENTIFIER_GLOBAL_VALUE (name) = build_tree_list (name, NULL_TREE);
-      TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (name)) = unknown_type_node;
-    }
-#else
-  if (current_lang_name == lang_name_cplusplus)
-    {
-      if (0)
-       warning ("functions are implicitly overloaded in C++");
-    }
-  else if (current_lang_name == lang_name_c)
-    error ("overloading function `%s' cannot be done in C language context");
-  else
-    my_friendly_abort (76);
-#endif
-}
-
-#ifdef NO_AUTO_OVERLOAD
-/* Check to see if NAME is overloaded. For first approximation,
-   check to see if its TREE_OVERLOADED is set.  This is used on
-   IDENTIFIER nodes.  */
-int
-is_overloaded (name)
-     tree name;
+tree
+get_id_2 (name, name2)
+     char *name;
+     tree name2;
 {
-  /* @@ */
-  return (TREE_OVERLOADED (name)
-         && (! IDENTIFIER_CLASS_VALUE (name) || current_class_type == 0)
-         && ! IDENTIFIER_LOCAL_VALUE (name));
+  OB_INIT ();
+  OB_PUTCP (name);
+  OB_PUTID (name2);
+  OB_FINISH ();
+  return get_identifier (obstack_base (&scratch_obstack));
 }
-#endif
 \f
 /* Given a tree_code CODE, and some arguments (at least one),
    attempt to use an overloaded operator on the arguments.
@@ -1171,6 +1142,9 @@ build_opfncall (code, flags, xarg1, xarg2, arg3)
   int try_second;
   int binary_is_unary;
 
+  if (flag_ansi_overloading)
+    return build_new_op (code, flags, xarg1, xarg2, arg3);
+
   if (xarg1 == error_mark_node)
     return error_mark_node;
 
@@ -1217,8 +1191,7 @@ build_opfncall (code, flags, xarg1, xarg2, arg3)
        tree args = tree_cons (NULL_TREE, xarg2, arg3);
        fnname = ansi_opname[(int) code];
        if (flags & LOOKUP_GLOBAL)
-         return build_overload_call (fnname, args, flags & LOOKUP_COMPLAIN,
-                                     (struct candidate *)0);
+         return build_overload_call (fnname, args, flags & LOOKUP_COMPLAIN);
 
        rval = build_method_call
          (build_indirect_ref (build1 (NOP_EXPR, xarg1, error_mark_node),
@@ -1242,8 +1215,7 @@ build_opfncall (code, flags, xarg1, xarg2, arg3)
        if (flags & LOOKUP_GLOBAL)
          return build_overload_call (fnname,
                                      build_tree_list (NULL_TREE, xarg1),
-                                     flags & LOOKUP_COMPLAIN,
-                                     (struct candidate *)0);
+                                     flags & LOOKUP_COMPLAIN);
        arg1 = TREE_TYPE (xarg1);
 
        /* This handles the case where we're trying to delete
@@ -1253,7 +1225,7 @@ build_opfncall (code, flags, xarg1, xarg2, arg3)
           
        if (TREE_CODE (TREE_TYPE (arg1)) == ARRAY_TYPE)
          {
-           /* Strip off the pointer and the array. */
+           /* Strip off the pointer and the array.  */
            arg1 = TREE_TYPE (TREE_TYPE (arg1));
 
            while (TREE_CODE (arg1) == ARRAY_TYPE)
@@ -1311,7 +1283,7 @@ build_opfncall (code, flags, xarg1, xarg2, arg3)
       /* Try to fail. First, fail if unary */
       if (! try_second)
        return rval;
-      /* Second, see if second argument is non-aggregate. */
+      /* Second, see if second argument is non-aggregate.  */
       type2 = TREE_TYPE (xarg2);
       if (TREE_CODE (type2) == OFFSET_TYPE)
        type2 = TREE_TYPE (type2);
@@ -1402,9 +1374,8 @@ build_opfncall (code, flags, xarg1, xarg2, arg3)
 
                  /* There's probably a LOT of code in the world that
                     relies upon this old behavior.  */
-                 if (! flag_traditional)
-                   pedwarn ("no `operator%s (int)' declared for postfix `%s', using prefix operator instead",
-                            op, op);
+                 pedwarn ("no `operator%s (int)' declared for postfix `%s', using prefix operator instead",
+                          op, op);
                  xarg2 = NULL_TREE;
                  binary_is_unary = 1;
                }
@@ -1446,7 +1417,7 @@ build_opfncall (code, flags, xarg1, xarg2, arg3)
     }
   else if (code == COND_EXPR)
     {
-      parms = tree_cons (0, xarg2, build_tree_list (NULL_TREE, arg3));
+      parms = tree_cons (NULL_TREE, xarg2, build_tree_list (NULL_TREE, arg3));
       rval = build_method_call (xarg1, fnname, parms, NULL_TREE, flags);
     }
   else if (code == METHOD_CALL_EXPR)
@@ -1465,8 +1436,7 @@ build_opfncall (code, flags, xarg1, xarg2, arg3)
     {
       parms = tree_cons (NULL_TREE, xarg1,
                         build_tree_list (NULL_TREE, xarg2));
-      rval = build_overload_call (fnname, parms, flags,
-                                 (struct candidate *)0);
+      rval = build_overload_call (fnname, parms, flags);
     }
 
   return rval;
@@ -1533,19 +1503,19 @@ hack_identifier (value, name)
   type = TREE_TYPE (value);
   if (TREE_CODE (value) == FIELD_DECL)
     {
-      if (current_class_decl == NULL_TREE)
+      if (current_class_ptr == NULL_TREE)
        {
          error ("request for member `%s' in static member function",
                 IDENTIFIER_POINTER (DECL_NAME (value)));
          return error_mark_node;
        }
-      TREE_USED (current_class_decl) = 1;
+      TREE_USED (current_class_ptr) = 1;
 
       /* Mark so that if we are in a constructor, and then find that
         this field was initialized by a base initializer,
         we can emit an error message.  */
       TREE_USED (value) = 1;
-      value = build_component_ref (C_C_D, name, 0, 1);
+      value = build_component_ref (current_class_ref, name, NULL_TREE, 1);
     }
   else if (really_overloaded_fn (value))
     {
@@ -1631,147 +1601,12 @@ hack_identifier (value, name)
       return value;
     }
 
-  if (TREE_CODE (type) == REFERENCE_TYPE && ! current_template_parms)
+  if (TREE_CODE (type) == REFERENCE_TYPE && ! processing_template_decl)
     value = convert_from_reference (value);
   return value;
 }
 
 \f
-#if 0
-/* Given an object OF, and a type conversion operator COMPONENT
-   build a call to the conversion operator, if a call is requested,
-   or return the address (as a pointer to member function) if one is not.
-
-   OF can be a TYPE_DECL or any kind of datum that would normally
-   be passed to `build_component_ref'.  It may also be NULL_TREE,
-   in which case `current_class_type' and `current_class_decl'
-   provide default values.
-
-   BASETYPE_PATH, if non-null, is the path of basetypes
-   to go through before we get the the instance of interest.
-
-   PROTECT says whether we apply C++ scoping rules or not.  */
-tree
-build_component_type_expr (of, component, basetype_path, protect)
-     tree of, component, basetype_path;
-     int protect;
-{
-  tree cname = NULL_TREE;
-  tree tmp, last;
-  tree name;
-  int flags = protect ? LOOKUP_NORMAL : LOOKUP_COMPLAIN;
-
-  if (of)
-    my_friendly_assert (IS_AGGR_TYPE (TREE_TYPE (of)), 253);
-  my_friendly_assert (TREE_CODE (component) == TYPE_EXPR, 254);
-
-  tmp = TREE_OPERAND (component, 0);
-  last = NULL_TREE;
-
-  while (tmp)
-    {
-      switch (TREE_CODE (tmp))
-       {
-       case CALL_EXPR:
-         if (last)
-           TREE_OPERAND (last, 0) = TREE_OPERAND (tmp, 0);
-         else
-           TREE_OPERAND (component, 0) = TREE_OPERAND (tmp, 0);
-
-         last = groktypename (build_tree_list (TREE_TYPE (component),
-                                               TREE_OPERAND (component, 0)));
-         name = build_typename_overload (last);
-         TREE_TYPE (name) = last;
-
-         if (TREE_OPERAND (tmp, 0)
-             && TREE_OPERAND (tmp, 0) != void_list_node)
-           {
-             cp_error ("`operator %T' requires empty parameter list", last);
-             TREE_OPERAND (tmp, 0) = NULL_TREE;
-           }
-
-         if (of && TREE_CODE (of) != TYPE_DECL)
-           return build_method_call (of, name, NULL_TREE, NULL_TREE, flags);
-         else if (of)
-           {
-             tree this_this;
-
-             if (current_class_decl == NULL_TREE)
-               {
-                 cp_error ("object required for `operator %T' call",
-                           TREE_TYPE (name));
-                 return error_mark_node;
-               }
-
-             this_this = convert_pointer_to (TREE_TYPE (of),
-                                             current_class_decl);
-             this_this = build_indirect_ref (this_this, NULL_PTR);
-             return build_method_call (this_this, name, NULL_TREE,
-                                       NULL_TREE, flags | LOOKUP_NONVIRTUAL);
-           }
-         else if (current_class_decl)
-           return build_method_call (tmp, name, NULL_TREE, NULL_TREE, flags);
-
-         cp_error ("object required for `operator %T' call",
-                   TREE_TYPE (name));
-         return error_mark_node;
-
-       case INDIRECT_REF:
-       case ADDR_EXPR:
-       case ARRAY_REF:
-         break;
-
-       case SCOPE_REF:
-         my_friendly_assert (cname == 0, 255);
-         cname = TREE_OPERAND (tmp, 0);
-         tmp = TREE_OPERAND (tmp, 1);
-         break;
-
-       default:
-         my_friendly_abort (77);
-       }
-      last = tmp;
-      tmp = TREE_OPERAND (tmp, 0);
-    }
-
-  last = groktypename (build_tree_list (TREE_TYPE (component), TREE_OPERAND (component, 0)));
-  name = build_typename_overload (last);
-  TREE_TYPE (name) = last;
-  if (of && TREE_CODE (of) == TYPE_DECL)
-    {
-      if (cname == NULL_TREE)
-       {
-         cname = DECL_NAME (of);
-         of = NULL_TREE;
-       }
-      else my_friendly_assert (cname == DECL_NAME (of), 256);
-    }
-
-  if (of)
-    {
-      tree this_this;
-
-      if (current_class_decl == NULL_TREE)
-       {
-         cp_error ("object required for `operator %T' call",
-                   TREE_TYPE (name));
-         return error_mark_node;
-       }
-
-      this_this = convert_pointer_to (TREE_TYPE (of), current_class_decl);
-      return build_component_ref (this_this, name, 0, protect);
-    }
-  else if (cname)
-    return build_offset_ref (cname, name);
-  else if (current_class_name)
-    return build_offset_ref (current_class_name, name);
-
-  cp_error ("object required for `operator %T' member reference",
-           TREE_TYPE (name));
-  return error_mark_node;
-}
-#endif
-\f
 static char *
 thunk_printable_name (decl)
      tree decl;
@@ -1815,11 +1650,11 @@ make_thunk (function, delta)
       TREE_READONLY (thunk) = TYPE_READONLY (TREE_TYPE (vtable_entry_type));
       TREE_THIS_VOLATILE (thunk) = TYPE_VOLATILE (TREE_TYPE (vtable_entry_type));
       make_function_rtl (thunk);
+      comdat_linkage (thunk);
       TREE_SET_CODE (thunk, THUNK_DECL);
       DECL_INITIAL (thunk) = function;
       THUNK_DELTA (thunk) = delta;
       DECL_EXTERNAL (thunk) = 1;
-      TREE_PUBLIC (thunk) = 1;
       /* So that finish_file can write out any thunks that need to be: */
       pushdecl_top_level (thunk);
     }
@@ -1831,20 +1666,21 @@ emit_thunk (thunk_fndecl)
   tree thunk_fndecl;
 {
   rtx insns;
-  char *fnname;
   char buffer[250];
   tree argp;
   struct args_size stack_args_size;
   tree function = TREE_OPERAND (DECL_INITIAL (thunk_fndecl), 0);
   int delta = THUNK_DELTA (thunk_fndecl);
+  char *fnname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0);
   int tem;
   int failure = 0;
+  int save_ofp;
 
-  /* Used to remember which regs we need to emit a USE rtx for. */
+  /* Used to remember which regs we need to emit a USE rtx for.  */
   rtx need_use[FIRST_PSEUDO_REGISTER];
   int need_use_count = 0;
 
-  /* rtx for the 'this' parameter. */
+  /* rtx for the 'this' parameter.  */
   rtx this_rtx = 0, this_reg_rtx = 0, fixed_this_rtx;
 
   char *(*save_decl_printable_name) () = decl_printable_name;
@@ -1856,20 +1692,30 @@ emit_thunk (thunk_fndecl)
 
   TREE_ASM_WRITTEN (thunk_fndecl) = 1;
 
-  if (! TREE_PUBLIC (function))
-    TREE_PUBLIC (thunk_fndecl) = 0;
-  if (DECL_EXTERNAL (function))
-    return;
-  DECL_EXTERNAL (thunk_fndecl) = 0;
+  TREE_ADDRESSABLE (function) = 1;
+  mark_used (function);
 
   decl_printable_name = thunk_printable_name;
   if (current_function_decl)
     abort ();
   current_function_decl = thunk_fndecl;
+
+  TREE_SET_CODE (thunk_fndecl, FUNCTION_DECL);
+#ifdef ASM_OUTPUT_MI_THUNK
+  temporary_allocation ();
+  assemble_start_function (thunk_fndecl, fnname);
+  ASM_OUTPUT_MI_THUNK (asm_out_file, thunk_fndecl, delta, function);
+  assemble_end_function (thunk_fndecl, fnname);
+  permanent_allocation (1);
+#else
+  save_ofp = flag_omit_frame_pointer;
+  flag_omit_frame_pointer = 1;
   init_function_start (thunk_fndecl, input_filename, lineno);
   pushlevel (0);
   expand_start_bindings (1);
 
+  temporary_allocation ();
+
   /* Start updating where the next arg would go.  */
   INIT_CUMULATIVE_ARGS (args_so_far, TREE_TYPE (function), NULL_RTX, 0);
   stack_args_size.constant = 0;
@@ -1878,7 +1724,7 @@ emit_thunk (thunk_fndecl)
 
   /* Now look through all the parameters, make sure that we
      don't clobber any registers used for parameters.
-     Also, pick up an rtx for the first "this" parameter. */
+     Also, pick up an rtx for the first "this" parameter.  */
   for (argp = TYPE_ARG_TYPES (TREE_TYPE (function));
        argp != NULL_TREE;
        argp = TREE_CHAIN (argp))
@@ -2031,20 +1877,18 @@ emit_thunk (thunk_fndecl)
 
   /* Now turn the rtl into assembler code.  */
 
-    {
-      char *fnname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0);
-      assemble_start_function (thunk_fndecl, fnname);
-      final (insns, asm_out_file, optimize, 0);
-      assemble_end_function (thunk_fndecl, fnname);
-    };
-
- exit_rest_of_compilation:
+  assemble_start_function (thunk_fndecl, fnname);
+  final (insns, asm_out_file, optimize, 0);
+  assemble_end_function (thunk_fndecl, fnname);
 
   reload_completed = 0;
 
   /* Cancel the effect of rtl_in_current_obstack.  */
 
-  resume_temporary_allocation ();
+  permanent_allocation (1);
+  flag_omit_frame_pointer = save_ofp;
+#endif /* ASM_OUTPUT_MI_THUNK */
+  TREE_SET_CODE (thunk_fndecl, THUNK_DECL);
 
   decl_printable_name = save_decl_printable_name;
   current_function_decl = 0;
@@ -2054,6 +1898,7 @@ emit_thunk (thunk_fndecl)
 
 /* For the anonymous union in TYPE, return the member that is at least as
    large as the rest of the members, so we can copy it.  */
+
 static tree
 largest_union_member (type)
      tree type;
@@ -2070,6 +1915,7 @@ largest_union_member (type)
 }
 
 /* Generate code for default X(X&) constructor.  */
+
 void
 do_build_copy_constructor (fndecl)
      tree fndecl;
@@ -2086,7 +1932,7 @@ do_build_copy_constructor (fndecl)
 
   if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type))
     {
-      t = build (INIT_EXPR, void_type_node, C_C_D, parm);
+      t = build (INIT_EXPR, void_type_node, current_class_ref, parm);
       TREE_SIDE_EFFECTS (t) = 1;
       cplus_expand_expr_stmt (t);
     }
@@ -2105,8 +1951,12 @@ do_build_copy_constructor (fndecl)
            (build_reference_type (basetype), parm,
             CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE);
          p = convert_from_reference (p);
-         current_base_init_list = tree_cons (basetype,
-                                             p, current_base_init_list);
+
+         if (p == error_mark_node)
+           cp_error ("in default copy constructor");
+         else 
+           current_base_init_list = tree_cons (basetype,
+                                               p, current_base_init_list);
        }
        
       for (i = 0; i < n_bases; ++i)
@@ -2119,9 +1969,15 @@ do_build_copy_constructor (fndecl)
          p = convert_to_reference
            (build_reference_type (basetype), parm,
             CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE);
-         p = convert_from_reference (p);
-         current_base_init_list = tree_cons (basetype,
-                                             p, current_base_init_list);
+
+         if (p == error_mark_node) 
+           cp_error ("in default copy constructor");
+         else 
+           {
+             p = convert_from_reference (p);
+             current_base_init_list = tree_cons (basetype,
+                                                 p, current_base_init_list);
+           }
        }
       for (; fields; fields = TREE_CHAIN (fields))
        {
@@ -2176,7 +2032,7 @@ do_build_assign_ref (fndecl)
 
   if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type))
     {
-      tree t = build (MODIFY_EXPR, void_type_node, C_C_D, parm);
+      tree t = build (MODIFY_EXPR, void_type_node, current_class_ref, parm);
       TREE_SIDE_EFFECTS (t) = 1;
       cplus_expand_expr_stmt (t);
     }
@@ -2190,16 +2046,13 @@ do_build_assign_ref (fndecl)
       for (i = 0; i < n_bases; ++i)
        {
          tree basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i));
-         if (TYPE_HAS_ASSIGN_REF (basetype))
-           {
-             tree p = convert_to_reference
-               (build_reference_type (basetype), parm,
-                CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE);
-             p = convert_from_reference (p);
-             p = build_member_call (basetype, ansi_opname [MODIFY_EXPR],
-                                    build_tree_list (NULL_TREE, p));
-             expand_expr_stmt (p);
-           }
+         tree p = convert_to_reference
+           (build_reference_type (basetype), parm,
+            CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE);
+         p = convert_from_reference (p);
+         p = build_member_call (basetype, ansi_opname [MODIFY_EXPR],
+                                build_tree_list (NULL_TREE, p));
+         expand_expr_stmt (p);
        }
       for (; fields; fields = TREE_CHAIN (fields))
        {
@@ -2208,6 +2061,24 @@ do_build_assign_ref (fndecl)
 
          if (TREE_CODE (field) != FIELD_DECL)
            continue;
+
+         if (TREE_READONLY (field))
+           {
+             if (DECL_NAME (field))
+               cp_error ("non-static const member `%#D', can't use default assignment operator", field);
+             else
+               cp_error ("non-static const member in type `%T', can't use default assignment operator", current_class_type);
+             continue;
+           }
+         else if (TREE_CODE (TREE_TYPE (field)) == REFERENCE_TYPE)
+           {
+             if (DECL_NAME (field))
+               cp_error ("non-static reference member `%#D', can't use default assignment operator", field);
+             else
+               cp_error ("non-static reference member in type `%T', can't use default assignment operator", current_class_type);
+             continue;
+           }
+
          if (DECL_NAME (field))
            {
              if (VFIELD_NAME_P (DECL_NAME (field)))
@@ -2227,13 +2098,13 @@ do_build_assign_ref (fndecl)
          else
            continue;
 
-         comp = build (COMPONENT_REF, TREE_TYPE (field), C_C_D, field);
+         comp = build (COMPONENT_REF, TREE_TYPE (field), current_class_ref, field);
          init = build (COMPONENT_REF, TREE_TYPE (field), parm, field);
 
          expand_expr_stmt (build_modify_expr (comp, NOP_EXPR, init));
        }
     }
-  c_expand_return (C_C_D);
+  c_expand_return (current_class_ref);
   pop_momentary ();
 }
 
@@ -2245,11 +2116,13 @@ synthesize_method (fndecl)
   tree context = hack_decl_function_context (fndecl);
   tree base = DECL_CLASS_CONTEXT (fndecl);
 
-  if (nested)
+  if (! context)
+    push_to_top_level ();
+  else if (nested)
     push_cp_function_context (context);
 
   interface_unknown = 1;
-  start_function (NULL_TREE, fndecl, NULL_TREE, NULL_TREE, 1);
+  start_function (NULL_TREE, fndecl, NULL_TREE, 1);
   store_parm_decls ();
 
   if (DECL_NAME (fndecl) == ansi_opname[MODIFY_EXPR])
@@ -2275,11 +2148,18 @@ synthesize_method (fndecl)
       /* Turn off DECL_INLINE for the moment so function_cannot_inline_p
          will check our size.  */
       DECL_INLINE (fndecl) = 0;
-      if (function_cannot_inline_p (fndecl) == 0)
+
+      /* We say !at_eof because at the end of the file some of the rtl
+        for fndecl may have been allocated on the temporary obstack.
+        (The function_obstack is the temporary one if we're not in a
+        function). */
+      if ((! at_eof) && function_cannot_inline_p (fndecl) == 0)
        DECL_INLINE (fndecl) = 1;
     }
 
   extract_interface_info ();
-  if (nested)
+  if (! context)
+    pop_from_top_level ();
+  else if (nested)
     pop_cp_function_context (context);
 }