OSDN Git Service

* class.c (build_base_path): Use build_address directly.
[pf3gnuchains/gcc-fork.git] / gcc / cp / typeck.c
index 32447b6..e62db90 100644 (file)
@@ -1,6 +1,6 @@
 /* Build expressions with type checking for C++ compiler.
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
    Hacked by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GCC.
@@ -24,11 +24,7 @@ Boston, MA 02111-1307, USA.  */
 /* This file is part of the C++ front end.
    It contains routines to build C++ expressions given their operands,
    including computing the types of the result, C and C++ specific error
-   checks, and some optimization.
-
-   There are also routines to build RETURN_STMT nodes and CASE_STMT nodes,
-   and to process initializations in declarations (since they work
-   like a strange sort of assignment).  */
+   checks, and some optimization.  */
 
 #include "config.h"
 #include "system.h"
@@ -54,7 +50,6 @@ static int comp_ptr_ttypes_const (tree, tree);
 static bool comp_except_types (tree, tree, bool);
 static bool comp_array_types (tree, tree, bool);
 static tree common_base_type (tree, tree);
-static tree lookup_anon_field (tree, tree);
 static tree pointer_diff (tree, tree, tree);
 static tree get_delta_difference (tree, tree, int);
 static void casts_away_constness_r (tree *, tree *);
@@ -96,6 +91,9 @@ require_complete_type (tree value)
   else
     type = TREE_TYPE (value);
 
+  if (type == error_mark_node)
+    return error_mark_node;
+
   /* First, detect a valid value with a complete type.  */
   if (COMPLETE_TYPE_P (type))
     return value;
@@ -124,7 +122,7 @@ complete_type (tree type)
   else if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type))
     {
       tree t = complete_type (TREE_TYPE (type));
-      if (COMPLETE_TYPE_P (t) && ! processing_template_decl)
+      if (COMPLETE_TYPE_P (t) && !dependent_type_p (type))
        layout_type (type);
       TYPE_NEEDS_CONSTRUCTING (type)
        = TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (t));
@@ -163,8 +161,7 @@ complete_type_or_diagnostic (tree type, tree value, int diag_type)
 int
 type_unknown_p (tree exp)
 {
-  return (TREE_CODE (exp) == OVERLOAD
-          || TREE_CODE (exp) == TREE_LIST
+  return (TREE_CODE (exp) == TREE_LIST
          || TREE_TYPE (exp) == unknown_type_node);
 }
 
@@ -265,14 +262,12 @@ type_after_usual_arithmetic_conversions (tree t1, tree t2)
   tree attributes;
 
   /* FIXME: Attributes.  */
-  my_friendly_assert (ARITHMETIC_TYPE_P (t1) 
-                     || TREE_CODE (t1) == COMPLEX_TYPE
-                     || TREE_CODE (t1) == ENUMERAL_TYPE,
-                     19990725);
-  my_friendly_assert (ARITHMETIC_TYPE_P (t2) 
-                     || TREE_CODE (t2) == COMPLEX_TYPE
-                     || TREE_CODE (t2) == ENUMERAL_TYPE,
-                     19990725);
+  gcc_assert (ARITHMETIC_TYPE_P (t1) 
+             || TREE_CODE (t1) == COMPLEX_TYPE
+             || TREE_CODE (t1) == ENUMERAL_TYPE);
+  gcc_assert (ARITHMETIC_TYPE_P (t2) 
+             || TREE_CODE (t2) == COMPLEX_TYPE
+             || TREE_CODE (t2) == ENUMERAL_TYPE);
 
   /* In what follows, we slightly generalize the rules given in [expr] so
      as to deal with `long long' and `complex'.  First, merge the
@@ -348,7 +343,7 @@ type_after_usual_arithmetic_conversions (tree t1, tree t2)
       if (same_type_p (TYPE_MAIN_VARIANT (t1), long_long_integer_type_node)
          || same_type_p (TYPE_MAIN_VARIANT (t2), long_long_integer_type_node))
        {
-         tree t = ((TREE_UNSIGNED (t1) || TREE_UNSIGNED (t2))
+         tree t = ((TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
                    ? long_long_unsigned_type_node 
                    : long_long_integer_type_node);
          return build_type_attribute_variant (t, attributes);
@@ -362,12 +357,12 @@ type_after_usual_arithmetic_conversions (tree t1, tree t2)
       if (same_type_p (TYPE_MAIN_VARIANT (t1), long_integer_type_node)
          || same_type_p (TYPE_MAIN_VARIANT (t2), long_integer_type_node))
        {
-         tree t = ((TREE_UNSIGNED (t1) || TREE_UNSIGNED (t2))
+         tree t = ((TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
                    ? long_unsigned_type_node : long_integer_type_node);
          return build_type_attribute_variant (t, attributes);
        }
       /* Otherwise prefer the unsigned one.  */
-      if (TREE_UNSIGNED (t1))
+      if (TYPE_UNSIGNED (t1))
        return build_type_attribute_variant (t1, attributes);
       else
        return build_type_attribute_variant (t2, attributes);
@@ -443,7 +438,6 @@ composite_pointer_type_r (tree t1, tree t2, const char* location)
   result_type = cp_build_qualified_type (result_type,
                                         (cp_type_quals (pointee1)
                                          | cp_type_quals (pointee2)));
-  result_type = build_pointer_type (result_type);
   /* If the original types were pointers to members, so is the
      result.  */
   if (TYPE_PTR_TO_MEMBER_P (t1))
@@ -456,6 +450,8 @@ composite_pointer_type_r (tree t1, tree t2, const char* location)
       result_type = build_ptrmem_type (TYPE_PTRMEM_CLASS_TYPE (t1),
                                       result_type);
     }
+  else
+    result_type = build_pointer_type (result_type);
 
   /* Merge the attributes.  */
   attributes = (*targetm.merge_type_attributes) (t1, t2);
@@ -579,8 +575,8 @@ composite_pointer_type (tree t1, tree t2, tree arg1, tree arg2,
 tree
 merge_types (tree t1, tree t2)
 {
-  register enum tree_code code1;
-  register enum tree_code code2;
+  enum tree_code code1;
+  enum tree_code code2;
   tree attributes;
 
   /* Save time if the two types are the same.  */
@@ -666,9 +662,9 @@ merge_types (tree t1, tree t2)
 
        /* Save space: see if the result is identical to one of the args.  */
        if (valtype == TREE_TYPE (t1) && ! p2)
-         return build_type_attribute_variant (t1, attributes);
+         return cp_build_type_attribute_variant (t1, attributes);
        if (valtype == TREE_TYPE (t2) && ! p1)
-         return build_type_attribute_variant (t2, attributes);
+         return cp_build_type_attribute_variant (t2, attributes);
 
        /* Simple way if one arg fails to specify argument types.  */
        if (p1 == NULL_TREE || TREE_VALUE (p1) == void_type_node)
@@ -676,7 +672,7 @@ merge_types (tree t1, tree t2)
            rval = build_function_type (valtype, p2);
            if ((raises = TYPE_RAISES_EXCEPTIONS (t2)))
              rval = build_exception_variant (rval, raises);
-           return build_type_attribute_variant (rval, attributes);
+           return cp_build_type_attribute_variant (rval, attributes);
          }
        raises = TYPE_RAISES_EXCEPTIONS (t1);
        if (p2 == NULL_TREE || TREE_VALUE (p2) == void_type_node)
@@ -684,7 +680,7 @@ merge_types (tree t1, tree t2)
            rval = build_function_type (valtype, p1);
            if (raises)
              rval = build_exception_variant (rval, raises);
-           return build_type_attribute_variant (rval, attributes);
+           return cp_build_type_attribute_variant (rval, attributes);
          }
 
        rval = build_function_type (valtype, commonparms (p1, p2));
@@ -714,9 +710,15 @@ merge_types (tree t1, tree t2)
        break;
       }
 
+    case TYPENAME_TYPE:
+      /* There is no need to merge attributes into a TYPENAME_TYPE.
+        When the type is instantiated it will have whatever
+        attributes result from the instantiation.  */
+      return t1;
+
     default:;
     }
-  return build_type_attribute_variant (t1, attributes);
+  return cp_build_type_attribute_variant (t1, attributes);
 }
 
 /* Return the common type of two types.
@@ -751,7 +753,7 @@ common_type (tree t1, tree t2)
     return composite_pointer_type (t1, t2, error_mark_node, error_mark_node,
                                   "conversion");
   else
-    abort ();
+    gcc_unreachable ();
 }
 \f
 /* Compare two exception specifier types for exactness or subsetness, if
@@ -857,6 +859,7 @@ comp_array_types (tree t1, tree t2, bool allow_redeclaration)
 {
   tree d1;
   tree d2;
+  tree max1, max2;
 
   if (t1 == t2)
     return true;
@@ -887,8 +890,27 @@ comp_array_types (tree t1, tree t2, bool allow_redeclaration)
     return allow_redeclaration;
 
   /* Check that the dimensions are the same.  */
-  return (cp_tree_equal (TYPE_MIN_VALUE (d1), TYPE_MIN_VALUE (d2))
-         && cp_tree_equal (TYPE_MAX_VALUE (d1), TYPE_MAX_VALUE (d2)));
+
+  if (!cp_tree_equal (TYPE_MIN_VALUE (d1), TYPE_MIN_VALUE (d2)))
+    return false;
+  max1 = TYPE_MAX_VALUE (d1);
+  max2 = TYPE_MAX_VALUE (d2);
+  if (processing_template_decl && !abi_version_at_least (2)
+      && !value_dependent_expression_p (max1)
+      && !value_dependent_expression_p (max2))
+    {
+      /* With abi-1 we do not fold non-dependent array bounds, (and
+         consequently mangle them incorrectly).  We must therefore
+         fold them here, to verify the domains have the same
+         value.  */
+      max1 = fold (max1);
+      max2 = fold (max2);
+    }
+
+  if (!cp_tree_equal (max1, max2))
+    return false;
+
+  return true;
 }
 
 /* Return true if T1 and T2 are related as allowed by STRICT.  STRICT
@@ -900,11 +922,11 @@ comptypes (tree t1, tree t2, int strict)
   if (t1 == t2)
     return true;
 
-  /* Suppress errors caused by previously reported errors */
+  /* Suppress errors caused by previously reported errors */
   if (t1 == error_mark_node || t2 == error_mark_node)
     return false;
   
-  my_friendly_assert (TYPE_P (t1) && TYPE_P (t2), 20030623);
+  gcc_assert (TYPE_P (t1) && TYPE_P (t2));
   
   /* TYPENAME_TYPEs should be resolved if the qualifying scope is the
      current instantiation.  */
@@ -927,12 +949,12 @@ comptypes (tree t1, tree t2, int strict)
   /* If either type is the internal version of sizetype, use the
      language version.  */
   if (TREE_CODE (t1) == INTEGER_TYPE && TYPE_IS_SIZETYPE (t1)
-      && TYPE_DOMAIN (t1))
-    t1 = TYPE_DOMAIN (t1);
+      && TYPE_ORIG_SIZE_TYPE (t1))
+    t1 = TYPE_ORIG_SIZE_TYPE (t1);
 
   if (TREE_CODE (t2) == INTEGER_TYPE && TYPE_IS_SIZETYPE (t2)
-      && TYPE_DOMAIN (t2))
-    t2 = TYPE_DOMAIN (t2);
+      && TYPE_ORIG_SIZE_TYPE (t2))
+    t2 = TYPE_ORIG_SIZE_TYPE (t2);
 
   if (TYPE_PTRMEMFUNC_P (t1))
     t1 = TYPE_PTRMEMFUNC_FN_TYPE (t1);
@@ -943,8 +965,10 @@ comptypes (tree t1, tree t2, int strict)
   if (TREE_CODE (t1) != TREE_CODE (t2))
     return false;
 
-  /* Qualifiers must match.  */
-  if (cp_type_quals (t1) != cp_type_quals (t2))
+  /* Qualifiers must match.  For array types, we will check when we
+     recur on the array element types.  */
+  if (TREE_CODE (t1) != ARRAY_TYPE
+      && TYPE_QUALS (t1) != TYPE_QUALS (t2))
     return false;
   if (TYPE_FOR_JAVA (t1) != TYPE_FOR_JAVA (t2))
     return false;
@@ -953,7 +977,8 @@ comptypes (tree t1, tree t2, int strict)
      definition.  Note that we already checked for equality of the type
      qualifiers (just above).  */
 
-  if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
+  if (TREE_CODE (t1) != ARRAY_TYPE
+      && TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
     return true;
 
   if (!(*targetm.comp_type_attributes) (t1, t2))
@@ -974,7 +999,7 @@ comptypes (tree t1, tree t2, int strict)
        return true;
       /* Don't check inheritance.  */
       strict = COMPARE_STRICT;
-      /* fall through */
+      /* Fall through.  */
 
     case RECORD_TYPE:
     case UNION_TYPE:
@@ -995,7 +1020,7 @@ comptypes (tree t1, tree t2, int strict)
       if (!comptypes (TYPE_OFFSET_BASETYPE (t1), TYPE_OFFSET_BASETYPE (t2),
                      strict & ~COMPARE_REDECLARATION))
        return false;
-      /* FALLTHROUGH*/
+      /* Fall through.  */
 
     case POINTER_TYPE:
     case REFERENCE_TYPE:
@@ -1029,6 +1054,11 @@ comptypes (tree t1, tree t2, int strict)
     case COMPLEX_TYPE:
       return same_type_p (TREE_TYPE (t1), TREE_TYPE (t2));
 
+    case VECTOR_TYPE:
+      return TYPE_VECTOR_SUBPARTS (t1) == TYPE_VECTOR_SUBPARTS (t2)
+            && same_type_p (TREE_TYPE (t1), TREE_TYPE (t2));
+      break;
+
     default:
       break;
     }
@@ -1111,10 +1141,11 @@ common_base_type (tree tt1, tree tt2)
 
   /* Otherwise, try to find a unique baseclass of TT1
      that is shared by TT2, and follow that down.  */
-  for (i = CLASSTYPE_N_BASECLASSES (tt1)-1; i >= 0; i--)
+  for (i = BINFO_N_BASE_BINFOS (TYPE_BINFO (tt1))-1; i >= 0; i--)
     {
-      tree basetype = TYPE_BINFO_BASETYPE (tt1, i);
+      tree basetype = BINFO_TYPE (BINFO_BASE_BINFO (TYPE_BINFO (tt1), i));
       tree trial = common_base_type (basetype, tt2);
+      
       if (trial)
        {
          if (trial == error_mark_node)
@@ -1127,10 +1158,11 @@ common_base_type (tree tt1, tree tt2)
     }
 
   /* Same for TT2.  */
-  for (i = CLASSTYPE_N_BASECLASSES (tt2)-1; i >= 0; i--)
+  for (i = BINFO_N_BASE_BINFOS (TYPE_BINFO (tt2))-1; i >= 0; i--)
     {
-      tree basetype = TYPE_BINFO_BASETYPE (tt2, i);
+      tree basetype = BINFO_TYPE (BINFO_BASE_BINFO (TYPE_BINFO (tt2), i));
       tree trial = common_base_type (tt1, basetype);
+      
       if (trial)
        {
          if (trial == error_mark_node)
@@ -1184,7 +1216,7 @@ cxx_sizeof_or_alignof_type (tree type, enum tree_code op, bool complain)
   tree value;
   const char *op_name;
 
-  my_friendly_assert (op == SIZEOF_EXPR || op == ALIGNOF_EXPR, 20020720);
+  gcc_assert (op == SIZEOF_EXPR || op == ALIGNOF_EXPR);
   if (type == error_mark_node)
     return error_mark_node;
   
@@ -1233,6 +1265,7 @@ cxx_sizeof_or_alignof_expr (tree e, enum tree_code op)
     }
   
   if (TREE_CODE (e) == COMPONENT_REF
+      && TREE_CODE (TREE_OPERAND (e, 1)) == FIELD_DECL
       && DECL_C_BIT_FIELD (TREE_OPERAND (e, 1)))
     {
       error ("invalid application of `%s' to a bit-field", op_name);
@@ -1255,6 +1288,33 @@ cxx_sizeof_or_alignof_expr (tree e, enum tree_code op)
 }
   
 \f
+/* EXPR is being used in a context that is not a function call.
+   Enforce:
+
+     [expr.ref] 
+
+     The expression can be used only as the left-hand operand of a
+     member function call.  
+
+     [expr.mptr.operator]
+
+     If the result of .* or ->* is a function, then that result can be
+     used only as the operand for the function call operator ().  
+
+   by issuing an error message if appropriate.  Returns true iff EXPR
+   violates these rules.  */
+
+bool
+invalid_nonstatic_memfn_p (tree expr)
+{
+  if (TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE)
+    {
+      error ("invalid use of non-static member function");
+      return true;
+    }
+  return false;
+}
+
 /* Perform the conversions in [expr] that apply when an lvalue appears
    in an rvalue context: the lvalue-to-rvalue, array-to-pointer, and
    function-to-pointer conversions.
@@ -1264,8 +1324,8 @@ cxx_sizeof_or_alignof_expr (tree e, enum tree_code op)
 tree
 decay_conversion (tree exp)
 {
-  register tree type;
-  register enum tree_code code;
+  tree type;
+  enum tree_code code;
 
   type = TREE_TYPE (exp);
   code = TREE_CODE (type);
@@ -1307,16 +1367,13 @@ decay_conversion (tree exp)
       error ("void value not ignored as it ought to be");
       return error_mark_node;
     }
-  if (code == METHOD_TYPE)
-    {
-      error ("invalid use of non-static member function");
-      return error_mark_node;
-    }
+  if (invalid_nonstatic_memfn_p (exp))
+    return error_mark_node;
   if (code == FUNCTION_TYPE || is_overloaded_fn (exp))
     return build_unary_op (ADDR_EXPR, exp, 0);
   if (code == ARRAY_TYPE)
     {
-      register tree adr;
+      tree adr;
       tree ptrtype;
 
       if (TREE_CODE (exp) == INDIRECT_REF)
@@ -1326,8 +1383,8 @@ decay_conversion (tree exp)
       if (TREE_CODE (exp) == COMPOUND_EXPR)
        {
          tree op1 = decay_conversion (TREE_OPERAND (exp, 1));
-         return build (COMPOUND_EXPR, TREE_TYPE (op1),
-                       TREE_OPERAND (exp, 0), op1);
+         return build2 (COMPOUND_EXPR, TREE_TYPE (op1),
+                        TREE_OPERAND (exp, 0), op1);
        }
 
       if (!lvalue_p (exp)
@@ -1341,15 +1398,9 @@ decay_conversion (tree exp)
 
       if (TREE_CODE (exp) == VAR_DECL)
        {
-         /* ??? This is not really quite correct
-            in that the type of the operand of ADDR_EXPR
-            is not the target type of the type of the ADDR_EXPR itself.
-            Question is, can this lossage be avoided?  */
-         adr = build1 (ADDR_EXPR, ptrtype, exp);
          if (!cxx_mark_addressable (exp))
            return error_mark_node;
-         TREE_CONSTANT (adr) = staticp (exp);
-         TREE_SIDE_EFFECTS (adr) = 0;   /* Default would be, same as EXP.  */
+         adr = build_nop (ptrtype, build_address (exp));
          return adr;
        }
       /* This way is better for a COMPONENT_REF since it can
@@ -1388,7 +1439,7 @@ perform_integral_promotions (tree expr)
   tree promoted_type;
 
   type = TREE_TYPE (expr);
-  my_friendly_assert (INTEGRAL_OR_ENUMERATION_TYPE_P (type), 20030703);
+  gcc_assert (INTEGRAL_OR_ENUMERATION_TYPE_P (type));
   promoted_type = type_promotes_to (type);
   if (type != promoted_type)
     expr = cp_convert (promoted_type, expr);
@@ -1468,7 +1519,8 @@ rationalize_conditional_expr (enum tree_code code, tree t)
        build_conditional_expr (build_x_binary_op ((TREE_CODE (t) == MIN_EXPR
                                                    ? LE_EXPR : GE_EXPR),
                                                   TREE_OPERAND (t, 0),
-                                                  TREE_OPERAND (t, 1)),
+                                                  TREE_OPERAND (t, 1),
+                                                  /*overloaded_p=*/NULL),
                            build_unary_op (code, TREE_OPERAND (t, 0), 0),
                            build_unary_op (code, TREE_OPERAND (t, 1), 0));
     }
@@ -1484,7 +1536,7 @@ rationalize_conditional_expr (enum tree_code code, tree t)
    anonymous unions can nest, we must also search all anonymous unions
    that are directly reachable.  */
 
-static tree
+tree
 lookup_anon_field (tree t, tree type)
 {
   tree field;
@@ -1541,15 +1593,15 @@ build_class_member_access_expr (tree object, tree member,
   if (TREE_CODE (member) == PSEUDO_DTOR_EXPR)
     return member;
 
-  my_friendly_assert (DECL_P (member) || BASELINK_P (member),
-                     20020801);
+  gcc_assert (DECL_P (member) || BASELINK_P (member));
 
   /* [expr.ref]
 
      The type of the first expression shall be "class object" (of a
      complete type).  */
   object_type = TREE_TYPE (object);
-  if (!complete_type_or_else (object_type, object))
+  if (!currently_open_class (object_type) 
+      && !complete_type_or_else (object_type, object))
     return error_mark_node;
   if (!CLASS_TYPE_P (object_type))
     {
@@ -1603,7 +1655,7 @@ build_class_member_access_expr (tree object, tree member,
       result = member;
       /* If OBJECT has side-effects, they are supposed to occur.  */
       if (TREE_SIDE_EFFECTS (object))
-       result = build (COMPOUND_EXPR, TREE_TYPE (result), object, result);
+       result = build2 (COMPOUND_EXPR, TREE_TYPE (result), object, result);
     }
   else if (TREE_CODE (member) == FIELD_DECL)
     {
@@ -1643,8 +1695,7 @@ build_class_member_access_expr (tree object, tree member,
                                    /*nonnull=*/1);
          /* If we found the base successfully then we should be able
             to convert to it successfully.  */
-         my_friendly_assert (object != error_mark_node,
-                             20020801);
+         gcc_assert (object != error_mark_node);
        }
 
       /* Complain about other invalid uses of offsetof, even though they will
@@ -1652,7 +1703,8 @@ build_class_member_access_expr (tree object, tree member,
         actually used the offsetof macro, since there's no way to know at this
         point.  So we just give a warning, instead of a pedwarn.  */
       if (null_object_p && warn_invalid_offsetof
-         && CLASSTYPE_NON_POD_P (object_type))
+         && CLASSTYPE_NON_POD_P (object_type)
+         && ! skip_evaluation)
        {
          warning ("invalid access to non-static data member `%D' of NULL object", 
                   member);
@@ -1699,7 +1751,8 @@ build_class_member_access_expr (tree object, tree member,
          member_type = cp_build_qualified_type (member_type, type_quals);
        }
 
-      result = fold (build (COMPONENT_REF, member_type, object, member));
+      result = fold (build3 (COMPONENT_REF, member_type, object, member,
+                            NULL_TREE));
 
       /* Mark the expression const or volatile, as appropriate.  Even
         though we've dealt with the type above, we still have to mark the
@@ -1726,7 +1779,7 @@ build_class_member_access_expr (tree object, tree member,
        type = unknown_type_node;
       /* Note that we do not convert OBJECT to the BASELINK_BINFO
         base.  That will happen when the function is called.  */
-      result = build (COMPONENT_REF, type, object, member);
+      result = build3 (COMPONENT_REF, type, object, member, NULL_TREE);
     }
   else if (TREE_CODE (member) == CONST_DECL)
     {
@@ -1734,8 +1787,8 @@ build_class_member_access_expr (tree object, tree member,
       result = member;
       /* If OBJECT has side-effects, they are supposed to occur.  */
       if (TREE_SIDE_EFFECTS (object))
-       result = build (COMPOUND_EXPR, TREE_TYPE (result),
-                       object, result);
+       result = build2 (COMPOUND_EXPR, TREE_TYPE (result),
+                        object, result);
     }
   else
     {
@@ -1761,6 +1814,7 @@ lookup_destructor (tree object, tree scope, tree dtor_name)
 {
   tree object_type = TREE_TYPE (object);
   tree dtor_type = TREE_OPERAND (dtor_name, 0);
+  tree expr;
 
   if (scope && !check_dtor_name (scope, dtor_name))
     {
@@ -1768,17 +1822,20 @@ lookup_destructor (tree object, tree scope, tree dtor_name)
             scope, dtor_type);
       return error_mark_node;
     }
-  if (!same_type_p (dtor_type, TYPE_MAIN_VARIANT (object_type)))
+  if (!DERIVED_FROM_P (dtor_type, TYPE_MAIN_VARIANT (object_type)))
     {
-      error ("destructor name `%T' does not match type `%T' of expression",
-            dtor_type, object_type);
+      error ("the type being destroyed is `%T', but the destructor refers to `%T'",
+            TYPE_MAIN_VARIANT (object_type), dtor_type);
       return error_mark_node;
     }
-  if (!TYPE_HAS_DESTRUCTOR (object_type))
-    return build (PSEUDO_DTOR_EXPR, void_type_node, object, scope,
-                 dtor_type);
-  return lookup_member (object_type, complete_dtor_identifier,
+  if (!TYPE_HAS_DESTRUCTOR (dtor_type))
+    return build3 (PSEUDO_DTOR_EXPR, void_type_node, object, scope,
+                  dtor_type);
+  expr = lookup_member (dtor_type, complete_dtor_identifier,
                        /*protect=*/1, /*want_type=*/false);
+  expr = (adjust_result_of_qualified_name_lookup
+         (expr, dtor_type, object_type));
+  return expr;
 }
 
 /* This function is called by the parser to process a class member
@@ -1808,6 +1865,9 @@ finish_class_member_access_expr (tree object, tree name)
     {
       if (/* If OBJECT_TYPE is dependent, so is OBJECT.NAME.  */
          dependent_type_p (object_type)
+         /* If NAME is just an IDENTIFIER_NODE, then the expression
+            is dependent.  */
+         || TREE_CODE (object) == IDENTIFIER_NODE
          /* If NAME is "f<args>", where either 'f' or 'args' is
             dependent, then the expression is dependent.  */
          || (TREE_CODE (name) == TEMPLATE_ID_EXPR
@@ -1818,7 +1878,7 @@ finish_class_member_access_expr (tree object, tree name)
          || (TREE_CODE (name) == SCOPE_REF
              && TYPE_P (TREE_OPERAND (name, 0))
              && dependent_type_p (TREE_OPERAND (name, 0))))
-       return build_min_nt (COMPONENT_REF, object, name);
+       return build_min_nt (COMPONENT_REF, object, name, NULL_TREE);
       object = build_non_dependent_expr (object);
     }
   
@@ -1832,7 +1892,8 @@ finish_class_member_access_expr (tree object, tree name)
 
      The type of the first expression shall be "class object" (of a
      complete type).  */
-  if (!complete_type_or_else (object_type, object))
+  if (!currently_open_class (object_type) 
+      && !complete_type_or_else (object_type, object))
     return error_mark_node;
   if (!CLASS_TYPE_P (object_type))
     {
@@ -1844,9 +1905,7 @@ finish_class_member_access_expr (tree object, tree name)
   if (BASELINK_P (name))
     {
       /* A member function that has already been looked up.  */
-      my_friendly_assert ((TREE_CODE (BASELINK_FUNCTIONS (name)) 
-                          == TEMPLATE_ID_EXPR), 
-                         20020805);
+      gcc_assert (TREE_CODE (BASELINK_FUNCTIONS (name)) == TEMPLATE_ID_EXPR);
       member = name;
     }
   else
@@ -1860,6 +1919,11 @@ finish_class_member_access_expr (tree object, tree name)
          is_template_id = true;
          template_args = TREE_OPERAND (name, 1);
          name = TREE_OPERAND (name, 0);
+
+         if (TREE_CODE (name) == OVERLOAD)
+           name = DECL_NAME (get_first_fn (name));
+         else if (DECL_P (name))
+           name = DECL_NAME (name);
        }
 
       if (TREE_CODE (name) == SCOPE_REF)
@@ -1870,12 +1934,10 @@ finish_class_member_access_expr (tree object, tree name)
             or a BIT_NOT_EXPR.  */
          scope = TREE_OPERAND (name, 0);
          name = TREE_OPERAND (name, 1);
-         my_friendly_assert ((CLASS_TYPE_P (scope) 
-                              || TREE_CODE (scope) == NAMESPACE_DECL),
-                             20020804);
-         my_friendly_assert ((TREE_CODE (name) == IDENTIFIER_NODE
-                              || TREE_CODE (name) == BIT_NOT_EXPR),
-                             20020804);
+         gcc_assert (CLASS_TYPE_P (scope)
+                     || TREE_CODE (scope) == NAMESPACE_DECL);
+         gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE
+                     || TREE_CODE (name) == BIT_NOT_EXPR);
 
          /* If SCOPE is a namespace, then the qualified name does not
             name a member of OBJECT_TYPE.  */
@@ -1888,8 +1950,13 @@ finish_class_member_access_expr (tree object, tree name)
 
          /* Find the base of OBJECT_TYPE corresponding to SCOPE.  */
          access_path = lookup_base (object_type, scope, ba_check, NULL);
-         if (!access_path || access_path == error_mark_node)
+         if (access_path == error_mark_node)
            return error_mark_node;
+         if (!access_path)
+           {
+             error ("`%T' is not a base of `%T'", scope, object_type);
+             return error_mark_node;
+           }
        }
       else
        {
@@ -1934,7 +2001,7 @@ finish_class_member_access_expr (tree object, tree name)
                                         /*preserve_reference=*/false);
   if (processing_template_decl && expr != error_mark_node)
     return build_min_non_dep (COMPONENT_REF, expr,
-                             orig_object, orig_name);
+                             orig_object, orig_name, NULL_TREE);
   return expr;
 }
 
@@ -1957,12 +2024,13 @@ build_ptrmemfunc_access_expr (tree ptrmem, tree member_name)
      routine directly because it expects the object to be of class
      type.  */
   ptrmem_type = TREE_TYPE (ptrmem);
-  my_friendly_assert (TYPE_PTRMEMFUNC_P (ptrmem_type), 20020804);
+  gcc_assert (TYPE_PTRMEMFUNC_P (ptrmem_type));
   member = lookup_member (ptrmem_type, member_name, /*protect=*/0,
                          /*want_type=*/false);
   member_type = cp_build_qualified_type (TREE_TYPE (member),
                                         cp_type_quals (ptrmem_type));
-  return fold (build (COMPONENT_REF, member_type, ptrmem, member));
+  return fold (build3 (COMPONENT_REF, member_type,
+                      ptrmem, member, NULL_TREE));
 }
 
 /* Given an expression PTR for a pointer, return an expression
@@ -1986,7 +2054,7 @@ build_x_indirect_ref (tree expr, const char *errorstring)
     }
 
   rval = build_new_op (INDIRECT_REF, LOOKUP_NORMAL, expr, NULL_TREE,
-                      NULL_TREE);
+                      NULL_TREE, /*overloaded_p=*/NULL);
   if (!rval)
     rval = build_indirect_ref (expr, errorstring);
 
@@ -1999,7 +2067,7 @@ build_x_indirect_ref (tree expr, const char *errorstring)
 tree
 build_indirect_ref (tree ptr, const char *errorstring)
 {
-  register tree pointer, type;
+  tree pointer, type;
 
   if (ptr == error_mark_node)
     return error_mark_node;
@@ -2096,8 +2164,8 @@ build_array_ref (tree array, tree idx)
     case COMPOUND_EXPR:
       {
        tree value = build_array_ref (TREE_OPERAND (array, 1), idx);
-       return build (COMPOUND_EXPR, TREE_TYPE (value),
-                     TREE_OPERAND (array, 0), value);
+       return build2 (COMPOUND_EXPR, TREE_TYPE (value),
+                      TREE_OPERAND (array, 0), value);
       }
 
     case COND_EXPR:
@@ -2110,8 +2178,7 @@ build_array_ref (tree array, tree idx)
       break;
     }
 
-  if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE
-      && TREE_CODE (array) != INDIRECT_REF)
+  if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE)
     {
       tree rval, type;
 
@@ -2156,8 +2223,8 @@ build_array_ref (tree array, tree idx)
         would get a crash in store_bit_field/extract_bit_field when trying
         to access a non-existent part of the register.  */
       if (TREE_CODE (idx) == INTEGER_CST
-         && TYPE_VALUES (TREE_TYPE (array))
-         && ! int_fits_type_p (idx, TYPE_VALUES (TREE_TYPE (array))))
+         && TYPE_DOMAIN (TREE_TYPE (array))
+         && ! int_fits_type_p (idx, TYPE_DOMAIN (TREE_TYPE (array))))
        {
          if (!cxx_mark_addressable (array))
            return error_mark_node;
@@ -2179,7 +2246,7 @@ build_array_ref (tree array, tree idx)
        }
 
       type = TREE_TYPE (TREE_TYPE (array));
-      rval = build (ARRAY_REF, type, array, idx);
+      rval = build4 (ARRAY_REF, type, array, idx, NULL_TREE, NULL_TREE);
       /* Array ref is const/volatile if the array elements are
         or if the array is..  */
       TREE_READONLY (rval)
@@ -2286,7 +2353,7 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function)
          break;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
 
       /* Convert down to the right base before using the instance.  First
@@ -2298,8 +2365,8 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function)
       if (instance_ptr == error_mark_node)
        return error_mark_node;
       /* ...and then the delta in the PMF.  */
-      instance_ptr = build (PLUS_EXPR, TREE_TYPE (instance_ptr),
-                           instance_ptr, delta);
+      instance_ptr = build2 (PLUS_EXPR, TREE_TYPE (instance_ptr),
+                            instance_ptr, delta);
 
       /* Hand back the adjusted 'this' argument to our caller.  */
       *instance_ptrptr = instance_ptr;
@@ -2310,9 +2377,10 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function)
       vtbl = build_indirect_ref (vtbl, NULL);
 
       /* Finally, extract the function pointer from the vtable.  */
-      e2 = fold (build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, idx));
+      e2 = fold (build2 (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, idx));
       e2 = build_indirect_ref (e2, NULL);
       TREE_CONSTANT (e2) = 1;
+      TREE_INVARIANT (e2) = 1;
 
       /* When using function descriptors, the address of the
         vtable entry is treated as a function pointer.  */
@@ -2326,8 +2394,8 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function)
       /* Make sure this doesn't get evaluated first inside one of the
         branches of the COND_EXPR.  */
       if (instance_save_expr)
-       e1 = build (COMPOUND_EXPR, TREE_TYPE (e1),
-                   instance_save_expr, e1);
+       e1 = build2 (COMPOUND_EXPR, TREE_TYPE (e1),
+                    instance_save_expr, e1);
 
       function = e1;
     }
@@ -2337,10 +2405,9 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function)
 tree
 build_function_call (tree function, tree params)
 {
-  register tree fntype, fndecl;
-  register tree coerced_params;
-  tree result;
-  tree name = NULL_TREE, assembler_name = NULL_TREE;
+  tree fntype, fndecl;
+  tree coerced_params;
+  tree name = NULL_TREE;
   int is_method;
   tree original = function;
 
@@ -2353,7 +2420,6 @@ build_function_call (tree function, tree params)
   if (TREE_CODE (function) == FUNCTION_DECL)
     {
       name = DECL_NAME (function);
-      assembler_name = DECL_ASSEMBLER_NAME (function);
 
       mark_used (function);
       fndecl = function;
@@ -2413,26 +2479,12 @@ build_function_call (tree function, tree params)
   if (coerced_params == error_mark_node)
     return error_mark_node;
 
-  /* Check for errors in format strings.  */
+  /* Check for errors in format strings and inappropriately
+     null parameters.  */
 
-  if (warn_format)
-    check_function_format (NULL, TYPE_ATTRIBUTES (fntype), coerced_params);
+  check_function_arguments (TYPE_ATTRIBUTES (fntype), coerced_params);
 
-  /* Recognize certain built-in functions so we can make tree-codes
-     other than CALL_EXPR.  We do this when it enables fold-const.c
-     to do something useful.  */
-
-  if (TREE_CODE (function) == ADDR_EXPR
-      && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL
-      && DECL_BUILT_IN (TREE_OPERAND (function, 0)))
-    {
-      result = expand_tree_builtin (TREE_OPERAND (function, 0),
-                                   params, coerced_params);
-      if (result)
-       return result;
-    }
-
-  return build_cxx_call (function, params, coerced_params);
+  return build_cxx_call (function, coerced_params);
 }
 \f
 /* Convert the actual parameter expressions in the list VALUES
@@ -2455,8 +2507,8 @@ build_function_call (tree function, tree params)
 tree
 convert_arguments (tree typelist, tree values, tree fndecl, int flags)
 {
-  register tree typetail, valtail;
-  register tree result = NULL_TREE;
+  tree typetail, valtail;
+  tree result = NULL_TREE;
   const char *called_thing = 0;
   int i = 0;
 
@@ -2481,8 +2533,8 @@ convert_arguments (tree typelist, tree values, tree fndecl, int flags)
        valtail;
        valtail = TREE_CHAIN (valtail), i++)
     {
-      register tree type = typetail ? TREE_VALUE (typetail) : 0;
-      register tree val = TREE_VALUE (valtail);
+      tree type = typetail ? TREE_VALUE (typetail) : 0;
+      tree val = TREE_VALUE (valtail);
 
       if (val == error_mark_node)
        return error_mark_node;
@@ -2572,7 +2624,7 @@ convert_arguments (tree typelist, tree values, tree fndecl, int flags)
 
   if (typetail != 0 && typetail != void_list_node)
     {
-      /* See if there are default arguments that can be used */
+      /* See if there are default arguments that can be used */
       if (TREE_PURPOSE (typetail) 
          && TREE_CODE (TREE_PURPOSE (typetail)) != DEFAULT_ARG)
        {
@@ -2614,7 +2666,8 @@ convert_arguments (tree typelist, tree values, tree fndecl, int flags)
    conversions on the operands.  CODE is the kind of expression to build.  */
 
 tree
-build_x_binary_op (enum tree_code code, tree arg1, tree arg2)
+build_x_binary_op (enum tree_code code, tree arg1, tree arg2, 
+                  bool *overloaded_p)
 {
   tree orig_arg1;
   tree orig_arg2;
@@ -2635,7 +2688,8 @@ build_x_binary_op (enum tree_code code, tree arg1, tree arg2)
   if (code == DOTSTAR_EXPR)
     expr = build_m_component_ref (arg1, arg2);
   else
-    expr = build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE);
+    expr = build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE, 
+                        overloaded_p);
 
   if (processing_template_decl && expr != error_mark_node)
     return build_min_non_dep (code, expr, orig_arg1, orig_arg2);
@@ -2666,17 +2720,17 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
                 int convert_p ATTRIBUTE_UNUSED)
 {
   tree op0, op1;
-  register enum tree_code code0, code1;
+  enum tree_code code0, code1;
   tree type0, type1;
 
   /* Expression code to give to the expression when it is built.
      Normally this is CODE, which is what the caller asked for,
      but in some special cases we change it.  */
-  register enum tree_code resultcode = code;
+  enum tree_code resultcode = code;
 
   /* Data type in which the computation is to be performed.
      In the simplest cases this is the common type of the arguments.  */
-  register tree result_type = NULL;
+  tree result_type = NULL;
 
   /* Nonzero means operands have already been type-converted
      in whatever way is necessary.
@@ -2808,15 +2862,20 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
     case ROUND_DIV_EXPR:
     case EXACT_DIV_EXPR:
       if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
-          || code0 == COMPLEX_TYPE)
+          || code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE)
          && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
-             || code1 == COMPLEX_TYPE))
+             || code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE))
        {
          if (TREE_CODE (op1) == INTEGER_CST && integer_zerop (op1))
            warning ("division by zero in `%E / 0'", op0);
          else if (TREE_CODE (op1) == REAL_CST && real_zerop (op1))
            warning ("division by zero in `%E / 0.'", op0);
              
+         if (code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE)
+           code0 = TREE_CODE (TREE_TYPE (TREE_TYPE (op0)));
+         if (code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE)
+           code1 = TREE_CODE (TREE_TYPE (TREE_TYPE (op1)));
+
          if (!(code0 == INTEGER_TYPE && code1 == INTEGER_TYPE))
            resultcode = RDIV_EXPR;
          else
@@ -2826,7 +2885,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
               point, so we have to dig out the original type to find out if
               it was unsigned.  */
            shorten = ((TREE_CODE (op0) == NOP_EXPR
-                       && TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op0, 0))))
+                       && TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op0, 0))))
                       || (TREE_CODE (op1) == INTEGER_CST
                           && ! integer_all_onesp (op1)));
 
@@ -2855,7 +2914,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
             quotient can't be represented in the computation mode.  We shorten
             only if unsigned or if dividing by something we know != -1.  */
          shorten = ((TREE_CODE (op0) == NOP_EXPR
-                     && TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op0, 0))))
+                     && TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op0, 0))))
                     || (TREE_CODE (op1) == INTEGER_CST
                         && ! integer_all_onesp (op1)));
          common = 1;
@@ -3016,17 +3075,22 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
                                   cp_convert (TREE_TYPE (pfn0),
                                               integer_zero_node));
          e1 = cp_build_binary_op (TRUTH_ORIF_EXPR, e1, e2);
-         e2 = build (EQ_EXPR, boolean_type_node, pfn0, pfn1);
+         e2 = build2 (EQ_EXPR, boolean_type_node, pfn0, pfn1);
          e = cp_build_binary_op (TRUTH_ANDIF_EXPR, e2, e1);
          if (code == EQ_EXPR)
            return e;
          return cp_build_binary_op (EQ_EXPR, e, integer_zero_node);
        }
-      else if ((TYPE_PTRMEMFUNC_P (type0)
-               && same_type_p (TYPE_PTRMEMFUNC_FN_TYPE (type0), type1))
-              || (TYPE_PTRMEMFUNC_P (type1)
-                  && same_type_p (TYPE_PTRMEMFUNC_FN_TYPE (type1), type0)))
-       abort ();
+      else
+       {
+         gcc_assert (!TYPE_PTRMEMFUNC_P (type0)
+                     || !same_type_p (TYPE_PTRMEMFUNC_FN_TYPE (type0),
+                                      type1));
+         gcc_assert (!TYPE_PTRMEMFUNC_P (type1)
+                     || !same_type_p (TYPE_PTRMEMFUNC_FN_TYPE (type1),
+                                      type0));
+       }
+      
       break;
 
     case MAX_EXPR:
@@ -3114,7 +3178,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
          tree arg0 = get_narrower (op0, &unsigned0);
          tree arg1 = get_narrower (op1, &unsigned1);
          /* UNS is 1 if the operation to be done is an unsigned one.  */
-         int uns = TREE_UNSIGNED (result_type);
+         int uns = TYPE_UNSIGNED (result_type);
          tree type;
 
          final_type = result_type;
@@ -3123,9 +3187,9 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
             but it *requires* conversion to FINAL_TYPE.  */
 
          if (op0 == arg0 && TREE_TYPE (op0) != final_type)
-           unsigned0 = TREE_UNSIGNED (TREE_TYPE (op0));
+           unsigned0 = TYPE_UNSIGNED (TREE_TYPE (op0));
          if (op1 == arg1 && TREE_TYPE (op1) != final_type)
-           unsigned1 = TREE_UNSIGNED (TREE_TYPE (op1));
+           unsigned1 = TYPE_UNSIGNED (TREE_TYPE (op1));
 
          /* Now UNSIGNED0 is 1 if ARG0 zero-extends to FINAL_TYPE.  */
 
@@ -3177,7 +3241,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
          final_type = result_type;
 
          if (arg0 == op0 && final_type == TREE_TYPE (op0))
-           unsigned_arg = TREE_UNSIGNED (TREE_TYPE (op0));
+           unsigned_arg = TYPE_UNSIGNED (TREE_TYPE (op0));
 
          if (TYPE_PRECISION (TREE_TYPE (arg0)) < TYPE_PRECISION (result_type)
              /* We can shorten only if the shift count is less than the
@@ -3190,7 +3254,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
                 ones made by sign-extension and bring in zeros.
                 We can't optimize that case at all, but in most machines
                 it never happens because available widths are 2**N.  */
-             && (!TREE_UNSIGNED (final_type)
+             && (!TYPE_UNSIGNED (final_type)
                  || unsigned_arg
                  || (((unsigned) 2 * TYPE_PRECISION (TREE_TYPE (arg0)))
                      <= TYPE_PRECISION (result_type))))
@@ -3232,8 +3296,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
             bound the ranges of the arguments until that point.  */
          && !processing_template_decl)
        {
-         int op0_signed = ! TREE_UNSIGNED (TREE_TYPE (orig_op0));
-         int op1_signed = ! TREE_UNSIGNED (TREE_TYPE (orig_op1));
+         int op0_signed = !TYPE_UNSIGNED (TREE_TYPE (orig_op0));
+         int op1_signed = !TYPE_UNSIGNED (TREE_TYPE (orig_op1));
 
          int unsignedp0, unsignedp1;
          tree primop0 = get_narrower (op0, &unsignedp0);
@@ -3257,7 +3321,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
          /* Do not warn if the comparison is being done in a signed type,
             since the signed type will only be chosen if it can represent
             all the values of the unsigned type.  */
-         if (! TREE_UNSIGNED (result_type))
+         if (!TYPE_UNSIGNED (result_type))
            /* OK */;
          /* Do not warn if both operands are unsigned.  */
          else if (op0_signed == op1_signed)
@@ -3385,15 +3449,10 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
     build_type = result_type;
 
   {
-    register tree result = build (resultcode, build_type, op0, op1);
-    register tree folded;
-
-    folded = fold (result);
-    if (folded == result)
-      TREE_CONSTANT (folded) = TREE_CONSTANT (op0) & TREE_CONSTANT (op1);
+    tree result = fold (build2 (resultcode, build_type, op0, op1));
     if (final_type != 0)
-      return cp_convert (final_type, folded);
-    return folded;
+      result = cp_convert (final_type, result);
+    return result;
   }
 }
 \f
@@ -3401,8 +3460,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
    of pointer PTROP and integer INTOP.  */
 
 static tree
-cp_pointer_int_sum (enum tree_code resultcode, register tree ptrop,
-                   register tree intop)
+cp_pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
 {
   tree res_type = TREE_TYPE (ptrop);
 
@@ -3420,9 +3478,9 @@ cp_pointer_int_sum (enum tree_code resultcode, register tree ptrop,
    The resulting tree has type int.  */
 
 static tree
-pointer_diff (register tree op0, register tree op1, register tree ptrtype)
+pointer_diff (tree op0, tree op1, tree ptrtype)
 {
-  register tree result, folded;
+  tree result;
   tree restype = ptrdiff_type_node;
   tree target_type = TREE_TYPE (ptrtype);
 
@@ -3456,12 +3514,8 @@ pointer_diff (register tree op0, register tree op1, register tree ptrtype)
 
   /* Do the division.  */
 
-  result = build (EXACT_DIV_EXPR, restype, op0, cp_convert (restype, op1));
-
-  folded = fold (result);
-  if (folded == result)
-    TREE_CONSTANT (folded) = TREE_CONSTANT (op0) & TREE_CONSTANT (op1);
-  return folded;
+  result = build2 (EXACT_DIV_EXPR, restype, op0, cp_convert (restype, op1));
+  return fold (result);
 }
 \f
 /* Construct and perhaps optimize a tree representation
@@ -3479,21 +3533,46 @@ build_x_unary_op (enum tree_code code, tree xarg)
     {
       if (type_dependent_expression_p (xarg))
        return build_min_nt (code, xarg, NULL_TREE);
+
+      /* For non-dependent pointer-to-member, the SCOPE_REF will be
+        processed during template substitution.  Just compute the
+        right type here and build an ADDR_EXPR around it for
+        diagnostics.  */
+      if (code == ADDR_EXPR && TREE_CODE (xarg) == SCOPE_REF)
+       {
+         tree type;
+         if (TREE_TYPE (xarg) == unknown_type_node)
+           type = unknown_type_node;
+         else if (TREE_CODE (TREE_TYPE (xarg)) == FUNCTION_TYPE)
+           type = build_pointer_type (TREE_TYPE (xarg));
+         else
+           type = build_ptrmem_type (TREE_OPERAND (xarg, 0),
+                                     TREE_TYPE (xarg));
+         return build_min (code, type, xarg, NULL_TREE);
+       }
+
       xarg = build_non_dependent_expr (xarg);
     }
 
   exp = NULL_TREE;
 
-  /* & rec, on incomplete RECORD_TYPEs is the simple opr &, not an
-     error message.  */
+  /* [expr.unary.op] says:
+
+       The address of an object of incomplete type can be taken.
+
+     (And is just the ordinary address operator, not an overloaded
+     "operator &".)  However, if the type is a template
+     specialization, we must complete the type at this point so that
+     an overloaded "operator &" will be available if required.  */
   if (code == ADDR_EXPR
       && TREE_CODE (xarg) != TEMPLATE_ID_EXPR
-      && ((IS_AGGR_TYPE_CODE (TREE_CODE (TREE_TYPE (xarg)))
-          && !COMPLETE_TYPE_P (TREE_TYPE (xarg)))
+      && ((CLASS_TYPE_P (TREE_TYPE (xarg))
+          && !COMPLETE_TYPE_P (complete_type (TREE_TYPE (xarg))))
          || (TREE_CODE (xarg) == OFFSET_REF)))
-    /* don't look for a function */;
+    /* Don't look for a function.  */;
   else
-    exp = build_new_op (code, LOOKUP_NORMAL, xarg, NULL_TREE, NULL_TREE);
+    exp = build_new_op (code, LOOKUP_NORMAL, xarg, NULL_TREE, NULL_TREE,
+                       /*overloaded_p=*/NULL);
   if (!exp && code == ADDR_EXPR)
     {
       /*  A pointer to member-function can be formed only by saying
@@ -3524,9 +3603,9 @@ build_x_unary_op (enum tree_code code, tree xarg)
            {
              /* A single non-static member, make sure we don't allow a
                  pointer-to-member.  */
-             xarg = build (OFFSET_REF, TREE_TYPE (xarg),
-                           TREE_OPERAND (xarg, 0),
-                           ovl_cons (TREE_OPERAND (xarg, 1), NULL_TREE));
+             xarg = build2 (OFFSET_REF, TREE_TYPE (xarg),
+                            TREE_OPERAND (xarg, 0),
+                            ovl_cons (TREE_OPERAND (xarg, 1), NULL_TREE));
              PTRMEM_OK_P (xarg) = ptrmem;
            }         
         }
@@ -3583,8 +3662,6 @@ build_address (tree t)
     return error_mark_node;
 
   addr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (t)), t);
-  if (staticp (t))
-    TREE_CONSTANT (addr) = 1;
 
   return addr;
 }
@@ -3594,16 +3671,9 @@ build_address (tree t)
 tree
 build_nop (tree type, tree expr)
 {
-  tree nop;
-
   if (type == error_mark_node || error_operand_p (expr))
     return expr;
-    
-  nop = build1 (NOP_EXPR, type, expr);
-  if (TREE_CONSTANT (expr))
-    TREE_CONSTANT (nop) = 1;
-  
-  return nop;
+  return build1 (NOP_EXPR, type, expr);
 }
 
 /* C++: Must handle pointers to members.
@@ -3619,8 +3689,8 @@ tree
 build_unary_op (enum tree_code code, tree xarg, int noconvert)
 {
   /* No default_conversion here.  It causes trouble for ADDR_EXPR.  */
-  register tree arg = xarg;
-  register tree argtype = 0;
+  tree arg = xarg;
+  tree argtype = 0;
   const char *errstring = NULL;
   tree val;
 
@@ -3639,9 +3709,8 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
       else
        {
          if (!noconvert)
-          arg = default_conversion (arg);
+           arg = default_conversion (arg);
          arg = build1 (NON_LVALUE_EXPR, TREE_TYPE (arg), arg);
-         TREE_CONSTANT (arg) = TREE_CONSTANT (TREE_OPERAND (arg, 0));
        }
       break;
 
@@ -3728,8 +3797,8 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
          arg = stabilize_reference (arg);
          real = build_unary_op (REALPART_EXPR, arg, 1);
          imag = build_unary_op (IMAGPART_EXPR, arg, 1);
-         return build (COMPLEX_EXPR, TREE_TYPE (arg),
-                       build_unary_op (code, real, 1), imag);
+         return build2 (COMPLEX_EXPR, TREE_TYPE (arg),
+                        build_unary_op (code, real, 1), imag);
        }
 
       /* Report invalid types.  */
@@ -3758,7 +3827,7 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
                        0);
 
       {
-       register tree inc;
+       tree inc;
        tree result_type = TREE_TYPE (arg);
 
        arg = get_unwidened (arg, 0);
@@ -3814,16 +3883,17 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
                value = arg;
              else
                value = save_expr (arg);
-             incremented = build (((code == PREINCREMENT_EXPR
-                                    || code == POSTINCREMENT_EXPR)
-                                   ? PLUS_EXPR : MINUS_EXPR),
-                                  argtype, value, inc);
+             incremented = build2 (((code == PREINCREMENT_EXPR
+                                     || code == POSTINCREMENT_EXPR)
+                                    ? PLUS_EXPR : MINUS_EXPR),
+                                   argtype, value, inc);
 
              modify = build_modify_expr (arg, NOP_EXPR, incremented);
-             compound = build (COMPOUND_EXPR, TREE_TYPE (arg), modify, value);
+             compound = build2 (COMPOUND_EXPR, TREE_TYPE (arg),
+                                modify, value);
 
              /* Eliminate warning about unused result of + or -.  */
-             TREE_NO_UNUSED_WARNING (compound) = 1;
+             TREE_NO_WARNING (compound) = 1;
              return compound;
            }
 
@@ -3848,7 +3918,7 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
            val = boolean_increment (code, arg);
          }
        else
-         val = build (code, TREE_TYPE (arg), arg, inc);
+         val = build2 (code, TREE_TYPE (arg), arg, inc);
 
        TREE_SIDE_EFFECTS (val) = 1;
        return cp_convert (result_type, val);
@@ -3865,10 +3935,8 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
 
       if (TREE_CODE (argtype) == REFERENCE_TYPE)
        {
-         arg = build1
-           (CONVERT_EXPR,
-            build_pointer_type (TREE_TYPE (argtype)), arg);
-         TREE_CONSTANT (arg) = TREE_CONSTANT (TREE_OPERAND (arg, 0));
+         tree type = build_pointer_type (TREE_TYPE (argtype));
+         arg = build1 (CONVERT_EXPR, type, arg);
          return arg;
        }
       else if (pedantic && DECL_MAIN_P (arg))
@@ -3886,10 +3954,8 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
          arg = TREE_OPERAND (arg, 0);
          if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE)
            {
-             arg = build1
-               (CONVERT_EXPR,
-                build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg);
-             TREE_CONSTANT (arg) = TREE_CONSTANT (TREE_OPERAND (arg, 0));
+             tree type = build_pointer_type (TREE_TYPE (TREE_TYPE (arg)));
+             arg = build1 (CONVERT_EXPR, type, arg);
            }
          else if (lvalue_p (arg))
            /* Don't let this be an lvalue.  */
@@ -3897,27 +3963,12 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
          return arg;
        }
 
-      /* For &x[y], return x+y */
-      if (TREE_CODE (arg) == ARRAY_REF)
-       {
-         if (!cxx_mark_addressable (TREE_OPERAND (arg, 0)))
-           return error_mark_node;
-         return cp_build_binary_op (PLUS_EXPR, TREE_OPERAND (arg, 0),
-                                    TREE_OPERAND (arg, 1));
-       }
-
       /* Uninstantiated types are all functions.  Taking the
         address of a function is a no-op, so just return the
         argument.  */
 
-      if (TREE_CODE (arg) == IDENTIFIER_NODE
-         && IDENTIFIER_OPNAME_P (arg))
-       {
-         abort ();
-         /* We don't know the type yet, so just work around the problem.
-            We know that this will resolve to an lvalue.  */
-         return build1 (ADDR_EXPR, unknown_type_node, arg);
-       }
+      gcc_assert (TREE_CODE (arg) != IDENTIFIER_NODE
+                 || !IDENTIFIER_OPNAME_P (arg));
 
       if (TREE_CODE (arg) == COMPONENT_REF && type_unknown_p (arg)
          && !really_overloaded_fn (TREE_OPERAND (arg, 1)))
@@ -3979,7 +4030,11 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
          if (! lvalue_p (arg) && pedantic)
            pedwarn ("ISO C++ forbids taking the address of a cast to a non-lvalue expression");
          break;
-         
+
+       case OVERLOAD:
+         arg = OVL_CURRENT (arg);
+         break;
+
        default:
          break;
        }
@@ -4002,7 +4057,11 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
       {
        tree addr;
 
-       if (TREE_CODE (arg) != COMPONENT_REF)
+       if (TREE_CODE (arg) != COMPONENT_REF
+           /* Inside a template, we are processing a non-dependent
+              expression so we can just form an ADDR_EXPR with the
+              correct type.  */
+           || processing_template_decl)
          addr = build_address (arg);
        else if (TREE_CODE (TREE_OPERAND (arg, 1)) == BASELINK)
          {
@@ -4010,15 +4069,14 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
 
            /* We can only get here with a single static member
               function.  */
-           my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL
-                               && DECL_STATIC_FUNCTION_P (fn),
-                               20030906);
+           gcc_assert (TREE_CODE (fn) == FUNCTION_DECL
+                       && DECL_STATIC_FUNCTION_P (fn));
            mark_used (fn);
            addr = build_address (fn);
            if (TREE_SIDE_EFFECTS (TREE_OPERAND (arg, 0)))
              /* Do not lose object's side effects.  */
-             addr = build (COMPOUND_EXPR, TREE_TYPE (addr),
-                           TREE_OPERAND (arg, 0), addr);
+             addr = build2 (COMPOUND_EXPR, TREE_TYPE (addr),
+                            TREE_OPERAND (arg, 0), addr);
          }
        else if (DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1)))
          {
@@ -4028,9 +4086,6 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
          }
        else
          {
-           /* Unfortunately we cannot just build an address
-              expression here, because we would not handle
-              address-constant-expressions or offsetof correctly.  */
            tree field = TREE_OPERAND (arg, 1);
            tree rval = build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 0), 0);
            tree binfo = lookup_base (TREE_TYPE (TREE_TYPE (rval)),
@@ -4038,9 +4093,9 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
                                      ba_check, NULL);
            
            rval = build_base_path (PLUS_EXPR, rval, binfo, 1);
-           rval = build_nop (argtype, rval);
-           addr = fold (build (PLUS_EXPR, argtype, rval,
-                               cp_convert (argtype, byte_position (field))));
+
+           TREE_OPERAND (arg, 0) = build_indirect_ref (rval, NULL);
+           addr = build_address (arg);
          }
 
        if (TREE_CODE (argtype) == POINTER_TYPE
@@ -4081,8 +4136,8 @@ unary_complex_lvalue (enum tree_code code, tree arg)
   if (TREE_CODE (arg) == COMPOUND_EXPR)
     {
       tree real_result = build_unary_op (code, TREE_OPERAND (arg, 1), 0);
-      return build (COMPOUND_EXPR, TREE_TYPE (real_result),
-                   TREE_OPERAND (arg, 0), real_result);
+      return build2 (COMPOUND_EXPR, TREE_TYPE (real_result),
+                    TREE_OPERAND (arg, 0), real_result);
     }
 
   /* Handle (a ? b : c) used as an "lvalue".  */
@@ -4099,11 +4154,11 @@ unary_complex_lvalue (enum tree_code code, tree arg)
       if (TREE_SIDE_EFFECTS (lvalue))
        {
          lvalue = stabilize_reference (lvalue);
-         arg = build (TREE_CODE (arg), TREE_TYPE (arg),
-                      lvalue, TREE_OPERAND (arg, 1));
+         arg = build2 (TREE_CODE (arg), TREE_TYPE (arg),
+                       lvalue, TREE_OPERAND (arg, 1));
        }
       return unary_complex_lvalue
-       (code, build (COMPOUND_EXPR, TREE_TYPE (lvalue), arg, lvalue));
+       (code, build2 (COMPOUND_EXPR, TREE_TYPE (lvalue), arg, lvalue));
     }
 
   if (code != ADDR_EXPR)
@@ -4114,8 +4169,9 @@ unary_complex_lvalue (enum tree_code code, tree arg)
       || TREE_CODE (arg) == INIT_EXPR)
     {
       tree real_result = build_unary_op (code, TREE_OPERAND (arg, 0), 0);
-      arg = build (COMPOUND_EXPR, TREE_TYPE (real_result), arg, real_result);
-      TREE_NO_UNUSED_WARNING (arg) = 1;
+      arg = build2 (COMPOUND_EXPR, TREE_TYPE (real_result),
+                   arg, real_result);
+      TREE_NO_WARNING (arg) = 1;
       return arg;
     }
 
@@ -4125,7 +4181,7 @@ unary_complex_lvalue (enum tree_code code, tree arg)
     {
       tree t;
 
-      my_friendly_assert (TREE_CODE (arg) != SCOPE_REF, 313);
+      gcc_assert (TREE_CODE (arg) != SCOPE_REF);
 
       if (TREE_CODE (arg) != OFFSET_REF)
        return 0;
@@ -4161,7 +4217,8 @@ unary_complex_lvalue (enum tree_code code, tree arg)
              return error_mark_node;
            }
 
-         type = build_ptrmem_type (DECL_FIELD_CONTEXT (t), TREE_TYPE (t));
+         type = build_ptrmem_type (context_for_name_lookup (t), 
+                                   TREE_TYPE (t));
          t = make_ptrmem_cst (type, TREE_OPERAND (arg, 1));
          return t;
        }
@@ -4186,7 +4243,7 @@ unary_complex_lvalue (enum tree_code code, tree arg)
       }
 
     if (TREE_CODE (arg) == SAVE_EXPR && TREE_CODE (targ) == INDIRECT_REF)
-      return build (SAVE_EXPR, build_pointer_type (TREE_TYPE (arg)),
+      return build3 (SAVE_EXPR, build_pointer_type (TREE_TYPE (arg)),
                     TREE_OPERAND (targ, 0), current_function_decl, NULL);
   }
 
@@ -4203,7 +4260,7 @@ unary_complex_lvalue (enum tree_code code, tree arg)
 bool
 cxx_mark_addressable (tree exp)
 {
-  register tree x = exp;
+  tree x = exp;
 
   while (1)
     switch (TREE_CODE (x))
@@ -4220,19 +4277,19 @@ cxx_mark_addressable (tree exp)
        if (x == current_class_ptr)
          {
             error ("cannot take the address of `this', which is an rvalue expression");
-           TREE_ADDRESSABLE (x) = 1; /* so compiler doesn't die later */
+           TREE_ADDRESSABLE (x) = 1; /* so compiler doesn't die later */
            return true;
          }
-       /* FALLTHRU */
+       /* Fall through.  */
 
       case VAR_DECL:
        /* Caller should not be trying to mark initialized
           constant fields addressable.  */
-       my_friendly_assert (DECL_LANG_SPECIFIC (x) == 0
-                           || DECL_IN_AGGR_P (x) == 0
-                           || TREE_STATIC (x)
-                           || DECL_EXTERNAL (x), 314);
-       /* FALLTHRU */
+       gcc_assert (DECL_LANG_SPECIFIC (x) == 0
+                   || DECL_IN_AGGR_P (x) == 0
+                   || TREE_STATIC (x)
+                   || DECL_EXTERNAL (x));
+       /* Fall through.  */
 
       case CONST_DECL:
       case RESULT_DECL:
@@ -4241,12 +4298,10 @@ cxx_mark_addressable (tree exp)
          warning ("address requested for `%D', which is declared `register'",
                      x);
        TREE_ADDRESSABLE (x) = 1;
-       put_var_into_stack (x, /*rescan=*/true);
        return true;
 
       case FUNCTION_DECL:
        TREE_ADDRESSABLE (x) = 1;
-       TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;
        return true;
 
       case CONSTRUCTOR:
@@ -4279,11 +4334,13 @@ build_x_conditional_expr (tree ifexp, tree op1, tree op2)
         IFEXP is type-dependent, even though the eventual type of the
         expression doesn't dependent on IFEXP.  */
       if (type_dependent_expression_p (ifexp)
-         || type_dependent_expression_p (op1)
+         /* As a GNU extension, the middle operand may be omitted.  */
+         || (op1 && type_dependent_expression_p (op1))
          || type_dependent_expression_p (op2))
        return build_min_nt (COND_EXPR, ifexp, op1, op2);
       ifexp = build_non_dependent_expr (ifexp);
-      op1 = build_non_dependent_expr (op1);
+      if (op1)
+       op1 = build_non_dependent_expr (op1);
       op2 = build_non_dependent_expr (op2);
     }
 
@@ -4295,7 +4352,7 @@ build_x_conditional_expr (tree ifexp, tree op1, tree op2)
 }
 \f
 /* Given a list of expressions, return a compound expression
-   that performs them all and returns the value of the last of them. */
+   that performs them all and returns the value of the last of them.  */
 
 tree build_x_compound_expr_from_list (tree list, const char *msg)
 {
@@ -4331,7 +4388,8 @@ build_x_compound_expr (tree op1, tree op2)
       op2 = build_non_dependent_expr (op2);
     }
 
-  result = build_new_op (COMPOUND_EXPR, LOOKUP_NORMAL, op1, op2, NULL_TREE);
+  result = build_new_op (COMPOUND_EXPR, LOOKUP_NORMAL, op1, op2, NULL_TREE,
+                        /*overloaded_p=*/NULL);
   if (!result)
     result = build_compound_expr (op1, op2);
 
@@ -4341,7 +4399,7 @@ build_x_compound_expr (tree op1, tree op2)
   return result;
 }
 
-/* Build a compound expression. */
+/* Build a compound expression.  */
 
 tree
 build_compound_expr (tree lhs, tree rhs)
@@ -4356,16 +4414,16 @@ build_compound_expr (tree lhs, tree rhs)
     {
       /* If the rhs is a TARGET_EXPR, then build the compound
          expression inside the target_expr's initializer. This
-        helps the compiler to eliminate unncessary temporaries.  */
+        helps the compiler to eliminate unnecessary temporaries.  */
       tree init = TREE_OPERAND (rhs, 1);
       
-      init = build (COMPOUND_EXPR, TREE_TYPE (init), lhs, init);
+      init = build2 (COMPOUND_EXPR, TREE_TYPE (init), lhs, init);
       TREE_OPERAND (rhs, 1) = init;
       
       return rhs;
     }
   
-  return build (COMPOUND_EXPR, TREE_TYPE (rhs), lhs, rhs);
+  return build2 (COMPOUND_EXPR, TREE_TYPE (rhs), lhs, rhs);
 }
 
 /* Issue an error message if casting from SRC_TYPE to DEST_TYPE casts
@@ -4460,7 +4518,17 @@ build_static_cast (tree type, tree expr)
      t.  */
   result = perform_direct_initialization_if_possible (type, expr);
   if (result)
-    return convert_from_reference (result);
+    {
+      result = convert_from_reference (result);
+      /* [expr.static.cast]
+
+         If T is a reference type, the result is an lvalue; otherwise,
+        the result is an rvalue.  */
+      if (TREE_CODE (type) != REFERENCE_TYPE
+         && real_lvalue_p (result))
+       result = build1 (NON_LVALUE_EXPR, TREE_TYPE (result), result);
+      return result;
+    }
   
   /* [expr.static.cast]
 
@@ -4681,7 +4749,7 @@ build_const_cast (tree type, tree expr)
       return t;
     }
 
-  if (!POINTER_TYPE_P (type))
+  if (!POINTER_TYPE_P (type) && !TYPE_PTRMEM_P (type))
     error ("invalid use of const_cast with type `%T', which is not a pointer, reference, nor a pointer-to-data-member type", type);
   else if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
     {
@@ -4737,7 +4805,7 @@ build_const_cast (tree type, tree expr)
 tree
 build_c_cast (tree type, tree expr)
 {
-  register tree value = expr;
+  tree value = expr;
   tree otype;
 
   if (type == error_mark_node || expr == error_mark_node)
@@ -4747,7 +4815,7 @@ build_c_cast (tree type, tree expr)
     {
       tree t = build_min (CAST_EXPR, type,
                          tree_cons (NULL_TREE, value, NULL_TREE));
-      /* We don't know if it will or will not have side effects. */
+      /* We don't know if it will or will not have side effects.  */
       TREE_SIDE_EFFECTS (t) = 1;
       return t;
     }
@@ -4866,7 +4934,9 @@ build_c_cast (tree type, tree expr)
       if (TREE_CODE (value) == INTEGER_CST)
        {
          TREE_OVERFLOW (value) = TREE_OVERFLOW (ovalue);
-         TREE_CONSTANT_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (ovalue);
+
+         if (TREE_CODE_CLASS (TREE_CODE (ovalue)) == 'c')
+           TREE_CONSTANT_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (ovalue);
        }
     }
 
@@ -4902,11 +4972,12 @@ build_c_cast (tree type, tree expr)
 tree
 build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
 {
-  register tree result;
+  tree result;
   tree newrhs = rhs;
   tree lhstype = TREE_TYPE (lhs);
   tree olhstype = lhstype;
-  tree olhs = lhs;
+  tree olhs = NULL_TREE;
+  bool plain_assign = (modifycode == NOP_EXPR);
 
   /* Avoid duplicate error messages from operands that had errors.  */
   if (lhs == error_mark_node || rhs == error_mark_node)
@@ -4915,17 +4986,17 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
   /* Handle control structure constructs used as "lvalues".  */
   switch (TREE_CODE (lhs))
     {
-      /* Handle --foo = 5; as these are valid constructs in C++ */
+      /* Handle --foo = 5; as these are valid constructs in C++ */
     case PREDECREMENT_EXPR:
     case PREINCREMENT_EXPR:
       if (TREE_SIDE_EFFECTS (TREE_OPERAND (lhs, 0)))
-       lhs = build (TREE_CODE (lhs), TREE_TYPE (lhs),
-                    stabilize_reference (TREE_OPERAND (lhs, 0)),
-                    TREE_OPERAND (lhs, 1));
-      return build (COMPOUND_EXPR, lhstype,
-                   lhs,
-                   build_modify_expr (TREE_OPERAND (lhs, 0),
-                                      modifycode, rhs));
+       lhs = build2 (TREE_CODE (lhs), TREE_TYPE (lhs),
+                     stabilize_reference (TREE_OPERAND (lhs, 0)),
+                     TREE_OPERAND (lhs, 1));
+      return build2 (COMPOUND_EXPR, lhstype,
+                    lhs,
+                    build_modify_expr (TREE_OPERAND (lhs, 0),
+                                       modifycode, rhs));
 
       /* Handle (a, b) used as an "lvalue".  */
     case COMPOUND_EXPR:
@@ -4933,18 +5004,18 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
                                  modifycode, rhs);
       if (newrhs == error_mark_node)
        return error_mark_node;
-      return build (COMPOUND_EXPR, lhstype,
-                   TREE_OPERAND (lhs, 0), newrhs);
+      return build2 (COMPOUND_EXPR, lhstype,
+                    TREE_OPERAND (lhs, 0), newrhs);
 
     case MODIFY_EXPR:
       if (TREE_SIDE_EFFECTS (TREE_OPERAND (lhs, 0)))
-       lhs = build (TREE_CODE (lhs), TREE_TYPE (lhs),
-                    stabilize_reference (TREE_OPERAND (lhs, 0)),
-                    TREE_OPERAND (lhs, 1));
+       lhs = build2 (TREE_CODE (lhs), TREE_TYPE (lhs),
+                     stabilize_reference (TREE_OPERAND (lhs, 0)),
+                     TREE_OPERAND (lhs, 1));
       newrhs = build_modify_expr (TREE_OPERAND (lhs, 0), modifycode, rhs);
       if (newrhs == error_mark_node)
        return error_mark_node;
-      return build (COMPOUND_EXPR, lhstype, lhs, newrhs);
+      return build2 (COMPOUND_EXPR, lhstype, lhs, newrhs);
 
       /* Handle (a ? b : c) used as an "lvalue".  */
     case COND_EXPR:
@@ -4975,7 +5046,9 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
          return cond;
        /* Make sure the code to compute the rhs comes out
           before the split.  */
-       return build (COMPOUND_EXPR, TREE_TYPE (lhs), preeval, cond);
+       if (preeval)
+         cond = build2 (COMPOUND_EXPR, TREE_TYPE (lhs), preeval, cond);
+       return cond;
       }
       
     default:
@@ -4986,20 +5059,20 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
     {
       if (TREE_CODE (rhs) == CONSTRUCTOR)
        {
-         my_friendly_assert (same_type_p (TREE_TYPE (rhs), lhstype),
-                             20011220);
-         result = build (INIT_EXPR, lhstype, lhs, rhs);
+         if (! same_type_p (TREE_TYPE (rhs), lhstype))
+           /* Call convert to generate an error; see PR 11063.  */
+           rhs = convert (lhstype, rhs);
+         result = build2 (INIT_EXPR, lhstype, lhs, rhs);
          TREE_SIDE_EFFECTS (result) = 1;
          return result;
        }
       else if (! IS_AGGR_TYPE (lhstype))
-       /* Do the default thing */;
+       /* Do the default thing */;
       else
        {
          result = build_special_member_call (lhs, complete_ctor_identifier,
                                              build_tree_list (NULL_TREE, rhs),
-                                             TYPE_BINFO (lhstype), 
-                                             LOOKUP_NORMAL);
+                                             lhstype, LOOKUP_NORMAL);
          if (result == NULL_TREE)
            return error_mark_node;
          return result;
@@ -5020,11 +5093,12 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
        {
          /* `operator=' is not an inheritable operator.  */
          if (! IS_AGGR_TYPE (lhstype))
-           /* Do the default thing */;
+           /* Do the default thing */;
          else
            {
              result = build_new_op (MODIFY_EXPR, LOOKUP_NORMAL,
-                                    lhs, rhs, make_node (NOP_EXPR));
+                                    lhs, rhs, make_node (NOP_EXPR),
+                                    /*overloaded_p=*/NULL);
              if (result == NULL_TREE)
                return error_mark_node;
              return result;
@@ -5037,8 +5111,7 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
             value with the RHS producing the value we should actually
             store into the LHS.  */
 
-         my_friendly_assert (!PROMOTES_TO_AGGR_TYPE (lhstype, REFERENCE_TYPE),
-                             978652);
+         gcc_assert (!PROMOTES_TO_AGGR_TYPE (lhstype, REFERENCE_TYPE));
          lhs = stabilize_reference (lhs);
          newrhs = cp_build_binary_op (modifycode, lhs, rhs);
          if (newrhs == error_mark_node)
@@ -5051,57 +5124,11 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
          /* Now it looks like a plain assignment.  */
          modifycode = NOP_EXPR;
        }
-      my_friendly_assert (TREE_CODE (lhstype) != REFERENCE_TYPE, 20011220);
-      my_friendly_assert (TREE_CODE (TREE_TYPE (newrhs)) != REFERENCE_TYPE,
-                         20011220);
-    }
-
-  /* Handle a cast used as an "lvalue".
-     We have already performed any binary operator using the value as cast.
-     Now convert the result to the cast type of the lhs,
-     and then true type of the lhs and store it there;
-     then convert result back to the cast type to be the value
-     of the assignment.  */
-
-  switch (TREE_CODE (lhs))
-    {
-    case NOP_EXPR:
-    case CONVERT_EXPR:
-    case FLOAT_EXPR:
-    case FIX_TRUNC_EXPR:
-    case FIX_FLOOR_EXPR:
-    case FIX_ROUND_EXPR:
-    case FIX_CEIL_EXPR:
-      {
-       tree inner_lhs = TREE_OPERAND (lhs, 0);
-       tree result;
-
-       if (TREE_CODE (TREE_TYPE (newrhs)) == ARRAY_TYPE
-           || TREE_CODE (TREE_TYPE (newrhs)) == FUNCTION_TYPE
-           || TREE_CODE (TREE_TYPE (newrhs)) == METHOD_TYPE
-           || TREE_CODE (TREE_TYPE (newrhs)) == OFFSET_TYPE)
-         newrhs = decay_conversion (newrhs);
-       
-       /* ISO C++ 5.4/1: The result is an lvalue if T is a reference
-          type, otherwise the result is an rvalue.  */
-       if (! lvalue_p (lhs))
-         pedwarn ("ISO C++ forbids cast to non-reference type used as lvalue");
-
-       result = build_modify_expr (inner_lhs, NOP_EXPR,
-                                   cp_convert (TREE_TYPE (inner_lhs),
-                                               cp_convert (lhstype, newrhs)));
-       if (result == error_mark_node)
-         return result;
-       return cp_convert (TREE_TYPE (lhs), result);
-      }
-
-    default:
-      break;
+      gcc_assert (TREE_CODE (lhstype) != REFERENCE_TYPE);
+      gcc_assert (TREE_CODE (TREE_TYPE (newrhs)) != REFERENCE_TYPE);
     }
 
-  /* Now we have handled acceptable kinds of LHS that are not truly lvalues.
-     Reject anything strange now.  */
-
+  /* The left-hand side must be an lvalue.  */
   if (!lvalue_or_else (lhs, "assignment"))
     return error_mark_node;
 
@@ -5135,6 +5162,15 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
 
       if (lhstype != TREE_TYPE (lhs))
        {
+         /* Avoid warnings converting integral types back into enums for
+            enum bit fields.  */
+         if (TREE_CODE (lhstype) == INTEGER_TYPE
+             && TREE_CODE (olhstype) == ENUMERAL_TYPE)
+           {
+             if (TREE_SIDE_EFFECTS (lhs))
+               lhs = stabilize_reference (lhs);
+             olhs = lhs;
+           }
          lhs = copy_node (lhs);
          TREE_TYPE (lhs) = lhstype;
        }
@@ -5188,17 +5224,19 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
         accidental self-initialization.  So we force the TARGET_EXPR to be
         expanded without a target.  */
       if (TREE_CODE (newrhs) == TARGET_EXPR)
-       newrhs = build (COMPOUND_EXPR, TREE_TYPE (newrhs), newrhs,
-                       TREE_OPERAND (newrhs, 0));
+       newrhs = build2 (COMPOUND_EXPR, TREE_TYPE (newrhs), newrhs,
+                        TREE_OPERAND (newrhs, 0));
     }
 
   if (newrhs == error_mark_node)
     return error_mark_node;
 
-  result = build (modifycode == NOP_EXPR ? MODIFY_EXPR : INIT_EXPR,
-                 lhstype, lhs, newrhs);
+  result = build2 (modifycode == NOP_EXPR ? MODIFY_EXPR : INIT_EXPR,
+                  lhstype, lhs, newrhs);
 
   TREE_SIDE_EFFECTS (result) = 1;
+  if (!plain_assign)
+    TREE_NO_WARNING (result) = 1;
 
   /* If we got the LHS in a different type for storing in,
      convert the result back to the nominal type of LHS
@@ -5207,13 +5245,10 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
 
   if (olhstype == TREE_TYPE (result))
     return result;
-  /* Avoid warnings converting integral types back into enums
-     for enum bit fields.  */
-  if (TREE_CODE (TREE_TYPE (result)) == INTEGER_TYPE
-      && TREE_CODE (olhstype) == ENUMERAL_TYPE)
+  if (olhs)
     {
-      result = build (COMPOUND_EXPR, olhstype, result, olhs);
-      TREE_NO_UNUSED_WARNING (result) = 1;
+      result = build2 (COMPOUND_EXPR, olhstype, result, olhs);
+      TREE_NO_WARNING (result) = 1;
       return result;
     }
   return convert_for_assignment (olhstype, result, "assignment",
@@ -5230,9 +5265,13 @@ build_x_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
   if (modifycode != NOP_EXPR)
     {
       tree rval = build_new_op (MODIFY_EXPR, LOOKUP_NORMAL, lhs, rhs,
-                               make_node (modifycode));
+                               make_node (modifycode),
+                               /*overloaded_p=*/NULL);
       if (rval)
-       return rval;
+       {
+         TREE_NO_WARNING (rval) = 1;
+         return rval;
+       }
     }
   return build_modify_expr (lhs, modifycode, rhs);
 }
@@ -5254,51 +5293,53 @@ get_delta_difference (tree from, tree to, int force)
   tree binfo;
   tree virt_binfo;
   base_kind kind;
-  
+  tree result;
+
+  /* Assume no conversion is required.  */
+  result = integer_zero_node;
   binfo = lookup_base (to, from, ba_check, &kind);
   if (kind == bk_inaccessible || kind == bk_ambig)
-    {
-      error ("   in pointer to member function conversion");
-      goto error;
-    }
-  if (!binfo)
+    error ("   in pointer to member function conversion");
+  else if (!binfo)
     {
       if (!force)
        {
          error_not_base_type (from, to);
          error ("   in pointer to member conversion");
-         goto error;
        }
-      binfo = lookup_base (from, to, ba_check, &kind);
-      if (!binfo)
-       goto error;
+      else
+       {
+         binfo = lookup_base (from, to, ba_check, &kind);
+         if (binfo)
+           {
+             virt_binfo = binfo_from_vbase (binfo);
+             if (virt_binfo)
+               /* This is a reinterpret cast, we choose to do nothing.  */
+               warning ("pointer to member cast via virtual base `%T'",
+                        BINFO_TYPE (virt_binfo));
+             else
+               result = size_diffop (size_zero_node, BINFO_OFFSET (binfo));
+           }
+       }
+    }
+  else
+    {
       virt_binfo = binfo_from_vbase (binfo);
-      if (virt_binfo)
-        {
-          /* This is a reinterpret cast, we choose to do nothing.  */
-          warning ("pointer to member cast via virtual base `%T'",
+      if (!virt_binfo)
+       result = BINFO_OFFSET (binfo);
+      else
+       {
+         /* This is a reinterpret cast, we choose to do nothing.  */
+         if (force)
+           warning ("pointer to member cast via virtual base `%T'",
+                    BINFO_TYPE (virt_binfo));
+         else
+           error ("pointer to member conversion via virtual base `%T'",
                   BINFO_TYPE (virt_binfo));
-         goto error;
-        }
-      return convert_to_integer (ptrdiff_type_node, 
-                                size_diffop (size_zero_node,
-                                             BINFO_OFFSET (binfo)));
+       }
     }
 
-  virt_binfo = binfo_from_vbase (binfo);
-  if (!virt_binfo)
-    return convert_to_integer (ptrdiff_type_node, BINFO_OFFSET (binfo));
-
-  /* This is a reinterpret cast, we choose to do nothing.  */
-  if (force)
-    warning ("pointer to member cast via virtual base `%T'",
-            BINFO_TYPE (virt_binfo));
-  else
-    error ("pointer to member conversion via virtual base `%T'",
-          BINFO_TYPE (virt_binfo));
-
- error:
-  return convert_to_integer(ptrdiff_type_node, integer_zero_node);
+  return fold (convert_to_integer (ptrdiff_type_node, result));
 }
 
 /* Return a constructor for the pointer-to-member-function TYPE using
@@ -5322,7 +5363,8 @@ build_ptrmemfunc1 (tree type, tree delta, tree pfn)
   u = tree_cons (pfn_field, pfn,
                 build_tree_list (delta_field, delta));
   u = build_constructor (type, u);
-  TREE_CONSTANT (u) = TREE_CONSTANT (pfn) && TREE_CONSTANT (delta);
+  TREE_CONSTANT (u) = TREE_CONSTANT (pfn) & TREE_CONSTANT (delta);
+  TREE_INVARIANT (u) = TREE_INVARIANT (pfn) & TREE_INVARIANT (delta);
   TREE_STATIC (u) = (TREE_CONSTANT (u)
                     && (initializer_constant_valid_p (pfn, TREE_TYPE (pfn))
                         != NULL_TREE)
@@ -5396,7 +5438,8 @@ build_ptrmemfunc (tree type, tree pfn, int force)
        }
 
       /* Just adjust the DELTA field.  */
-      my_friendly_assert (TREE_TYPE (delta) == ptrdiff_type_node, 20030727);
+      gcc_assert  (same_type_ignoring_top_level_qualifiers_p
+                  (TREE_TYPE (delta), ptrdiff_type_node));
       if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_delta)
        n = cp_build_binary_op (LSHIFT_EXPR, n, integer_one_node);
       delta = cp_build_binary_op (PLUS_EXPR, delta, n);
@@ -5416,7 +5459,7 @@ build_ptrmemfunc (tree type, tree pfn, int force)
     return instantiate_type (type, pfn, tf_error | tf_warning);
 
   fn = TREE_OPERAND (pfn, 0);
-  my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 0);
+  gcc_assert (TREE_CODE (fn) == FUNCTION_DECL);
   return make_ptrmem_cst (to_type, fn);
 }
 
@@ -5424,7 +5467,7 @@ build_ptrmemfunc (tree type, tree pfn, int force)
    given by CST.
 
    ??? There is no consistency as to the types returned for the above
-   values.  Some code acts as if its a sizetype and some as if its
+   values.  Some code acts as if it were a sizetype and some as if it were
    integer_type_node.  */
 
 void
@@ -5434,7 +5477,7 @@ expand_ptrmemfunc_cst (tree cst, tree *delta, tree *pfn)
   tree fn = PTRMEM_CST_MEMBER (cst);
   tree ptr_class, fn_class;
 
-  my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 0);
+  gcc_assert (TREE_CODE (fn) == FUNCTION_DECL);
 
   /* The class that the function belongs to.  */
   fn_class = DECL_CONTEXT (fn);
@@ -5454,32 +5497,32 @@ expand_ptrmemfunc_cst (tree cst, tree *delta, tree *pfn)
          fn; the call will do the opposite adjustment.  */
       tree orig_class = DECL_CONTEXT (fn);
       tree binfo = binfo_or_else (orig_class, fn_class);
-      *delta = fold (build (PLUS_EXPR, TREE_TYPE (*delta),
-                           *delta, BINFO_OFFSET (binfo)));
+      *delta = fold (build2 (PLUS_EXPR, TREE_TYPE (*delta),
+                            *delta, BINFO_OFFSET (binfo)));
 
       /* We set PFN to the vtable offset at which the function can be
         found, plus one (unless ptrmemfunc_vbit_in_delta, in which
         case delta is shifted left, and then incremented).  */
       *pfn = DECL_VINDEX (fn);
-      *pfn = fold (build (MULT_EXPR, integer_type_node, *pfn,
-                         TYPE_SIZE_UNIT (vtable_entry_type)));
+      *pfn = fold (build2 (MULT_EXPR, integer_type_node, *pfn,
+                          TYPE_SIZE_UNIT (vtable_entry_type)));
 
       switch (TARGET_PTRMEMFUNC_VBIT_LOCATION)
        {
        case ptrmemfunc_vbit_in_pfn:
-         *pfn = fold (build (PLUS_EXPR, integer_type_node, *pfn,
-                             integer_one_node));
+         *pfn = fold (build2 (PLUS_EXPR, integer_type_node, *pfn,
+                              integer_one_node));
          break;
 
        case ptrmemfunc_vbit_in_delta:
-         *delta = fold (build (LSHIFT_EXPR, TREE_TYPE (*delta),
-                               *delta, integer_one_node));
-         *delta = fold (build (PLUS_EXPR, TREE_TYPE (*delta),
-                               *delta, integer_one_node));
+         *delta = fold (build2 (LSHIFT_EXPR, TREE_TYPE (*delta),
+                                *delta, integer_one_node));
+         *delta = fold (build2 (PLUS_EXPR, TREE_TYPE (*delta),
+                                *delta, integer_one_node));
          break;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
 
       *pfn = fold (build1 (NOP_EXPR, TYPE_PTRMEMFUNC_FN_TYPE (type),
@@ -5538,10 +5581,9 @@ dubious_conversion_warnings (tree type, tree expr,
     }
   /* And warn about assigning a negative value to an unsigned
      variable.  */
-  else if (TREE_UNSIGNED (type) && TREE_CODE (type) != BOOLEAN_TYPE)
+  else if (TYPE_UNSIGNED (type) && TREE_CODE (type) != BOOLEAN_TYPE)
     {
-      if (TREE_CODE (expr) == INTEGER_CST
-         && TREE_NEGATED_INT (expr))
+      if (TREE_CODE (expr) == INTEGER_CST && TREE_NEGATED_INT (expr))
        {
          if (fndecl)
            warning ("passing negative value `%E' for %s %P of `%D'",
@@ -5569,8 +5611,8 @@ static tree
 convert_for_assignment (tree type, tree rhs,
                        const char *errtype, tree fndecl, int parmnum)
 {
-  register tree rhstype;
-  register enum tree_code coder;
+  tree rhstype;
+  enum tree_code coder;
 
   /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue.  */
   if (TREE_CODE (rhs) == NON_LVALUE_EXPR)
@@ -5580,8 +5622,7 @@ convert_for_assignment (tree type, tree rhs,
   coder = TREE_CODE (rhstype);
 
   if (TREE_CODE (type) == VECTOR_TYPE && coder == VECTOR_TYPE
-      && ((*targetm.vector_opaque_p) (type)
-         || (*targetm.vector_opaque_p) (rhstype)))
+      && vector_types_convertible_p (type, rhstype))
     return convert (type, rhs);
 
   if (rhs == error_mark_node || rhstype == error_mark_node)
@@ -5589,8 +5630,6 @@ convert_for_assignment (tree type, tree rhs,
   if (TREE_CODE (rhs) == TREE_LIST && TREE_VALUE (rhs) == error_mark_node)
     return error_mark_node;
 
-  rhs = dubious_conversion_warnings (type, rhs, errtype, fndecl, parmnum);
-
   /* The RHS of an assignment cannot have void type.  */
   if (coder == VOID_TYPE)
     {
@@ -5668,9 +5707,9 @@ tree
 convert_for_initialization (tree exp, tree type, tree rhs, int flags,
                            const char *errtype, tree fndecl, int parmnum)
 {
-  register enum tree_code codel = TREE_CODE (type);
-  register tree rhstype;
-  register enum tree_code coder;
+  enum tree_code codel = TREE_CODE (type);
+  tree rhstype;
+  enum tree_code coder;
 
   /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
      Strip such NOP_EXPRs, since RHS is used in non-lvalue context.  */
@@ -5739,63 +5778,6 @@ convert_for_initialization (tree exp, tree type, tree rhs, int flags,
   return convert_for_assignment (type, rhs, errtype, fndecl, parmnum);
 }
 \f
-/* Expand an ASM statement with operands, handling output operands
-   that are not variables or INDIRECT_REFS by transforming such
-   cases into cases that expand_asm_operands can handle.
-
-   Arguments are same as for expand_asm_operands.
-
-   We don't do default conversions on all inputs, because it can screw
-   up operands that are expected to be in memory.  */
-
-void
-c_expand_asm_operands (tree string, tree outputs, tree inputs, tree clobbers,
-                      int vol, const char *filename, int line)
-{
-  int noutputs = list_length (outputs);
-  register int i;
-  /* o[I] is the place that output number I should be written.  */
-  register tree *o = alloca (noutputs * sizeof (tree));
-  register tree tail;
-
-  /* Record the contents of OUTPUTS before it is modified.  */
-  for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
-    o[i] = TREE_VALUE (tail);
-
-  /* Generate the ASM_OPERANDS insn;
-     store into the TREE_VALUEs of OUTPUTS some trees for
-     where the values were actually stored.  */
-  expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line);
-
-  /* Copy all the intermediate outputs into the specified outputs.  */
-  for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
-    {
-      if (o[i] != TREE_VALUE (tail))
-       {
-         expand_expr (build_modify_expr (o[i], NOP_EXPR, TREE_VALUE (tail)),
-                      const0_rtx, VOIDmode, EXPAND_NORMAL);
-         free_temp_slots ();
-
-         /* Restore the original value so that it's correct the next
-            time we expand this function.  */
-         TREE_VALUE (tail) = o[i];
-       }
-      /* Detect modification of read-only values.
-        (Otherwise done by build_modify_expr.)  */
-      else
-       {
-         tree type = TREE_TYPE (o[i]);
-         if (type != error_mark_node
-             && (CP_TYPE_CONST_P (type)
-                 || (CLASS_TYPE_P (type) && C_TYPE_FIELDS_READONLY (type))))
-           readonly_error (o[i], "modification by `asm'", 1);
-       }
-    }
-
-  /* Those MODIFY_EXPRs could do autoincrements.  */
-  emit_queue ();
-}
-\f
 /* If RETVAL is the address of, or a reference to, a local variable or
    temporary give an appropriate warning.  */
 
@@ -5838,7 +5820,7 @@ maybe_warn_about_returning_address_of_local (tree retval)
        }
     }
 
-  if (TREE_CODE (whats_returned) == VAR_DECL
+  if (DECL_P (whats_returned)
       && DECL_NAME (whats_returned)
       && DECL_FUNCTION_SCOPE_P (whats_returned)
       && !(TREE_STATIC (whats_returned)
@@ -5903,7 +5885,7 @@ check_return_expr (tree retval)
      return value, the named return value is used.  */
   result = DECL_RESULT (current_function_decl);
   valtype = TREE_TYPE (result);
-  my_friendly_assert (valtype != NULL_TREE, 19990924);
+  gcc_assert (valtype != NULL_TREE);
   fn_returns_value_p = !VOID_TYPE_P (valtype);
   if (!retval && DECL_NAME (result) && fn_returns_value_p)
     retval = result;
@@ -5955,9 +5937,29 @@ check_return_expr (tree retval)
 
   /* Effective C++ rule 15.  See also start_function.  */
   if (warn_ecpp
-      && DECL_NAME (current_function_decl) == ansi_assopname(NOP_EXPR)
-      && retval != current_class_ref)
-    warning ("`operator=' should return a reference to `*this'");
+      && DECL_NAME (current_function_decl) == ansi_assopname(NOP_EXPR))
+    {
+      bool warn = true;
+
+      /* The function return type must be a reference to the current
+       class.  */
+      if (TREE_CODE (valtype) == REFERENCE_TYPE
+         && same_type_ignoring_top_level_qualifiers_p
+             (TREE_TYPE (valtype), TREE_TYPE (current_class_ref)))
+       {
+         /* Returning '*this' is obviously OK.  */
+         if (retval == current_class_ref)
+           warn = false;
+         /* If we are calling a function whose return type is the same of
+            the current class reference, it is ok.  */
+         else if (TREE_CODE (retval) == INDIRECT_REF
+                  && TREE_CODE (TREE_OPERAND (retval, 0)) == CALL_EXPR)
+           warn = false;
+       }
+
+      if (warn)
+       warning ("`operator=' should return a reference to `*this'");
+    }
 
   /* The fabled Named Return Value optimization, as per [class.copy]/15:
 
@@ -5976,8 +5978,7 @@ check_return_expr (tree retval)
      returned expression uses the chosen variable somehow.  And people expect
      this restriction, anyway.  (jason 2000-11-19)
 
-     See finish_function, genrtl_start_function, and declare_return_variable
-     for other pieces of this optimization.  */
+     See finish_function and finalize_nrv for the rest of this optimization.  */
 
   if (fn_returns_value_p && flag_elide_constructors)
     {
@@ -6027,15 +6028,15 @@ check_return_expr (tree retval)
       else if (! current_function_returns_struct
               && TREE_CODE (retval) == TARGET_EXPR
               && TREE_CODE (TREE_OPERAND (retval, 1)) == AGGR_INIT_EXPR)
-       retval = build (COMPOUND_EXPR, TREE_TYPE (retval), retval,
-                       TREE_OPERAND (retval, 0));
+       retval = build2 (COMPOUND_EXPR, TREE_TYPE (retval), retval,
+                        TREE_OPERAND (retval, 0));
       else
        maybe_warn_about_returning_address_of_local (retval);
     }
   
   /* Actually copy the value returned into the appropriate location.  */
   if (retval && retval != result)
-    retval = build (INIT_EXPR, TREE_TYPE (result), result, retval);
+    retval = build2 (INIT_EXPR, TREE_TYPE (result), result, retval);
 
   return retval;
 }
@@ -6166,7 +6167,7 @@ cp_type_quals (tree type)
   return TYPE_QUALS (type);
 }
 
-/* Returns nonzero if the TYPE contains a mutable member */
+/* Returns nonzero if the TYPE contains a mutable member */
 
 bool
 cp_has_mutable_p (tree type)