]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/cp/cvt.c
Merge from trunk.
[thirdparty/gcc.git] / gcc / cp / cvt.c
index 26c4442a94bc9764d34ef5ad393c83d7f3e3929c..6d0e34156ffced97be1d7f67758f451a0e7a8365 100644 (file)
@@ -1,7 +1,5 @@
 /* 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, 2007, 2008, 2009, 2010
-   Free Software Foundation, Inc.
+   Copyright (C) 1987-2013 Free Software Foundation, Inc.
    Hacked by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GCC.
@@ -31,19 +29,20 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
+#include "stor-layout.h"
 #include "flags.h"
 #include "cp-tree.h"
 #include "intl.h"
 #include "convert.h"
-#include "toplev.h"
 #include "decl.h"
 #include "target.h"
+#include "wide-int.h"
 
-static tree cp_convert_to_pointer (tree, tree);
-static tree convert_to_pointer_force (tree, tree);
+static tree cp_convert_to_pointer (tree, tree, tsubst_flags_t);
+static tree convert_to_pointer_force (tree, tree, tsubst_flags_t);
 static tree build_type_conversion (tree, tree);
-static tree build_up_reference (tree, tree, int, tree);
-static void warn_ref_binding (tree, tree, tree);
+static tree build_up_reference (tree, tree, int, tree, tsubst_flags_t);
+static void diagnose_ref_binding (location_t, tree, tree, tree);
 
 /* Change of width--truncation and extension of integers or reals--
    is represented with NOP_EXPR.  Proper functioning of many things
@@ -75,11 +74,13 @@ static void warn_ref_binding (tree, tree, tree);
    else try C-style pointer conversion.  */
 
 static tree
-cp_convert_to_pointer (tree type, tree expr)
+cp_convert_to_pointer (tree type, tree expr, tsubst_flags_t complain)
 {
   tree intype = TREE_TYPE (expr);
   enum tree_code form;
   tree rval;
+  location_t loc = EXPR_LOC_OR_HERE (expr);
+
   if (intype == error_mark_node)
     return error_mark_node;
 
@@ -88,30 +89,32 @@ cp_convert_to_pointer (tree type, tree expr)
       intype = complete_type (intype);
       if (!COMPLETE_TYPE_P (intype))
        {
-         error ("can't convert from incomplete type %qT to %qT",
-                intype, type);
+         if (complain & tf_error)
+           error_at (loc, "can%'t convert from incomplete type %qT to %qT",
+                     intype, type);
          return error_mark_node;
        }
 
       rval = build_type_conversion (type, expr);
       if (rval)
        {
-         if (rval == error_mark_node)
-           error ("conversion of %qE from %qT to %qT is ambiguous",
-                  expr, intype, type);
+         if ((complain & tf_error)
+             && rval == error_mark_node)
+           error_at (loc, "conversion of %qE from %qT to %qT is ambiguous",
+                     expr, intype, type);
          return rval;
        }
     }
 
   /* Handle anachronistic conversions from (::*)() to cv void* or (*)().  */
-  if (TREE_CODE (type) == POINTER_TYPE
+  if (TYPE_PTR_P (type)
       && (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
          || VOID_TYPE_P (TREE_TYPE (type))))
     {
       if (TYPE_PTRMEMFUNC_P (intype)
          || TREE_CODE (intype) == METHOD_TYPE)
-       return convert_member_func_to_ptr (type, expr);
-      if (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE)
+       return convert_member_func_to_ptr (type, expr, complain);
+      if (TYPE_PTR_P (TREE_TYPE (expr)))
        return build_nop (type, expr);
       intype = TREE_TYPE (expr);
     }
@@ -126,7 +129,7 @@ cp_convert_to_pointer (tree type, tree expr)
       intype = TYPE_MAIN_VARIANT (intype);
 
       if (TYPE_MAIN_VARIANT (type) != intype
-         && TREE_CODE (type) == POINTER_TYPE
+         && TYPE_PTR_P (type)
          && TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE
          && MAYBE_CLASS_TYPE_P (TREE_TYPE (type))
          && MAYBE_CLASS_TYPE_P (TREE_TYPE (intype))
@@ -146,11 +149,13 @@ cp_convert_to_pointer (tree type, tree expr)
          binfo = NULL_TREE;
          /* Try derived to base conversion.  */
          if (!same_p)
-           binfo = lookup_base (intype_class, type_class, ba_check, NULL);
+           binfo = lookup_base (intype_class, type_class, ba_check,
+                                NULL, complain);
          if (!same_p && !binfo)
            {
              /* Try base to derived conversion.  */
-             binfo = lookup_base (type_class, intype_class, ba_check, NULL);
+             binfo = lookup_base (type_class, intype_class, ba_check,
+                                  NULL, complain);
              code = MINUS_EXPR;
            }
          if (binfo == error_mark_node)
@@ -158,7 +163,7 @@ cp_convert_to_pointer (tree type, tree expr)
          if (binfo || same_p)
            {
              if (binfo)
-               expr = build_base_path (code, expr, binfo, 0);
+               expr = build_base_path (code, expr, binfo, 0, complain);
              /* Add any qualifier conversions.  */
              return build_nop (type, expr);
            }
@@ -166,33 +171,35 @@ cp_convert_to_pointer (tree type, tree expr)
 
       if (TYPE_PTRMEMFUNC_P (type))
        {
-         error ("cannot convert %qE from type %qT to type %qT",
-                expr, intype, type);
+         if (complain & tf_error)
+           error_at (loc, "cannot convert %qE from type %qT to type %qT",
+                     expr, intype, type);
          return error_mark_node;
        }
 
       return build_nop (type, expr);
     }
-  else if ((TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
+  else if ((TYPE_PTRDATAMEM_P (type) && TYPE_PTRDATAMEM_P (intype))
           || (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype)))
     return convert_ptrmem (type, expr, /*allow_inverse_p=*/false,
-                          /*c_cast_p=*/false, tf_warning_or_error);
+                          /*c_cast_p=*/false, complain);
   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));
+           return cp_convert_to_pointer (type, PTRMEM_CST_MEMBER (expr),
+                                         complain);
          else if (TREE_CODE (expr) == OFFSET_REF)
            {
              tree object = TREE_OPERAND (expr, 0);
              return get_member_function_from_ptrfunc (&object,
-                                                      TREE_OPERAND (expr, 1));
+                                                      TREE_OPERAND (expr, 1),
+                                                      complain);
            }
        }
-      error ("cannot convert %qE from type %qT to type %qT",
-            expr, intype, type);
+      error_at (loc, "cannot convert %qE from type %qT to type %qT",
+               expr, intype, type);
       return error_mark_node;
     }
 
@@ -200,22 +207,24 @@ cp_convert_to_pointer (tree type, tree expr)
     {
       if (TYPE_PTRMEMFUNC_P (type))
        return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0,
-                                /*c_cast_p=*/false, tf_warning_or_error);
+                                /*c_cast_p=*/false, complain);
 
-      if (TYPE_PTRMEM_P (type))
-       {
-         /* A NULL pointer-to-member is represented by -1, not by
-            zero.  */
-         expr = build_int_cst_type (type, -1);
-       }
-      else
-       expr = build_int_cst (type, 0);
+      if (complain & tf_warning)
+       maybe_warn_zero_as_null_pointer_constant (expr, loc);
 
-      return expr;
+      /* A NULL pointer-to-data-member is represented by -1, not by
+        zero.  */
+      tree val = (TYPE_PTRDATAMEM_P (type)
+                 ? build_int_cst_type (type, -1)
+                 : build_int_cst (type, 0));
+
+      return (TREE_SIDE_EFFECTS (expr)
+             ? build2 (COMPOUND_EXPR, type, expr, val) : val);
     }
-  else if (TYPE_PTR_TO_MEMBER_P (type) && INTEGRAL_CODE_P (form))
+  else if (TYPE_PTRMEM_P (type) && INTEGRAL_CODE_P (form))
     {
-      error ("invalid conversion from %qT to %qT", intype, type);
+      if (complain & tf_error)
+       error_at (loc, "invalid conversion from %qT to %qT", intype, type);
       return error_mark_node;
     }
 
@@ -223,7 +232,8 @@ cp_convert_to_pointer (tree type, tree expr)
     {
       if (TYPE_PRECISION (intype) == POINTER_SIZE)
        return build1 (CONVERT_EXPR, type, expr);
-      expr = cp_convert (c_common_type_for_size (POINTER_SIZE, 0), expr);
+      expr = cp_convert (c_common_type_for_size (POINTER_SIZE, 0), expr,
+                        complain);
       /* Modes may be different but sizes should be the same.  There
         is supposed to be some integral type that is the same width
         as a pointer.  */
@@ -234,10 +244,11 @@ cp_convert_to_pointer (tree type, tree expr)
     }
 
   if (type_unknown_p (expr))
-    return instantiate_type (type, expr, tf_warning_or_error);
+    return instantiate_type (type, expr, complain);
 
-  error ("cannot convert %qE from type %qT to type %qT",
-        expr, intype, type);
+  if (complain & tf_error)
+    error_at (loc, "cannot convert %qE from type %qT to type %qT",
+             expr, intype, type);
   return error_mark_node;
 }
 
@@ -246,7 +257,7 @@ cp_convert_to_pointer (tree type, tree expr)
    (such as conversion from sub-type to private super-type).  */
 
 static tree
-convert_to_pointer_force (tree type, tree expr)
+convert_to_pointer_force (tree type, tree expr, tsubst_flags_t complain)
 {
   tree intype = TREE_TYPE (expr);
   enum tree_code form = TREE_CODE (intype);
@@ -265,18 +276,18 @@ convert_to_pointer_force (tree type, tree expr)
          tree binfo;
 
          binfo = lookup_base (TREE_TYPE (intype), TREE_TYPE (type),
-                              ba_unique, NULL);
+                              ba_unique, NULL, complain);
          if (!binfo)
            {
              binfo = lookup_base (TREE_TYPE (type), TREE_TYPE (intype),
-                                  ba_unique, NULL);
+                                  ba_unique, NULL, complain);
              code = MINUS_EXPR;
            }
          if (binfo == error_mark_node)
            return error_mark_node;
          if (binfo)
            {
-             expr = build_base_path (code, expr, binfo, 0);
+             expr = build_base_path (code, expr, binfo, 0, complain);
              if (expr == error_mark_node)
                 return error_mark_node;
              /* Add any qualifier conversions.  */
@@ -288,7 +299,7 @@ convert_to_pointer_force (tree type, tree expr)
        }
     }
 
-  return cp_convert_to_pointer (type, expr);
+  return cp_convert_to_pointer (type, expr, complain);
 }
 
 /* We are passing something to a function which requires a reference.
@@ -300,7 +311,8 @@ convert_to_pointer_force (tree type, tree expr)
      If DIRECT_BIND is set, DECL is the reference we're binding to.  */
 
 static tree
-build_up_reference (tree type, tree arg, int flags, tree decl)
+build_up_reference (tree type, tree arg, int flags, tree decl,
+                   tsubst_flags_t complain)
 {
   tree rval;
   tree argtype = TREE_TYPE (arg);
@@ -314,7 +326,7 @@ build_up_reference (tree type, tree arg, int flags, tree decl)
         here because it needs to live as long as DECL.  */
       tree targ = arg;
 
-      arg = make_temporary_var_for_ref_to_temp (decl, TREE_TYPE (arg));
+      arg = make_temporary_var_for_ref_to_temp (decl, target_type);
 
       /* Process the initializer for the declaration.  */
       DECL_INITIAL (arg) = targ;
@@ -322,12 +334,12 @@ build_up_reference (tree type, tree arg, int flags, tree decl)
                      LOOKUP_ONLYCONVERTING|DIRECT_BIND);
     }
   else if (!(flags & DIRECT_BIND) && ! lvalue_p (arg))
-    return get_target_expr (arg);
+    return get_target_expr_sfinae (arg, complain);
 
   /* 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 = cp_build_unary_op (ADDR_EXPR, arg, 1, tf_warning_or_error);
+  rval = cp_build_addr_expr (arg, complain);
   if (rval == error_mark_node)
     return error_mark_node;
 
@@ -337,16 +349,18 @@ build_up_reference (tree type, tree arg, int flags, tree decl)
       && 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);
+      tree binfo = lookup_base (argtype, target_type, ba_check,
+                               NULL, complain);
       if (binfo == error_mark_node)
        return error_mark_node;
       if (binfo == NULL_TREE)
        return error_not_base_type (target_type, argtype);
-      rval = build_base_path (PLUS_EXPR, rval, binfo, 1);
+      rval = build_base_path (PLUS_EXPR, rval, binfo, 1, complain);
     }
   else
     rval
-      = convert_to_pointer_force (build_pointer_type (target_type), rval);
+      = convert_to_pointer_force (build_pointer_type (target_type),
+                                 rval, complain);
   return build_nop (type, rval);
 }
 
@@ -359,7 +373,7 @@ build_up_reference (tree type, tree arg, int flags, tree decl)
    non-volatile const type.  */
 
 static void
-warn_ref_binding (tree reftype, tree intype, tree decl)
+diagnose_ref_binding (location_t loc, tree reftype, tree intype, tree decl)
 {
   tree ttl = TREE_TYPE (reftype);
 
@@ -380,7 +394,7 @@ warn_ref_binding (tree reftype, tree intype, tree decl)
        msg = G_("conversion to non-const reference type %q#T from "
                 "rvalue of type %qT");
 
-      permerror (input_location, msg, reftype, intype);
+      permerror (loc, msg, reftype, intype);
     }
 }
 
@@ -393,19 +407,18 @@ warn_ref_binding (tree reftype, tree intype, tree decl)
 
 tree
 convert_to_reference (tree reftype, tree expr, int convtype,
-                     int flags, tree decl)
+                     int flags, tree decl, tsubst_flags_t complain)
 {
   tree type = TYPE_MAIN_VARIANT (TREE_TYPE (reftype));
   tree intype;
   tree rval = NULL_TREE;
   tree rval_as_conversion = NULL_TREE;
   bool can_convert_intype_to_type;
+  location_t loc = EXPR_LOC_OR_HERE (expr);
 
   if (TREE_CODE (type) == FUNCTION_TYPE
       && TREE_TYPE (expr) == unknown_type_node)
-    expr = instantiate_type (type, expr,
-                            (flags & LOOKUP_COMPLAIN)
-                            ? tf_warning_or_error : tf_none);
+    expr = instantiate_type (type, expr, complain);
 
   if (expr == error_mark_node)
     return error_mark_node;
@@ -417,7 +430,8 @@ convert_to_reference (tree reftype, tree expr, int convtype,
 
   intype = TYPE_MAIN_VARIANT (intype);
 
-  can_convert_intype_to_type = can_convert (type, intype);
+  can_convert_intype_to_type = can_convert_standard (type, intype, complain);
+
   if (!can_convert_intype_to_type
       && (convtype & CONV_IMPLICIT) && MAYBE_CLASS_TYPE_P (intype)
       && ! (flags & LOOKUP_NO_CONVERSION))
@@ -437,24 +451,30 @@ convert_to_reference (tree reftype, tree expr, int convtype,
        }
     }
 
-  if (((convtype & CONV_STATIC) && can_convert (intype, type))
+  if (((convtype & CONV_STATIC)
+       && can_convert_standard (intype, type, complain))
       || ((convtype & CONV_IMPLICIT) && can_convert_intype_to_type))
     {
-      if (flags & LOOKUP_COMPLAIN)
-       {
-         tree ttl = TREE_TYPE (reftype);
-         tree ttr = lvalue_type (expr);
+      {
+       tree ttl = TREE_TYPE (reftype);
+       tree ttr = lvalue_type (expr);
 
-         if (! real_lvalue_p (expr))
-           warn_ref_binding (reftype, intype, decl);
+       if ((complain & tf_error)
+           && ! real_lvalue_p (expr))
+         diagnose_ref_binding (loc, reftype, intype, decl);
 
-         if (! (convtype & CONV_CONST)
-                  && !at_least_as_qualified_p (ttl, ttr))
-           permerror (input_location, "conversion from %qT to %qT discards qualifiers",
-                      ttr, reftype);
-       }
+       if (! (convtype & CONV_CONST)
+           && !at_least_as_qualified_p (ttl, ttr))
+         {
+           if (complain & tf_error)
+             permerror (loc, "conversion from %qT to %qT discards qualifiers",
+                        ttr, reftype);
+           else
+             return error_mark_node;
+         }
+      }
 
-      return build_up_reference (reftype, expr, flags, decl);
+      return build_up_reference (reftype, expr, flags, decl, complain);
     }
   else if ((convtype & CONV_REINTERPRET) && lvalue_p (expr))
     {
@@ -465,28 +485,29 @@ convert_to_reference (tree reftype, tree expr, int convtype,
 
       /* B* bp; A& ar = (A&)bp; is valid, but it's probably not what they
         meant.  */
-      if (TREE_CODE (intype) == POINTER_TYPE
+      if ((complain & tf_warning)
+         && TYPE_PTR_P (intype)
          && (comptypes (TREE_TYPE (intype), type,
                         COMPARE_BASE | COMPARE_DERIVED)))
-       warning (0, "casting %qT to %qT does not dereference pointer",
-                intype, reftype);
+       warning_at (loc, 0, "casting %qT to %qT does not dereference pointer",
+                   intype, reftype);
 
-      rval = cp_build_unary_op (ADDR_EXPR, expr, 0, tf_warning_or_error);
+      rval = cp_build_addr_expr (expr, complain);
       if (rval != error_mark_node)
        rval = convert_force (build_pointer_type (TREE_TYPE (reftype)),
-                             rval, 0);
+                             rval, 0, complain);
       if (rval != error_mark_node)
        rval = build1 (NOP_EXPR, reftype, rval);
     }
   else
     {
       rval = convert_for_initialization (NULL_TREE, type, expr, flags,
-                                        ICR_CONVERTING, 0, 0,
-                                         tf_warning_or_error);
+                                        ICR_CONVERTING, 0, 0, complain);
       if (rval == NULL_TREE || rval == error_mark_node)
        return rval;
-      warn_ref_binding (reftype, intype, decl);
-      rval = build_up_reference (reftype, rval, flags, decl);
+      if (complain & tf_error)
+       diagnose_ref_binding (loc, reftype, intype, decl);
+      rval = build_up_reference (reftype, rval, flags, decl, complain);
     }
 
   if (rval)
@@ -495,8 +516,8 @@ convert_to_reference (tree reftype, tree expr, int convtype,
       return rval;
     }
 
-  if (flags & LOOKUP_COMPLAIN)
-    error ("cannot convert type %qT to type %qT", intype, reftype);
+  if (complain & tf_error)
+    error_at (loc, "cannot convert type %qT to type %qT", intype, reftype);
 
   return error_mark_node;
 }
@@ -513,6 +534,7 @@ convert_from_reference (tree val)
       tree t = TREE_TYPE (TREE_TYPE (val));
       tree ref = build1 (INDIRECT_REF, t, val);
 
+      mark_exp_read (val);
        /* We *must* set TREE_READONLY when dereferencing a pointer to const,
          so that we get the proper error message if the result is used
          to assign to.  Also, &* is supposed to be a no-op.  */
@@ -520,7 +542,6 @@ convert_from_reference (tree val)
       TREE_THIS_VOLATILE (ref) = CP_TYPE_VOLATILE_P (t);
       TREE_SIDE_EFFECTS (ref)
        = (TREE_THIS_VOLATILE (ref) || TREE_SIDE_EFFECTS (val));
-      REFERENCE_REF_P (ref) = 1;
       val = ref;
     }
 
@@ -531,32 +552,59 @@ convert_from_reference (tree val)
    argument of class type into a temporary.  */
 
 tree
-force_rvalue (tree expr)
+force_rvalue (tree expr, tsubst_flags_t complain)
 {
-  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);
+  tree type = TREE_TYPE (expr);
+  if (MAYBE_CLASS_TYPE_P (type) && TREE_CODE (expr) != TARGET_EXPR)
+    {
+      vec<tree, va_gc> *args = make_tree_vector_single (expr);
+      expr = build_special_member_call (NULL_TREE, complete_ctor_identifier,
+                                       &args, type, LOOKUP_NORMAL, complain);
+      release_tree_vector (args);
+      expr = build_cplus_new (type, expr, complain);
+    }
   else
-    expr = decay_conversion (expr);
+    expr = decay_conversion (expr, complain);
 
   return expr;
 }
 
 \f
-/* Fold away simple conversions, but make sure the result is an rvalue.  */
+/* If EXPR and ORIG are INTEGER_CSTs, return a version of EXPR that has
+   TREE_OVERFLOW set only if it is set in ORIG.  Otherwise, return EXPR
+   unchanged.  */
+
+static tree
+ignore_overflows (tree expr, tree orig)
+{
+  if (TREE_CODE (expr) == INTEGER_CST
+      && TREE_CODE (orig) == INTEGER_CST
+      && TREE_OVERFLOW (expr) != TREE_OVERFLOW (orig))
+    {
+      gcc_assert (!TREE_OVERFLOW (orig));
+      /* Ensure constant sharing.  */
+      expr = wide_int_to_tree (TREE_TYPE (expr), expr);
+    }
+  return expr;
+}
+
+/* Fold away simple conversions, but make sure TREE_OVERFLOW is set
+   properly.  */
 
 tree
 cp_fold_convert (tree type, tree expr)
 {
-  return rvalue (fold_convert (type, expr));
+  tree conv = fold_convert (type, expr);
+  conv = ignore_overflows (conv, expr);
+  return conv;
 }
 
 /* C++ conversions, preference to static cast conversions.  */
 
 tree
-cp_convert (tree type, tree expr)
+cp_convert (tree type, tree expr, tsubst_flags_t complain)
 {
-  return ocp_convert (type, expr, CONV_OLD_CONVERT, LOOKUP_NORMAL);
+  return ocp_convert (type, expr, CONV_OLD_CONVERT, LOOKUP_NORMAL, complain);
 }
 
 /* C++ equivalent of convert_and_check but using cp_convert as the
@@ -567,19 +615,30 @@ cp_convert (tree type, tree expr)
    i.e. because of language rules and not because of an explicit cast.  */
 
 tree
-cp_convert_and_check (tree type, tree expr)
+cp_convert_and_check (tree type, tree expr, tsubst_flags_t complain)
 {
   tree result;
 
   if (TREE_TYPE (expr) == type)
     return expr;
   
-  result = cp_convert (type, expr);
+  result = cp_convert (type, expr, complain);
 
-  if (c_inhibit_evaluation_warnings == 0
-      && !TREE_OVERFLOW_P (expr)
-      && result != error_mark_node)
-    warnings_for_convert_and_check (type, expr, result);
+  if ((complain & tf_warning)
+      && c_inhibit_evaluation_warnings == 0)
+    {
+      tree folded = maybe_constant_value (expr);
+      tree stripped = folded;
+      tree folded_result = cp_convert (type, folded, complain);
+
+      /* maybe_constant_value wraps an INTEGER_CST with TREE_OVERFLOW in a
+        NOP_EXPR so that it isn't TREE_CONSTANT anymore.  */
+      STRIP_NOPS (stripped);
+
+      if (!TREE_OVERFLOW_P (stripped)
+         && folded_result != error_mark_node)
+       warnings_for_convert_and_check (type, folded, folded_result);
+    }
 
   return result;
 }
@@ -589,12 +648,14 @@ cp_convert_and_check (tree type, tree expr)
    FLAGS indicates how we should behave.  */
 
 tree
-ocp_convert (tree type, tree expr, int convtype, int flags)
+ocp_convert (tree type, tree expr, int convtype, int flags,
+            tsubst_flags_t complain)
 {
   tree e = expr;
   enum tree_code code = TREE_CODE (type);
   const char *invalid_conv_diag;
   tree e1;
+  location_t loc = EXPR_LOC_OR_HERE (expr);
 
   if (error_operand_p (e) || type == error_mark_node)
     return error_mark_node;
@@ -605,11 +666,15 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
   if ((invalid_conv_diag
        = targetm.invalid_conversion (TREE_TYPE (expr), type)))
     {
-      error (invalid_conv_diag);
+      if (complain & tf_error)
+       error (invalid_conv_diag);
       return error_mark_node;
     }
 
-  e = integral_constant_value (e);
+  /* FIXME remove when moving to c_fully_fold model.  */
+  /* FIXME do we still need this test?  */
+  if (!CLASS_TYPE_P (type))
+    e = integral_constant_value (e);
   if (error_operand_p (e))
     return error_mark_node;
 
@@ -629,6 +694,8 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
         conversion.  */
       else if (TREE_CODE (type) == COMPLEX_TYPE)
        return fold_if_not_in_template (convert_to_complex (type, e));
+      else if (TREE_CODE (type) == VECTOR_TYPE)
+       return fold_if_not_in_template (convert_to_vector (type, e));
       else if (TREE_CODE (e) == TARGET_EXPR)
        {
          /* Don't build a NOP_EXPR of class type.  Instead, change the
@@ -651,13 +718,14 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
 
   if (code == VOID_TYPE && (convtype & CONV_STATIC))
     {
-      e = convert_to_void (e, ICV_CAST, tf_warning_or_error);
+      e = convert_to_void (e, ICV_CAST, complain);
       return e;
     }
 
   if (INTEGRAL_CODE_P (code))
     {
       tree intype = TREE_TYPE (e);
+      tree converted;
 
       if (TREE_CODE (type) == ENUMERAL_TYPE)
        {
@@ -666,12 +734,11 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
          if (((INTEGRAL_OR_ENUMERATION_TYPE_P (intype)
                || TREE_CODE (intype) == REAL_TYPE)
               && ! (convtype & CONV_STATIC))
-             || TREE_CODE (intype) == POINTER_TYPE)
+             || TYPE_PTR_P (intype))
            {
-             if (flags & LOOKUP_COMPLAIN)
-               permerror (input_location, "conversion from %q#T to %q#T", intype, type);
-
-             if (!flag_permissive)
+             if (complain & tf_error)
+               permerror (loc, "conversion from %q#T to %q#T", intype, type);
+             else
                return error_mark_node;
            }
 
@@ -682,12 +749,13 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
             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, ENUM_UNDERLYING_TYPE (type)))
-           warning (OPT_Wconversion, 
-                    "the result of the conversion is unspecified because "
-                    "%qE is outside the range of type %qT",
-                    expr, type);
+         if ((complain & tf_warning)
+             && TREE_CODE (e) == INTEGER_CST
+             && !int_fits_type_p (e, ENUM_UNDERLYING_TYPE (type)))
+           warning_at (loc, OPT_Wconversion, 
+                       "the result of the conversion is unspecified because "
+                       "%qE is outside the range of type %qT",
+                       expr, type);
        }
       if (MAYBE_CLASS_TYPE_P (intype))
        {
@@ -695,19 +763,41 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
          rval = build_type_conversion (type, e);
          if (rval)
            return rval;
-         if (flags & LOOKUP_COMPLAIN)
-           error ("%q#T used where a %qT was expected", intype, type);
+         if (complain & tf_error)
+           error_at (loc, "%q#T used where a %qT was expected", intype, type);
          return error_mark_node;
        }
       if (code == BOOLEAN_TYPE)
-       return cp_truthvalue_conversion (e);
+       {
+         if (VOID_TYPE_P (intype))
+           {
+             if (complain & tf_error)
+               error_at (loc,
+                         "could not convert %qE from %<void%> to %<bool%>",
+                         expr);
+             return error_mark_node;
+           }
 
-      return fold_if_not_in_template (convert_to_integer (type, e));
+         /* We can't implicitly convert a scoped enum to bool, so convert
+            to the underlying type first.  */
+         if (SCOPED_ENUM_P (intype) && (convtype & CONV_STATIC))
+           e = build_nop (ENUM_UNDERLYING_TYPE (intype), e);
+         return cp_truthvalue_conversion (e);
+       }
+
+      converted = fold_if_not_in_template (convert_to_integer (type, e));
+
+      /* Ignore any integer overflow caused by the conversion.  */
+      return ignore_overflows (converted, e);
     }
   if (NULLPTR_TYPE_P (type) && e && null_ptr_cst_p (e))
-    return nullptr_node;
-  if (POINTER_TYPE_P (type) || TYPE_PTR_TO_MEMBER_P (type))
-    return fold_if_not_in_template (cp_convert_to_pointer (type, e));
+    {
+      if (complain & tf_warning)
+       maybe_warn_zero_as_null_pointer_constant (e, loc);
+      return nullptr_node;
+    }
+  if (POINTER_TYPE_P (type) || TYPE_PTRMEM_P (type))
+    return fold_if_not_in_template (cp_convert_to_pointer (type, e, complain));
   if (code == VECTOR_TYPE)
     {
       tree in_vtype = TREE_TYPE (e);
@@ -717,8 +807,9 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
          ret_val = build_type_conversion (type, e);
          if (ret_val)
            return ret_val;
-         if (flags & LOOKUP_COMPLAIN)
-           error ("%q#T used where a %qT was expected", in_vtype, type);
+         if (complain & tf_error)
+           error_at (loc, "%q#T used where a %qT was expected",
+                     in_vtype, type);
          return error_mark_node;
        }
       return fold_if_not_in_template (convert_to_vector (type, e));
@@ -731,10 +822,10 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
          rval = build_type_conversion (type, e);
          if (rval)
            return rval;
-         else
-           if (flags & LOOKUP_COMPLAIN)
-             error ("%q#T used where a floating point value was expected",
-                       TREE_TYPE (e));
+         else if (complain & tf_error)
+           error_at (loc,
+                     "%q#T used where a floating point value was expected",
+                     TREE_TYPE (e));
        }
       if (code == REAL_TYPE)
        return fold_if_not_in_template (convert_to_real (type, e));
@@ -761,40 +852,39 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
 
       ctor = e;
 
-      if (abstract_virtuals_error (NULL_TREE, type))
+      if (abstract_virtuals_error_sfinae (NULL_TREE, type, complain))
        return error_mark_node;
 
       if (BRACE_ENCLOSED_INITIALIZER_P (ctor))
-       ctor = perform_implicit_conversion (type, ctor, tf_warning_or_error);
+       ctor = perform_implicit_conversion (type, ctor, complain);
       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);
+       ctor = build_user_type_conversion (type, ctor, flags, complain);
       else
        {
-         VEC(tree,gc) *ctor_vec = make_tree_vector_single (ctor);
+         vec<tree, va_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);
+                                           type, flags, complain);
          release_tree_vector (ctor_vec);
        }
       if (ctor)
-       return build_cplus_new (type, ctor);
+       return build_cplus_new (type, ctor, complain);
     }
 
-  if (flags & LOOKUP_COMPLAIN)
+  if (complain & tf_error)
     {
       /* 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))
+      if (invalid_nonstatic_memfn_p (expr, complain))
        /* We displayed the error message.  */;
       else
-       error ("conversion from %qT to non-scalar type %qT requested",
-              TREE_TYPE (expr), type);
+       error_at (loc, "conversion from %qT to non-scalar type %qT requested",
+                 TREE_TYPE (expr), type);
     }
   return error_mark_node;
 }
@@ -821,6 +911,8 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
 tree
 convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
 {
+  location_t loc = EXPR_LOC_OR_HERE (expr);
+
   if (expr == error_mark_node
       || TREE_TYPE (expr) == error_mark_node)
     return error_mark_node;
@@ -835,7 +927,7 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
        exprv = TREE_OPERAND (exprv, 1);
       if (DECL_P (exprv)
          || handled_component_p (exprv)
-         || TREE_CODE (exprv) == INDIRECT_REF)
+         || INDIRECT_REF_P (exprv))
        /* Expr is not being 'used' here, otherwise we whould have
           called mark_{rl}value_use use here, which would have in turn
           called mark_exp_read.  Rather, we call mark_exp_read directly
@@ -851,7 +943,7 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
   if (TREE_CODE (expr) == PSEUDO_DTOR_EXPR)
     {
       if (complain & tf_error)
-        error ("pseudo-destructor is not called");
+        error_at (loc, "pseudo-destructor is not called");
       return error_mark_node;
     }
   if (VOID_TYPE_P (TREE_TYPE (expr)))
@@ -863,20 +955,24 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
        /* 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);
+       bool side_effects = ((op1 && TREE_SIDE_EFFECTS (op1))
+                            || TREE_SIDE_EFFECTS (op2));
        tree new_op1, new_op2;
+       new_op1 = NULL_TREE;
        if (implicit != ICV_CAST && !side_effects)
          {
-           new_op1 = convert_to_void (op1, ICV_SECOND_OF_COND, complain);
+           if (op1)
+             new_op1 = convert_to_void (op1, ICV_SECOND_OF_COND, complain);
            new_op2 = convert_to_void (op2, ICV_THIRD_OF_COND, complain);
          }
        else
          {
-           new_op1 = convert_to_void (op1, ICV_CAST, complain);
+           if (op1)
+             new_op1 = convert_to_void (op1, ICV_CAST, complain);
            new_op2 = convert_to_void (op2, ICV_CAST, complain);
          }
 
-       expr = build3 (COND_EXPR, TREE_TYPE (new_op1),
+       expr = build3 (COND_EXPR, TREE_TYPE (new_op2),
                       TREE_OPERAND (expr, 0), new_op1, new_op2);
        break;
       }
@@ -924,35 +1020,35 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
              switch (implicit)
                {
                  case ICV_CAST:
-                   warning (0, "conversion to void will not access "
+                   warning_at (loc, 0, "conversion to void will not access "
                                "object of incomplete type %qT", type);
                    break;
                  case ICV_SECOND_OF_COND:
-                   warning (0, "indirection will not access object of "
+                   warning_at (loc, 0, "indirection will not access object of "
                                "incomplete type %qT in second operand "
                                "of conditional expression", type);
                    break;
                  case ICV_THIRD_OF_COND:
-                   warning (0, "indirection will not access object of "
+                   warning_at (loc, 0, "indirection will not access object of "
                                "incomplete type %qT in third operand "
                                "of conditional expression", type);
                    break;
                  case ICV_RIGHT_OF_COMMA:
-                   warning (0, "indirection will not access object of "
+                   warning_at (loc, 0, "indirection will not access object of "
                                "incomplete type %qT in right operand of "
                                "comma operator", type);
                    break;
                  case ICV_LEFT_OF_COMMA:
-                   warning (0, "indirection will not access object of "
+                   warning_at (loc, 0, "indirection will not access object of "
                                "incomplete type %qT in left operand of "
                                "comma operator", type);
                    break;
                  case ICV_STATEMENT:
-                   warning (0, "indirection will not access object of "
+                   warning_at (loc, 0, "indirection will not access object of "
                                "incomplete type %qT in statement", type);
                     break;
                  case ICV_THIRD_IN_FOR:
-                   warning (0, "indirection will not access object of "
+                   warning_at (loc, 0, "indirection will not access object of "
                                "incomplete type %qT in for increment "
                                "expression", type);
                    break;
@@ -968,37 +1064,37 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
              switch (implicit)
                {
                  case ICV_CAST:
-                   warning (0, "conversion to void will not access "
+                   warning_at (loc, 0, "conversion to void will not access "
                                "object of type %qT", type);
                    break;
                  case ICV_SECOND_OF_COND:
-                   warning (0, "implicit dereference will not access object "
-                               "of type %qT in second operand of "
+                   warning_at (loc, 0, "implicit dereference will not access "
+                               "object of type %qT in second operand of "
                                "conditional expression", type);
                    break;
                  case ICV_THIRD_OF_COND:
-                   warning (0, "implicit dereference will not access object "
-                               "of type %qT in third operand of "
+                   warning_at (loc, 0, "implicit dereference will not access "
+                               "object of type %qT in third operand of "
                                "conditional expression", type);
                    break;
                  case ICV_RIGHT_OF_COMMA:
-                   warning (0, "implicit dereference will not access object "
-                               "of type %qT in right operand of "
+                   warning_at (loc, 0, "implicit dereference will not access "
+                               "object of type %qT in right operand of "
                                "comma operator", type);
                    break;
                  case ICV_LEFT_OF_COMMA:
-                   warning (0, "implicit dereference will not access object "
-                               "of type %qT in left operand of comma operator",
-                            type);
+                   warning_at (loc, 0, "implicit dereference will not access "
+                               "object of type %qT in left operand of comma "
+                               "operator", type);
                    break;
                  case ICV_STATEMENT:
-                   warning (0, "implicit dereference will not access object "
-                               "of type %qT in statement",  type);
+                   warning_at (loc, 0, "implicit dereference will not access "
+                               "object of type %qT in statement",  type);
                     break;
                  case ICV_THIRD_IN_FOR:
-                   warning (0, "implicit dereference will not access object "
-                               "of type %qT in for increment expression",
-                            type);
+                   warning_at (loc, 0, "implicit dereference will not access "
+                               "object of type %qT in for increment expression",
+                               type);
                    break;
                  default:
                    gcc_unreachable ();
@@ -1010,37 +1106,37 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
              switch (implicit)
                {
                  case ICV_CAST:
-                   warning (0, "conversion to void will not access "
+                   warning_at (loc, 0, "conversion to void will not access "
                                "object of non-trivially-copyable type %qT",
-                            type);
+                               type);
                    break;
                  case ICV_SECOND_OF_COND:
-                   warning (0, "indirection will not access object of "
+                   warning_at (loc, 0, "indirection will not access object of "
                                "non-trivially-copyable type %qT in second "
                                "operand of conditional expression", type);
                    break;
                  case ICV_THIRD_OF_COND:
-                   warning (0, "indirection will not access object of "
+                   warning_at (loc, 0, "indirection will not access object of "
                                "non-trivially-copyable type %qT in third "
                                "operand of conditional expression", type);
                    break;
                  case ICV_RIGHT_OF_COMMA:
-                   warning (0, "indirection will not access object of "
+                   warning_at (loc, 0, "indirection will not access object of "
                                "non-trivially-copyable type %qT in right "
                                "operand of comma operator", type);
                    break;
                  case ICV_LEFT_OF_COMMA:
-                   warning (0, "indirection will not access object of "
+                   warning_at (loc, 0, "indirection will not access object of "
                                "non-trivially-copyable type %qT in left "
                                "operand of comma operator", type);
                    break;
                  case ICV_STATEMENT:
-                   warning (0, "indirection will not access object of "
+                   warning_at (loc, 0, "indirection will not access object of "
                                "non-trivially-copyable type %qT in statement",
-                             type);
+                               type);
                     break;
                  case ICV_THIRD_IN_FOR:
-                   warning (0, "indirection will not access object of "
+                   warning_at (loc, 0, "indirection will not access object of "
                                "non-trivially-copyable type %qT in for "
                                "increment expression", type);
                    break;
@@ -1055,13 +1151,13 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
                - 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.)  */
+                 control it. (See also warn_if_unused_value() in c-common.c.)  */
             if (warn_unused_value
                && implicit != ICV_CAST
                 && (complain & tf_warning)
                 && !TREE_NO_WARNING (expr)
                 && !is_reference)
-              warning (OPT_Wunused_value, "value computed is not used");
+              warning_at (loc, OPT_Wunused_value, "value computed is not used");
             expr = TREE_OPERAND (expr, 0);
           }
 
@@ -1078,37 +1174,37 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
          switch (implicit)
            {
              case ICV_CAST:
-               warning (0, "conversion to void will not access "
+               warning_at (loc, 0, "conversion to void will not access "
                            "object %qE of incomplete type %qT", expr, type);
                break;
              case ICV_SECOND_OF_COND:
-               warning (0, "variable %qE of incomplete type %qT will not "
-                           "be accessed in second operand of "
+               warning_at (loc, 0, "variable %qE of incomplete type %qT will "
+                           "not be accessed in second operand of "
                            "conditional expression", expr, type);
                break;
              case ICV_THIRD_OF_COND:
-               warning (0, "variable %qE of incomplete type %qT will not "
-                           "be accessed in third operand of "
+               warning_at (loc, 0, "variable %qE of incomplete type %qT will "
+                           "not be accessed in third operand of "
                            "conditional expression", expr, type);
                break;
              case ICV_RIGHT_OF_COMMA:
-               warning (0, "variable %qE of incomplete type %qT will not "
-                           "be accessed in right operand of comma operator",
-                        expr, type);
+               warning_at (loc, 0, "variable %qE of incomplete type %qT will "
+                           "not be accessed in right operand of comma operator",
+                           expr, type);
                break;
              case ICV_LEFT_OF_COMMA:
-               warning (0, "variable %qE of incomplete type %qT will not "
-                           "be accessed in left operand of comma operator",
-                        expr, type);
+               warning_at (loc, 0, "variable %qE of incomplete type %qT will "
+                           "not be accessed in left operand of comma operator",
+                           expr, type);
                break;
              case ICV_STATEMENT:
-               warning (0, "variable %qE of incomplete type %qT will not "
-                           "be accessed in statement", expr, type);
+               warning_at (loc, 0, "variable %qE of incomplete type %qT will "
+                           "not be accessed in statement", expr, type);
                break;
              case ICV_THIRD_IN_FOR:
-               warning (0, "variable %qE of incomplete type %qT will not "
-                           "be accessed in for increment expression",
-                        expr, type);
+               warning_at (loc, 0, "variable %qE of incomplete type %qT will "
+                           "not be accessed in for increment expression",
+                           expr, type);
                break;
              default:
                gcc_unreachable ();
@@ -1155,32 +1251,32 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
          switch (implicit)
            {
              case ICV_CAST:
-               error ("conversion to void "
-                      "cannot resolve address of overloaded function");
+               error_at (loc, "conversion to void "
+                         "cannot resolve address of overloaded function");
                break;
              case ICV_SECOND_OF_COND:
-               error ("second operand of conditional expression "
-                      "cannot resolve address of overloaded function");
+               error_at (loc, "second operand of conditional expression "
+                         "cannot resolve address of overloaded function");
                break;
              case ICV_THIRD_OF_COND:
-               error ("third operand of conditional expression "
-                      "cannot resolve address of overloaded function");
+               error_at (loc, "third operand of conditional expression "
+                         "cannot resolve address of overloaded function");
                break;
              case ICV_RIGHT_OF_COMMA:
-               error ("right operand of comma operator "
-                      "cannot resolve address of overloaded function");
+               error_at (loc, "right operand of comma operator "
+                         "cannot resolve address of overloaded function");
                break;
              case ICV_LEFT_OF_COMMA:
-               error ("left operand of comma operator "
-                      "cannot resolve address of overloaded function");
+               error_at (loc, "left operand of comma operator "
+                         "cannot resolve address of overloaded function");
                break;
              case ICV_STATEMENT:
-               error ("statement "
-                      "cannot resolve address of overloaded function");
+               error_at (loc, "statement "
+                         "cannot resolve address of overloaded function");
                break;
              case ICV_THIRD_IN_FOR:
-               error ("for increment expression "
-                      "cannot resolve address of overloaded function");
+               error_at (loc, "for increment expression "
+                         "cannot resolve address of overloaded function");
                break;
            }
        else
@@ -1194,34 +1290,34 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
          switch (implicit)
            {
              case ICV_SECOND_OF_COND:
-               warning (OPT_Waddress,
-                        "second operand of conditional expression "
-                        "is a reference, not call, to function %qE", expr);
+               warning_at (loc, OPT_Waddress,
+                           "second operand of conditional expression "
+                           "is a reference, not call, to function %qE", expr);
                break;
              case ICV_THIRD_OF_COND:
-               warning (OPT_Waddress,
-                        "third operand of conditional expression "
-                        "is a reference, not call, to function %qE", expr);
+               warning_at (loc, OPT_Waddress,
+                           "third operand of conditional expression "
+                           "is a reference, not call, to function %qE", expr);
                break;
              case ICV_RIGHT_OF_COMMA:
-               warning (OPT_Waddress,
-                        "right operand of comma operator "
-                        "is a reference, not call, to function %qE", expr);
+               warning_at (loc, OPT_Waddress,
+                           "right operand of comma operator "
+                           "is a reference, not call, to function %qE", expr);
                break;
              case ICV_LEFT_OF_COMMA:
-               warning (OPT_Waddress,
-                        "left operand of comma operator "
-                        "is a reference, not call, to function %qE", expr);
+               warning_at (loc, OPT_Waddress,
+                           "left operand of comma operator "
+                           "is a reference, not call, to function %qE", expr);
                break;
              case ICV_STATEMENT:
-               warning (OPT_Waddress,
-                        "statement is a reference, not call, to function %qE",
-                        expr);
+               warning_at (loc, OPT_Waddress,
+                           "statement is a reference, not call, to function %qE",
+                           expr);
                break;
              case ICV_THIRD_IN_FOR:
-               warning (OPT_Waddress,
-                        "for increment expression "
-                        "is a reference, not call, to function %qE", expr);
+               warning_at (loc, OPT_Waddress,
+                           "for increment expression "
+                           "is a reference, not call, to function %qE", expr);
                break;
              default:
                gcc_unreachable ();
@@ -1246,28 +1342,30 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
              switch (implicit)
                {
                  case ICV_SECOND_OF_COND:
-                   warning (OPT_Wunused_value,
-                            "second operand of conditional expression has no effect");
+                   warning_at (loc, OPT_Wunused_value,
+                               "second operand of conditional expression "
+                               "has no effect");
                    break;
                  case ICV_THIRD_OF_COND:
-                   warning (OPT_Wunused_value,
-                            "third operand of conditional expression has no effect");
+                   warning_at (loc, OPT_Wunused_value,
+                               "third operand of conditional expression "
+                               "has no effect");
                    break;
                  case ICV_RIGHT_OF_COMMA:
-                   warning (OPT_Wunused_value,
-                            "right operand of comma operator has no effect");
+                   warning_at (loc, OPT_Wunused_value,
+                               "right operand of comma operator has no effect");
                    break;
                  case ICV_LEFT_OF_COMMA:
-                   warning (OPT_Wunused_value,
-                            "left operand of comma operator has no effect");
+                   warning_at (loc, OPT_Wunused_value,
+                               "left operand of comma operator has no effect");
                    break;
                  case ICV_STATEMENT:
-                   warning (OPT_Wunused_value,
-                            "statement has no effect");
+                   warning_at (loc, OPT_Wunused_value,
+                               "statement has no effect");
                    break;
                  case ICV_THIRD_IN_FOR:
-                   warning (OPT_Wunused_value,
-                            "for increment expression has no effect");
+                   warning_at (loc, OPT_Wunused_value,
+                               "for increment expression has no effect");
                    break;
                  default:
                    gcc_unreachable ();
@@ -1305,7 +1403,7 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
                            || code == POSTDECREMENT_EXPR
                            || code == POSTINCREMENT_EXPR)))
                   && (complain & tf_warning))
-               warning (OPT_Wunused_value, "value computed is not used");
+               warning_at (loc, OPT_Wunused_value, "value computed is not used");
            }
        }
       expr = build1 (CONVERT_EXPR, void_type_node, expr);
@@ -1346,7 +1444,8 @@ convert (tree type, tree expr)
     return fold_if_not_in_template (build_nop (type, expr));
 
   return ocp_convert (type, expr, CONV_OLD_CONVERT,
-                     LOOKUP_NORMAL|LOOKUP_NO_CONVERSION);
+                     LOOKUP_NORMAL|LOOKUP_NO_CONVERSION,
+                     tf_warning_or_error);
 }
 
 /* Like cp_convert, except permit conversions to take place which
@@ -1354,31 +1453,31 @@ convert (tree type, tree expr)
    (such as conversion from sub-type to private super-type).  */
 
 tree
-convert_force (tree type, tree expr, int convtype)
+convert_force (tree type, tree expr, int convtype, tsubst_flags_t complain)
 {
   tree e = expr;
   enum tree_code code = TREE_CODE (type);
 
   if (code == REFERENCE_TYPE)
     return (fold_if_not_in_template
-           (convert_to_reference (type, e, CONV_C_CAST, LOOKUP_COMPLAIN,
-                                  NULL_TREE)));
+           (convert_to_reference (type, e, CONV_C_CAST, 0,
+                                  NULL_TREE, complain)));
 
   if (code == POINTER_TYPE)
-    return fold_if_not_in_template (convert_to_pointer_force (type, e));
+    return fold_if_not_in_template (convert_to_pointer_force (type, e,
+                                                             complain));
 
   /* From typeck.c convert_for_assignment */
-  if (((TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE && TREE_CODE (e) == ADDR_EXPR
-       && TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
+  if (((TYPE_PTR_P (TREE_TYPE (e)) && TREE_CODE (e) == ADDR_EXPR
        && TREE_CODE (TREE_TYPE (TREE_TYPE (e))) == METHOD_TYPE)
        || integer_zerop (e)
        || TYPE_PTRMEMFUNC_P (TREE_TYPE (e)))
       && TYPE_PTRMEMFUNC_P (type))
     /* compatible pointer to member functions.  */
     return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), e, 1,
-                            /*c_cast_p=*/1, tf_warning_or_error);
+                            /*c_cast_p=*/1, complain);
 
-  return ocp_convert (type, e, CONV_C_CAST|convtype, LOOKUP_NORMAL);
+  return ocp_convert (type, e, CONV_C_CAST|convtype, LOOKUP_NORMAL, complain);
 }
 
 /* Convert an aggregate EXPR to type XTYPE.  If a conversion
@@ -1397,7 +1496,8 @@ build_type_conversion (tree xtype, tree expr)
 {
   /* C++: check to see if we can convert this aggregate type
      into the required type.  */
-  return build_user_type_conversion (xtype, expr, LOOKUP_NORMAL);
+  return build_user_type_conversion (xtype, expr, LOOKUP_NORMAL,
+                                    tf_warning_or_error);
 }
 
 /* Convert the given EXPR to one of a group of types suitable for use in an
@@ -1415,10 +1515,13 @@ build_expr_type_conversion (int desires, tree expr, bool complain)
   if (expr == null_node
       && (desires & WANT_INT)
       && !(desires & WANT_NULL))
-    warning_at (input_location, OPT_Wconversion_null,
-               "converting NULL to non-pointer type");
+    {
+      source_location loc =
+       expansion_point_location_if_in_system_header (input_location);
 
-  basetype = TREE_TYPE (expr);
+      warning_at (loc, OPT_Wconversion_null,
+                 "converting NULL to non-pointer type");
+    }
 
   if (basetype == error_mark_node)
     return error_mark_node;
@@ -1442,7 +1545,8 @@ build_expr_type_conversion (int desires, tree expr, bool complain)
 
       case FUNCTION_TYPE:
       case ARRAY_TYPE:
-       return (desires & WANT_POINTER) ? decay_conversion (expr)
+       return (desires & WANT_POINTER) ? decay_conversion (expr,
+                                                           tf_warning_or_error)
                                        : NULL_TREE;
 
       case COMPLEX_TYPE:
@@ -1468,14 +1572,12 @@ build_expr_type_conversion (int desires, tree expr, bool complain)
 
   /* The code for conversions from class type is currently only used for
      delete expressions.  Other expressions are handled by build_new_op.  */
-  if (!complete_type_or_else (basetype, expr))
+  if (!complete_type_or_maybe_complain (basetype, expr, complain))
     return error_mark_node;
   if (!TYPE_HAS_CONVERSION (basetype))
     return NULL_TREE;
 
-  for (conv = lookup_conversions (basetype, /*lookup_template_convs_p=*/true);
-       conv;
-       conv = TREE_CHAIN (conv))
+  for (conv = lookup_conversions (basetype); conv; conv = TREE_CHAIN (conv))
     {
       int win = 0;
       tree candidate;
@@ -1521,31 +1623,51 @@ build_expr_type_conversion (int desires, tree expr, bool complain)
          break;
 
        default:
+         /* A wildcard could be instantiated to match any desired
+            type, but we can't deduce the template argument.  */
+         if (WILDCARD_TYPE_P (candidate))
+           win = true;
          break;
        }
 
       if (win)
        {
-         if (winner)
+         if (TREE_CODE (cand) == TEMPLATE_DECL)
            {
              if (complain)
+               error ("default type conversion can't deduce template"
+                      " argument for %qD", cand);
+             return error_mark_node;
+           }
+
+         if (winner)
+           {
+             tree winner_type
+               = non_reference (TREE_TYPE (TREE_TYPE (winner)));
+
+             if (!same_type_ignoring_top_level_qualifiers_p (winner_type,
+                                                             candidate))
                {
-                 error ("ambiguous default type conversion from %qT",
-                        basetype);
-                 error ("  candidate conversions include %qD and %qD",
-                        winner, cand);
+                 if (complain)
+                   {
+                     error ("ambiguous default type conversion from %qT",
+                            basetype);
+                     error ("  candidate conversions include %qD and %qD",
+                            winner, cand);
+                   }
+                 return error_mark_node;
                }
-             return error_mark_node;
            }
-         else
-           winner = cand;
+
+         winner = cand;
        }
     }
 
   if (winner)
     {
       tree type = non_reference (TREE_TYPE (TREE_TYPE (winner)));
-      return build_user_type_conversion (type, expr, LOOKUP_NORMAL);
+      return build_user_type_conversion (type, expr, LOOKUP_NORMAL,
+                                        tf_warning_or_error);
     }
 
   return NULL_TREE;
@@ -1573,6 +1695,11 @@ type_promotes_to (tree type)
   if (TREE_CODE (type) == BOOLEAN_TYPE)
     type = integer_type_node;
 
+  /* Scoped enums don't promote, but pretend they do for backward ABI bug
+     compatibility wrt varargs.  */
+  else if (SCOPED_ENUM_P (type) && abi_version_at_least (6))
+    ;
+
   /* Normally convert enums to int, but convert wide enums to something
      wider.  */
   else if (TREE_CODE (type) == ENUMERAL_TYPE
@@ -1583,6 +1710,9 @@ type_promotes_to (tree type)
       int precision = MAX (TYPE_PRECISION (type),
                           TYPE_PRECISION (integer_type_node));
       tree totype = c_common_type_for_size (precision, 0);
+      if (SCOPED_ENUM_P (type))
+       warning (OPT_Wabi, "scoped enum %qT will not promote to an integral "
+                "type in a future version of GCC", type);
       if (TREE_CODE (type) == ENUMERAL_TYPE)
        type = ENUM_UNDERLYING_TYPE (type);
       if (TYPE_UNSIGNED (type)
@@ -1627,8 +1757,7 @@ perform_qualification_conversions (tree type, tree expr)
   else if (TYPE_PTR_P (type) && TYPE_PTR_P (expr_type)
           && comp_ptr_ttypes (TREE_TYPE (type), TREE_TYPE (expr_type)))
     return build_nop (type, expr);
-  else if (TYPE_PTR_TO_MEMBER_P (type)
-          && TYPE_PTR_TO_MEMBER_P (expr_type)
+  else if (TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (expr_type)
           && same_type_p (TYPE_PTRMEM_CLASS_TYPE (type),
                           TYPE_PTRMEM_CLASS_TYPE (expr_type))
           && comp_ptr_ttypes (TYPE_PTRMEM_POINTED_TO_TYPE (type),