86th Cygnus<->FSF quick merge
authorMike Stump <mrs@gcc.gnu.org>
Thu, 30 May 1996 19:11:58 +0000 (19:11 +0000)
committerMike Stump <mrs@gcc.gnu.org>
Thu, 30 May 1996 19:11:58 +0000 (19:11 +0000)
From-SVN: r12126

16 files changed:
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/cvt.c
gcc/cp/decl.c
gcc/cp/error.c
gcc/cp/except.c
gcc/cp/gxxint.texi
gcc/cp/init.c
gcc/cp/lex.c
gcc/cp/method.c
gcc/cp/pt.c
gcc/cp/search.c
gcc/cp/tree.c
gcc/cp/typeck.c

index f0dd601c72a8bce96639c2d528f0d3522475c64e..1f6eeb971e21b6a6db490a46f52baf86cc5b6ce0 100644 (file)
@@ -3,6 +3,131 @@ Sat May 11 04:33:50 1996  Doug Evans  <dje@canuck.cygnus.com>
        * decl2.c (finish_vtable_vardecl): Surround DECL_ONE_ONLY with ifdef.
        (finish_file): Likewise.
 
+Wed May 29 17:04:33 1996  Mike Stump  <mrs@cygnus.com>
+
+       * cvt.c (build_up_reference): Redo how and when temporaries are
+       created.
+       * decl.c (grok_reference_init): Don't try and be smart about
+       running cleanups.
+
+Wed May 29 16:02:08 1996  Mike Stump  <mrs@cygnus.com>
+
+       * cvt.c (build_up_reference): Add NULL_TREE to all calls to build
+       (TARGET_EXPR...), now that it has 4 arguments.
+       * tree.c (build_cplus_new): Ditto.
+
+Thu May 23 16:40:30 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * error.c (dump_expr, case CAST_EXPR): Handle T() properly.
+
+       * pt.c (instantiate_decl): Don't call push/pop_cp_function_context.
+       * decl.c (struct saved_scope): Remove named_labels,
+       {base,member}_init_list.
+       (maybe_push_to_top_level): Don't set them.  Call
+       push_cp_function_context if appropriate.
+       (pop_from_top_level): Likewise.
+
+       * method.c (do_build_assign_ref): Remove obsolete check of
+       TYPE_HAS_ASSIGN_REF (basetype).
+
+       * decl.c (grokfndecl): Diagnose user definition of
+       implicitly-declared methods.
+
+Thu May 23 12:13:08 1996  Bob Manson  <manson@charmed.cygnus.com>
+
+       * method.c (do_build_copy_constructor): Add code to give
+       meaningful error messages instead of crashing.
+       (do_build_assign_ref): Don't synthesize assignment operators for
+       classes containing reference or const members.
+
+       * class.c (struct base_info): Remove cant_synth_copy_ctor
+       and cant_synth_asn_ref.
+       (finish_base_struct): Remove the code that tries to conditionalize
+       synthesis of copy constructors & assignment operators based on
+       access permissions. Instead, let it fail when it tries to
+       synthesize the copy constructor. This will give meaningful error
+       messages instead of silently generating code to perform a bitcopy.
+
+Wed May 22 11:45:19 1996  Bob Manson  <manson@charmed.cygnus.com>
+
+       * lex.c (real_yylex): Remove old-n-crufty #if 0 code for
+       determining types for constant values.
+
+       * decl.c (struct named_label_list): Use instead of stuffing
+       random items into a TREE_LIST node.
+       (named_label_uses): Use the new struct.
+       (poplevel): Ditto.
+       (lookup_label): Ditto.
+       (define_label): Add an error message to tell the user the line
+       where the goto is located in addition to the destination of the
+       goto.
+       (init_decl_processing): Use NULL instead of NULL_TREE to initialize
+       named_label_uses.
+       (finish_function): Ditto.
+       
+       (start_decl): Complain about defining a static data member
+       in a different type from which it was declared.
+
+Wed May 22 09:33:23 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * cvt.c (build_expr_type_conversion): Adjust.
+
+Tue May 21 11:21:56 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * call.c (build_method_call): Always convert 'this' to the
+       appropriate type.
+
+       * search.c (add_conversions): Put the conversion function in
+       TREE_VALUE, the type in TREE_PURPOSE.
+       * cvt.c (build_type_conversion): Adjust.
+       * call.c (user_harshness): Adjust.
+
+       * method.c (emit_thunk): Call temporary_allocation and
+       permanent_allocation around the ASM_OUTPUT_MI_THUNK case, too.
+
+       * tree.c (build_cplus_array_type): Handle tweaking of
+       TYPE_MAIN_VARIANT here.
+       * typeck.c (common_type): Not here.
+
+       * typeck.c (complete_type): Only try to complete an array type if
+       it has a domain.
+
+Mon May 20 14:55:59 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * decl.c (grokvardecl): Call complete_type.
+       (grokdeclarator): Call complete_type for PARM_DECLs.
+
+Fri May 17 16:41:17 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * pt.c (instantiate_class_template): Re-set
+       CLASSTYPE_GOT_SEMICOLON after calling finish_struct_1.
+
+Fri May 17 14:56:55 1996  Mike Stump  <mrs@cygnus.com>
+
+       * cp-tree.h (cp_expand_decl_cleanup): Remove, the backend is now
+       smart enough to do it right.
+       * tree.c (cp_expand_decl_cleanup): Ditto.
+       * decl.c (cp_finish_decl): Use expand_decl_cleanup instead of
+       cp_expand_decl_cleanup.
+       (store_parm_decls): Ditto.
+       (hack_incomplete_structures): Ditto.
+       * except.c (push_eh_cleanup): Ditto.
+
+Fri May 17 13:13:51 1996  Mike Stump  <mrs@cygnus.com>
+
+       * expr.c (expand_expr, cond UNSAVE_EXPR): Move from the C++
+       frontend to the backend where it belongs.
+       * tree.c (unsave_expr): Ditto.
+       (unsave_expr_now): Ditto.
+       * tree.def (UNSAVE_EXPR): Ditto.
+       * cp-tree.h (unsave_expr): Ditto.
+       (unsave_expr_now): Ditto.
+
+Fri May 17 11:02:41 1996  Mike Stump  <mrs@cygnus.com>
+
+       * init.c (emit_base_init): Make sure the partial EH cleanups live
+       on the function_obstack.
+
 Thu May 16 15:29:33 1996  Bob Manson  <manson@charmed.cygnus.com>
 
        * expr.c (do_case): Don't try to dereference null TREE_TYPEs
@@ -2369,7 +2494,7 @@ Mon Nov 13 15:45:34 1995  Mike Stump  <mrs@cygnus.com>
        indirect binding.
        * decl.c (cp_finish_decl): Ensure that we reuse stack slots as fast
        as they are unused.
-       (expand_static_init): Diotto.
+       (expand_static_init): Ditto.
        (cplus_expand_expr_stmt): Ditto.
        * decl2.c (finish_file): Ditto.
        * init.c (perform_member_init): Ditto.
index 6e2132de058dda402d27465a0d7edc684c6070e1..3accebcbe60a2262071173b8a7dbd4649074586a 100644 (file)
@@ -641,10 +641,10 @@ user_harshness (type, parmtype)
     {
       struct harshness_code tmp;
 
-      if (winner && TREE_PURPOSE (winner) == TREE_PURPOSE (conv))
+      if (winner && TREE_VALUE (winner) == TREE_VALUE (conv))
        continue;
 
-      if (tmp = convert_harshness (type, TREE_VALUE (conv), NULL_TREE),
+      if (tmp = convert_harshness (type, TREE_PURPOSE (conv), NULL_TREE),
          (tmp.code < USER_CODE) && (tmp.distance >= 0))
        {
          if (winner)
@@ -2531,8 +2531,8 @@ build_method_call (instance, name, parms, basetype_path, flags)
     {
       int sub_flags = DECL_CONSTRUCTOR_P (function) ? flags : LOOKUP_NORMAL;
       basetype = TREE_TYPE (instance);
-      if (TYPE_METHOD_BASETYPE (TREE_TYPE (function)) != TYPE_MAIN_VARIANT (basetype)
-         && TYPE_USES_COMPLEX_INHERITANCE (basetype))
+      if (TYPE_METHOD_BASETYPE (TREE_TYPE (function))
+         != TYPE_MAIN_VARIANT (basetype))
        {
          basetype = DECL_CLASS_CONTEXT (function);
          instance_ptr = convert_pointer_to (basetype, instance_ptr);
index 4c6cf3ecd714ea1a09eef5ab74e3125023aaa355..9227baf13aa327fff9de98fed0c7aaa37448bf21 100644 (file)
@@ -1408,8 +1408,6 @@ struct base_info
   tree rtti;
   char cant_have_default_ctor;
   char cant_have_const_ctor;
-  char cant_synth_copy_ctor;
-  char cant_synth_asn_ref;
   char no_const_asn_ref;
   char base_has_virtual;
 };
@@ -1465,13 +1463,8 @@ finish_base_struct (t, b, t_binfo)
            TREE_VEC_ELT (binfos, j) = TREE_VEC_ELT (binfos, j+1);
        }
 
-      if (TYPE_HAS_INIT_REF (basetype)
-         && !TYPE_HAS_CONST_INIT_REF (basetype))
+      if (! TYPE_HAS_CONST_INIT_REF (basetype))
        b->cant_have_const_ctor = 1;
-      if (! TYPE_HAS_INIT_REF (basetype)
-         || (TYPE_HAS_NONPUBLIC_CTOR (basetype) == 2
-             && ! is_friend_type (t, basetype)))
-       b->cant_synth_copy_ctor = 1;
 
       if (TYPE_HAS_CONSTRUCTOR (basetype)
          && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (basetype))
@@ -1488,11 +1481,6 @@ finish_base_struct (t, b, t_binfo)
       if (TYPE_HAS_ASSIGN_REF (basetype)
          && !TYPE_HAS_CONST_ASSIGN_REF (basetype))
        b->no_const_asn_ref = 1;
-      if (! TYPE_HAS_ASSIGN_REF (basetype)
-         || TYPE_HAS_ABSTRACT_ASSIGN_REF (basetype)
-         || (TYPE_HAS_NONPUBLIC_ASSIGN_REF (basetype) == 2
-             && ! is_friend_type (t, basetype)))
-       b->cant_synth_asn_ref = 1;
 
       b->n_ancestors += CLASSTYPE_N_SUPERCLASSES (basetype);
       TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (basetype);
@@ -1645,8 +1633,6 @@ finish_base_struct (t, b, t_binfo)
        {
          cp_warning ("direct base `%T' inaccessible in `%T' due to ambiguity",
                      basetype, t);
-         b->cant_synth_asn_ref = 1;
-         b->cant_synth_copy_ctor = 1;
        }
     }
   {
@@ -1660,8 +1646,6 @@ finish_base_struct (t, b, t_binfo)
            if (extra_warnings)
              cp_warning ("virtual base `%T' inaccessible in `%T' due to ambiguity",
                          basetype, t);
-           b->cant_synth_asn_ref = 1;
-           b->cant_synth_copy_ctor = 1;
          }
       }
   }    
@@ -3016,8 +3000,6 @@ finish_struct_1 (t, attributes, warn_anon)
   tree vfields;
   int cant_have_default_ctor;
   int cant_have_const_ctor;
-  int cant_synth_copy_ctor;
-  int cant_synth_asn_ref;
   int no_const_asn_ref;
 
   /* The index of the first base class which has virtual
@@ -3108,8 +3090,6 @@ finish_struct_1 (t, attributes, warn_anon)
       CLASSTYPE_RTTI (t) = base_info.rtti;
       cant_have_default_ctor = base_info.cant_have_default_ctor;
       cant_have_const_ctor = base_info.cant_have_const_ctor;
-      cant_synth_copy_ctor = base_info.cant_synth_copy_ctor;
-      cant_synth_asn_ref = base_info.cant_synth_asn_ref;
       no_const_asn_ref = base_info.no_const_asn_ref;
       base_has_virtual = base_info.base_has_virtual;
       n_baseclasses = TREE_VEC_LENGTH (BINFO_BASETYPES (t_binfo));
@@ -3126,8 +3106,6 @@ finish_struct_1 (t, attributes, warn_anon)
       last_x = NULL_TREE;
       cant_have_default_ctor = 0;
       cant_have_const_ctor = 0;
-      cant_synth_copy_ctor = 0;
-      cant_synth_asn_ref = 0;
       no_const_asn_ref = 0;
       base_has_virtual = 0;
     }
@@ -3273,7 +3251,7 @@ finish_struct_1 (t, attributes, warn_anon)
 
 #if 0
       if (DECL_NAME (x) == constructor_name (t))
-       cant_have_default_ctor = cant_synth_copy_ctor = 1;
+       cant_have_default_ctor = 1;
 #endif
 
       if (TREE_TYPE (x) == error_mark_node)
@@ -3313,8 +3291,8 @@ finish_struct_1 (t, attributes, warn_anon)
             aggregate, initialization by a brace-enclosed list) is the
             only way to initialize nonstatic const and reference
             members.  */
-         cant_synth_asn_ref = 1;
          cant_have_default_ctor = 1;
+         TYPE_HAS_COMPLEX_ASSIGN_REF (t) = 1;
 
          if (! TYPE_HAS_CONSTRUCTOR (t) && extra_warnings)
            {
@@ -3336,8 +3314,8 @@ finish_struct_1 (t, attributes, warn_anon)
             aggregate, initialization by a brace-enclosed list) is the
             only way to initialize nonstatic const and reference
             members.  */
-         cant_synth_asn_ref = 1;
          cant_have_default_ctor = 1;
+         TYPE_HAS_COMPLEX_ASSIGN_REF (t) = 1;
 
          if (! TYPE_HAS_CONSTRUCTOR (t) && !IS_SIGNATURE (t)
              && extra_warnings)
@@ -3508,18 +3486,10 @@ finish_struct_1 (t, attributes, warn_anon)
                  TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_HAS_COMPLEX_INIT_REF (type);
                }
 
-             if (! TYPE_HAS_INIT_REF (type)
-                 || (TYPE_HAS_NONPUBLIC_CTOR (type)
-                     && ! is_friend (t, type)))
-               cant_synth_copy_ctor = 1;
-             else if (!TYPE_HAS_CONST_INIT_REF (type))
+             if (!TYPE_HAS_CONST_INIT_REF (type))
                cant_have_const_ctor = 1;
 
-             if (! TYPE_HAS_ASSIGN_REF (type)
-                 || (TYPE_HAS_NONPUBLIC_ASSIGN_REF (type)
-                     && ! is_friend (t, type)))
-               cant_synth_asn_ref = 1;
-             else if (!TYPE_HAS_CONST_ASSIGN_REF (type))
+             if (!TYPE_HAS_CONST_ASSIGN_REF (type))
                no_const_asn_ref = 1;
 
              if (TYPE_HAS_CONSTRUCTOR (type)
@@ -3614,8 +3584,7 @@ finish_struct_1 (t, attributes, warn_anon)
     }
 
   /* Create default copy constructor, if needed.  */
-  if (! TYPE_HAS_INIT_REF (t) && ! cant_synth_copy_ctor
-      && ! IS_SIGNATURE (t))
+  if (! TYPE_HAS_INIT_REF (t) && ! IS_SIGNATURE (t))
     {
       /* ARM 12.18: You get either X(X&) or X(const X&), but
         not both.  --Chip  */
@@ -3630,8 +3599,7 @@ finish_struct_1 (t, attributes, warn_anon)
   TYPE_HAS_COMPLEX_ASSIGN_REF (t)
     |= TYPE_HAS_ASSIGN_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t);
 
-  if (! TYPE_HAS_ASSIGN_REF (t) && ! cant_synth_asn_ref
-      && ! IS_SIGNATURE (t))
+  if (! TYPE_HAS_ASSIGN_REF (t) && ! IS_SIGNATURE (t))
     {
       tree default_fn = cons_up_default_function (t, name,
                                                  5 + no_const_asn_ref);
index 272ac1b4e2b8060ae5eca4f9d5409c631f618ddf..d1317743ac3699d915de86b7d41bd315b8c35acc 100644 (file)
@@ -2403,7 +2403,6 @@ extern void print_lang_statistics         PROTO((void));
 extern tree array_type_nelts_total             PROTO((tree));
 extern tree array_type_nelts_top               PROTO((tree));
 extern tree break_out_target_exprs             PROTO((tree));
-extern int cp_expand_decl_cleanup              PROTO((tree, tree));
 extern tree get_type_decl                      PROTO((tree));
 extern tree vec_binfo_member                   PROTO((tree, tree));
 extern tree hack_decl_function_context                 PROTO((tree));
index 972939e6e4c32fcf814440a7a89d975c6a59b498..3672ee5b7fa5ab23365a0eb7e1563d9f6af36eb1 100644 (file)
@@ -596,13 +596,24 @@ build_up_reference (type, arg, flags, checkconst)
 
   if (TREE_ADDRESSABLE (targ) == 0)
     {
-      tree temp;
+      if (! (flags&INDIRECT_BIND)
+         && toplevel_bindings_p ())
+       {
+         tree temp = get_temp_name (argtype, 0);
+         /* Give this new temp some rtl and initialize it.  */
+         DECL_INITIAL (temp) = targ;
+         TREE_STATIC (temp) = 1;
+         cp_finish_decl (temp, targ, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
+         /* Do this after declaring it static.  */
+         rval = build_unary_op (ADDR_EXPR, temp, 0);
+         TREE_TYPE (rval) = type;
+         literal_flag = TREE_CONSTANT (rval);
+         goto done;
+       }
 
       if (TREE_CODE (targ) == CALL_EXPR && IS_AGGR_TYPE (argtype))
        {
-         temp = build_cplus_new (argtype, targ);
-         rval = build1 (ADDR_EXPR, type, temp);
-         goto done;
+         arg = build_cplus_new (argtype, targ);
        }
       else if (flags&INDIRECT_BIND)
        {
@@ -611,41 +622,41 @@ build_up_reference (type, arg, flags, checkconst)
              use INDIRECT_BIND.  */
          tree slot = build (VAR_DECL, argtype);
          layout_decl (slot, 0);
-         rval = build (TARGET_EXPR, argtype, slot, arg, NULL_TREE);
-         rval = build1 (ADDR_EXPR, type, rval);
-         goto done;
+         arg = build (TARGET_EXPR, argtype, slot, arg, NULL_TREE, NULL_TREE);
        }
       else
        {
-         temp = get_temp_name (argtype, 0);
-         if (toplevel_bindings_p ())
-           {
-             /* Give this new temp some rtl and initialize it.  */
-             DECL_INITIAL (temp) = targ;
-             TREE_STATIC (temp) = 1;
-             cp_finish_decl (temp, targ, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
-             /* Do this after declaring it static.  */
-             rval = build_unary_op (ADDR_EXPR, temp, 0);
-             TREE_TYPE (rval) = type;
-             literal_flag = TREE_CONSTANT (rval);
-             goto done;
-           }
+         tree temp = get_temp_name (argtype, 0);
+         rval = build_unary_op (ADDR_EXPR, temp, 0);
+         if (binfo && !BINFO_OFFSET_ZEROP (binfo))
+           rval = convert_pointer_to (target_type, rval);
          else
-           {
-             rval = build_unary_op (ADDR_EXPR, temp, 0);
-             if (binfo && !BINFO_OFFSET_ZEROP (binfo))
-               rval = convert_pointer_to (target_type, rval);
-             else
-               TREE_TYPE (rval) = type;
+           TREE_TYPE (rval) = type;
+
+         temp = build (MODIFY_EXPR, argtype, temp, arg);
+         TREE_SIDE_EFFECTS (temp) = 1;
+         return build (COMPOUND_EXPR, type, temp, rval);
+       }
+    }
+
+  if (! (flags&INDIRECT_BIND))
+    {
+      if (TREE_CODE (arg) == TARGET_EXPR)
+       {
+         tree decl = TREE_OPERAND (arg, 0);
+         tree cleanup;
 
-             temp = build (MODIFY_EXPR, argtype, temp, arg);
-             TREE_SIDE_EFFECTS (temp) = 1;
-             return build (COMPOUND_EXPR, type, temp, rval);
+         if (! toplevel_bindings_p ())
+           {
+             expand_decl (decl);
+             cleanup = maybe_build_cleanup (decl);
+             if (cleanup)
+               expand_decl_cleanup (decl, cleanup);
            }
        }
     }
-  else
-    rval = build1 (ADDR_EXPR, type, arg);
+
+  rval = build1 (ADDR_EXPR, type, arg);
 
  done:
   if (TYPE_USES_COMPLEX_INHERITANCE (argtype)
@@ -1498,10 +1509,10 @@ build_type_conversion (code, xtype, expr, for_sure)
   /* Nope; try looking for others.  */
   for (conv = lookup_conversions (basetype); conv; conv = TREE_CHAIN (conv))
     {
-      if (winner && TREE_PURPOSE (winner) == TREE_PURPOSE (conv))
+      if (winner && TREE_VALUE (winner) == TREE_VALUE (conv))
        continue;
 
-      if (can_convert (xtype, TREE_VALUE (conv)))
+      if (can_convert (xtype, TREE_PURPOSE (conv)))
        {
          if (winner)
            {
@@ -1510,7 +1521,7 @@ build_type_conversion (code, xtype, expr, for_sure)
                  cp_error ("ambiguous conversion from `%T' to `%T'", basetype,
                            xtype);
                  cp_error ("  candidate conversions include `%T' and `%T'",
-                           TREE_VALUE (winner), TREE_VALUE (conv));
+                           TREE_PURPOSE (winner), TREE_PURPOSE (conv));
                }
              return NULL_TREE;
            }
@@ -1521,7 +1532,7 @@ build_type_conversion (code, xtype, expr, for_sure)
 
   if (winner)
     return build_type_conversion_1 (xtype, basetype, expr,
-                                   TREE_PURPOSE (winner), for_sure);
+                                   DECL_NAME (TREE_VALUE (winner)), for_sure);
 
   return NULL_TREE;
 }
@@ -1580,10 +1591,10 @@ build_expr_type_conversion (desires, expr, complain)
       int win = 0;
       tree candidate;
 
-      if (winner && TREE_PURPOSE (winner) == TREE_PURPOSE (conv))
+      if (winner && TREE_VALUE (winner) == TREE_VALUE (conv))
        continue;
 
-      candidate = TREE_VALUE (conv);
+      candidate = TREE_PURPOSE (conv);
       if (TREE_CODE (candidate) == REFERENCE_TYPE)
        candidate = TREE_TYPE (candidate);
 
@@ -1609,7 +1620,7 @@ build_expr_type_conversion (desires, expr, complain)
                  cp_error ("ambiguous default type conversion from `%T'",
                            basetype);
                  cp_error ("  candidate conversions include `%T' and `%T'",
-                           TREE_VALUE (winner), TREE_VALUE (conv));
+                           TREE_PURPOSE (winner), TREE_PURPOSE (conv));
                }
              return error_mark_node;
            }
@@ -1620,11 +1631,11 @@ build_expr_type_conversion (desires, expr, complain)
 
   if (winner)
     {
-      tree type = TREE_VALUE (winner);
+      tree type = TREE_PURPOSE (winner);
       if (TREE_CODE (type) == REFERENCE_TYPE)
        type = TREE_TYPE (type);
       return build_type_conversion_1 (type, basetype, expr,
-                                     TREE_PURPOSE (winner), 1);
+                                     DECL_NAME (TREE_VALUE (winner)), 1);
     }
 
   return NULL_TREE;
@@ -1819,6 +1830,41 @@ null_ptr_cst (t)
   return (INTEGRAL_TYPE_P (TREE_TYPE (t)) && integer_zerop (t));
 }
 
+tree
+build_conv (code, type, from)
+     enum tree_code code;
+     tree type, from;
+{
+  tree t = build1 (code, type, from);
+  int rank = ICS_STD_RANK (from);
+  switch (code)
+    {
+    case PROMO_CONV:
+      if (rank < PROMO_RANK)
+       rank = PROMO_RANK;
+      break;
+      
+    case PTR_CONV:
+    case PMEM_CONV:
+    case BASE_CONV:
+    case STD_CONV:
+      if (rank < STD_RANK)
+       rank = STD_RANK;
+      break;
+
+    case PBOOL_CONV:
+      if (rank < PBOOL_RANK)
+       rank = PBOOL_RANK;
+      break;
+
+    default:
+      break;
+    }
+  ICS_STD_RANK (t) = rank;
+  ICS_USER_FLAG (t) = ICS_USER_FLAG (from);
+  return t;
+}
+
 tree
 standard_conversion (to, from, expr)
      tree to, from, expr;
@@ -1830,25 +1876,27 @@ standard_conversion (to, from, expr)
   if (from == to)
     return from;
 
-  conv = from;
+  conv = build1 (EXACT_CONV, from, expr);
+  if (TREE_CODE (expr) == USER_CONV)
+    ICS_USER_FLAG (conv) = 1;
 
   if (fcode == FUNCTION_TYPE)
     {
       from = build_pointer_type (from);
       fcode = TREE_CODE (from);
-      conv = build1 (LVALUE_CONV, from, conv);
+      conv = build_conv (LVALUE_CONV, from, conv);
     }
   else if (fcode == ARRAY_TYPE)
     {
       from = build_pointer_type (TREE_TYPE (from));
       fcode = TREE_CODE (from);
-      conv = build1 (LVALUE_CONV, from, conv);
+      conv = build_conv (LVALUE_CONV, from, conv);
     }
 
   if ((tcode == POINTER_TYPE || TYPE_PTRMEMFUNC_P (to))
       && expr && null_ptr_cst (expr))
     {
-      conv = build1 (CONV_CONV, to, conv);
+      conv = build_conv (STD_CONV, to, conv);
     }
   else if (tcode == POINTER_TYPE && fcode == POINTER_TYPE)
     {
@@ -1864,7 +1912,7 @@ standard_conversion (to, from, expr)
          from = cp_build_type_variant (void_type_node,
                                        TYPE_READONLY (TREE_TYPE (from)),
                                        TYPE_VOLATILE (TREE_TYPE (from)));
-         conv = build1 (CONV_CONV, from, conv);
+         conv = build_conv (PTR_CONV, from, conv);
        }
       else if (ufcode == OFFSET_TYPE && utcode == OFFSET_TYPE)
        {
@@ -1877,7 +1925,7 @@ standard_conversion (to, from, expr)
                             1)))
            {
              from = build_offset_type (tbase, TREE_TYPE (TREE_TYPE (from)));
-             conv = build1 (CONV_CONV, from, conv);
+             conv = build_conv (PMEM_CONV, from, conv);
            }
          else
            return 0;
@@ -1890,7 +1938,7 @@ standard_conversion (to, from, expr)
              from = cp_build_type_variant (TREE_TYPE (to),
                                            TYPE_READONLY (TREE_TYPE (from)),
                                            TYPE_VOLATILE (TREE_TYPE (from)));
-             conv = build1 (CONV_CONV, from, conv);
+             conv = build_conv (PTR_CONV, from, conv);
            }
          else
            return 0;
@@ -1901,7 +1949,7 @@ standard_conversion (to, from, expr)
       if (! comptypes (from, to, 1) && comp_ptr_ttypes (to, from))
        {
          from = to;
-         conv = build1 (QUAL_CONV, from, conv);
+         conv = build_conv (QUAL_CONV, from, conv);
        }
     }
   else if (TYPE_PTRMEMFUNC_P (to) && TYPE_PTRMEMFUNC_P (from))
@@ -1923,29 +1971,32 @@ standard_conversion (to, from, expr)
                                    TYPE_VOLATILE (fbase));
       from = build_cplus_method_type (from, TREE_TYPE (fromfn),
                                      TREE_CHAIN (TYPE_ARG_TYPES (fromfn)));
-      conv = build1 (CONV_CONV, from, conv);
+      conv = build_conv (PMEM_CONV, from, conv);
     }
   else if (tcode == BOOLEAN_TYPE)
     {
-      if (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE
-         || fcode == POINTER_TYPE)
-       return build1 (CONV_CONV, to, conv);
-      else
+      if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE
+            || fcode == POINTER_TYPE || TYPE_PTRMEMFUNC_P (from)))
        return 0;
+
+      if (fcode == POINTER_TYPE || TYPE_PTRMEMFUNC_P (from))
+       conv = build_conv (PBOOL_CONV, to, conv);
+      else
+       conv = build_conv (STD_CONV, to, conv);
     }
   else if (INTEGRAL_CODE_P (tcode) || tcode == REAL_TYPE)
     {
       if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE))
        return 0;
       else if (to == type_promotes_to (from))
-       conv = build1 (PROMO_CONV, to, conv);
+       conv = build_conv (PROMO_CONV, to, conv);
       else 
-       conv = build1 (CONV_CONV, to, conv);
+       conv = build_conv (STD_CONV, to, conv);
     }
   else if (IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from)
           && DERIVED_FROM_P (to, from))
     {
-      conv = build1 (CONV_CONV, to, conv);
+      conv = build_conv (BASE_CONV, to, conv);
     }
   else
     return 0;
@@ -1958,16 +2009,366 @@ implicit_conversion (to, from, expr, flags)
      tree to, from, expr;
      int flags;
 {
-  tree conv = standard_conversion (to, from, expr);
+  tree t, conv = standard_conversion (to, from, expr);
+  struct z_candidate *cand;
 
   if (conv || (flags & LOOKUP_NO_CONVERSION))
     return conv;
 
   flags |= LOOKUP_NO_CONVERSION;
 
-    /* try constructors */;
-    /* try conversion ops */;
+  cand = build_user_type_conversion_1 (to, expr, flags);
+  if (! cand)
+    return NULL_TREE;
+
+  conv = cand->second_conv;
+
+  for (t = conv; TREE_CODE (TREE_OPERAND (t, 0)) != EXACT_MATCH; )
+    t = TREE_OPERAND (t, 0));
+
+  TREE_OPERAND (t, 0) = build (USER_CONV
 
   return conv;
 }
+
+struct z_candidate *
+add_method_candidate (candidates, method, instance, parms, flags)
+     struct z_candidate *candidates;
+     tree method, instance, parms;
+     int flags;
+{
+  
+}
+
+struct z_candidate *
+build_user_type_conversion_1 (totype, expr, flags)
+     tree totype, expr;
+     int flags;
+{
+  struct z_candidate *candidates, *cand;
+  tree fromtype = TREE_TYPE (expr);
+  tree ctors = NULL_TREE, convs = NULL_TREE, t;
+
+  if (IS_AGGR_TYPE (totype))
+    ctors = lookup_fnfields (TYPE_BINFO (totype), ctor_identifier, 0);
+  if (IS_AGGR_TYPE (fromtype))
+    convs = lookup_conversions (fromtype);
+
+  if (ctors)
+    ctors = TREE_VALUE (ctors);
+  for (; ctors; ctors = DECL_CHAIN (ctors))
+    {
+      candidates = add_ctor_candidate (candidates, ctors, expr, flags);
+    }
+
+  for (; convs; convs = TREE_CHAIN (convs))
+    {
+      tree fn = TREE_VALUE (convs);
+      tree ics = standard_conversion (totype, TREE_TYPE (TREE_TYPE (fn)), 0);
+      if (ics)
+       {
+         candidates = add_method_candidate
+           (candidates, fn, expr, NULL_TREE, flags);
+         candidates->second_ics = ics;
+       }
+    }
+
+  if (! any_viable (candidates))
+    {
+      if (flags & LOOKUP_COMPLAIN)
+       cp_error ("no viable candidates");
+      return 0;
+    }
+
+  candidates = splice_viable (candidates);
+  cand = tourney (candidates, totype);
+
+  if (cand == 0)
+    {
+      if (flags & LOOKUP_COMPLAIN)
+       cp_error ("ambiguous user-defined type conversion");
+    }
+
+  return cand;
+}
+
+/* Compare two implicit conversion sequences according to the rules set out in
+   [over.ics.rank].  Return values:
+
+      1: ics1 is better than ics2
+     -1: ics2 is better than ics1
+      0: ics1 and ics2 are indistinguishable */
+
+int
+compare_ics (ics1, ics2)
+     tree ics1, ics2;
+{
+  tree main1, main2;
+
+  if (ICS_RANK (ics1) > ICS_RANK (ics2))
+    return 1;
+  else if (ICS_RANK (ics1) < ICS_RANK (ics2))
+    return -1;
+
+  /* User-defined  conversion sequence U1 is a better conversion sequence
+     than another user-defined conversion sequence U2 if they contain the
+     same user-defined conversion operator or constructor and if the sec-
+     ond standard conversion sequence of U1 is  better  than  the  second
+     standard conversion sequence of U2. */
+
+  if (ICS_RANK (ics1) == USER_RANK)
+    {
+      tree t1, t2;
+
+      for (t1 = ics1; TREE_CODE (t1) != USER_CONV; t1 = TREE_OPERAND (t1, 0))
+       ;
+      for (t2 = ics2; TREE_CODE (t2) != USER_CONV; t2 = TREE_OPERAND (t2, 0))
+       ;
+
+      if (USER_CONV_FN (t1) != USER_CONV_FN (t2))
+       return 0;
+      else if (ICS_STD_RANK (ics1) > ICS_STD_RANK (ics2))
+       return 1;
+      else if (ICS_STD_RANK (ics1) < ICS_STD_RANK (ics2))
+       return -1;
+
+      /* else fall through */
+    }
+
+#if 0 /* Handled by ranking */
+  /* A conversion that is not a conversion of a pointer,  or  pointer  to
+     member,  to  bool  is  better than another conversion that is such a
+     conversion.  */
+  {
+    int bool1 = TREE_CODE (ics1) == BOOL_CONV;
+    int bool2 = TREE_CODE (ics2) == BOOL_CONV;
+
+    if (bool1)
+      {
+       tree it = TREE_TYPE (TREE_OPERAND (ics1, 0));
+       if (TREE_CODE (it) != POINTER_TYPE
+           && ! TYPE_PTRMEMFUNC_TYPE (it))
+         bool1 = 0;
+      }
+    if (bool2)
+      {
+       tree it = TREE_TYPE (TREE_OPERAND (ics2, 0));
+       if (TREE_CODE (it) != POINTER_TYPE
+           && ! TYPE_PTRMEMFUNC_TYPE (it))
+         bool2 = 0;
+      }
+    if (bool1 && ! bool2)
+      return 1;
+    if (bool2 && ! bool1)
+      return -1;
+  }
+#endif
+
+  if (TREE_CODE (ics1) == QUAL_CONV)
+    main1 = TREE_OPERAND (ics1, 0);
+  else
+    main1 = ics1;
+
+  if (TREE_CODE (ics2) == QUAL_CONV)
+    main2 = TREE_OPERAND (ics2, 0);
+  else
+    main2 = ics2;
+
+  if (TREE_CODE (main1) != TREE_CODE (main2))
+    return 0;
+
+  if (TREE_CODE (main1) == PTR_CONV || TREE_CODE (main1) == PMEM_CONV
+      || TREE_CODE (main1) == REF_BIND)
+    {
+      tree to1 = TREE_TYPE (main1);
+      tree from1 = TREE_TYPE (TREE_OPERAND (main1, 0));
+      tree to2 = TREE_TYPE (main2);
+      tree from2 = TREE_TYPE (TREE_OPERAND (main2, 0));
+      int distf, distt;
+
+      /* Standard conversion sequence S1 is a better conversion sequence than
+        standard conversion sequence S2 if...
+
+        S1 and S2 differ only in their qualification conversion  and  they
+        yield types identical except for cv-qualifiers and S2 adds all the
+        qualifiers that S1 adds (and in the same places) and S2  adds  yet
+        more  cv-qualifiers  than  S1,  or the similar case with reference
+        binding15). */
+      if (from1 == from2 && to1 == to2)
+       {
+         to1 = TREE_TYPE (TREE_TYPE (ics1));
+         to2 = TREE_TYPE (TREE_TYPE (ics2));
+         if (TYPE_READONLY (to1) >= TYPE_READONLY (to2)
+             && TYPE_VOLATILE (to1) > TYPE_VOLATILE (to2))
+           return 1;
+         else if (TYPE_READONLY (to1) > TYPE_READONLY (to2)
+                  && TYPE_VOLATILE (to1) == TYPE_VOLATILE (to2))
+           return 1;
+         else if (TYPE_READONLY (to1) <= TYPE_READONLY (to2)
+                  && TYPE_VOLATILE (to1) < TYPE_VOLATILE (to2))
+           return -1;
+         else if (TYPE_READONLY (to1) < TYPE_READONLY (to2)
+                  && TYPE_VOLATILE (to1) == TYPE_VOLATILE (to2))
+           return -1;
+         return 0;
+       }
+       
+      if (TYPE_PTRMEMFUNC_P (to1))
+       {
+         to1 = TYPE_METHOD_BASETYPE (TYPE_PTRMEMFUNC_FN_TYPE (to1));
+         from1 = TYPE_METHOD_BASETYPE (TYPE_PTRMEMFUNC_FN_TYPE (from1));
+       }
+      else
+       {
+         to1 = TREE_TYPE (to1);
+         from1 = TREE_TYPE (from1);
+
+         if (TREE_CODE (to1) == OFFSET_TYPE)
+           {
+             to1 = TYPE_OFFSET_BASETYPE (to1);
+             from1 = TYPE_OFFSET_BASETYPE (from1);
+           }
+       }
+
+      if (TYPE_PTRMEMFUNC_P (to2))
+       {
+         to2 = TYPE_METHOD_BASETYPE (TYPE_PTRMEMFUNC_FN_TYPE (to2));
+         from2 = TYPE_METHOD_BASETYPE (TYPE_PTRMEMFUNC_FN_TYPE (from2));
+       }
+      else
+       {
+         to2 = TREE_TYPE (to2);
+         from2 = TREE_TYPE (from2);
+
+         if (TREE_CODE (to2) == OFFSET_TYPE)
+           {
+             to2 = TYPE_OFFSET_BASETYPE (to2);
+             from2 = TYPE_OFFSET_BASETYPE (from2);
+           }
+       }
+
+      if (! (IS_AGGR_TYPE (from1) && IS_AGGR_TYPE (from2)))
+       return 0;
+
+      distf = get_base_distance (from1, from2, 0, 0);
+      if (distf == -1)
+       distf = -get_base_distance (from2, from1, 0, 0);
+      if (distf == -1)
+       return 0;
+
+      /* If class B is derived directly or indirectly from class  A,  conver-
+        sion  of  B*  to  A*  is  better than conversion of B* to void*, and
+        conversion of A* to void* is better than conversion of B* to void*. */
+
+      if (TREE_CODE (to1) == VOID_TYPE && TREE_CODE (to2) == VOID_TYPE)
+       {
+         if (distf > 0)
+           return 1;
+         else if (distf < 0)
+           return -1;
+       }
+      else if (TREE_CODE (to2) == VOID_TYPE && IS_AGGR_TYPE (to1)
+              && get_base_distance (to1, from1, 0, 0) != -1)
+       return 1;
+      else if (TREE_CODE (to1) == VOID_TYPE && IS_AGGR_TYPE (to2)
+              && get_base_distance (to2, from2, 0, 0) != -1)
+       return -1;
+
+      if (! (IS_AGGR_TYPE (to1) && IS_AGGR_TYPE (to2)))
+       return 0;
+
+      /* If  class B is derived directly or indirectly from class A and class
+        C is derived directly or indirectly from B */
+
+      distt = get_base_distance (to1, to2, 0, 0);
+      if (distt == -1)
+       distt = -get_base_distance (to2, to1, 0, 0);
+      if (distt == -1)
+       return 0;
+
+      /* --conversion of C* to B* is better than conversion of C* to A*, */
+      if (distf == 0)
+       {
+         if (distt > 0)
+           return -1;
+         else if (distt < 0)
+           return 1;
+       }
+      /* --conversion of B* to A* is better than conversion of C* to A*, */
+      else if (distt == 0)
+       {
+         if (distf > 0)
+           return 1;
+         else if (distf < 0)
+           return -1;
+       }
+    }
+  return 0;
+}
+
+int joust (cand1, cand2)
+     struct z_candidate *cand1, *cand2;
+{
+  int winner = 0;
+  int i;
+
+  for (i = 0; i < TREE_VEC_LENGTH (cand1->convs); ++i)
+    {
+      int comp = compare_ics (TREE_VEC_ELT (cand1->convs, i),
+                             TREE_VEC_ELT (cand2->convs, i));
+
+      if (comp != 0)
+       {
+         if (winner && comp != winner)
+           return 0;
+         winner = comp;
+       }
+    }
+
+  if (winner == 0 && cand1->second_ics)
+    winner = compare_ics (cand1->second_ics, cand2->second_ics);
+
+  return winner;
+}
+
+struct z_candidate *
+tourney (candidates)
+     struct z_candidate *candidates;
+{
+  struct z_candidate *champ = candidates, *challenger;
+  int fate;
+
+  /* This algorithm has a worst case of O(2n) (winner is last) , and a best
+     case of O(n/2) (no winner); much better than a sorting algorithm.  */
+
+  for (challenger = champ->next; challenger; )
+    {
+      fate = joust (champ, challenger);
+      if (fate == 1)
+       challenger = challenger->next;
+      else
+       {
+         if (fate == 0)
+           {
+             champ = challenger->next;
+             if (champ == 0)
+               return 0;
+           }
+         else
+           champ = challenger;
+
+         challenger = champ->next;
+       }
+    }
+
+  for (challenger = candidates; challenger != champ;
+       challenger = challenger->next)
+    {
+      fate = joust (champ, challenger);
+      if (fate != 1)
+       return 0;
+    }
+
+  return champ;
+}
 #endif
index 73b570945d290ecfadfc8bdaadcf0508adc8ffc2..fe1b60fb2dfdab15a33691b53fb56c223dae96bd 100644 (file)
@@ -300,6 +300,16 @@ tree pfn_identifier, index_identifier, delta_identifier, delta2_identifier;
 tree pfn_or_delta2_identifier, tag_identifier;
 tree vt_off_identifier;
 
+struct named_label_list
+{
+  struct binding_level *binding_level;
+  tree names_in_scope;
+  tree label_decl;
+  char *filename_o_goto;
+  int lineno_o_goto;
+  struct named_label_list *next;
+};
+
 /* A list (chain of TREE_LIST nodes) of named label uses.
    The TREE_PURPOSE field is the list of variables defined
    the the label's scope defined at the point of use.
@@ -307,11 +317,17 @@ tree vt_off_identifier;
    The TREE_TYPE field holds `current_binding_level' at the
    point of the label's use.
 
+   BWAHAHAAHAHahhahahahaah.  No, no, no, said the little chicken.
+
+   Look at the pretty struct named_label_list. See the pretty struct
+   with the pretty named fields that describe what they do. See the
+   pretty lack of gratuitous casts. Notice the code got a lot cleaner.
+
    Used only for jumps to as-yet undefined labels, since
    jumps to defined labels can have their validity checked
    by stmt.c.  */
 
-static tree named_label_uses;
+static struct named_label_list *named_label_uses = NULL;
 
 /* A list of objects which have constructors or destructors
    which reside in the global scope.  The decl is stored in
@@ -1199,12 +1215,12 @@ poplevel (keep, reverse, functionbody)
     level_chain = current_binding_level->level_chain;
     if (level_chain)
       {
-       tree labels;
-       for (labels = named_label_uses; labels; labels = TREE_CHAIN (labels))
-         if (TREE_TYPE (labels) == (tree)current_binding_level)
+       struct named_label_list *labels;
+       for (labels = named_label_uses; labels; labels = labels->next)
+         if (labels->binding_level == current_binding_level)
            {
-             TREE_TYPE (labels) = (tree)level_chain;
-             TREE_PURPOSE (labels) = level_chain->names;
+             labels->binding_level = level_chain;
+             labels->names_in_scope = level_chain->names;
            }
       }
   }
@@ -1739,11 +1755,9 @@ struct saved_scope {
   tree old_bindings;
   struct saved_scope *prev;
   tree class_name, class_type, function_decl;
-  tree base_init_list, member_init_list;
   struct binding_level *class_bindings;
   tree *lang_base, *lang_stack, lang_name;
   int lang_stacksize;
-  tree named_labels;
   int minimal_parse_mode;
   tree last_function_parms;
   tree template_parms;
@@ -1803,6 +1817,9 @@ maybe_push_to_top_level (pseudo)
   struct binding_level *b = inner_binding_level;
   tree old_bindings = NULL_TREE;
 
+  if (current_function_decl)
+    push_cp_function_context (NULL_TREE);
+
   if (previous_class_type)
     old_bindings = store_bindings (previous_class_values, old_bindings);
 
@@ -1832,19 +1849,17 @@ maybe_push_to_top_level (pseudo)
   s->class_name = current_class_name;
   s->class_type = current_class_type;
   s->function_decl = current_function_decl;
-  s->base_init_list = current_base_init_list;
-  s->member_init_list = current_member_init_list;
   s->class_bindings = class_binding_level;
   s->lang_stack = current_lang_stack;
   s->lang_base = current_lang_base;
   s->lang_stacksize = current_lang_stacksize;
   s->lang_name = current_lang_name;
-  s->named_labels = named_labels;
   s->minimal_parse_mode = minimal_parse_mode;
   s->last_function_parms = last_function_parms;
   s->template_parms = current_template_parms;
   s->previous_class_type = previous_class_type;
   s->previous_class_values = previous_class_values;
+
   current_class_name = current_class_type = NULL_TREE;
   current_function_decl = NULL_TREE;
   class_binding_level = (struct binding_level *)0;
@@ -1902,8 +1917,6 @@ pop_from_top_level ()
     }
   current_class_name = s->class_name;
   current_class_type = s->class_type;
-  current_base_init_list = s->base_init_list;
-  current_member_init_list = s->member_init_list;
   current_function_decl = s->function_decl;
   class_binding_level = s->class_bindings;
   free (current_lang_base);
@@ -1915,7 +1928,6 @@ pop_from_top_level ()
     strict_prototype = strict_prototypes_lang_cplusplus;
   else if (current_lang_name == lang_name_c)
     strict_prototype = strict_prototypes_lang_c;
-  named_labels = s->named_labels;
   minimal_parse_mode = s->minimal_parse_mode;
   last_function_parms = s->last_function_parms;
   current_template_parms = s->template_parms;
@@ -1923,6 +1935,9 @@ pop_from_top_level ()
   previous_class_values = s->previous_class_values;
 
   free (s);
+
+  if (current_function_decl)
+    pop_cp_function_context (NULL_TREE);
 }
 \f
 /* Push a definition of struct, union or enum tag "name".
@@ -3717,13 +3732,20 @@ lookup_label (id)
 
   if ((decl == NULL_TREE
       || DECL_SOURCE_LINE (decl) == 0)
-      && (named_label_uses == NULL_TREE
-         || TREE_PURPOSE (named_label_uses) != current_binding_level->names
-         || TREE_VALUE (named_label_uses) != decl))
-    {
-      named_label_uses
-       = tree_cons (current_binding_level->names, decl, named_label_uses);
-      TREE_TYPE (named_label_uses) = (tree)current_binding_level;
+      && (named_label_uses == NULL
+         || named_label_uses->names_in_scope != current_binding_level->names
+         || named_label_uses->label_decl != decl))
+    {
+      struct named_label_list *new_ent;
+      new_ent
+       = (struct named_label_list*)oballoc (sizeof (struct named_label_list));
+      new_ent->label_decl = decl;
+      new_ent->names_in_scope = current_binding_level->names;
+      new_ent->binding_level = current_binding_level;
+      new_ent->lineno_o_goto = lineno;
+      new_ent->filename_o_goto = input_filename;
+      new_ent->next = named_label_uses;
+      named_label_uses = new_ent;
     }
 
   /* Use a label already defined or ref'd with this name.  */
@@ -3754,7 +3776,7 @@ lookup_label (id)
   SET_IDENTIFIER_LABEL_VALUE (id, decl);
 
   named_labels = tree_cons (NULL_TREE, decl, named_labels);
-  TREE_VALUE (named_label_uses) = decl;
+  named_label_uses->label_decl = decl;
 
   return decl;
 }
@@ -3830,7 +3852,7 @@ define_label (filename, line, name)
     }
   else
     {
-      tree uses, prev;
+      struct named_label_list *uses, *prev;
       int identified = 0;
 
       /* Mark label as having been defined.  */
@@ -3839,17 +3861,17 @@ define_label (filename, line, name)
       DECL_SOURCE_FILE (decl) = filename;
       DECL_SOURCE_LINE (decl) = line;
 
-      for (prev = NULL_TREE, uses = named_label_uses;
-          uses;
-          prev = uses, uses = TREE_CHAIN (uses))
-       if (TREE_VALUE (uses) == decl)
+      prev = NULL;
+      uses = named_label_uses;
+      while (uses != NULL)
+       if (uses->label_decl == decl)
          {
            struct binding_level *b = current_binding_level;
            while (b)
              {
                tree new_decls = b->names;
-               tree old_decls = ((tree)b == TREE_TYPE (uses)
-                                 ? TREE_PURPOSE (uses) : NULL_TREE);
+               tree old_decls = (b == uses->binding_level)
+                                 ? uses->names_in_scope : NULL_TREE;
                while (new_decls != old_decls)
                  {
                    if (TREE_CODE (new_decls) == VAR_DECL
@@ -3862,23 +3884,35 @@ define_label (filename, line, name)
                             && DECL_INITIAL (new_decls) != error_mark_node)
                            || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (new_decls))))
                      {
-                       if (! identified)
-                         cp_error ("jump to label `%D'", decl);
-                       identified = 1;
+                       if (! identified) 
+                         {
+                           cp_error ("jump to label `%D'", decl);
+                           error_with_file_and_line (uses->filename_o_goto,
+                                                     uses->lineno_o_goto,
+                                                     "  from here");
+                           identified = 1;
+                       }
                        cp_error_at ("  crosses initialization of `%#D'",
                                     new_decls);
                      }
                    new_decls = TREE_CHAIN (new_decls);
                  }
-               if ((tree)b == TREE_TYPE (uses))
+               if (b == uses->binding_level)
                  break;
                b = b->level_chain;
              }
 
-           if (prev)
-             TREE_CHAIN (prev) = TREE_CHAIN (uses);
+           if (prev != NULL)
+             prev->next = uses->next;
            else
-             named_label_uses = TREE_CHAIN (uses);
+             named_label_uses = uses->next;
+
+           uses = uses->next;
+         }
+       else
+         {
+           prev = uses;
+           uses = uses->next;
          }
       current_function_return_value = NULL_TREE;
       return decl;
@@ -4665,7 +4699,7 @@ init_decl_processing ()
 
   current_function_decl = NULL_TREE;
   named_labels = NULL_TREE;
-  named_label_uses = NULL_TREE;
+  named_label_uses = NULL;
   current_binding_level = NULL_BINDING_LEVEL;
   free_binding_level = NULL_BINDING_LEVEL;
 
@@ -5797,8 +5831,13 @@ start_decl (declarator, declspecs, initialized, raises)
          tree field = lookup_field (context, DECL_NAME (decl), 0, 0);
          if (field == NULL_TREE || TREE_CODE (field) != VAR_DECL)
            cp_error ("`%#D' is not a static member of `%#T'", decl, context);
-         else if (duplicate_decls (decl, field))
-           decl = field;
+         else
+           {
+             if (DECL_CONTEXT (field) != context)
+               cp_pedwarn ("ANSI C++ does not permit `%T::%D' to be defined as `%T::%D'", DECL_CONTEXT (field), DECL_NAME (decl), context, DECL_NAME (decl));
+             if (duplicate_decls (decl, field))
+               decl = field;
+           }
        }
       else
        {
@@ -6034,25 +6073,7 @@ grok_reference_init (decl, type, init, cleanupp)
     goto fail;
   else if (tmp != NULL_TREE)
     {
-      tree subtype = TREE_TYPE (type);
       init = tmp;
-
-      /* Associate the cleanup with the reference so that we
-        don't get burned by "aggressive" cleanup policy.  */
-      if (TYPE_NEEDS_DESTRUCTOR (subtype))
-       {
-         if (TREE_CODE (tmp) == ADDR_EXPR)
-           tmp = TREE_OPERAND (tmp, 0);
-         if (TREE_CODE (tmp) == TARGET_EXPR)
-           {
-             *cleanupp = build_delete
-               (build_pointer_type (subtype),
-                build_unary_op (ADDR_EXPR, TREE_OPERAND (tmp, 0), 0),
-                integer_two_node, LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0);
-             TREE_OPERAND (tmp, 2) = error_mark_node;
-           }
-       }
-
       DECL_INITIAL (decl) = save_expr (init);
     }
   else
@@ -6620,7 +6641,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
                {
                  /* XXX: Why don't we use decl here?  */
                  /* Ans: Because it was already expanded? */
-                 if (! cp_expand_decl_cleanup (NULL_TREE, cleanup))
+                 if (! expand_decl_cleanup (NULL_TREE, cleanup))
                    cp_error ("parser lost in parsing declaration of `%D'",
                              decl);
                  /* Cleanup used up here.  */
@@ -6710,7 +6731,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
              /* Store the cleanup, if there was one.  */
              if (cleanup)
                {
-                 if (! cp_expand_decl_cleanup (decl, cleanup))
+                 if (! expand_decl_cleanup (decl, cleanup))
                    cp_error ("parser lost in parsing declaration of `%D'",
                              decl);
                }
@@ -7113,6 +7134,8 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
       if (check)
        {
          tmp = check_classfn (ctype, decl);
+         if (tmp && DECL_ARTIFICIAL (tmp))
+           cp_error ("definition of implicitly-declared `%D'", tmp);
          if (tmp && duplicate_decls (decl, tmp))
            return tmp;
        }
@@ -7159,6 +7182,8 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
              revert_static_member_fn (&decl, NULL, NULL);
              last_function_parms = TREE_CHAIN (last_function_parms);
            }
+         if (tmp && DECL_ARTIFICIAL (tmp))
+           cp_error ("definition of implicitly-declared `%D'", tmp);
          if (tmp && duplicate_decls (decl, tmp))
            return tmp;
        }
@@ -7224,7 +7249,7 @@ grokvardecl (type, declarator, specbits, initialized, constp)
       DECL_ASSEMBLER_NAME (decl) = build_static_name (basetype, declarator);
     }
   else
-    decl = build_decl (VAR_DECL, declarator, type);
+    decl = build_decl (VAR_DECL, declarator, complete_type (type));
 
   DECL_ASSEMBLER_NAME (decl) = current_namespace_id (DECL_ASSEMBLER_NAME (decl));
 
@@ -9118,7 +9143,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
            return NULL_TREE;
          }
 
-       decl = build_decl (PARM_DECL, declarator, type);
+       decl = build_decl (PARM_DECL, declarator, complete_type (type));
 
        bad_specifiers (decl, "parameter", virtualp, quals != NULL_TREE,
                        inlinep, friendp, raises != NULL_TREE);
@@ -11279,7 +11304,7 @@ store_parm_decls ()
                  && (cleanup = maybe_build_cleanup (parm), cleanup))
                {
                  expand_decl (parm);
-                 if (! cp_expand_decl_cleanup (parm, cleanup))
+                 if (! expand_decl_cleanup (parm, cleanup))
                    cp_error ("parser lost in parsing declaration of `%D'",
                              parm);
                  parms_have_cleanups = 1;
@@ -11973,7 +11998,7 @@ finish_function (lineno, call_poplevel, nested)
       current_function_decl = NULL_TREE;
     }
 
-  named_label_uses = NULL_TREE;
+  named_label_uses = NULL;
   current_class_ptr = NULL_TREE;
   current_class_ref = NULL_TREE;
 }
@@ -12200,7 +12225,7 @@ hack_incomplete_structures (type)
              expand_decl (decl);
              cleanup = maybe_build_cleanup (decl);
              expand_decl_init (decl);
-             if (! cp_expand_decl_cleanup (decl, cleanup))
+             if (! expand_decl_cleanup (decl, cleanup))
                cp_error ("parser lost in parsing declaration of `%D'",
                          decl);
            }
index 1f661558869e349e7b2099bca5739514d288f08d..db4f294ff864b8fe29ddca9cc4898c189d77b0bd 100644 (file)
@@ -1285,7 +1285,8 @@ dump_expr (t, nop)
       break;
 
     case CAST_EXPR:
-      if (TREE_CHAIN (TREE_OPERAND (t, 0)))
+      if (TREE_OPERAND (t, 0) == NULL_TREE
+         || TREE_CHAIN (TREE_OPERAND (t, 0)))
        {
          dump_type (TREE_TYPE (t), 0);
          OB_PUTC ('(');
index b530a3ba058662d1ed017edb56c3690bf42f5f45..adebe3b47210ab694a643919cfb16f906faad025 100644 (file)
@@ -962,7 +962,7 @@ push_eh_cleanup ()
   cleanup = build (COMPOUND_EXPR, void_type_node, cleanup,
                   build_modify_expr (saved_in_catch, NOP_EXPR,
                                      build_modify_expr (saved_throw_type, NOP_EXPR, integer_zero_node)));
-  cp_expand_decl_cleanup (NULL_TREE, cleanup);
+  expand_decl_cleanup (NULL_TREE, cleanup);
 
   resume_momentary (yes);
 }
index ccdc8aef4c1dc2e3236c425019632d6c58a52984..be3d89659e31e071652d09bf1d14f1d8eabcbd36 100644 (file)
@@ -9,7 +9,7 @@
 @chapter Internal Architecture of the Compiler
 
 This is meant to describe the C++ front-end for gcc in detail.
-Questions and comments to mrs@@cygnus.com.
+Questions and comments to Mike Stump @code{<mrs@@cygnus.com>}.
 
 @menu
 * Limitations of g++::          
@@ -310,9 +310,7 @@ vtables.  See also vtable and vfield.
 
 This section describes some of the macros used on trees.  The list
 should be alphabetical.  Eventually all macros should be documented
-here.  There are some postscript drawings that can be used to better
-understand from of the more complex data structures, contact Mike Stump
-(@code{mrs@@cygnus.com}) for information about them.
+here.
 
 @table @code
 @item BINFO_BASETYPES
index 5695c980f62c8b385798f15a994dfc2f81968788..bccbc29af3ce704dff8498725c04c88f4ddeacdc 100644 (file)
@@ -615,9 +615,14 @@ emit_base_init (t, immediately)
       if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (base_binfo)))
        {
          start_protect ();
+
+         /* All cleanups must be on the function_obstack.  */
+         push_obstacks_nochange ();
+         resume_temporary_allocation ();
          protect_list = tree_cons (NULL_TREE,
                                    build_partial_cleanup_for (base_binfo),
                                    protect_list);
+         pop_obstacks ();
        }
 
       rbase_init_list = TREE_CHAIN (rbase_init_list);
index 0b46990f60db6b148dbcbb4c95722a15a2fef199..fffbc8a8059b8d170bf070d02bea95b061cfd3df 100644 (file)
@@ -2750,24 +2750,6 @@ identifier_typedecl_value (node)
   return NULL_TREE;
 }
 
-struct try_type
-{
-  tree *node_var;
-  char unsigned_flag;
-  char long_flag;
-  char long_long_flag;
-};
-
-struct try_type type_sequence[] = 
-{
-  { &integer_type_node, 0, 0, 0},
-  { &unsigned_type_node, 1, 0, 0},
-  { &long_integer_type_node, 0, 1, 0},
-  { &long_unsigned_type_node, 1, 1, 0},
-  { &long_long_integer_type_node, 0, 1, 1},
-  { &long_long_unsigned_type_node, 1, 1, 1}
-};
-
 int
 real_yylex ()
 {
@@ -3528,83 +3510,10 @@ real_yylex ()
            yylval.ttype = build_int_2 (low, high);
            TREE_TYPE (yylval.ttype) = long_long_unsigned_type_node;
 
-#if 0
-           /* Find the first allowable type that the value fits in.  */
-           type = 0;
-           for (i = 0; i < sizeof (type_sequence) / sizeof (type_sequence[0]);
-                i++)
-             if (!(spec_long && !type_sequence[i].long_flag)
-                 && !(spec_long_long && !type_sequence[i].long_long_flag)
-                 && !(spec_unsigned && !type_sequence[i].unsigned_flag)
-                 /* A hex or octal constant traditionally is unsigned.  */
-                 && !(base != 10 && flag_traditional
-                      && !type_sequence[i].unsigned_flag)
-                 /* A decimal constant can't be unsigned int
-                    unless explicitly specified.  */
-                 && !(base == 10 && !spec_unsigned
-                      && *type_sequence[i].node_var == unsigned_type_node))
-               if (int_fits_type_p (yylval.ttype, *type_sequence[i].node_var))
-                 {
-                   type = *type_sequence[i].node_var;
-                   break;
-                 }
-           if (flag_traditional && type == long_unsigned_type_node
-               && !spec_unsigned)
-             type = long_integer_type_node;
-             
-           if (type == 0)
-             {
-               type = long_long_integer_type_node;
-               warning ("integer constant out of range");
-             }
-
-           /* Warn about some cases where the type of a given constant
-              changes from traditional C to ANSI C.  */
-           if (warn_traditional)
-             {
-               tree other_type = 0;
-
-               /* This computation is the same as the previous one
-                  except that flag_traditional is used backwards.  */
-               for (i = 0; i < sizeof (type_sequence) / sizeof (type_sequence[0]);
-                    i++)
-                 if (!(spec_long && !type_sequence[i].long_flag)
-                     && !(spec_long_long && !type_sequence[i].long_long_flag)
-                     && !(spec_unsigned && !type_sequence[i].unsigned_flag)
-                     /* A hex or octal constant traditionally is unsigned.  */
-                     && !(base != 10 && !flag_traditional
-                          && !type_sequence[i].unsigned_flag)
-                     /* A decimal constant can't be unsigned int
-                        unless explicitly specified.  */
-                     && !(base == 10 && !spec_unsigned
-                          && *type_sequence[i].node_var == unsigned_type_node))
-                   if (int_fits_type_p (yylval.ttype, *type_sequence[i].node_var))
-                     {
-                       other_type = *type_sequence[i].node_var;
-                       break;
-                     }
-               if (!flag_traditional && type == long_unsigned_type_node
-                   && !spec_unsigned)
-                 type = long_integer_type_node;
-             
-               if (other_type != 0 && other_type != type)
-                 {
-                   if (flag_traditional)
-                     warning ("type of integer constant would be different without -traditional");
-                   else
-                     warning ("type of integer constant would be different with -traditional");
-                 }
-             }
-
-#else /* 1 */
            if (!spec_long && !spec_unsigned
                && !(flag_traditional && base != 10)
                && int_fits_type_p (yylval.ttype, integer_type_node))
              {
-#if 0
-               if (warn_traditional && base != 10)
-                 warning ("small nondecimal constant becomes signed in ANSI C++");
-#endif
                type = integer_type_node;
              }
            else if (!spec_long && (base != 10 || spec_unsigned)
@@ -3622,10 +3531,6 @@ real_yylex ()
                     && int_fits_type_p (yylval.ttype,
                                         long_unsigned_type_node))
              {
-#if 0
-               if (warn_traditional && !spec_unsigned)
-                 warning ("large integer constant becomes unsigned in ANSI C++");
-#endif
                if (flag_traditional && !spec_unsigned)
                  type = long_integer_type_node;
                else
@@ -3642,11 +3547,6 @@ real_yylex ()
            else if (int_fits_type_p (yylval.ttype,
                                      long_long_unsigned_type_node))
              {
-#if 0
-               if (warn_traditional && !spec_unsigned)
-                 warning ("large nondecimal constant is unsigned in ANSI C++");
-#endif
-
                if (flag_traditional && !spec_unsigned)
                  type = long_long_integer_type_node;
                else
@@ -3661,7 +3561,6 @@ real_yylex ()
                if (base == 10 && ! spec_unsigned && TREE_UNSIGNED (type))
                  warning ("decimal integer constant is so large that it is unsigned");
              }
-#endif
 
            TREE_TYPE (yylval.ttype) = type;
            *p = 0;
index 321492370ea143001c500464d3454a0f2008a5e7..aa607e676a781a1280bc70ffcbb76bdde0d17a49 100644 (file)
@@ -1751,9 +1751,11 @@ emit_thunk (thunk_fndecl)
     abort ();
   current_function_decl = thunk_fndecl;
 #ifdef ASM_OUTPUT_MI_THUNK
+  temporary_allocation ();
   assemble_start_function (thunk_fndecl, fnname);
   ASM_OUTPUT_MI_THUNK (asm_out_file, thunk_fndecl, delta, function);
   assemble_end_function (thunk_fndecl, fnname);
+  permanent_allocation (1);
 #else
   save_ofp = flag_omit_frame_pointer;
   flag_omit_frame_pointer = 1;
@@ -1995,8 +1997,12 @@ do_build_copy_constructor (fndecl)
            (build_reference_type (basetype), parm,
             CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE);
          p = convert_from_reference (p);
-         current_base_init_list = tree_cons (basetype,
-                                             p, current_base_init_list);
+
+         if (p == error_mark_node)
+           cp_error ("in default copy constructor");
+         else 
+           current_base_init_list = tree_cons (basetype,
+                                               p, current_base_init_list);
        }
        
       for (i = 0; i < n_bases; ++i)
@@ -2009,9 +2015,15 @@ do_build_copy_constructor (fndecl)
          p = convert_to_reference
            (build_reference_type (basetype), parm,
             CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE);
-         p = convert_from_reference (p);
-         current_base_init_list = tree_cons (basetype,
-                                             p, current_base_init_list);
+
+         if (p == error_mark_node) 
+           cp_error ("in default copy constructor");
+         else 
+           {
+             p = convert_from_reference (p);
+             current_base_init_list = tree_cons (basetype,
+                                                 p, current_base_init_list);
+           }
        }
       for (; fields; fields = TREE_CHAIN (fields))
        {
@@ -2080,16 +2092,13 @@ do_build_assign_ref (fndecl)
       for (i = 0; i < n_bases; ++i)
        {
          tree basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i));
-         if (TYPE_HAS_ASSIGN_REF (basetype))
-           {
-             tree p = convert_to_reference
-               (build_reference_type (basetype), parm,
-                CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE);
-             p = convert_from_reference (p);
-             p = build_member_call (basetype, ansi_opname [MODIFY_EXPR],
-                                    build_tree_list (NULL_TREE, p));
-             expand_expr_stmt (p);
-           }
+         tree p = convert_to_reference
+           (build_reference_type (basetype), parm,
+            CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE);
+         p = convert_from_reference (p);
+         p = build_member_call (basetype, ansi_opname [MODIFY_EXPR],
+                                build_tree_list (NULL_TREE, p));
+         expand_expr_stmt (p);
        }
       for (; fields; fields = TREE_CHAIN (fields))
        {
@@ -2098,6 +2107,24 @@ do_build_assign_ref (fndecl)
 
          if (TREE_CODE (field) != FIELD_DECL)
            continue;
+
+         if (TREE_READONLY (field))
+           {
+             if (DECL_NAME (field))
+               cp_error ("non-static const member `%#D', can't use default assignment operator", field);
+             else
+               cp_error ("non-static const member in type `%T', can't use default assignment operator", current_class_type);
+             continue;
+           }
+         else if (TREE_CODE (TREE_TYPE (field)) == REFERENCE_TYPE)
+           {
+             if (DECL_NAME (field))
+               cp_error ("non-static reference member `%#D', can't use default assignment operator", field);
+             else
+               cp_error ("non-static reference member in type `%T', can't use default assignment operator", current_class_type);
+             continue;
+           }
+
          if (DECL_NAME (field))
            {
              if (VFIELD_NAME_P (DECL_NAME (field)))
index 536e6c6be561b3dec798e7fc912df69aa18a715a..39fadec4f1163276ea3b874b211b071ae497b18b 100644 (file)
@@ -1187,6 +1187,7 @@ instantiate_class_template (type)
 
       /* XXX handle attributes */
       type = finish_struct_1 (type, NULL_TREE, 0);
+      CLASSTYPE_GOT_SEMICOLON (type) = 1;
     }
   else
     {
@@ -2968,8 +2969,6 @@ instantiate_decl (d)
   if (! push_tinst_level (d))
     return d;
 
-  if (TREE_CODE (d) == FUNCTION_DECL && nested)
-    push_cp_function_context (NULL_TREE);
   push_to_top_level ();
 
   /* Trick tsubst into giving us a new decl in case the template changed.  */
@@ -3044,8 +3043,6 @@ instantiate_decl (d)
     }
 
   pop_from_top_level ();
-  if (TREE_CODE (d) == FUNCTION_DECL && nested)
-    pop_cp_function_context (NULL_TREE);
   pop_tinst_level ();
 
   return d;
index 2a852cd12761baf9bb9347f35aed505f3a3fe099..465234c63aa5ffd23be29f37ab14ceb02ce589e4 100644 (file)
@@ -3508,7 +3508,7 @@ add_conversions (binfo)
       tree tmp = TREE_VEC_ELT (method_vec, i);
       if (! IDENTIFIER_TYPENAME_P (DECL_NAME (tmp)))
        break;
-      conversions = tree_cons (DECL_NAME (tmp), TREE_TYPE (TREE_TYPE (tmp)),
+      conversions = tree_cons (TREE_TYPE (TREE_TYPE (tmp)), tmp,
                               conversions);
     }
 }
index d0970cd2d484895dbe49eb88b81ebf2fcb104b68..b61932f387934647bc90b18ff9520cec46f527db 100644 (file)
@@ -220,7 +220,7 @@ build_cplus_new (type, init)
                TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), slot);
   TREE_SIDE_EFFECTS (rval) = 1;
   TREE_ADDRESSABLE (rval) = 1;
-  rval = build (TARGET_EXPR, type, slot, rval, NULL_TREE);
+  rval = build (TARGET_EXPR, type, slot, rval, NULL_TREE, NULL_TREE);
   TREE_SIDE_EFFECTS (rval) = 1;
   TREE_ADDRESSABLE (rval) = 1;
 
@@ -399,7 +399,7 @@ build_cplus_method_type (basetype, rettype, argtypes)
 }
 
 tree
-build_cplus_array_type (elt_type, index_type)
+build_cplus_array_type_1 (elt_type, index_type)
      tree elt_type;
      tree index_type;
 {
@@ -433,6 +433,24 @@ build_cplus_array_type (elt_type, index_type)
   saveable_obstack = ambient_saveable_obstack;
   return t;
 }
+
+tree
+build_cplus_array_type (elt_type, index_type)
+     tree elt_type;
+     tree index_type;
+{
+  tree t;
+  int constp = TYPE_READONLY (elt_type);
+  int volatilep = TYPE_VOLATILE (elt_type);
+  elt_type = TYPE_MAIN_VARIANT (elt_type);
+
+  t = build_cplus_array_type_1 (elt_type, index_type);
+
+  if (constp || volatilep)
+    t = cp_build_type_variant (t, constp, volatilep);
+
+  return t;
+}
 \f
 /* Make a variant type in the proper way for C/C++, propagating qualifiers
    down to the element type of an array.  */
@@ -451,9 +469,9 @@ cp_build_type_variant (type, constp, volatilep)
 
       push_obstacks (TYPE_OBSTACK (real_main_variant),
                     TYPE_OBSTACK (real_main_variant));
-      type = build_cplus_array_type (cp_build_type_variant (TREE_TYPE (type),
-                                                           constp, volatilep),
-                                    TYPE_DOMAIN (type));
+      type = build_cplus_array_type_1 (cp_build_type_variant
+                                      (TREE_TYPE (type), constp, volatilep),
+                                      TYPE_DOMAIN (type));
 
       /* TYPE must be on same obstack as REAL_MAIN_VARIANT.  If not,
         make a copy.  (TYPE might have come from the hash table and
@@ -467,6 +485,7 @@ cp_build_type_variant (type, constp, volatilep)
 
       TYPE_MAIN_VARIANT (type) = real_main_variant;
       pop_obstacks ();
+      return type;
     }
   return build_type_variant (type, constp, volatilep);
 }
@@ -1753,16 +1772,6 @@ break_out_target_exprs (t)
   return mapcar (t, bot_manip);
 }
 
-/* Since cleanup may have SAVE_EXPRs in it, we protect it with an
-   UNSAVE_EXPR as the backend cannot yet handle SAVE_EXPRs in cleanups
-   by itself.  */
-int
-cp_expand_decl_cleanup (decl, cleanup)
-     tree decl, cleanup;
-{
-  return expand_decl_cleanup (decl, unsave_expr (cleanup));
-}
-
 /* Obstack used for allocating nodes in template function and variable
    definitions.  */
 
index e1fac0d9341fc9e90bb817296010427199e8668c..d8b26e76633955d3bbd1c4578ce879a9944d182b 100644 (file)
@@ -129,7 +129,7 @@ complete_type (type)
 {
   if (TYPE_SIZE (type) != NULL_TREE)
     ;
-  else if (TREE_CODE (type) == ARRAY_TYPE)
+  else if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type))
     {
       tree t = complete_type (TREE_TYPE (type));
       if (TYPE_SIZE (t) != NULL_TREE)
@@ -437,10 +437,6 @@ common_type (t1, t2)
 
     case ARRAY_TYPE:
       {
-       int constp 
-         = TYPE_READONLY (t1) || TYPE_READONLY (t2);
-       int volatilep
-         = TYPE_VOLATILE (t1) || TYPE_VOLATILE (t2);
        tree elt = common_type (TREE_TYPE (t1), TREE_TYPE (t2));
        /* Save space: see if the result is identical to one of the args.  */
        if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1))
@@ -448,9 +444,8 @@ common_type (t1, t2)
        if (elt == TREE_TYPE (t2) && TYPE_DOMAIN (t2))
          return build_type_attribute_variant (t2, attributes);
        /* Merge the element types, and have a size if either arg has one.  */
-       t1 = build_cplus_array_type (TYPE_MAIN_VARIANT (elt), TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2));
-       if (constp || volatilep)
-         t1 = cp_build_type_variant (t1, constp, volatilep);
+       t1 = build_cplus_array_type
+         (elt, TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2));
        return build_type_attribute_variant (t1, attributes);
       }