OSDN Git Service

Fix PR c++/42766
[pf3gnuchains/gcc-fork.git] / gcc / cp / cvt.c
index 83b35d6..cbe8596 100644 (file)
@@ -1,13 +1,14 @@
 /* Language-level data type conversion for GNU C++.
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+   Free Software Foundation, Inc.
    Hacked by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GCC is distributed in the hope that it will be useful,
@@ -16,9 +17,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 
 /* This file contains the functions for converting C++ expressions
@@ -38,7 +38,7 @@ Boston, MA 02110-1301, USA.  */
 #include "decl.h"
 #include "target.h"
 
-static tree cp_convert_to_pointer (tree, tree, bool);
+static tree cp_convert_to_pointer (tree, tree);
 static tree convert_to_pointer_force (tree, tree);
 static tree build_type_conversion (tree, tree);
 static tree build_up_reference (tree, tree, int, tree);
@@ -71,12 +71,10 @@ static void warn_ref_binding (tree, tree, tree);
      else if dealing with method pointers, delegate
      else convert blindly
    else if converting class, pass off to build_type_conversion
-   else try C-style pointer conversion.  If FORCE is true then allow
-   conversions via virtual bases (these are permitted by reinterpret_cast,
-   but not static_cast).  */
+   else try C-style pointer conversion.  */
 
 static tree
-cp_convert_to_pointer (tree type, tree expr, bool force)
+cp_convert_to_pointer (tree type, tree expr)
 {
   tree intype = TREE_TYPE (expr);
   enum tree_code form;
@@ -84,7 +82,7 @@ cp_convert_to_pointer (tree type, tree expr, bool force)
   if (intype == error_mark_node)
     return error_mark_node;
 
-  if (IS_AGGR_TYPE (intype))
+  if (MAYBE_CLASS_TYPE_P (intype))
     {
       intype = complete_type (intype);
       if (!COMPLETE_TYPE_P (intype))
@@ -129,8 +127,8 @@ cp_convert_to_pointer (tree type, tree expr, bool force)
       if (TYPE_MAIN_VARIANT (type) != intype
          && TREE_CODE (type) == POINTER_TYPE
          && TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE
-         && IS_AGGR_TYPE (TREE_TYPE (type))
-         && IS_AGGR_TYPE (TREE_TYPE (intype))
+         && MAYBE_CLASS_TYPE_P (TREE_TYPE (type))
+         && MAYBE_CLASS_TYPE_P (TREE_TYPE (intype))
          && TREE_CODE (TREE_TYPE (intype)) == RECORD_TYPE)
        {
          enum tree_code code = PLUS_EXPR;
@@ -174,61 +172,17 @@ cp_convert_to_pointer (tree type, tree expr, bool force)
 
       return build_nop (type, expr);
     }
-  else if (TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
-    {
-      tree b1;
-      tree b2;
-      tree binfo;
-      enum tree_code code = PLUS_EXPR;
-      base_kind bk;
-
-      b1 = TYPE_PTRMEM_CLASS_TYPE (type);
-      b2 = TYPE_PTRMEM_CLASS_TYPE (intype);
-      binfo = lookup_base (b1, b2, ba_check, &bk);
-      if (!binfo)
-       {
-         binfo = lookup_base (b2, b1, ba_check, &bk);
-         code = MINUS_EXPR;
-       }
-      if (binfo == error_mark_node)
-       return error_mark_node;
-
-      if (bk == bk_via_virtual)
-       {
-         if (force)
-           warning (0, "pointer to member cast from %qT to %qT is via"
-                    " virtual base", intype, type);
-         else
-           {
-             error ("pointer to member cast from %qT to %qT is"
-                    " via virtual base", intype, type);
-             return error_mark_node;
-           }
-         /* This is a reinterpret cast, whose result is unspecified.
-            We choose to do nothing.  */
-         return build1 (NOP_EXPR, type, expr);
-       }
-
-      if (TREE_CODE (expr) == PTRMEM_CST)
-       expr = cplus_expand_constant (expr);
-
-      if (binfo && !integer_zerop (BINFO_OFFSET (binfo)))
-       expr = size_binop (code,
-                          build_nop (sizetype, expr),
-                          BINFO_OFFSET (binfo));
-      return build_nop (type, expr);
-    }
-  else if (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype))
-    return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0,
-                            /*c_cast_p=*/false);
+  else if ((TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
+          || (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype)))
+    return convert_ptrmem (type, expr, /*allow_inverse_p=*/false,
+                          /*c_cast_p=*/false);
   else if (TYPE_PTRMEMFUNC_P (intype))
     {
       if (!warn_pmf2ptr)
        {
          if (TREE_CODE (expr) == PTRMEM_CST)
            return cp_convert_to_pointer (type,
-                                         PTRMEM_CST_MEMBER (expr),
-                                         force);
+                                         PTRMEM_CST_MEMBER (expr));
          else if (TREE_CODE (expr) == OFFSET_REF)
            {
              tree object = TREE_OPERAND (expr, 0);
@@ -251,9 +205,7 @@ cp_convert_to_pointer (tree type, tree expr, bool force)
        {
          /* A NULL pointer-to-member is represented by -1, not by
             zero.  */
-         expr = build_int_cst (type, -1);
-         /* Fix up the representation of -1 if appropriate.  */
-         expr = force_fit_type (expr, 0, false, false);
+         expr = build_int_cst_type (type, -1);
        }
       else
        expr = build_int_cst (type, 0);
@@ -304,8 +256,8 @@ convert_to_pointer_force (tree type, tree expr)
 
       if (TYPE_MAIN_VARIANT (type) != intype
          && TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE
-         && IS_AGGR_TYPE (TREE_TYPE (type))
-         && IS_AGGR_TYPE (TREE_TYPE (intype))
+         && MAYBE_CLASS_TYPE_P (TREE_TYPE (type))
+         && MAYBE_CLASS_TYPE_P (TREE_TYPE (intype))
          && TREE_CODE (TREE_TYPE (intype)) == RECORD_TYPE)
        {
          enum tree_code code = PLUS_EXPR;
@@ -335,7 +287,7 @@ convert_to_pointer_force (tree type, tree expr)
        }
     }
 
-  return cp_convert_to_pointer (type, expr, true);
+  return cp_convert_to_pointer (type, expr);
 }
 
 /* We are passing something to a function which requires a reference.
@@ -374,14 +326,14 @@ build_up_reference (tree type, tree arg, int flags, tree decl)
   /* If we had a way to wrap this up, and say, if we ever needed its
      address, transform all occurrences of the register, into a memory
      reference we could win better.  */
-  rval = build_unary_op (ADDR_EXPR, arg, 1);
+  rval = cp_build_unary_op (ADDR_EXPR, arg, 1, tf_warning_or_error);
   if (rval == error_mark_node)
     return error_mark_node;
 
   if ((flags & LOOKUP_PROTECT)
       && TYPE_MAIN_VARIANT (argtype) != TYPE_MAIN_VARIANT (target_type)
-      && IS_AGGR_TYPE (argtype)
-      && IS_AGGR_TYPE (target_type))
+      && MAYBE_CLASS_TYPE_P (argtype)
+      && MAYBE_CLASS_TYPE_P (target_type))
     {
       /* We go through lookup_base for the access control.  */
       tree binfo = lookup_base (argtype, target_type, ba_check, NULL);
@@ -427,7 +379,7 @@ warn_ref_binding (tree reftype, tree intype, tree decl)
          msg = "conversion to non-const reference type %q#T from"
            " rvalue of type %qT";
 
-      pedwarn (msg, reftype, intype);
+      permerror (input_location, msg, reftype, intype);
     }
 }
 
@@ -466,7 +418,7 @@ convert_to_reference (tree reftype, tree expr, int convtype,
 
   can_convert_intype_to_type = can_convert (type, intype);
   if (!can_convert_intype_to_type
-      && (convtype & CONV_IMPLICIT) && IS_AGGR_TYPE (intype)
+      && (convtype & CONV_IMPLICIT) && MAYBE_CLASS_TYPE_P (intype)
       && ! (flags & LOOKUP_NO_CONVERSION))
     {
       /* Look for a user-defined conversion to lvalue that we can use.  */
@@ -497,8 +449,8 @@ convert_to_reference (tree reftype, tree expr, int convtype,
 
          if (! (convtype & CONV_CONST)
                   && !at_least_as_qualified_p (ttl, ttr))
-           pedwarn ("conversion from %qT to %qT discards qualifiers",
-                    ttr, reftype);
+           permerror (input_location, "conversion from %qT to %qT discards qualifiers",
+                      ttr, reftype);
        }
 
       return build_up_reference (reftype, expr, flags, decl);
@@ -518,7 +470,7 @@ convert_to_reference (tree reftype, tree expr, int convtype,
        warning (0, "casting %qT to %qT does not dereference pointer",
                 intype, reftype);
 
-      rval = build_unary_op (ADDR_EXPR, expr, 0);
+      rval = cp_build_unary_op (ADDR_EXPR, expr, 0, tf_warning_or_error);
       if (rval != error_mark_node)
        rval = convert_force (build_pointer_type (TREE_TYPE (reftype)),
                              rval, 0);
@@ -528,7 +480,8 @@ convert_to_reference (tree reftype, tree expr, int convtype,
   else
     {
       rval = convert_for_initialization (NULL_TREE, type, expr, flags,
-                                        "converting", 0, 0);
+                                        "converting", 0, 0,
+                                         tf_warning_or_error);
       if (rval == NULL_TREE || rval == error_mark_node)
        return rval;
       warn_ref_binding (reftype, intype, decl);
@@ -553,9 +506,10 @@ convert_to_reference (tree reftype, tree expr, int convtype,
 tree
 convert_from_reference (tree val)
 {
-  if (TREE_CODE (TREE_TYPE (val)) == REFERENCE_TYPE)
+  if (TREE_TYPE (val)
+      && TREE_CODE (TREE_TYPE (val)) == REFERENCE_TYPE)
     {
-      tree t = canonical_type_variant (TREE_TYPE (TREE_TYPE (val)));
+      tree t = TREE_TYPE (TREE_TYPE (val));
       tree ref = build1 (INDIRECT_REF, t, val);
 
        /* We *must* set TREE_READONLY when dereferencing a pointer to const,
@@ -578,7 +532,7 @@ convert_from_reference (tree val)
 tree
 force_rvalue (tree expr)
 {
-  if (IS_AGGR_TYPE (TREE_TYPE (expr)) && TREE_CODE (expr) != TARGET_EXPR)
+  if (MAYBE_CLASS_TYPE_P (TREE_TYPE (expr)) && TREE_CODE (expr) != TARGET_EXPR)
     expr = ocp_convert (TREE_TYPE (expr), expr,
                        CONV_IMPLICIT|CONV_FORCE_TEMP, LOOKUP_NORMAL);
   else
@@ -586,7 +540,16 @@ force_rvalue (tree expr)
 
   return expr;
 }
+
 \f
+/* Fold away simple conversions, but make sure the result is an rvalue.  */
+
+tree
+cp_fold_convert (tree type, tree expr)
+{
+  return rvalue (fold_convert (type, expr));
+}
+
 /* C++ conversions, preference to static cast conversions.  */
 
 tree
@@ -595,6 +558,31 @@ cp_convert (tree type, tree expr)
   return ocp_convert (type, expr, CONV_OLD_CONVERT, LOOKUP_NORMAL);
 }
 
+/* C++ equivalent of convert_and_check but using cp_convert as the
+   conversion function.
+
+   Convert EXPR to TYPE, warning about conversion problems with constants.
+   Invoke this function on every expression that is converted implicitly,
+   i.e. because of language rules and not because of an explicit cast.  */
+
+tree
+cp_convert_and_check (tree type, tree expr)
+{
+  tree result;
+
+  if (TREE_TYPE (expr) == type)
+    return expr;
+  
+  result = cp_convert (type, expr);
+
+  if (c_inhibit_evaluation_warnings == 0
+      && !TREE_OVERFLOW_P (expr)
+      && result != error_mark_node)
+    warnings_for_convert_and_check (type, expr, result);
+
+  return result;
+}
+
 /* Conversion...
 
    FLAGS indicates how we should behave.  */
@@ -605,6 +593,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
   tree e = expr;
   enum tree_code code = TREE_CODE (type);
   const char *invalid_conv_diag;
+  tree e1;
 
   if (error_operand_p (e) || type == error_mark_node)
     return error_mark_node;
@@ -621,13 +610,9 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
 
   e = integral_constant_value (e);
 
-  if (IS_AGGR_TYPE (type) && (convtype & CONV_FORCE_TEMP)
-      /* Some internal structures (vtable_entry_type, sigtbl_ptr_type)
-        don't go through finish_struct, so they don't have the synthesized
-        constructors.  So don't force a temporary.  */
-      && TYPE_HAS_CONSTRUCTOR (type))
+  if (MAYBE_CLASS_TYPE_P (type) && (convtype & CONV_FORCE_TEMP))
     /* We need a new temporary; don't take this shortcut.  */;
-  else if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
+  else if (same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE (e)))
     {
       if (same_type_p (type, TREE_TYPE (e)))
        /* The call to fold will not always remove the NOP_EXPR as
@@ -644,10 +629,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
       else if (TREE_CODE (e) == TARGET_EXPR)
        {
          /* Don't build a NOP_EXPR of class type.  Instead, change the
-            type of the temporary.  Only allow this for cv-qual changes,
-            though.  */
-         gcc_assert (same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (e)),
-                                  TYPE_MAIN_VARIANT (type)));
+            type of the temporary.  */
          TREE_TYPE (e) = TREE_TYPE (TARGET_EXPR_SLOT (e)) = type;
          return e;
        }
@@ -660,30 +642,50 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
        }
     }
 
+  e1 = targetm.convert_to_type (type, e);
+  if (e1)
+    return e1;
+
   if (code == VOID_TYPE && (convtype & CONV_STATIC))
     {
-      e = convert_to_void (e, /*implicit=*/NULL);
+      e = convert_to_void (e, /*implicit=*/NULL, tf_warning_or_error);
       return e;
     }
 
   if (INTEGRAL_CODE_P (code))
     {
       tree intype = TREE_TYPE (e);
-      /* enum = enum, enum = int, enum = float, (enum)pointer are all
-        errors.  */
-      if (TREE_CODE (type) == ENUMERAL_TYPE
-         && (((INTEGRAL_OR_ENUMERATION_TYPE_P (intype)
+
+      if (TREE_CODE (type) == ENUMERAL_TYPE)
+       {
+         /* enum = enum, enum = int, enum = float, (enum)pointer are all
+            errors.  */
+         if (((INTEGRAL_OR_ENUMERATION_TYPE_P (intype)
                || TREE_CODE (intype) == REAL_TYPE)
               && ! (convtype & CONV_STATIC))
-             || TREE_CODE (intype) == POINTER_TYPE))
-       {
-         if (flags & LOOKUP_COMPLAIN)
-           pedwarn ("conversion from %q#T to %q#T", intype, type);
+             || TREE_CODE (intype) == POINTER_TYPE)
+           {
+             if (flags & LOOKUP_COMPLAIN)
+               permerror (input_location, "conversion from %q#T to %q#T", intype, type);
 
-         if (flag_pedantic_errors)
-           return error_mark_node;
+             if (!flag_permissive)
+               return error_mark_node;
+           }
+
+         /* [expr.static.cast]
+
+            8. A value of integral or enumeration type can be explicitly
+            converted to an enumeration type. The value is unchanged if
+            the original value is within the range of the enumeration
+            values. Otherwise, the resulting enumeration value is
+            unspecified.  */
+         if (TREE_CODE (expr) == INTEGER_CST && !int_fits_type_p (expr, type))
+           warning (OPT_Wconversion, 
+                    "the result of the conversion is unspecified because "
+                    "%qE is outside the range of type %qT",
+                    expr, type);
        }
-      if (IS_AGGR_TYPE (intype))
+      if (MAYBE_CLASS_TYPE_P (intype))
        {
          tree rval;
          rval = build_type_conversion (type, e);
@@ -699,11 +701,11 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
       return fold_if_not_in_template (convert_to_integer (type, e));
     }
   if (POINTER_TYPE_P (type) || TYPE_PTR_TO_MEMBER_P (type))
-    return fold_if_not_in_template (cp_convert_to_pointer (type, e, false));
+    return fold_if_not_in_template (cp_convert_to_pointer (type, e));
   if (code == VECTOR_TYPE)
     {
       tree in_vtype = TREE_TYPE (e);
-      if (IS_AGGR_TYPE (in_vtype))
+      if (MAYBE_CLASS_TYPE_P (in_vtype))
        {
          tree ret_val;
          ret_val = build_type_conversion (type, e);
@@ -717,7 +719,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
     }
   if (code == REAL_TYPE || code == COMPLEX_TYPE)
     {
-      if (IS_AGGR_TYPE (TREE_TYPE (e)))
+      if (MAYBE_CLASS_TYPE_P (TREE_TYPE (e)))
        {
          tree rval;
          rval = build_type_conversion (type, e);
@@ -737,7 +739,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
   /* New C++ semantics:  since assignment is now based on
      memberwise copying,  if the rhs type is derived from the
      lhs type, then we may still do a conversion.  */
-  if (IS_AGGR_TYPE_CODE (code))
+  if (RECORD_OR_UNION_CODE_P (code))
     {
       tree dtype = TREE_TYPE (e);
       tree ctor = NULL_TREE;
@@ -756,24 +758,38 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
       if (abstract_virtuals_error (NULL_TREE, type))
        return error_mark_node;
 
-      if ((flags & LOOKUP_ONLYCONVERTING)
-         && ! (IS_AGGR_TYPE (dtype) && DERIVED_FROM_P (type, dtype)))
+      if (BRACE_ENCLOSED_INITIALIZER_P (ctor))
+       ctor = perform_implicit_conversion (type, ctor, tf_warning_or_error);
+      else if ((flags & LOOKUP_ONLYCONVERTING)
+              && ! (CLASS_TYPE_P (dtype) && DERIVED_FROM_P (type, dtype)))
        /* For copy-initialization, first we create a temp of the proper type
           with a user-defined conversion sequence, then we direct-initialize
           the target with the temp (see [dcl.init]).  */
        ctor = build_user_type_conversion (type, ctor, flags);
       else
-       ctor = build_special_member_call (NULL_TREE,
-                                         complete_ctor_identifier,
-                                         build_tree_list (NULL_TREE, ctor),
-                                         type, flags);
+       {
+         VEC(tree,gc) *ctor_vec = make_tree_vector_single (ctor);
+         ctor = build_special_member_call (NULL_TREE,
+                                           complete_ctor_identifier,
+                                           &ctor_vec,
+                                           type, flags,
+                                           tf_warning_or_error);
+         release_tree_vector (ctor_vec);
+       }
       if (ctor)
        return build_cplus_new (type, ctor);
     }
 
   if (flags & LOOKUP_COMPLAIN)
-    error ("conversion from %qT to non-scalar type %qT requested",
-          TREE_TYPE (expr), type);
+    {
+      /* If the conversion failed and expr was an invalid use of pointer to
+        member function, try to report a meaningful error.  */
+      if (invalid_nonstatic_memfn_p (expr, tf_warning_or_error))
+       /* We displayed the error message.  */;
+      else
+       error ("conversion from %qT to non-scalar type %qT requested",
+              TREE_TYPE (expr), type);
+    }
   return error_mark_node;
 }
 
@@ -792,21 +808,25 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
    make it impossible to ignore the reference return value from functions. We
    issue warnings in the confusing cases.
 
-   IMPLICIT is tells us the context of an implicit void conversion.  */
+   IMPLICIT is non-NULL iff an expression is being implicitly converted; it
+   is NULL when the user is explicitly converting an expression to void via
+   a cast.  When non-NULL, IMPLICIT is a string indicating the context of
+   the implicit conversion.  */
 
 tree
-convert_to_void (tree expr, const char *implicit)
+convert_to_void (tree expr, const char *implicit, tsubst_flags_t complain)
 {
   if (expr == error_mark_node
       || TREE_TYPE (expr) == error_mark_node)
     return error_mark_node;
   if (!TREE_TYPE (expr))
     return expr;
-  if (invalid_nonstatic_memfn_p (expr))
+  if (invalid_nonstatic_memfn_p (expr, complain))
     return error_mark_node;
   if (TREE_CODE (expr) == PSEUDO_DTOR_EXPR)
     {
-      error ("pseudo-destructor is not called");
+      if (complain & tf_error)
+        error ("pseudo-destructor is not called");
       return error_mark_node;
     }
   if (VOID_TYPE_P (TREE_TYPE (expr)))
@@ -818,12 +838,13 @@ convert_to_void (tree expr, const char *implicit)
        /* The two parts of a cond expr might be separate lvalues.  */
        tree op1 = TREE_OPERAND (expr,1);
        tree op2 = TREE_OPERAND (expr,2);
+       bool side_effects = TREE_SIDE_EFFECTS (op1) || TREE_SIDE_EFFECTS (op2);
        tree new_op1 = convert_to_void
-         (op1, (implicit && !TREE_SIDE_EFFECTS (op2)
-                ? "second operand of conditional" : NULL));
+         (op1, (implicit && !side_effects
+                ? "second operand of conditional" : NULL), complain);
        tree new_op2 = convert_to_void
-         (op2, (implicit && !TREE_SIDE_EFFECTS (op1)
-                ? "third operand of conditional" : NULL));
+         (op2, (implicit && !side_effects
+                ? "third operand of conditional" : NULL), complain);
 
        expr = build3 (COND_EXPR, TREE_TYPE (new_op1),
                       TREE_OPERAND (expr, 0), new_op1, new_op2);
@@ -836,7 +857,7 @@ convert_to_void (tree expr, const char *implicit)
        tree op1 = TREE_OPERAND (expr,1);
        tree new_op1 = convert_to_void
          (op1, (implicit && !TREE_NO_WARNING (expr)
-                ? "right-hand operand of comma" : NULL));
+                ? "right-hand operand of comma" : NULL), complain);
 
        if (new_op1 != op1)
          {
@@ -866,16 +887,36 @@ convert_to_void (tree expr, const char *implicit)
 
        /* Can't load the value if we don't know the type.  */
        if (is_volatile && !is_complete)
-         warning (0, "object of incomplete type %qT will not be accessed in %s",
-                  type, implicit ? implicit : "void context");
+          {
+            if (complain & tf_warning)
+              warning (0, "object of incomplete type %qT will not be accessed in %s",
+                       type, implicit ? implicit : "void context");
+          }
        /* Don't load the value if this is an implicit dereference, or if
           the type needs to be handled by ctors/dtors.  */
        else if (is_volatile && (is_reference || TREE_ADDRESSABLE (type)))
-         warning (0, "object of type %qT will not be accessed in %s",
-                  TREE_TYPE (TREE_OPERAND (expr, 0)),
-                  implicit ? implicit : "void context");
+          {
+            if (complain & tf_warning)
+              warning (0, "object of type %qT will not be accessed in %s",
+                       TREE_TYPE (TREE_OPERAND (expr, 0)),
+                       implicit ? implicit : "void context");
+          }
        if (is_reference || !is_volatile || !is_complete || TREE_ADDRESSABLE (type))
-         expr = TREE_OPERAND (expr, 0);
+          {
+            /* Emit a warning (if enabled) when the "effect-less" INDIRECT_REF
+               operation is stripped off. Note that we don't warn about
+               - an expression with TREE_NO_WARNING set. (For an example of
+                 such expressions, see build_over_call in call.c.)
+               - automatic dereferencing of references, since the user cannot
+                 control it. (See also warn_if_unused_value() in stmt.c.)  */
+            if (warn_unused_value
+               && implicit
+                && (complain & tf_warning)
+                && !TREE_NO_WARNING (expr)
+                && !is_reference)
+              warning (OPT_Wunused_value, "value computed is not used");
+            expr = TREE_OPERAND (expr, 0);
+          }
 
        break;
       }
@@ -886,14 +927,37 @@ convert_to_void (tree expr, const char *implicit)
        tree type = TREE_TYPE (expr);
        int is_complete = COMPLETE_TYPE_P (complete_type (type));
 
-       if (TYPE_VOLATILE (type) && !is_complete)
+       if (TYPE_VOLATILE (type) && !is_complete && (complain & tf_warning))
          warning (0, "object %qE of incomplete type %qT will not be accessed in %s",
                   expr, type, implicit ? implicit : "void context");
        break;
       }
 
+    case TARGET_EXPR:
+      /* Don't bother with the temporary object returned from a function if
+        we don't use it and don't need to destroy it.  We'll still
+        allocate space for it in expand_call or declare_return_variable,
+        but we don't need to track it through all the tree phases.  */
+      if (TARGET_EXPR_IMPLICIT_P (expr)
+         && TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (expr)))
+       {
+         tree init = TARGET_EXPR_INITIAL (expr);
+         if (TREE_CODE (init) == AGGR_INIT_EXPR
+             && !AGGR_INIT_VIA_CTOR_P (init))
+           {
+             tree fn = AGGR_INIT_EXPR_FN (init);
+             expr = build_call_array_loc (input_location,
+                                          TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))),
+                                          fn,
+                                          aggr_init_expr_nargs (init),
+                                          AGGR_INIT_EXPR_ARGP (init));
+           }
+       }
+      break;
+
     default:;
     }
+  expr = resolve_nondeduced_context (expr);
   {
     tree probe = expr;
 
@@ -903,14 +967,22 @@ convert_to_void (tree expr, const char *implicit)
       {
        /* [over.over] enumerates the places where we can take the address
           of an overloaded function, and this is not one of them.  */
-       pedwarn ("%s cannot resolve address of overloaded function",
-                   implicit ? implicit : "void cast");
+       if (complain & tf_error)
+         error ("%s cannot resolve address of overloaded function",
+                implicit ? implicit : "void cast");
+       else
+         return error_mark_node;
        expr = void_zero_node;
       }
     else if (implicit && probe == expr && is_overloaded_fn (probe))
-      /* Only warn when there is no &.  */
-      warning (0, "%s is a reference, not call, to function %qE",
-                 implicit, expr);
+      {
+       /* Only warn when there is no &.  */
+       if (complain & tf_warning)
+         warning (OPT_Waddress, "%s is a reference, not call, to function %qE",
+                  implicit, expr);
+       if (TREE_CODE (expr) == COMPONENT_REF)
+         expr = TREE_OPERAND (expr, 0);
+      }
   }
 
   if (expr != error_mark_node && !VOID_TYPE_P (TREE_TYPE (expr)))
@@ -922,13 +994,15 @@ convert_to_void (tree expr, const char *implicit)
        {
          /* The middle end does not warn about expressions that have
             been explicitly cast to void, so we must do so here.  */
-         if (!TREE_SIDE_EFFECTS (expr))
-           warning (OPT_Wunused_value, "%s has no effect", implicit);
+         if (!TREE_SIDE_EFFECTS (expr)) {
+            if (complain & tf_warning)
+              warning (OPT_Wunused_value, "%s has no effect", implicit);
+          }
          else
            {
              tree e;
              enum tree_code code;
-             enum tree_code_class class;
+             enum tree_code_class tclass;
 
              e = expr;
              /* We might like to warn about (say) "(int) f()", as the
@@ -945,16 +1019,17 @@ convert_to_void (tree expr, const char *implicit)
                e = TREE_OPERAND (e, 0);
 
              code = TREE_CODE (e);
-             class = TREE_CODE_CLASS (code);
-             if (class == tcc_comparison
-                  || class == tcc_unary
-                  || (class == tcc_binary
+             tclass = TREE_CODE_CLASS (code);
+             if ((tclass == tcc_comparison
+                  || tclass == tcc_unary
+                  || (tclass == tcc_binary
                       && !(code == MODIFY_EXPR
                            || code == INIT_EXPR
                            || code == PREDECREMENT_EXPR
                            || code == PREINCREMENT_EXPR
                            || code == POSTDECREMENT_EXPR
                            || code == POSTINCREMENT_EXPR)))
+                  && (complain & tf_warning))
                warning (OPT_Wunused_value, "value computed is not used");
            }
        }
@@ -973,7 +1048,7 @@ convert_to_void (tree expr, const char *implicit)
 
    Most of this routine is from build_reinterpret_cast.
 
-   The backend cannot call cp_convert (what was convert) because
+   The back end cannot call cp_convert (what was convert) because
    conversions to/from basetypes may involve memory references
    (vbases) and adding or subtracting small values (multiple
    inheritance), but it calls convert from the constant folding code
@@ -1072,7 +1147,7 @@ build_expr_type_conversion (int desires, tree expr, bool complain)
   if (basetype == error_mark_node)
     return error_mark_node;
 
-  if (! IS_AGGR_TYPE (basetype))
+  if (! MAYBE_CLASS_TYPE_P (basetype))
     switch (TREE_CODE (basetype))
       {
       case INTEGER_TYPE:
@@ -1080,7 +1155,6 @@ build_expr_type_conversion (int desires, tree expr, bool complain)
          return expr;
        /* else fall through...  */
 
-      case VECTOR_TYPE:
       case BOOLEAN_TYPE:
        return (desires & WANT_INT) ? expr : NULL_TREE;
       case ENUMERAL_TYPE:
@@ -1094,6 +1168,23 @@ build_expr_type_conversion (int desires, tree expr, bool complain)
       case ARRAY_TYPE:
        return (desires & WANT_POINTER) ? decay_conversion (expr)
                                        : NULL_TREE;
+
+      case VECTOR_TYPE:
+       if ((desires & WANT_VECTOR) == 0)
+         return NULL_TREE;
+       switch (TREE_CODE (TREE_TYPE (basetype)))
+         {
+         case INTEGER_TYPE:
+         case BOOLEAN_TYPE:
+           return (desires & WANT_INT) ? expr : NULL_TREE;
+         case ENUMERAL_TYPE:
+           return (desires & WANT_ENUM) ? expr : NULL_TREE;
+         case REAL_TYPE:
+           return (desires & WANT_FLOAT) ? expr : NULL_TREE;
+         default:
+           return NULL_TREE;
+         }
+
       default:
        return NULL_TREE;
       }
@@ -1105,15 +1196,21 @@ build_expr_type_conversion (int desires, tree expr, bool complain)
   if (!TYPE_HAS_CONVERSION (basetype))
     return NULL_TREE;
 
-  for (conv = lookup_conversions (basetype); conv; conv = TREE_CHAIN (conv))
+  for (conv = lookup_conversions (basetype, /*lookup_template_convs_p=*/true);
+       conv;
+       conv = TREE_CHAIN (conv))
     {
       int win = 0;
       tree candidate;
       tree cand = TREE_VALUE (conv);
+      cand = OVL_CURRENT (cand);
 
       if (winner && winner == cand)
        continue;
 
+      if (DECL_NONCONVERTING_P (cand))
+       continue;
+
       candidate = non_reference (TREE_TYPE (TREE_TYPE (cand)));
 
       switch (TREE_CODE (candidate))
@@ -1128,6 +1225,23 @@ build_expr_type_conversion (int desires, tree expr, bool complain)
        case POINTER_TYPE:
          win = (desires & WANT_POINTER); break;
 
+       case VECTOR_TYPE:
+         if ((desires & WANT_VECTOR) == 0)
+           break;
+         switch (TREE_CODE (TREE_TYPE (candidate)))
+           {
+           case BOOLEAN_TYPE:
+           case INTEGER_TYPE:
+             win = (desires & WANT_INT); break;
+           case ENUMERAL_TYPE:
+             win = (desires & WANT_ENUM); break;
+           case REAL_TYPE:
+             win = (desires & WANT_FLOAT); break;
+           default:
+             break;
+           }
+         break;
+
        default:
          break;
        }
@@ -1164,19 +1278,28 @@ build_expr_type_conversion (int desires, tree expr, bool complain)
 tree
 type_promotes_to (tree type)
 {
+  tree promoted_type;
+
   if (type == error_mark_node)
     return error_mark_node;
 
   type = TYPE_MAIN_VARIANT (type);
 
+  /* Check for promotions of target-defined types first.  */
+  promoted_type = targetm.promoted_type (type);
+  if (promoted_type)
+    return promoted_type;
+
   /* bool always promotes to int (not unsigned), even if it's the same
      size.  */
-  if (type == boolean_type_node)
+  if (TREE_CODE (type) == BOOLEAN_TYPE)
     type = integer_type_node;
 
   /* Normally convert enums to int, but convert wide enums to something
      wider.  */
   else if (TREE_CODE (type) == ENUMERAL_TYPE
+          || type == char16_type_node
+          || type == char32_type_node
           || type == wchar_type_node)
     {
       int precision = MAX (TYPE_PRECISION (type),