]> gcc.gnu.org Git - gcc.git/blobdiff - gcc/cp/call.c
call.c: Fix comment formatting.
[gcc.git] / gcc / cp / call.c
index b2f9291139fdf103a2266a83423b0f3597a236a3..2dc4f2240c640e0154b5efa43e93efcb3ff653be 100644 (file)
@@ -36,8 +36,9 @@ Boston, MA 02111-1307, USA.  */
 #include "toplev.h"
 #include "expr.h"
 #include "diagnostic.h"
-
-extern int inhibit_warnings;
+#include "intl.h"
+#include "target.h"
+#include "convert.h"
 
 static tree build_field_call (tree, tree, tree);
 static struct z_candidate * tourney (struct z_candidate *);
@@ -46,18 +47,19 @@ static int joust (struct z_candidate *, struct z_candidate *, bool);
 static int compare_ics (tree, tree);
 static tree build_over_call (struct z_candidate *, int);
 static tree build_java_interface_fn_ref (tree, tree);
-#define convert_like(CONV, EXPR) \
-  convert_like_real ((CONV), (EXPR), NULL_TREE, 0, 0)
-#define convert_like_with_context(CONV, EXPR, FN, ARGNO) \
-  convert_like_real ((CONV), (EXPR), (FN), (ARGNO), 0)
-static tree convert_like_real (tree, tree, tree, int, int);
+#define convert_like(CONV, EXPR)                               \
+  convert_like_real ((CONV), (EXPR), NULL_TREE, 0, 0,          \
+                    /*issue_conversion_warnings=*/true)
+#define convert_like_with_context(CONV, EXPR, FN, ARGNO)       \
+  convert_like_real ((CONV), (EXPR), (FN), (ARGNO), 0,                 \
+                    /*issue_conversion_warnings=*/true)
+static tree convert_like_real (tree, tree, tree, int, int, bool);
 static void op_error (enum tree_code, enum tree_code, tree, tree,
                            tree, const char *);
 static tree build_object_call (tree, tree);
 static tree resolve_args (tree);
 static struct z_candidate *build_user_type_conversion_1 (tree, tree, int);
-static void print_z_candidate (const char *msgid, struct z_candidate *,
-                              void (*)(const char *, ...));
+static void print_z_candidate (const char *, struct z_candidate *);
 static void print_z_candidates (struct z_candidate *);
 static tree build_this (tree);
 static struct z_candidate *splice_viable (struct z_candidate *, bool, bool *);
@@ -87,7 +89,6 @@ static struct z_candidate *add_function_candidate
 static tree implicit_conversion (tree, tree, tree, int);
 static tree standard_conversion (tree, tree, tree);
 static tree reference_binding (tree, tree, tree, int);
-static tree non_reference (tree);
 static tree build_conv (enum tree_code, tree, tree);
 static bool is_subseq (tree, tree);
 static tree maybe_handle_ref_bind (tree *);
@@ -103,11 +104,12 @@ static tree direct_reference_binding (tree, tree);
 static bool promoted_arithmetic_type_p (tree);
 static tree conditional_conversion (tree, tree);
 static char *name_as_c_string (tree, tree, bool *);
-static tree call_builtin_trap (void);
+static tree call_builtin_trap (tree);
 static tree prep_operand (tree);
 static void add_candidates (tree, tree, tree, bool, tree, tree,
                            int, struct z_candidate **);
 static tree merge_conversion_sequences (tree, tree);
+static bool magic_varargs_p (tree);
 
 tree
 build_vfield_ref (tree datum, tree type)
@@ -205,106 +207,6 @@ check_dtor_name (tree basetype, tree name)
   return false;
 }
 
-/* Build a method call of the form `EXP->SCOPES::NAME (PARMS)'.
-   This is how virtual function calls are avoided.  */
-
-tree
-build_scoped_method_call (tree exp, tree basetype, tree name, tree parms)
-{
-  /* Because this syntactic form does not allow
-     a pointer to a base class to be `stolen',
-     we need not protect the derived->base conversion
-     that happens here.
-     
-     @@ But we do have to check access privileges later.  */
-  tree binfo, decl;
-  tree type = TREE_TYPE (exp);
-
-  if (type == error_mark_node
-      || basetype == error_mark_node)
-    return error_mark_node;
-
-  if (processing_template_decl)
-    {
-      name = build_min_nt (SCOPE_REF, basetype, name);
-      return build_min_nt (METHOD_CALL_EXPR, name, exp, parms, NULL_TREE);
-    }
-
-  if (TREE_CODE (type) == REFERENCE_TYPE)
-    type = TREE_TYPE (type);
-
-  if (TREE_CODE (basetype) == TREE_VEC)
-    {
-      binfo = basetype;
-      basetype = BINFO_TYPE (binfo);
-    }
-  else
-    binfo = NULL_TREE;
-
-  /* Check the destructor call syntax.  */
-  if (TREE_CODE (name) == BIT_NOT_EXPR)
-    {
-      /* We can get here if someone writes their destructor call like
-        `obj.NS::~T()'; this isn't really a scoped method call, so hand
-        it off.  */
-      if (TREE_CODE (basetype) == NAMESPACE_DECL)
-       return build_method_call (exp, name, parms, NULL_TREE, LOOKUP_NORMAL);
-
-      if (! check_dtor_name (basetype, name))
-       error ("qualified type `%T' does not match destructor name `~%T'",
-                 basetype, TREE_OPERAND (name, 0));
-
-      /* Destructors can be "called" for simple types; see 5.2.4 and 12.4 Note
-        that explicit ~int is caught in the parser; this deals with typedefs
-        and template parms.  */
-      if (! IS_AGGR_TYPE (basetype))
-       {
-         if (TYPE_MAIN_VARIANT (type) != TYPE_MAIN_VARIANT (basetype))
-           error ("type of `%E' does not match destructor type `%T' (type was `%T')",
-                     exp, basetype, type);
-
-         return cp_convert (void_type_node, exp);
-       }
-    }
-
-  if (TREE_CODE (basetype) == NAMESPACE_DECL)
-    {
-      error ("`%D' is a namespace", basetype);
-      return error_mark_node;
-    }
-  if (! is_aggr_type (basetype, 1))
-    return error_mark_node;
-
-  if (! IS_AGGR_TYPE (type))
-    {
-      error ("base object `%E' of scoped method call is of non-aggregate type `%T'",
-               exp, type);
-      return error_mark_node;
-    }
-
-  decl = build_scoped_ref (exp, basetype, &binfo);
-
-  if (binfo)
-    {
-      /* Call to a destructor.  */
-      if (TREE_CODE (name) == BIT_NOT_EXPR)
-       {
-         if (! TYPE_HAS_DESTRUCTOR (TREE_TYPE (decl)))
-           return cp_convert (void_type_node, exp);
-         
-         return build_delete (TREE_TYPE (decl), decl, 
-                              sfk_complete_destructor,
-                              LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR,
-                              0);
-       }
-
-      /* Call to a method.  */
-      return build_method_call (decl, name, parms, binfo,
-                               LOOKUP_NORMAL|LOOKUP_NONVIRTUAL);
-    }
-  return error_mark_node;
-}
-
 /* We want the address of a function or method.  We avoid creating a
    pointer-to-member function.  */
 
@@ -317,24 +219,16 @@ build_addr_func (tree function)
      functions.  */
   if (TREE_CODE (type) == METHOD_TYPE)
     {
-      tree addr;
-
-      type = build_pointer_type (type);
-
-      if (!cxx_mark_addressable (function))
-       return error_mark_node;
-
-      addr = build1 (ADDR_EXPR, type, function);
-
-      /* Address of a static or external variable or function counts
-        as a constant */
-      if (staticp (function))
-       TREE_CONSTANT (addr) = 1;
-
-      function = addr;
+      if (TREE_CODE (function) == OFFSET_REF)
+       {
+         tree object = build_address (TREE_OPERAND (function, 0));
+         return get_member_function_from_ptrfunc (&object,
+                                                  TREE_OPERAND (function, 1));
+       }
+      function = build_address (function);
     }
   else
-    function = default_conversion (function);
+    function = decay_conversion (function);
 
   return function;
 }
@@ -410,10 +304,8 @@ build_call (tree function, tree parms)
                                    TREE_VALUE (tmp), t);
        }
 
-  function = build_nt (CALL_EXPR, function, parms, NULL_TREE);
+  function = build (CALL_EXPR, result_type, function, parms);
   TREE_HAS_CONSTRUCTOR (function) = is_constructor;
-  TREE_TYPE (function) = result_type;
-  TREE_SIDE_EFFECTS (function) = 1;
   TREE_NOTHROW (function) = nothrow;
   
   return function;
@@ -434,8 +326,7 @@ build_call (tree function, tree parms)
 
    BASETYPE_PATH, if non-NULL, contains a chain from the type of INSTANCE
    down to the real instance type to use for access checking.  We need this
-   information to get protected accesses correct.  This parameter is used
-   by build_member_call.
+   information to get protected accesses correct.
 
    FLAGS is the logical disjunction of zero or more LOOKUP_
    flags.  See cp-tree.h for more info.
@@ -468,17 +359,13 @@ build_method_call (tree instance, tree name, tree parms,
   n_build_method_call++;
 #endif
 
-  if (instance == error_mark_node
+  if (error_operand_p (instance)
       || name == error_mark_node
-      || parms == error_mark_node
-      || (instance && TREE_TYPE (instance) == error_mark_node))
+      || parms == error_mark_node)
     return error_mark_node;
 
-  if (processing_template_decl)
-    return build_min_nt (METHOD_CALL_EXPR, name, instance, parms, NULL_TREE);
+  my_friendly_assert (!processing_template_decl, 20030707);
 
-  if (TREE_CODE (instance) == OFFSET_REF)
-    instance = resolve_offset_ref (instance);
   if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
     instance = convert_from_reference (instance);
   object_type = TREE_TYPE (instance);
@@ -496,7 +383,7 @@ build_method_call (tree instance, tree name, tree parms,
           TREE_OPERAND (name, 0), object_type);
 
       if (! TYPE_HAS_DESTRUCTOR (complete_type (object_type)))
-       return cp_convert (void_type_node, instance);
+       return convert_to_void (instance, /*implicit=*/NULL);
       instance = default_conversion (instance);
       instance_ptr = build_unary_op (ADDR_EXPR, instance, 0);
       return build_delete (build_pointer_type (object_type),
@@ -528,7 +415,7 @@ build_method_call (tree instance, tree name, tree parms,
   else
     fn = lookup_member (object_type, name, /*protect=*/2, /*want_type=*/false);
   
-  if (fn && TREE_CODE (fn) == TREE_LIST && !BASELINK_P (fn))
+  if (fn && TREE_CODE (fn) == TREE_LIST)
     {
       error ("request for member `%D' is ambiguous", name);
       print_candidates (fn);
@@ -537,10 +424,7 @@ build_method_call (tree instance, tree name, tree parms,
 
   /* If the name could not be found, issue an error.  */
   if (!fn)
-    {
-      unqualified_name_lookup_error (name);
-      return error_mark_node;
-    }
+    return unqualified_name_lookup_error (name);
 
   if (BASELINK_P (fn) && has_template_args)
     BASELINK_FUNCTIONS (fn)
@@ -679,23 +563,12 @@ build_conv (enum tree_code code, tree type, tree from)
   return t;
 }
 
-/* If T is a REFERENCE_TYPE return the type to which T refers.
-   Otherwise, return T itself.  */
-
-static tree
-non_reference (tree t)
-{
-  if (TREE_CODE (t) == REFERENCE_TYPE)
-    t = TREE_TYPE (t);
-  return t;
-}
-
 tree
 strip_top_quals (tree t)
 {
   if (TREE_CODE (t) == ARRAY_TYPE)
     return t;
-  return TYPE_MAIN_VARIANT (t);
+  return cp_build_qualified_type (t, 0);
 }
 
 /* Returns the standard conversion path (see [conv]) from type FROM to type
@@ -709,8 +582,7 @@ standard_conversion (tree to, tree from, tree expr)
   tree conv;
   bool fromref = false;
 
-  if (TREE_CODE (to) == REFERENCE_TYPE)
-    to = TREE_TYPE (to);
+  to = non_reference (to);
   if (TREE_CODE (from) == REFERENCE_TYPE)
     {
       fromref = true;
@@ -722,7 +594,7 @@ standard_conversion (tree to, tree from, tree expr)
   if ((TYPE_PTRFN_P (to) || TYPE_PTRMEMFUNC_P (to))
       && expr && type_unknown_p (expr))
     {
-      expr = instantiate_type (to, expr, tf_none);
+      expr = instantiate_type (to, expr, tf_conv);
       if (expr == error_mark_node)
        return NULL_TREE;
       from = TREE_TYPE (expr);
@@ -748,7 +620,7 @@ standard_conversion (tree to, tree from, tree expr)
   else if (fromref || (expr && lvalue_p (expr)))
     conv = build_conv (RVALUE_CONV, from, conv);
 
-   /* Allow conversion between `__complex__' data types  */
+   /* Allow conversion between `__complex__' data types.  */
   if (tcode == COMPLEX_TYPE && fcode == COMPLEX_TYPE)
     {
       /* The standard conversion sequence to convert FROM to TO is
@@ -771,11 +643,15 @@ standard_conversion (tree to, tree from, tree expr)
   if (same_type_p (from, to))
     return conv;
 
-  if ((tcode == POINTER_TYPE || TYPE_PTRMEMFUNC_P (to))
+  if ((tcode == POINTER_TYPE || TYPE_PTR_TO_MEMBER_P (to))
       && expr && null_ptr_cst_p (expr))
-    {
-      conv = build_conv (STD_CONV, to, conv);
-    }
+    conv = build_conv (STD_CONV, to, conv);
+  else if (tcode == POINTER_TYPE && fcode == POINTER_TYPE
+          && TREE_CODE (TREE_TYPE (to)) == VECTOR_TYPE
+          && TREE_CODE (TREE_TYPE (from)) == VECTOR_TYPE
+          && ((*targetm.vector_opaque_p) (TREE_TYPE (to))
+              || (*targetm.vector_opaque_p) (TREE_TYPE (from))))
+    conv = build_conv (STD_CONV, to, conv);
   else if ((tcode == INTEGER_TYPE && fcode == POINTER_TYPE)
           || (tcode == POINTER_TYPE && fcode == INTEGER_TYPE))
     {
@@ -784,65 +660,88 @@ standard_conversion (tree to, tree from, tree expr)
       conv = build_conv (STD_CONV, to, conv);
       ICS_BAD_FLAG (conv) = 1;
     }
-  else if (tcode == ENUMERAL_TYPE && fcode == INTEGER_TYPE
-          && TYPE_PRECISION (to) == TYPE_PRECISION (from))
+  else if (tcode == ENUMERAL_TYPE && fcode == INTEGER_TYPE)
     {
       /* For backwards brain damage compatibility, allow interconversion of
         enums and integers with a pedwarn.  */
       conv = build_conv (STD_CONV, to, conv);
       ICS_BAD_FLAG (conv) = 1;
     }
-  else if (tcode == POINTER_TYPE && fcode == POINTER_TYPE)
+  else if ((tcode == POINTER_TYPE && fcode == POINTER_TYPE)
+          || (TYPE_PTRMEM_P (to) && TYPE_PTRMEM_P (from)))
     {
-      enum tree_code ufcode = TREE_CODE (TREE_TYPE (from));
-      enum tree_code utcode = TREE_CODE (TREE_TYPE (to));
+      tree to_pointee;
+      tree from_pointee;
 
-      if (same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (from),
-                                                    TREE_TYPE (to)))
+      if (tcode == POINTER_TYPE
+         && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (from),
+                                                       TREE_TYPE (to)))
        ;
-      else if (utcode == VOID_TYPE && ufcode != OFFSET_TYPE
-              && ufcode != FUNCTION_TYPE)
+      else if (VOID_TYPE_P (TREE_TYPE (to))
+              && !TYPE_PTRMEM_P (from)
+              && TREE_CODE (TREE_TYPE (from)) != FUNCTION_TYPE)
        {
          from = build_pointer_type
            (cp_build_qualified_type (void_type_node, 
                                      cp_type_quals (TREE_TYPE (from))));
          conv = build_conv (PTR_CONV, from, conv);
        }
-      else if (ufcode == OFFSET_TYPE && utcode == OFFSET_TYPE)
+      else if (TYPE_PTRMEM_P (from))
        {
-         tree fbase = TYPE_OFFSET_BASETYPE (TREE_TYPE (from));
-         tree tbase = TYPE_OFFSET_BASETYPE (TREE_TYPE (to));
+         tree fbase = TYPE_PTRMEM_CLASS_TYPE (from);
+         tree tbase = TYPE_PTRMEM_CLASS_TYPE (to);
 
          if (DERIVED_FROM_P (fbase, tbase)
              && (same_type_ignoring_top_level_qualifiers_p
-                 (TREE_TYPE (TREE_TYPE (from)),
-                  TREE_TYPE (TREE_TYPE (to)))))
+                 (TYPE_PTRMEM_POINTED_TO_TYPE (from),
+                  TYPE_PTRMEM_POINTED_TO_TYPE (to))))
            {
-             from = build_ptrmem_type (tbase, TREE_TYPE (TREE_TYPE (from)));
+             from = build_ptrmem_type (tbase, 
+                                       TYPE_PTRMEM_POINTED_TO_TYPE (from));
              conv = build_conv (PMEM_CONV, from, conv);
            }
        }
       else if (IS_AGGR_TYPE (TREE_TYPE (from))
-              && IS_AGGR_TYPE (TREE_TYPE (to)))
+              && IS_AGGR_TYPE (TREE_TYPE (to))
+              /* [conv.ptr]
+                 
+                 An rvalue of type "pointer to cv D," where D is a
+                 class type, can be converted to an rvalue of type
+                 "pointer to cv B," where B is a base class (clause
+                 _class.derived_) of D.  If B is an inaccessible
+                 (clause _class.access_) or ambiguous
+                 (_class.member.lookup_) base class of D, a program
+                 that necessitates this conversion is ill-formed.  */
+              /* Therefore, we use DERIVED_FROM_P, and not
+                 ACESSIBLY_UNIQUELY_DERIVED_FROM_P, in this test.  */
+              && DERIVED_FROM_P (TREE_TYPE (to), TREE_TYPE (from)))
        {
-         if (DERIVED_FROM_P (TREE_TYPE (to), TREE_TYPE (from)))
-           {
-             from = 
-               cp_build_qualified_type (TREE_TYPE (to),
-                                        cp_type_quals (TREE_TYPE (from)));
-             from = build_pointer_type (from);
-             conv = build_conv (PTR_CONV, from, conv);
-           }
+         from = 
+           cp_build_qualified_type (TREE_TYPE (to),
+                                    cp_type_quals (TREE_TYPE (from)));
+         from = build_pointer_type (from);
+         conv = build_conv (PTR_CONV, from, conv);
+       }
+
+      if (tcode == POINTER_TYPE)
+       {
+         to_pointee = TREE_TYPE (to);
+         from_pointee = TREE_TYPE (from);
+       }
+      else
+       {
+         to_pointee = TYPE_PTRMEM_POINTED_TO_TYPE (to);
+         from_pointee = TYPE_PTRMEM_POINTED_TO_TYPE (from);
        }
 
       if (same_type_p (from, to))
        /* OK */;
-      else if (comp_ptr_ttypes (TREE_TYPE (to), TREE_TYPE (from)))
+      else if (comp_ptr_ttypes (to_pointee, from_pointee))
        conv = build_conv (QUAL_CONV, to, conv);
       else if (expr && string_conv_p (to, expr, 0))
        /* converting from string constant to char *.  */
        conv = build_conv (QUAL_CONV, to, conv);
-      else if (ptr_reasonably_similar (TREE_TYPE (to), TREE_TYPE (from)))
+      else if (ptr_reasonably_similar (to_pointee, from_pointee))
        {
          conv = build_conv (PTR_CONV, to, conv);
          ICS_BAD_FLAG (conv) = 1;
@@ -867,21 +766,33 @@ standard_conversion (tree to, tree from, tree expr)
        return 0;
 
       from = cp_build_qualified_type (tbase, cp_type_quals (fbase));
-      from = build_cplus_method_type (from, TREE_TYPE (fromfn),
-                                     TREE_CHAIN (TYPE_ARG_TYPES (fromfn)));
+      from = build_method_type_directly (from, 
+                                        TREE_TYPE (fromfn),
+                                        TREE_CHAIN (TYPE_ARG_TYPES (fromfn)));
       from = build_ptrmemfunc_type (build_pointer_type (from));
       conv = build_conv (PMEM_CONV, from, conv);
     }
   else if (tcode == BOOLEAN_TYPE)
     {
-      if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE
-            || fcode == POINTER_TYPE || TYPE_PTRMEMFUNC_P (from)))
-       return 0;
+      /* [conv.bool]
 
-      conv = build_conv (STD_CONV, to, conv);
-      if (fcode == POINTER_TYPE
-         || (TYPE_PTRMEMFUNC_P (from) && ICS_STD_RANK (conv) < PBOOL_RANK))
-       ICS_STD_RANK (conv) = PBOOL_RANK;
+          An rvalue of arithmetic, enumeration, pointer, or pointer to
+         member type can be converted to an rvalue of type bool.  */
+      if (ARITHMETIC_TYPE_P (from)
+         || fcode == ENUMERAL_TYPE
+         || fcode == POINTER_TYPE
+         || TYPE_PTR_TO_MEMBER_P (from))
+       {
+         conv = build_conv (STD_CONV, to, conv);
+         if (fcode == POINTER_TYPE
+             || TYPE_PTRMEM_P (from)
+             || (TYPE_PTRMEMFUNC_P (from) 
+                 && ICS_STD_RANK (conv) < PBOOL_RANK))
+           ICS_STD_RANK (conv) = PBOOL_RANK;
+         return conv;
+       }
+      
+      return NULL_TREE;
     }
   /* We don't check for ENUMERAL_TYPE here because there are no standard
      conversions to enum type.  */
@@ -893,10 +804,14 @@ standard_conversion (tree to, tree from, tree expr)
       conv = build_conv (STD_CONV, to, conv);
 
       /* Give this a better rank if it's a promotion.  */
-      if (to == type_promotes_to (from)
+      if (same_type_p (to, type_promotes_to (from))
          && ICS_STD_RANK (TREE_OPERAND (conv, 0)) <= PROMO_RANK)
        ICS_STD_RANK (conv) = PROMO_RANK;
     }
+  else if (fcode == VECTOR_TYPE && tcode == VECTOR_TYPE
+      && ((*targetm.vector_opaque_p) (from)
+         || (*targetm.vector_opaque_p) (to)))
+    return build_conv (STD_CONV, to, conv);
   else if (IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from)
           && is_properly_derived_from (from, to))
     {
@@ -1179,14 +1094,14 @@ reference_binding (tree rto, tree rfrom, tree expr, int flags)
         -- is an lvalue (but not an lvalue for a bit-field), and "cv1 T1"
            is reference-compatible with "cv2 T2,"
         
-        the reference is bound directly to the initializer exprssion
+        the reference is bound directly to the initializer expression
         lvalue.  */
       conv = build1 (IDENTITY_CONV, from, expr);
       conv = direct_reference_binding (rto, conv);
-      if ((lvalue_p & clk_bitfield) != 0 
-         && CP_TYPE_CONST_NON_VOLATILE_P (to))
+      if ((lvalue_p & clk_bitfield) != 0
+         || ((lvalue_p & clk_packed) != 0 && !TYPE_PACKED (to)))
        /* For the purposes of overload resolution, we ignore the fact
-          this expression is a bitfield. (In particular,
+          this expression is a bitfield or packed field. (In particular,
           [over.ics.ref] says specifically that a function with a
           non-const reference parameter is viable even if the
           argument is a bitfield.)
@@ -1197,13 +1112,14 @@ reference_binding (tree rto, tree rfrom, tree expr, int flags)
           a temporary, so we just issue an error when the conversion
           actually occurs.  */
        NEED_TEMPORARY_P (conv) = 1;
+                                       
       return conv;
     }
   else if (CLASS_TYPE_P (from) && !(flags & LOOKUP_NO_CONVERSION))
     {
       /* [dcl.init.ref]
 
-        If the initializer exprsesion
+        If the initializer expression
 
         -- has a class type (i.e., T2 is a class type) can be
            implicitly converted to an lvalue of type "cv3 T3," where
@@ -1295,14 +1211,6 @@ implicit_conversion (tree to, tree from, tree expr, int flags)
 {
   tree conv;
 
-  /* Resolve expressions like `A::p' that we thought might become
-     pointers-to-members.  */
-  if (expr && TREE_CODE (expr) == OFFSET_REF)
-    {
-      expr = resolve_offset_ref (expr);
-      from = TREE_TYPE (expr);
-    }
-
   if (from == error_mark_node || to == error_mark_node
       || expr == error_mark_node)
     return NULL_TREE;
@@ -1344,8 +1252,7 @@ add_candidate (struct z_candidate **candidates,
               tree fn, tree args, tree convs, tree access_path, 
               tree conversion_path, int viable)
 {
-  struct z_candidate *cand
-    = (struct z_candidate *) ggc_alloc_cleared (sizeof (struct z_candidate));
+  struct z_candidate *cand = ggc_alloc_cleared (sizeof (struct z_candidate));
 
   cand->fn = fn;
   cand->args = args;
@@ -1729,8 +1636,7 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
             T       operator-(T);  */
 
     case CONVERT_EXPR: /* unary + */
-      if (TREE_CODE (type1) == POINTER_TYPE
-         && TREE_CODE (TREE_TYPE (type1)) != OFFSET_TYPE)
+      if (TREE_CODE (type1) == POINTER_TYPE)
        break;
     case NEGATE_EXPR:
       if (ARITHMETIC_TYPE_P (type1))
@@ -1755,12 +1661,10 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
 
     case MEMBER_REF:
       if (TREE_CODE (type1) == POINTER_TYPE
-         && (TYPE_PTRMEMFUNC_P (type2) || TYPE_PTRMEM_P (type2)))
+         && TYPE_PTR_TO_MEMBER_P (type2))
        {
          tree c1 = TREE_TYPE (type1);
-         tree c2 = (TYPE_PTRMEMFUNC_P (type2)
-                    ? TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (type2)))
-                    : TYPE_OFFSET_BASETYPE (TREE_TYPE (type2)));
+         tree c2 = TYPE_PTRMEM_CLASS_TYPE (type2);
 
          if (IS_AGGR_TYPE (c1) && DERIVED_FROM_P (c2, c1)
              && (TYPE_PTRMEMFUNC_P (type2)
@@ -1830,19 +1734,17 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
       if ((TYPE_PTRMEMFUNC_P (type1) && TYPE_PTRMEMFUNC_P (type2))
          || (TYPE_PTRMEM_P (type1) && TYPE_PTRMEM_P (type2)))
        break;
-      if ((TYPE_PTRMEMFUNC_P (type1) || TYPE_PTRMEM_P (type1))
-         && null_ptr_cst_p (args[1]))
+      if (TYPE_PTR_TO_MEMBER_P (type1) && null_ptr_cst_p (args[1]))
        {
          type2 = type1;
          break;
        }
-      if ((TYPE_PTRMEMFUNC_P (type2) || TYPE_PTRMEM_P (type2))
-         && null_ptr_cst_p (args[0]))
+      if (TYPE_PTR_TO_MEMBER_P (type2) && null_ptr_cst_p (args[0]))
        {
          type1 = type2;
          break;
        }
-      /* FALLTHROUGH */
+      /* Fall through.  */
     case LT_EXPR:
     case GT_EXPR:
     case LE_EXPR:
@@ -2008,12 +1910,8 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
        break;
 
       /* Otherwise, the types should be pointers.  */
-      if (!(TREE_CODE (type1) == POINTER_TYPE
-           || TYPE_PTRMEM_P (type1)
-           || TYPE_PTRMEMFUNC_P (type1))
-         || !(TREE_CODE (type2) == POINTER_TYPE
-              || TYPE_PTRMEM_P (type2)
-              || TYPE_PTRMEMFUNC_P (type2)))
+      if (!(TYPE_PTR_P (type1) || TYPE_PTR_TO_MEMBER_P (type1))
+         || !(TYPE_PTR_P (type2) || TYPE_PTR_TO_MEMBER_P (type2)))
        return;
       
       /* We don't check that the two types are the same; the logic
@@ -2031,8 +1929,8 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
   if (type2 && !same_type_p (type1, type2)
       && TREE_CODE (type1) == TREE_CODE (type2)
       && (TREE_CODE (type1) == REFERENCE_TYPE
-         || (TREE_CODE (type1) == POINTER_TYPE
-             && TYPE_PTRMEM_P (type1) == TYPE_PTRMEM_P (type2))
+         || (TYPE_PTR_P (type1) && TYPE_PTR_P (type2))
+         || (TYPE_PTRMEM_P (type1) && TYPE_PTRMEM_P (type2))
          || TYPE_PTRMEMFUNC_P (type1)
          || IS_AGGR_TYPE (type1)
          || TREE_CODE (type1) == ENUMERAL_TYPE))
@@ -2139,7 +2037,7 @@ add_builtin_candidates (struct z_candidate **candidates, enum tree_code code,
     case GT_EXPR:
     case GE_EXPR:
       enum_p = 1;
-      /* FALLTHROUGH */
+      /* Fall through.  */
     
     default:
       ref1 = 0;
@@ -2437,34 +2335,37 @@ equal_functions (tree fn1, tree fn2)
   return fn1 == fn2;
 }
 
-/* Print information about one overload candidate CANDIDATE.  STR is the
-   text to print before the candidate itself and ERRFN is the routine
-   (i.e. error, warning or pedwarn) used to do the printing.  */
+/* Print information about one overload candidate CANDIDATE.  MSGSTR
+   is the text to print before the candidate itself.
+
+   NOTE: Unlike most diagnostic functions in GCC, MSGSTR is expected
+   to have been run through gettext by the caller.  This wart makes
+   life simpler in print_z_candidates and for the translators.  */
 
 static void
-print_z_candidate (const char *msgid, struct z_candidate *candidate,
-                  void (*errfn)(const char *, ...))
+print_z_candidate (const char *msgstr, struct z_candidate *candidate)
 {
   if (TREE_CODE (candidate->fn) == IDENTIFIER_NODE)
     {
       if (TREE_VEC_LENGTH (candidate->convs) == 3)
-       errfn ("%s %D(%T, %T, %T) <built-in>", msgid, candidate->fn,
-              TREE_TYPE (TREE_VEC_ELT (candidate->convs, 0)),
-              TREE_TYPE (TREE_VEC_ELT (candidate->convs, 1)),
-              TREE_TYPE (TREE_VEC_ELT (candidate->convs, 2)));
+       inform ("%s %D(%T, %T, %T) <built-in>", msgstr, candidate->fn,
+               TREE_TYPE (TREE_VEC_ELT (candidate->convs, 0)),
+               TREE_TYPE (TREE_VEC_ELT (candidate->convs, 1)),
+               TREE_TYPE (TREE_VEC_ELT (candidate->convs, 2)));
       else if (TREE_VEC_LENGTH (candidate->convs) == 2)
-       errfn ("%s %D(%T, %T) <built-in>", msgid, candidate->fn,
-              TREE_TYPE (TREE_VEC_ELT (candidate->convs, 0)),
-              TREE_TYPE (TREE_VEC_ELT (candidate->convs, 1)));
+       inform ("%s %D(%T, %T) <built-in>", msgstr, candidate->fn,
+               TREE_TYPE (TREE_VEC_ELT (candidate->convs, 0)),
+               TREE_TYPE (TREE_VEC_ELT (candidate->convs, 1)));
       else
-       errfn ("%s %D(%T) <built-in>", msgid, candidate->fn,
-              TREE_TYPE (TREE_VEC_ELT (candidate->convs, 0)));
+       inform ("%s %D(%T) <built-in>", msgstr, candidate->fn,
+               TREE_TYPE (TREE_VEC_ELT (candidate->convs, 0)));
     }
   else if (TYPE_P (candidate->fn))
-    errfn ("%s %T <conversion>", msgid, candidate->fn);
+    inform ("%s %T <conversion>", msgstr, candidate->fn);
+  else if (candidate->viable == -1)
+    inform ("%J%s %+#D <near match>", candidate->fn, msgstr, candidate->fn);
   else
-    errfn ("%H%s %+#D%s", &DECL_SOURCE_LOCATION (candidate->fn), msgid,
-          candidate->fn, candidate->viable == -1 ? " <near match>" : "");
+    inform ("%J%s %+#D", candidate->fn, msgstr, candidate->fn);
 }
 
 static void
@@ -2496,11 +2397,27 @@ print_z_candidates (struct z_candidate *candidates)
        }
     }
 
-  str = "candidates are:";
-  for (; candidates; candidates = candidates->next)
+  if (!candidates)
+    return;
+
+  str = _("candidates are:");
+  print_z_candidate (str, candidates);
+  if (candidates->next)
     {
-      print_z_candidate (str, candidates, error);
-      str = "               "; 
+      /* Indent successive candidates by the width of the translation
+        of the above string.  */
+      size_t len = gcc_gettext_width (str) + 1;
+      char *spaces = alloca (len);
+      memset (spaces, ' ', len-1);
+      spaces[len - 1] = '\0';
+
+      candidates = candidates->next;
+      do
+       {
+         print_z_candidate (spaces, candidates);
+         candidates = candidates->next;
+       }
+      while (candidates);
     }
 }
 
@@ -2721,73 +2638,6 @@ build_user_type_conversion (tree totype, tree expr, int flags)
   return NULL_TREE;
 }
 
-/* Find the possibly overloaded set of functions corresponding to a
-   call of the form SCOPE::NAME (...). NAME might be a
-   TEMPLATE_ID_EXPR, OVERLOAD, _DECL, IDENTIFIER_NODE or LOOKUP_EXPR. */
-
-tree
-resolve_scoped_fn_name (tree scope, tree name)
-{
-  tree fn;
-  tree template_args = NULL_TREE;
-  bool is_template_id = TREE_CODE (name) == TEMPLATE_ID_EXPR;
-  
-  if (is_template_id)
-    {
-      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 (TREE_CODE (name) == LOOKUP_EXPR)
-    name = TREE_OPERAND (name, 0);
-  
-  if (TREE_CODE (scope) == NAMESPACE_DECL)
-    fn = lookup_namespace_name (scope, name);
-  else
-    {
-      if (!TYPE_BEING_DEFINED (scope)
-         && !COMPLETE_TYPE_P (complete_type (scope)))
-       {
-         error ("incomplete type '%T' cannot be used to name a scope",
-                scope);
-         return error_mark_node;
-       }
-      
-      if (BASELINK_P (name))
-       fn = name;
-      else
-       fn = lookup_member (scope, name, /*protect=*/1, /*want_type=*/false);
-      if (fn && current_class_type)
-       fn = (adjust_result_of_qualified_name_lookup 
-             (fn, scope, current_class_type));
-
-      /* It might be the name of a function pointer member.  */
-      if (fn && TREE_CODE (fn) == FIELD_DECL)
-       fn = resolve_offset_ref (build_offset_ref (scope, fn));
-    }
-  
-  if (!fn)
-    {
-      error ("'%D' has no member named '%E'", scope, name);
-      return error_mark_node;
-    }
-  if (is_template_id)
-    {
-      tree fns = fn;
-
-      if (BASELINK_P (fn))
-       fns = BASELINK_FUNCTIONS (fns);
-      fns = build_nt (TEMPLATE_ID_EXPR, fns, template_args);
-      if (BASELINK_P (fn))
-       BASELINK_FUNCTIONS (fn) = fns;
-      else
-       fn = fns;
-    }
-  
-  return fn;
-}
-
 /* Do any initial processing on the arguments to a function call.  */
 
 static tree
@@ -2805,8 +2655,6 @@ resolve_args (tree args)
          error ("invalid use of void expression");
          return error_mark_node;
        }
-      else if (TREE_CODE (arg) == OFFSET_REF)
-       arg = resolve_offset_ref (arg);
       arg = convert_from_reference (arg);
       TREE_VALUE (t) = arg;
     }
@@ -2909,8 +2757,8 @@ build_new_function_call (tree fn, tree args)
    the arguments provided.  *SIZE points to the total number of bytes
    required by the allocation, and is updated if that is changed here.
    *COOKIE_SIZE is non-NULL if a cookie should be used.  If this
-   function determins that no cookie should be used, after all,
-   *COOKIE_SIZE is set to NULL_TREE. */
+   function determines that no cookie should be used, after all,
+   *COOKIE_SIZE is set to NULL_TREE.  */
 
 tree
 build_operator_new_call (tree fnname, tree args, tree *size, tree *cookie_size)
@@ -2938,7 +2786,7 @@ build_operator_new_call (tree fnname, tree args, tree *size, tree *cookie_size)
        error ("no matching function for call to `%D(%A)'",
               DECL_NAME (OVL_CURRENT (fns)), args);
       else
-       error ("call of overlopaded `%D(%A)' is ambiguous",
+       error ("call of overloaded `%D(%A)' is ambiguous",
               DECL_NAME (OVL_CURRENT (fns)), args);
       if (candidates)
        print_z_candidates (candidates);
@@ -3111,23 +2959,32 @@ op_error (enum tree_code code, enum tree_code code2,
   switch (code)
     {
     case COND_EXPR:
-      error ("%s for `%T ? %T : %T' operator", problem,
-               error_type (arg1), error_type (arg2), error_type (arg3));
+      error ("%s for ternary 'operator?:' in '%E ? %E : %E'",
+             problem, arg1, arg2, arg3);
       break;
+      
     case POSTINCREMENT_EXPR:
     case POSTDECREMENT_EXPR:
-      error ("%s for `%T %s' operator", problem, error_type (arg1), opname);
+      error ("%s for 'operator%s' in '%E%s'", problem, opname, arg1, opname);
       break;
+      
     case ARRAY_REF:
-      error ("%s for `%T [%T]' operator", problem,
-               error_type (arg1), error_type (arg2));
+      error ("%s for 'operator[]' in '%E[%E]'", problem, arg1, arg2);
       break;
+
+    case REALPART_EXPR:
+    case IMAGPART_EXPR:
+      error ("%s for '%s' in '%s %E'", problem, opname, opname, arg1);
+      break;
+      
     default:
       if (arg2)
-       error ("%s for `%T %s %T' operator", problem,
-                 error_type (arg1), opname, error_type (arg2));
+       error ("%s for 'operator%s' in '%E %s %E'",
+               problem, opname, arg1, opname, arg2);
       else
-       error ("%s for `%s %T' operator", problem, opname, error_type (arg1));
+       error ("%s for 'operator%s' in '%s%E'",
+               problem, opname, opname, arg1);
+      break;
     }
 }
 
@@ -3140,6 +2997,7 @@ conditional_conversion (tree e1, tree e2)
   tree t1 = non_reference (TREE_TYPE (e1));
   tree t2 = non_reference (TREE_TYPE (e2));
   tree conv;
+  bool good_base;
 
   /* [expr.cond]
 
@@ -3166,29 +3024,36 @@ conditional_conversion (tree e1, tree e2)
      same cv-qualification as, or a greater cv-qualification than, the
      cv-qualification of T1.  If the conversion is applied, E1 is
      changed to an rvalue of type T2 that still refers to the original
-     source class object (or the appropriate subobject thereof).  */
+     source class object (or the appropriate subobject thereof).
+
+     FIXME we can't express an rvalue that refers to the original object;
+     we have to create a new one.  */
   if (CLASS_TYPE_P (t1) && CLASS_TYPE_P (t2)
-      && same_or_base_type_p (TYPE_MAIN_VARIANT (t2), 
-                             TYPE_MAIN_VARIANT (t1)))
+      && ((good_base = DERIVED_FROM_P (t2, t1)) || DERIVED_FROM_P (t1, t2)))
     {
-      if (at_least_as_qualified_p (t2, t1))
+      if (good_base && at_least_as_qualified_p (t2, t1))
        {
          conv = build1 (IDENTITY_CONV, t1, e1);
          if (!same_type_p (TYPE_MAIN_VARIANT (t1), 
                            TYPE_MAIN_VARIANT (t2)))
-           conv = build_conv (BASE_CONV, t2, conv);
+           {
+             conv = build_conv (BASE_CONV, t2, conv);
+             NEED_TEMPORARY_P (conv) = 1;
+           }
+         else
+           conv = build_conv (RVALUE_CONV, t2, conv);
          return conv;
        }
       else
        return NULL_TREE;
     }
+  else
+    /* [expr.cond]
 
-  /* [expr.cond]
-
-     E1 can be converted to match E2 if E1 can be implicitly converted
-     to the type that expression E2 would have if E2 were converted to
-     an rvalue (or the type it has, if E2 is an rvalue).  */
-  return implicit_conversion (t2, t1, e1, LOOKUP_NORMAL);
+       Otherwise: E1 can be converted to match E2 if E1 can be implicitly
+       converted to the type that expression E2 would have if E2 were
+       converted to an rvalue (or the type it has, if E2 is an rvalue).  */
+    return implicit_conversion (t2, t1, e1, LOOKUP_NORMAL);
 }
 
 /* Implement [expr.cond].  ARG1, ARG2, and ARG3 are the three
@@ -3225,16 +3090,13 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3)
   
      The first expr ession is implicitly converted to bool (clause
      _conv_).  */
-  arg1 = cp_convert (boolean_type_node, arg1);
+  arg1 = perform_implicit_conversion (boolean_type_node, arg1);
 
   /* If something has already gone wrong, just pass that fact up the
      tree.  */
-  if (arg1 == error_mark_node 
-      || arg2 == error_mark_node 
-      || arg3 == error_mark_node 
-      || TREE_TYPE (arg1) == error_mark_node
-      || TREE_TYPE (arg2) == error_mark_node
-      || TREE_TYPE (arg3) == error_mark_node)
+  if (error_operand_p (arg1)
+      || error_operand_p (arg2)
+      || error_operand_p (arg3))
     return error_mark_node;
 
   /* [expr.cond]
@@ -3316,19 +3178,21 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3)
        {
          arg2 = convert_like (conv2, arg2);
          arg2 = convert_from_reference (arg2);
-         /* That may not quite have done the trick.  If the two types
-            are cv-qualified variants of one another, we will have
-            just used an IDENTITY_CONV.  */
-         if (!same_type_p (TREE_TYPE (arg2), arg3_type))
-           arg2 = convert (arg3_type, arg2);
+         if (!same_type_p (TREE_TYPE (arg2), arg3_type)
+             && CLASS_TYPE_P (arg3_type))
+           /* The types need to match if we're converting to a class type.
+              If not, we don't care about cv-qual mismatches, since
+              non-class rvalues are not cv-qualified.  */
+           abort ();
          arg2_type = TREE_TYPE (arg2);
        }
       else if (conv3 && !ICS_BAD_FLAG (conv3))
        {
          arg3 = convert_like (conv3, arg3);
          arg3 = convert_from_reference (arg3);
-         if (!same_type_p (TREE_TYPE (arg3), arg2_type))
-           arg3 = convert (arg2_type, arg3);
+         if (!same_type_p (TREE_TYPE (arg3), arg2_type)
+             && CLASS_TYPE_P (arg2_type))
+           abort ();
          arg3_type = TREE_TYPE (arg3);
        }
     }
@@ -3337,8 +3201,9 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3)
 
      If the second and third operands are lvalues and have the same
      type, the result is of that type and is an lvalue.  */
-  if (real_lvalue_p (arg2) && real_lvalue_p (arg3) && 
-      same_type_p (arg2_type, arg3_type))
+  if (real_lvalue_p (arg2) 
+      && real_lvalue_p (arg3) 
+      && same_type_p (arg2_type, arg3_type))
     {
       result_type = arg2_type;
       goto valid_operands;
@@ -3480,18 +3345,17 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3)
        cv-qualification of either the second or the third operand.
        The result is of the common type.  */
   else if ((null_ptr_cst_p (arg2) 
-           && (TYPE_PTR_P (arg3_type) || TYPE_PTRMEM_P (arg3_type)
-               || TYPE_PTRMEMFUNC_P (arg3_type)))
+           && (TYPE_PTR_P (arg3_type) || TYPE_PTR_TO_MEMBER_P (arg3_type)))
           || (null_ptr_cst_p (arg3) 
-              && (TYPE_PTR_P (arg2_type) || TYPE_PTRMEM_P (arg2_type)
-               || TYPE_PTRMEMFUNC_P (arg2_type)))
+              && (TYPE_PTR_P (arg2_type) || TYPE_PTR_TO_MEMBER_P (arg2_type)))
           || (TYPE_PTR_P (arg2_type) && TYPE_PTR_P (arg3_type))
           || (TYPE_PTRMEM_P (arg2_type) && TYPE_PTRMEM_P (arg3_type))
-          || (TYPE_PTRMEMFUNC_P (arg2_type) 
-              && TYPE_PTRMEMFUNC_P (arg3_type)))
+          || (TYPE_PTRMEMFUNC_P (arg2_type) && TYPE_PTRMEMFUNC_P (arg3_type)))
     {
       result_type = composite_pointer_type (arg2_type, arg3_type, arg2,
                                            arg3, "conditional expression");
+      if (result_type == error_mark_node)
+       return error_mark_node;
       arg2 = perform_implicit_conversion (result_type, arg2);
       arg3 = perform_implicit_conversion (result_type, arg3);
     }
@@ -3504,16 +3368,19 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3)
 
  valid_operands:
   result = fold (build (COND_EXPR, result_type, arg1, arg2, arg3));
+  /* We can't use result_type below, as fold might have returned a
+     throw_expr.  */
+
   /* Expand both sides into the same slot, hopefully the target of the
      ?: expression.  We used to check for TARGET_EXPRs here, but now we
      sometimes wrap them in NOP_EXPRs so the test would fail.  */
-  if (!lvalue_p && IS_AGGR_TYPE (result_type))
-    result = build_target_expr_with_type (result, result_type);
+  if (!lvalue_p && IS_AGGR_TYPE (TREE_TYPE (result)))
+    result = get_target_expr (result);
   
   /* If this expression is an rvalue, but might be mistaken for an
      lvalue, we must add a NON_LVALUE_EXPR.  */
   if (!lvalue_p && real_lvalue_p (result))
-    result = build1 (NON_LVALUE_EXPR, result_type, result);
+    result = build1 (NON_LVALUE_EXPR, TREE_TYPE (result), result);
 
   return result;
 }
@@ -3527,8 +3394,6 @@ prep_operand (tree operand)
 {
   if (operand)
     {
-      if (TREE_CODE (operand) == OFFSET_REF)
-       operand = resolve_offset_ref (operand);
       operand = convert_from_reference (operand);
       if (CLASS_TYPE_P (TREE_TYPE (operand))
          && CLASSTYPE_TEMPLATE_INSTANTIATION (TREE_TYPE (operand)))
@@ -3544,7 +3409,7 @@ prep_operand (tree operand)
    CANDIDATES.  The ARGS are the arguments provided to the call,
    without any implicit object parameter.  The EXPLICIT_TARGS are
    explicit template arguments provided.  TEMPLATE_ONLY is true if
-   only template fucntions should be considered.  CONVERSION_PATH,
+   only template functions should be considered.  CONVERSION_PATH,
    ACCESS_PATH, and FLAGS are as for add_function_candidate.  */
 
 static void
@@ -3924,15 +3789,13 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
                       int flags, tree placement)
 {
   tree fn = NULL_TREE;
-  tree fns, fnname, fntype, argtypes, args, type;
+  tree fns, fnname, argtypes, args, type;
   int pass;
 
   if (addr == error_mark_node)
     return error_mark_node;
 
-  type = TREE_TYPE (TREE_TYPE (addr));
-  while (TREE_CODE (type) == ARRAY_TYPE)
-    type = TREE_TYPE (type);
+  type = strip_array_types (TREE_TYPE (TREE_TYPE (addr)));
 
   fnname = ansi_opname (code);
 
@@ -3943,7 +3806,7 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
        the lookup selects a placement deallocation function, the
        program is ill-formed.
   
-       Therefore, we ask lookup_fnfields to complain ambout ambiguity.  */
+       Therefore, we ask lookup_fnfields to complain about ambiguity.  */
     {
       fns = lookup_fnfields (TYPE_BINFO (type), fnname, 1);
       if (fns == error_mark_node)
@@ -3962,10 +3825,6 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
 
       /* Find the allocation function that is being called.  */
       call_expr = placement;
-      /* Sometimes we have a COMPOUND_EXPR, rather than a simple
-        CALL_EXPR.  */
-      while (TREE_CODE (call_expr) == COMPOUND_EXPR)
-       call_expr = TREE_OPERAND (call_expr, 1);
       /* Extract the function.  */
       alloc_fn = get_callee_fndecl (call_expr);
       my_friendly_assert (alloc_fn != NULL_TREE, 20020327);
@@ -3985,21 +3844,11 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
   addr = cp_convert (ptr_type_node, addr);
 
   /* We make two tries at finding a matching `operator delete'.  On
-     the first pass, we look for an one-operator (or placement)
+     the first pass, we look for a one-operator (or placement)
      operator delete.  If we're not doing placement delete, then on
      the second pass we look for a two-argument delete.  */
   for (pass = 0; pass < (placement ? 1 : 2); ++pass) 
     {
-      if (pass == 0)
-       argtypes = tree_cons (NULL_TREE, ptr_type_node, argtypes);
-      else 
-       /* Normal delete; now try to find a match including the size
-          argument.  */
-       argtypes = tree_cons (NULL_TREE, ptr_type_node,
-                             tree_cons (NULL_TREE, sizetype, 
-                                        void_list_node));
-      fntype = build_function_type (void_type_node, argtypes);
-
       /* Go through the `operator delete' functions looking for one
         with a matching type.  */
       for (fn = BASELINK_P (fns) ? BASELINK_FUNCTIONS (fns) : fns; 
@@ -4008,13 +3857,30 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
        {
          tree t;
 
-         /* Exception specifications on the `delete' operator do not
-            matter.  */
-         t = build_exception_variant (TREE_TYPE (OVL_CURRENT (fn)),
-                                      NULL_TREE);
-         /* We also don't compare attributes.  We're really just
-            trying to check the types of the first two parameters.  */
-         if (comptypes (t, fntype, COMPARE_NO_ATTRIBUTES))
+         /* The first argument must be "void *".  */
+         t = TYPE_ARG_TYPES (TREE_TYPE (OVL_CURRENT (fn)));
+         if (!same_type_p (TREE_VALUE (t), ptr_type_node))
+           continue;
+         t = TREE_CHAIN (t);
+         /* On the first pass, check the rest of the arguments.  */
+         if (pass == 0)
+           {
+             while (argtypes && t)
+               {
+                 if (!same_type_p (TREE_VALUE (argtypes),
+                                   TREE_VALUE (t)))
+                   break;
+                 argtypes = TREE_CHAIN (argtypes);
+                 t = TREE_CHAIN (t);
+               }
+             if (!argtypes && !t)
+               break;
+           }
+         /* On the second pass, the second argument must be
+            "size_t".  */
+         else if (pass == 1
+                  && same_type_p (TREE_VALUE (t), sizetype)
+                  && TREE_CHAIN (t) == void_list_node)
            break;
        }
 
@@ -4033,7 +3899,7 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
       /* If the FN is a member function, make sure that it is
         accessible.  */
       if (DECL_CLASS_SCOPE_P (fn))
-       enforce_access (type, fn);
+       perform_or_defer_access_check (TYPE_BINFO (type), fn);
 
       if (pass == 0)
        args = tree_cons (NULL_TREE, addr, args);
@@ -4041,7 +3907,15 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
        args = tree_cons (NULL_TREE, addr, 
                          build_tree_list (NULL_TREE, size));
 
-      return build_function_call (fn, args);
+      if (placement)
+       {
+         /* The placement args might not be suitable for overload
+            resolution at this point, so build the call directly.  */
+         mark_used (fn);
+         return build_cxx_call (fn, args, args);
+       }
+      else
+       return build_function_call (fn, args);
     }
 
   /* If we are doing placement delete we do nothing if we don't find a
@@ -4049,7 +3923,8 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
   if (placement)
     return NULL_TREE;
 
-  error ("no suitable `operator delete' for `%T'", type);
+  error ("no suitable `operator %s' for `%T'",
+        operator_name_info[(int)code].name, type);
   return error_mark_node;
 }
 
@@ -4060,6 +3935,8 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
 bool
 enforce_access (tree basetype_path, tree decl)
 {
+  my_friendly_assert (TREE_CODE (basetype_path) == TREE_VEC, 20030624);
+  
   if (!accessible_p (basetype_path, decl))
     {
       if (TREE_PRIVATE (decl))
@@ -4075,14 +3952,17 @@ enforce_access (tree basetype_path, tree decl)
   return true;
 }
 
-/* Perform the conversions in CONVS on the expression EXPR. 
-   FN and ARGNUM are used for diagnostics.  ARGNUM is zero based, -1
+/* Perform the conversions in CONVS on the expression EXPR.  FN and
+   ARGNUM are used for diagnostics.  ARGNUM is zero based, -1
    indicates the `this' argument of a method.  INNER is nonzero when
    being called to continue a conversion chain. It is negative when a
-   reference binding will be applied, positive otherwise.  */
+   reference binding will be applied, positive otherwise.  If
+   ISSUE_CONVERSION_WARNINGS is true, warnings about suspicious
+   conversions will be emitted if appropriate.  */
 
 static tree
-convert_like_real (tree convs, tree expr, tree fn, int argnum, int inner)
+convert_like_real (tree convs, tree expr, tree fn, int argnum, int inner,
+                  bool issue_conversion_warnings)
 {
   int savew, savee;
 
@@ -4098,11 +3978,13 @@ convert_like_real (tree convs, tree expr, tree fn, int argnum, int inner)
        {
          if (TREE_CODE (t) == USER_CONV || !ICS_BAD_FLAG (t))
            {
-             expr = convert_like_real (t, expr, fn, argnum, 1);
+             expr = convert_like_real (t, expr, fn, argnum, 1,
+                                       /*issue_conversion_warnings=*/false);
              break;
            }
          else if (TREE_CODE (t) == AMBIG_CONV)
-           return convert_like_real (t, expr, fn, argnum, 1);
+           return convert_like_real (t, expr, fn, argnum, 1,
+                                     /*issue_conversion_warnings=*/false);
          else if (TREE_CODE (t) == IDENTITY_CONV)
            break;
        }
@@ -4112,7 +3994,7 @@ convert_like_real (tree convs, tree expr, tree fn, int argnum, int inner)
       return cp_convert (totype, expr);
     }
   
-  if (!inner)
+  if (issue_conversion_warnings)
     expr = dubious_conversion_warnings
              (totype, expr, "argument", fn, argnum);
   switch (TREE_CODE (convs))
@@ -4210,7 +4092,8 @@ convert_like_real (tree convs, tree expr, tree fn, int argnum, int inner)
     };
 
   expr = convert_like_real (TREE_OPERAND (convs, 0), expr, fn, argnum,
-                            TREE_CODE (convs) == REF_BIND ? -1 : 1);
+                            TREE_CODE (convs) == REF_BIND ? -1 : 1,
+                           /*issue_conversion_warnings=*/false);
   if (expr == error_mark_node)
     return error_mark_node;
 
@@ -4219,7 +4102,7 @@ convert_like_real (tree convs, tree expr, tree fn, int argnum, int inner)
     case RVALUE_CONV:
       if (! IS_AGGR_TYPE (totype))
        return expr;
-      /* else fall through */
+      /* Else fall through.  */
     case BASE_CONV:
       if (TREE_CODE (convs) == BASE_CONV && !NEED_TEMPORARY_P (convs))
        {
@@ -4256,9 +4139,26 @@ convert_like_real (tree convs, tree expr, tree fn, int argnum, int inner)
        tree ref_type = totype;
 
        /* If necessary, create a temporary.  */
-       if (NEED_TEMPORARY_P (convs) || !non_cast_lvalue_p (expr))
+       if (NEED_TEMPORARY_P (convs) || !lvalue_p (expr))
          {
            tree type = TREE_TYPE (TREE_OPERAND (convs, 0));
+
+           if (!CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (ref_type)))
+             {
+               /* If the reference is volatile or non-const, we
+                  cannot create a temporary.  */
+               cp_lvalue_kind lvalue = real_lvalue_p (expr);
+               
+               if (lvalue & clk_bitfield)
+                 error ("cannot bind bitfield `%E' to `%T'",
+                        expr, ref_type);
+               else if (lvalue & clk_packed)
+                 error ("cannot bind packed field `%E' to `%T'",
+                        expr, ref_type);
+               else
+                 error ("cannot bind rvalue `%E' to `%T'", expr, ref_type);
+               return error_mark_node;
+             }
            expr = build_target_expr_with_type (expr, type);
          }
 
@@ -4292,37 +4192,45 @@ convert_like_real (tree convs, tree expr, tree fn, int argnum, int inner)
                      LOOKUP_NORMAL|LOOKUP_NO_CONVERSION);
 }
 
-/* Build a call to __builtin_trap which can be used in an expression.  */
+/* Build a call to __builtin_trap which can be used as an expression of
+   type TYPE.  */
 
 static tree
-call_builtin_trap (void)
+call_builtin_trap (tree type)
 {
-  tree fn = get_identifier ("__builtin_trap");
-  if (IDENTIFIER_GLOBAL_VALUE (fn))
-    fn = IDENTIFIER_GLOBAL_VALUE (fn);
-  else
-    abort ();
+  tree fn = IDENTIFIER_GLOBAL_VALUE (get_identifier ("__builtin_trap"));
 
+  my_friendly_assert (fn != NULL, 20030927);
   fn = build_call (fn, NULL_TREE);
-  fn = build (COMPOUND_EXPR, integer_type_node, fn, integer_zero_node);
+  fn = build (COMPOUND_EXPR, type, fn, error_mark_node);
+  fn = force_target_expr (type, fn);
   return fn;
 }
 
 /* ARG is being passed to a varargs function.  Perform any conversions
-   required.  Array/function to pointer decay must have already happened.
-   Return the converted value.  */
+   required.  Return the converted value.  */
 
 tree
 convert_arg_to_ellipsis (tree arg)
 {
+  /* [expr.call]
+
+     The lvalue-to-rvalue, array-to-pointer, and function-to-pointer
+     standard conversions are performed.  */
+  arg = decay_conversion (arg);
+  /* [expr.call]
+
+     If the argument has integral or enumeration type that is subject
+     to the integral promotions (_conv.prom_), or a floating point
+     type that is subject to the floating point promotion
+     (_conv.fpprom_), the value of the argument is converted to the
+     promoted type before the call.  */
   if (TREE_CODE (TREE_TYPE (arg)) == REAL_TYPE
       && (TYPE_PRECISION (TREE_TYPE (arg))
          < TYPE_PRECISION (double_type_node)))
-    /* Convert `float' to `double'.  */
-    arg = cp_convert (double_type_node, arg);
-  else
-    /* Convert `short' and `char' to full-size `int'.  */
-    arg = default_conversion (arg);
+    arg = convert_to_real (double_type_node, arg);
+  else if (INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (arg)))
+    arg = perform_integral_promotions (arg);
 
   arg = require_complete_type (arg);
   
@@ -4334,7 +4242,7 @@ convert_arg_to_ellipsis (tree arg)
       warning ("cannot pass objects of non-POD type `%#T' through `...'; \
 call will abort at runtime",
               TREE_TYPE (arg));
-      arg = call_builtin_trap ();
+      arg = call_builtin_trap (TREE_TYPE (arg));
     }
 
   return arg;
@@ -4356,8 +4264,10 @@ build_x_va_arg (tree expr, tree type)
   if (! pod_type_p (type))
     {
       /* Undefined behavior [expr.call] 5.2.2/7.  */
-      warning ("cannot receive objects of non-POD type `%#T' through `...'",
-                 type);
+      warning ("cannot receive objects of non-POD type `%#T' through `...'; \
+call will abort at runtime",
+              type);
+      return call_builtin_trap (type);
     }
   
   return build_va_arg (expr, type);
@@ -4372,11 +4282,9 @@ cxx_type_promotes_to (tree type)
 {
   tree promote;
 
-  if (TREE_CODE (type) == ARRAY_TYPE)
-    return build_pointer_type (TREE_TYPE (type));
-
-  if (TREE_CODE (type) == FUNCTION_TYPE)
-    return build_pointer_type (type);
+  /* Perform the array-to-pointer and function-to-pointer
+     conversions.  */
+  type = type_decays_to (type);
 
   promote = type_promotes_to (type);
   if (same_type_p (type, promote))
@@ -4438,7 +4346,9 @@ type_passed_as (tree type)
     type = build_reference_type (type);
   else if (PROMOTE_PROTOTYPES
           && INTEGRAL_TYPE_P (type)
-          && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
+          && COMPLETE_TYPE_P (type)
+          && INT_CST_LT_UNSIGNED (TYPE_SIZE (type),
+                                  TYPE_SIZE (integer_type_node)))
     type = integer_type_node;
 
   return type;
@@ -4456,11 +4366,36 @@ convert_for_arg_passing (tree type, tree val)
     val = build1 (ADDR_EXPR, build_reference_type (type), val);
   else if (PROMOTE_PROTOTYPES
           && INTEGRAL_TYPE_P (type)
-          && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
-    val = default_conversion (val);
+          && COMPLETE_TYPE_P (type)
+          && INT_CST_LT_UNSIGNED (TYPE_SIZE (type),
+                                  TYPE_SIZE (integer_type_node)))
+    val = perform_integral_promotions (val);
   return val;
 }
 
+/* Returns true iff FN is a function with magic varargs, i.e. ones for
+   which no conversions at all should be done.  This is true for some
+   builtins which don't act like normal functions.  */
+
+static bool
+magic_varargs_p (tree fn)
+{
+  if (DECL_BUILT_IN (fn))
+    switch (DECL_FUNCTION_CODE (fn))
+      {
+      case BUILT_IN_CLASSIFY_TYPE:
+      case BUILT_IN_CONSTANT_P:
+      case BUILT_IN_NEXT_ARG:
+      case BUILT_IN_STDARG_START:
+      case BUILT_IN_VA_START:
+       return true;
+
+      default:;
+      }
+
+  return false;
+}
+
 /* Subroutine of the various build_*_call functions.  Overload resolution
    has chosen a winning candidate CAND; build up a CALL_EXPR accordingly.
    ARGS is a TREE_LIST of the unconverted arguments to the call.  FLAGS is a
@@ -4484,7 +4419,39 @@ build_over_call (struct z_candidate *cand, int flags)
       joust (cand, WRAPPER_ZC (TREE_VALUE (val)), 1);
 
   if (DECL_FUNCTION_MEMBER_P (fn))
-    enforce_access (cand->access_path, fn);
+    {
+      /* If FN is a template function, two cases must be considered.
+        For example:
+
+          struct A {
+            protected:
+              template <class T> void f();
+          };
+          template <class T> struct B {
+            protected:
+              void g();
+          };
+          struct C : A, B<int> {
+            using A::f;        // #1
+            using B<int>::g;   // #2
+          };
+
+        In case #1 where `A::f' is a member template, DECL_ACCESS is
+        recorded in the primary template but not in its specialization.
+        We check access of FN using its primary template.
+
+        In case #2, where `B<int>::g' has a DECL_TEMPLATE_INFO simply
+        because it is a member of class template B, DECL_ACCESS is
+        recorded in the specialization `B<int>::g'.  We cannot use its
+        primary template because `B<T>::g' and `B<int>::g' may have
+        different access.  */
+      if (DECL_TEMPLATE_INFO (fn)
+         && is_member_template (DECL_TI_TEMPLATE (fn)))
+       perform_or_defer_access_check (cand->access_path,
+                                      DECL_TI_TEMPLATE (fn));
+      else
+       perform_or_defer_access_check (cand->access_path, fn);
+    }
 
   if (args && TREE_CODE (args) != TREE_LIST)
     args = build_tree_list (NULL_TREE, args);
@@ -4533,12 +4500,17 @@ build_over_call (struct z_candidate *cand, int flags)
                                       TREE_VALUE (arg),
                                       cand->conversion_path,
                                       1);
+      /* Check that the base class is accessible.  */
+      if (!accessible_base_p (TREE_TYPE (argtype), 
+                             BINFO_TYPE (cand->conversion_path)))
+       error ("`%T' is not an accessible base of `%T'",
+              BINFO_TYPE (cand->conversion_path),
+              TREE_TYPE (argtype));
       /* If fn was found by a using declaration, the conversion path
          will be to the derived class, not the base declaring fn. We
          must convert from derived to base.  */
       base_binfo = lookup_base (TREE_TYPE (TREE_TYPE (converted_arg)),
                                TREE_TYPE (parmtype), ba_ignore, NULL);
-      
       converted_arg = build_base_path (PLUS_EXPR, converted_arg,
                                       base_binfo, 1);
       
@@ -4573,10 +4545,14 @@ build_over_call (struct z_candidate *cand, int flags)
 
   /* Ellipsis */
   for (; arg; arg = TREE_CHAIN (arg))
-    converted_args 
-      = tree_cons (NULL_TREE,
-                  convert_arg_to_ellipsis (TREE_VALUE (arg)),
-                  converted_args);
+    {
+      tree a = TREE_VALUE (arg);
+      if (magic_varargs_p (fn))
+       /* Do no conversions for magic varargs.  */;
+      else
+       a = convert_arg_to_ellipsis (a);
+      converted_args = tree_cons (NULL_TREE, a, converted_args);
+    }
 
   converted_args = nreverse (converted_args);
 
@@ -4655,9 +4631,30 @@ build_over_call (struct z_candidate *cand, int flags)
     {
       tree to = stabilize_reference
        (build_indirect_ref (TREE_VALUE (converted_args), 0));
+      tree type = TREE_TYPE (to);
+      tree as_base = CLASSTYPE_AS_BASE (type);
 
       arg = build_indirect_ref (TREE_VALUE (TREE_CHAIN (converted_args)), 0);
-      val = build (MODIFY_EXPR, TREE_TYPE (to), to, arg);
+      if (tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (as_base)))
+       val = build (MODIFY_EXPR, TREE_TYPE (to), to, arg);
+      else
+       {
+         /* We must only copy the non-tail padding parts. Use
+            CLASSTYPE_AS_BASE for the bitwise copy.  */
+         tree to_as_base, arg_as_base, base_ptr_type;
+
+         to = save_expr (to);
+         base_ptr_type = build_pointer_type (as_base);
+         to_as_base = build_indirect_ref
+           (build_nop (base_ptr_type, build_unary_op (ADDR_EXPR, to, 0)), 0);
+         arg_as_base = build_indirect_ref
+           (build_nop (base_ptr_type, build_unary_op (ADDR_EXPR, arg, 0)), 0);
+         
+         val = build (MODIFY_EXPR, as_base, to_as_base, arg_as_base);
+         val = build (COMPOUND_EXPR, type, convert_to_void (val, NULL), to);
+         TREE_USED (val) = 1;
+       }
+      
       return val;
     }
 
@@ -4686,10 +4683,22 @@ build_over_call (struct z_candidate *cand, int flags)
   else
     fn = build_addr_func (fn);
 
+  return build_cxx_call (fn, args, converted_args);
+}
+
+/* Build and return a call to FN, using the the CONVERTED_ARGS.  ARGS
+   gives the original form of the arguments.  This function performs
+   no overload resolution, conversion, or other high-level
+   operations.  */
+
+tree
+build_cxx_call(tree fn, tree args, tree converted_args)
+{
+  tree fndecl;
+
   /* 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 (fn) == ADDR_EXPR
       && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
       && DECL_BUILT_IN (TREE_OPERAND (fn, 0)))
@@ -4700,14 +4709,26 @@ build_over_call (struct z_candidate *cand, int flags)
        return exp;
     }
 
-  /* Some built-in function calls will be evaluated at
-     compile-time in fold ().  */
-  fn = fold (build_call (fn, converted_args));
+  fn = build_call (fn, converted_args);
+
+  /* If this call might throw an exception, note that fact.  */
+  fndecl = get_callee_fndecl (fn);
+  if ((!fndecl || !TREE_NOTHROW (fndecl)) 
+      && at_function_scope_p ()
+      && cfun)
+    cp_function_chain->can_throw = 1;
+
+  /* Some built-in function calls will be evaluated at compile-time in
+     fold ().  */
+  fn = fold (fn);
+
   if (VOID_TYPE_P (TREE_TYPE (fn)))
     return fn;
+
   fn = require_complete_type (fn);
   if (fn == error_mark_node)
     return error_mark_node;
+
   if (IS_AGGR_TYPE (TREE_TYPE (fn)))
     fn = build_cplus_new (TREE_TYPE (fn), fn);
   return convert_from_reference (fn);
@@ -4837,11 +4858,23 @@ build_special_member_call (tree instance, tree name, tree args,
       TREE_TYPE (instance) = build_pointer_type (class_type);
       instance = build1 (INDIRECT_REF, class_type, instance);
     }
-  else if (name == complete_dtor_identifier 
-          || name == base_dtor_identifier
-          || name == deleting_dtor_identifier)
-    my_friendly_assert (args == NULL_TREE, 20020712);
+  else
+    {
+      if (name == complete_dtor_identifier 
+         || name == base_dtor_identifier
+         || name == deleting_dtor_identifier)
+       my_friendly_assert (args == NULL_TREE, 20020712);
 
+      /* We must perform the conversion here so that we do not
+        subsequently check to see whether BINFO is an accessible
+        base.  (It is OK for a constructor to call a constructor in
+        an inaccessible base as long as the constructor being called
+        is accessible.)  */
+      if (!same_type_ignoring_top_level_qualifiers_p 
+         (TREE_TYPE (instance), BINFO_TYPE (binfo)))
+       instance = convert_to_base_statically (instance, binfo);
+    }
+  
   my_friendly_assert (instance != NULL_TREE, 20020712);
 
   /* Resolve the name.  */
@@ -4877,7 +4910,9 @@ build_special_member_call (tree instance, tree name, tree args,
       args = tree_cons (NULL_TREE, sub_vtt, args);
     }
 
-  return build_new_method_call (instance, fns, args, binfo, flags);
+  return build_new_method_call (instance, fns, args, 
+                               TYPE_BINFO (BINFO_TYPE (binfo)), 
+                               flags);
 }
 
 /* Return the NAME, as a C string.  The NAME indicates a function that
@@ -4935,6 +4970,9 @@ build_new_method_call (tree instance, tree fns, tree args,
   tree class_type;
   int template_only = 0;
   bool any_viable_p;
+  tree orig_instance;
+  tree orig_fns;
+  tree orig_args;
 
   my_friendly_assert (instance != NULL_TREE, 20020729);
 
@@ -4943,14 +4981,26 @@ build_new_method_call (tree instance, tree fns, tree args,
       || args == error_mark_node)
     return error_mark_node;
 
+  orig_instance = instance;
+  orig_fns = fns;
+  orig_args = args;
+
+  if (processing_template_decl)
+    {
+      instance = build_non_dependent_expr (instance);
+      if (!BASELINK_P (fns)
+         && TREE_CODE (fns) != PSEUDO_DTOR_EXPR
+         && TREE_TYPE (fns) != unknown_type_node)
+       fns = build_non_dependent_expr (fns);
+      args = build_non_dependent_args (orig_args);
+    }
+
   /* Process the argument list.  */
   user_args = args;
   args = resolve_args (args);
   if (args == error_mark_node)
     return error_mark_node;
 
-  if (TREE_CODE (instance) == OFFSET_REF)
-    instance = resolve_offset_ref (instance);
   if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
     instance = convert_from_reference (instance);
   basetype = TYPE_MAIN_VARIANT (TREE_TYPE (instance));
@@ -4960,7 +5010,7 @@ build_new_method_call (tree instance, tree fns, tree args,
     {
       call = build_field_call (instance_ptr, fns, args);
       if (call)
-       return call;
+       goto finish;
       error ("call to non-function `%D'", fns);
       return error_mark_node;
     }
@@ -5121,7 +5171,13 @@ build_new_method_call (tree instance, tree fns, tree args,
       if (!is_dummy_object (instance_ptr) && TREE_SIDE_EFFECTS (instance))
        call = build (COMPOUND_EXPR, TREE_TYPE (call), instance, call);
     }
-
+ finish:;
+  
+  if (processing_template_decl && call != error_mark_node)
+    return build_min_non_dep
+      (CALL_EXPR, call,
+       build_min_nt (COMPONENT_REF, orig_instance, orig_fns),
+       orig_args);
   return call;
 }
 
@@ -5202,7 +5258,7 @@ maybe_handle_implicit_object (tree *ics)
       tree reference_type;
 
       /* The `this' parameter is a pointer to a class type.  Make the
-        implict conversion talk about a reference to that same class
+        implicit conversion talk about a reference to that same class
         type.  */
       reference_type = TREE_TYPE (TREE_TYPE (*ics));
       reference_type = build_reference_type (reference_type);
@@ -5295,7 +5351,7 @@ compare_ics (tree ics1, tree ics2)
     {
       /* XXX Isn't this an extension? */
       /* Both ICS are bad.  We try to make a decision based on what
-        would have happenned if they'd been good.  */
+        would have happened if they'd been good.  */
       if (ICS_USER_FLAG (ics1) > ICS_USER_FLAG (ics2)
          || ICS_STD_RANK (ics1) > ICS_STD_RANK (ics2))
        return -1;
@@ -5415,25 +5471,17 @@ compare_ics (tree ics1, tree ics2)
      for pointers A*, except opposite: if B is derived from A then
      A::* converts to B::*, not vice versa.  For that reason, we
      switch the from_ and to_ variables here.  */
-  else if (TYPE_PTRMEM_P (from_type1)
-          && TYPE_PTRMEM_P (from_type2)
-          && TYPE_PTRMEM_P (to_type1)
-          && TYPE_PTRMEM_P (to_type2))
-    {
-      deref_to_type1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (from_type1));
-      deref_to_type2 = TYPE_OFFSET_BASETYPE (TREE_TYPE (from_type2));
-      deref_from_type1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (to_type1));
-      deref_from_type2 = TYPE_OFFSET_BASETYPE (TREE_TYPE (to_type2));
-    }
-  else if (TYPE_PTRMEMFUNC_P (from_type1)
-          && TYPE_PTRMEMFUNC_P (from_type2)
-          && TYPE_PTRMEMFUNC_P (to_type1)
-          && TYPE_PTRMEMFUNC_P (to_type2))
+  else if ((TYPE_PTRMEM_P (from_type1) && TYPE_PTRMEM_P (from_type2)
+           && TYPE_PTRMEM_P (to_type1) && TYPE_PTRMEM_P (to_type2))
+          || (TYPE_PTRMEMFUNC_P (from_type1)
+              && TYPE_PTRMEMFUNC_P (from_type2)
+              && TYPE_PTRMEMFUNC_P (to_type1)
+              && TYPE_PTRMEMFUNC_P (to_type2)))
     {
-      deref_to_type1 = TYPE_PTRMEMFUNC_OBJECT_TYPE (from_type1);
-      deref_to_type2 = TYPE_PTRMEMFUNC_OBJECT_TYPE (from_type2);
-      deref_from_type1 = TYPE_PTRMEMFUNC_OBJECT_TYPE (to_type1);
-      deref_from_type2 = TYPE_PTRMEMFUNC_OBJECT_TYPE (to_type2);
+      deref_to_type1 = TYPE_PTRMEM_CLASS_TYPE (from_type1);
+      deref_to_type2 = TYPE_PTRMEM_CLASS_TYPE (from_type2);
+      deref_from_type1 = TYPE_PTRMEM_CLASS_TYPE (to_type1);
+      deref_from_type2 = TYPE_PTRMEM_CLASS_TYPE (to_type2);
     }
 
   if (deref_from_type1 != NULL_TREE
@@ -5711,45 +5759,52 @@ joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn)
   /* warn about confusing overload resolution for user-defined conversions,
      either between a constructor and a conversion op, or between two
      conversion ops.  */
-  if (winner && cand1->second_conv
-      && ((DECL_CONSTRUCTOR_P (cand1->fn)
-          != DECL_CONSTRUCTOR_P (cand2->fn))
-         /* Don't warn if the two conv ops convert to the same type...  */
-         || (! DECL_CONSTRUCTOR_P (cand1->fn)
-             && ! same_type_p (TREE_TYPE (TREE_TYPE (cand1->fn)),
-                               TREE_TYPE (TREE_TYPE (cand2->fn))))))
-    {
-      int comp = compare_ics (cand1->second_conv, cand2->second_conv);
-      if (comp != winner)
+  if (winner && warn_conversion && cand1->second_conv
+      && (!DECL_CONSTRUCTOR_P (cand1->fn) || !DECL_CONSTRUCTOR_P (cand2->fn))
+      && winner != compare_ics (cand1->second_conv, cand2->second_conv))
+    {
+      struct z_candidate *w, *l;
+      bool give_warning = false;
+      
+      if (winner == 1)
+       w = cand1, l = cand2;
+      else
+       w = cand2, l = cand1;
+      
+      /* We don't want to complain about `X::operator T1 ()'
+        beating `X::operator T2 () const', when T2 is a no less
+        cv-qualified version of T1.  */
+      if (DECL_CONTEXT (w->fn) == DECL_CONTEXT (l->fn)
+         && !DECL_CONSTRUCTOR_P (w->fn) && !DECL_CONSTRUCTOR_P (l->fn))
        {
-         struct z_candidate *w, *l;
-         tree convn;
-         if (winner == 1)
-           w = cand1, l = cand2;
-         else
-           w = cand2, l = cand1;
-         if (DECL_CONTEXT (cand1->fn) == DECL_CONTEXT (cand2->fn)
-             && ! DECL_CONSTRUCTOR_P (cand1->fn)
-             && ! DECL_CONSTRUCTOR_P (cand2->fn)
-             && (convn = standard_conversion
-                 (TREE_TYPE (TREE_TYPE (l->fn)),
-                  TREE_TYPE (TREE_TYPE (w->fn)), NULL_TREE))
-             && TREE_CODE (convn) == QUAL_CONV)
-           /* Don't complain about `operator char *()' beating
-              `operator const char *() const'.  */;
-         else if (warn)
+         tree t = TREE_TYPE (TREE_TYPE (l->fn));
+         tree f = TREE_TYPE (TREE_TYPE (w->fn));
+         
+         if (TREE_CODE (t) == TREE_CODE (f) && POINTER_TYPE_P (t))
            {
-             tree source = source_type (TREE_VEC_ELT (w->convs, 0));
-             if (! DECL_CONSTRUCTOR_P (w->fn))
-               source = TREE_TYPE (source);
-             warning ("choosing `%D' over `%D'", w->fn, l->fn);
-             warning ("  for conversion from `%T' to `%T'",
-                         source, TREE_TYPE (w->second_conv));
-             warning ("  because conversion sequence for the argument is better");
+             t = TREE_TYPE (t);
+             f = TREE_TYPE (f);
            }
-         else
-           add_warning (w, l);
+         if (!comp_ptr_ttypes (t, f))
+           give_warning = true;
        }
+      else
+       give_warning = true;
+      
+      if (!give_warning)
+       /*NOP*/;
+      else if (warn)
+       {
+         tree source = source_type (TREE_VEC_ELT (w->convs, 0));
+         if (! DECL_CONSTRUCTOR_P (w->fn))
+           source = TREE_TYPE (source);
+         warning ("choosing `%D' over `%D'", w->fn, l->fn);
+         warning ("  for conversion from `%T' to `%T'",
+                  source, TREE_TYPE (w->second_conv));
+         warning ("  because conversion sequence for the argument is better");
+       }
+      else
+       add_warning (w, l);
     }
 
   if (winner)
@@ -5866,12 +5921,12 @@ tweak:
         {
          if (warn)
            {
-             print_z_candidate ("ISO C++ says that ", w, pedwarn);
-             /* Translators note: This message is a continuation of the
-                previous one, aligned on the right.  */
-             print_z_candidate ("              and ", l, pedwarn);
-             pedwarn ("are ambiguous even though the worst conversion \
-for the former is better than the worst conversion for the latter");
+             pedwarn ("\
+ISO C++ says that these are ambiguous, even \
+though the worst conversion for the first is better than \
+the worst conversion for the second:");
+             print_z_candidate (_("candidate 1:"), w);
+             print_z_candidate (_("candidate 2:"), l);
            }
          else
            add_warning (w, l);
@@ -5987,6 +6042,42 @@ perform_implicit_conversion (tree type, tree expr)
   return convert_like (conv, expr);
 }
 
+/* Convert EXPR to TYPE (as a direct-initialization) if that is
+   permitted.  If the conversion is valid, the converted expression is
+   returned.  Otherwise, NULL_TREE is returned, except in the case
+   that TYPE is a class type; in that case, an error is issued.  */
+
+tree
+perform_direct_initialization_if_possible (tree type, tree expr)
+{
+  tree conv;
+  
+  if (type == error_mark_node || error_operand_p (expr))
+    return error_mark_node;
+  /* [dcl.init]
+
+     If the destination type is a (possibly cv-qualified) class type:
+
+     -- If the initialization is direct-initialization ...,
+     constructors are considered. ... If no constructor applies, or
+     the overload resolution is ambiguous, the initialization is
+     ill-formed.  */
+  if (CLASS_TYPE_P (type))
+    {
+      expr = build_special_member_call (NULL_TREE, complete_ctor_identifier,
+                                       build_tree_list (NULL_TREE, expr),
+                                       TYPE_BINFO (type),
+                                       LOOKUP_NORMAL);
+      return build_cplus_new (type, expr);
+    }
+  conv = implicit_conversion (type, TREE_TYPE (expr), expr,
+                             LOOKUP_NORMAL);
+  if (!conv || ICS_BAD_FLAG (conv))
+    return NULL_TREE;
+  return convert_like_real (conv, expr, NULL_TREE, 0, 0, 
+                           /*issue_conversion_warnings=*/false);
+}
+
 /* DECL is a VAR_DECL whose type is a REFERENCE_TYPE.  The reference
    is being bound to a temporary.  Create and return a new VAR_DECL
    with the indicated TYPE; this variable will store the value to
@@ -6026,14 +6117,18 @@ make_temporary_var_for_ref_to_temp (tree decl, tree type)
 }
 
 /* Convert EXPR to the indicated reference TYPE, in a way suitable for
-   initializing a variable of that TYPE.   If DECL is non-NULL, it is
+   initializing a variable of that TYPE.  If DECL is non-NULL, it is
    the VAR_DECL being initialized with the EXPR.  (In that case, the
-   type of DECL will be TYPE.)
+   type of DECL will be TYPE.)  If DECL is non-NULL, then CLEANUP must
+   also be non-NULL, and with *CLEANUP initialized to NULL.  Upon
+   return, if *CLEANUP is no longer NULL, it will be a CLEANUP_STMT
+   that should be inserted after the returned expression is used to
+   initialize DECL.
 
    Return the converted expression.  */
 
 tree
-initialize_reference (tree type, tree expr, tree decl)
+initialize_reference (tree type, tree expr, tree decl, tree *cleanup)
 {
   tree conv;
 
@@ -6043,7 +6138,15 @@ initialize_reference (tree type, tree expr, tree decl)
   conv = reference_binding (type, TREE_TYPE (expr), expr, LOOKUP_NORMAL);
   if (!conv || ICS_BAD_FLAG (conv))
     {
-      error ("could not convert `%E' to `%T'", expr, type);
+      if (!(TYPE_QUALS (TREE_TYPE (type)) & TYPE_QUAL_CONST)
+          && !real_lvalue_p (expr))
+        error ("invalid initialization of non-const reference of "
+               "type '%T' from a temporary of type '%T'",
+               type, TREE_TYPE (expr));
+      else
+        error ("invalid initialization of reference of type "
+              "'%T' from expression of type '%T'", type, 
+              TREE_TYPE (expr));
       return error_mark_node;
     }
 
@@ -6079,7 +6182,7 @@ initialize_reference (tree type, tree expr, tree decl)
        T t;
        const S& s = t;
 
-    we can extend the lifetime of the returnn value of the conversion
+    we can extend the lifetime of the return value of the conversion
     operator.  */
   my_friendly_assert (TREE_CODE (conv) == REF_BIND, 20030302);
   if (decl)
@@ -6100,15 +6203,53 @@ initialize_reference (tree type, tree expr, tree decl)
        base_conv_type = NULL_TREE;
       /* Perform the remainder of the conversion.  */
       expr = convert_like (conv, expr);
-      if (!real_non_cast_lvalue_p (expr))
+      if (!real_lvalue_p (expr))
        {
+         tree init;
+         tree type;
+
          /* Create the temporary variable.  */
-         var = make_temporary_var_for_ref_to_temp (decl, TREE_TYPE (expr));
-         DECL_INITIAL (var) = expr;
-         cp_finish_decl (var, expr, NULL_TREE, 
-                     LOOKUP_ONLYCONVERTING|DIRECT_BIND);
+         type = TREE_TYPE (expr);
+         var = make_temporary_var_for_ref_to_temp (decl, type);
+         layout_decl (var, 0);
+         /* Create the INIT_EXPR that will initialize the temporary
+            variable.  */
+         init = build (INIT_EXPR, type, var, expr);
+         if (at_function_scope_p ())
+           {
+             add_decl_stmt (var);
+             *cleanup = cxx_maybe_build_cleanup (var);
+             if (*cleanup)
+               /* We must be careful to destroy the temporary only
+                  after its initialization has taken place.  If the
+                  initialization throws an exception, then the
+                  destructor should not be run.  We cannot simply
+                  transform INIT into something like:
+            
+                    (INIT, ({ CLEANUP_STMT; }))
+
+                  because emit_local_var always treats the
+                  initializer as a full-expression.  Thus, the
+                  destructor would run too early; it would run at the
+                  end of initializing the reference variable, rather
+                  than at the end of the block enclosing the
+                  reference variable.
+
+                  The solution is to pass back a CLEANUP_STMT which
+                  the caller is responsible for attaching to the
+                  statement tree.  */
+               *cleanup = build_stmt (CLEANUP_STMT, var, *cleanup);
+           }
+         else
+           {
+             rest_of_decl_compilation (var, NULL, /*toplev=*/1, at_eof);
+             if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+               static_aggregates = tree_cons (NULL_TREE, var,
+                                              static_aggregates);
+           }
          /* Use its address to initialize the reference variable.  */
          expr = build_address (var);
+         expr = build (COMPOUND_EXPR, TREE_TYPE (expr), init, expr);
        }
       else
        /* Take the address of EXPR.  */
This page took 0.084685 seconds and 5 git commands to generate.