31th Cygnus<->FSF merge.
authorMike Stump <mrs@gcc.gnu.org>
Fri, 8 Apr 1994 06:08:43 +0000 (06:08 +0000)
committerMike Stump <mrs@gcc.gnu.org>
Fri, 8 Apr 1994 06:08:43 +0000 (06:08 +0000)
From-SVN: r6996

21 files changed:
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-tree.def
gcc/cp/cp-tree.h
gcc/cp/cvt.c
gcc/cp/decl.c
gcc/cp/decl.h
gcc/cp/decl2.c
gcc/cp/errfn.c
gcc/cp/error.c
gcc/cp/expr.c
gcc/cp/init.c
gcc/cp/lex.c
gcc/cp/method.c
gcc/cp/parse.y
gcc/cp/pt.c
gcc/cp/search.c
gcc/cp/spew.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/cp/typeck2.c

index 663b727..5a1e161 100644 (file)
@@ -2658,7 +2658,7 @@ build_scoped_method_call (exp, scopes, name, parms)
       return error_mark_node;
     }
 
-  if (binfo = binfo_or_else (basetype, type))
+  if ((binfo = binfo_or_else (basetype, type)))
     {
       if (binfo == error_mark_node)
        return error_mark_node;
@@ -2965,13 +2965,14 @@ build_method_call (instance, name, parms, basetype_path, flags)
 
       if (TREE_CODE (basetype) == REFERENCE_TYPE)
        {
-         basetype = TYPE_MAIN_VARIANT (TREE_TYPE (basetype));
+         basetype = TREE_TYPE (basetype);
          if (! IS_AGGR_TYPE (basetype))
            goto non_aggr_error;
          /* Call to convert not needed because we are remaining
             within the same type.  */
-         instance_ptr = build1 (NOP_EXPR, TYPE_POINTER_TO (basetype), instance);
-         inst_ptr_basetype = basetype;
+         instance_ptr = build1 (NOP_EXPR, build_pointer_type (basetype),
+                                instance);
+         inst_ptr_basetype = TYPE_MAIN_VARIANT (basetype);
        }
       else
        {
@@ -3077,7 +3078,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
       return error_mark_node;
     }
 
-  save_basetype = basetype;
+  save_basetype = TYPE_MAIN_VARIANT (basetype);
 
 #if 0
   if (all_virtual == 1
@@ -3118,8 +3119,9 @@ build_method_call (instance, name, parms, basetype_path, flags)
 
   if (instance)
     {
-      constp = TREE_READONLY (instance);
-      volatilep = TREE_THIS_VOLATILE (instance);
+      /* TREE_READONLY (instance) fails for references.  */
+      constp = TYPE_READONLY (TREE_TYPE (TREE_TYPE (instance_ptr)));
+      volatilep = TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (instance_ptr)));
       parms = tree_cons (NULL_TREE, instance_ptr, parms);
     }
   else
@@ -3161,9 +3163,9 @@ build_method_call (instance, name, parms, basetype_path, flags)
            parms = tree_cons (NULL_TREE, instance_ptr, parms);
        }
     }
-  parmtypes = tree_cons (NULL_TREE,
-                        build_pointer_type (build_type_variant (basetype, constp, volatilep)),
-                        parmtypes);
+
+  parmtypes = tree_cons (NULL_TREE, TREE_TYPE (instance_ptr), parmtypes);
+
   if (last == NULL_TREE)
     last = parmtypes;
 
@@ -3253,19 +3255,22 @@ build_method_call (instance, name, parms, basetype_path, flags)
          if (flags & LOOKUP_GLOBAL)
            {
              tree friend_parms;
-             tree parm = TREE_VALUE (parms);
+             tree parm = instance_ptr;
 
              if (TREE_CODE (TREE_TYPE (parm)) == REFERENCE_TYPE)
-               friend_parms = parms;
+               {
+                 /* TREE_VALUE (parms) may have been modified by now;
+                     restore it to its original value. */
+                 TREE_VALUE (parms) = parm;
+                 friend_parms = parms;
+               }
              else if (TREE_CODE (TREE_TYPE (parm)) == POINTER_TYPE)
                {
                  tree new_type;
                  parm = build_indirect_ref (parm, "friendifying parms (compiler error)");
                  new_type = build_reference_type (TREE_TYPE (parm));
                  /* It is possible that this should go down a layer. */
-                 new_type = build_type_variant (new_type,
-                                                TREE_READONLY (parm),
-                                                TREE_THIS_VOLATILE (parm));
+                 new_type = build_type_variant (new_type, constp, volatilep);
                  parm = convert (new_type, parm);
                  friend_parms = tree_cons (NULL_TREE, parm, TREE_CHAIN (parms));
                }
@@ -3330,9 +3335,20 @@ build_method_call (instance, name, parms, basetype_path, flags)
            basetype_path = TREE_VALUE (basetype_path);
          basetype = BINFO_TYPE (basetype_path);
 
-         /* Cast the instance variable to the appropriate type.  */
-         TREE_VALUE (parms) = convert_force (TYPE_POINTER_TO (basetype),
-                                             instance_ptr);
+         /* Cast the instance variable if necessary.  */
+         if (basetype != TYPE_MAIN_VARIANT
+             (TREE_TYPE (TREE_TYPE (TREE_VALUE (parms)))))
+           {
+             if (basetype == save_basetype)
+               TREE_VALUE (parms) = instance_ptr;
+             else
+               {
+                 tree type = build_pointer_type
+                   (build_type_variant (basetype, constp, volatilep));
+                 TREE_VALUE (parms) = convert_force (type, instance_ptr);
+               }
+           }
+
          /* FIXME: this is the wrong place to get an error.  Hopefully
             the access-control rewrite will make this change more cleanly.  */
          if (TREE_VALUE (parms) == error_mark_node)
@@ -3468,12 +3484,18 @@ build_method_call (instance, name, parms, basetype_path, flags)
             then all we ever saw were private members.  */
          if (cp - candidates > 1)
            {
+             int n_candidates = cp - candidates;
+             TREE_VALUE (parms) = instance_ptr;
              cp = ideal_candidate (save_basetype, candidates,
-                                   cp - candidates, parms, len);
+                                   n_candidates, parms, len);
              if (cp == (struct candidate *)0)
                {
-                 cp_error ("ambiguous type conversion requested for %s `%D'",
-                           name_kind, name);
+                 if (flags & LOOKUP_COMPLAIN)
+                   {
+                     cp_error ("call of overloaded %s `%D' is ambiguous",
+                               name_kind, name);
+                     print_n_candidates (candidates, n_candidates);
+                   }
                  return error_mark_node;
                }
              if ((flag_ansi_overloading && (cp->h.code & EVIL_CODE))
@@ -3483,8 +3505,9 @@ build_method_call (instance, name, parms, basetype_path, flags)
          else if ((flag_ansi_overloading && (cp[-1].h.code & EVIL_CODE))
                   || (!flag_ansi_overloading && cp[-1].evil == 2))
            {
-             cp_error ("ambiguous type conversion requested for %s `%D'",
-                       name_kind, name);
+             if (flags & LOOKUP_COMPLAIN)
+               cp_error ("ambiguous type conversion requested for %s `%D'",
+                         name_kind, name);
              return error_mark_node;
            }
          else
@@ -3549,10 +3572,12 @@ build_method_call (instance, name, parms, basetype_path, flags)
       continue;
 
     found_and_maybe_warn:
-      if ((flag_ansi_overloading
-          && (cp->v.ansi_harshness[0].code & CONST_CODE))
-         || (!flag_ansi_overloading
-             && CONST_HARSHNESS (cp->v.old_harshness[0])))
+      if (((flag_ansi_overloading
+           && (cp->v.ansi_harshness[0].code & CONST_CODE))
+          || (!flag_ansi_overloading
+              && CONST_HARSHNESS (cp->v.old_harshness[0])))
+         /* 12.1p2: Constructors can be called for const objects.  */
+         && ! DECL_CONSTRUCTOR_P (cp->function))
        {
          if (flags & LOOKUP_COMPLAIN)
            {
index 0c5cc26..20116fe 100644 (file)
@@ -371,35 +371,67 @@ tree
 build_vtable_entry (delta, pfn)
      tree delta, pfn;
 {
-  extern int flag_huge_objects;
-  tree elems = tree_cons (NULL_TREE, delta,
-                         tree_cons (NULL_TREE, integer_zero_node,
-                                    build_tree_list (NULL_TREE, pfn)));
-  tree entry = build (CONSTRUCTOR, vtable_entry_type, NULL_TREE, elems);
-
-  /* DELTA is constructed by `size_int', which means it may be an
-     unsigned quantity on some platforms.  Therefore, we cannot use
-     `int_fits_type_p', because when DELTA is really negative,
-     `force_fit_type' will make it look like a very large number.  */
-
-  if ((TREE_INT_CST_LOW (TYPE_MAX_VALUE (delta_type_node))
-       < TREE_INT_CST_LOW (delta))
-      || (TREE_INT_CST_LOW (delta)
-         < TREE_INT_CST_LOW (TYPE_MIN_VALUE (delta_type_node))))
-    if (flag_huge_objects)
-      sorry ("object size exceeds built-in limit for virtual function table implementation");
-    else
-      sorry ("object size exceeds normal limit for virtual function table implementation, recompile all source and use -fhuge-objects");
+  extern tree abort_fndecl;
+  if (TREE_CODE (pfn) == ADDR_EXPR)
+    {
+      tree fndecl = TREE_OPERAND (pfn, 0);
+      if (TREE_CODE(fndecl) == FUNCTION_DECL
+         && DECL_ABSTRACT_VIRTUAL_P(fndecl))
+       {
+         tree d = copy_node (fndecl);
+         DECL_RTL (d) = DECL_RTL (abort_fndecl);
+         TREE_OPERAND (pfn, 0) = d;
+       }
+    }
+
+  if (flag_vtable_thunks)
+    {
+      HOST_WIDE_INT idelta = TREE_INT_CST_LOW (delta);
+      extern tree make_thunk ();
+      if (idelta)
+       {
+         pfn = build1 (ADDR_EXPR, ptr_type_node,
+                       make_thunk (pfn, idelta));
+         TREE_READONLY (pfn) = 1;
+         TREE_CONSTANT (pfn) = 1;
+       }
+#ifdef GATHER_STATISTICS
+      n_vtable_entries += 1;
+#endif
+      return pfn;
+    }
+  else
+    {
+      extern int flag_huge_objects;
+      tree elems = tree_cons (NULL_TREE, delta,
+                             tree_cons (NULL_TREE, integer_zero_node,
+                                        build_tree_list (NULL_TREE, pfn)));
+      tree entry = build (CONSTRUCTOR, vtable_entry_type, NULL_TREE, elems);
+
+      /* DELTA is constructed by `size_int', which means it may be an
+        unsigned quantity on some platforms.  Therefore, we cannot use
+        `int_fits_type_p', because when DELTA is really negative,
+        `force_fit_type' will make it look like a very large number.  */
+
+      if ((TREE_INT_CST_LOW (TYPE_MAX_VALUE (delta_type_node))
+          < TREE_INT_CST_LOW (delta))
+         || (TREE_INT_CST_LOW (delta)
+             < TREE_INT_CST_LOW (TYPE_MIN_VALUE (delta_type_node))))
+       if (flag_huge_objects)
+         sorry ("object size exceeds built-in limit for virtual function table implementation");
+       else
+         sorry ("object size exceeds normal limit for virtual function table implementation, recompile all source and use -fhuge-objects");
 
-  TREE_CONSTANT (entry) = 1;
-  TREE_STATIC (entry) = 1;
-  TREE_READONLY (entry) = 1;
+      TREE_CONSTANT (entry) = 1;
+      TREE_STATIC (entry) = 1;
+      TREE_READONLY (entry) = 1;
 
 #ifdef GATHER_STATISTICS
-  n_vtable_entries += 1;
+      n_vtable_entries += 1;
 #endif
 
-  return entry;
+      return entry;
+    }
 }
 
 /* Given an object INSTANCE, return an expression which yields the
@@ -471,7 +503,7 @@ build_vfn_ref (ptr_to_instptr, instance, idx)
        vtbl = build_indirect_ref (build_vfield_ref (instance, basetype),
                                   NULL_PTR);
     }
-  if (!flag_vtable_hack)
+  if (!flag_vtable_thunks)
     assemble_external (vtbl);
   aref = build_array_ref (vtbl, idx);
 
@@ -480,12 +512,17 @@ build_vfn_ref (ptr_to_instptr, instance, idx)
   if (!building_cleanup && TREE_CODE (aref) == INDIRECT_REF)
     TREE_OPERAND (aref, 0) = save_expr (TREE_OPERAND (aref, 0));
 
-  *ptr_to_instptr
-    = build (PLUS_EXPR, TREE_TYPE (*ptr_to_instptr),
-            *ptr_to_instptr,
-            convert (ptrdiff_type_node,
-                     build_component_ref (aref, delta_identifier, 0, 0)));
-  return build_component_ref (aref, pfn_identifier, 0, 0);
+  if (flag_vtable_thunks)
+    return aref;
+  else
+    {
+      *ptr_to_instptr
+       = build (PLUS_EXPR, TREE_TYPE (*ptr_to_instptr),
+                *ptr_to_instptr,
+                convert (ptrdiff_type_node,
+                         build_component_ref (aref, delta_identifier, 0, 0)));
+      return build_component_ref (aref, pfn_identifier, 0, 0);
+    }
 }
 
 /* Set TREE_PUBLIC and/or TREE_EXTERN on the vtable DECL,
@@ -828,18 +865,14 @@ modify_vtable_entry (old_entry_in_list, new_entry, fndecl)
     DECL_VINDEX (fndecl) = vindex;
   else
     {
-      if (! tree_int_cst_equal (DECL_VINDEX (fndecl), vindex))
+      if (! tree_int_cst_equal (DECL_VINDEX (fndecl), vindex)
+         && ! doing_hard_virtuals)
        {
-         tree elts = CONSTRUCTOR_ELTS (new_entry);
-
-         if (! doing_hard_virtuals)
-           {
-             pending_hard_virtuals
-               = tree_cons (fndecl, FNADDR_FROM_VTABLE_ENTRY (new_entry),
-                            pending_hard_virtuals);
-             TREE_TYPE (pending_hard_virtuals) = TREE_OPERAND (base_pfn, 0);
-             return;
-           }
+         pending_hard_virtuals
+           = tree_cons (fndecl, FNADDR_FROM_VTABLE_ENTRY (new_entry),
+                        pending_hard_virtuals);
+         TREE_TYPE (pending_hard_virtuals) = TREE_OPERAND (base_pfn, 0);
+         return;
        }
     }
 }
@@ -972,7 +1005,6 @@ static int
 is_normal (binfo, t)
      tree t, binfo;
 {
-  tree binfo2;
   int i = CLASSTYPE_VFIELD_PARENT (t);
   if (i != -1)
     {
@@ -992,10 +1024,13 @@ modify_other_vtable_entries (t, binfo, fndecl, base_fndecl, pfn)
      tree t, binfo;
      tree fndecl, base_fndecl, pfn;
 {
-  tree vfields, virtuals;
+  tree virtuals;
   tree binfos;
   int i, n_baselinks;
   unsigned HOST_WIDE_INT n;
+#if 0
+  tree vfields;
+#endif
   
   virtuals = BINFO_VIRTUALS (binfo);
   n = 0;
@@ -1173,7 +1208,10 @@ modify_vtable_entries (t, fndecl, base_fndecl, pfn)
                  DECL_ASSEMBLER_NAME(fndecl));
     }
 #endif
+#if 0
+  /* this is wrong, see p4736a.C testcase */
   DECL_CONTEXT (fndecl) = DECL_CONTEXT (base_fndecl);
+#endif
 
   offset = integer_zero_node;
   if (context != t && TYPE_USES_COMPLEX_INHERITANCE (t))
@@ -1377,7 +1415,7 @@ add_virtual_function (pending_virtuals, has_virtual, x, t)
   TREE_CONSTANT (vfn) = 1;
 
   /* current_class_type may be NULL_TREE in case of error.  */
-  if (current_class_type)
+  if (current_class_type && !flag_vtable_thunks)
     TREE_ADDRESSABLE (x) = CLASSTYPE_VTABLE_NEEDS_WRITING (current_class_type);
 
   /* If the virtual function is a redefinition of a prior one,
@@ -1386,7 +1424,7 @@ add_virtual_function (pending_virtuals, has_virtual, x, t)
      to hold that entry.  */
   if (DECL_VINDEX (x) == error_mark_node)
     {
-      tree entry = build_vtable_entry (integer_zero_node, vfn);
+      tree entry;
 
       if (flag_dossier && *has_virtual == 0)
        {
@@ -1416,6 +1454,7 @@ add_virtual_function (pending_virtuals, has_virtual, x, t)
        DECL_VINDEX (x) = index;
       }
 #endif
+      entry = build_vtable_entry (integer_zero_node, vfn);
       pending_virtuals = tree_cons (DECL_VINDEX (x), entry, pending_virtuals);
     }
   /* Happens if declared twice in class or we're not in a class definition.
@@ -2041,7 +2080,7 @@ finish_base_struct (t, b, t_binfo)
              if (! TREE_VIA_VIRTUAL (base_base_binfo))
                TREE_VEC_ELT (base_binfos, j)
                  = make_binfo (BINFO_OFFSET (base_base_binfo),
-                               BINFO_TYPE (base_base_binfo),
+                               base_base_binfo,
                                BINFO_VTABLE (base_base_binfo),
                                BINFO_VIRTUALS (base_base_binfo),
                                chain);
@@ -2773,7 +2812,6 @@ finish_struct (t, list_of_fieldlists, warn_anon)
   int any_default_members = 0;
   int const_sans_init = 0;
   int ref_sans_init = 0;
-  int do_mem_init = 0;
   int nonprivate_method = 0;
   tree t_binfo = TYPE_BINFO (t);
   tree access_decls = 0;
@@ -3005,10 +3043,10 @@ finish_struct (t, list_of_fieldlists, warn_anon)
              if (DECL_VINDEX (x)
                  || (all_virtual == 1 && ! DECL_CONSTRUCTOR_P (x)))
                {
-                 pending_virtuals = add_virtual_function (pending_virtuals,
-                                                          &has_virtual, x, t);
-                 if (DECL_ABSTRACT_VIRTUAL_P (x))
-                   abstract_virtuals = tree_cons (NULL_TREE, x, abstract_virtuals);
+                  pending_virtuals = add_virtual_function (pending_virtuals,
+                                                           &has_virtual, x, t);
+                  if (DECL_ABSTRACT_VIRTUAL_P (x))
+                    abstract_virtuals = tree_cons (NULL_TREE, x, abstract_virtuals);
                }
              continue;
            }
@@ -3772,8 +3810,9 @@ finish_struct (t, list_of_fieldlists, warn_anon)
              if (! SAME_FN (decl, base_fndecl))
                {
                  tree base_context = DECL_CLASS_CONTEXT (base_fndecl);
-                 tree binfo = NULL_TREE, these_virtuals;
+                 tree binfo = NULL_TREE;
 #if 0
+                 tree these_virtuals;
                  unsigned HOST_WIDE_INT i
                    = (TREE_INT_CST_LOW (DECL_VINDEX (base_fndecl))
                       & (((unsigned HOST_WIDE_INT)1<<(BITS_PER_WORD-1))-1));
index dc4bbda..3ddb359 100644 (file)
@@ -90,3 +90,13 @@ DEFTREECODE (TEMPLATE_CONST_PARM, "template_const_parm", "c", 2)
                 TREE_CHAIN      null
    Other useful fields to be defined later.  */
 DEFTREECODE (UNINSTANTIATED_P_TYPE, "uninstantiated_p_type", "t", 0)
+
+/* A thunk is a stub function.
+
+   Thunks are used to implement multiple inheritance:
+   At run-time, such a thunk subtracts THUNK_DELTA (an int, not a tree)
+   from the this pointer, and then jumps to DECL_INITIAL
+   (which is an ADDR_EXPR whose operand is a FUNCTION_DECL).
+
+   Other kinds of thunks may be defined later. */
+DEFTREECODE (THUNK_DECL, "thunk_decl", "d", 0)
index e4db0dc..e5a10db 100644 (file)
@@ -259,10 +259,10 @@ extern int flag_signed_bitfields;
 
 extern int write_virtuals;
 
-/* True if we want output of vtables to be controlled by whether
-   we seen the class's first non-inline virtual function.
+/* True for more efficient but incompatible (not not fully tested)
+   vtable implementation (using thunks).
    0 is old behavior; 1 is new behavior. */
-extern flag_vtable_hack;
+extern int flag_vtable_thunks;
 
 /* INTERFACE_ONLY nonzero means that we are in an "interface"
    section of the compiler.  INTERFACE_UNKNOWN nonzero means
@@ -339,10 +339,12 @@ enum languages { lang_c, lang_cplusplus };
 /* Virtual function addresses can be gotten from a virtual function
    table entry using this macro.  */
 #define FNADDR_FROM_VTABLE_ENTRY(ENTRY) \
-  TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (ENTRY))))
+  (!flag_vtable_thunks ? \
+     TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (ENTRY)))) \
+   : TREE_CODE (TREE_OPERAND ((ENTRY), 0)) != THUNK_DECL ? (ENTRY) \
+   : DECL_INITIAL (TREE_OPERAND ((ENTRY), 0)))
 #define SET_FNADDR_FROM_VTABLE_ENTRY(ENTRY,VALUE) \
   (TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (ENTRY)))) = (VALUE))
-
 #define FUNCTION_ARG_CHAIN(NODE) (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (NODE))))
 #define PROMOTES_TO_AGGR_TYPE(NODE,CODE)       \
   (((CODE) == TREE_CODE (NODE)                 \
@@ -924,7 +926,8 @@ struct lang_decl_flags
   unsigned mutable_flag : 1;
   unsigned is_default_implementation : 1;
   unsigned synthesized : 1;
-  unsigned dummy : 10;
+  unsigned saved_inline : 1;
+  unsigned dummy : 9;
 
   tree access;
   tree context;
@@ -986,6 +989,11 @@ struct lang_decl
    member function.  */
 #define DECL_STATIC_FUNCTION_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.static_function)
 
+/* Nonzero for FUNCTION_DECL means that this decl is a member function
+   (static or non-static).  */
+#define DECL_FUNCTION_MEMBER_P(NODE) \
+ (TREE_CODE (TREE_TYPE (NODE)) == METHOD_TYPE || DECL_STATIC_FUNCTION_P (NODE))
+
 /* Nonzero for FUNCTION_DECL means that this member function
    has `this' as const X *const.  */
 #define DECL_CONST_MEMFUNC_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.const_memfunc)
@@ -1005,8 +1013,9 @@ struct lang_decl
 /* Nonzero if allocated on permanent_obstack.  */
 #define LANG_DECL_PERMANENT(LANGDECL) ((LANGDECL)->decl_flags.permanent_attr)
 
-/* The _TYPE context in which this _DECL appears.  This field is used
-   only to compute access information.  */
+/* The _TYPE context in which this _DECL appears.  This field holds the
+   class where a virtual function instance is actually defined, and the
+   lexical scope of a friend function defined in a class body.  */
 #define DECL_CLASS_CONTEXT(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.context)
 
 /* For a FUNCTION_DECL: the chain through which the next method
@@ -1029,6 +1038,10 @@ struct lang_decl
    squirreled away.  */
 #define DECL_PENDING_INLINE_INFO(NODE) (DECL_LANG_SPECIFIC(NODE)->pending_inline_info)
 
+/* True if on the saved_inlines (see decl2.c) list. */
+#define DECL_SAVED_INLINE(DECL) \
+  (DECL_LANG_SPECIFIC(DECL)->decl_flags.saved_inline)
+
 /* For a FUNCTION_DECL: if this function was declared inside a signature
    declaration, this is the corresponding member function pointer that was
    created for it.  */
@@ -1057,7 +1070,9 @@ struct lang_decl
 /* Nonzero in IDENTIFIER_NODE means that this name is overloaded, and
    should be looked up in a non-standard way.  */
 #define TREE_OVERLOADED(NODE) (TREE_LANG_FLAG_0 (NODE))
+#if 0                          /* UNUSED */
 #define DECL_OVERLOADED(NODE) (DECL_LANG_FLAG_4 (NODE))
+#endif
 
 /* Nonzero if this (non-TYPE)_DECL has its virtual attribute set.
    For a FUNCTION_DECL, this is when the function is a virtual function.
@@ -1165,8 +1180,8 @@ struct lang_decl
 #define DELTA2_FROM_PTRMEMFUNC(NODE) (build_component_ref (build_component_ref ((NODE), pfn_or_delta2_identifier, 0, 0), delta2_identifier, 0, 0))
 #define PFN_FROM_PTRMEMFUNC(NODE) (build_component_ref (build_component_ref ((NODE), pfn_or_delta2_identifier, 0, 0), pfn_identifier, 0, 0))
 
-/* Nonzero for VAR_DECL node means that `external' was specified in
-   its declaration.  */
+/* Nonzero for VAR_DECL and FUNCTION_DECL node means that `external' was
+   specified in its declaration.  */
 #define DECL_THIS_EXTERN(NODE) (DECL_LANG_FLAG_2(NODE))
 
 /* Nonzero for SAVE_EXPR if used to initialize a PARM_DECL.  */
@@ -1232,6 +1247,8 @@ struct lang_decl
 #define DECL_TEMPLATE_RESULT(NODE)      DECL_RESULT(NODE)
 #define DECL_TEMPLATE_INSTANTIATIONS(NODE) DECL_VINDEX(NODE)
 
+#define THUNK_DELTA(DECL) ((DECL)->decl.frame_size)
+
 /* ...and for unexpanded-parameterized-type nodes.  */
 #define UPT_TEMPLATE(NODE)      TREE_PURPOSE(TYPE_VALUES(NODE))
 #define UPT_PARMS(NODE)         TREE_VALUE(TYPE_VALUES(NODE))
@@ -1293,6 +1310,7 @@ extern tree void_list_node;
 extern tree void_zero_node;
 extern tree default_function_type;
 extern tree vtable_entry_type;
+extern tree memptr_type;
 extern tree sigtable_entry_type;
 extern tree __t_desc_type_node, __i_desc_type_node, __m_desc_type_node;
 extern tree Type_info_type_node;
@@ -1790,6 +1808,7 @@ extern void print_binding_stack                   PROTO((void));
 extern void push_to_top_level                  PROTO((void));
 extern void pop_from_top_level                 PROTO((void));
 extern void set_identifier_type_value          PROTO((tree, tree));
+extern void pop_everything                     PROTO((void));
 extern tree make_type_decl                     PROTO((tree, tree));
 extern void pushtag                            PROTO((tree, tree, int));
 extern tree make_anon_name                     PROTO((void));
@@ -1823,6 +1842,7 @@ extern void expand_static_init                    PROTO((tree, tree));
 extern int complete_array_type                 PROTO((tree, tree, int));
 extern tree build_ptrmemfunc_type              PROTO((tree));
 extern tree grokdeclarator                     (); /* PROTO((tree, tree, enum decl_context, int, tree)); */
+extern int parmlist_is_exprlist                        PROTO((tree));
 extern tree xref_defn_tag                      PROTO((tree, tree, tree));
 extern tree xref_tag                           PROTO((tree, tree, tree, int));
 extern tree start_enum                         PROTO((tree));
@@ -1928,7 +1948,6 @@ extern tree build_dynamic_cast                    PROTO((tree, tree));
 /* in init.c */
 extern void emit_base_init                     PROTO((tree, int));
 extern void check_base_init                    PROTO((tree));
-extern tree build_virtual_init                 PROTO((tree, tree, tree));
 extern void init_vtbl_ptrs                     PROTO((tree, int, int));
 extern void do_member_init                     PROTO((tree, tree, tree));
 extern void expand_member_init                 PROTO((tree, tree, tree));
@@ -2000,6 +2019,16 @@ extern void dump_time_statistics         PROTO((void));
 extern void compiler_error_with_decl           PROTO((tree, char *));
 extern void yyerror                            PROTO((char *));
 
+/* in errfn.c */
+extern void cp_error                           ();
+extern void cp_error_at                                ();
+extern void cp_warning                         ();
+extern void cp_warning_at                      ();
+extern void cp_pedwarn                         ();
+extern void cp_pedwarn_at                      ();
+extern void cp_compiler_error                  ();
+extern void cp_sprintf                         ();
+
 /* in error.c */
 extern void init_error                         PROTO((void));
 extern char *fndecl_as_string                  PROTO((tree, tree, int));
@@ -2059,7 +2088,7 @@ extern void push_memoized_context         PROTO((tree, int));
 extern void pop_memoized_context               PROTO((int));
 extern tree get_binfo                          PROTO((tree, tree, int));
 extern int get_base_distance                   PROTO((tree, tree, int, tree *));
-extern enum access_type check_access   PROTO((tree, tree));
+extern enum access_type compute_access         PROTO((tree, tree));
 extern tree lookup_field                       PROTO((tree, tree, int, int));
 extern tree lookup_nested_field                        PROTO((tree, int));
 extern tree lookup_fnfields                    PROTO((tree, tree, int));
@@ -2071,7 +2100,7 @@ extern tree get_abstract_virtuals         PROTO((tree));
 extern tree get_baselinks                      PROTO((tree, tree, tree));
 extern tree next_baselink                      PROTO((tree));
 extern tree init_vbase_pointers                        PROTO((tree, tree));
-extern tree build_vbase_vtables_init           PROTO((tree, tree, tree, tree, int));
+extern void expand_vbase_vtables_init          PROTO((tree, tree, tree, tree, int));
 extern void clear_search_slots                 PROTO((tree));
 extern tree get_vbase_types                    PROTO((tree));
 extern void build_mi_matrix                    PROTO((tree));
@@ -2132,6 +2161,7 @@ extern tree virtual_member                        PROTO((tree, tree));
 extern tree virtual_offset                     PROTO((tree, tree, tree));
 extern void debug_binfo                                PROTO((tree));
 extern int decl_list_length                    PROTO((tree));
+extern int count_functions                     PROTO((tree));
 extern tree decl_value_member                  PROTO((tree, tree));
 extern int is_overloaded_fn                    PROTO((tree));
 extern tree get_first_fn                       PROTO((tree));
index 5e41618..fbe0d61 100644 (file)
@@ -285,22 +285,21 @@ build_up_reference (type, arg, flags, checkconst)
 {
   tree rval, targ;
   int literal_flag = 0;
-  tree argtype = TREE_TYPE (arg), basetype = argtype;
+  tree argtype = TREE_TYPE (arg);
   tree target_type = TREE_TYPE (type);
   tree binfo = NULL_TREE;
 
   my_friendly_assert (TREE_CODE (type) == REFERENCE_TYPE, 187);
-  if (flags != 0
+  if ((flags & LOOKUP_PROTECT)
       && TYPE_MAIN_VARIANT (argtype) != TYPE_MAIN_VARIANT (target_type)
       && IS_AGGR_TYPE (argtype)
       && IS_AGGR_TYPE (target_type))
     {
       binfo = get_binfo (target_type, argtype, 1);
-      if ((flags & LOOKUP_PROTECT) && binfo == error_mark_node)
+      if (binfo == error_mark_node)
        return error_mark_node;
       if (binfo == NULL_TREE)
        return error_not_base_type (target_type, argtype);
-      basetype = BINFO_TYPE (binfo);
     }
 
   /* Pass along const and volatile down into the type. */
@@ -619,8 +618,8 @@ convert_to_reference (decl, reftype, expr, fndecl, parmnum,
   register enum tree_code form = TREE_CODE (intype);
   tree rval = NULL_TREE;
 
-  if (TREE_CODE(type) == ARRAY_TYPE)
-    type = build_pointer_type (TREE_TYPE(type));
+  if (TREE_CODE (type) == ARRAY_TYPE)
+    type = build_pointer_type (TREE_TYPE (type));
   if (form == REFERENCE_TYPE)
     intype = TREE_TYPE (intype);
   intype = TYPE_MAIN_VARIANT (intype);
@@ -639,10 +638,11 @@ convert_to_reference (decl, reftype, expr, fndecl, parmnum,
       /* Section 13.  */
       if (flags & LOOKUP_COMPLAIN)
        {
-         /* Since convert_for_initialization didn't call convert_for_assignment,
-            we have to do this checking here.  FIXME: We should have a common
-            routine between here and convert_for_assignment.  */
-         if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE)
+         /* Since convert_for_initialization didn't call
+            convert_for_assignment, we have to do this checking here.
+            FIXME: We should have a common routine between here and
+            convert_for_assignment.  */
+         if (form == REFERENCE_TYPE)
            {
              register tree ttl = TREE_TYPE (reftype);
              register tree ttr = TREE_TYPE (TREE_TYPE (expr));
@@ -683,37 +683,52 @@ convert_to_reference (decl, reftype, expr, fndecl, parmnum,
         then we don't need to convert it to reference type if
         it is only being used to initialize DECL which is also
         of the same aggregate type.  */
-      if (form == REFERENCE_TYPE
-         || (decl != NULL_TREE && decl != error_mark_node
-             && IS_AGGR_TYPE (type)
-             && TREE_CODE (expr) == CALL_EXPR
-             && TYPE_MAIN_VARIANT (type) == intype))
+      if (decl != NULL_TREE && decl != error_mark_node
+         && IS_AGGR_TYPE (type)
+         && TREE_CODE (expr) == CALL_EXPR
+         && TYPE_MAIN_VARIANT (type) == intype)
        {
-         if (decl && decl != error_mark_node)
-           {
-             tree e1 = build (INIT_EXPR, void_type_node, decl, expr);
-             tree e2;
+         tree e1 = build (INIT_EXPR, void_type_node, decl, expr);
+         tree e2;
 
-             TREE_SIDE_EFFECTS (e1) = 1;
-             if (form == REFERENCE_TYPE)
-               e2 = build1 (NOP_EXPR, reftype, decl);
-             else
-               {
-                 e2 = build_unary_op (ADDR_EXPR, decl, 0);
-                 TREE_TYPE (e2) = reftype;
-                 TREE_REFERENCE_EXPR (e2) = 1;
-               }
-             return build_compound_expr (tree_cons (NULL_TREE, e1,
-                                                    build_tree_list (NULL_TREE, e2)));
+         TREE_SIDE_EFFECTS (e1) = 1;
+         if (form == REFERENCE_TYPE)
+           e2 = build1 (NOP_EXPR, reftype, decl);
+         else
+           {
+             e2 = build_unary_op (ADDR_EXPR, decl, 0);
+             TREE_TYPE (e2) = reftype;
+             TREE_REFERENCE_EXPR (e2) = 1;
            }
-         expr = copy_node (expr);
-         TREE_TYPE (expr) = reftype;
-         return expr;
+         return build_compound_expr
+           (tree_cons (NULL_TREE, e1, build_tree_list (NULL_TREE, e2)));
+       }
+
+      else if (form == REFERENCE_TYPE)
+       {
+         rval = copy_node (expr);
+         TREE_TYPE (rval) = build_pointer_type (TREE_TYPE (TREE_TYPE (expr)));
+         rval = convert (build_pointer_type (TREE_TYPE (reftype)), rval);
+         TREE_TYPE (rval) = reftype;
+         return rval;
        }
+
       return build_up_reference (reftype, expr, flags, decl!=NULL_TREE);
     }
 
-  if (decl == error_mark_node)
+  if (decl == NULL_TREE && lvalue_p (expr))
+    {
+      /* When casting an lvalue to a reference type, just convert into
+        a pointer to the new type and deference it.  This is allowed
+        by San Diego WP section 5.2.8 paragraph 9, though perhaps it
+        should be done directly (jason).  (int &)ri ---> *(int*)&ri */
+      rval = build_unary_op (ADDR_EXPR, expr, 0);
+      if (rval != error_mark_node)
+       rval = convert_force (build_pointer_type (TREE_TYPE (reftype)), rval);
+      if (rval != error_mark_node)
+       TREE_TYPE (rval) = reftype;
+    }
+  else if (decl == error_mark_node || decl == NULL_TREE)
     {
       tree rval_as_conversion = NULL_TREE;
       tree rval_as_ctor = NULL_TREE;
@@ -798,12 +813,12 @@ convert_to_reference (decl, reftype, expr, fndecl, parmnum,
 
   my_friendly_assert (form != OFFSET_TYPE, 189);
 
-  if ((flags & (LOOKUP_COMPLAIN|LOOKUP_SPECULATIVELY)) == LOOKUP_COMPLAIN)
-    cp_error ("cannot convert type `%T' to type `%T'", intype, reftype);
-
   if (flags & LOOKUP_SPECULATIVELY)
     return NULL_TREE;
 
+  else if (flags & LOOKUP_COMPLAIN)
+    cp_error ("cannot convert type `%T' to type `%T'", intype, reftype);
+
   return error_mark_node;
 }
 
@@ -1025,14 +1040,13 @@ convert_to_aggr (type, expr, msgp, protect)
            *msgp = "only private conversions apply";
        else if (saw_protected)
          *msgp = "only protected conversions apply";
+       else
+         *msgp = "no appropriate conversion to type `%s'";
       }
     return error_mark_node;
   }
   /* NOTREACHED */
 
- not_found:
-  if (msgp) *msgp = "no appropriate conversion to type `%s'";
-  return error_mark_node;
  found:
   if (access == access_private)
     if (! can_be_private)
@@ -1436,7 +1450,7 @@ convert_force (type, expr)
 
   if (code == REFERENCE_TYPE)
     return fold (convert_to_reference (0, type, e, NULL_TREE, -1,
-                                      NULL, -1, 0));
+                                      NULL, -1, LOOKUP_COMPLAIN));
   else if (TREE_CODE (TREE_TYPE (e)) == REFERENCE_TYPE)
     e = convert_from_reference (e);
 
index 1ad7849..6781216 100644 (file)
@@ -224,7 +224,7 @@ tree sizet_ftype_string;
 tree int_ftype_cptr_cptr_sizet;
 
 /* C++ extensions */
-tree vtable_entry_type;
+tree memptr_type, vtable_entry_type;
 tree delta_type_node;
 tree __t_desc_type_node, __i_desc_type_node, __m_desc_type_node;
 tree __t_desc_array_type, __i_desc_array_type, __m_desc_array_type;
@@ -310,11 +310,6 @@ static tree named_label_uses;
    in the TREE_PURPOSE slot.  */
 tree static_aggregates;
 
-/* A list of functions which were declared inline, but later had their
-   address taken.  Used only for non-virtual member functions, since we can
-   find other functions easily enough.  */
-tree pending_addressable_inlines;
-
 /* A list of overloaded functions which we should forget ever
    existed, such as functions declared in a function's scope,
    once we leave that function's scope.  */
@@ -1682,6 +1677,26 @@ set_nested_typename (decl, classname, name, type)
     DECL_NESTED_TYPENAME (decl) = name;
 }
 
+/* Pop off extraneous binding levels left over due to syntax errors.  */
+void
+pop_everything ()
+{
+#ifdef DEBUG_CP_BINDING_LEVELS
+  fprintf (stderr, "XXX entering pop_everything ()\n");
+#endif
+  while (current_binding_level != global_binding_level
+        && ! current_binding_level->pseudo_global)
+    {
+      if (class_binding_level)
+       pop_nested_class (1);
+      else
+       poplevel (0, 0, 0);
+    }
+#ifdef DEBUG_CP_BINDING_LEVELS
+  fprintf (stderr, "XXX leaving pop_everything ()\n");
+#endif
+}
+
 #if 0 /* not yet, should get fixed properly later */
 /* Create a TYPE_DECL node with the correct DECL_ASSEMBLER_NAME.
    Other routines shouldn't use build_decl directly; they'll produce
@@ -1981,7 +1996,14 @@ decls_match (newdecl, olddecl)
 
       if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (f1)),
                     TYPE_MAIN_VARIANT (TREE_TYPE (f2)), 2))
-       types_match = compparms (p1, p2, 2);
+       {
+         if (DECL_LANGUAGE (olddecl) == lang_c
+             && ! strict_prototypes_lang_c
+             && p2 == NULL_TREE)
+           types_match = self_promoting_args_p (p1);
+         else
+           types_match = compparms (p1, p2, 1);
+       }
       else
        types_match = 0;
     }
@@ -2096,42 +2118,7 @@ duplicate_decls (newdecl, olddecl)
   int new_defines_function;
   tree previous_c_decl = NULL_TREE;
 
-  if (TREE_CODE (newdecl) == FUNCTION_DECL && is_overloaded_fn (olddecl))
-    {
-      olddecl = get_first_fn (olddecl);
-
-      while (olddecl)
-       {
-         if (DECL_LANGUAGE (olddecl) == lang_c)
-           previous_c_decl = olddecl;
-
-         /* Redeclaration.  */
-         if (decls_match (newdecl, olddecl))
-           {
-             types_match = 1;
-             break;
-           }
-         /* Ambiguous overload.  */
-         else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)),
-                             TYPE_ARG_TYPES (TREE_TYPE (olddecl)), 2))
-           break;
-
-         /* Attempt to define multiple C-binding fns.  */
-         if (previous_c_decl)
-           break;
-         
-         olddecl = DECL_CHAIN (olddecl);
-       }
-      if (!olddecl)
-       {
-         /* If we found no match, make this join the other
-            overloaded decls.  */
-         DECL_OVERLOADED (newdecl) = 1;
-         return 1;
-       }
-    }
-  else
-    types_match = decls_match (newdecl, olddecl);
+  types_match = decls_match (newdecl, olddecl);
 
   if (TREE_CODE (olddecl) != TREE_LIST)
     olddecl_friend = DECL_LANG_SPECIFIC (olddecl) && DECL_FRIEND_P (olddecl);
@@ -2149,6 +2136,14 @@ duplicate_decls (newdecl, olddecl)
 
   if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
     {
+      if ((TREE_CODE (newdecl) == FUNCTION_DECL
+          && TREE_CODE (olddecl) == TEMPLATE_DECL
+          && ! DECL_TEMPLATE_IS_CLASS (olddecl))
+         || (TREE_CODE (olddecl) == FUNCTION_DECL
+             && TREE_CODE (newdecl) == TEMPLATE_DECL
+             && ! DECL_TEMPLATE_IS_CLASS (newdecl)))
+       return 0;
+      
       cp_error ("`%#D' redeclared as different kind of symbol", newdecl);
       if (TREE_CODE (olddecl) == TREE_LIST)
        olddecl = TREE_VALUE (olddecl);
@@ -2167,7 +2162,8 @@ duplicate_decls (newdecl, olddecl)
     ;
   else if (TREE_CODE (olddecl) == FUNCTION_DECL
           && (DECL_BUILT_IN (olddecl)
-              || DECL_BUILT_IN_NONANSI (olddecl)))
+              || DECL_BUILT_IN_NONANSI (olddecl))
+          && DECL_ASSEMBLER_NAME (newdecl) == DECL_ASSEMBLER_NAME (olddecl))
     {
       /* If you declare a built-in or predefined function name as static,
         the old definition is overridden,
@@ -2195,101 +2191,34 @@ duplicate_decls (newdecl, olddecl)
          return 0;
        }
     }
-  else if (!types_match && previous_c_decl
-          && DECL_LANGUAGE (newdecl) == lang_c)
-    {
-      cp_error ("declaration of C function `%#D' conflicts with", newdecl);
-      cp_error_at ("previous declaration `%#D' here", previous_c_decl);
-    }
-  else if (!types_match && TREE_CODE (newdecl) == TEMPLATE_DECL)
-    return 0;
   else if (!types_match)
     {
-      tree oldtype = TREE_TYPE (olddecl);
-      tree newtype = TREE_TYPE (newdecl);
-      int give_error = 0;
+      if (TREE_CODE (newdecl) == TEMPLATE_DECL)
+       return 0;
+      if (TREE_CODE (newdecl) == FUNCTION_DECL)
+       {
+         if (DECL_LANGUAGE (newdecl) == lang_c
+             && DECL_LANGUAGE (olddecl) == lang_c)
+           {
+             cp_error ("declaration of C function `%#D' conflicts with",
+                       newdecl);
+             cp_error_at ("previous declaration `%#D' here", olddecl);
+           }
+         
+         return 0;
+       }
 
       /* Already complained about this, so don't do so again.  */
       if (current_class_type == NULL_TREE
          || IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (newdecl)) != current_class_type)
        {
-         give_error = 1;
-
          /* Since we're doing this before finish_struct can set the
             line number on NEWDECL, we just do a regular error here.  */
          if (DECL_SOURCE_LINE (newdecl) == 0)
            cp_error ("conflicting types for `%#D'", newdecl);
          else
            cp_error_at ("conflicting types for `%#D'", newdecl);
-       }
-
-      /* Check for function type mismatch
-        involving an empty arglist vs a nonempty one.  */
-      if (TREE_CODE (olddecl) == FUNCTION_DECL
-         && comptypes (TREE_TYPE (oldtype),
-                       TREE_TYPE (newtype), 1)
-         && ((TYPE_ARG_TYPES (oldtype) == NULL_TREE
-              && DECL_INITIAL (olddecl) == NULL_TREE)
-             || (TYPE_ARG_TYPES (newtype) == NULL_TREE
-                 && DECL_INITIAL (newdecl) == NULL_TREE)))
-       {
-         /* Classify the problem further.  */
-         register tree t = TYPE_ARG_TYPES (oldtype);
-
-         if (t == NULL_TREE)
-           t = TYPE_ARG_TYPES (newtype);
-         for (; t; t = TREE_CHAIN (t))
-           {
-             register tree type = TREE_VALUE (t);
-
-             if (TREE_CHAIN (t) == NULL_TREE && type != void_type_node)
-               {
-                 give_error = 1;
-                 error ("A parameter list with an ellipsis can't match");
-                 error ("an empty parameter name list declaration.");
-                 break;
-               }
-
-             if (TYPE_MAIN_VARIANT (type) == float_type_node
-                 || C_PROMOTING_INTEGER_TYPE_P (type))
-               {
-                 give_error = 1;
-                 error ("An argument type that has a default promotion");
-                 error ("can't match an empty parameter name list declaration.");
-                 break;
-               }
-           }
-       }
-      if (give_error)
-       cp_error_at ("previous declaration as `%#D'", olddecl);
-
-      /* There is one thing GNU C++ cannot tolerate: a constructor
-        which takes the type of object being constructed.
-        Farm that case out here.  */
-      if (TREE_CODE (newdecl) == FUNCTION_DECL
-         && DECL_CONSTRUCTOR_P (newdecl))
-       {
-         tree tmp = TREE_CHAIN (TYPE_ARG_TYPES (newtype));
-
-         if (tmp != NULL_TREE
-             && (TYPE_MAIN_VARIANT (TREE_VALUE (tmp))
-                 == TYPE_METHOD_BASETYPE (newtype)))
-           {
-             tree parm = TREE_CHAIN (DECL_ARGUMENTS (newdecl));
-             tree argtypes
-               = hash_tree_chain (build_reference_type (TREE_VALUE (tmp)),
-                                  TREE_CHAIN (tmp));
-
-             DECL_ARG_TYPE (parm)
-               = TREE_TYPE (parm)
-                 = TYPE_REFERENCE_TO (TREE_VALUE (tmp));
-
-             TREE_TYPE (newdecl) = newtype
-               = build_cplus_method_type (TYPE_METHOD_BASETYPE (newtype),
-                                          TREE_TYPE (newtype), argtypes);
-             error ("constructor cannot take as argument the type being constructed");
-             SET_IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (newdecl), current_class_type);
-           }
+         cp_error_at ("previous declaration as `%#D'", olddecl);
        }
     }
   else
@@ -2315,18 +2244,25 @@ duplicate_decls (newdecl, olddecl)
        }
       else if (TREE_CODE (olddecl) == FUNCTION_DECL
               && DECL_LANGUAGE (newdecl) != DECL_LANGUAGE (olddecl))
-       /* extern "C" int foo ();
-          int foo () { bar (); }
-          is OK.  */
-       if (current_lang_stack == current_lang_base)
-         DECL_LANGUAGE (newdecl) = DECL_LANGUAGE (olddecl);
-       else
-         {
-           cp_error_at ("previous declaration of `%#D' with %L linkage",
-                        olddecl, DECL_LANGUAGE (olddecl));
-           cp_error ("conflicts with new declaration with %L linkage",
-                     DECL_LANGUAGE (newdecl));
-         }
+       {
+         /* extern "C" int foo ();
+            int foo () { bar (); }
+            is OK.  */
+         if (current_lang_stack == current_lang_base)
+           {
+             DECL_LANGUAGE (newdecl) = DECL_LANGUAGE (olddecl);
+             if (TYPE_ARG_TYPES (TREE_TYPE (olddecl)) == NULL_TREE
+                 && TYPE_ARG_TYPES (TREE_TYPE (newdecl)) == void_list_node)
+               TREE_TYPE (newdecl) = TREE_TYPE (olddecl);
+           }
+         else
+           {
+             cp_error_at ("previous declaration of `%#D' with %L linkage",
+                          olddecl, DECL_LANGUAGE (olddecl));
+             cp_error ("conflicts with new declaration with %L linkage",
+                       DECL_LANGUAGE (newdecl));
+           }
+       }
 
       /* These bits are logically part of the type.  */
       if (pedantic
@@ -2386,10 +2322,6 @@ duplicate_decls (newdecl, olddecl)
 #endif
     }
 
-  if (TREE_CODE (olddecl) == TEMPLATE_DECL
-      && DECL_TEMPLATE_INFO (olddecl)->length)
-    DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
-  
   /* Special handling ensues if new decl is a function definition.  */
   new_defines_function = (TREE_CODE (newdecl) == FUNCTION_DECL
                          && DECL_INITIAL (newdecl) != NULL_TREE);
@@ -2463,8 +2395,13 @@ duplicate_decls (newdecl, olddecl)
        TREE_THIS_VOLATILE (olddecl) = 1;
 
       /* Merge the initialization information.  */
-      if (DECL_INITIAL (newdecl) == NULL_TREE)
-       DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
+      if (DECL_INITIAL (newdecl) == NULL_TREE
+         && DECL_INITIAL (olddecl) != NULL_TREE)
+       {
+         DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
+         DECL_SOURCE_FILE (newdecl) = DECL_SOURCE_FILE (olddecl);
+         DECL_SOURCE_LINE (newdecl) = DECL_SOURCE_LINE (olddecl);
+       }
       /* Keep the old rtl since we can safely use it, unless it's the
         call to abort() used for abstract virtuals.  */
       if ((DECL_LANG_SPECIFIC (olddecl)
@@ -2547,7 +2484,7 @@ duplicate_decls (newdecl, olddecl)
            DECL_FRAME_SIZE (newdecl) = DECL_FRAME_SIZE (olddecl);
 
          DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
-         if (DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl))
+         if ((DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl)))
            /* Previously saved insns go together with
               the function's previous definition.  */
            DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
@@ -2557,6 +2494,15 @@ duplicate_decls (newdecl, olddecl)
        }
     }
 
+  if (TREE_CODE (newdecl) == TEMPLATE_DECL)
+    {
+      if (DECL_TEMPLATE_INFO (olddecl)->length)
+       DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
+      DECL_TEMPLATE_MEMBERS (newdecl) = DECL_TEMPLATE_MEMBERS (olddecl);
+      DECL_TEMPLATE_INSTANTIATIONS (newdecl)
+       = DECL_TEMPLATE_INSTANTIATIONS (olddecl);
+    }
+  
   /* Now preserve various other info from the definition.  */
   TREE_ADDRESSABLE (newdecl) = TREE_ADDRESSABLE (olddecl);
   TREE_ASM_WRITTEN (newdecl) = TREE_ASM_WRITTEN (olddecl);
@@ -2706,7 +2652,10 @@ pushdecl (x)
          file = DECL_SOURCE_FILE (t);
          line = DECL_SOURCE_LINE (t);
 
-         if (TREE_CODE (t) != TREE_CODE (x))
+         if (TREE_CODE (x) == FUNCTION_DECL && DECL_LANGUAGE (x) == lang_c
+             && is_overloaded_fn (t))
+           /* don't do anything just yet */;
+         else if (TREE_CODE (t) != TREE_CODE (x))
            {
              if (TREE_CODE (t) == TYPE_DECL || TREE_CODE (x) == TYPE_DECL)
                {
@@ -2723,39 +2672,47 @@ pushdecl (x)
          else if (duplicate_decls (x, t))
            {
 #if 0
-         /* This is turned off until I have time to do it right (bpk).  */
-
-         /* Also warn if they did a prototype with `static' on it, but
-            then later left the `static' off.  */
-         else if (! TREE_PUBLIC (name) && TREE_PUBLIC (x))
-           {
-             if (DECL_LANG_SPECIFIC (t) && DECL_FRIEND_P (t))
-               return t;
+             /* This is turned off until I have time to do it right (bpk).  */
 
-             if (extra_warnings)
+             /* Also warn if they did a prototype with `static' on it, but
+                then later left the `static' off.  */
+             if (! TREE_PUBLIC (name) && TREE_PUBLIC (x))
                {
-                 cp_warning ("`static' missing from declaration of `%D'", t);
-                 warning_with_file_and_line (file, line,
-                                             "previous declaration of `%s'",
-                                             decl_as_string (t, 0));
-               }
+                 if (DECL_LANG_SPECIFIC (t) && DECL_FRIEND_P (t))
+                   return t;
 
-             /* Now fix things so it'll do what they expect.  */
-             if (current_function_decl)
-               TREE_PUBLIC (current_function_decl) = 0;
-           }
-#endif
+                 if (extra_warnings)
+                   {
+                     cp_warning ("`static' missing from declaration of `%D'", t);
+                     warning_with_file_and_line (file, line,
+                                                 "previous declaration of `%s'",
+                                                 decl_as_string (t, 0));
+                   }
 
+                 /* Now fix things so it'll do what they expect.  */
+                 if (current_function_decl)
+                   TREE_PUBLIC (current_function_decl) = 0;
+               }
              /* Due to interference in memory reclamation (X may be
                 obstack-deallocated at this point), we must guard against
-                one really special case.  */
+                one really special case.  [jason: This should be handled
+                by start_function]  */
              if (current_function_decl == x)
                current_function_decl = t;
+#endif
              
              return t;
            }
        }
-      
+
+      if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_FUNCTION_MEMBER_P (x))
+       {
+         t = push_overloaded_decl (x, 1);
+         if (t != x || DECL_LANGUAGE (x) == lang_c)
+           return t;
+       }
+      else if (TREE_CODE (x) == TEMPLATE_DECL && ! DECL_TEMPLATE_IS_CLASS (x))
+       return push_overloaded_decl (x, 0);
 
       /* If declaring a type as a typedef, and the type has no known
         typedef name, install this TYPE_DECL as its typedef name.  */
@@ -2819,7 +2776,7 @@ pushdecl (x)
              && !DECL_BUILT_IN (decl))
            {
              cp_pedwarn ("type mismatch with previous external decl", x);
-             cp_pedwarn_at ("previous external decl of `%D'", decl);
+             cp_pedwarn_at ("previous external decl of `%#D'", decl);
            }
        }
 
@@ -3176,8 +3133,6 @@ push_overloaded_decl (decl, forgettable)
   tree orig_name = DECL_NAME (decl);
   tree glob = IDENTIFIER_GLOBAL_VALUE (orig_name);
 
-  DECL_OVERLOADED (decl) = 1;
-
   if (forgettable
       && ! flag_traditional
       && (glob == NULL_TREE || TREE_PERMANENT (glob) == 1)
@@ -3187,18 +3142,6 @@ push_overloaded_decl (decl, forgettable)
 
   if (glob)
     {
-      if (DECL_LANGUAGE (decl) == lang_c)
-       {
-         tree decls = get_first_fn (glob);
-         while (decls && DECL_LANGUAGE (decls) == lang_cplusplus)
-           decls = DECL_CHAIN (decls);
-         if (decls)
-           {
-             cp_error_at ("C-language function `%#D'", decls);
-             cp_error ("overloaded as `%#D'", decl);
-           }
-       }
-
       /* We cache the value of builtin functions as ADDR_EXPRs
         in the name space.  Convert it to some kind of _DECL after
         remembering what to forget.  */
@@ -3210,7 +3153,7 @@ push_overloaded_decl (decl, forgettable)
          tree tmp;
 
          for (tmp = get_first_fn (glob); tmp; tmp = DECL_CHAIN (tmp))
-           if (decl == tmp)
+           if (decl == tmp || duplicate_decls (decl, tmp))
              return decl;
        }
       else if (TREE_CODE (glob) == VAR_DECL)
@@ -3219,40 +3162,26 @@ push_overloaded_decl (decl, forgettable)
          cp_error ("conflicts with function declaration `%#D'", decl);
          return error_mark_node;
        }
+      else if (TREE_CODE (glob) == TYPE_DECL)
+       {
+         tree t = TREE_TYPE (glob);
+         if (IS_AGGR_TYPE (t) && warn_shadow)
+           cp_warning ("`%#D' hides constructor for `%#T'", decl, t);
+       }
       else if (is_overloaded_fn (glob))
         {
-          tree name = DECL_ASSEMBLER_NAME (decl);
           tree tmp;
          
          for (tmp = get_first_fn (glob); tmp; tmp = DECL_CHAIN (tmp))
            {
-             if (TREE_CODE (tmp) == FUNCTION_DECL
-                 && comptypes (TREE_TYPE (tmp), TREE_TYPE (decl), 2))
+             if (decl == tmp || duplicate_decls (decl, tmp))
+               return tmp;
+             if (compparms (TYPE_ARG_TYPES (TREE_TYPE (decl)),
+                            TYPE_ARG_TYPES (TREE_TYPE (tmp)), 2))
                {
-                 if (DECL_LANGUAGE (tmp) != DECL_LANGUAGE (decl))
-                   {
-                     if (current_lang_stack == current_lang_base)
-                       {
-                         DECL_LANGUAGE (decl) = DECL_LANGUAGE (tmp);
-                         return tmp;
-                       }
-                     cp_error_at ("previous declaration of `%#D' with %L linkage",
-                                  tmp, DECL_LANGUAGE (tmp));
-                     cp_error ("conflicts with new %L-language declaration",
-                                  DECL_LANGUAGE (decl));
-                   }
-                 else if (TREE_CODE (tmp) != TEMPLATE_DECL
-                          && DECL_ASSEMBLER_NAME (tmp) != name)
-                   {
-                     cp_error ("new declaration `%#D'", decl);
-                     cp_error_at ("ambiguates old declaration `%#D'", tmp);
-                   }
+                 cp_error ("new declaration `%#D'", decl);
+                 cp_error_at ("ambiguates old declaration `%#D'", tmp);
                }
-             /* If we really have seen this before, then if it ambiguates
-                something, we've already given an error before.  */
-             if (TREE_CODE (tmp) != TEMPLATE_DECL
-                 && DECL_ASSEMBLER_NAME (tmp) == name)
-               return decl;
            }
        }
     }
@@ -3335,7 +3264,7 @@ redeclaration_error_message (newdecl, olddecl)
       /* Because C++ can put things into name space for free,
         constructs like "typedef struct foo { ... } foo"
         would look like an erroneous redeclaration.  */
-      if (comptypes (newdecl, olddecl, 0))
+      if (comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl), 0))
        return 0;
       else
        return "redefinition of `%#D'";
@@ -3378,15 +3307,12 @@ redeclaration_error_message (newdecl, olddecl)
       /* If at least one is a reference, it's ok.  */
       if (DECL_EXTERNAL (newdecl) || DECL_EXTERNAL (olddecl))
        return 0;
-      /* Reject two definitions.  */
-      if (DECL_INITIAL (olddecl) != NULL_TREE
-         && DECL_INITIAL (newdecl) != NULL_TREE)
-       return "redefinition of `%#D'";
       /* Now we have two tentative defs, or one tentative and one real def.  */
       /* Insist that the linkage match.  */
       if (TREE_PUBLIC (olddecl) != TREE_PUBLIC (newdecl))
        return "conflicting declarations of `%#D'";
-      return 0;
+      /* Reject two definitions.  */
+      return "redefinition of `%#D'";
     }
   else
     {
@@ -4114,6 +4040,9 @@ init_decl_processing ()
   lang_name_cplusplus = get_identifier ("C++");
   lang_name_c = get_identifier ("C");
 
+  if (flag_ansi || pedantic)
+    strict_prototypes_lang_c = strict_prototypes_lang_cplusplus;
+
   /* Initially, C.  */
   current_lang_name = lang_name_c;
 
@@ -4418,6 +4347,21 @@ init_decl_processing ()
   builtin_function ("__builtin_constant_p", int_ftype_int,
                    BUILT_IN_CONSTANT_P, NULL_PTR);
 
+  builtin_function ("__builtin_return_address",
+                   build_function_type (ptr_type_node, 
+                                        tree_cons (NULL_TREE,
+                                                   unsigned_type_node,
+                                                   endlink)),
+                   BUILT_IN_RETURN_ADDRESS, NULL_PTR);
+
+  builtin_function ("__builtin_frame_address",
+                   build_function_type (ptr_type_node, 
+                                        tree_cons (NULL_TREE,
+                                                   unsigned_type_node,
+                                                   endlink)),
+                   BUILT_IN_FRAME_ADDRESS, NULL_PTR);
+
+
   builtin_function ("__builtin_alloca",
                    build_function_type (ptr_type_node,
                                         tree_cons (NULL_TREE,
@@ -4596,14 +4540,14 @@ init_decl_processing ()
       pushdecl (lookup_name (get_identifier ("__gc_main"), 0));
     }
 
-  /* Simplify life by making a "vtable_entry_type".  Give its
+  /* Simplify life by making a "memptr_type".  Give its
      fields names so that the debugger can use them.  */
 
-  vtable_entry_type = make_lang_type (RECORD_TYPE);
+  memptr_type = make_lang_type (RECORD_TYPE);
   fields[0] = build_lang_field_decl (FIELD_DECL, delta_identifier, delta_type_node);
   fields[1] = build_lang_field_decl (FIELD_DECL, index_identifier, delta_type_node);
   fields[2] = build_lang_field_decl (FIELD_DECL, pfn_identifier, ptr_type_node);
-  finish_builtin_type (vtable_entry_type, VTBL_PTR_TYPE, fields, 2,
+  finish_builtin_type (memptr_type, VTBL_PTR_TYPE, fields, 2,
                       double_type_node);
 
   /* Make this part of an invisible union.  */
@@ -4614,8 +4558,13 @@ init_decl_processing ()
   DECL_SIZE (fields[3]) = TYPE_SIZE (delta_type_node);
   TREE_UNSIGNED (fields[3]) = 0;
   TREE_CHAIN (fields[2]) = fields[3];
-  vtable_entry_type = build_type_variant (vtable_entry_type, 1, 0);
-  record_builtin_type (RID_MAX, VTBL_PTR_TYPE, vtable_entry_type);
+  memptr_type = build_type_variant (memptr_type, 1, 0);
+  record_builtin_type (RID_MAX, VTBL_PTR_TYPE, memptr_type);
+
+  if (flag_vtable_thunks)
+    vtable_entry_type = ptr_type_node;
+  else
+    vtable_entry_type = memptr_type;
 
 #ifdef VTABLE_USES_MASK
   /* This is primarily for virtual function definition.  We
@@ -5115,7 +5064,6 @@ start_decl (declarator, declspecs, initialized, raises)
       DECL_EXTERNAL (d) = (DECL_EXTERNAL (decl)
                           && !(context && !DECL_THIS_EXTERN (decl)));
       DECL_TEMPLATE_RESULT (d) = decl;
-      DECL_OVERLOADED (d) = 1;
       decl = d;
     }
 
@@ -5227,25 +5175,7 @@ start_decl (declarator, declspecs, initialized, raises)
       || TREE_CODE (type) == LANG_TYPE)
     tem = decl;
   else
-    {
-      tem = pushdecl (decl);
-      if (is_overloaded_fn (tem))
-       {
-         tree tem2;
-         tem = get_first_fn (tem);
-         tem2 = decl_value_member (decl, tem);
-         
-         if (tem2 != NULL_TREE)
-           tem = tem2;
-         else
-           {
-             while (tem && ! decls_match (decl, tem))
-               tem = DECL_CHAIN (tem);
-             if (tem == NULL_TREE)
-               tem = decl;
-           }
-       }
-    }
+    tem = pushdecl (decl);
             
   /* Tell the back-end to use or not use .common as appropriate.  */
   DECL_COMMON (tem) = flag_conserve_space;
@@ -5267,10 +5197,7 @@ start_decl (declarator, declspecs, initialized, raises)
     }
 #endif
 
-  if (TREE_CODE (decl) == FUNCTION_DECL && DECL_OVERLOADED (decl))
-    /* @@ Also done in start_function.  */
-    tem = push_overloaded_decl (tem, 1);
-  else if (TREE_CODE (decl) == TEMPLATE_DECL)
+  if (TREE_CODE (decl) == TEMPLATE_DECL)
     {
       tree result = DECL_TEMPLATE_RESULT (decl);
       if (DECL_CONTEXT (result) != NULL_TREE)
@@ -5339,6 +5266,7 @@ start_decl (declarator, declspecs, initialized, raises)
   return tem;
 }
 
+#if 0                          /* unused */
 static void
 make_temporary_for_reference (decl, ctor_call, init, cleanupp)
      tree decl, ctor_call, init;
@@ -5397,6 +5325,7 @@ make_temporary_for_reference (decl, ctor_call, init, cleanupp)
   if (TREE_STATIC (tmp))
     preserve_initializer ();
 }
+#endif
 
 /* Handle initialization of references.
    These three arguments from from `finish_decl', and have the
@@ -5559,7 +5488,6 @@ grok_reference_init (decl, type, init, cleanupp)
   else
     my_friendly_abort (1);
 
- done:
   /* ?? Can this be optimized in some cases to
      hand back the DECL_INITIAL slot??  */
   if (TYPE_SIZE (TREE_TYPE (type)))
@@ -6140,6 +6068,7 @@ finish_decl (decl, init, asmspec_tree, need_pop)
 
       if (TREE_CODE (decl) == FUNCTION_DECL)
        {
+#if 0
          /* C++: Handle overloaded functions with default parameters.  */
          if (DECL_OVERLOADED (decl))
            {
@@ -6184,6 +6113,7 @@ finish_decl (decl, init, asmspec_tree, need_pop)
                }
              DECL_LANG_SPECIFIC (decl) = tmp_lang_decl;
            }
+#endif
        }
       else if (DECL_EXTERNAL (decl))
        ;
@@ -6926,7 +6856,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
   /* Look inside a declarator for the name being declared
      and get it as a string, for an error message.  */
   {
-    tree type, last = NULL_TREE;
+    tree last = NULL_TREE;
     register tree decl = declarator;
     name = NULL;
 
@@ -8722,10 +8652,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
                           && ! funcdef_flag
                           && RIDBIT_NOTSETP (RID_STATIC, specbits)
                           && RIDBIT_NOTSETP (RID_INLINE, specbits)));
-           if (TREE_CODE (type) == METHOD_TYPE)
-             publicp 
-               |= (ctype && CLASSTYPE_INTERFACE_KNOWN (ctype))
-                 || (!funcdef_flag && RIDBIT_NOTSETP (RID_INLINE, specbits));
            decl = grokfndecl (ctype, type, declarator,
                               virtualp, flags, quals,
                               raises, friendp ? -1 : 0, publicp);
@@ -8852,25 +8778,32 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
       }
     else if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE)
       {
-       int was_overloaded = 0;
        tree original_name = declarator;
        int publicp = 0;
 
        if (! declarator)
          return NULL_TREE;
 
-       if (RIDBIT_SETP (RID_AUTO, specbits)
-           || RIDBIT_SETP (RID_REGISTER, specbits))
-         error ("invalid storage class for function `%s'", name);
+       if (RIDBIT_SETP (RID_AUTO, specbits))
+         error ("storage class `auto' invalid for function `%s'", name);
+       else if (RIDBIT_SETP (RID_REGISTER, specbits))
+         error ("storage class `register' invalid for function `%s'", name);
 
        /* Function declaration not at top level.
           Storage classes other than `extern' are not allowed
           and `extern' makes no difference.  */
        if (current_binding_level != global_binding_level
-           && (RIDBIT_SETP (RID_STATIC, specbits) || RIDBIT_SETP (RID_INLINE, specbits))
+           && ! processing_template_decl
+           && (RIDBIT_SETP (RID_STATIC, specbits)
+               || RIDBIT_SETP (RID_INLINE, specbits))
            && pedantic)
-         pedwarn ("invalid storage class for function `%s'", name);
-
+         {
+           if (RIDBIT_SETP (RID_STATIC, specbits))
+             pedwarn ("storage class `static' invalid for function `%s' declared out of global scope", name);
+           else
+             pedwarn ("storage class `inline' invalid for function `%s' declared out of global scope", name);
+         }
+       
        if (ctype == NULL_TREE)
          {
            if (virtualp)
@@ -8887,11 +8820,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
                      && IDENTIFIER_POINTER (original_name)[0] == '_'
                      && IDENTIFIER_POINTER (original_name)[1] == '_'
                      && strncmp (IDENTIFIER_POINTER (original_name)+2, "builtin_", 8) == 0))
-             {
-               /* Plain overloading: will not be grok'd by grokclassfn.  */
-               declarator = build_decl_overload (dname, TYPE_ARG_TYPES (type), 0);
-               was_overloaded = 1;
-             }
+             /* Plain overloading: will not be grok'd by grokclassfn.  */
+             declarator = build_decl_overload (dname, TYPE_ARG_TYPES (type), 0);
          }
        else if (TREE_CODE (type) == FUNCTION_TYPE && staticp < 2)
          type = build_cplus_method_type (build_type_variant (ctype, constp, volatilep),
@@ -8926,8 +8856,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
                cp_error_at ("cannot declare member function `%D' to have static linkage", decl);
                illegal_static = 1;
              }
-           else if (! was_overloaded
-                    && ! ctype
+           else if (! ctype
                     && IDENTIFIER_LENGTH (original_name) == 4
                     && IDENTIFIER_POINTER (original_name)[0] == 'm'
                     && ! strcmp (IDENTIFIER_POINTER (original_name), "main"))
@@ -8954,8 +8883,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
          {
            tree last = tree_last (TYPE_ARG_TYPES (type));
 
-           if (! was_overloaded
-               && ! ctype
+           if (! ctype
                && ! strcmp (IDENTIFIER_POINTER (original_name), "main"))
              error ("cannot inline function `main'");
            else if (last && last != void_list_node)
@@ -8971,8 +8899,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
                  pedwarn ("ANSI C++ does not permit `extern inline'");
              }
          }
-       if (was_overloaded)
-         DECL_OVERLOADED (decl) = 1;
       }
     else
       {
@@ -9012,6 +8938,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
     if (RIDBIT_SETP (RID_REGISTER, specbits))
       DECL_REGISTER (decl) = 1;
 
+    if (RIDBIT_SETP (RID_EXTERN, specbits))
+      DECL_THIS_EXTERN (decl) = 1;
+
     /* Record constancy and volatility.  */
 
     if (constp)
@@ -9753,7 +9682,7 @@ xref_tag (code_type_node, name, binfo, globalize)
 
   /* If a cross reference is requested, look up the type
      already defined for this tag and return it.  */
-  if (t = IDENTIFIER_TYPE_VALUE(name))
+  if ((t = IDENTIFIER_TYPE_VALUE(name)))
     {
        if (TREE_CODE(t) != code) t = NULL_TREE;
     }
@@ -10000,7 +9929,7 @@ xref_tag (code_type_node, name, binfo, globalize)
   
              base_binfo = make_binfo (integer_zero_node, basetype,
                                  TYPE_BINFO_VTABLE (basetype),
-                                 TYPE_BINFO_VIRTUALS (basetype), 0);
+                                 TYPE_BINFO_VIRTUALS (basetype), NULL_TREE);
  
              TREE_VEC_ELT (binfos, i) = base_binfo;
              TREE_VIA_PUBLIC (base_binfo) = via_public;
@@ -10468,7 +10397,7 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
       if ( !(DECL_VINDEX (decl1)
             && write_virtuals >= 2
             && CLASSTYPE_VTABLE_NEEDS_WRITING (ctype)))
-       current_extern_inline = TREE_PUBLIC (decl1) && DECL_INLINE (decl1);
+       current_extern_inline = DECL_THIS_EXTERN (decl1) && DECL_INLINE (decl1);
 
       raises = TYPE_RAISES_EXCEPTIONS (fntype);
 
@@ -10585,73 +10514,19 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
        defining how to inline.  So set DECL_EXTERNAL in that case.  */
     DECL_EXTERNAL (decl1) = current_extern_inline;
 
-  /* Now see if this is the implementation of a declared function.  */
-  if (ctype == NULL_TREE && current_lang_name == lang_name_cplusplus
-      && !DECL_CONTEXT (decl1))
-    {
-      olddecl = lookup_name_current_level (DECL_NAME (decl1));
-      if (olddecl && TREE_CODE (olddecl) != FUNCTION_DECL)
-       olddecl = NULL_TREE;
-      if (olddecl && DECL_NAME (decl1) != DECL_NAME (olddecl))
-       {
-         /* Collision between user and internal naming scheme.  */
-         olddecl = lookup_name_current_level (DECL_ASSEMBLER_NAME (decl1));
-         if (olddecl == NULL_TREE)
-           olddecl = decl1;
-       }
-      if (olddecl && olddecl != decl1
-         && DECL_NAME (decl1) == DECL_NAME (olddecl))
-       {
-         if (TREE_CODE (olddecl) == FUNCTION_DECL
-             && decls_match (decl1, olddecl))
-           {
-             olddecl = DECL_MAIN_VARIANT (olddecl);
-             /* The following copy is needed to handle forcing a function's
-                linkage to obey the linkage of the original decl.  */
-             DECL_ASSEMBLER_NAME (decl1) = DECL_ASSEMBLER_NAME (olddecl);
-             DECL_OVERLOADED (decl1) = DECL_OVERLOADED (olddecl);
-             if (! DECL_BUILT_IN (olddecl) && DECL_INITIAL (olddecl))
-               redeclaration_error_message (decl1, olddecl);
-             if (duplicate_decls (decl1, olddecl))
-               decl1 = olddecl;
-             else
-               olddecl = NULL_TREE;
-           }
-         else
-           olddecl = NULL_TREE;
-       }
-    }
-
   /* Record the decl so that the function name is defined.
      If we already have a decl for this name, and it is a FUNCTION_DECL,
      use the old decl.  */
 
-  if (olddecl)
-    current_function_decl = olddecl;
-  else if (pre_parsed_p == 0)
+  if (pre_parsed_p == 0)
     {
-      current_function_decl = pushdecl (decl1);
-      if (TREE_CODE (current_function_decl) == TREE_LIST
-         || (DECL_ASSEMBLER_NAME (current_function_decl)
-             != DECL_ASSEMBLER_NAME (decl1)))
-       {
-         /* @@ revert to modified original declaration.  */
-         decl1 = DECL_MAIN_VARIANT (decl1);
-         current_function_decl = decl1;
-       }
-      else
-       {
-         decl1 = current_function_decl;
-         DECL_MAIN_VARIANT (decl1) = decl1;
-       }
+      current_function_decl = decl1 = pushdecl (decl1);
+      DECL_MAIN_VARIANT (decl1) = decl1;
       fntype = TREE_TYPE (decl1);
     }
   else
     current_function_decl = decl1;
 
-  if (DECL_OVERLOADED (decl1))
-    decl1 = push_overloaded_decl (decl1, 1);
-
   if (ctype != NULL_TREE && DECL_STATIC_FUNCTION_P (decl1))
     {
       if (TREE_CODE (fntype) == METHOD_TYPE)
@@ -10956,7 +10831,7 @@ store_return_init (return_id, init)
     /* Give this error as many times as there are occurrences,
        so that users can use Emacs compilation buffers to find
        and fix all such places.  */
-    error ("ANSI C++ does not permit named return values");
+    pedwarn ("ANSI C++ does not permit named return values");
 
   if (return_id != NULL_TREE)
     {
@@ -11266,8 +11141,7 @@ finish_function (lineno, call_poplevel)
         tables.  */
       init_vtbl_ptrs (binfo, 1, 0);
       if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
-       expand_expr_stmt (build_vbase_vtables_init (binfo, binfo,
-                                                   C_C_D, current_class_decl, 0));
+       expand_vbase_vtables_init (binfo, binfo, C_C_D, current_class_decl, 0);
       if (! ok_to_optimize_dtor)
        {
          cond = build_binary_op (NE_EXPR,
@@ -11604,6 +11478,12 @@ finish_function (lineno, call_poplevel)
       rest_of_compilation (fndecl);
     }
 
+  if (DECL_INLINE (fndecl)
+      && !TREE_ASM_WRITTEN (fndecl) && DECL_FUNCTION_MEMBER_P (fndecl))
+    {
+      mark_inline_for_output (fndecl);
+    }
+
   if (ctype && TREE_ASM_WRITTEN (fndecl))
     note_debug_info_needed (ctype);
 
@@ -11715,10 +11595,7 @@ start_method (declspecs, declarator, raises)
       return void_type_node;
     }
 
-  /* If we're expanding a template, a function must be explicitly declared
-     inline if we're to compile it now.  If it isn't, we have to wait to see
-     whether it's needed, and whether an override exists.  */
-  if (flag_default_inline && !processing_template_defn)
+  if (flag_default_inline)
     DECL_INLINE (fndecl) = 1;
 
   /* We read in the parameters on the maybepermanent_obstack,
@@ -11777,7 +11654,6 @@ finish_method (decl)
 {
   register tree fndecl = decl;
   tree old_initial;
-  tree context = DECL_CONTEXT (fndecl);
 
   register tree link;
 
index aabfa2f..b088179 100644 (file)
@@ -48,11 +48,6 @@ extern tree pending_statics;
    in the TREE_PURPOSE slot.  */
 extern tree static_aggregates;
 
-/* A list of functions which were declared inline, but later had their
-   address taken.  Used only for non-virtual member functions, since we can
-   find other functions easily enough.  */
-extern tree pending_addressable_inlines;
-
 #ifdef DEBUG_CP_BINDING_LEVELS
 /* Purely for debugging purposes.  */
 extern int debug_bindings_indentation;
index c752e23..2177713 100644 (file)
@@ -47,7 +47,9 @@ tree pending_vtables;
    an initializer, and then initialized, staticly, outside the class.  */
 tree pending_statics;
 
-extern tree pending_addressable_inlines;
+/* A list of functions which were declared inline, but which we
+   may need to emit outline anyway. */
+static tree saved_inlines;
 
 /* Used to help generate temporary names which are unique within
    a function.  Reset to 0 by start_function.  */
@@ -129,9 +131,12 @@ int warn_implicit = 1;
 
 int warn_ctor_dtor_privacy = 1;
 
-/* True if we want output of vtables to be controlled by whether
+/* True if we want to implement vtbvales using "thunks".
+   The default is off now, but will be on later.
+
+   Also causes output of vtables to be controlled by whether
    we seen the class's first non-inline virtual function. */
-int flag_vtable_hack = 0;
+int flag_vtable_thunks = 0;
 
 /* Nonzero means give string constants the type `const char *'
    to get extra warnings from them.  These warnings will be too numerous
@@ -364,7 +369,7 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] =
   {"ansi-overloading", &flag_ansi_overloading, 1},
   {"huge-objects", &flag_huge_objects, 1},
   {"conserve-space", &flag_conserve_space, 1},
-  {"vtable-hack", &flag_vtable_hack, 1},
+  {"vtable-thunks", &flag_vtable_thunks, 1},
 };
 
 /* Decode the string P as a language-specific option.
@@ -609,6 +614,7 @@ grok_method_quals (ctype, function, quals)
   return ctype;
 }
 
+#if 0                          /* Not used. */
 /* This routine replaces cryptic DECL_NAMEs with readable DECL_NAMEs.
    It leaves DECL_ASSEMBLER_NAMEs with the correct value.  */
 /* This does not yet work with user defined conversion operators
@@ -625,6 +631,7 @@ substitute_nice_name (decl)
       DECL_NAME (decl) = get_identifier (n);
     }
 }
+#endif
 
 /* Warn when -fexternal-templates is used and #pragma
    interface/implementation is not used all the times it should be,
@@ -1071,7 +1078,10 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
   if (doing_vec
       && TREE_CODE (type) == POINTER_TYPE
       && !TYPE_HAS_DESTRUCTOR (TREE_TYPE (type)))
-    doing_vec = 0;
+    {
+      doing_vec = 0;
+      use_global_delete = 1;
+    }
 
   if (doing_vec)
     return build_vec_delete (t, maxindex, elt_size, NULL_TREE,
@@ -1093,7 +1103,6 @@ check_classfn (ctype, cname, function)
 {
   tree fn_name = DECL_NAME (function);
   tree fndecl;
-  int need_quotes = 0;
   tree method_vec = CLASSTYPE_METHOD_VEC (ctype);
   tree *methods = 0;
   tree *end = 0;
@@ -1241,12 +1250,14 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree)
        }
       else if (pedantic)
        {
+#if 0
+         /* Already warned in grokdeclarator.  */
          if (DECL_NAME (value))
            pedwarn ("ANSI C++ forbids initialization of member `%s'",
                     IDENTIFIER_POINTER (DECL_NAME (value)));
          else
            pedwarn ("ANSI C++ forbids initialization of fields");
-
+#endif
          init = NULL_TREE;
        }
       else
@@ -1675,7 +1686,6 @@ grok_function_init (decl, init)
   /* An initializer for a function tells how this function should
      be inherited.  */
   tree type = TREE_TYPE (decl);
-  extern tree abort_fndecl;
 
   if (TREE_CODE (type) == FUNCTION_TYPE)
     cp_error ("initializer specified for non-member function `%D'", decl);
@@ -1683,14 +1693,19 @@ grok_function_init (decl, init)
     cp_error ("initializer specified for non-virtual method `%D'", decl);
   else if (integer_zerop (init))
     {
+#if 0
       /* Mark this function as being "defined".  */
       DECL_INITIAL (decl) = error_mark_node;
       /* pure virtual destructors must be defined. */
+      /* pure virtual needs to be defined (as abort) only when put in 
+        vtbl. For wellformed call, it should be itself. pr4737 */
       if (!DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl)))
        {
+         extern tree abort_fndecl;
          /* Give this node rtl from `abort'.  */
          DECL_RTL (decl) = DECL_RTL (abort_fndecl);
        }
+#endif
       DECL_ABSTRACT_VIRTUAL_P (decl) = 1;
     }
   else if (TREE_CODE (init) == OFFSET_REF
@@ -1791,7 +1806,6 @@ tree
 constructor_name_full (thing)
      tree thing;
 {
-  tree t;
   if (TREE_CODE (thing) == UNINSTANTIATED_P_TYPE)
     return DECL_NAME (UPT_TEMPLATE (thing));
   if (IS_AGGR_TYPE_CODE (TREE_CODE (thing)))
@@ -1898,6 +1912,9 @@ void
 mark_inline_for_output (decl)
      tree decl;
 {
+  if (DECL_SAVED_INLINE (decl))
+    return;
+  DECL_SAVED_INLINE (decl) = 1;
   if (DECL_PENDING_INLINE_INFO (decl) != 0
       && ! DECL_PENDING_INLINE_INFO (decl)->deja_vu)
     {
@@ -1917,8 +1934,7 @@ mark_inline_for_output (decl)
        }
       DECL_PENDING_INLINE_INFO (decl) = 0;
     }
-  pending_addressable_inlines = perm_tree_cons (NULL_TREE, decl,
-                                               pending_addressable_inlines);
+  saved_inlines = perm_tree_cons (NULL_TREE, decl, saved_inlines);
 }
 
 void
@@ -2275,7 +2291,7 @@ coerce_delete_type (type)
 }
 \f
 static void
-write_vtable_entries (decl)
+mark_vtable_entries (decl)
      tree decl;
 {
   tree entries = TREE_CHAIN (CONSTRUCTOR_ELTS (DECL_INITIAL (decl)));
@@ -2287,51 +2303,16 @@ write_vtable_entries (decl)
     {
       tree fnaddr = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries));
       tree fn = TREE_OPERAND (fnaddr, 0);
-      if (! DECL_EXTERNAL (fn) && ! TREE_ASM_WRITTEN (fn)
-         && DECL_SAVED_INSNS (fn))
-       {
-         if (TREE_PUBLIC (DECL_CLASS_CONTEXT (fn)))
-           TREE_PUBLIC (fn) = 1;
-         TREE_ADDRESSABLE (fn) = 1;
-         temporary_allocation ();
-         output_inline_function (fn);
-         permanent_allocation (1);
-       }
-      else
-       assemble_external (fn);
+      TREE_ADDRESSABLE (fn) = 1;
     }
 }
 
-/* Note even though prev is never used in here, walk_vtables
-   expects this to have two arguments, so concede.  */
-static void
-finish_vtable_typedecl (prev, vars)
-     tree prev, vars;
-{
-  tree decl = TYPE_BINFO_VTABLE (TREE_TYPE (vars));
-
-  /* If we are controlled by `+e2', obey.  */
-  if (write_virtuals == 2)
-    {
-      tree binfo = value_member (DECL_NAME (vars), pending_vtables);
-      if (binfo)
-       TREE_PURPOSE (binfo) = void_type_node;
-      else
-       decl = NULL_TREE;
-    }
-  /* If this type has inline virtual functions, then
-     write those functions out now.  */
-  if (decl && write_virtuals >= 0
-      && ! DECL_EXTERNAL (decl) && (TREE_PUBLIC (decl) || TREE_USED (decl)))
-    write_vtable_entries (decl);
-}
-
 static void
 finish_vtable_vardecl (prev, vars)
      tree prev, vars;
 {
   tree ctype = DECL_CONTEXT (vars);
-  if (flag_vtable_hack && !CLASSTYPE_INTERFACE_KNOWN (ctype))
+  if (flag_vtable_thunks && !CLASSTYPE_INTERFACE_KNOWN (ctype))
     {
       tree method;
       for (method = CLASSTYPE_METHODS (ctype); method != NULL_TREE;
@@ -2339,6 +2320,8 @@ finish_vtable_vardecl (prev, vars)
        {
          if (DECL_VINDEX (method) != NULL_TREE && !DECL_SAVED_INSNS (method))
            {
+             SET_CLASSTYPE_INTERFACE_KNOWN (ctype);
+             CLASSTYPE_INTERFACE_ONLY (ctype) = DECL_EXTERNAL (method);
              TREE_PUBLIC (vars) = 1;
              DECL_EXTERNAL (vars) = DECL_EXTERNAL (method);
              break;
@@ -2354,15 +2337,32 @@ finish_vtable_vardecl (prev, vars)
       /* Stuff this virtual function table's size into
         `pfn' slot of `the_null_vtable_entry'.  */
       tree nelts = array_type_nelts (TREE_TYPE (vars));
-      SET_FNADDR_FROM_VTABLE_ENTRY (the_null_vtable_entry, nelts);
+      if (flag_vtable_thunks)
+       TREE_VALUE (CONSTRUCTOR_ELTS (DECL_INITIAL (vars))) = nelts;
+      else
+       SET_FNADDR_FROM_VTABLE_ENTRY (the_null_vtable_entry, nelts);
       /* Kick out the dossier before writing out the vtable.  */
       if (flag_dossier)
        rest_of_decl_compilation (TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (TREE_CHAIN (CONSTRUCTOR_ELTS (DECL_INITIAL (vars))))), 0), 0, 1, 1);
 
       /* Write it out.  */
-      write_vtable_entries (vars);
+      mark_vtable_entries (vars);
       if (TREE_TYPE (DECL_INITIAL (vars)) == 0)
-       store_init_value (vars, DECL_INITIAL (vars));
+         store_init_value (vars, DECL_INITIAL (vars));
+      if (flag_vtable_thunks)
+       {
+         tree list = CONSTRUCTOR_ELTS (DECL_INITIAL (vars));
+         for (; list; list = TREE_CHAIN (list))
+           {
+             tree vfunc = TREE_VALUE (list);
+             if (TREE_CODE (vfunc) == ADDR_EXPR)
+               {
+                 vfunc = TREE_OPERAND (vfunc, 0);
+                 if (TREE_CODE (vfunc) == THUNK_DECL)
+                   emit_thunk (vfunc);
+               }
+           }
+       }
 
 #ifdef DWARF_DEBUGGING_INFO
       if (write_symbols == DWARF_DEBUG)
@@ -2394,7 +2394,7 @@ finish_vtable_vardecl (prev, vars)
 
       rest_of_decl_compilation (vars, 0, 1, 1);
     }
-  else if (TREE_USED (vars) && flag_vtable_hack)
+  else if (TREE_USED (vars) && flag_vtable_thunks)
     assemble_external (vars);
   /* We know that PREV must be non-zero here.  */
   TREE_CHAIN (prev) = TREE_CHAIN (vars);
@@ -2679,23 +2679,6 @@ finish_file ()
   parse_time -= this_time - start_time;
   varconst_time += this_time - start_time;
 
-  /* Now write out inline functions which had their addresses taken
-     and which were not declared virtual and which were not declared
-     `extern inline'.  */
-  while (pending_addressable_inlines)
-    {
-      tree decl = TREE_VALUE (pending_addressable_inlines);
-      if (! TREE_ASM_WRITTEN (decl)
-         && ! DECL_EXTERNAL (decl)
-         && DECL_SAVED_INSNS (decl))
-       {
-         temporary_allocation ();
-         output_inline_function (decl);
-         permanent_allocation (1);
-       }
-      pending_addressable_inlines = TREE_CHAIN (pending_addressable_inlines);
-    }
-
   start_time = get_run_time ();
 
   /* Now delete from the chain of variables all virtual function tables.
@@ -2726,7 +2709,38 @@ finish_file ()
   pushdecl (vars);
 #endif
 
-  walk_vtables (finish_vtable_typedecl, finish_vtable_vardecl);
+  walk_vtables ((void (*)())0, finish_vtable_vardecl);
+
+  /* Now write out inline functions which had their addresses taken
+     and which were not declared virtual and which were not declared
+     `extern inline'.  */
+  while (saved_inlines)
+    {
+      tree decl = TREE_VALUE (saved_inlines);
+      saved_inlines = TREE_CHAIN (saved_inlines);
+      if (TREE_ASM_WRITTEN (decl))
+       continue;
+      if (DECL_FUNCTION_MEMBER_P (decl) && !TREE_PUBLIC (decl))
+       {
+         tree ctype = DECL_CLASS_CONTEXT (decl);
+         if (CLASSTYPE_INTERFACE_KNOWN (ctype))
+           {
+             TREE_PUBLIC (decl) = 1;
+             DECL_EXTERNAL (decl) = CLASSTYPE_INTERFACE_ONLY (ctype);
+           }
+       }
+      if (TREE_PUBLIC (decl) || TREE_ADDRESSABLE (decl))
+       {
+         if (DECL_EXTERNAL (decl))
+           assemble_external (decl);
+         else
+           {   
+             temporary_allocation ();
+             output_inline_function (decl);
+             permanent_allocation (1);
+           }
+       }
+    }
 
   if (write_virtuals == 2)
     {
@@ -2839,8 +2853,11 @@ reparse_decl_as_expr1 (decl)
     case BIT_NOT_EXPR:
       return build_x_unary_op (BIT_NOT_EXPR,
                               reparse_decl_as_expr1 (TREE_OPERAND (decl, 0)));
+
+    default:
+      my_friendly_abort (5);
+      return NULL_TREE;
     }
-  my_friendly_abort (5);
 }
 
 /* This is something of the form `int (*a)++' that has turned out to be an
@@ -2865,6 +2882,8 @@ tree
 finish_decl_parsing (decl)
      tree decl;
 {
+  extern int current_class_depth;
+  
   switch (TREE_CODE (decl))
     {
     case IDENTIFIER_NODE:
@@ -2878,5 +2897,12 @@ finish_decl_parsing (decl)
     case BIT_NOT_EXPR:
       TREE_OPERAND (decl, 0) = finish_decl_parsing (TREE_OPERAND (decl, 0));
       return decl;
+    case SCOPE_REF:
+      push_nested_class (TREE_OPERAND (decl, 0), 3);
+      TREE_COMPLEXITY (decl) = current_class_depth;
+      return decl;
+    default:
+      my_friendly_abort (5);
+      return NULL_TREE;
     }
 }
index 335a304..2cf2b87 100644 (file)
@@ -112,7 +112,7 @@ cp_thing (errfn, atarg1, format, arglist)
       if (*f == 'l')
        ++f;
 
-      function = cp_printers[*f];
+      function = cp_printers[(int)*f];
 
       if (function)
        {
index 3cc3ce8..781453a 100644 (file)
@@ -92,9 +92,6 @@ init_error ()
   scratch_firstobj = (char *)obstack_alloc (&scratch_obstack, 0);
 }
 
-/* Counter to help build parameter names in case they were omitted.  */
-static int dummy_name;
-
 enum pad { none, before, after };
 
 static void
@@ -505,8 +502,9 @@ ident_fndecl (t)
   else if (TREE_CODE (n) == TREE_LIST
           && TREE_CODE (TREE_VALUE (n)) == FUNCTION_DECL)
     return TREE_VALUE (n);
-  else
-    my_friendly_abort (66);
+
+  my_friendly_abort (66);
+  return NULL_TREE;
 }
 
 #ifndef NO_DOLLAR_IN_LABEL
@@ -715,7 +713,6 @@ dump_function_decl (t, v)
   tree fntype = TREE_TYPE (t);
   tree parmtypes = TYPE_ARG_TYPES (fntype);
   tree cname = NULL_TREE;
-  int spaces = 0;
 
   /* Friends have DECL_CLASS_CONTEXT set, but not DECL_CONTEXT.  */
   if (DECL_CONTEXT (t))
@@ -1335,6 +1332,7 @@ code_as_string (c, v)
 char *
 language_as_string (c, v)
      enum languages c;
+     int v;
 {
   switch (c)
     {
@@ -1346,13 +1344,14 @@ language_as_string (c, v)
 
     default:
       my_friendly_abort (355);
+      return 0;
     }
 }
 
 /* Return the proper printed version of a parameter to a C++ function.  */
 char *
 parm_as_string (p, v)
-     int p;
+     int p, v;
 {
   if (p < 0)
     return "`this'";
@@ -1364,6 +1363,7 @@ parm_as_string (p, v)
 char *
 op_as_string (p, v)
      enum tree_code p;
+     int v;
 {
   static char buf[] = "operator                ";
 
index c606ef0..b59fefe 100644 (file)
@@ -211,6 +211,9 @@ cplus_expand_expr (exp, target, tmode, modifier)
 #endif
       }
 
+    case THUNK_DECL:
+      return DECL_RTL (exp);
+
     default:
       break;
     }
index eeb5de6..90ff11c 100644 (file)
@@ -50,6 +50,7 @@ void expand_aggr_init ();
 static void expand_aggr_init_1 ();
 static void expand_recursive_init_1 ();
 static void expand_recursive_init ();
+static void expand_virtual_init PROTO((tree, tree, tree));
 tree expand_vec_init ();
 tree build_vec_delete ();
 
@@ -60,7 +61,9 @@ static tree BIN, BID;
 
 /* Cache the identifier nodes for the two magic field of a new cookie.  */
 static tree nc_nelts_field_id;
+#if 0
 static tree nc_ptr_2comp_field_id;
+#endif
 
 static tree minus_one;
 
@@ -122,7 +125,7 @@ init_vtbl_ptrs (binfo, init_self, can_elide)
   if (init_self && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
     {
       tree base_ptr = convert_pointer_to_real (binfo, current_class_decl);
-      expand_expr_stmt (build_virtual_init (binfo, binfo, base_ptr));
+      expand_virtual_init (binfo, binfo, base_ptr);
     }
 }
 \f
@@ -345,13 +348,12 @@ emit_base_init (t, immediately)
 {
   extern tree in_charge_identifier;
 
-  tree member, decl, vbases;
-  tree init_list, member_init;
+  tree member, vbases;
+  tree init_list;
   int pass, start;
   tree t_binfo = TYPE_BINFO (t);
   tree binfos = BINFO_BASETYPES (t_binfo);
   int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-  tree fields_to_unmark = NULL_TREE;
   int have_init_list = 0, from_init_list;
 
   if (! immediately)
@@ -600,8 +602,8 @@ emit_base_init (t, immediately)
   /* Initialize all the virtual function table fields that
      do come from virtual base classes. */
   if (TYPE_USES_VIRTUAL_BASECLASSES (t))
-    expand_expr_stmt (build_vbase_vtables_init (t_binfo, t_binfo,
-                                               C_C_D, current_class_decl, 0));
+    expand_vbase_vtables_init (t_binfo, t_binfo,
+                               C_C_D, current_class_decl, 0);
   for (vbases = CLASSTYPE_VBASECLASSES (t); vbases; vbases = TREE_CHAIN (vbases))
     CLEAR_BINFO_BASEINIT_MARKED (vbases);
 
@@ -610,8 +612,7 @@ emit_base_init (t, immediately)
   init_vtbl_ptrs (t_binfo, 0, 1);
 
   if (CLASSTYPE_NEEDS_VIRTUAL_REINIT (t))
-    expand_expr_stmt (build_virtual_init (TYPE_BINFO (t), t,
-                                         current_class_decl));
+    expand_virtual_init (TYPE_BINFO (t), t, current_class_decl);
 
   if (current_member_init_list)
     {
@@ -704,8 +705,8 @@ check_base_init (t)
 
    BINFO is the exact type that DECL is supposed to be.  In
    multiple inheritance, this might mean "C's A" if C : A, B.  */
-tree
-build_virtual_init (main_binfo, binfo, decl)
+static void
+expand_virtual_init (main_binfo, binfo, decl)
      tree main_binfo, binfo;
      tree decl;
 {
@@ -733,7 +734,6 @@ build_virtual_init (main_binfo, binfo, decl)
     {
       tree binfos = TYPE_BINFO_BASETYPES (TREE_TYPE (TREE_TYPE (decl)));
       int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-      tree result = NULL_TREE;
 
       for (i = n_baselinks-1; i >= 0; i--)
        {
@@ -751,9 +751,9 @@ build_virtual_init (main_binfo, binfo, decl)
          else
            this_decl = build (PLUS_EXPR, TYPE_POINTER_TO (BINFO_TYPE (base_binfo)),
                               decl, BINFO_OFFSET (base_binfo));
-         result = tree_cons (NULL_TREE, build_virtual_init (main_binfo, base_binfo, this_decl), result);
+         expand_virtual_init (main_binfo, base_binfo, this_decl);
        }
-      return build_compound_expr (result);
+      return;
     }
 #endif
 
@@ -779,11 +779,11 @@ build_virtual_init (main_binfo, binfo, decl)
   decl = convert_pointer_to_real (vtype_binfo, decl);
   vtbl_ptr = build_vfield_ref (build_indirect_ref (decl, NULL_PTR), vtype);
   if (vtbl_ptr == error_mark_node)
-    return error_mark_node;
+    return;
 
   /* Have to convert VTBL since array sizes may be different.  */
-  return build_modify_expr (vtbl_ptr, NOP_EXPR,
-                           convert (TREE_TYPE (vtbl_ptr), vtbl));
+  expand_expr_stmt (build_modify_expr (vtbl_ptr, NOP_EXPR,
+                                      convert (TREE_TYPE (vtbl_ptr), vtbl)));
 }
 
 /* Subroutine of `expand_aggr_vbase_init'.
@@ -1304,8 +1304,7 @@ expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags)
              tree addr = build_unary_op (ADDR_EXPR, exp, 0);
              expand_aggr_vbase_init (binfo, exp, addr, NULL_TREE);
 
-             expand_expr_stmt (build_vbase_vtables_init (binfo, binfo,
-                                                         exp, addr, 1));
+             expand_vbase_vtables_init (binfo, binfo, exp, addr, 1);
            }
          expand_expr_stmt (build_modify_expr (exp, INIT_EXPR, init));
          return;
@@ -1427,7 +1426,6 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, alias_this, flags)
 {
   tree type = TREE_TYPE (exp);
   tree init_type = NULL_TREE;
-  tree rval;
 
   my_friendly_assert (init != error_mark_node && type != error_mark_node, 211);
 
@@ -1716,13 +1714,13 @@ expand_recursive_init_1 (binfo, true_exp, addr, init_list, alias_this)
              if (TREE_VALUE (init_list))
                {
                  /* We have to ensure that the second argment to
-                    build_virtual_init is in binfo's hierarchy.  */
-                 expand_expr_stmt (build_virtual_init (binfo,
-                                                       get_binfo (TREE_VALUE (init_list), binfo, 0),
-                                                       addr));
+                    expand_virtual_init is in binfo's hierarchy.  */
+                 expand_virtual_init (binfo,
+                                     get_binfo (TREE_VALUE (init_list), binfo, 0),
+                                     addr);
                  if (TREE_VALUE (init_list) == binfo
                      && TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
-                   expand_expr_stmt (build_vbase_vtables_init (binfo, binfo, true_exp, addr, 1));
+                   expand_vbase_vtables_init (binfo,binfo, true_exp, addr, 1);
                }
            }
          else
@@ -1771,7 +1769,7 @@ expand_recursive_init (binfo, true_exp, exp, init, init_list, alias_this)
   if (true_exp == exp && TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
     {
       expand_aggr_vbase_init (binfo, exp, addr, init_list);
-      expand_expr_stmt (build_vbase_vtables_init (binfo, binfo, true_exp, addr, 1));
+      expand_vbase_vtables_init (binfo, binfo, true_exp, addr, 1);
     }
   expand_recursive_init_1 (binfo, true_exp, addr, init_list, alias_this);
 
@@ -1858,8 +1856,6 @@ tree
 get_type_value (name)
      tree name;
 {
-  tree type;
-
   if (name == error_mark_node)
     return NULL_TREE;
 
@@ -1952,7 +1948,7 @@ build_member_call (cname, name, parmlist)
     return build_method_call (decl, method_name, parmlist, basetype_path,
                              LOOKUP_NORMAL|LOOKUP_NONVIRTUAL);
   if (TREE_CODE (name) == IDENTIFIER_NODE
-      && (t = lookup_field (TYPE_BINFO (type), name, 1, 0)))
+      && ((t = lookup_field (TYPE_BINFO (type), name, 1, 0))))
     {
       if (t == error_mark_node)
        return error_mark_node;
@@ -2525,8 +2521,10 @@ add_friend (type, decl)
            {
              if (decl == TREE_VALUE (friends))
                {
-                 cp_pedwarn_at ("`%D' is already a friend of class `%T'",
-                                decl, type);
+                 cp_pedwarn ("`%D' is already a friend of class `%T'",
+                             decl, type);
+                 cp_pedwarn_at ("previous friend declaration of `%D'",
+                                TREE_VALUE (friends));
                  return;
                }
            }
@@ -2606,9 +2604,9 @@ static void
 xref_friend (type, decl, ctype)
      tree type, decl, ctype;
 {
-  tree typedecl = TYPE_NAME (type);
   tree friend_decl = TYPE_NAME (ctype);
 #if 0
+  tree typedecl = TYPE_NAME (type);
   tree t = tree_cons (NULL_TREE, ctype, DECL_UNDEFINED_FRIENDS (typedecl));
 
   DECL_UNDEFINED_FRIENDS (typedecl) = t;
@@ -2841,18 +2839,8 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals)
       make_decl_rtl (decl, NULL_PTR, 1);
       add_friend (current_class_type, decl);
 
-      if (! TREE_OVERLOADED (declarator)
-         && IDENTIFIER_GLOBAL_VALUE (declarator)
-         && TREE_CODE (IDENTIFIER_GLOBAL_VALUE (declarator)) == FUNCTION_DECL)
-       {
-         error ("friend `%s' implicitly overloaded",
-                IDENTIFIER_POINTER (declarator));
-         cp_error_at ("after declaration of non-overloaded `%D'", IDENTIFIER_GLOBAL_VALUE (declarator));
-       }
       DECL_FRIEND_P (decl) = 1;
-      DECL_OVERLOADED (decl) = 1;
       TREE_OVERLOADED (declarator) = 1;
-      decl = push_overloaded_decl (decl, 1);
     }
   else
     {
@@ -2973,7 +2961,7 @@ build_builtin_call (type, node, arglist)
 
    Unless I am mistaken, a call to new () will return initialized
    data regardless of whether the constructor itself is private or
-   not.
+   not.  NOPE; new fails if the constructor is private (jcm).
 
    Note that build_new does nothing to assure that any special
    alignment requirements of the type are met.  Rather, it leaves
@@ -2990,8 +2978,8 @@ build_new (placement, decl, init, use_global_new)
      int use_global_new;
 {
   tree type, true_type, size, rval;
-  tree init1 = NULL_TREE, nelts;
-  int has_call = 0, has_array = 0;
+  tree nelts;
+  int has_array = 0;
 
   tree pending_sizes = NULL_TREE;
 
@@ -3014,13 +3002,7 @@ build_new (placement, decl, init, use_global_new)
       nelts = integer_one_node;
 
       if (absdcl && TREE_CODE (absdcl) == CALL_EXPR)
-       {
-         /* probably meant to be a call */
-         has_call = 1;
-         init1 = TREE_OPERAND (absdcl, 1);
-         absdcl = TREE_OPERAND (absdcl, 0);
-         TREE_VALUE (decl) = absdcl;
-       }
+       my_friendly_abort (215);
       while (absdcl && TREE_CODE (absdcl) == INDIRECT_REF)
        {
          last_absdcl = absdcl;
@@ -3047,7 +3029,7 @@ build_new (placement, decl, init, use_global_new)
                error ("new of array type fails to specify size");
              else
                {
-                 this_nelts = save_expr (this_nelts);
+                 this_nelts = save_expr (convert (sizetype, this_nelts));
                  absdcl = TREE_OPERAND (absdcl, 0);
                  if (this_nelts == integer_zero_node)
                    {
@@ -3068,25 +3050,12 @@ build_new (placement, decl, init, use_global_new)
        TREE_VALUE (decl) = absdcl;
 
       type = true_type = groktypename (decl);
-      if (! type || type == error_mark_node
-         || true_type == error_mark_node)
+      if (! type || type == error_mark_node)
        {
          immediate_size_expand = old_immediate_size_expand;
          return error_mark_node;
        }
 
-      /* ``A reference cannot be created by the new operator.  A reference
-        is not an object (8.2.2, 8.4.3), so a pointer to it could not be
-        returned by new.'' ARM 5.3.3 */
-      if (TREE_CODE (type) == REFERENCE_TYPE)
-       error ("new cannot be applied to a reference type");
-
-      type = TYPE_MAIN_VARIANT (type);
-      if (type == void_type_node)
-       {
-         error ("invalid type: `void []'");
-         return error_mark_node;
-       }
       if (current_function_decl
          && DECL_CONSTRUCTOR_P (current_function_decl))
        {
@@ -3123,42 +3092,37 @@ build_new (placement, decl, init, use_global_new)
       decl = TYPE_NAME (type);
     }
 
-  if (TYPE_SIZE (type) == 0)
+  /* ``A reference cannot be created by the new operator.  A reference
+     is not an object (8.2.2, 8.4.3), so a pointer to it could not be
+     returned by new.'' ARM 5.3.3 */
+  if (TREE_CODE (type) == REFERENCE_TYPE)
     {
-      if (type == void_type_node)
-       error ("invalid type for new: `void'");
-      else
-       incomplete_type_error (0, type);
-      return error_mark_node;
+      error ("new cannot be applied to a reference type");
+      type = true_type = TREE_TYPE (type);
     }
 
-  if (TYPE_LANG_SPECIFIC (type) && CLASSTYPE_ABSTRACT_VIRTUALS (type))
+  /* When the object being created is an array, the new-expression yields a
+     pointer to the initial element (if any) of the array.  For example,
+     both new int and new int[10] return an int*.  5.3.4.  */
+  if (TREE_CODE (type) == ARRAY_TYPE && has_array == 0)
     {
-      abstract_virtuals_error (NULL_TREE, type);
-      return error_mark_node;
+      nelts = array_type_nelts_top (type);
+      has_array = 1;
+      type = true_type = TREE_TYPE (type);
     }
 
-  if (TYPE_LANG_SPECIFIC (type) && IS_SIGNATURE (type))
+  if (TYPE_READONLY (type) || TYPE_VOLATILE (type))
     {
-      signature_error (NULL_TREE, type);
-      return error_mark_node;
+      pedwarn ("const and volatile types cannot be created with operator new");
+      type = true_type = TYPE_MAIN_VARIANT (type);
     }
-
+  
   /* If our base type is an array, then make sure we know how many elements
      it has.  */
   while (TREE_CODE (true_type) == ARRAY_TYPE)
     {
       tree this_nelts = array_type_nelts_top (true_type);
-      if (nelts == integer_one_node)
-       {
-         has_array = 1;
-         nelts = this_nelts;
-       }
-      else
-       {
-         my_friendly_assert (has_array != 0, 216);
-         nelts = build_binary_op (MULT_EXPR, nelts, this_nelts, 1);
-       }
+      nelts = build_binary_op (MULT_EXPR, nelts, this_nelts, 1);
       true_type = TREE_TYPE (true_type);
     }
   if (has_array)
@@ -3167,8 +3131,27 @@ build_new (placement, decl, init, use_global_new)
   else
     size = size_in_bytes (type);
 
-  if (has_call)
-    init = init1;
+  if (TYPE_SIZE (true_type) == 0)
+    {
+      if (true_type == void_type_node)
+       error ("invalid type for new: `void'");
+      else
+       incomplete_type_error (0, true_type);
+      return error_mark_node;
+    }
+
+  if (TYPE_LANG_SPECIFIC (true_type)
+      && CLASSTYPE_ABSTRACT_VIRTUALS (true_type))
+    {
+      abstract_virtuals_error (NULL_TREE, true_type);
+      return error_mark_node;
+    }
+
+  if (TYPE_LANG_SPECIFIC (true_type) && IS_SIGNATURE (true_type))
+    {
+      signature_error (NULL_TREE, true_type);
+      return error_mark_node;
+    }
 
   /* Get a little extra space to store a couple of things before the new'ed
      array. */
@@ -3182,7 +3165,8 @@ build_new (placement, decl, init, use_global_new)
   /* Allocate the object. */
   if (TYPE_LANG_SPECIFIC (true_type)
       && (TREE_GETS_NEW (true_type) || TREE_GETS_PLACED_NEW (true_type))
-      && !use_global_new)
+      && !use_global_new
+      && !has_array)
     rval = build_opfncall (NEW_EXPR, LOOKUP_NORMAL,
                           TYPE_POINTER_TO (true_type), size, placement);
   else if (placement)
@@ -3302,8 +3286,7 @@ build_new (placement, decl, init, use_global_new)
   if (init == void_type_node)
     goto done;
 
-  if (TYPE_NEEDS_CONSTRUCTING (type)
-      || (has_call || init))
+  if (TYPE_NEEDS_CONSTRUCTING (type) || init)
     {
       if (! TYPE_NEEDS_CONSTRUCTING (type) && ! IS_AGGR_TYPE (type))
        {
@@ -3719,8 +3702,6 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
 
   if (! TYPE_NEEDS_DESTRUCTOR (type))
     {
-      tree virtual_size;
-
       if (auto_delete == integer_zero_node)
        return void_zero_node;
 
@@ -4100,7 +4081,7 @@ build_vec_delete (base, maxindex, elt_size, dtor_dummy, auto_delete_vec, auto_de
       /* This is the real size */
       virtual_size = size_binop (PLUS_EXPR, virtual_size, BI_header_size);
       body = build_tree_list (NULL_TREE,
-                             build_x_delete (ptr_type_node, base_tbd, 0,
+                             build_x_delete (ptr_type_node, base_tbd, 1,
                                              virtual_size));
       body = build (COND_EXPR, void_type_node,
                    build (BIT_AND_EXPR, integer_type_node,
@@ -4112,7 +4093,7 @@ build_vec_delete (base, maxindex, elt_size, dtor_dummy, auto_delete_vec, auto_de
 
   body = tree_cons (NULL_TREE,
                    build_delete (ptype, tbase, auto_delete,
-                                 LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0),
+                                 LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 1),
                    body);
 
   body = tree_cons (NULL_TREE,
index 8f7c2be..26155a7 100644 (file)
@@ -21,10 +21,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 /* This file is the lexical analyzer for GNU C++.  */
 
-#if defined(GATHER_STATISTICS) || defined(SPEW_DEBUG)
-#undef YYDEBUG
+/* Cause the `yydebug' variable to be defined.  */
 #define YYDEBUG 1
-#endif
 
 #include <sys/types.h>
 #include <stdio.h>
@@ -898,7 +896,6 @@ yyhook (yyn)
 {
   reduce_count[yyn] += 1;
 }
-#endif
 
 static int
 reduce_cmp (p, q)
@@ -913,6 +910,7 @@ token_cmp (p, q)
 {
   return token_count[*q] - token_count[*p];
 }
+#endif
 
 void
 print_parse_statistics ()
@@ -1829,7 +1827,7 @@ cons_up_default_function (type, name, fields, kind)
                 IDENTIFIER_POINTER (t), func_buf);
       }
   }
-#endif /* DEBUG_DEFAULT_FUNCTIONS
+#endif /* DEBUG_DEFAULT_FUNCTIONS */
 
   DECL_CLASS_CONTEXT (fn) = type;
 
@@ -1858,6 +1856,7 @@ largest_union_member (type)
 
   /* We should always find one.  */
   my_friendly_abort (323);
+  return NULL_TREE;
 }
 
 /* Construct the body of a default assignment operator.
@@ -1946,7 +1945,7 @@ default_assign_ref_body (bufp, lenp, type, fields)
        {
          tree binfo = TREE_VEC_ELT (bases, i);
          tree btype, name;
-         char *s, *p;
+         char *s;
 
          btype = BINFO_TYPE (binfo);
          name = TYPE_NESTED_NAME (btype);
@@ -1976,7 +1975,7 @@ default_assign_ref_body (bufp, lenp, type, fields)
        {
          if (TREE_CODE (f) == FIELD_DECL && ! DECL_VIRTUAL_P (f))
            {
-             char *s, *p;
+             char *s;
              tree x;
              tree t = TREE_TYPE (f);
 
@@ -2098,7 +2097,7 @@ default_copy_constructor_body (bufp, lenp, type, fields)
       for (;;)
        {
          tree binfo, btype, name;
-         char *s, *p;
+         char *s;
 
          if (v)
            {
@@ -2143,7 +2142,7 @@ default_copy_constructor_body (bufp, lenp, type, fields)
        {
          if (TREE_CODE (f) == FIELD_DECL && ! DECL_VIRTUAL_P (f))
            {
-             char *s, *p;
+             char *s;
              tree x;
              tree t = TREE_TYPE (f);
 
@@ -2469,9 +2468,6 @@ check_newline ()
 
                      if (impl_file_chain == 0)
                        {
-                         char *filename;
-                         tree fi;
-
                          /* If this is zero at this point, then we are
                             auto-implementing.  */
                          if (main_input_filename == 0)
@@ -2577,10 +2573,16 @@ check_newline ()
                      else
                        error ("`#pragma implementation' can only appear at top-level");
                      interface_only = 0;
+#if 0
                      /* We make this non-zero so that we infer decl linkage
                         in the impl file only for variables first declared
                         in the interface file.  */
                      interface_unknown = 1;
+#else
+                     /* We make this zero so that templates in the impl
+                         file will be emitted properly. */
+                     interface_unknown = 0;
+#endif
                      TREE_INT_CST_LOW (fileinfo) = interface_only;
                      TREE_INT_CST_HIGH (fileinfo) = interface_unknown;
                    }
@@ -4679,7 +4681,8 @@ make_lang_type (code)
   SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, interface_unknown);
   CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
   CLASSTYPE_VBASE_SIZE (t) = integer_zero_node;
-  TYPE_BINFO (t) = make_binfo (integer_zero_node, t, 0, 0, 0);
+  TYPE_BINFO (t) = make_binfo (integer_zero_node, t, NULL_TREE, NULL_TREE,
+                              NULL_TREE);
   CLASSTYPE_BINFO_AS_LIST (t) = build_tree_list (NULL_TREE, TYPE_BINFO (t));
 
   /* Make sure this is laid out, for ease of use later.
index 0345065..cdf3d19 100644 (file)
@@ -32,6 +32,11 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "class.h"
 #include "obstack.h"
 #include <ctype.h>
+#include "rtl.h"
+#include "expr.h"
+#include "output.h"
+#include "hard-reg-set.h"
+#include "flags.h"
 
 /* TREE_LIST of the current inline functions that need to be
    processed.  */
@@ -495,7 +500,7 @@ build_overload_name (parmtypes, begin, end)
 
   if (begin) OB_INIT ();
 
-  if (just_one = (TREE_CODE (parmtypes) != TREE_LIST))
+  if ((just_one = (TREE_CODE (parmtypes) != TREE_LIST)))
     {
       parmtype = parmtypes;
       goto only_one;
@@ -1651,3 +1656,254 @@ build_component_type_expr (of, component, basetype_path, protect)
            TREE_TYPE (name));
   return error_mark_node;
 }
+\f
+static char *
+thunk_printable_name (decl)
+     tree decl;
+{
+  return "<thunk function>";
+}
+
+tree
+make_thunk (function, delta)
+     tree function;
+     int delta;
+{
+  char buffer[250];
+  tree thunk_fndecl;
+  tree thunk;
+  static int thunk_number = 0;
+  tree func_decl;
+  if (TREE_CODE (function) != ADDR_EXPR)
+    abort ();
+  func_decl = TREE_OPERAND (function, 0);
+  if (TREE_CODE (func_decl) != FUNCTION_DECL)
+    abort ();
+  sprintf (buffer, "__thunk_%d_%d", -delta, thunk_number++);
+  thunk = build_decl (THUNK_DECL, get_identifier (buffer),
+                     TREE_TYPE (func_decl));
+  DECL_RESULT (thunk)
+    = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
+  make_function_rtl (thunk);
+  DECL_INITIAL (thunk) = function;
+  THUNK_DELTA (thunk) = delta;
+  return thunk;
+}
+
+void
+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);
+  int tem;
+  int failure = 0;
+
+  /* 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 this_rtx = 0, this_reg_rtx = 0, fixed_this_rtx;
+
+  char *(*save_decl_printable_name) () = decl_printable_name;
+  /* Data on reg parms scanned so far.  */
+  CUMULATIVE_ARGS args_so_far;
+
+  if (TREE_ASM_WRITTEN (thunk_fndecl))
+    return;
+
+  decl_printable_name = thunk_printable_name;
+  if (current_function_decl)
+    abort ();
+  current_function_decl = thunk_fndecl;
+  init_function_start (thunk_fndecl, input_filename, lineno);
+  pushlevel (0);
+  expand_start_bindings (1);
+
+  /* Start updating where the next arg would go.  */
+  INIT_CUMULATIVE_ARGS (args_so_far, TREE_TYPE (function), NULL_RTX);
+  stack_args_size.constant = 0;
+  stack_args_size.var = 0;
+  /* SETUP for possible structure return address FIXME */
+
+  /* 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. */
+  for (argp = TYPE_ARG_TYPES (TREE_TYPE (function));
+       argp != NULL_TREE;
+       argp = TREE_CHAIN (argp))
+
+    {
+      tree passed_type = TREE_VALUE (argp);
+      register rtx entry_parm;
+      int named = 1; /* FIXME */
+      struct args_size stack_offset;
+      struct args_size arg_size;
+
+      if (passed_type == void_type_node)
+       break;
+
+      if ((TREE_CODE (TYPE_SIZE (passed_type)) != INTEGER_CST
+          && contains_placeholder_p (TYPE_SIZE (passed_type)))
+#ifdef FUNCTION_ARG_PASS_BY_REFERENCE
+         || FUNCTION_ARG_PASS_BY_REFERENCE (args_so_far,
+                                            TYPE_MODE (passed_type),
+                                            passed_type, named)
+#endif
+         )
+       passed_type = build_pointer_type (passed_type);
+
+      entry_parm = FUNCTION_ARG (args_so_far,
+                                TYPE_MODE (passed_type),
+                                passed_type,
+                                named);
+      if (entry_parm != 0)
+       need_use[need_use_count++] = entry_parm;
+
+      locate_and_pad_parm (TYPE_MODE (passed_type), passed_type,
+#ifdef STACK_PARMS_IN_REG_PARM_AREA
+                          1,
+#else
+                          entry_parm != 0,
+#endif
+                          thunk_fndecl,
+                          &stack_args_size, &stack_offset, &arg_size);
+
+/*    REGNO (entry_parm);*/
+      if (this_rtx == 0)
+       {
+         this_reg_rtx = entry_parm;
+         if (!entry_parm)
+           {
+             rtx offset_rtx = ARGS_SIZE_RTX (stack_offset);
+
+             rtx internal_arg_pointer, stack_parm;
+
+             if ((ARG_POINTER_REGNUM == STACK_POINTER_REGNUM
+                  || ! (fixed_regs[ARG_POINTER_REGNUM]
+                        || ARG_POINTER_REGNUM == FRAME_POINTER_REGNUM)))
+               internal_arg_pointer = copy_to_reg (virtual_incoming_args_rtx);
+             else
+               internal_arg_pointer = virtual_incoming_args_rtx;
+
+             if (offset_rtx == const0_rtx)
+               entry_parm = gen_rtx (MEM, TYPE_MODE (passed_type),
+                                     internal_arg_pointer);
+             else
+               entry_parm = gen_rtx (MEM, TYPE_MODE (passed_type),
+                                     gen_rtx (PLUS, Pmode,
+                                              internal_arg_pointer, 
+                                              offset_rtx));
+           }
+         
+         this_rtx = entry_parm;
+       }
+
+      FUNCTION_ARG_ADVANCE (args_so_far,
+                           TYPE_MODE (passed_type),
+                           passed_type,
+                           named);
+    }
+
+  fixed_this_rtx = plus_constant (this_rtx, delta);
+  if (this_rtx != fixed_this_rtx)
+    emit_move_insn (this_rtx, fixed_this_rtx);
+
+  if (this_reg_rtx)
+    emit_insn (gen_rtx (USE, VOIDmode, this_reg_rtx));
+
+  emit_indirect_jump (XEXP (DECL_RTL (function), 0));
+
+  while (need_use_count > 0)
+    emit_insn (gen_rtx (USE, VOIDmode, need_use[--need_use_count]));
+
+  expand_end_bindings (NULL, 1, 0);
+  poplevel (0, 0, 1);
+
+  TREE_ASM_WRITTEN (thunk_fndecl) = 1;
+
+  /* From now on, allocate rtl in current_obstack, not in saveable_obstack.
+     Note that that may have been done above, in save_for_inline_copying.
+     The call to resume_temporary_allocation near the end of this function
+     goes back to the usual state of affairs.  */
+
+  rtl_in_current_obstack ();
+
+  insns = get_insns ();
+
+  /* Copy any shared structure that should not be shared.  */
+
+  unshare_all_rtl (insns);
+
+  /* Instantiate all virtual registers.  */
+
+  instantiate_virtual_regs (current_function_decl, get_insns ());
+
+  /* We are no longer anticipating cse in this function, at least.  */
+
+  cse_not_expected = 1;
+
+  /* Now we choose between stupid (pcc-like) register allocation
+     (if we got the -noreg switch and not -opt)
+     and smart register allocation.  */
+
+  if (optimize > 0)                    /* Stupid allocation probably won't work */
+    obey_regdecls = 0;         /* if optimizations being done.  */
+
+  regclass_init ();
+
+  regclass (insns, max_reg_num ());
+  if (obey_regdecls)
+    {
+      stupid_life_analysis (insns, max_reg_num (), NULL);
+      failure = reload (insns, 0, NULL);
+    }
+  else
+    {
+      /* Do control and data flow analysis,
+        and write some of the results to dump file.  */
+
+      flow_analysis (insns, max_reg_num (), NULL);
+      local_alloc ();
+      failure = global_alloc (NULL);
+    }
+
+  reload_completed = 1;
+
+#ifdef LEAF_REGISTERS
+  leaf_function = 0;
+  if (optimize > 0 && only_leaf_regs_used () && leaf_function_p ())
+    leaf_function = 1;
+#endif
+
+  /* If a machine dependent reorganization is needed, call it.  */
+#ifdef MACHINE_DEPENDENT_REORG
+   MACHINE_DEPENDENT_REORG (insns);
+#endif
+
+  /* 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:
+
+  reload_completed = 0;
+
+  /* Cancel the effect of rtl_in_current_obstack.  */
+
+  resume_temporary_allocation ();
+
+  decl_printable_name = save_decl_printable_name;
+  current_function_decl = 0;
+}
index 70026d3..9730a62 100644 (file)
@@ -40,10 +40,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
   */
 
 %{
-#if defined(GATHER_STATISTICS) || defined(SPEW_DEBUG)
-#undef YYDEBUG
+/* Cause the `yydebug' variable to be defined.  */
 #define YYDEBUG 1
-#endif
 
 #include "config.h"
 
@@ -74,8 +72,6 @@ void yyerror ();
 /* Like YYERROR but do call yyerror.  */
 #define YYERROR1 { yyerror ("syntax error"); YYERROR; }
 
-static void position_after_white_space ();
-
 /* Contains the statement keyword (if/while/do) to include in an
    error message if the user supplies an empty conditional expression.  */
 static char *cond_stmt_keyword;
@@ -338,6 +334,8 @@ asm_keyword:
 lang_extdef:
          { if (pending_lang_change) do_pending_lang_change(); }
          extdef
+         { if (! global_bindings_p () && ! pseudo_global_level_p())
+             pop_everything (); }
        ;
 
 extdef:
@@ -1226,9 +1224,11 @@ unary_expr:
                  $$ = build_new ($2, typename, NULL_TREE, $$ != NULL_TREE);
                }
        | .scope new '(' type_id ')'
-               { $$ = build_new ($2, $4, NULL_TREE, $$ != NULL_TREE); }
+               { $$ = build_new ($2, groktypename ($4), NULL_TREE,
+                                 $$ != NULL_TREE); }
        | .scope new '(' nonnull_exprlist ')' '(' type_id ')'
-               { $$ = build_new ($4, $7, NULL_TREE, $$ != NULL_TREE); }
+               { $$ = build_new ($4, groktypename ($7), NULL_TREE,
+                                 $$ != NULL_TREE); }
        /* Unswallow a ':' which is probably meant for ?: expression.  */
        | .scope new TYPENAME_COLON
                { yyungetc (':', 1); $$ = build_new ($2, $3, NULL_TREE, $$ != NULL_TREE); }
@@ -1347,8 +1347,8 @@ expr_no_commas:
                { $$ = build_modify_expr ($$, NOP_EXPR, $3); }
        | expr_no_commas ASSIGN expr_no_commas
                { register tree rval;
-                 if (rval = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL, $$, $3,
-                                            make_node ($2)))
+                 if ((rval = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL, $$, $3,
+                                            make_node ($2))))
                    $$ = rval;
                  else
                    $$ = build_modify_expr ($$, $2, $3); }
@@ -1473,8 +1473,7 @@ primary:
                    $$ = require_complete_type ($$);
                 }
        | primary '[' expr ']'
-               { do_array:
-                   $$ = grok_array_decl ($$, $3); }
+               { $$ = grok_array_decl ($$, $3); }
        | object identifier_or_opname  %prec UNARY
                { $$ = build_component_ref ($$, $2, NULL_TREE, 1); }
        | object id_scope identifier_or_opname %prec UNARY
@@ -1570,10 +1569,6 @@ primary:
        | TYPEID '(' type_id ')'
                { tree type = groktypename ($3);
                  $$ = get_typeid (type); }
-       | SCOPE typespec '(' nonnull_exprlist ')'
-               { $$ = build_functional_cast ($2, $4); }
-       | SCOPE typespec LEFT_RIGHT
-               { $$ = build_functional_cast ($2, NULL_TREE); }
        | SCOPE IDENTIFIER
                {
                do_scoped_id:
@@ -1617,7 +1612,6 @@ primary:
                {
                  if (TREE_CODE ($2) == IDENTIFIER_NODE)
                    goto do_scoped_id;
-               do_scoped_operator:
                  $$ = $2;
                }
        | id_scope identifier_or_opname  %prec HYPERUNARY
@@ -2040,6 +2034,13 @@ initdcl0:
                { current_declspecs = $<ttype>0;
                  if (TREE_CODE (current_declspecs) != TREE_LIST)
                    current_declspecs = get_decl_list (current_declspecs);
+                 if (have_extern_spec && !used_extern_spec)
+                   {
+                     current_declspecs = decl_tree_cons
+                       (NULL_TREE, get_identifier ("extern"), 
+                        current_declspecs);
+                     used_extern_spec = 1;
+                   }
                  $<itype>5 = suspend_momentary ();
                  $<ttype>$ = start_decl ($<ttype>1, current_declspecs, 1, $2);
                  cplus_decl_attributes ($<ttype>$, $4); }
@@ -2052,6 +2053,13 @@ initdcl0:
                  current_declspecs = $<ttype>0;
                  if (TREE_CODE (current_declspecs) != TREE_LIST)
                    current_declspecs = get_decl_list (current_declspecs);
+                 if (have_extern_spec && !used_extern_spec)
+                   {
+                     current_declspecs = decl_tree_cons
+                       (NULL_TREE, get_identifier ("extern"), 
+                        current_declspecs);
+                     used_extern_spec = 1;
+                   }
                  $$ = suspend_momentary ();
                  d = start_decl ($<ttype>1, current_declspecs, 0, $2);
                  cplus_decl_attributes (d, $4);
index 90fe017..e9810e1 100644 (file)
@@ -87,7 +87,6 @@ process_template_parm (list, next)
   if (!is_type)
     {
       tree tinfo = 0;
-      int  idx = 0;
       parm = TREE_PURPOSE (parm);
       my_friendly_assert (TREE_CODE (parm) == TREE_LIST, 260);
       parm = TREE_VALUE (parm);
@@ -281,19 +280,7 @@ end_template_decl (d1, d2, is_class, defn)
     {
       poplevel (0, 0, 0);
       poplevel (0, 0, 0);
-      if (TREE_TYPE (decl))
-       {
-         /* Function template */
-         tree t = IDENTIFIER_GLOBAL_VALUE (DECL_NAME (decl));
-         if (t && is_overloaded_fn (t))
-           for (t = get_first_fn (t); t; t = DECL_CHAIN (t))
-             if (TREE_CODE (t) == TEMPLATE_DECL
-                 && duplicate_decls (decl, t))
-               decl = t;
-         push_overloaded_decl (decl, 0);
-       }
-      else
-       pushdecl (decl);
+      pushdecl (decl);
     }
  lose:
 #if 0 /* It happens sometimes, with syntactic or semantic errors.
@@ -470,7 +457,6 @@ mangle_class_name_for_template (name, parms, arglist)
   static struct obstack scratch_obstack;
   static char *scratch_firstobj;
   int i, nparms;
-  char ibuf[100];
 
   if (!scratch_firstobj)
     {
@@ -492,8 +478,6 @@ mangle_class_name_for_template (name, parms, arglist)
 #define advance
 #define cat(s) obstack_grow (&scratch_obstack, (s), strlen (s))
 #endif
-#define icat(n)        sprintf(ibuf,"%d",(n)); cat(ibuf)
-#define xcat(n)        sprintf(ibuf,"%ux",n); cat(ibuf)
 
   cat (name);
   ccat ('<');
@@ -540,7 +524,9 @@ mangle_class_name_for_template (name, parms, arglist)
   ccat ('\0');
   return (char *) obstack_base (&scratch_obstack);
 
+#if 0
  too_long:
+#endif
   fatal ("out of (preallocated) string space creating template instantiation name");
   /* NOTREACHED */
   return NULL;
@@ -619,7 +605,11 @@ push_template_decls (parmlist, arglist, class_level)
 
   /* Don't want to push values into global context.  */
   if (!class_level)
-    pushlevel (0);
+    {
+      pushlevel (1);
+      declare_pseudo_global_level ();
+    }
+
   nparms = TREE_VEC_LENGTH (parmlist);
 
   for (i = 0; i < nparms; i++)
@@ -669,8 +659,6 @@ push_template_decls (parmlist, arglist, class_level)
            pushdecl (decl);
        }
     }
-  if (!class_level)
-    set_current_level_tags_transparency (1);
 }
 
 void
@@ -1235,7 +1223,7 @@ tsubst (t, args, nargs, in_decl)
                  {
                    my_friendly_assert (TREE_CODE (method) == FUNCTION_DECL,
                                        282);
-                   if (TREE_TYPE (method) != type)
+                   if (! comptypes (type, TREE_TYPE (method), 1))
                      {
                        tree mtype = TREE_TYPE (method);
                        tree t1, t2;
@@ -1348,7 +1336,6 @@ tsubst (t, args, nargs, in_decl)
                    {
                      got_it = 1;
                      r = val;
-                     break;
                    }
                }
 
@@ -2186,7 +2173,7 @@ do_pending_expansions ()
       tree t = i->fndecl;
 
       int decision = 0;
-#define DECIDE(N) if(1){decision=(N); goto decided;}else
+#define DECIDE(N) do {decision=(N); goto decided;} while(0)
 
       my_friendly_assert (TREE_CODE (t) == FUNCTION_DECL
                          || TREE_CODE (t) == VAR_DECL, 294);
index 048e0a4..984ee43 100644 (file)
@@ -377,6 +377,7 @@ pop_memoized_context (use_old)
     type_stack = (struct type_level *)type_stack->base.prev;
 }
 \f
+#if 0                          /* unused */
 /* This is the newer recursive depth first search routine. */
 /* Return non-zero if PARENT is directly derived from TYPE.  By directly
    we mean it's only one step up the inheritance lattice.  We check this
@@ -402,6 +403,7 @@ immediately_derived (parent, type)
     }
   return 0;
 }
+#endif
 
 /* Check whether the type given in BINFO is derived from PARENT.  If
    it isn't, return 0.  If it is, but the derivation is MI-ambiguous
@@ -459,7 +461,7 @@ get_binfo (parent, binfo, protect)
 }
 
 /* This is the newer depth first get_base_distance routine.  */
-static
+static int
 get_base_distance_recursive (binfo, depth, is_private, basetype_path, rval,
                             rval_private_ptr, new_binfo_ptr, parent, path_ptr,
                             protect, via_virtual_ptr, via_virtual)
@@ -583,10 +585,7 @@ get_base_distance (parent, binfo, protect, path_ptr)
      int protect;
      tree *path_ptr;
 {
-  int head, tail;
-  int is_private = 0;
   int rval;
-  int depth = 0;
   int rval_private = 0;
   tree type;
   tree new_binfo = NULL_TREE;
@@ -1966,54 +1965,31 @@ get_first_matching_virtual (binfo, fndecl, dtorp)
     }
 }
 
-/* Return the list of virtual functions which are abstract in type TYPE.
-   This information is cached, and so must be built on a
-   non-temporary obstack.  */
-tree
-get_abstract_virtuals (type)
-     tree type;
+/* Return the list of virtual functions which are abstract in type TYPE
+   that come from non virtual base classes.  See init_vtbl_ptrs for
+   the style of search we do.  */
+static tree
+get_abstract_virtuals_1 (binfo, do_self, abstract_virtuals)
+     tree binfo, abstract_virtuals;
+     int do_self;
 {
-  /* For each layer of base class (i.e., the first base class, and each
-     virtual base class from that one), modify the virtual function table
-     of the derived class to contain the new virtual function.
-     A class has as many vfields as it has virtual base classes (total).  */
-  tree vfields, vbases, base, tmp;
-  tree vfield = CLASSTYPE_VFIELD (type);
-  tree fcontext = vfield ? DECL_FCONTEXT (vfield) : NULL_TREE;
-  tree abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (type);
+  tree binfos = BINFO_BASETYPES (binfo);
+  int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
 
-  for (vfields = CLASSTYPE_VFIELDS (type); vfields; vfields = TREE_CHAIN (vfields))
+  for (i = 0; i < n_baselinks; i++)
     {
-      int normal;
-
-      /* This code is most likely wrong, and probably only works for single
-        inheritance or by accident. */
-
-      /* Find the right base class for this derived class, call it BASE.  */
-      base = VF_BASETYPE_VALUE (vfields);
-      if (base == type)
-       continue;
-
-      /* We call this case NORMAL iff this virtual function table
-        pointer field has its storage reserved in this class.
-        This is normally the case without virtual baseclasses
-        or off-center multiple baseclasses.  */
-      normal = (base == fcontext
-               && (VF_BINFO_VALUE (vfields) == NULL_TREE
-                   || ! TREE_VIA_VIRTUAL (VF_BINFO_VALUE (vfields))));
-
-      if (normal)
-       tmp = TREE_CHAIN (TYPE_BINFO_VIRTUALS (type));
-      else
-       {
-         /* n.b.: VF_BASETYPE_VALUE (vfields) is the first basetype
-            that provides the virtual function table, whereas
-            VF_DERIVED_VALUE (vfields) is an immediate base type of TYPE
-            that dominates VF_BASETYPE_VALUE (vfields).  The list of
-            vfields we want lies between these two values.  */
-         tree binfo = get_binfo (VF_NORMAL_VALUE (vfields), type, 0);
-         tmp = TREE_CHAIN (BINFO_VIRTUALS (binfo));
-       }
+      tree base_binfo = TREE_VEC_ELT (binfos, i);
+      int is_not_base_vtable =
+       i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
+      if (! TREE_VIA_VIRTUAL (base_binfo))
+       abstract_virtuals
+         = get_abstract_virtuals_1 (base_binfo, is_not_base_vtable,
+                                    abstract_virtuals);
+    }
+  /* Should we use something besides CLASSTYPE_VFIELDS? */
+  if (do_self && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
+    {
+      tree tmp = TREE_CHAIN (BINFO_VIRTUALS (binfo));
 
       /* Get around dossier entry if there is one.  */
       if (flag_dossier)
@@ -2028,6 +2004,23 @@ get_abstract_virtuals (type)
          tmp = TREE_CHAIN (tmp);
        }
     }
+  return abstract_virtuals;
+}
+
+/* Return the list of virtual functions which are abstract in type TYPE.
+   This information is cached, and so must be built on a
+   non-temporary obstack.  */
+tree
+get_abstract_virtuals (type)
+     tree type;
+{
+  tree vbases, tmp;
+  tree abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (type);
+
+  /* First get all from non-virtual bases. */
+  abstract_virtuals
+    = get_abstract_virtuals_1 (TYPE_BINFO (type), 1, abstract_virtuals);
+                                              
   for (vbases = CLASSTYPE_VBASECLASSES (type); vbases; vbases = TREE_CHAIN (vbases))
     {
       if (! BINFO_VIRTUALS (vbases))
@@ -2414,8 +2407,7 @@ dfs_init_vbase_pointers (binfo)
 {
   tree type = BINFO_TYPE (binfo);
   tree fields = TYPE_FIELDS (type);
-  tree path, this_vbase_ptr;
-  int distance;
+  tree this_vbase_ptr;
 
   CLEAR_BINFO_VTABLE_PATH_MARKED (binfo);
 
@@ -2500,9 +2492,9 @@ init_vbase_pointers (type, decl_ptr)
    offsets are valid to store vtables.  When zero, we must store new
    vtables through virtual baseclass pointers.  */
 
-tree
-build_vbase_vtables_init (main_binfo, binfo, true_exp, decl_ptr,
-                         use_computed_offsets)
+void
+expand_vbase_vtables_init (main_binfo, binfo, true_exp, decl_ptr,
+                          use_computed_offsets)
      tree main_binfo, binfo;
      tree true_exp, decl_ptr;
      int use_computed_offsets;
@@ -2512,7 +2504,6 @@ build_vbase_vtables_init (main_binfo, binfo, true_exp, decl_ptr,
   if (TYPE_USES_VIRTUAL_BASECLASSES (type))
     {
       int old_flag = flag_this_is_variable;
-      tree vtable_init_result = NULL_TREE;
       tree vbases = CLASSTYPE_VBASECLASSES (type);
 
       vbase_types = CLASSTYPE_VBASECLASSES (for_type);
@@ -2538,7 +2529,7 @@ build_vbase_vtables_init (main_binfo, binfo, true_exp, decl_ptr,
              tree addr;
              tree vtbl = BINFO_VTABLE (vbases);
              tree init = build_unary_op (ADDR_EXPR, vtbl, 0);
-             if (!flag_vtable_hack)
+             if (!flag_vtable_thunks)
                assemble_external (vtbl);
              TREE_USED (vtbl) = 1;
 
@@ -2552,8 +2543,7 @@ build_vbase_vtables_init (main_binfo, binfo, true_exp, decl_ptr,
                  tree ref = build_vfield_ref (build_indirect_ref (addr, NULL_PTR),
                                               BINFO_TYPE (vbases));
                  init = convert_force (TREE_TYPE (ref), init);
-                 vtable_init_result = tree_cons (NULL_TREE, build_modify_expr (ref, NOP_EXPR, init),
-                                                 vtable_init_result);
+                 expand_expr_stmt (build_modify_expr (ref, NOP_EXPR, init));
                }
            }
          vbases = TREE_CHAIN (vbases);
@@ -2562,10 +2552,7 @@ build_vbase_vtables_init (main_binfo, binfo, true_exp, decl_ptr,
       dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep);
 
       flag_this_is_variable = old_flag;
-      if (vtable_init_result)
-       return build_compound_expr (vtable_init_result);
     }
-  return error_mark_node;
 }
 
 void
@@ -2586,7 +2573,7 @@ dfs_get_vbase_types (binfo)
 {
   if (TREE_VIA_VIRTUAL (binfo) && ! BINFO_VBASE_MARKED (binfo))
     {
-      vbase_types = make_binfo (integer_zero_node, BINFO_TYPE (binfo),
+      vbase_types = make_binfo (integer_zero_node, binfo,
                                BINFO_VTABLE (binfo),
                                BINFO_VIRTUALS (binfo), vbase_types);
       TREE_VIA_VIRTUAL (vbase_types) = 1;
index fd0cafa..da707eb 100644 (file)
@@ -46,9 +46,11 @@ struct token  {
 
 static int do_aggr ();
 static struct token frob_identifier ();
+static tree hack_more_ids ();
+#if 0
 static struct token hack_scope ();
 static tree hack_ptype ();
-static tree hack_more_ids ();
+#endif
 
 /* From lex.c: */
 /* the declaration found for the last IDENTIFIER token read in.
@@ -70,8 +72,10 @@ static unsigned int yylex_ctr = 0;
 static int debug_yychar ();
 #endif
 
+#if 0                          /* Used by arbitrate_lookup */
 static char follows_typename[END_OF_SAVED_INPUT+1];
 static char follows_identifier[END_OF_SAVED_INPUT+1];
+#endif
 
 /* This is a hack!!! TEMPLATE_TYPE_SEEN_BEFORE_SCOPE consists of the name
  * of the last template_type parsed in parse.y if it is followed by a
@@ -84,6 +88,7 @@ tree template_type_seen_before_scope;
 void
 init_spew ()
 {
+#if 0                          /* Used by arbitrate_lookup */
   static char *chars_following_identifier = ".+-|/%^!?:";
   short *ps;
   static short toks_follow_ids[] =
@@ -102,8 +107,6 @@ init_spew ()
       TYPENAME_COLON, PAREN_STAR_PAREN, TYPENAME_ELLIPSIS, PTYPENAME,
       PRE_PARSED_FUNCTION_DECL, PRE_PARSED_CLASS_DECL, -1 };
 
-  gcc_obstack_init(&token_obstack);
-
   /* Initialize the arrays saying what tokens are definitely
      (or possibly) valid following typenames and identifiers.  */
   while (*chars_following_identifier)
@@ -112,6 +115,9 @@ init_spew ()
     follows_identifier[*ps] = 1;
   for (ps = toks_follow_types; *ps != -1; ps++)
     follows_typename[*ps] = 1;
+#endif
+
+  gcc_obstack_init(&token_obstack);
 }
 
 #ifdef SPEW_DEBUG
index 785033c..a63ccac 100644 (file)
@@ -448,7 +448,7 @@ propagate_binfo_offsets (binfo, offset)
                  if (! TREE_VIA_VIRTUAL (base_base_binfo))
                    TREE_VEC_ELT (base_binfos, k)
                      = make_binfo (BINFO_OFFSET (base_base_binfo),
-                                   BINFO_TYPE (base_base_binfo),
+                                   base_base_binfo,
                                    BINFO_VTABLE (base_base_binfo),
                                    BINFO_VIRTUALS (base_base_binfo),
                                    chain);
@@ -563,7 +563,7 @@ layout_vbasetypes (rec, max)
              if (! TREE_VIA_VIRTUAL (base_base_binfo))
                TREE_VEC_ELT (base_binfos, j)
                  = make_binfo (BINFO_OFFSET (base_base_binfo),
-                               BINFO_TYPE (base_base_binfo),
+                               base_base_binfo,
                                BINFO_VTABLE (base_base_binfo),
                                BINFO_VIRTUALS (base_base_binfo),
                                chain);
@@ -600,13 +600,15 @@ layout_basetypes (rec, binfos)
   unsigned record_align = MAX (BITS_PER_UNIT, TYPE_ALIGN (rec));
 #endif
 
-  /* Record size so far is CONST_SIZE + VAR_SIZE bits,
-     where CONST_SIZE is an integer
-     and VAR_SIZE is a tree expression.
-     If VAR_SIZE is null, the size is just CONST_SIZE.
-     Naturally we try to avoid using VAR_SIZE.  */
-  register unsigned const_size = 0;
+  /* Record size so far is CONST_SIZE + VAR_SIZE bits, where CONST_SIZE is
+     an integer and VAR_SIZE is a tree expression.  If VAR_SIZE is null,
+     the size is just CONST_SIZE.  Naturally we try to avoid using
+     VAR_SIZE.  And so far, we've been sucessful. */
+#if 0
   register tree var_size = 0;
+#endif
+
+  register unsigned const_size = 0;
   int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
 
   /* Handle basetypes almost like fields, but record their
@@ -945,7 +947,9 @@ get_identifier_list (value)
          || TREE_VALUE (list) != value))
     list = NULL_TREE;
   else if (IDENTIFIER_HAS_TYPE_VALUE (value)
-          && TREE_CODE (IDENTIFIER_TYPE_VALUE (value)) == RECORD_TYPE)
+          && TREE_CODE (IDENTIFIER_TYPE_VALUE (value)) == RECORD_TYPE
+          && IDENTIFIER_TYPE_VALUE (value)
+             == TYPE_MAIN_VARIANT (IDENTIFIER_TYPE_VALUE (value)))
     {
       tree type = IDENTIFIER_TYPE_VALUE (value);
 
@@ -1052,6 +1056,11 @@ list_hash_lookup_or_cons (value)
    OFFSET is the offset added to `this' to convert it to a pointer
    of type `TYPE *'
 
+   BINFO is the base binfo to use, if we are deriving from one.  This
+   is necessary, as we want specialized parent binfos from base
+   classes, so that the VTABLE_NAMEs of bases are for the most derived
+   type, instead of of the simple type.
+
    VTABLE is the virtual function table with which to initialize
    sub-objects of type TYPE.
 
@@ -1060,47 +1069,35 @@ list_hash_lookup_or_cons (value)
    CHAIN are more associations we must retain.  */
 
 tree
-make_binfo (offset, type, vtable, virtuals, chain)
-     tree offset, type;
+make_binfo (offset, binfo, vtable, virtuals, chain)
+     tree offset, binfo;
      tree vtable, virtuals;
      tree chain;
 {
-  tree binfo = make_tree_vec (6);
-  tree old_binfo = TYPE_BINFO (type);
-  tree last;
+  tree new_binfo = make_tree_vec (6);
+  tree type;
 
-  TREE_CHAIN (binfo) = chain;
-  if (chain)
-    TREE_USED (binfo) = TREE_USED (chain);
+  if (TREE_CODE (binfo) == TREE_VEC)
+    type = BINFO_TYPE (binfo);
+  else
+    {
+      type = binfo;
+      binfo = TYPE_BINFO (binfo);
+    }
 
-  TREE_TYPE (binfo) = TYPE_MAIN_VARIANT (type);
-  BINFO_OFFSET (binfo) = offset;
-  BINFO_VTABLE (binfo) = vtable;
-  BINFO_VIRTUALS (binfo) = virtuals;
-  BINFO_VPTR_FIELD (binfo) = NULL_TREE;
+  TREE_CHAIN (new_binfo) = chain;
+  if (chain)
+    TREE_USED (new_binfo) = TREE_USED (chain);
 
-  last = binfo;
-  if (old_binfo != NULL_TREE
-      && BINFO_BASETYPES (old_binfo) != NULL_TREE)
-    {
-      int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (type);
-      tree binfos = TYPE_BINFO_BASETYPES (type);
+  TREE_TYPE (new_binfo) = TYPE_MAIN_VARIANT (type);
+  BINFO_OFFSET (new_binfo) = offset;
+  BINFO_VTABLE (new_binfo) = vtable;
+  BINFO_VIRTUALS (new_binfo) = virtuals;
+  BINFO_VPTR_FIELD (new_binfo) = NULL_TREE;
 
-      BINFO_BASETYPES (binfo) = make_tree_vec (n_baseclasses);
-      for (i = 0; i < n_baseclasses; i++)
-       {
-         tree base_binfo = TREE_VEC_ELT (binfos, i);
-         tree old_base_binfo = old_binfo ? BINFO_BASETYPE (old_binfo, i) : 0;
-         BINFO_BASETYPE (binfo, i) = base_binfo;
-         if (old_binfo)
-           {
-             TREE_VIA_PUBLIC (base_binfo) = TREE_VIA_PUBLIC (old_base_binfo);
-             TREE_VIA_PROTECTED (base_binfo) = TREE_VIA_PROTECTED (old_base_binfo);
-             TREE_VIA_VIRTUAL (base_binfo) = TREE_VIA_VIRTUAL (old_base_binfo);
-           }
-       }
-    }
-  return binfo;
+  if (binfo && BINFO_BASETYPES (binfo) != NULL_TREE)
+    BINFO_BASETYPES (new_binfo) = copy_node (BINFO_BASETYPES (binfo));      
+  return new_binfo;
 }
 
 tree
@@ -1320,6 +1317,18 @@ is_overloaded_fn (x)
   return 0;
 }
 
+int
+really_overloaded_fn (x)
+     tree x;
+{     
+  if (TREE_CODE (x) == TREE_LIST
+      && (TREE_CODE (TREE_VALUE (x)) == FUNCTION_DECL
+         || TREE_CODE (TREE_VALUE (x)) == TEMPLATE_DECL))
+    return 1;
+
+  return 0;
+}
+
 tree
 get_first_fn (from)
      tree from;
@@ -1336,13 +1345,27 @@ tree
 fnaddr_from_vtable_entry (entry)
      tree entry;
 {
-  return TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (entry))));
+  if (flag_vtable_thunks)
+    {
+      tree func = entry;
+      if (TREE_CODE (func) == ADDR_EXPR)
+       func = TREE_OPERAND (func, 0);
+      if (TREE_CODE (func) == THUNK_DECL)
+       return DECL_INITIAL (func);
+      else
+       return entry;
+    }
+  else
+    return TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (entry))));
 }
 
 void
 set_fnaddr_from_vtable_entry (entry, value)
      tree entry, value;
 {
+  if (flag_vtable_thunks)
+    abort ();
+  else
   TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (entry)))) = value;
 }
 
index f7f1505..1271272 100644 (file)
@@ -41,9 +41,6 @@ extern void warning ();
 int mark_addressable ();
 static tree convert_for_assignment ();
 /* static */ tree convert_for_initialization ();
-int compparms ();
-static int self_promoting_args_p ();
-int comp_target_types ();
 extern tree shorten_compare ();
 extern void binary_op_error ();
 static tree pointer_int_sum ();
@@ -386,7 +383,7 @@ common_type (t1, t2)
        if (p1 == NULL_TREE || TREE_VALUE (p1) == void_type_node)
          {
            rval = build_function_type (valtype, p2);
-           if (raises = TYPE_RAISES_EXCEPTIONS (t2))
+           if ((raises = TYPE_RAISES_EXCEPTIONS (t2)))
              rval = build_exception_variant (NULL_TREE, rval, raises);
            return rval;
          }
@@ -606,7 +603,7 @@ comptypes (type1, type2, strict)
                         TYPE_POINTER_TO (TYPE_METHOD_BASETYPE (t1)), strict)
              && comptypes (TREE_TYPE (t1), TREE_TYPE (t2), strict)
              && compparms (TREE_CHAIN (TYPE_ARG_TYPES (t1)),
-                           TREE_CHAIN (TYPE_ARG_TYPES(t2)), strict));
+                           TREE_CHAIN (TYPE_ARG_TYPES (t2)), strict));
     case POINTER_TYPE:
     case REFERENCE_TYPE:
       t1 = TREE_TYPE (t1);
@@ -678,7 +675,7 @@ comp_target_types (ttl, ttr, nptrs)
     return comp_array_types (comp_target_types, ttl, ttr, 0);
   else if (TREE_CODE (ttr) == FUNCTION_TYPE || TREE_CODE (ttr) == METHOD_TYPE)
     if (comp_target_types (TREE_TYPE (ttl), TREE_TYPE (ttr), nptrs))
-      switch (comp_target_parms (TYPE_ARG_TYPES (ttl), TYPE_ARG_TYPES (ttr), 0))
+      switch (comp_target_parms (TYPE_ARG_TYPES (ttl), TYPE_ARG_TYPES (ttr), 1))
        {
        case 0:
          return 0;
@@ -797,10 +794,10 @@ compparms (parms1, parms2, strict)
   /* An unspecified parmlist matches any specified parmlist
      whose argument types don't need default promotions.  */
 
-  if (t1 == 0)
-    return self_promoting_args_p (t2);
-  if (t2 == 0)
-    return self_promoting_args_p (t1);
+  if (strict <= 0 && t1 == 0)
+       return self_promoting_args_p (t2);
+  if (strict < 0 && t2 == 0)
+       return self_promoting_args_p (t1);
 
   while (1)
     {
@@ -956,7 +953,7 @@ comp_target_parms (parms1, parms2, strict)
 /* Return 1 if PARMS specifies a fixed number of parameters
    and none of their types is affected by default promotions.  */
 
-static int
+int
 self_promoting_args_p (parms)
      tree parms;
 {
@@ -2111,7 +2108,6 @@ get_member_function_from_ptrfunc (instance_ptrptr, instance, function)
       tree e2;
       tree e3;
       tree aref, vtbl;
-      tree aux_delta;
 
       /* convert down to the right base, before using the instance. */
       instance = convert_pointer_to_real (TYPE_METHOD_BASETYPE (TREE_TYPE (fntype)),
@@ -2121,7 +2117,7 @@ get_member_function_from_ptrfunc (instance_ptrptr, instance, function)
 
       vtbl = convert_pointer_to (ptr_type_node, instance);
       vtbl = build (PLUS_EXPR,
-                   build_pointer_type (build_pointer_type (vtable_entry_type)),
+                   build_pointer_type (build_pointer_type (memptr_type)),
                    vtbl, convert (sizetype, delta2));
       vtbl = build_indirect_ref (vtbl, NULL_PTR);
       aref = build_array_ref (vtbl, size_binop (MINUS_EXPR,
@@ -3602,7 +3598,7 @@ build_component_addr (arg, argtype, msg)
         baseclasses.  */
       rval = build1 (NOP_EXPR, argtype,
                     convert_pointer_to (basetype, rval));
-      TREE_CONSTANT (rval) == TREE_CONSTANT (TREE_OPERAND (rval, 0));
+      TREE_CONSTANT (rval) = TREE_CONSTANT (TREE_OPERAND (rval, 0));
     }
   else
     /* This conversion is harmless.  */
@@ -4935,6 +4931,7 @@ build_c_cast (type, expr)
   return value;
 }
 \f
+#if 0
 /* Build an assignment expression of lvalue LHS from value RHS.
 
    In C++, if the left hand side of the assignment is a REFERENCE_TYPE,
@@ -4969,7 +4966,6 @@ get_base_ref (type, base_index, expr)
   return ref;
 }
 
-#if 0
 /* Build an assignment expression of lvalue LHS from value RHS.
    MODIFYCODE is the code for a binary operator that we use
    to combine the old value of LHS with RHS to get the new value.
@@ -5833,6 +5829,7 @@ language_lvalue_valid (exp)
 static tree
 get_delta_difference (from, to, force)
      tree from, to;
+     int force;
 {
   tree delta = integer_zero_node;
   tree binfo;
@@ -5840,6 +5837,11 @@ get_delta_difference (from, to, force)
   if (to == from)
     return delta;
 
+  /* Should get_base_distance here, so we can check if any thing along the
+     path is virtual, and we need to make sure we stay
+     inside the real binfos when going through virtual bases.
+     Maybe we should replace virtual bases with
+     binfo_member (...CLASSTYPE_VBASECLASSES...)...  (mrs) */
   binfo = get_binfo (from, to, 1);
   if (binfo == error_mark_node)
     {
@@ -5867,7 +5869,7 @@ get_delta_difference (from, to, force)
        }
       if (TREE_VIA_VIRTUAL (binfo))
        {
-         warning ("pointer to member conversion from virtual base class will only work if your very careful");
+         warning ("pointer to member conversion to virtual base class will only work if your very careful");
        }
       return fold (size_binop (MINUS_EXPR,
                               integer_zero_node,
@@ -6815,10 +6817,8 @@ c_expand_return (retval)
     {
       tree whats_returned = TREE_OPERAND (retval, 0);
 
-      if (TREE_CODE (whats_returned) == TREE_LIST)
-       whats_returned = TREE_VALUE (whats_returned);
-
-      if (DECL_NAME (whats_returned)
+      if (TREE_CODE (whats_returned) == VAR_DECL
+         && DECL_NAME (whats_returned)
          && IDENTIFIER_LOCAL_VALUE (DECL_NAME (whats_returned))
          && !TREE_STATIC (whats_returned))
        cp_warning_at ("address of local variable `%D' returned", whats_returned);
index f9f9be7..19c8b73 100644 (file)
@@ -60,7 +60,7 @@ binfo_or_else (parent_or_type, type)
   tree binfo;
   if (TYPE_MAIN_VARIANT (parent_or_type) == TYPE_MAIN_VARIANT (type))
     return parent_or_type;
-  if (binfo = get_binfo (parent_or_type, TYPE_MAIN_VARIANT (type), 0))
+  if ((binfo = get_binfo (parent_or_type, TYPE_MAIN_VARIANT (type), 0)))
     {
       if (binfo == error_mark_node)
        return NULL_TREE;
@@ -329,7 +329,7 @@ ack (s, v, v2)
    silly.  So instead, we just do the equivalent of a call to fatal in the
    same situation (call exit).  */
 
-/* First used: 0 (reserved), Last used: 355.  */
+/* First used: 0 (reserved), Last used: 355.  Free: 180.  */
 
 static int abortcount = 0;
 
@@ -434,9 +434,10 @@ initializer_constant_valid_p (value)
          return 2;
        return 0;
       }
-    }
 
-  return 0;
+    default:
+      return 0;
+    }
 }
 \f
 /* Perform appropriate conversions on the initial value of a variable,
@@ -583,6 +584,9 @@ store_init_value (decl, init)
   else if (TREE_STATIC (decl)
           && (! TREE_CONSTANT (value)
               || ! initializer_constant_valid_p (value)
+#if 0
+              /* A STATIC PUBLIC int variable doesn't have to be
+                 run time inited when doing pic.  (mrs) */
               /* Since ctors and dtors are the only things that can
                  reference vtables, and they are always written down
                  the the vtable definition, we can leave the
@@ -590,7 +594,10 @@ store_init_value (decl, init)
                  However, other initialized data cannot be initialized
                  this way.  Instead a global file-level initializer
                  must do the job.  */
-              || (flag_pic && !DECL_VIRTUAL_P (decl) && TREE_PUBLIC (decl))))
+              || (flag_pic && !DECL_VIRTUAL_P (decl) && TREE_PUBLIC (decl))
+#endif
+              ))
+
     return value;
   else
     {
@@ -1283,7 +1290,7 @@ build_x_arrow (datum)
 
   if (IS_AGGR_TYPE (type) && TYPE_OVERLOADS_ARROW (type))
     {
-      while (rval = build_opfncall (COMPONENT_REF, LOOKUP_NORMAL, rval, NULL_TREE, NULL_TREE))
+      while ((rval = build_opfncall (COMPONENT_REF, LOOKUP_NORMAL, rval, NULL_TREE, NULL_TREE)))
        {
          if (rval == error_mark_node)
            return error_mark_node;