OSDN Git Service

* g++.dg/abi/vague1.C: Use xfail, rather than embedded Tcl code.
[pf3gnuchains/gcc-fork.git] / gcc / cp / typeck.c
index 57d95ad..21068b3 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 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
    Hacked by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GCC.
@@ -946,6 +946,13 @@ comptypes (t1, t2, strict)
   if (TYPE_PTRMEMFUNC_P (t2))
     t2 = TYPE_PTRMEMFUNC_FN_TYPE (t2);
 
+  /* TYPENAME_TYPEs should be resolved if the qualifying scope is the
+     current instantiation.  */
+  if (TREE_CODE (t1) == TYPENAME_TYPE)
+    t1 = resolve_typename_type_in_current_instantiation (t1);
+  if (TREE_CODE (t2) == TYPENAME_TYPE)
+    t2 = resolve_typename_type_in_current_instantiation (t2);
+
   /* Different classes of types can't be compatible.  */
   if (TREE_CODE (t1) != TREE_CODE (t2))
     return 0;
@@ -964,11 +971,9 @@ comptypes (t1, t2, strict)
   if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
     return 1;
 
-  if (strict & COMPARE_NO_ATTRIBUTES)
-    attrval = 1;
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
-  else if (! (attrval = (*targetm.comp_type_attributes) (t1, t2)))
-     return 0;
+  if (! (attrval = (*targetm.comp_type_attributes) (t1, t2)))
+    return 0;
 
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
   val = 0;
@@ -1934,7 +1939,8 @@ build_class_member_access_expr (tree object, tree member,
                       && integer_zerop (TREE_OPERAND (object, 0)));
 
       /* Convert OBJECT to the type of MEMBER.  */
-      if (!same_type_p (object_type, member_scope))
+      if (!same_type_p (TYPE_MAIN_VARIANT (object_type),
+                       TYPE_MAIN_VARIANT (member_scope)))
        {
          tree binfo;
          base_kind kind;
@@ -1944,7 +1950,7 @@ build_class_member_access_expr (tree object, tree member,
          if (binfo == error_mark_node)
            return error_mark_node;
 
-         /* It is invalid to use to try to get to a virtual base of a
+         /* It is invalid to try to get to a virtual base of a
             NULL object.  The most common cause is invalid use of
             offsetof macro.  */
          if (null_object_p && kind == bk_via_virtual)
@@ -1968,7 +1974,8 @@ build_class_member_access_expr (tree object, tree member,
         give the right answer.  Note that we complain whether or not they
         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 && CLASSTYPE_NON_POD_P (object_type))
+      if (null_object_p && warn_invalid_offsetof
+         && CLASSTYPE_NON_POD_P (object_type))
        {
          warning ("invalid access to non-static data member `%D' of NULL object", 
                   member);
@@ -2094,7 +2101,7 @@ lookup_destructor (tree object, tree scope, tree dtor_name)
     return build (PSEUDO_DTOR_EXPR, void_type_node, object, scope,
                  dtor_type);
   return lookup_member (object_type, complete_dtor_identifier,
-                       /*protect=*/1, /*want_type=*/0);
+                       /*protect=*/1, /*want_type=*/false);
 }
 
 /* This function is called by the parser to process a class member
@@ -2198,7 +2205,7 @@ finish_class_member_access_expr (tree object, tree name)
            {
              /* Look up the member.  */
              member = lookup_member (access_path, name, /*protect=*/1, 
-                                     /*want_type=*/0);
+                                     /*want_type=*/false);
              if (member == NULL_TREE)
                {
                  error ("'%D' has no member named '%E'", object_type, name);
@@ -2214,7 +2221,7 @@ finish_class_member_access_expr (tree object, tree name)
        {
          /* An unqualified name.  */
          member = lookup_member (object_type, name, /*protect=*/1, 
-                                 /*want_type=*/0);
+                                 /*want_type=*/false);
          if (member == NULL_TREE)
            {
              error ("'%D' has no member named '%E'", object_type, name);
@@ -2278,7 +2285,7 @@ build_ptrmemfunc_access_expr (tree ptrmem, tree member_name)
   ptrmem_type = TREE_TYPE (ptrmem);
   my_friendly_assert (TYPE_PTRMEMFUNC_P (ptrmem_type), 20020804);
   member = lookup_member (ptrmem_type, member_name, /*protect=*/0,
-                         /*want_type=*/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));
@@ -2301,8 +2308,8 @@ build_x_indirect_ref (ptr, errorstring)
   if (processing_template_decl)
     return build_min_nt (INDIRECT_REF, ptr);
 
-  rval = build_opfncall (INDIRECT_REF, LOOKUP_NORMAL, ptr, NULL_TREE,
-                        NULL_TREE);
+  rval = build_new_op (INDIRECT_REF, LOOKUP_NORMAL, ptr, NULL_TREE,
+                      NULL_TREE);
   if (rval)
     return rval;
   return build_indirect_ref (ptr, errorstring);
@@ -2345,7 +2352,6 @@ build_indirect_ref (ptr, errorstring)
           return error_mark_node;
         }
       else if (TREE_CODE (pointer) == ADDR_EXPR
-              && !flag_volatile
               && same_type_p (t, TREE_TYPE (TREE_OPERAND (pointer, 0))))
        /* The POINTER was something like `&x'.  We simplify `*&x' to
           `x'.  */
@@ -2360,8 +2366,7 @@ build_indirect_ref (ptr, errorstring)
          TREE_READONLY (ref) = CP_TYPE_CONST_P (t);
          TREE_THIS_VOLATILE (ref) = CP_TYPE_VOLATILE_P (t);
          TREE_SIDE_EFFECTS (ref)
-           = (TREE_THIS_VOLATILE (ref) || TREE_SIDE_EFFECTS (pointer)
-              || flag_volatile);
+           = (TREE_THIS_VOLATILE (ref) || TREE_SIDE_EFFECTS (pointer));
          return ref;
        }
     }
@@ -2650,12 +2655,10 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
 }
 
 tree
-build_function_call_real (function, params, require_complete, flags)
+build_function_call (function, params)
      tree function, params;
-     int require_complete, flags;
 {
   register tree fntype, fndecl;
-  register tree value_type;
   register tree coerced_params;
   tree result;
   tree name = NULL_TREE, assembler_name = NULL_TREE;
@@ -2726,20 +2729,10 @@ build_function_call_real (function, params, require_complete, flags)
   /* Convert the parameters to the types declared in the
      function prototype, or apply default promotions.  */
 
-  if (flags & LOOKUP_COMPLAIN)
-    coerced_params = convert_arguments (TYPE_ARG_TYPES (fntype),
-                                       params, fndecl, LOOKUP_NORMAL);
-  else
-    coerced_params = convert_arguments (TYPE_ARG_TYPES (fntype),
-                                       params, fndecl, 0);
-
+  coerced_params = convert_arguments (TYPE_ARG_TYPES (fntype),
+                                     params, fndecl, LOOKUP_NORMAL);
   if (coerced_params == error_mark_node)
-    {
-      if (flags & LOOKUP_SPECULATIVELY)
-       return NULL_TREE;
-      else
-       return error_mark_node;
-    }
+    return error_mark_node;
 
   /* Check for errors in format strings.  */
 
@@ -2760,27 +2753,7 @@ build_function_call_real (function, params, require_complete, flags)
        return result;
     }
 
-  /* Some built-in function calls will be evaluated at
-     compile-time in fold ().  */
-  result = fold (build_call (function, coerced_params));
-  value_type = TREE_TYPE (result);
-
-  if (require_complete)
-    {
-      if (TREE_CODE (value_type) == VOID_TYPE)
-       return result;
-      result = require_complete_type (result);
-    }
-  if (IS_AGGR_TYPE (value_type))
-    result = build_cplus_new (value_type, result);
-  return convert_from_reference (result);
-}
-
-tree
-build_function_call (function, params)
-     tree function, params;
-{
-  return build_function_call_real (function, params, 1, LOOKUP_NORMAL);
+  return build_cxx_call (function, params, coerced_params);
 }
 \f
 /* Convert the actual parameter expressions in the list VALUES
@@ -2973,6 +2946,183 @@ build_x_binary_op (code, arg1, arg2)
   return build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE);
 }
 
+#if 0
+
+tree
+build_template_expr (enum tree_code code, tree op0, tree op1, tree op2)
+{
+  tree type;
+
+  /* If any of the operands is erroneous the result is erroneous too.  */
+  if (error_operand_p (op0)
+      || (op1 && error_operand_p (op1))
+      || (op2 && error_operand_p (op2)))
+    return error_mark_node;
+      
+  if (dependent_type_p (TREE_TYPE (op0))
+      || (op1 && dependent_type_p (TREE_TYPE (op1)))
+      || (op2 && dependent_type_p (TREE_TYPE (op2))))
+    /* If at least one operand has a dependent type, we cannot
+       determine the type of the expression until instantiation time.  */
+    type = NULL_TREE;
+  else
+    {
+      struct z_candidate *cand;
+      tree op0_type;
+      tree op1_type;
+      tree op2_type;
+
+      /* None of the operands is dependent, so we can compute the type
+        of the expression at this point.  We must compute the type so
+        that in things like:
+
+          template <int I>
+          void f() { S<sizeof(I + 3)> s; ... }
+
+        we can tell that the type of "s" is non-dependent.
+
+        If we're processing a template argument, we do not want to
+        actually change the operands in any way.  Adding conversions,
+        performing constant folding, etc., would all change mangled
+        names.  For example, in:
+        
+          template <int I>
+          void f(S<sizeof(3 + 4 + I)>);
+        
+        we need to determine that "3 + 4 + I" has type "int", without
+        actually turning the expression into "7 + I".  */
+      cand = find_overloaded_op (code, op0, op1, op2);
+      if (cand) 
+       /* If an overloaded operator was found, the expression will
+          have the type returned by the function.  */
+       type = non_reference (TREE_TYPE (cand->fn));
+      else
+       {
+         /* There is no overloaded operator so we can just use the
+            default rules for determining the type of the operand.  */
+         op0_type = TREE_TYPE (op0);
+         op1_type = op1 ? TREE_TYPE (op1) : NULL_TREE;
+         op2_type = op2 ? TREE_TYPE (op2) : NULL_TREE;
+         type = NULL_TREE;
+
+         switch (code)
+           {
+           case MODIFY_EXPR:
+             /* [expr.ass]
+
+                The result of the assignment operation is the value
+                stored in the left operand.  */
+             type = op0_type;
+             break;
+           case COMPONENT_REF:
+             /* Implement this case.  */
+             break;
+           case POSTINCREMENT_EXPR:
+           case POSTDECREMENT_EXPR:
+             /* [expr.post.incr]
+
+                The type of the result is the cv-unqualified version
+                of the type of the operand.  */
+             type = TYPE_MAIN_VARIANT (op0_type);
+             break;
+           case PREINCREMENT_EXPR:
+           case PREDECREMENT_EXPR:
+             /* [expr.pre.incr]
+
+                The value is the new value of the operand.  */
+             type = op0_type;
+             break;
+           case INDIRECT_REF:
+             /* [expr.unary.op]
+
+                If the type of the expression is "pointer to T", the
+                type of the result is "T".  */
+             type = TREE_TYPE (op0_type);
+             break;
+           case ADDR_EXPR:
+             /* [expr.unary.op]
+
+                If the type of the expression is "T", the type of the
+                result is "pointer to T".  */
+             /* FIXME: Handle the pointer-to-member case.  */
+             break;
+           case MEMBER_REF:
+             /* FIXME: Implement this case.  */
+             break;
+           case LSHIFT_EXPR:
+           case RSHIFT_EXPR:
+             /* [expr.shift]
+
+                The type of the result is that of the promoted left
+                operand.  */
+             break;
+           case PLUS_EXPR:
+           case MINUS_EXPR:
+             /* FIXME: Be careful of special pointer-arithmetic
+                cases.  */
+             /* Fall through. */
+           case MAX_EXPR:
+           case MIN_EXPR:
+             /* These are GNU extensions; the result type is computed
+                as it would be for other arithmetic operators.  */
+             /* Fall through. */
+           case BIT_AND_EXPR:
+           case BIT_XOR_EXPR:
+           case BIT_IOR_EXPR:
+           case MULT_EXPR:
+           case TRUNC_DIV_EXPR:
+           case TRUNC_MOD_EXPR:
+             /* [expr.bit.and], [expr.xor], [expr.or], [expr.mul]
+
+                The usual arithmetic conversions are performed on the
+                operands and determine the type of the result.  */
+             /* FIXME: Check that this is possible.  */
+             type = type_after_usual_arithmetic_conversions (t1, t2);
+             break;
+           case GT_EXPR:
+           case LT_EXPR:
+           case GE_EXPR:
+           case LE_EXPR:
+           case EQ_EXPR:
+           case NE_EXPR:
+             /* [expr.rel]
+
+                The type of the result is bool.  */
+             type = boolean_type_node;
+             break;
+           case TRUTH_ANDIF_EXPR:
+           case TRUTH_ORIF_EXPR:
+             /* [expr.log.and], [expr.log.org]
+                
+                The result is a bool.  */
+             type = boolean_type_node;
+             break;
+           case COND_EXPR:
+             /* FIXME: Handle special rules for conditioanl
+                expressions.  */
+             break;
+           case COMPOUND_EXPR:
+             type = op1_type;
+             break;
+           default:
+             abort ();
+           }
+         /* If the type of the expression could not be determined,
+            something is wrong.  */
+         if (!type)
+           abort ();
+         /* If the type is erroneous, the expression is erroneous
+            too.  */
+         if (type == error_mark_node)
+           return error_mark_node;
+       }
+    }
+  
+  return build_min (code, type, op0, op1, op2, NULL_TREE);
+}
+
+#endif
+
 /* Build a binary-operation expression without default conversions.
    CODE is the kind of expression to build.
    This function differs from `build' in several ways:
@@ -3907,7 +4057,45 @@ condition_conversion (expr)
   t = fold (build1 (CLEANUP_POINT_EXPR, boolean_type_node, t));
   return t;
 }
-                              
+               
+/* Return an ADDR_EXPR giving the address of T.  This function
+   attempts no optimizations or simplifications; it is a low-level
+   primitive.  */
+
+tree
+build_address (tree t)
+{
+  tree addr;
+
+  if (error_operand_p (t) || !cxx_mark_addressable (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;
+}
+
+/* Return a NOP_EXPR converting EXPR to TYPE.  */
+
+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;
+}
+
 /* C++: Must handle pointers to members.
 
    Perhaps type instantiation should be extended to handle conversion
@@ -4241,7 +4429,11 @@ build_unary_op (code, xarg, noconvert)
             We could defer this in non-MS mode, but it's easier to give
             a useful error here.  */
 
-         tree base = TREE_TYPE (TREE_OPERAND (arg, 0));
+         /* Inside constant member functions, the `this' pointer
+            contains an extra const qualifier.  TYPE_MAIN_VARIANT
+            is used here to remove this const from the diagnostics
+            and the created OFFSET_REF.  */
+         tree base = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (arg, 0)));
          tree name = DECL_NAME (get_first_fn (TREE_OPERAND (arg, 1)));
 
          if (! flag_ms_extensions)
@@ -4249,9 +4441,15 @@ build_unary_op (code, xarg, noconvert)
              if (current_class_type
                  && TREE_OPERAND (arg, 0) == current_class_ref)
                /* An expression like &memfn.  */
-               pedwarn ("ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function.  Say `&%T::%D'", base, name);
+               pedwarn ("ISO C++ forbids taking the address of an unqualified"
+                        " or parenthesized non-static member function to form"
+                        " a pointer to member function.  Say `&%T::%D'",
+                        base, name);
              else
-               pedwarn ("ISO C++ forbids taking the address of a bound member function to form a pointer to member function.  Say `&%T::%D'", base, name);
+               pedwarn ("ISO C++ forbids taking the address of a bound member"
+                        " function to form a pointer to member function."
+                        "  Say `&%T::%D'",
+                        base, name);
            }
          arg = build_offset_ref (base, name);
         }
@@ -4297,9 +4495,6 @@ build_unary_op (code, xarg, noconvert)
       if (argtype != error_mark_node)
        argtype = build_pointer_type (argtype);
 
-      if (!cxx_mark_addressable (arg))
-       return error_mark_node;
-
       {
        tree addr;
 
@@ -4307,19 +4502,19 @@ build_unary_op (code, xarg, noconvert)
            && TREE_CODE (TREE_OPERAND (arg, 1)) == BASELINK)
          arg = BASELINK_FUNCTIONS (TREE_OPERAND (arg, 1));
 
-       if (TREE_CODE (arg) == COMPONENT_REF
-           && DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1)))
+       if (TREE_CODE (arg) != COMPONENT_REF)
+         addr = build_address (arg);
+       else if (DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1)))
          {
            error ("attempt to take address of bit-field structure member `%D'",
                   TREE_OPERAND (arg, 1));
            return error_mark_node;
          }
-       else if (TREE_CODE (arg) == COMPONENT_REF
-                && TREE_CODE (TREE_OPERAND (arg, 0)) == INDIRECT_REF
-                && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (arg, 0), 0))
-                    == INTEGER_CST))
+       else
          {
-           /* offsetof idiom, fold it.  */
+           /* 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)),
@@ -4332,13 +4527,6 @@ build_unary_op (code, xarg, noconvert)
            addr = fold (build (PLUS_EXPR, argtype, rval,
                                cp_convert (argtype, byte_position (field))));
          }
-       else
-         addr = build1 (ADDR_EXPR, argtype, arg);
-
-       /* Address of a static or external variable or
-          function counts as a constant */
-       if (staticp (arg))
-         TREE_CONSTANT (addr) = 1;
 
        if (TREE_CODE (argtype) == POINTER_TYPE
            && TREE_CODE (TREE_TYPE (argtype)) == METHOD_TYPE)
@@ -4552,7 +4740,7 @@ cxx_mark_addressable (exp)
          warning ("address requested for `%D', which is declared `register'",
                      x);
        TREE_ADDRESSABLE (x) = 1;
-       put_var_into_stack (x);
+       put_var_into_stack (x, /*rescan=*/true);
        return true;
 
       case FUNCTION_DECL:
@@ -4602,8 +4790,8 @@ build_x_compound_expr (list)
   if (rest == NULL_TREE)
     return build_compound_expr (list);
 
-  result = build_opfncall (COMPOUND_EXPR, LOOKUP_NORMAL,
-                          TREE_VALUE (list), TREE_VALUE (rest), NULL_TREE);
+  result = build_new_op (COMPOUND_EXPR, LOOKUP_NORMAL,
+                        TREE_VALUE (list), TREE_VALUE (rest), NULL_TREE);
   if (result)
     return build_x_compound_expr (tree_cons (NULL_TREE, result,
                                                  TREE_CHAIN (rest)));
@@ -4614,7 +4802,7 @@ build_x_compound_expr (list)
       /* the left-hand operand of a comma expression is like an expression
          statement: we should warn if it doesn't have any side-effects,
          unless it was explicitly cast to (void).  */
-      if ((extra_warnings || warn_unused_value)
+      if (warn_unused_value
            && !(TREE_CODE (TREE_VALUE(list)) == CONVERT_EXPR
                 && VOID_TYPE_P (TREE_TYPE (TREE_VALUE(list)))))
         warning("left-hand operand of comma expression has no effect");
@@ -5147,6 +5335,10 @@ build_modify_expr (lhs, modifycode, rhs)
                    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));
       newrhs = build_modify_expr (TREE_OPERAND (lhs, 0), modifycode, rhs);
       if (newrhs == error_mark_node)
        return error_mark_node;
@@ -5235,8 +5427,8 @@ build_modify_expr (lhs, modifycode, rhs)
            /* Do the default thing */;
          else
            {
-             result = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL,
-                                      lhs, rhs, make_node (NOP_EXPR));
+             result = build_new_op (MODIFY_EXPR, LOOKUP_NORMAL,
+                                    lhs, rhs, make_node (NOP_EXPR));
              if (result == NULL_TREE)
                return error_mark_node;
              return result;
@@ -5327,7 +5519,7 @@ build_modify_expr (lhs, modifycode, rhs)
          || TREE_CODE (TREE_TYPE (lhs)) == METHOD_TYPE
          /* If it's an aggregate and any field is const, then it is
             effectively const.  */
-         || (IS_AGGR_TYPE_CODE (TREE_CODE (lhstype))
+         || (CLASS_TYPE_P (lhstype)
              && C_TYPE_FIELDS_READONLY (lhstype))))
     readonly_error (lhs, "assignment", 0);
 
@@ -5352,14 +5544,6 @@ build_modify_expr (lhs, modifycode, rhs)
        }
     }
 
-  if (TREE_CODE (lhstype) != REFERENCE_TYPE)
-    {
-      if (TREE_SIDE_EFFECTS (lhs))
-       lhs = stabilize_reference (lhs);
-      if (TREE_SIDE_EFFECTS (newrhs))
-       newrhs = stabilize_reference (newrhs);
-    }
-
   /* Convert new value to destination type.  */
 
   if (TREE_CODE (lhstype) == ARRAY_TYPE)
@@ -5488,8 +5672,8 @@ build_x_modify_expr (lhs, modifycode, rhs)
 
   if (modifycode != NOP_EXPR)
     {
-      tree rval = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL, lhs, rhs,
-                                 make_node (modifycode));
+      tree rval = build_new_op (MODIFY_EXPR, LOOKUP_NORMAL, lhs, rhs,
+                               make_node (modifycode));
       if (rval)
        return rval;
     }
@@ -5538,9 +5722,8 @@ get_delta_difference (from, to, force)
       if (virt_binfo)
         {
           /* This is a reinterpret cast, we choose to do nothing.  */
-          warning ("pointer to member cast via virtual base `%T' of `%T'",
-                     BINFO_TYPE (virt_binfo),
-                     BINFO_TYPE (BINFO_INHERITANCE_CHAIN (virt_binfo)));
+          warning ("pointer to member cast via virtual base `%T'",
+                  BINFO_TYPE (virt_binfo));
           return delta;
         }
       delta = BINFO_OFFSET (binfo);
@@ -5557,13 +5740,11 @@ get_delta_difference (from, to, force)
     {
       /* This is a reinterpret cast, we choose to do nothing.  */
       if (force)
-        warning ("pointer to member cast via virtual base `%T' of `%T'",
-                    BINFO_TYPE (virt_binfo),
-                    BINFO_TYPE (BINFO_INHERITANCE_CHAIN (virt_binfo)));
+        warning ("pointer to member cast via virtual base `%T'",
+                BINFO_TYPE (virt_binfo));
       else
-       error ("pointer to member conversion via virtual base `%T' of `%T'",
-                 BINFO_TYPE (virt_binfo),
-                  BINFO_TYPE (BINFO_INHERITANCE_CHAIN (virt_binfo)));
+       error ("pointer to member conversion via virtual base `%T'",
+              BINFO_TYPE (virt_binfo));
       return delta;
     }
   delta = BINFO_OFFSET (binfo);
@@ -5592,7 +5773,7 @@ build_ptrmemfunc1 (type, delta, pfn)
   /* Finish creating the initializer.  */
   u = tree_cons (pfn_field, pfn,
                 build_tree_list (delta_field, delta));
-  u = build (CONSTRUCTOR, type, NULL_TREE, u);
+  u = build_constructor (type, u);
   TREE_CONSTANT (u) = TREE_CONSTANT (pfn) && TREE_CONSTANT (delta);
   TREE_STATIC (u) = (TREE_CONSTANT (u)
                     && (initializer_constant_valid_p (pfn, TREE_TYPE (pfn))
@@ -5619,11 +5800,17 @@ build_ptrmemfunc (type, pfn, force)
      int force;
 {
   tree fn;
-  tree pfn_type = TREE_TYPE (pfn);
-  tree to_type = build_ptrmemfunc_type (type);
+  tree pfn_type;
+  tree to_type;
+
+  if (error_operand_p (pfn))
+    return error_mark_node;
+
+  pfn_type = TREE_TYPE (pfn);
+  to_type = build_ptrmemfunc_type (type);
 
   /* Handle multiple conversions of pointer to member functions.  */
-  if (TYPE_PTRMEMFUNC_P (TREE_TYPE (pfn)))
+  if (TYPE_PTRMEMFUNC_P (pfn_type))
     {
       tree delta = NULL_TREE;
       tree npfn = NULL_TREE;
@@ -6004,7 +6191,7 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
 
       if (fndecl)
        savew = warningcount, savee = errorcount;
-      rhs = initialize_reference (type, rhs);
+      rhs = initialize_reference (type, rhs, /*decl=*/NULL_TREE);
       if (fndecl)
        {
          if (warningcount > savew)
@@ -6082,8 +6269,7 @@ c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
          tree type = TREE_TYPE (o[i]);
          if (type != error_mark_node
              && (CP_TYPE_CONST_P (type)
-                 || (IS_AGGR_TYPE_CODE (TREE_CODE (type))
-                     && C_TYPE_FIELDS_READONLY (type))))
+                 || (CLASS_TYPE_P (type) && C_TYPE_FIELDS_READONLY (type))))
            readonly_error (o[i], "modification by `asm'", 1);
        }
     }
@@ -6384,15 +6570,14 @@ comp_ptr_ttypes_real (to, from, constp)
        }
 
       if (TREE_CODE (to) != POINTER_TYPE)
-       return 
-         same_type_ignoring_top_level_qualifiers_p (to, from)
-         && (constp >= 0 || to_more_cv_qualified);
+       return ((constp >= 0 || to_more_cv_qualified)
+               && same_type_ignoring_top_level_qualifiers_p (to, from));
     }
 }
 
-/* When comparing, say, char ** to char const **, this function takes the
-   'char *' and 'char const *'.  Do not pass non-pointer types to this
-   function.  */
+/* When comparing, say, char ** to char const **, this function takes
+   the 'char *' and 'char const *'.  Do not pass non-pointer/reference
+   types to this function.  */
 
 int
 comp_ptr_ttypes (to, from)