56th Cygnus<->FSF merge
authorMike Stump <mrs@gcc.gnu.org>
Thu, 16 Feb 1995 15:24:37 +0000 (15:24 +0000)
committerMike Stump <mrs@gcc.gnu.org>
Thu, 16 Feb 1995 15:24:37 +0000 (15:24 +0000)
From-SVN: r8957

18 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/decl2.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/parse.y
gcc/cp/pt.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/cp/typeck2.c

index c871a580395154eb75e2fdf2f1d62c2362aded27..a092c8db65b61353e2d5c26e13eb93e4563cf9a8 100644 (file)
@@ -10,6 +10,306 @@ Wed Jan 25 15:02:09 1995  David S. Miller  (davem@nadzieja.rutgers.edu)
        * class.c (instantiate_type): Change error message text.
        * typeck2.c (store_init_value): Likewise.
 
+Thu Feb 16 03:28:49 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * class.c (finish_struct): Use TYPE_{MIN,MAX}_VALUE to determine
+       whether an enumerated type fits in a bitfield.
+
+Wed Feb 15 15:38:12 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * class.c (grow_method): Update method_vec after growing the class
+        obstack.
+
+Wed Feb 15 13:42:59 1995  Mike Stump  <mrs@cygnus.com>
+
+       * parse.y (handler_seq): Push a level for the catch parameters.
+
+Wed Feb 15 12:42:57 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * init.c (emit_base_init): Update BINFO_INHERITANCE_CHAIN on my
+       bases, in case they've been clobbered.
+
+Wed Feb 15 12:07:29 1995  Mike Stump  <mrs@cygnus.com>
+
+       * class.c (finish_base_struct): Set up BINFO_INHERITANCE_CHAIN here,
+       so that one day it will always be valid.
+       * tree.c (propagate_binfo_offsets, layout_vbasetypes): Ditto.
+
+       * cp-tree.h (copy_binfo): Removed, unused.
+       * tree.c (copy_binfo): Ditto.
+
+Wed Feb 15 00:05:30 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * init.c (build_new): Save the allocation before calling
+       expand_vec_init on it.
+
+       * decl.c (finish_enum): The TYPE_PRECISION of the enum type mush
+       match the TYPE_PRECISION of the underlying type for constant folding
+       to work.
+
+Tue Feb 14 15:31:25 1995  Mike Stump  <mrs@cygnus.com>
+
+       * except.c (push_eh_entry, expand_start_all_catch,
+       expand_leftover_cleanups, expand_end_catch_block): Keep track of
+       the context in which the exception region occurs.
+       (build_exception_table): If the region was not output, don't output
+       the entry in the eh table for it.
+
+Tue Feb 14 02:15:43 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * init.c (expand_default_init): Only use a previous constructor call
+       if it's a call to our constructor.  Does the word "Duh" mean
+       anything to you?
+
+       * decl.c (grokparms): Fine, just don't call
+       convert_for_initialization at all.  OK?  Happy now?
+
+Mon Feb 13 02:23:44 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * cp-tree.h (CLASSTYPE_FIRST_CONVERSION): Make sure that the class
+       method vector has a second element before returning it.
+
+       * decl.c (grokparms): Don't strip REFERENCE_TYPE before calling
+       convert_for_initialization.
+
+Sun Feb 12 03:57:06 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * typeck.c (build_modify_expr): Compare function name to
+       constructor_name (current_class_type) instead of current_class_name.
+
+       * decl.c (grokparms): Don't do anything with the return value of
+       convert_for_initialization.
+
+       * error.c (dump_decl): Also dump_readonly_or_volatile on the decl.
+
+       * decl.c (duplicate_decls): Tweak error message.
+
+       * typeck.c (build_const_cast): Implement checking.
+       (build_reinterpret_cast): Implement some checking.
+
+       * cp-tree.h (CONV_FORCE_TEMP): Require a new temporary when
+       converting to the same aggregate type.
+       (CONV_STATIC_CAST): Include it.
+       (CONV_C_CAST): Ditto.
+       * cvt.c (convert_force): Use CONV_C_CAST instead of CONV_OLD_CONVERT.
+       (cp_convert): Only force a new temporary if CONV_FORCE_TEMP.
+
+Fri Feb 10 16:18:52 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * typeck.c (build_c_cast): Use non_lvalue to tack something on
+        where necessary.
+
+       * decl.c (auto_function): Now a function.
+       * except.c (init_exception_processing): terminate, unexpected,
+       set_terminate, and set_unexpected have C++ linkage.
+
+       * typeck.c (build_unary_op, TRUTH_NOT_EXPR): Use convert instead of
+       truthvalue_conversion for converting to bool, as it handles
+       user-defined conversions properly.
+       (condition_conversion): Ditto.
+
+       * except.c (expand_throw): Don't call convert_to_reference.
+       Pass the correct parameters to build_new.
+
+       * method.c (do_build_assign_ref): Don't use access control when
+       converting to a base reference here.
+       (do_build_copy_constructor): Or here.
+
+       * init.c (build_new): Unset TREE_READONLY on the dereferenced
+       pointer before assigning to it.
+
+       * decl.c (maybe_build_cleanup): Don't bother stripping const here.
+
+       * decl2.c (delete_sanity): You can now delete pointer to const.
+
+Fri Feb 10 13:28:38 1995  Jason Merrill  <jason@python.cygnus.com>
+
+       * decl.c (finish_function): Don't rely on actual parameters being
+       evaluated left-to-right.
+       * except.c (expand_end_catch_block): Ditto.
+
+Fri Feb 10 00:52:04 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * tree.c (real_lvalue_p): Like lvalue_p, but class temps aren't
+       considered lvalues.
+       * cvt.c (convert_to_reference): Use real_lvalue_p instead of
+        lvalue_p.
+
+       * cvt.c (build_type_conversion_1): Don't call convert on aggregate
+       types.
+       (convert_to_reference): Fix erroneous text substitution.
+
+       * typeck2.c (initializer_constant_valid_p): Update from C frontend.
+       Add new argument to all callers.
+
+       * typeck.c (convert_arguments): Check for error_mark_node before
+       trying to do anything with the actual parameter.
+
+       * typeck.c (condition_conversion): Build up a CLEANUP_POINT_EXPR and
+       fold it.
+       (bool_truthvalue_conversion): Remove.  Fix all callers to call
+       truthvalue_conversion instead.
+       (various): Fold CLEANUP_POINT_EXPRs.
+
+       * parse.y (conditions): Call condition_conversion rather than
+       building up a CLEANUP_POINT_EXPR.
+
+       * pt.c (end_template_decl): Don't warn_if_unknown_interface here
+       under -falt-external-templates.
+
+Thu Feb  9 05:24:10 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * init.c (build_new): Complain about new of const type without
+       initializer.  Other cleanup.
+
+       * call.c (compute_conversion_costs): Don't call
+       build_type_conversion with a reference type; convert to the target
+       type and check its lvaluetude.
+       * cvt.c (convert_to_reference): Ditto.
+
+       * cvt.c (build_type_conversion_1): There will never be any need to
+       dereference references here now.
+
+Thu Feb  9 00:37:47 1995  Mike Stump  <mrs@cygnus.com>
+
+       * except.c (expand_builtin_throw): Make sure we only `use' the
+       value of return_val_rtx.
+
+Wed Feb  8 15:45:55 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * parse.y (structsp): Don't complain about declaring a type being
+       defined to be a friend.
+
+       * decl2.c (warn_if_unknown_interface): Note the template in question
+       and the point of instantiation, for -falt-external-templates.
+       * lex.c (reinit_parse_for_method): Pass the decl to
+       warn_if_unknown_interface.
+       * pt.c (instantiate_template): Ditto.
+       (end_template_decl): Ditto.
+
+       * decl.c (set_nested_typename): Set IDENTIFIER_TYPE_VALUE on the
+       nested name again, to make local classes work a bit better.
+
+       * typeck.c (build_function_call_real): Dereference reference after
+       checking for incomplete type.
+
+       * init.c (build_new): Accept new of const and volatile types.
+
+Wed Feb  8 14:04:16 1995  Jason Merrill  <jason@deneb.cygnus.com>
+
+       * decl.c (grokdeclarator): Fix error message.
+
+Wed Feb  8 03:16:15 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * typeck.c (convert_for_initialization): Do bash arrays when
+       converting to a reference to non-array.
+
+Tue Feb  7 15:50:33 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * cvt.c (cp_convert): Don't call convert_to_reference, or
+       automatically dereference references.  Do pass reference conversions
+       to cp_convert_to_pointer.
+       (cp_convert_to_pointer): Support references.
+
+       * call.c (build_method_call): Don't build up a reference to the
+       parameter here; let build_overload_call handle that.
+
+       * typeck.c (build_c_cast): Call convert_to_reference directly if
+       converting to a reference type.
+       * method.c (do_build_copy_constructor): Ditto.
+       * method.c (do_build_copy_constructor): Ditto.
+       (do_build_assign_ref): Ditto.
+
+       * call.c (build_method_call): Dereference a returned reference.
+       * typeck.c (build_function_call_real): Ditto.
+
+       * decl.c (xref_basetypes): Check for unions with basetypes here.
+       (xref_tag): Instead of here.
+
+       * pt.c (process_template_parm): Template type parm decls are
+       artificial.
+
+Mon Feb  6 04:32:09 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * parse.y (typed_declspecs): Add missing semicolon.
+       (do_xref_defn): Resurrect.
+       (named_class_head_sans_basetype): Move template specialization
+       definition cases to named_class_head_sans_basetype_defn.
+
+       * decl2.c (grokfield): Call pushdecl_class_level after setting the
+       TYPE_NAME, not before.
+
+Sun Feb  5 02:50:45 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * call.c (convert_harshness): Don't call sorry here.  Don't allow
+       conversions between function pointer types if pedantic.
+
+       * pt.c (overload_template_name): Pass globalize=1 to xref_tag.
+
+       * lex.c (cons_up_default_function): Use the full name for the return
+       type of op=.
+
+       * decl.c (set_nested_typename): Don't worry about anonymous types,
+       as they already have a unique name.
+       (pushdecl): Remove redundant set_nested_typename
+       (xref_tag): Split out base handling into xref_basetypes.
+
+       * cp-tree.h (TYPE_INCOMPLETE): New macro; TEMPLATE_TYPE_PARMs are
+       not considered incomplete even though their definition is unknown.
+
+       * decl.c (xref_defn_tag): Lose.
+       (xref_tag): xref_next_defn = ! globalize.
+       (pushdecl): Don't set DECL_NESTED_TYPENAME on artificial decls.  The
+       ones that should have it set will have it set by pushtag.
+       (pushdecl_class_level): Ditto.
+       (pushtag): Tidy up a bit.
+       (set_nested_typename): Push a decl for the nested typename from
+       here, rather than from xref_defn_tag.
+
+       * parse.y (do_xref): Lose.
+       (named_class_head): If we see 'class foo:' we know it's a
+       definition, so don't worry about base lists for non-definitions.
+
+       * pt.c (push_template_decls): Template parm decls are artificial.
+
+       * decl.c (duplicate_decls): Restore check for qualifier
+       disagreement for non-functions.
+       (decls_match): Remove check for qualifier disagreement.
+
+Fri Feb  3 14:58:58 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * decl.c (grok_reference_init): Convert initializer from
+        reference.
+       * typeck.c (convert_for_initialization): Ditto.
+
+       * decl.c (duplicate_decls): Propagate DECL_NESTED_TYPENAME.
+
+       * cvt.c (cp_convert): Don't convert to the same class type by just
+       tacking on a NOP_EXPR.
+       (convert_to_reference): Use comp_target_types instead of comptypes
+       so that we don't allow conversions two levels down.
+
+Thu Feb  2 15:07:58 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * class.c (build_vbase_path): Bash types to make the backend happy.
+       * cvt.c (build_up_reference): Bash the types bashed by
+       build_vbase_path to be reference types instead of pointer types.
+       (convert_to_reference): Ditto.
+
+       * typeck.c (build_c_cast): Don't strip NOPs if we're converting to a
+       reference type.
+
+       * parse.y (structsp): Put back error for 'struct B: public A;'.
+
+Wed Feb  1 23:02:06 1995  Mike Stump  <mrs@cygnus.com>
+
+       * except.c: Add support for mips systems that don't define __mips
+       but do define mips, like Ultrix.
+
+Wed Feb  1 22:39:07 1995  Mike Stump  <mrs@cygnus.com>
+
+       * except.c: Add support for exception handling on the Alpha.
+
 Wed Feb  1 10:12:14 1995  Mike Stump  <mrs@cygnus.com>
 
        * decl2.c (finish_file): Fix bug in Jan 31st change.
index 631f1af222bb4c08ed257d7185e2128490ceb46b..be7cf3c64fada6820bc12727f904c6729804a2e8 100644 (file)
@@ -176,6 +176,9 @@ convert_harshness (type, parmtype, parm)
       if (type == parmtype)
        return ZERO_RETURN (h);
 
+      if (pedantic)
+       return EVIL_RETURN (h);
+
       /* Compare return types.  */
       p1 = TREE_TYPE (type);
       p2 = TREE_TYPE (parmtype);
@@ -207,14 +210,16 @@ convert_harshness (type, parmtype, parm)
 
          if (! BINFO_OFFSET_ZEROP (binfo))
            {
+#if 0
              static int explained = 0;
              if (h2.distance < 0)
-               message_2_types (sorry, "cannot cast `%d' to `%d' at function call site", p2, p1);
+               message_2_types (sorry, "cannot cast `%s' to `%s' at function call site", p2, p1);
              else
-               message_2_types (sorry, "cannot cast `%d' to `%d' at function call site", p1, p2);
+               message_2_types (sorry, "cannot cast `%s' to `%s' at function call site", p1, p2);
 
              if (! explained++)
                sorry ("(because pointer values change during conversion)");
+#endif
              return EVIL_RETURN (h);
            }
        }
@@ -877,12 +882,15 @@ compute_conversion_costs (function, tta_in, cp, arglen)
 
                      inhibit_warnings = 1;
                      conv = build_type_conversion
-                       (CALL_EXPR, TREE_VALUE (ttf), TREE_VALUE (tta), 0);
+                       (CALL_EXPR, formal_type, TREE_VALUE (tta), 0);
                      inhibit_warnings = old_inhibit_warnings;
 
                      if (conv)
                        {
-                         if (conv == error_mark_node)
+                         if (conv == error_mark_node
+                             || (TREE_CODE (TREE_VALUE (ttf)) == REFERENCE_TYPE
+                                 && ! TYPE_READONLY (TREE_VALUE (TREE_VALUE (ttf)))
+                                 && ! lvalue_p (conv)))
                            win += 2;
                          else
                            {
@@ -891,22 +899,6 @@ compute_conversion_costs (function, tta_in, cp, arglen)
                                extra_conversions = 1;
                            }
                        }
-                     else if (TREE_CODE (TREE_VALUE (ttf)) == REFERENCE_TYPE)
-                       {
-                         conv = build_type_conversion (CALL_EXPR, formal_type,
-                                                       TREE_VALUE (tta), 0);
-                         if (conv)
-                           {
-                             if (conv == error_mark_node)
-                               win += 2;
-                             else
-                               {
-                                 win++;
-                                 if (TREE_CODE (conv) != CALL_EXPR)
-                                   extra_conversions = 1;
-                               }
-                           }
-                       }
                    }
                }
              dont_convert_types = 0;
@@ -2035,25 +2027,14 @@ build_method_call (instance, name, parms, basetype_path, flags)
              tree parm = instance_ptr;
 
              if (TREE_CODE (TREE_TYPE (parm)) == REFERENCE_TYPE)
-               {
-                 /* TREE_VALUE (parms) may have been modified by now;
-                     restore it to its original value. */
-                 TREE_VALUE (parms) = parm;
-                 friend_parms = parms;
-               }
+               parm = convert_from_reference (parm);
              else if (TREE_CODE (TREE_TYPE (parm)) == POINTER_TYPE)
-               {
-                 tree new_type;
-                 parm = build_indirect_ref (parm, "friendifying parms (compiler error)");
-                 new_type = cp_build_type_variant (TREE_TYPE (parm), constp,
-                                                  volatilep);
-                 new_type = build_reference_type (new_type);
-                 parm = convert (new_type, parm);
-                 friend_parms = tree_cons (NULL_TREE, parm, TREE_CHAIN (parms));
-               }
+               parm = build_indirect_ref (parm, "friendifying parms (compiler error)");
              else
                my_friendly_abort (167);
 
+             friend_parms = tree_cons (NULL_TREE, parm, TREE_CHAIN (parms));
+
              cp->h_len = len;
              cp->harshness = (struct harshness_code *)
                alloca ((len + 1) * sizeof (struct harshness_code));
@@ -2602,6 +2583,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
     TREE_TYPE (result) = value_type;
     TREE_SIDE_EFFECTS (result) = 1;
     TREE_HAS_CONSTRUCTOR (result) = is_constructor;
+    result = convert_from_reference (result);
     return result;
   }
 }
index 79e76bb3a767d56f8af658909fa4537ece59ce73..b5edebd54591de9abcfe6246a04f0aead1739231 100644 (file)
@@ -1453,6 +1453,7 @@ finish_base_struct (t, b, t_binfo)
              chain = TREE_VEC_ELT (base_binfos, j);
              TREE_VIA_PUBLIC (chain) = TREE_VIA_PUBLIC (base_base_binfo);
              TREE_VIA_PROTECTED (chain) = TREE_VIA_PROTECTED (base_base_binfo);
+             BINFO_INHERITANCE_CHAIN (chain) = base_binfo;
            }
 
          /* Completely unshare potentially shared data, and
@@ -1711,8 +1712,9 @@ finish_struct_bits (t, max_has_virtual)
 /* Add FN to the method_vec growing on the class_obstack.  Used by
    finish_struct_methods.  */
 static void
-grow_method (fn)
+grow_method (fn, method_vec_ptr)
      tree fn;
+     tree *method_vec_ptr;
 {
   tree method_vec = (tree)obstack_base (&class_obstack);
   tree *testp = &TREE_VEC_ELT (method_vec, 0);
@@ -1756,7 +1758,10 @@ grow_method (fn)
        }
     }
   else
-    obstack_ptr_grow (&class_obstack, fn);
+    {
+      obstack_ptr_grow (&class_obstack, fn);
+      *method_vec_ptr = (tree)obstack_base (&class_obstack);
+    }
 }
 
 /* Warn about duplicate methods in fn_fields.  Also compact method
@@ -1855,7 +1860,7 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
          else if (typecode_p (return_type, REAL_TYPE))
            TYPE_HAS_REAL_CONVERSION (t) = 1;
 
-         grow_method (fn_fields);
+         grow_method (fn_fields, &method_vec);
        }
       else
        {
@@ -1891,12 +1896,10 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
            }
        }
 
-      grow_method (fn_fields);
+      grow_method (fn_fields, &method_vec);
       fn_fields = nextp;
     }
 
-  /* Update in case method_vec has moved.  */
-  method_vec = (tree)obstack_base (&class_obstack);
   TREE_VEC_LENGTH (method_vec) = (tree *)obstack_next_free (&class_obstack)
     - (&TREE_VEC_ELT (method_vec, 0));
   obstack_finish (&class_obstack);
@@ -2289,13 +2292,9 @@ modify_one_vtable (binfo, t, fndecl, pfn)
          this_offset = size_binop (MINUS_EXPR, offset, base_offset);
 
          /* Make sure we can modify the derived association with immunity.  */
-         if (TREE_USED (binfo)) {
+         if (TREE_USED (binfo))
            my_friendly_assert (0, 999);
-#if 0
-           my_friendly_assert (*binfo2_ptr == binfo, 999);
-           *binfo2_ptr = copy_binfo (binfo);
-#endif
-         }
+
          if (binfo == TYPE_BINFO (t))
            {
              /* In this case, it is *type*'s vtable we are modifying.
@@ -3160,8 +3159,11 @@ finish_struct (t, list_of_fieldlists, warn_anon)
                    {
                      cp_warning_at ("width of `%D' exceeds its type", x);
                    }
-                 else if (width < TYPE_PRECISION (TREE_TYPE (x))
-                          && TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE)
+                 else if (TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE
+              && ((min_precision (TYPE_MIN_VALUE (TREE_TYPE (x)),
+                                  TREE_UNSIGNED (TREE_TYPE (x))) > width)
+                  || (min_precision (TYPE_MAX_VALUE (TREE_TYPE (x)),
+                                     TREE_UNSIGNED (TREE_TYPE (x))) > width)))
                    {
                      cp_warning_at ("`%D' is too small to hold all values of `%#T'",
                                     x, TREE_TYPE (x));
index 4f92ca3cf4a784fbae40154c6076d47060d12199..4cb8af9e90ef8d0098004782549c513772bd3787 100644 (file)
@@ -666,7 +666,9 @@ struct lang_type
    searched with TREE_CHAIN), or the first non-constructor function if
    there are no type conversion operators.  */
 #define CLASSTYPE_FIRST_CONVERSION(NODE) \
-  TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (NODE), 1)
+  TREE_VEC_LENGTH (CLASSTYPE_METHOD_VEC (NODE)) > 1 \
+    ? TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (NODE), 1) \
+    : NULL_TREE;
 
 /* Pointer from any member function to the head of the list of
    member functions of the type that member function belongs to.  */
@@ -842,6 +844,9 @@ struct lang_type
 
 /* Nonzero if a _DECL node requires us to output debug info for this class.  */
 #define CLASSTYPE_DEBUG_REQUESTED(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.debug_requested)
+
+#define TYPE_INCOMPLETE(NODE) \
+  (TYPE_SIZE (NODE) == NULL_TREE && TREE_CODE (NODE) != TEMPLATE_TYPE_PARM)
 \f
 /* Additional macros for inheritance information.  */
 
@@ -1816,7 +1821,9 @@ extern tree current_class_type;   /* _TYPE: the type of the current class */
    CONV_CONST      :  Perform the explicit conversions for const_cast.
    CONV_REINTERPRET:  Perform the explicit conversions for reinterpret_cast.
    CONV_PRIVATE    :  Perform upcasts to private bases.
-   CONV_NONCONVERTING : Allow non-converting constructors to be used.  */
+   CONV_NONCONVERTING : Allow non-converting constructors to be used.
+   CONV_FORCE_TEMP :  Require a new temporary when converting to the same
+                     aggregate type.  */
 
 #define CONV_IMPLICIT    1
 #define CONV_STATIC      2
@@ -1824,11 +1831,12 @@ extern tree current_class_type; /* _TYPE: the type of the current class */
 #define CONV_REINTERPRET 8
 #define CONV_PRIVATE    16
 #define CONV_NONCONVERTING 32
-#define CONV_STATIC_CAST (CONV_IMPLICIT | CONV_STATIC)
+#define CONV_FORCE_TEMP  64
+#define CONV_STATIC_CAST (CONV_IMPLICIT | CONV_STATIC | CONV_FORCE_TEMP)
 #define CONV_OLD_CONVERT (CONV_IMPLICIT | CONV_STATIC | CONV_CONST \
                          | CONV_REINTERPRET)
 #define CONV_C_CAST      (CONV_IMPLICIT | CONV_STATIC | CONV_CONST \
-                         | CONV_REINTERPRET | CONV_PRIVATE)
+                         | CONV_REINTERPRET | CONV_PRIVATE | CONV_FORCE_TEMP)
 
 /* Anatomy of a DECL_FRIENDLIST (which is a TREE_LIST):
    purpose = friend name (IDENTIFIER_NODE);
@@ -1946,6 +1954,7 @@ extern tree pushdecl_top_level                    PROTO((tree));
 extern void push_class_level_binding           PROTO((tree, tree));
 extern void push_overloaded_decl_top_level     PROTO((tree, int));
 extern tree pushdecl_class_level               PROTO((tree));
+extern tree pushdecl_nonclass_level            PROTO((tree));
 extern int overloaded_globals_p                        PROTO((tree));
 extern tree push_overloaded_decl               PROTO((tree, int));
 extern tree implicitly_declare                 PROTO((tree));
@@ -1971,8 +1980,8 @@ 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 void xref_basetypes                     PROTO((tree, tree, tree, tree));
 extern tree start_enum                         PROTO((tree));
 extern tree finish_enum                                PROTO((tree, tree));
 extern tree build_enumerator                   PROTO((tree, tree));
@@ -2019,7 +2028,7 @@ extern tree coerce_delete_type                    PROTO((tree));
 extern void walk_vtables                       PROTO((void (*)(), void (*)()));
 extern void walk_sigtables                     PROTO((void (*)(), void (*)()));
 extern void finish_file                                PROTO((void));
-extern void warn_if_unknown_interface          PROTO((void));
+extern void warn_if_unknown_interface          PROTO((tree));
 extern tree grok_x_components                  PROTO((tree, tree));
 extern tree reparse_absdcl_as_expr             PROTO((tree, tree));
 extern tree reparse_absdcl_as_casts            PROTO((tree, tree));
@@ -2286,7 +2295,6 @@ extern tree hash_chainon                  PROTO((tree, tree));
 extern tree get_decl_list                      PROTO((tree));
 extern tree list_hash_lookup_or_cons           PROTO((tree));
 extern tree make_binfo                         PROTO((tree, tree, tree, tree, tree));
-extern tree copy_binfo                         PROTO((tree));
 extern tree binfo_value                                PROTO((tree, tree));
 extern tree reverse_path                       PROTO((tree));
 extern tree virtual_member                     PROTO((tree, tree));
@@ -2311,7 +2319,7 @@ extern tree array_type_nelts_total                PROTO((tree));
 extern tree array_type_nelts_top               PROTO((tree));
 
 /* in typeck.c */
-extern tree bool_truthvalue_conversion         PROTO((tree));
+extern tree condition_conversion               PROTO((tree));
 extern tree target_type                                PROTO((tree));
 extern tree require_complete_type              PROTO((tree));
 extern int type_unknown_p                      PROTO((tree));
index 27d38fcdb12c7c3e01b3118690ef87f93401746a..ce01c662ccfa6071ded5c8105b7c2ef6e94df788 100644 (file)
@@ -113,7 +113,7 @@ cp_convert_to_pointer (type, expr)
   register tree intype = TREE_TYPE (expr);
   register enum tree_code form = TREE_CODE (intype);
   
-  if (form == POINTER_TYPE)
+  if (form == POINTER_TYPE || form == REFERENCE_TYPE)
     {
       intype = TYPE_MAIN_VARIANT (intype);
 
@@ -632,31 +632,49 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
 {
   register tree type = TYPE_MAIN_VARIANT (TREE_TYPE (reftype));
   register tree intype = TREE_TYPE (expr);
-  register enum tree_code form = TREE_CODE (intype);
   tree rval = NULL_TREE;
+  tree rval_as_conversion = NULL_TREE;
+  int i;
+
+  if (TREE_CODE (intype) == REFERENCE_TYPE)
+    my_friendly_abort (364);
 
-  if (form == REFERENCE_TYPE)
-    intype = TREE_TYPE (intype);
   intype = TYPE_MAIN_VARIANT (intype);
 
-  if (((convtype & CONV_STATIC) && comptypes (type, intype, -1))
-      || ((convtype & CONV_IMPLICIT) && comptypes (type, intype, 0)))
+  i = comp_target_types (type, intype, 0);
+
+  if (i <= 0 && (convtype & CONV_IMPLICIT) && IS_AGGR_TYPE (intype)
+      && ! (flags & LOOKUP_NO_CONVERSION))
+    {
+      /* Look for a user-defined conversion to lvalue that we can use.  */
+
+      rval_as_conversion = build_type_conversion (CONVERT_EXPR, type, expr, 1);
+
+      if (rval_as_conversion && rval_as_conversion != error_mark_node
+         && real_lvalue_p (rval_as_conversion))
+       {
+         expr = rval_as_conversion;
+         rval_as_conversion = NULL_TREE;
+         intype = type;
+         i = 1;
+       }
+    }
+
+  if (((convtype & CONV_STATIC) && i == -1)
+      || ((convtype & CONV_IMPLICIT) && i == 1))
     {
       if (flags & LOOKUP_COMPLAIN)
        {
          tree ttl = TREE_TYPE (reftype);
          tree ttr;
          
-         if (form == REFERENCE_TYPE)
-           ttr = TREE_TYPE (TREE_TYPE (expr));
-         else
-           {
-             int r = TREE_READONLY (expr);
-             int v = TREE_THIS_VOLATILE (expr);
-             ttr = cp_build_type_variant (TREE_TYPE (expr), r, v);
-           }
+         {
+           int r = TREE_READONLY (expr);
+           int v = TREE_THIS_VOLATILE (expr);
+           ttr = cp_build_type_variant (TREE_TYPE (expr), r, v);
+         }
 
-         if (! lvalue_p (expr) &&
+         if (! real_lvalue_p (expr) &&
              (decl == NULL_TREE || ! TYPE_READONLY (ttl)))
            {
              if (decl)
@@ -678,34 +696,9 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
            }
        }
 
-      if (form == REFERENCE_TYPE)
-       {
-         tree type = TREE_TYPE (expr);
-         TREE_TYPE (expr) = build_pointer_type (TREE_TYPE (type));
-         rval = cp_convert (build_pointer_type (TREE_TYPE (reftype)), expr,
-                            convtype, flags);
-         TREE_TYPE (expr) = type;
-         TREE_TYPE (rval) = reftype;
-         if (TREE_CODE (rval) == PLUS_EXPR || TREE_CODE (rval) == MINUS_EXPR)
-           TREE_TYPE (TREE_OPERAND (rval, 0))
-             = TREE_TYPE (TREE_OPERAND (rval, 1)) = reftype;
-         return rval;
-       }
-
       return build_up_reference (reftype, expr, flags,
                                 ! (convtype & CONV_CONST));
     }
-
-  if ((convtype & CONV_IMPLICIT)
-      && IS_AGGR_TYPE (intype)
-      && ! (flags & LOOKUP_NO_CONVERSION)
-      && (rval = build_type_conversion (CONVERT_EXPR, reftype, expr, 1)))
-    {
-      if (rval == error_mark_node)
-       cp_error ("conversion from `%T' to `%T' is ambiguous",
-                 intype, reftype);
-      return rval;
-    }
   else if ((convtype & CONV_REINTERPRET) && lvalue_p (expr))
     {
       /* When casting an lvalue to a reference type, just convert into
@@ -715,7 +708,7 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
 
       /* B* bp; A& ar = (A&)bp; is valid, but it's probably not what they
          meant.  */
-      if (form == POINTER_TYPE
+      if (TREE_CODE (intype) == POINTER_TYPE
          && (comptypes (TREE_TYPE (intype), type, -1)))
        cp_warning ("casting `%T' to `%T' does not dereference pointer",
                    intype, reftype);
@@ -728,16 +721,18 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
     }
   else if (decl)
     {
-      tree rval_as_conversion = NULL_TREE;
       tree rval_as_ctor = NULL_TREE;
       
-      if (IS_AGGR_TYPE (intype)
-         && (rval = build_type_conversion (CONVERT_EXPR, type, expr, 1)))
+      if (rval_as_conversion)
        {
-         if (rval == error_mark_node)
-           return rval;
-
-         rval_as_conversion = build_up_reference (reftype, rval, flags, 1);
+         if (rval_as_conversion == error_mark_node)
+           {
+             cp_error ("conversion from `%T' to `%T' is ambiguous",
+                       intype, reftype);
+             return error_mark_node;
+           }
+         rval_as_conversion = build_up_reference (reftype, rval_as_conversion,
+                                                  flags, 1);
        }
       
       /* Definitely need to go through a constructor here.  */
@@ -815,7 +810,7 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
       return rval;
     }
 
-  my_friendly_assert (form != OFFSET_TYPE, 189);
+  my_friendly_assert (TREE_CODE (intype) != OFFSET_TYPE, 189);
 
   if (flags & LOOKUP_SPECULATIVELY)
     return NULL_TREE;
@@ -1206,8 +1201,10 @@ cp_convert (type, expr, convtype, flags)
       || TREE_CODE (TREE_TYPE (e)) == ERROR_MARK)
     return error_mark_node;
 
-  /* Trivial conversion: cv-qualifiers do not matter on rvalues.  */
-  if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
+  if (IS_AGGR_TYPE (type) && (convtype & CONV_FORCE_TEMP))
+    /* We need a new temporary; don't take this shortcut.  */;
+  else if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
+    /* Trivial conversion: cv-qualifiers do not matter on rvalues.  */
     return fold (build1 (NOP_EXPR, type, e));
   
   if (code == VOID_TYPE && (convtype & CONV_STATIC))
@@ -1227,10 +1224,12 @@ cp_convert (type, expr, convtype, flags)
       code = TREE_CODE (type);
     }
 
+#if 0
   if (code == REFERENCE_TYPE)
     return fold (convert_to_reference (type, e, convtype, flags, NULL_TREE));
   else if (TREE_CODE (TREE_TYPE (e)) == REFERENCE_TYPE)
     e = convert_from_reference (e);
+#endif
 
   if (TREE_CODE (e) == OFFSET_REF)
     e = resolve_offset_ref (e);
@@ -1266,7 +1265,7 @@ cp_convert (type, expr, convtype, flags)
        return truthvalue_conversion (e);
       return fold (convert_to_integer (type, e));
     }
-  if (code == POINTER_TYPE)
+  if (code == POINTER_TYPE || code == REFERENCE_TYPE)
     return fold (cp_convert_to_pointer (type, e));
   if (code == REAL_TYPE)
     {
@@ -1458,7 +1457,7 @@ convert_force (type, expr, convtype)
       return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), e, 1);
     }
 
-  return cp_convert (type, e, CONV_OLD_CONVERT|convtype, 0);
+  return cp_convert (type, e, CONV_C_CAST|convtype, 0);
 }
 
 /* Subroutine of build_type_conversion.  */
@@ -1484,9 +1483,9 @@ build_type_conversion_1 (xtype, basetype, expr, typename, for_sure)
        return NULL_TREE;
       return error_mark_node;
     }
-  if (TREE_CODE (TREE_TYPE (rval)) == REFERENCE_TYPE
-      && TREE_CODE (xtype) != REFERENCE_TYPE)
-    rval = default_conversion (rval);
+
+  if (IS_AGGR_TYPE (TREE_TYPE (rval)))
+    return rval;
 
   if (warn_cast_qual
       && TREE_TYPE (xtype)
index 1cda932726567492aa23be3893ccfdde59da7a31..01547b0a766bdd85690e2a6136dd3975ef4d2f59 100644 (file)
@@ -121,17 +121,6 @@ static struct stack_level *decl_stack;
 #define WCHAR_TYPE "int"
 #endif
 
-#define builtin_function(NAME, TYPE, CODE, LIBNAME) \
-  define_function (NAME, TYPE, CODE, (void (*)())pushdecl, LIBNAME)
-#define auto_function(NAME, TYPE, CODE) \
-  do {                                 \
-    tree __name = NAME;                \
-    tree __type = TYPE;                        \
-    define_function (IDENTIFIER_POINTER (__name), __type, CODE,        \
-                    (void (*)())push_overloaded_decl_1,        \
-                    IDENTIFIER_POINTER (build_decl_overload (__name, TYPE_ARG_TYPES (__type), 0)));\
-  } while (0)
-
 static tree grokparms                          PROTO((tree, int));
 static tree lookup_nested_type                 PROTO((tree, tree));
 static char *redeclaration_error_message       PROTO((tree, tree));
@@ -1647,6 +1636,14 @@ set_nested_typename (decl, classname, name, type)
 {
   char *buf;
   my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 136);
+
+  /* No need to do this for anonymous names, since they're unique.  */
+  if (ANON_AGGRNAME_P (name))
+    {
+      DECL_NESTED_TYPENAME (decl) = name;
+      return;
+    }
+
   if (classname == NULL_TREE)
     classname = get_identifier ("");
 
@@ -1659,11 +1656,27 @@ set_nested_typename (decl, classname, name, type)
   DECL_NESTED_TYPENAME (decl) = get_identifier (buf);
   TREE_MANGLED (DECL_NESTED_TYPENAME (decl)) = 1;
 
-  /* This is a special usage of IDENTIFIER_TYPE_VALUE which have no
-     correspondence in any binding_level.  This is ok since the
-     DECL_NESTED_TYPENAME is just a convenience identifier whose
-     IDENTIFIER_TYPE_VALUE will remain constant from now on.  */
-  SET_IDENTIFIER_TYPE_VALUE (DECL_NESTED_TYPENAME (decl), type);
+  /* Create an extra decl so that the nested name will have a type value
+     where appropriate.  */
+  {
+    tree nested, type_decl;
+    nested = DECL_NESTED_TYPENAME (decl);
+    type_decl = build_decl (TYPE_DECL, nested, type);
+    DECL_NESTED_TYPENAME (type_decl) = nested;
+    SET_DECL_ARTIFICIAL (type_decl);
+#ifdef DWARF_DEBUGGING_INFO
+    /* Mark the TYPE_DECL node created just above as a
+       gratuitous one so that dwarfout.c will know not to
+       generate a TAG_typedef DIE for it.  */
+    if (write_symbols == DWARF_DEBUG)
+      DECL_IGNORED_P (type_decl) = 1;
+#endif /* DWARF_DEBUGGING_INFO */
+
+    /* Remove this when local classes are fixed.  */
+    SET_IDENTIFIER_TYPE_VALUE (nested, type);
+
+    pushdecl_nonclass_level (type_decl);
+  }
 }
 
 /* Pop off extraneous binding levels left over due to syntax errors.  */
@@ -1820,7 +1833,7 @@ pushtag (name, type, globalize)
                }
 #endif /* DWARF_DEBUGGING_INFO */
 
-             TYPE_NAME (type) = d;
+             TYPE_MAIN_DECL (type) = d;
 
              /* Make sure we're in this type's scope when we push the
                 decl for a template, otherwise class_binding_level will
@@ -1832,37 +1845,31 @@ pushtag (name, type, globalize)
              if (TREE_CODE (type) == UNINSTANTIATED_P_TYPE)
                popclass (0);
            }
-         if (write_symbols != DWARF_DEBUG)
+         if (newdecl)
            {
-             if (ANON_AGGRNAME_P (name))
-               DECL_IGNORED_P (d) = 1;
-           }
+             if (write_symbols != DWARF_DEBUG)
+               {
+                 if (ANON_AGGRNAME_P (name))
+                   DECL_IGNORED_P (d) = 1;
+               }
+
+             if (context == NULL_TREE)
+               /* Non-nested class.  */
+               set_nested_typename (d, NULL_TREE, name, type);
+             else if (context && TREE_CODE (context) == FUNCTION_DECL)
+               /* Function-nested class.  */
+               set_nested_typename (d, DECL_ASSEMBLER_NAME (c_decl),
+                                    name, type);
+             else /* if (context && IS_AGGR_TYPE (context)) */
+               /* Class-nested class.  */
+               set_nested_typename (d, DECL_NESTED_TYPENAME (c_decl),
+                                    name, type);
 
-         if (context == NULL_TREE)
-           /* Non-nested class.  */
-           set_nested_typename (d, NULL_TREE, name, type);
-         else if (context && TREE_CODE (context) == FUNCTION_DECL)
-           {
-             /* Function-nested class.  */
-             set_nested_typename (d, DECL_ASSEMBLER_NAME (c_decl),
-                                  name, type);
-             /* This builds the links for classes nested in fn scope.  */
-             DECL_CONTEXT (d) = context;
-           }
-/*        else if (TYPE_SIZE (current_class_type) == NULL_TREE)
-*/
-         else if (context && IS_AGGR_TYPE (context))
-           {
-             /* Class-nested class.  */
-             set_nested_typename (d, DECL_NESTED_TYPENAME (c_decl),
-                                  name, type);
-             /* This builds the links for classes nested in type scope.  */
              DECL_CONTEXT (d) = context;
+             TYPE_CONTEXT (type) = DECL_CONTEXT (d);
+             DECL_ASSEMBLER_NAME (d)
+               = get_identifier (build_overload_name (type, 1, 1));
            }
-         TYPE_CONTEXT (type) = DECL_CONTEXT (d);
-         if (newdecl)
-           DECL_ASSEMBLER_NAME (d)
-             = get_identifier (build_overload_name (type, 1, 1));
         }
       if (b->parm_flag == 2)
        {
@@ -2042,9 +2049,7 @@ decls_match (newdecl, olddecl)
       else if (TREE_TYPE (newdecl) == NULL_TREE)
        types_match = 0;
       else
-       types_match = (comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl), 1)
-                      && TREE_READONLY (newdecl) == TREE_READONLY (olddecl)
-                      && TREE_THIS_VOLATILE (newdecl) == TREE_THIS_VOLATILE (olddecl));
+       types_match = comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl), 1);
     }
 
   return types_match;
@@ -2312,6 +2317,13 @@ duplicate_decls (newdecl, olddecl)
                  }
              }
        }
+      /* These bits are logically part of the type for non-functions.  */
+      else if (TREE_READONLY (newdecl) != TREE_READONLY (olddecl)
+              || TREE_THIS_VOLATILE (newdecl) != TREE_THIS_VOLATILE (olddecl))
+       {
+         cp_pedwarn ("type qualifiers for `%#D'", newdecl);
+         cp_pedwarn_at ("conflict with previous decl `%#D'", olddecl);
+       }
     }
 
   /* If new decl is `static' and an `extern' was seen previously,
@@ -2347,6 +2359,8 @@ duplicate_decls (newdecl, olddecl)
       register tree newtype = TREE_TYPE (newdecl);
       register tree oldtype = TREE_TYPE (olddecl);
 
+      DECL_NESTED_TYPENAME (newdecl) = DECL_NESTED_TYPENAME (olddecl);
+
       if (newtype != error_mark_node && oldtype != error_mark_node
          && TYPE_LANG_SPECIFIC (newtype) && TYPE_LANG_SPECIFIC (oldtype))
        {
@@ -2826,6 +2840,7 @@ pushdecl (x)
            {
              tree tname = DECL_NAME (name);
 
+             /* This is a disgusting kludge for dealing with UPTs.  */
              if (global_bindings_p () && ANON_AGGRNAME_P (tname))
                {
                  /* do gratuitous C++ typedefing, and make sure that
@@ -2837,7 +2852,10 @@ pushdecl (x)
            }
          my_friendly_assert (TREE_CODE (name) == TYPE_DECL, 140);
 
-         if (! DECL_NESTED_TYPENAME (x))
+         /* Don't set nested_typename on template type parms, for instance.
+            Any artificial decls that need DECL_NESTED_TYPENAME will have it
+            set in pushtag.  */
+         if (! DECL_NESTED_TYPENAME (x) && ! DECL_ARTIFICIAL (x))
            set_nested_typename (x, current_class_name, DECL_NAME (x), type);
 
          if (type != error_mark_node
@@ -3056,16 +3074,6 @@ pushdecl (x)
        }
     }
 
-  if (TREE_CODE (x) == TYPE_DECL && name != NULL_TREE)
-    {
-      if (current_class_name)
-       {
-         if (! TREE_MANGLED (name))
-           set_nested_typename (x, current_class_name, DECL_NAME (x),
-                                TREE_TYPE (x));
-       }
-    }
-
   /* Put decls on list in reverse order.
      We will reverse them later if necessary.  */
   TREE_CHAIN (x) = b->names;
@@ -3190,7 +3198,11 @@ pushdecl_class_level (x)
       if (TREE_CODE (x) == TYPE_DECL)
        {
          set_identifier_type_value (name, TREE_TYPE (x));
-         if (!DECL_NESTED_TYPENAME (x))
+
+         /* Don't set nested_typename on template type parms, for instance.
+            Any artificial decls that need DECL_NESTED_TYPENAME will have it
+            set in pushtag.  */
+         if (! DECL_NESTED_TYPENAME (x) && ! DECL_ARTIFICIAL (x))
            set_nested_typename (x, current_class_name, name, TREE_TYPE (x));
        }
     }
@@ -4259,6 +4271,22 @@ push_overloaded_decl_1 (x)
   push_overloaded_decl (x, 0);
 }
 
+#define builtin_function(NAME, TYPE, CODE, LIBNAME) \
+  define_function (NAME, TYPE, CODE, (void (*)())pushdecl, LIBNAME)
+
+#ifdef __GNUC__
+__inline
+#endif
+tree auto_function (name, type, code)
+     tree name, type;
+     enum built_in_function code;
+{
+  return define_function
+    (IDENTIFIER_POINTER (name), type, code, (void (*)())push_overloaded_decl_1,
+     IDENTIFIER_POINTER (build_decl_overload (name, TYPE_ARG_TYPES (type),
+                                             0)));
+}
+
 /* Create the predefined scalar types of C,
    and some nodes representing standard constants (0, 1, (void *)0).
    Initialize the global binding level.
@@ -5733,6 +5761,9 @@ grok_reference_init (decl, type, init, cleanupp)
   if (TREE_CODE (init) == TREE_LIST)
     init = build_compound_expr (init);
 
+  if (TREE_CODE (TREE_TYPE (init)) == REFERENCE_TYPE)
+    init = convert_from_reference (init);
+
   if (TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE
       && TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE)
     {
@@ -7442,7 +7473,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
              || id == ridpointers[(int) RID_WCHAR])
            {
              if (type)
-               error ("extraneous `%T' ignored", id);
+               {
+                 if (id == ridpointers[(int) RID_BOOL])
+                   error ("`bool' is now a keyword");
+                 else
+                   cp_error ("extraneous `%T' ignored", id);
+               }
              else
                {
                  if (id == ridpointers[(int) RID_INT])
@@ -9558,17 +9594,7 @@ grokparms (first_parm, funcdef_flag)
                        }
                      else
                        init = require_instantiated_type (type, init, integer_zero_node);
-
-                     /* Don't actually try to build up a reference here.  */
-                     {
-                       tree t = type;
-                       if (TREE_CODE (t) == REFERENCE_TYPE)
-                         t = TREE_TYPE (t);
-                       init = convert_for_initialization
-                         (NULL_TREE, t, init, LOOKUP_NORMAL,
-                          "argument passing", 0, 0);
-                     }
-                   }
+           }
 #if 0 /* This is too early to check; trailing parms might be merged in by
         duplicate_decls.  */
                  else if (any_init)
@@ -9961,73 +9987,6 @@ grok_op_properties (decl, virtualp, friendp)
    the current frame for the name (since C++ allows new names in any
    scope.)  */
 
-/* avoid rewriting all callers of xref_tag */
-static int xref_next_defn = 0;
-
-tree
-xref_defn_tag (code_type_node, name, binfo)
-     tree code_type_node;
-     tree name, binfo;
-{
-  tree rv, ncp;
-  xref_next_defn = 1;
-
-  if (class_binding_level)
-    {
-      tree n1;
-      char *buf;
-      /* we need to build a new IDENTIFIER_NODE for name which nukes
-       * the pieces... */
-/*
-      n1 = IDENTIFIER_LOCAL_VALUE (current_class_name);
-      if (n1)
-       n1 = DECL_NAME (n1);
-      else
-       n1 = current_class_name;
-*/
-      n1 = TYPE_NAME (current_class_type);
-      if (n1)
-       n1 = DECL_NESTED_TYPENAME(n1);
-      else
-       n1 = current_class_name;
-      
-      buf = (char *) alloca (4 + IDENTIFIER_LENGTH (n1)
-                            + IDENTIFIER_LENGTH (name));
-      
-      sprintf (buf, "%s::%s", IDENTIFIER_POINTER (n1),
-              IDENTIFIER_POINTER (name));
-      ncp = get_identifier (buf);
-#ifdef SPEW_DEBUG
-      if (spew_debug)
-       printf("*** %s ***\n", IDENTIFIER_POINTER (ncp));
-#endif
-#if 0
-      IDENTIFIER_LOCAL_VALUE (name) =
-       build_decl (TYPE_DECL, ncp, NULL_TREE);
-#endif
-      rv = xref_tag (code_type_node, name, binfo, 0);
-      if (! ANON_AGGRNAME_P (name))
-      {
-       register tree type_decl = build_decl (TYPE_DECL, ncp, rv);
-       SET_DECL_ARTIFICIAL (type_decl);
-#ifdef DWARF_DEBUGGING_INFO
-       /* Mark the TYPE_DECL node created just above as a gratuitous one
-          so that dwarfout.c will know not to generate a TAG_typedef DIE
-          for it.  */
-       if (write_symbols == DWARF_DEBUG)
-         DECL_IGNORED_P (type_decl) = 1;
-#endif /* DWARF_DEBUGGING_INFO */
-       pushdecl_nonclass_level (type_decl);
-      }
-    }
-  else
-    {
-      rv = xref_tag (code_type_node, name, binfo, 0);
-    }
-  xref_next_defn = 0;
-  return rv;
-}
-
 tree
 xref_tag (code_type_node, name, binfo, globalize)
      tree code_type_node;
@@ -10037,7 +9996,7 @@ xref_tag (code_type_node, name, binfo, globalize)
   enum tag_types tag_code;
   enum tree_code code;
   int temp = 0;
-  int i, len;
+  int i;
   register tree ref, t;
   struct binding_level *b = inner_binding_level;
 
@@ -10048,16 +10007,9 @@ xref_tag (code_type_node, name, binfo, globalize)
     case class_type:
     case signature_type:
       code = RECORD_TYPE;
-      len = list_length (binfo);
       break;
     case union_type:
       code = UNION_TYPE;
-      if (binfo)
-       {
-         cp_error ("derived union `%T' invalid", name);
-         binfo = NULL_TREE;
-       }
-      len = 0;
       break;
     case enum_type:
       code = ENUMERAL_TYPE;
@@ -10072,18 +10024,12 @@ xref_tag (code_type_node, name, binfo, globalize)
   if (t && TREE_CODE (t) != code)
     t = NULL_TREE;
 
-  if (xref_next_defn)
+  if (! globalize)
     {
       /* If we know we are defining this tag, only look it up in this scope
        * and don't try to find it as a type. */
-      xref_next_defn = 0;
-      if (t && TYPE_CONTEXT(t))
-       {
-         if (TREE_MANGLED (name))
-           ref = t;
-         else
-           ref = lookup_tag (code, name, b, 1);
-       }
+      if (t && TYPE_CONTEXT(t) && TREE_MANGLED (name))
+       ref = t;
       else
        ref = lookup_tag (code, name, b, 1);
     }
@@ -10180,6 +10126,7 @@ xref_tag (code_type_node, name, binfo, globalize)
          && IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE)
        IDENTIFIER_GLOBAL_VALUE (name) = TYPE_NAME (ref);
 
+#if 0
       if (binfo)
        {
          tree tt1 = binfo;
@@ -10202,128 +10149,11 @@ xref_tag (code_type_node, name, binfo, globalize)
             build them on the permanent obstack.  */
          end_temporary_allocation ();
        }
+#endif
     }
 
   if (binfo)
-    {
-      /* In the declaration `A : X, Y, ... Z' we mark all the types
-        (A, X, Y, ..., Z) so we can check for duplicates.  */
-      tree binfos;
-
-      SET_CLASSTYPE_MARKED (ref);
-      BINFO_BASETYPES (TYPE_BINFO (ref)) = binfos = make_tree_vec (len);
-
-      for (i = 0; binfo; binfo = TREE_CHAIN (binfo))
-       {
-         /* The base of a derived struct is public by default.  */
-         int via_public
-           = (TREE_PURPOSE (binfo) == (tree)access_public
-              || TREE_PURPOSE (binfo) == (tree)access_public_virtual
-              || (tag_code != class_type
-                  && (TREE_PURPOSE (binfo) == (tree)access_default
-                      || TREE_PURPOSE (binfo) == (tree)access_default_virtual)));
-         int via_protected = TREE_PURPOSE (binfo) == (tree)access_protected;
-         int via_virtual
-           = (TREE_PURPOSE (binfo) == (tree)access_private_virtual
-              || TREE_PURPOSE (binfo) == (tree)access_public_virtual
-              || TREE_PURPOSE (binfo) == (tree)access_default_virtual);
-         tree basetype = TREE_TYPE (TREE_VALUE (binfo));
-         tree base_binfo;
-
-         GNU_xref_hier (IDENTIFIER_POINTER (name),
-                        IDENTIFIER_POINTER (TREE_VALUE (binfo)),
-                        via_public, via_virtual, 0);
-
-         if (basetype && TREE_CODE (basetype) == TYPE_DECL)
-           basetype = TREE_TYPE (basetype);
-         if (!basetype || TREE_CODE (basetype) != RECORD_TYPE)
-           {
-             error ("base type `%s' fails to be a struct or class type",
-                    IDENTIFIER_POINTER (TREE_VALUE (binfo)));
-             continue;
-           }
-#if 1
-         /* This code replaces similar code in layout_basetypes.  */
-         else if (TYPE_SIZE (basetype) == NULL_TREE)
-           {
-             cp_error ("base class `%T' has incomplete type", basetype);
-             continue;
-           }
-#endif
-         else
-           {
-             if (CLASSTYPE_MARKED (basetype))
-               {
-                 if (basetype == ref)
-                   cp_error ("recursive type `%T' undefined", basetype);
-                 else
-                   cp_error ("duplicate base type `%T' invalid", basetype);
-                 continue;
-               }
-
-             /* Note that the BINFO records which describe individual
-                inheritances are *not* shared in the lattice!  They
-                cannot be shared because a given baseclass may be
-                inherited with different `accessibility' by different
-                derived classes.  (Each BINFO record describing an
-                individual inheritance contains flags which say what
-                the `accessibility' of that particular inheritance is.)  */
-  
-             base_binfo = make_binfo (integer_zero_node, basetype,
-                                 TYPE_BINFO_VTABLE (basetype),
-                                 TYPE_BINFO_VIRTUALS (basetype), NULL_TREE);
-             TREE_VEC_ELT (binfos, i) = base_binfo;
-             TREE_VIA_PUBLIC (base_binfo) = via_public;
-             TREE_VIA_PROTECTED (base_binfo) = via_protected;
-             TREE_VIA_VIRTUAL (base_binfo) = via_virtual;
-             BINFO_INHERITANCE_CHAIN (base_binfo) = TYPE_BINFO (ref);
-
-             SET_CLASSTYPE_MARKED (basetype);
-#if 0
-/* XYZZY TEST VIRTUAL BASECLASSES */
-if (CLASSTYPE_N_BASECLASSES (basetype) == NULL_TREE
-    && TYPE_HAS_DEFAULT_CONSTRUCTOR (basetype)
-    && via_virtual == 0)
-  {
-    warning ("making type `%s' a virtual baseclass",
-            TYPE_NAME_STRING (basetype));
-    via_virtual = 1;
-  }
-#endif
-             /* We are free to modify these bits because they are meaningless
-                at top level, and BASETYPE is a top-level type.  */
-             if (via_virtual || TYPE_USES_VIRTUAL_BASECLASSES (basetype))
-               {
-                 TYPE_USES_VIRTUAL_BASECLASSES (ref) = 1;
-                 TYPE_USES_COMPLEX_INHERITANCE (ref) = 1;
-               }
-
-             TYPE_OVERLOADS_METHOD_CALL_EXPR (ref) |= TYPE_OVERLOADS_METHOD_CALL_EXPR (basetype);
-             TYPE_GETS_NEW (ref) |= TYPE_GETS_NEW (basetype);
-             TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
-             CLASSTYPE_LOCAL_TYPEDECLS (ref) |= CLASSTYPE_LOCAL_TYPEDECLS (basetype);
-             i += 1;
-           }
-       }
-      if (i)
-       TREE_VEC_LENGTH (binfos) = i;
-      else
-       BINFO_BASETYPES (TYPE_BINFO (ref)) = NULL_TREE;
-
-      if (i > 1)
-       TYPE_USES_MULTIPLE_INHERITANCE (ref) = 1;
-      else if (i == 1)
-       TYPE_USES_MULTIPLE_INHERITANCE (ref)
-         = TYPE_USES_MULTIPLE_INHERITANCE (BINFO_TYPE (TREE_VEC_ELT (binfos, 0)));
-      if (TYPE_USES_MULTIPLE_INHERITANCE (ref))
-       TYPE_USES_COMPLEX_INHERITANCE (ref) = 1;
-
-      /* Unmark all the types.  */
-      while (--i >= 0)
-       CLEAR_CLASSTYPE_MARKED (BINFO_TYPE (TREE_VEC_ELT (binfos, i)));
-      CLEAR_CLASSTYPE_MARKED (ref);
-    }
+    xref_basetypes (code_type_node, name, ref, binfo);
 
  just_return:
 
@@ -10344,6 +10174,145 @@ if (CLASSTYPE_N_BASECLASSES (basetype) == NULL_TREE
 
   return ref;
 }
+
+void
+xref_basetypes (code_type_node, name, ref, binfo)
+     tree code_type_node;
+     tree name, ref;
+     tree binfo;
+{
+  /* In the declaration `A : X, Y, ... Z' we mark all the types
+     (A, X, Y, ..., Z) so we can check for duplicates.  */
+  tree binfos;
+  int i, len;
+  enum tag_types tag_code = (enum tag_types) TREE_INT_CST_LOW (code_type_node);
+
+  if (tag_code == union_type)
+    {
+      cp_error ("derived union `%T' invalid", ref);
+      return;
+    }
+
+  len = list_length (binfo);
+  push_obstacks (TYPE_OBSTACK (ref), TYPE_OBSTACK (ref));
+
+  SET_CLASSTYPE_MARKED (ref);
+  BINFO_BASETYPES (TYPE_BINFO (ref)) = binfos = make_tree_vec (len);
+
+  for (i = 0; binfo; binfo = TREE_CHAIN (binfo))
+    {
+      /* The base of a derived struct is public by default.  */
+      int via_public
+       = (TREE_PURPOSE (binfo) == (tree)access_public
+          || TREE_PURPOSE (binfo) == (tree)access_public_virtual
+          || (tag_code != class_type
+              && (TREE_PURPOSE (binfo) == (tree)access_default
+                  || TREE_PURPOSE (binfo) == (tree)access_default_virtual)));
+      int via_protected = TREE_PURPOSE (binfo) == (tree)access_protected;
+      int via_virtual
+       = (TREE_PURPOSE (binfo) == (tree)access_private_virtual
+          || TREE_PURPOSE (binfo) == (tree)access_public_virtual
+          || TREE_PURPOSE (binfo) == (tree)access_default_virtual);
+      tree basetype = TREE_TYPE (TREE_VALUE (binfo));
+      tree base_binfo;
+
+      GNU_xref_hier (IDENTIFIER_POINTER (name),
+                    IDENTIFIER_POINTER (TREE_VALUE (binfo)),
+                    via_public, via_virtual, 0);
+
+      if (basetype && TREE_CODE (basetype) == TYPE_DECL)
+       basetype = TREE_TYPE (basetype);
+      if (!basetype || TREE_CODE (basetype) != RECORD_TYPE)
+       {
+         cp_error ("base type `%T' fails to be a struct or class type",
+                   TREE_VALUE (binfo));
+         continue;
+       }
+#if 1
+      /* This code replaces similar code in layout_basetypes.  */
+      else if (TYPE_INCOMPLETE (basetype))
+       {
+         cp_error ("base class `%T' has incomplete type", basetype);
+         continue;
+       }
+#endif
+      else
+       {
+         if (CLASSTYPE_MARKED (basetype))
+           {
+             if (basetype == ref)
+               cp_error ("recursive type `%T' undefined", basetype);
+             else
+               cp_error ("duplicate base type `%T' invalid", basetype);
+             continue;
+           }
+
+         /* Note that the BINFO records which describe individual
+            inheritances are *not* shared in the lattice!  They
+            cannot be shared because a given baseclass may be
+            inherited with different `accessibility' by different
+            derived classes.  (Each BINFO record describing an
+            individual inheritance contains flags which say what
+            the `accessibility' of that particular inheritance is.)  */
+  
+         base_binfo = make_binfo (integer_zero_node, basetype,
+                                  TYPE_BINFO_VTABLE (basetype),
+                                  TYPE_BINFO_VIRTUALS (basetype), NULL_TREE);
+         TREE_VEC_ELT (binfos, i) = base_binfo;
+         TREE_VIA_PUBLIC (base_binfo) = via_public;
+         TREE_VIA_PROTECTED (base_binfo) = via_protected;
+         TREE_VIA_VIRTUAL (base_binfo) = via_virtual;
+         BINFO_INHERITANCE_CHAIN (base_binfo) = TYPE_BINFO (ref);
+
+         SET_CLASSTYPE_MARKED (basetype);
+#if 0
+         /* XYZZY TEST VIRTUAL BASECLASSES */
+         if (CLASSTYPE_N_BASECLASSES (basetype) == NULL_TREE
+             && TYPE_HAS_DEFAULT_CONSTRUCTOR (basetype)
+             && via_virtual == 0)
+           {
+             warning ("making type `%s' a virtual baseclass",
+                      TYPE_NAME_STRING (basetype));
+             via_virtual = 1;
+           }
+#endif
+         /* We are free to modify these bits because they are meaningless
+            at top level, and BASETYPE is a top-level type.  */
+         if (via_virtual || TYPE_USES_VIRTUAL_BASECLASSES (basetype))
+           {
+             TYPE_USES_VIRTUAL_BASECLASSES (ref) = 1;
+             TYPE_USES_COMPLEX_INHERITANCE (ref) = 1;
+           }
+
+         TYPE_OVERLOADS_METHOD_CALL_EXPR (ref) |= TYPE_OVERLOADS_METHOD_CALL_EXPR (basetype);
+         TYPE_GETS_NEW (ref) |= TYPE_GETS_NEW (basetype);
+         TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
+         CLASSTYPE_LOCAL_TYPEDECLS (ref) |= CLASSTYPE_LOCAL_TYPEDECLS (basetype);
+         i += 1;
+       }
+    }
+  if (i)
+    TREE_VEC_LENGTH (binfos) = i;
+  else
+    BINFO_BASETYPES (TYPE_BINFO (ref)) = NULL_TREE;
+
+  if (i > 1)
+    TYPE_USES_MULTIPLE_INHERITANCE (ref) = 1;
+  else if (i == 1)
+    TYPE_USES_MULTIPLE_INHERITANCE (ref)
+      = TYPE_USES_MULTIPLE_INHERITANCE (BINFO_TYPE (TREE_VEC_ELT (binfos, 0)));
+  if (TYPE_USES_MULTIPLE_INHERITANCE (ref))
+    TYPE_USES_COMPLEX_INHERITANCE (ref) = 1;
+
+  /* Unmark all the types.  */
+  while (--i >= 0)
+    CLEAR_CLASSTYPE_MARKED (BINFO_TYPE (TREE_VEC_ELT (binfos, i)));
+  CLEAR_CLASSTYPE_MARKED (ref);
+
+  pop_obstacks ();
+}
+  
 \f
 static tree current_local_enum = NULL_TREE;
 
@@ -10452,19 +10421,23 @@ finish_enum (enumtype, values)
 
     TYPE_SIZE (enumtype) = NULL_TREE;
 
-    /* Lay out the type as though it were an integer.  */
-    if (! flag_short_enums && precision < TYPE_PRECISION (integer_type_node))
-      {
-       TYPE_MIN_VALUE (enumtype) = minnode;
-       TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node);
-       layout_type (enumtype);
-      }
+    /* Set TYPE_MIN_VALUE and TYPE_MAX_VALUE according to `precision'.  */
 
     TYPE_PRECISION (enumtype) = precision;
     if (unsignedp)
       fixup_unsigned_type (enumtype);
     else
       fixup_signed_type (enumtype);
+
+    if (flag_short_enums || precision > TYPE_PRECISION (integer_type_node))
+      /* Use the width of the narrowest normal C type which is wide enough.  */
+      TYPE_PRECISION (enumtype) = TYPE_PRECISION (type_for_size
+                                                 (precision, 1));
+    else
+      TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node);
+
+    TYPE_SIZE (enumtype) = 0;
+    layout_type (enumtype);
   }
 
   if (flag_cadillac)
@@ -11530,7 +11503,8 @@ finish_function (lineno, call_poplevel, nested)
 
       if (call_poplevel)
        {
-         expand_end_bindings (decls = getdecls (), decls != NULL_TREE, 0);
+         decls = getdecls ();
+         expand_end_bindings (decls, decls != NULL_TREE, 0);
          poplevel (decls != NULL_TREE, 1, 0);
        }
 
@@ -12002,11 +11976,6 @@ maybe_build_cleanup (decl)
          || flag_expensive_optimizations)
        flags |= LOOKUP_NONVIRTUAL;
 
-      /* Use TYPE_MAIN_VARIANT so we don't get a warning about
-        calling delete on a `const' variable.  */
-      if (TYPE_READONLY (TREE_TYPE (TREE_TYPE (rval))))
-       rval = build1 (NOP_EXPR, TYPE_POINTER_TO (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (rval)))), rval);
-
       rval = build_delete (TREE_TYPE (rval), rval, integer_two_node, flags, 0);
 
       if (TYPE_USES_VIRTUAL_BASECLASSES (type)
index 0f4ec36b76b47b15373a5799997d28ad3f352b00..32090e974a6a6ec9cfbcb134c1dd4192ee0ff958 100644 (file)
@@ -683,11 +683,29 @@ substitute_nice_name (decl)
    interface/implementation is not used all the times it should be,
    inform the user.  */
 void
-warn_if_unknown_interface ()
+warn_if_unknown_interface (decl)
+     tree decl;
 {
   static int already_warned = 0;
-  if (++already_warned == 1)
-    warning ("templates that are built with -fexternal-templates should be in files that have #pragma interface/implementation");
+  if (already_warned++)
+    return;
+
+  if (flag_alt_external_templates)
+    {
+      struct tinst_level *til = tinst_for_decl ();
+      int sl = lineno;
+      char *sf = input_filename;
+
+      lineno = til->line;
+      input_filename = til->file;
+      cp_warning ("template `%#D' instantiated in file without #pragma interface",
+                 decl);
+      lineno = sl;
+      input_filename = sf;
+    }
+  else
+    cp_warning_at ("template `%#D' defined in file without #pragma interface",
+                  decl);
 }
 
 /* A subroutine of the parser, to handle a component list.  */
@@ -734,7 +752,7 @@ grok_x_components (specs, components)
          else if (IS_SIGNATURE(t))
            tcode = signature_type_node;
          
-         t = xref_defn_tag(tcode, TYPE_IDENTIFIER(t), NULL_TREE);
+         t = xref_tag (tcode, TYPE_IDENTIFIER (t), NULL_TREE, 0);
          if (TYPE_CONTEXT(t))
            CLASSTYPE_NO_GLOBALIZE(t) = 1;
          return NULL_TREE;
@@ -747,7 +765,7 @@ grok_x_components (specs, components)
          else
            tcode = enum_type_node;
 
-         t = xref_defn_tag(tcode, TYPE_IDENTIFIER(t), NULL_TREE);
+         t = xref_tag (tcode, TYPE_IDENTIFIER (t), NULL_TREE, 0);
          if (TREE_CODE(t) == UNION_TYPE && TYPE_CONTEXT(t))
            CLASSTYPE_NO_GLOBALIZE(t) = 1;
          if (TREE_CODE (t) == UNION_TYPE
@@ -1103,12 +1121,15 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
 
   if (code == POINTER_TYPE)
     {
+#if 0
+      /* As of Valley Forge, you can delete a pointer to constant.  */
       /* You can't delete a pointer to constant.  */
       if (TREE_READONLY (TREE_TYPE (type)))
        {
          error ("`const *' cannot be deleted");
          return error_mark_node;
        }
+#endif
       /* You also can't delete functions.  */
       if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
        {
@@ -1288,7 +1309,6 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree)
       DECL_CONTEXT (value) = current_class_type;
       DECL_CLASS_CONTEXT (value) = current_class_type;
       CLASSTYPE_LOCAL_TYPEDECLS (current_class_type) = 1;
-      pushdecl_class_level (value);
 
       /* If we declare a typedef name for something that has no name,
         the typedef name is used for linkage.  See 7.1.3 p4 94/0158. */
@@ -1299,6 +1319,8 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree)
          TYPE_NAME (TREE_TYPE (value)) = value;
          TYPE_STUB_DECL (TREE_TYPE (value)) = value;
        }
+
+      pushdecl_class_level (value);
       return value;
     }
 
index ff4cc0904ea9d3bf0cec8efb6015f26e98b723e2..2be11e0d90daf62c7778b3ae8140d478944954f6 100644 (file)
@@ -599,6 +599,7 @@ dump_decl (t, v)
        {
          dump_type_prefix (TREE_TYPE (t), v);
          OB_PUTC (' ');
+         dump_readonly_or_volatile (t, after);
        }
       /* DECL_CLASS_CONTEXT isn't being set in some cases.  Hmm...  */
       if (DECL_CONTEXT (t)
index 218818d92afae8235220271168d9aff59bc74caf..6fc23ec85cdf30dd68d70b34fd46d5e1ecabde35 100644 (file)
@@ -48,7 +48,12 @@ tree builtin_return_address_fndecl;
 #define __rs6000
 #endif
 #endif
-#if defined(__i386) || defined(__rs6000) || defined(__hppa) || defined(__mc68000) || defined (__mips) || defined (__arm)
+#ifdef mips
+#ifndef __mips
+#define __mips
+#endif
+#endif
+#if defined(__i386) || defined(__rs6000) || defined(__hppa) || defined(__mc68000) || defined (__mips) || defined (__arm) || defined (__alpha)
 #define TRY_NEW_EH
 #endif
 #endif
@@ -390,44 +395,45 @@ static tree TerminateFunctionCall;
 /* =================================================================== */
 
 struct labelNode {
-    rtx label;
-       struct labelNode *chain;
- };
+  rtx label;
+  struct labelNode *chain;
+};
 
 
 /* this is the most important structure here.  Basically this is how I store
    an exception table entry internally. */
 struct ehEntry {
-    rtx start_label;
-       rtx end_label;
-       rtx exception_handler_label;
+  rtx start_label;
+  rtx end_label;
+  rtx exception_handler_label;
 
-       tree finalization;
- };
+  tree finalization;
+  tree context;
+};
 
 struct ehNode {
-    struct ehEntry *entry;
-       struct ehNode *chain;
- };
+  struct ehEntry *entry;
+  struct ehNode *chain;
+};
 
 struct ehStack {
-    struct ehNode *top;
- };
+  struct ehNode *top;
+};
 
 struct ehQueue {
-    struct ehNode *head;
-       struct ehNode *tail;
- };
+  struct ehNode *head;
+  struct ehNode *tail;
+};
 
 struct exceptNode {
-    rtx catchstart;
-       rtx catchend;
+  rtx catchstart;
+  rtx catchend;
 
-       struct exceptNode *chain;
- };
+  struct exceptNode *chain;
+};
 
 struct exceptStack {
-       struct exceptNode *top;
+  struct exceptNode *top;
  };
 /* ========================================================================= */
 
@@ -603,6 +609,7 @@ push_eh_entry (stack)
   LABEL_PRESERVE_P (entry->exception_handler_label) = 1;
 
   entry->finalization = NULL_TREE;
+  entry->context = current_function_decl;
 
   node->entry = entry;
   node->chain = stack->top;
@@ -715,6 +722,8 @@ lang_interim_eh (finalization)
     start_protect ();
 }
 
+extern tree auto_function PROTO((tree, tree, enum built_in_function));
+
 /* sets up all the global eh stuff that needs to be initialized at the
    start of compilation.
 
@@ -735,44 +744,34 @@ init_exception_processing ()
   tree catch_match_fndecl;
   tree find_first_exception_match_fndecl;
   tree unwind_fndecl;
-  tree temp, PFV;
-
-  interim_eh_hook = lang_interim_eh;
 
   /* void (*)() */
-  PFV = build_pointer_type (build_function_type (void_type_node, void_list_node));
+  tree PFV = build_pointer_type (build_function_type
+                                (void_type_node, void_list_node));
 
   /* arg list for the build_function_type call for set_terminate () and
      set_unexpected () */
-  temp = tree_cons (NULL_TREE, PFV, void_list_node);
+  tree pfvlist = tree_cons (NULL_TREE, PFV, void_list_node);
 
-  push_lang_context (lang_name_c);
+  /* void (*pfvtype (void (*) ()))() */
+  tree pfvtype = build_function_type (PFV, pfvlist);
 
-  set_terminate_fndecl =
-    define_function ("set_terminate",
-                    build_function_type (PFV, temp),
-                    NOT_BUILT_IN,
-                    pushdecl,
-                    0);
-  set_unexpected_fndecl =
-    define_function ("set_unexpected",
-                    build_function_type (PFV, temp),
-                    NOT_BUILT_IN,
-                    pushdecl,
-                    0);
+  /* void vtype () */
+  tree vtype = build_function_type (void_type_node, void_list_node);
+  
+  set_terminate_fndecl = auto_function (get_identifier ("set_terminate"),
+                                       pfvtype, NOT_BUILT_IN);
+  set_unexpected_fndecl = auto_function (get_identifier ("set_unexpected"),
+                                        pfvtype, NOT_BUILT_IN);
+  unexpected_fndecl = auto_function (get_identifier ("unexpected"),
+                                    vtype, NOT_BUILT_IN);
+  terminate_fndecl = auto_function (get_identifier ("terminate"),
+                                   vtype, NOT_BUILT_IN);
+
+  interim_eh_hook = lang_interim_eh;
+
+  push_lang_context (lang_name_c);
 
-  unexpected_fndecl =
-    define_function ("unexpected",
-                    build_function_type (void_type_node, void_list_node),
-                    NOT_BUILT_IN,
-                    pushdecl,
-                    0);
-  terminate_fndecl =
-    define_function ("terminate",
-                    build_function_type (void_type_node, void_list_node),
-                    NOT_BUILT_IN,
-                    pushdecl,
-                    0);
   catch_match_fndecl =
     define_function ("__throw_type_match",
                     build_function_type (integer_type_node,
@@ -843,6 +842,11 @@ init_exception_processing ()
   saved_pc = gen_rtx (REG, Pmode, 7);
   saved_throw_type = gen_rtx (REG, Pmode, 8);
   saved_throw_value = gen_rtx (REG, Pmode, 9);
+#endif
+#ifdef __alpha
+  saved_pc = gen_rtx (REG, Pmode, 9);
+  saved_throw_type = gen_rtx (REG, Pmode, 10);
+  saved_throw_value = gen_rtx (REG, Pmode, 11);
 #endif
   new_eh_queue (&ehqueue);
   new_eh_queue (&eh_table_output_queue);
@@ -989,6 +993,7 @@ expand_start_all_catch ()
   entry->end_label = gen_label_rtx ();
   entry->exception_handler_label = gen_label_rtx ();
   entry->finalization = TerminateFunctionCall;
+  entry->context = current_function_decl;
   assemble_external (TREE_OPERAND (Terminate, 0));
   pop_rtl_from_perm ();
 
@@ -1091,6 +1096,7 @@ expand_leftover_cleanups ()
       entry.end_label = label;
       entry.exception_handler_label = gen_label_rtx ();
       entry.finalization = TerminateFunctionCall;
+      entry.context = current_function_decl;
       assemble_external (TREE_OPERAND (Terminate, 0));
       pop_rtl_from_perm ();
 
@@ -1243,13 +1249,15 @@ void expand_end_catch_block ()
       emit_jump (throw_label);
       /* No associated finalization.  */
       entry.finalization = NULL_TREE;
+      entry.context = current_function_decl;
 
       /* Because we are reordered out of line, we have to protect this. */
       /* label for the start of the protection region.  */
       start_protect_label_rtx = pop_label_entry (&false_label_stack);
 
       /* Cleanup the EH paramater.  */
-      expand_end_bindings (decls = getdecls (), decls != NULL_TREE, 0);
+      decls = getdecls ();
+      expand_end_bindings (decls, decls != NULL_TREE, 0);
       
       /* label we emit to jump to if this catch block didn't match. */
       emit_label (end_protect_label_rtx = pop_label_entry (&false_label_stack));
@@ -1309,7 +1317,7 @@ do_unwind (throw_label)
   easy_expand_asm ("restore");
   emit_barrier ();
 #endif
-#if defined(__i386) || defined(__rs6000) || defined(__hppa) || defined(__mc68000) || defined (__mips)
+#if defined(__i386) || defined(__rs6000) || defined(__hppa) || defined(__mc68000) || defined (__mips) || defined(__alpha)
   extern FILE *asm_out_file;
   tree fcall;
   tree params;
@@ -1449,7 +1457,7 @@ expand_builtin_throw ()
 #ifndef sparc
   /* On the SPARC, __builtin_return_address is already -8, no need to
      subtract any more from it. */
-  emit_insn (gen_add2_insn (return_val_rtx, GEN_INT (-1)));
+  return_val_rtx = plus_constant (return_val_rtx, -1);
 #endif
 #endif
 
@@ -1542,10 +1550,8 @@ expand_throw (exp)
        rtx throw_type_rtx = expand_expr (throw_type, NULL_RTX, VOIDmode, 0);
        rtx throw_value_rtx;
 
-       exp = convert_to_reference (build_reference_type (build_type_variant (TREE_TYPE (exp), 1, 0)), exp, CONV_STATIC, LOOKUP_COMPLAIN, error_mark_node);
-
        /* Make a copy of the thrown object.  WP 15.1.5  */
-       exp = build_new (NULL_TREE, TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (exp))), exp, 0);
+       exp = build_new (NULL_TREE, type, build_tree_list (NULL_TREE, exp), 0);
 
        if (exp == error_mark_node)
          error ("  in thrown expression");
@@ -1557,7 +1563,7 @@ expand_throw (exp)
   else
     {
       /* rethrow current exception */
-      /* This part is easy, as we dont' have to do anything else.  */
+      /* This part is easy, as we don't have to do anything else.  */
     }
 
   emit_move_insn (saved_pc, gen_rtx (LABEL_REF, Pmode, label));
@@ -1585,6 +1591,11 @@ build_exception_table ()
 
  while (entry = dequeue_eh_entry (&eh_table_output_queue))
    {
+     tree context = entry->context;
+
+     if (context && ! TREE_ASM_WRITTEN (context))
+       continue;
+
      if (count == 0)
        {
         exception_section ();
index 961fb6d16f377047d0908c8908b68097b9e99049..9be741779ffa9b47a676fcdb39a64dac8ad0df5d 100644 (file)
@@ -1193,17 +1193,17 @@ The below points out some flaws in g++'s exception handling, as it now
 stands.
 
 Only exact type matching or reference matching of throw types works.
-Only works on a SPARC machines (like Suns), and i386 machines.  Partial
-support is also in for rs6000, hppa, m68k and mips machines, but a stack
-unwinder called __unwind_function has to be written, and added to
-libgcc2 for them.  All completely constructed temps and local variables
-are cleaned up in all unwinded scopes.  Completed parts of partially
-constructed objects are not cleaned up.  Don't expect exception handling
-to work right if you optimize, in fact the compiler will probably core
-dump.  If two EH regions are the exact same size, the backend cannot
-tell which one is first.  It punts by picking the last one, if they tie.
-This is usually right.  We really should stick in a nop, if they are the
-same size.
+Only works on a SPARC machines (like Suns), i386 machines, arm machines
+and rs6000 machines.  Partial support is also in for alpha, hppa, m68k
+and mips machines, but a stack unwinder called __unwind_function has to
+be written, and added to libgcc2 for them.  All completely constructed
+temps and local variables are cleaned up in all unwinded scopes.
+Completed parts of partially constructed objects are not cleaned up.
+Don't expect exception handling to work right if you optimize, in fact
+the compiler will probably core dump.  If two EH regions are the exact
+same size, the backend cannot tell which one is first.  It punts by
+picking the last one, if they tie.  This is usually right.  We really
+should stick in a nop, if they are the same size.
 
 When we invoke the copy constructor for an exception object because it
 is passed by value, and if we take a hit (exception) inside the copy
@@ -1223,14 +1223,14 @@ implements set compares, not exact list equality.  Type smashing should
 smash exception specifications using set union.
 
 Thrown objects are allocated on the heap, in the usual way, but they are
-never deleted.  They should be deleted by the catch clauses.
-
-In stmt.c, expand_end_bindings attempts to eliminate the generation of
-destructors for a binding contour if the code would be unreachable (last
-insn == BARRIER). In this case, interim_eh_hook is never called for the
-end of the lifetimes of auto variables, so the compiler generates
-invalid assembler (the end label for the scope is never declared, and
-destructor code isn't generated on the exception path).
+never deleted.  They should be deleted by the catch clauses.  If one
+runs out of heap space, throwing an object will probably never work.
+This could be relaxed some by passing an __in_chrg parameter to track
+who has control over the exception object.
+
+When the backend returns a value, it can create new exception regions
+that need protecting.  The new region should rethrow the object in
+context of the last associated cleanup that ran to completion.
 
 @node Free Store, Concept Index, Exception Handling, Top
 @section Free Store
index fd8bf2b845b70d433b0de34cbbecb1c874c0c7c0..cf8b0e7772a19825cf20c0754d3fe8a62174b45d 100644 (file)
@@ -574,6 +574,12 @@ emit_base_init (t, immediately)
       tree base = current_class_decl;
       tree base_binfo = TREE_VEC_ELT (binfos, i);
 
+#if 0 /* Once unsharing happens soon enough.  */
+      my_friendly_assert (BINFO_INHERITANCE_CHAIN (base_binfo) == t_binfo);
+#else
+      BINFO_INHERITANCE_CHAIN (base_binfo) = t_binfo;
+#endif
+
       if (TYPE_NEEDS_CONSTRUCTING (BINFO_TYPE (base_binfo)))
        {
          if (! TREE_VIA_VIRTUAL (base_binfo)
@@ -1210,7 +1216,8 @@ expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags)
       if (parms)
        init = TREE_VALUE (parms);
     }
-  else if (TREE_CODE (init) == INDIRECT_REF && TREE_HAS_CONSTRUCTOR (init))
+  else if (TREE_CODE (init) == INDIRECT_REF && TREE_HAS_CONSTRUCTOR (init)
+          && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (init)))
     {
       rval = convert_for_initialization (exp, type, init, 0, 0, 0, 0);
       TREE_USED (rval) = 1;
@@ -2932,11 +2939,8 @@ build_new (placement, decl, init, use_global_new)
     }
 
   if (TYPE_READONLY (type) || TYPE_VOLATILE (type))
-    {
-      pedwarn ("const and volatile types cannot be created with operator new");
-      type = true_type = TYPE_MAIN_VARIANT (type);
-    }
-  
+    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)
@@ -3000,7 +3004,7 @@ build_new (placement, decl, init, use_global_new)
       rval = convert (TYPE_POINTER_TO (true_type), rval);
     }
   else if (! has_array && flag_this_is_variable > 0
-          && TYPE_HAS_CONSTRUCTOR (true_type) && init != void_type_node)
+          && TYPE_NEEDS_CONSTRUCTING (true_type) && init != void_type_node)
     {
       if (init == NULL_TREE || TREE_CODE (init) == TREE_LIST)
        rval = NULL_TREE;
@@ -3061,57 +3065,8 @@ build_new (placement, decl, init, use_global_new)
                                             build_tree_list (NULL_TREE, rval)));
     }
 
-  /* We've figured out where the allocation is to go.
-     If we're not eliding constructors, then if a constructor
-     is defined, we must go through it.  */
-  if (!has_array && (rval == NULL_TREE || !flag_elide_constructors)
-      && TYPE_HAS_CONSTRUCTOR (true_type) && init != void_type_node)
-    {
-      tree newrval;
-      /* Constructors are never virtual. If it has an initialization, we
-        need to complain if we aren't allowed to use the ctor that took
-        that argument.  */
-      int flags = LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_COMPLAIN;
-
-      /* If a copy constructor might work, set things up so that we can
-        try that after this.  We deliberately don't clear LOOKUP_COMPLAIN
-        any more, since that would make it impossible to rationally use
-        the access of a constructor that matches perfectly.  */
-#if 0
-      if (rval != NULL_TREE)
-       flags |= LOOKUP_SPECULATIVELY;
-#endif
-
-      if (rval && TYPE_USES_VIRTUAL_BASECLASSES (true_type))
-       {
-         init = tree_cons (NULL_TREE, integer_one_node, init);
-         flags |= LOOKUP_HAS_IN_CHARGE;
-       }
-
-      {
-       tree tmp = rval;
-       
-       if (tmp && TREE_CODE (TREE_TYPE (tmp)) == POINTER_TYPE)
-         tmp = build_indirect_ref (tmp, NULL_PTR);
-      
-       newrval = build_method_call (tmp, constructor_name_full (true_type),
-                                    init, NULL_TREE, flags);
-      }
-      
-      if (newrval)
-       {
-         rval = newrval;
-         TREE_HAS_CONSTRUCTOR (rval) = 1;
-       }
-      else
-       rval = error_mark_node;
-      goto done;
-    }
-
   if (rval == error_mark_node)
     return error_mark_node;
-  rval = save_expr (rval);
-  TREE_HAS_CONSTRUCTOR (rval) = 1;
 
   /* Don't call any constructors or do any initialization.  */
   if (init == void_type_node)
@@ -3123,20 +3078,60 @@ build_new (placement, decl, init, use_global_new)
        {
          /* New 2.0 interpretation: `new int (10)' means
             allocate an int, and initialize it with 10.  */
+         tree deref;
+
+         rval = save_expr (rval);
+         deref = build_indirect_ref (rval, NULL_PTR);
+         TREE_READONLY (deref) = 0;
 
-         init = build_c_cast (type, init, 1);
+         if (TREE_CHAIN (init) != NULL_TREE)
+           pedwarn ("initializer list being treated as compound expression");
+         init = build_compound_expr (init);
+
+         init = convert_for_initialization (deref, type, init, LOOKUP_NORMAL,
+                                            "new", NULL_TREE, 0);
          rval = build (COMPOUND_EXPR, TREE_TYPE (rval),
-                       build_modify_expr (build_indirect_ref (rval, NULL_PTR),
-                                          NOP_EXPR, init),
+                       build_modify_expr (deref, NOP_EXPR, init),
                        rval);
          TREE_SIDE_EFFECTS (rval) = 1;
          TREE_CALLS_NEW (rval) = 1;
        }
+      else if (! has_array)
+       {
+         tree newrval;
+         /* Constructors are never virtual. If it has an initialization, we
+            need to complain if we aren't allowed to use the ctor that took
+            that argument.  */
+         int flags = LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_COMPLAIN;
+
+         if (rval && TYPE_USES_VIRTUAL_BASECLASSES (true_type))
+           {
+             init = tree_cons (NULL_TREE, integer_one_node, init);
+             flags |= LOOKUP_HAS_IN_CHARGE;
+           }
+
+         newrval = rval;
+
+         if (newrval && TREE_CODE (TREE_TYPE (newrval)) == POINTER_TYPE)
+           newrval = build_indirect_ref (newrval, NULL_PTR);
+
+         newrval = build_method_call (newrval, constructor_name_full (true_type),
+                                      init, NULL_TREE, flags);
+
+         if (newrval)
+           {
+             rval = newrval;
+             TREE_HAS_CONSTRUCTOR (rval) = 1;
+           }
+         else
+           rval = error_mark_node;
+       }
       else if (current_function_decl == NULL_TREE)
        {
          extern tree static_aggregates;
 
          /* In case of static initialization, SAVE_EXPR is good enough.  */
+         rval = save_expr (rval);
          init = copy_to_permanent (init);
          rval = copy_to_permanent (rval);
          static_aggregates = perm_tree_cons (init, rval, static_aggregates);
@@ -3156,12 +3151,11 @@ build_new (placement, decl, init, use_global_new)
          /* As a matter of principle, `start_sequence' should do this.  */
          emit_note (0, -1);
 
-         if (has_array)
-           rval = expand_vec_init (decl, rval,
-                                   build_binary_op (MINUS_EXPR, nelts, integer_one_node, 1),
-                                   init, 0);
-         else
-           expand_aggr_init (build_indirect_ref (rval, NULL_PTR), init, 0, 0);
+         rval = save_expr (rval);
+         rval = expand_vec_init (decl, rval,
+                                 build_binary_op (MINUS_EXPR, nelts,
+                                                  integer_one_node, 1),
+                                 init, 0);
 
          do_pending_stack_adjust ();
 
@@ -3185,13 +3179,15 @@ build_new (placement, decl, init, use_global_new)
          rval = xval;
        }
     }
+  else if (TYPE_READONLY (true_type))
+    cp_error ("uninitialized const in `new' of `%#T'", true_type);
+
  done:
 
   if (flag_check_new && alloc_expr && rval != alloc_expr)
     {
       tree ifexp = build_binary_op (NE_EXPR, alloc_expr, integer_zero_node, 1);
-      rval = build_conditional_expr (ifexp, rval, convert (TREE_TYPE (rval),
-                                                          integer_zero_node));
+      rval = build_conditional_expr (ifexp, rval, alloc_expr);
     }
 
   if (rval && TREE_TYPE (rval) != build_pointer_type (type))
index d61de50be6a15f6fde0d206d744e29856fba263a..89a90ded3fac839d6641163b1384c681c8537171 100644 (file)
@@ -1539,7 +1539,7 @@ reinit_parse_for_method (yychar, decl)
       t->can_free = 1;
       t->deja_vu = 0;
       if (interface_unknown && processing_template_defn && flag_external_templates && ! DECL_IN_SYSTEM_HEADER (decl))
-       warn_if_unknown_interface ();
+       warn_if_unknown_interface (decl);
       t->interface = (interface_unknown ? 1 : (interface_only ? 0 : 2));
       store_pending_inline (decl, t);
     }
@@ -1700,8 +1700,8 @@ reinit_parse_for_block (yychar, obstackp, is_template)
    When KIND == 6, build default operator = (X&).  */
 
 tree
-cons_up_default_function (type, name, kind)
-     tree type, name;
+cons_up_default_function (type, full_name, kind)
+     tree type, full_name;
      int kind;
 {
   extern tree void_list_node;
@@ -1712,8 +1712,8 @@ cons_up_default_function (type, name, kind)
   tree argtype;
   int retref = 0;
   int complex = 0;
+  tree name = constructor_name (full_name);
 
-  name = constructor_name (name);
   switch (kind)
     {
       /* Destructors.  */
@@ -1750,7 +1750,7 @@ cons_up_default_function (type, name, kind)
       /* Fall through...  */
     case 6:
       retref = 1;
-      declspecs = build_decl_list (NULL_TREE, name);
+      declspecs = build_decl_list (NULL_TREE, full_name);
 
       name = ansi_opname [(int) MODIFY_EXPR];
 
index 5a646a51d0d2e6e9498c4c3ac476d9aaf31ab09a..f185ebe17695c40a816da8aeeb6fedfd8fbed7bf 100644 (file)
@@ -2069,7 +2069,9 @@ do_build_copy_constructor (fndecl)
           t = TREE_CHAIN (t))
        {
          tree basetype = BINFO_TYPE (t);
-         tree p = convert (build_reference_type (basetype), parm);
+         tree 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 (TYPE_NESTED_NAME (basetype),
                                              p, current_base_init_list);
@@ -2079,10 +2081,12 @@ do_build_copy_constructor (fndecl)
        {
          tree p, basetype = TREE_VEC_ELT (binfos, i);
          if (TREE_VIA_VIRTUAL (basetype))
-           continue;     
+           continue; 
 
          basetype = BINFO_TYPE (basetype);
-         p = convert (build_reference_type (basetype), parm);
+         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 (TYPE_NESTED_NAME (basetype),
                                              p, current_base_init_list);
@@ -2153,7 +2157,9 @@ do_build_assign_ref (fndecl)
          tree basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i));
          if (TYPE_HAS_ASSIGN_REF (basetype))
            {
-             tree p = convert (build_reference_type (basetype), parm);
+             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 (TYPE_NESTED_NAME (basetype),
                                     ansi_opname [MODIFY_EXPR],
index 6a4420ce18b290e06e852e940b61a3d6b1db63b8..102ca63e131b81ab070c04d7aca361aa021577b1 100644 (file)
@@ -280,7 +280,7 @@ empty_parms ()
 /* Used in lex.c for parsing pragmas.  */
 %token END_OF_LINE
 
-/* spew.c depends on this being the last token.  Define
+/* lex.c and pt.c depends on this being the last token.  Define
    any new tokens before this one!  */
 %token END_OF_SAVED_INPUT
 \f
@@ -940,8 +940,7 @@ paren_expr_or_null:
                         cond_stmt_keyword);
                  $$ = integer_zero_node; }
        | '(' expr ')'
-               { $$ = build1 (CLEANUP_POINT_EXPR, boolean_type_node, 
-                              bool_truthvalue_conversion ($2)); }
+               { $$ = condition_conversion ($2); }
        ;
 
 paren_cond_or_null:
@@ -950,16 +949,14 @@ paren_cond_or_null:
                         cond_stmt_keyword);
                  $$ = integer_zero_node; }
        | '(' condition ')'
-               { $$ = build1 (CLEANUP_POINT_EXPR, boolean_type_node, 
-                              bool_truthvalue_conversion ($2)); }
+               { $$ = condition_conversion ($2); }
        ;
 
 xcond:
        /* empty */
                { $$ = NULL_TREE; }
        | condition
-               { $$ = build1 (CLEANUP_POINT_EXPR, boolean_type_node, 
-                              bool_truthvalue_conversion ($$)); }
+               { $$ = condition_conversion ($$); }
        | error
                { $$ = NULL_TREE; }
        ;
@@ -1800,6 +1797,7 @@ type_id:
 typed_declspecs:
          typed_typespecs %prec EMPTY
        | typed_declspecs1
+       ;
 
 typed_declspecs1:
          declmods typespec
@@ -2151,9 +2149,9 @@ structsp:
                { $$ = finish_enum (start_enum (make_anon_name()), NULL_TREE);
                  check_for_missing_semicolon ($$); }
        | ENUM identifier
-               { $$ = xref_tag (enum_type_node, $2, NULL_TREE, 0); }
+               { $$ = xref_tag (enum_type_node, $2, NULL_TREE, 1); }
        | ENUM complex_type_name
-               { $$ = xref_tag (enum_type_node, $2, NULL_TREE, 0); }
+               { $$ = xref_tag (enum_type_node, $2, NULL_TREE, 1); }
 
        /* C++ extensions, merged with C to avoid shift/reduce conflicts */
        | class_head left_curly opt.component_decl_list '}'
@@ -2206,16 +2204,11 @@ structsp:
                    check_for_missing_semicolon ($$); }
        | class_head  %prec EMPTY
                {
-#if 0
-  /* It's no longer clear what the following error is supposed to
-     accomplish.  If it turns out to be needed, add a comment why.  */
-                 if (TYPE_BINFO_BASETYPES ($$) && !TYPE_SIZE ($$))
-                   {
-                     error ("incomplete definition of type `%s'",
-                            TYPE_NAME_STRING ($$));
-                     $$ = error_mark_node;
-                   }
-#endif
+                 /* struct B: public A; is not accepted by the WP grammar.  */
+                 if (TYPE_BINFO_BASETYPES ($$) && !TYPE_SIZE ($$)
+                     && ! TYPE_BEING_DEFINED ($$))
+                   cp_error ("base clause without member specification for `%#T'",
+                             $$);
                }
        ;
 
@@ -2257,6 +2250,12 @@ named_class_head_sans_basetype:
                { current_aggr = $$; $$ = $2; }
        | aggr template_type %prec EMPTY
                { current_aggr = $$; $$ = $2; }
+       | specialization
+       ;
+
+named_class_head_sans_basetype_defn:
+         aggr identifier_defn %prec EMPTY
+               { current_aggr = $$; $$ = $2; }
        | aggr template_type_name '{'
                { yyungetc ('{', 1);
                aggr2:
@@ -2265,37 +2264,21 @@ named_class_head_sans_basetype:
                  overload_template_name ($$, 0); }
        | aggr template_type_name ':'
                { yyungetc (':', 1); goto aggr2; }
-       | specialization
        ;
 
-named_class_head_sans_basetype_defn:
-         aggr identifier_defn %prec EMPTY
-               { current_aggr = $$; $$ = $2; }
-       ;
-
-do_xref: /* empty */ %prec EMPTY
-       { $<ttype>$ = xref_tag (current_aggr, $<ttype>0, NULL_TREE, 1); }
-
 do_xref_defn: /* empty */ %prec EMPTY
-       { $<ttype>$ = xref_defn_tag (current_aggr, $<ttype>0, NULL_TREE); }
+        { $<ttype>$ = xref_tag (current_aggr, $<ttype>0, NULL_TREE, 0); }
+       ;
 
 named_class_head:
-         named_class_head_sans_basetype do_xref
-         maybe_base_class_list %prec EMPTY
-               {
-                 if ($3)
-                   $$ = xref_tag (current_aggr, $1, $3, 1);
-                 else
-                   $$ = $<ttype>2;
-               }
-       |
-         named_class_head_sans_basetype_defn do_xref_defn
-         maybe_base_class_list %prec EMPTY
-               {
+         named_class_head_sans_basetype %prec EMPTY
+               { $$ = xref_tag (current_aggr, $1, NULL_TREE, 1); }
+       | named_class_head_sans_basetype_defn do_xref_defn
+          maybe_base_class_list %prec EMPTY
+               { 
+                 $$ = $<ttype>2;
                  if ($3)
-                   $$ = xref_defn_tag (current_aggr, $1, $3);
-                 else
-                   $$ = $<ttype>2;
+                    xref_basetypes (current_aggr, $1, $<ttype>2, $3); 
                }
        ;
 
@@ -3472,8 +3455,12 @@ handler_seq:
          /* empty */
        | handler_seq CATCH
                { emit_line_note (input_filename, lineno); }
-         handler_args compstmt
-               { expand_end_catch_block (); }
+          .pushlevel handler_args compstmt
+               { expand_end_catch_block ();
+                 expand_end_bindings (getdecls (), kept_level_p (), 1);
+                 poplevel (kept_level_p (), 1, 0);
+                 pop_momentary ();
+               }
        ;
 
 type_specifier_seq:
index a9dfb84be3bbb12008aab03c3a286bd9538f8095..5804bb6b87c724daa6331f49ba8c49752a012dcf 100644 (file)
@@ -128,6 +128,7 @@ process_template_parm (list, next)
            defval = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (defval));
        }
     }
+  SET_DECL_ARTIFICIAL (decl);
   pushdecl (decl);
   parm = build_tree_list (defval, parm);
   return chainon (list, parm);
@@ -238,8 +239,10 @@ end_template_decl (d1, d2, is_class, defn)
          DECL_CLASS_CONTEXT (decl) = DECL_CLASS_CONTEXT (d2);
          DECL_NAME (decl) = DECL_NAME (d2);
          TREE_TYPE (decl) = TREE_TYPE (d2);
-         if (interface_unknown && flag_external_templates && ! DECL_IN_SYSTEM_HEADER (decl))
-           warn_if_unknown_interface ();
+         if (interface_unknown && flag_external_templates
+             && ! flag_alt_external_templates
+             && ! DECL_IN_SYSTEM_HEADER (decl))
+           warn_if_unknown_interface (decl);
          TREE_PUBLIC (decl) = TREE_PUBLIC (d2) = flag_external_templates && !interface_unknown;
          DECL_EXTERNAL (decl) = (DECL_EXTERNAL (d2)
                                  && !(DECL_CLASS_CONTEXT (d2)
@@ -690,6 +693,7 @@ push_template_decls (parmlist, arglist, class_level)
        }
       if (decl != 0)
        {
+         SET_DECL_ARTIFICIAL (decl);
          layout_decl (decl, 0);
          if (class_level)
            pushdecl_class_level (decl);
@@ -1755,7 +1759,7 @@ instantiate_template (tmpl, targ_ptr)
                  = CLASSTYPE_INTERFACE_ONLY (DECL_CLASS_CONTEXT (fndecl));
              }
            else if (! DECL_IN_SYSTEM_HEADER (tmpl))
-             warn_if_unknown_interface ();
+             warn_if_unknown_interface (tmpl);
          }
 
        if (interface_unknown || ! flag_external_templates)
@@ -1850,7 +1854,7 @@ overload_template_name (id, classlevel)
     }
 #endif
 
-  t = xref_tag (tinfo->aggr, id, NULL_TREE, 0);
+  t = xref_tag (tinfo->aggr, id, NULL_TREE, 1);
   my_friendly_assert (TREE_CODE (t) == RECORD_TYPE
                      || TREE_CODE (t) == UNION_TYPE
                      || TREE_CODE (t) == UNINSTANTIATED_P_TYPE, 286);
index bb652c7387e58e1aae83f093ecba84a9e84d151e..4424423b07be775de44326048343b1bad36d2eb8 100644 (file)
@@ -31,6 +31,79 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
    Lvalues can be assigned, unless they have TREE_READONLY.
    Lvalues can have their address taken, unless they have DECL_REGISTER.  */
 
+int
+real_lvalue_p (ref)
+     tree ref;
+{
+  if (! language_lvalue_valid (ref))
+    return 0;
+  
+  if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
+    return 1;
+
+  if (ref == current_class_decl && flag_this_is_variable <= 0)
+    return 0;
+
+  switch (TREE_CODE (ref))
+    {
+      /* preincrements and predecrements are valid lvals, provided
+        what they refer to are valid lvals. */
+    case PREINCREMENT_EXPR:
+    case PREDECREMENT_EXPR:
+    case COMPONENT_REF:
+    case SAVE_EXPR:
+      return real_lvalue_p (TREE_OPERAND (ref, 0));
+
+    case STRING_CST:
+      return 1;
+
+    case VAR_DECL:
+      if (TREE_READONLY (ref) && ! TREE_STATIC (ref)
+         && DECL_LANG_SPECIFIC (ref)
+         && DECL_IN_AGGR_P (ref))
+       return 0;
+    case INDIRECT_REF:
+    case ARRAY_REF:
+    case PARM_DECL:
+    case RESULT_DECL:
+    case ERROR_MARK:
+      if (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE
+         && TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE)
+       return 1;
+      break;
+
+    case WITH_CLEANUP_EXPR:
+      return real_lvalue_p (TREE_OPERAND (ref, 0));
+
+      /* A currently unresolved scope ref.  */
+    case SCOPE_REF:
+      my_friendly_abort (103);
+    case OFFSET_REF:
+      if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL)
+       return 1;
+      return real_lvalue_p (TREE_OPERAND (ref, 0))
+       && real_lvalue_p (TREE_OPERAND (ref, 1));
+      break;
+
+    case COND_EXPR:
+      return (real_lvalue_p (TREE_OPERAND (ref, 1))
+             && real_lvalue_p (TREE_OPERAND (ref, 2)));
+
+    case MODIFY_EXPR:
+      return 1;
+
+    case COMPOUND_EXPR:
+      return real_lvalue_p (TREE_OPERAND (ref, 1));
+
+    case MAX_EXPR:
+    case MIN_EXPR:
+      return (real_lvalue_p (TREE_OPERAND (ref, 0))
+             && real_lvalue_p (TREE_OPERAND (ref, 1)));
+    }
+
+  return 0;
+}
+
 int
 lvalue_p (ref)
      tree ref;
@@ -496,6 +569,7 @@ propagate_binfo_offsets (binfo, offset)
                  chain = TREE_VEC_ELT (base_binfos, k);
                  TREE_VIA_PUBLIC (chain) = TREE_VIA_PUBLIC (base_base_binfo);
                  TREE_VIA_PROTECTED (chain) = TREE_VIA_PROTECTED (base_base_binfo);
+                 BINFO_INHERITANCE_CHAIN (chain) = base_binfo;
                }
              /* Now propagate the offset to the base types.  */
              propagate_binfo_offsets (base_binfo, offset);
@@ -616,6 +690,8 @@ layout_vbasetypes (rec, max)
     {
       tree base_binfos = BINFO_BASETYPES (vbase_types);
 
+      BINFO_INHERITANCE_CHAIN (vbase_types) = TYPE_BINFO (rec);
+
       if (base_binfos)
        {
          tree chain = NULL_TREE;
@@ -636,6 +712,7 @@ layout_vbasetypes (rec, max)
              chain = TREE_VEC_ELT (base_binfos, j);
              TREE_VIA_PUBLIC (chain) = TREE_VIA_PUBLIC (base_base_binfo);
              TREE_VIA_PROTECTED (chain) = TREE_VIA_PROTECTED (base_base_binfo);
+             BINFO_INHERITANCE_CHAIN (chain) = vbase_types;
            }
 
          propagate_binfo_offsets (vbase_types, BINFO_OFFSET (vbase_types));
@@ -1169,22 +1246,6 @@ make_binfo (offset, binfo, vtable, virtuals, chain)
   return new_binfo;
 }
 
-tree
-copy_binfo (list)
-     tree list;
-{
-  tree binfo = copy_list (list);
-  tree rval = binfo;
-  while (binfo)
-    {
-      TREE_USED (binfo) = 0;
-      if (BINFO_BASETYPES (binfo))
-       BINFO_BASETYPES (binfo) = copy_node (BINFO_BASETYPES (binfo));
-      binfo = TREE_CHAIN (binfo);
-    }
-  return rval;
-}
-
 /* Return the binfo value for ELEM in TYPE.  */
 
 tree
index 6642316e7b8f6facf42dd15d589edddc711afc6b..d36fa8d1ac856d7d8f928044a9d344a7d99f5aca 100644 (file)
@@ -2382,11 +2382,13 @@ build_function_call_real (function, params, require_complete, flags)
             function, coerced_params, NULL_TREE);
 
     TREE_SIDE_EFFECTS (result) = 1;
+
     if (! require_complete)
-      return result;
+      return convert_from_reference (result);
     if (value_type == void_type_node)
       return result;
-    return require_complete_type (result);
+    result = require_complete_type (result);
+    return convert_from_reference (result);
   }
 }
 
@@ -2463,6 +2465,9 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
       register tree type = typetail ? TREE_VALUE (typetail) : 0;
       register tree val = TREE_VALUE (valtail);
 
+      if (val == error_mark_node)
+       continue;
+
       if (type == void_type_node)
        {
          if (fndecl)
@@ -2987,9 +2992,6 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
     case TRUTH_AND_EXPR:
     case TRUTH_OR_EXPR:
       result_type = boolean_type_node;
-      op0 = bool_truthvalue_conversion (op0);
-      op1 = bool_truthvalue_conversion (op1);
-      converted = 1;
       break;
 
       /* Shift operations: result has same type as first operand;
@@ -3779,17 +3781,17 @@ build_x_unary_op (code, xarg)
   return build_unary_op (code, xarg, 0);
 }
 
-/* Just like truthvalue_conversion, but we want a BOOLEAN_TYPE */
+/* Just like truthvalue_conversion, but we want a CLEANUP_POINT_EXPR.  */
+   
 tree
-bool_truthvalue_conversion (expr)
+condition_conversion (expr)
      tree expr;
 {
-  /* We really want to preform the optimizations in truthvalue_conversion
-     but, not this way. */
-  /* expr = truthvalue_conversion (expr); */
-  return convert (boolean_type_node, expr);
+  tree t = convert (boolean_type_node, expr);
+  t = fold (build1 (CLEANUP_POINT_EXPR, boolean_type_node, t));
+  return t;
 }
-
+                              
 /* C++: Must handle pointers to members.
 
    Perhaps type instantiation should be extended to handle conversion
@@ -3927,7 +3929,7 @@ build_unary_op (code, xarg, noconvert)
       break;
 
     case TRUTH_NOT_EXPR:
-      arg = bool_truthvalue_conversion (arg);
+      arg = convert (boolean_type_node, arg);
       val = invert_truthvalue (arg);
       if (arg != error_mark_node)
        return val;
@@ -4538,7 +4540,7 @@ build_conditional_expr (ifexp, op1, op2)
       ifexp = op1 = save_expr (ifexp);
     }
 
-  ifexp = bool_truthvalue_conversion (ifexp);
+  ifexp = truthvalue_conversion (ifexp);
 
   if (TREE_CODE (ifexp) == ERROR_MARK)
     return error_mark_node;
@@ -4895,6 +4897,16 @@ build_compound_expr (list)
                break_out_cleanups (TREE_VALUE (list)), rest);
 }
 
+#ifdef __GNUC__
+__inline
+#endif
+int
+null_ptr_cst_p (t)
+     tree t;
+{
+  return (TREE_CODE (t) == INTEGER_CST && integer_zerop (t));
+}
+
 tree build_static_cast (type, expr)
    tree type, expr;
 {
@@ -4904,12 +4916,104 @@ tree build_static_cast (type, expr)
 tree build_reinterpret_cast (type, expr)
    tree type, expr;
 {
+  tree intype = TREE_TYPE (expr);
+
+  if (TYPE_PTRMEMFUNC_P (type))
+    type = TYPE_PTRMEMFUNC_FN_TYPE (type);
+  if (TYPE_PTRMEMFUNC_P (intype))
+    intype = TYPE_PTRMEMFUNC_FN_TYPE (intype);
+
+  if (! POINTER_TYPE_P (type) && ! TREE_CODE (type) == INTEGER_TYPE)
+    {
+      cp_error ("reinterpret_cast cannot convert to type `%T'", type);
+      return error_mark_node;
+    }
+  if (! POINTER_TYPE_P (intype) && ! TREE_CODE (intype) == INTEGER_TYPE)
+    {
+      cp_error ("reinterpret_cast cannot convert from type `%T'", type);
+      return error_mark_node;
+    }
+  if (TREE_CODE (type) == INTEGER_TYPE && TREE_CODE (intype) != POINTER_TYPE)
+    {
+      cp_error ("reinterpret_cast cannot convert non-pointer type `%T' to `%T'",
+               intype, type);
+      return error_mark_node;
+    }
+  if (TREE_CODE (intype) == INTEGER_TYPE && TREE_CODE (type) != POINTER_TYPE)
+    {
+      cp_error ("reinterpret_cast cannot convert `%T' to non-pointer type `%T'",
+               intype, type);
+      return error_mark_node;
+    }
+
+  if (TREE_CODE (type) == POINTER_TYPE && TREE_CODE (intype) == POINTER_TYPE)
+    expr = convert (ptr_type_node, expr);
+
   return build_c_cast (type, expr, 0);
 }
 
 tree build_const_cast (type, expr)
    tree type, expr;
 {
+  tree intype = TREE_TYPE (expr);
+  tree t1, t2;
+
+  if (TYPE_PTRMEMFUNC_P (type))
+    type = TYPE_PTRMEMFUNC_FN_TYPE (type);
+  if (TYPE_PTRMEMFUNC_P (intype))
+    intype = TYPE_PTRMEMFUNC_FN_TYPE (intype);
+
+  if (! POINTER_TYPE_P (type))
+    {
+      cp_error ("const_cast cannot convert to non-pointer type `%T'", type);
+      return error_mark_node;
+    }
+  if (TREE_CODE (type) == REFERENCE_TYPE && ! real_lvalue_p (expr))
+    {
+      cp_error ("const_cast cannot convert rvalue to type `%T'", type);
+      return error_mark_node;
+    }
+  if (TREE_CODE (type) == POINTER_TYPE && TREE_CODE (intype) != POINTER_TYPE)
+    {
+      cp_error ("const_cast cannot convert non-pointer type `%T' to type `%T'",
+               intype, type);
+      return error_mark_node;
+    }
+
+  if (TREE_CODE (type) == REFERENCE_TYPE)
+    {
+      t1 = TREE_TYPE (type);
+      t2 = intype;
+    }
+  else
+    {
+      t1 = TREE_TYPE (type);
+      t2 = TREE_TYPE (intype);
+
+      for (; TREE_CODE (t1) == POINTER_TYPE && TREE_CODE (t2) == POINTER_TYPE;
+          t1 = TREE_TYPE (t1), t2 = TREE_TYPE (t2))
+       ;
+    }
+
+  if (TREE_CODE (t1) == OFFSET_TYPE && TREE_CODE (t2) == OFFSET_TYPE)
+    {
+      if (TYPE_OFFSET_BASETYPE (t1) != TYPE_OFFSET_BASETYPE (t2))
+       {
+         cp_error ("const_cast cannot convert between pointers to members of different types `%T' and `%T'",
+                   TYPE_OFFSET_BASETYPE (t2), TYPE_OFFSET_BASETYPE (t1));
+         return error_mark_node;
+       }
+      t1 = TREE_TYPE (t1);
+      t2 = TREE_TYPE (t2);
+    }
+
+  if (TYPE_MAIN_VARIANT (t1) != TYPE_MAIN_VARIANT (t2))
+    {
+      cp_error ("const_cast cannot convert unrelated type `%T' to `%T'",
+               t2, t1);
+      return error_mark_node;
+    }
+
   return build_c_cast (type, expr, 0);
 }
 
@@ -4930,8 +5034,9 @@ build_c_cast (type, expr, allow_nonconverting)
     return error_mark_node;
 
   /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
-     Strip such NOP_EXPRs, since VALUE is being used in non-lvalue context.  */
-  if (TREE_CODE (value) == NOP_EXPR
+     Strip such NOP_EXPRs if VALUE is being used in non-lvalue context.  */
+  if (TREE_CODE (type) != REFERENCE_TYPE
+      && TREE_CODE (value) == NOP_EXPR
       && TREE_TYPE (value) == TREE_TYPE (TREE_OPERAND (value, 0)))
     value = TREE_OPERAND (value, 0);
 
@@ -4989,7 +5094,8 @@ build_c_cast (type, expr, allow_nonconverting)
     }
   else
     {
-      tree otype, ovalue;
+      tree otype;
+      int flag;
 
       /* Convert functions and arrays to pointers and
         convert references to their expanded types,
@@ -5041,17 +5147,28 @@ build_c_cast (type, expr, allow_nonconverting)
        warning ("cast to pointer from integer of different size");
 #endif
 
-      if (TREE_READONLY_DECL_P (value))
-       value = decl_constant_value (value);
+      flag = allow_nonconverting ? CONV_NONCONVERTING : 0;
 
-      ovalue = value;
-      value = convert_force (type, value, allow_nonconverting?CONV_NONCONVERTING:0);
-
-      /* Ignore any integer overflow caused by the cast.  */
-      if (TREE_CODE (value) == INTEGER_CST)
+      if (TREE_CODE (type) == REFERENCE_TYPE)
+       value = (convert_from_reference
+                (convert_to_reference (type, value, CONV_OLD_CONVERT|flag,
+                                       LOOKUP_COMPLAIN, NULL_TREE)));
+      else
        {
-         TREE_OVERFLOW (value) = TREE_OVERFLOW (ovalue);
-         TREE_CONSTANT_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (ovalue);
+         tree ovalue;
+
+         if (TREE_READONLY_DECL_P (value))
+           value = decl_constant_value (value);
+
+         ovalue = value;
+         value = convert_force (type, value, flag);
+
+         /* Ignore any integer overflow caused by the cast.  */
+         if (TREE_CODE (value) == INTEGER_CST)
+           {
+             TREE_OVERFLOW (value) = TREE_OVERFLOW (ovalue);
+             TREE_CONSTANT_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (ovalue);
+           }
        }
     }
 
@@ -5064,11 +5181,7 @@ build_c_cast (type, expr, allow_nonconverting)
          && TREE_CODE (value) == INTEGER_CST
          && TREE_CODE (expr) == INTEGER_CST
          && TREE_CODE (TREE_TYPE (expr)) != INTEGER_TYPE))
-    {
-      tree nvalue = build1 (NOP_EXPR, type, value);
-      TREE_CONSTANT (nvalue) = TREE_CONSTANT (value);
-      return nvalue;
-    }
+    value = non_lvalue (value);
 
   return value;
 }
@@ -5667,7 +5780,8 @@ build_modify_expr (lhs, modifycode, rhs)
     {
       if (flag_this_is_variable > 0
          && DECL_NAME (current_function_decl) != NULL_TREE
-         && current_class_name != DECL_NAME (current_function_decl))
+         && (DECL_NAME (current_function_decl)
+             != constructor_name (current_class_type)))
        warning ("assignment to `this' not in constructor or destructor");
       current_function_just_assigned_this = 1;
     }
@@ -6724,12 +6838,15 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
       rhs = resolve_offset_ref (rhs);
       if (rhs == error_mark_node)
        return error_mark_node;
-      rhstype = TREE_TYPE (rhs);
-      coder = TREE_CODE (rhstype);
     }
 
+  if (TREE_CODE (TREE_TYPE (rhs)) == REFERENCE_TYPE)
+    rhs = convert_from_reference (rhs);
+
   if ((TREE_CODE (TREE_TYPE (rhs)) == ARRAY_TYPE
-       && TREE_CODE (type) != ARRAY_TYPE && TREE_CODE (type) != REFERENCE_TYPE)
+       && TREE_CODE (type) != ARRAY_TYPE
+       && (TREE_CODE (type) != REFERENCE_TYPE
+          || TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE))
       || TREE_CODE (TREE_TYPE (rhs)) == FUNCTION_TYPE
       || TREE_CODE (TREE_TYPE (rhs)) == METHOD_TYPE)
     rhs = default_conversion (rhs);
@@ -7166,7 +7283,8 @@ c_expand_return (retval)
          /* Here is where we finally get RETVAL into RESULT.
             `expand_return' does the magic of protecting
             RESULT from cleanups.  */
-         retval = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (result), retval);
+         retval = fold (build1 (CLEANUP_POINT_EXPR, TREE_TYPE (result),
+                                retval));
          /* This part _must_ come second, because expand_return looks for
             the INIT_EXPR as the toplevel node only.  :-( */
          retval = build (INIT_EXPR, TREE_TYPE (result), result, retval);
@@ -7278,8 +7396,9 @@ c_expand_start_case (exp)
        exp = index;
     }
 
-  expand_start_case (1, build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp),
-                    type, "switch statement");
+  expand_start_case
+    (1, fold (build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp)),
+     type, "switch statement");
 
   return exp;
 }
index 5a52fd3a1a3ecfa5c81ef85daef7e6b01a81ea02..8a446c18f37017afe32b79c1e17c4ba678ede4e6 100644 (file)
@@ -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: 363.  Free: */
+/* First used: 0 (reserved), Last used: 364.  Free: */
 
 static int abortcount = 0;
 
@@ -379,65 +379,131 @@ my_friendly_assert (cond, where)
    for use in initializing a static variable; one that can be an
    element of a "constant" initializer.
 
-   Return 1 if the value is absolute; return 2 if it is relocatable.
+   Return null_pointer_node if the value is absolute;
+   if it is relocatable, return the variable that determines the relocation.
    We assume that VALUE has been folded as much as possible;
    therefore, we do not need to check for such things as
    arithmetic-combinations of integers.  */
 
-static int
-initializer_constant_valid_p (value)
+tree
+initializer_constant_valid_p (value, endtype)
      tree value;
+     tree endtype;
 {
   switch (TREE_CODE (value))
     {
     case CONSTRUCTOR:
-      return TREE_STATIC (value);
+      if (TREE_CODE (TREE_TYPE (value)) == UNION_TYPE
+         && TREE_CONSTANT (value))
+       return
+         initializer_constant_valid_p (TREE_VALUE (CONSTRUCTOR_ELTS (value)),
+                                       endtype);
+       
+      return TREE_STATIC (value) ? null_pointer_node : 0;
 
     case INTEGER_CST:
     case REAL_CST:
     case STRING_CST:
-      return 1;
+    case COMPLEX_CST:
+      return null_pointer_node;
 
     case ADDR_EXPR:
-      return 2;
+      return TREE_OPERAND (value, 0);
+
+    case NON_LVALUE_EXPR:
+      return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
 
     case CONVERT_EXPR:
     case NOP_EXPR:
-      /* Allow conversions between types of the same kind.  */
-      if (TREE_CODE (TREE_TYPE (value))
-         == TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))))
-       return initializer_constant_valid_p (TREE_OPERAND (value, 0));
+      /* Allow conversions between pointer types.  */
+      if (TREE_CODE (TREE_TYPE (value)) == POINTER_TYPE
+         && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == POINTER_TYPE)
+       return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
+
+      /* Allow conversions between real types.  */
+      if (TREE_CODE (TREE_TYPE (value)) == REAL_TYPE
+         && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == REAL_TYPE)
+       return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
+
+      /* Allow length-preserving conversions between integer types.  */
+      if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE
+         && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == INTEGER_TYPE
+         && (TYPE_PRECISION (TREE_TYPE (value))
+             == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0)))))
+       return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
+
+      /* Allow conversions between other integer types only if
+        explicit value.  */
+      if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE
+         && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == INTEGER_TYPE)
+       {
+         tree inner = initializer_constant_valid_p (TREE_OPERAND (value, 0),
+                                                    endtype);
+         if (inner == null_pointer_node)
+           return null_pointer_node;
+         return 0;
+       }
+
       /* Allow (int) &foo provided int is as wide as a pointer.  */
       if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE
          && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == POINTER_TYPE
-         && ! tree_int_cst_lt (TYPE_SIZE (TREE_TYPE (value)),
-                               TYPE_SIZE (TREE_TYPE (TREE_OPERAND (value, 0)))))
-       return initializer_constant_valid_p (TREE_OPERAND (value, 0));
+         && (TYPE_PRECISION (TREE_TYPE (value))
+             >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0)))))
+       return initializer_constant_valid_p (TREE_OPERAND (value, 0),
+                                            endtype);
+
+      /* Likewise conversions from int to pointers.  */
+      if (TREE_CODE (TREE_TYPE (value)) == POINTER_TYPE
+         && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == INTEGER_TYPE
+         && (TYPE_PRECISION (TREE_TYPE (value))
+             <= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0)))))
+       return initializer_constant_valid_p (TREE_OPERAND (value, 0),
+                                            endtype);
+
+      /* Allow conversions to union types if the value inside is okay.  */
+      if (TREE_CODE (TREE_TYPE (value)) == UNION_TYPE)
+       return initializer_constant_valid_p (TREE_OPERAND (value, 0),
+                                            endtype);
       return 0;
 
     case PLUS_EXPR:
+      if (TREE_CODE (endtype) == INTEGER_TYPE
+         && TYPE_PRECISION (endtype) < POINTER_SIZE)
+       return 0;
       {
-       int valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0));
-       int valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1));
-       if (valid0 == 1 && valid1 == 2)
-         return 2;
-       if (valid0 == 2 && valid1 == 1)
-         return 2;
+       tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
+                                                   endtype);
+       tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1),
+                                                   endtype);
+       /* If either term is absolute, use the other terms relocation.  */
+       if (valid0 == null_pointer_node)
+         return valid1;
+       if (valid1 == null_pointer_node)
+         return valid0;
        return 0;
       }
 
     case MINUS_EXPR:
+      if (TREE_CODE (endtype) == INTEGER_TYPE
+         && TYPE_PRECISION (endtype) < POINTER_SIZE)
+       return 0;
       {
-       int valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0));
-       int valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1));
-       if (valid0 == 2 && valid1 == 1)
-         return 2;
+       tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
+                                                   endtype);
+       tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1),
+                                                   endtype);
+       /* Win if second argument is absolute.  */
+       if (valid1 == null_pointer_node)
+         return valid0;
+       /* Win if both arguments have the same relocation.
+          Then the value is absolute.  */
+       if (valid0 == valid1)
+         return null_pointer_node;
        return 0;
       }
-
-    default:
-      return 0;
     }
+
+  return 0;
 }
 \f
 /* Perform appropriate conversions on the initial value of a variable,
@@ -583,7 +649,7 @@ store_init_value (decl, init)
     ;
   else if (TREE_STATIC (decl)
           && (! TREE_CONSTANT (value)
-              || ! initializer_constant_valid_p (value)
+              || ! initializer_constant_valid_p (value, TREE_TYPE (value))
 #if 0
               /* A STATIC PUBLIC int variable doesn't have to be
                  run time inited when doing pic.  (mrs) */
@@ -920,7 +986,7 @@ process_init_constructor (type, init, elts)
            erroneous = 1;
          else if (!TREE_CONSTANT (next1))
            allconstant = 0;
-         else if (! initializer_constant_valid_p (next1))
+         else if (! initializer_constant_valid_p (next1, TREE_TYPE (next1)))
            allsimple = 0;
          members = tree_cons (NULL_TREE, next1, members);
        }
@@ -984,7 +1050,7 @@ process_init_constructor (type, init, elts)
            erroneous = 1;
          else if (!TREE_CONSTANT (next1))
            allconstant = 0;
-         else if (! initializer_constant_valid_p (next1))
+         else if (! initializer_constant_valid_p (next1, TREE_TYPE (next1)))
            allsimple = 0;
          members = tree_cons (field, next1, members);
        }
@@ -1001,7 +1067,7 @@ process_init_constructor (type, init, elts)
                erroneous = 1;
              else if (!TREE_CONSTANT (next1))
                allconstant = 0;
-             else if (! initializer_constant_valid_p (next1))
+             else if (! initializer_constant_valid_p (next1, TREE_TYPE (next1)))
                allsimple = 0;
              members = tree_cons (field, next1, members);
            }
@@ -1082,7 +1148,7 @@ process_init_constructor (type, init, elts)
        erroneous = 1;
       else if (!TREE_CONSTANT (next1))
        allconstant = 0;
-      else if (initializer_constant_valid_p (next1) == 0)
+      else if (initializer_constant_valid_p (next1, TREE_TYPE (next1)) == 0)
        allsimple = 0;
       members = tree_cons (field, next1, members);
     }
@@ -1425,11 +1491,13 @@ build_functional_cast (exp, parms)
       /* this must build a C cast */
       if (parms == NULL_TREE)
        parms = integer_zero_node;
-      else if (TREE_CHAIN (parms) != NULL_TREE)
+      else
        {
-         pedwarn ("initializer list being treated as compound expression");
+         if (TREE_CHAIN (parms) != NULL_TREE)
+           pedwarn ("initializer list being treated as compound expression");
          parms = build_compound_expr (parms);
        }
+
       return build_c_cast (type, parms, 1);
     }