OSDN Git Service

* c-common.h (check_function_format): Remove first parameter.
[pf3gnuchains/gcc-fork.git] / gcc / cp / typeck.c
index 10103c8..1dfb337 100644 (file)
@@ -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);
 }
 
@@ -348,7 +345,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 +359,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 +440,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 +452,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);
@@ -1024,7 +1022,7 @@ comptypes (tree t1, tree t2, int strict)
       if (!comptypes (TYPE_OFFSET_BASETYPE (t1), TYPE_OFFSET_BASETYPE (t2),
                      strict & ~COMPARE_REDECLARATION))
        return false;
-      /* Fall through. */
+      /* Fall through.  */
 
     case POINTER_TYPE:
     case REFERENCE_TYPE:
@@ -1058,6 +1056,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;
     }
@@ -1285,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.
@@ -1337,11 +1367,8 @@ 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)
@@ -1374,7 +1401,6 @@ decay_conversion (tree exp)
          if (!cxx_mark_addressable (exp))
            return error_mark_node;
          adr = build_nop (ptrtype, build_address (exp));
-         TREE_SIDE_EFFECTS (adr) = 0;   /* Default would be, same as EXP.  */
          return adr;
        }
       /* This way is better for a COMPONENT_REF since it can
@@ -1510,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;
@@ -1726,7 +1752,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 (build (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
@@ -1753,7 +1780,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 = build (COMPONENT_REF, type, object, member, NULL_TREE);
     }
   else if (TREE_CODE (member) == CONST_DECL)
     {
@@ -1788,6 +1815,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))
     {
@@ -1795,17 +1823,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 ("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))
+  if (!TYPE_HAS_DESTRUCTOR (dtor_type))
     return build (PSEUDO_DTOR_EXPR, void_type_node, object, scope,
                  dtor_type);
-  return lookup_member (object_type, complete_dtor_identifier,
+  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
@@ -1848,7 +1879,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);
     }
   
@@ -1975,7 +2006,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;
 }
 
@@ -2003,7 +2034,7 @@ build_ptrmemfunc_access_expr (tree ptrmem, tree member_name)
                          /*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 (build (COMPONENT_REF, member_type, ptrmem, member, NULL_TREE));
 }
 
 /* Given an expression PTR for a pointer, return an expression
@@ -2151,8 +2182,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;
 
@@ -2220,7 +2250,7 @@ build_array_ref (tree array, tree idx)
        }
 
       type = TREE_TYPE (TREE_TYPE (array));
-      rval = build (ARRAY_REF, type, array, idx);
+      rval = build (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)
@@ -2354,6 +2384,7 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function)
       e2 = fold (build (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.  */
@@ -2380,7 +2411,6 @@ build_function_call (tree function, tree params)
 {
   tree fntype, fndecl;
   tree coerced_params;
-  tree result;
   tree name = NULL_TREE;
   int is_method;
   tree original = function;
@@ -2456,23 +2486,9 @@ build_function_call (tree function, tree params)
   /* Check for errors in format strings.  */
 
   if (warn_format)
-    check_function_format (NULL, 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.  */
+    check_function_format (TYPE_ATTRIBUTES (fntype), coerced_params);
 
-  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
@@ -2868,7 +2884,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)));
 
@@ -2897,7 +2913,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;
@@ -3156,7 +3172,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;
@@ -3165,9 +3181,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.  */
 
@@ -3219,7 +3235,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
@@ -3232,7 +3248,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))))
@@ -3274,8 +3290,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);
@@ -3299,7 +3315,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)
@@ -3427,15 +3443,10 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
     build_type = result_type;
 
   {
-    tree result = build (resultcode, build_type, op0, op1);
-    tree folded;
-
-    folded = fold (result);
-    if (folded == result)
-      TREE_CONSTANT (folded) = TREE_CONSTANT (op0) & TREE_CONSTANT (op1);
+    tree result = fold (build (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
@@ -3463,7 +3474,7 @@ cp_pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
 static tree
 pointer_diff (tree op0, tree op1, tree ptrtype)
 {
-  tree result, folded;
+  tree result;
   tree restype = ptrdiff_type_node;
   tree target_type = TREE_TYPE (ptrtype);
 
@@ -3498,11 +3509,7 @@ pointer_diff (tree op0, tree op1, 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;
+  return fold (result);
 }
 \f
 /* Construct and perhaps optimize a tree representation
@@ -3525,12 +3532,18 @@ build_x_unary_op (enum tree_code code, tree 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.  */;
   else
@@ -3625,8 +3638,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;
 }
@@ -3636,16 +3647,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.
@@ -3681,9 +3685,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;
 
@@ -3865,7 +3868,7 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
              compound = build (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;
            }
 
@@ -3907,10 +3910,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))
@@ -3928,10 +3929,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.  */
@@ -3939,8 +3938,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)
+      /* For &x[y], return x+y.  But, in a template, ARG may be an
+        ARRAY_REF representing a non-dependent expression.  In that
+        case, there may be an overloaded "operator []" that will be
+        chosen at instantiation time; we must not try to optimize
+        here.  */
+      if (TREE_CODE (arg) == ARRAY_REF && !processing_template_decl)
        {
          if (!cxx_mark_addressable (TREE_OPERAND (arg, 0)))
            return error_mark_node;
@@ -4021,7 +4024,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;
        }
@@ -4044,7 +4051,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)
          {
@@ -4157,7 +4168,7 @@ unary_complex_lvalue (enum tree_code code, tree arg)
     {
       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;
+      TREE_NO_WARNING (arg) = 1;
       return arg;
     }
 
@@ -4203,7 +4214,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;
        }
@@ -4288,7 +4300,6 @@ cxx_mark_addressable (tree exp)
 
       case FUNCTION_DECL:
        TREE_ADDRESSABLE (x) = 1;
-       TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;
        return true;
 
       case CONSTRUCTOR:
@@ -4505,7 +4516,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]
 
@@ -4726,7 +4747,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)
     {
@@ -4911,7 +4932,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);
        }
     }
 
@@ -5020,7 +5043,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 = build (COMPOUND_EXPR, TREE_TYPE (lhs), preeval, cond);
+       return cond;
       }
       
     default:
@@ -5221,7 +5246,7 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
   if (olhs)
     {
       result = build (COMPOUND_EXPR, olhstype, result, olhs);
-      TREE_NO_UNUSED_WARNING (result) = 1;
+      TREE_NO_WARNING (result) = 1;
       return result;
     }
   return convert_for_assignment (olhstype, result, "assignment",
@@ -5263,51 +5288,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
@@ -5331,7 +5358,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)
@@ -5547,10 +5575,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'",
@@ -5589,8 +5616,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)
@@ -5983,9 +6009,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, cxx_expand_function_start, and
-     cp_copy_res_decl_for_inlining 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)
     {