]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/cp/cvt.c
Merge from trunk.
[thirdparty/gcc.git] / gcc / cp / cvt.c
index 348e6082ceb452a7b9869db0c9b78f6b485013bd..6d0e34156ffced97be1d7f67758f451a0e7a8365 100644 (file)
@@ -29,18 +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 "decl.h"
 #include "target.h"
+#include "wide-int.h"
 
 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, tsubst_flags_t);
-static void warn_ref_binding (location_t, tree, tree, tree);
+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
@@ -105,14 +107,14 @@ cp_convert_to_pointer (tree type, tree expr, tsubst_flags_t complain)
     }
 
   /* 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, complain);
-      if (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE)
+      if (TYPE_PTR_P (TREE_TYPE (expr)))
        return build_nop (type, expr);
       intype = TREE_TYPE (expr);
     }
@@ -127,7 +129,7 @@ cp_convert_to_pointer (tree type, tree expr, tsubst_flags_t complain)
       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))
@@ -203,13 +205,13 @@ cp_convert_to_pointer (tree type, tree expr, tsubst_flags_t complain)
 
   if (null_ptr_cst_p (expr))
     {
-      if (complain & tf_warning)
-       maybe_warn_zero_as_null_pointer_constant (expr, loc);
-
       if (TYPE_PTRMEMFUNC_P (type))
        return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0,
                                 /*c_cast_p=*/false, complain);
 
+      if (complain & tf_warning)
+       maybe_warn_zero_as_null_pointer_constant (expr, loc);
+
       /* A NULL pointer-to-data-member is represented by -1, not by
         zero.  */
       tree val = (TYPE_PTRDATAMEM_P (type)
@@ -371,7 +373,7 @@ build_up_reference (tree type, tree arg, int flags, tree decl,
    non-volatile const type.  */
 
 static void
-warn_ref_binding (location_t loc, tree reftype, tree intype, tree decl)
+diagnose_ref_binding (location_t loc, tree reftype, tree intype, tree decl)
 {
   tree ttl = TREE_TYPE (reftype);
 
@@ -428,7 +430,7 @@ convert_to_reference (tree reftype, tree expr, int convtype,
 
   intype = TYPE_MAIN_VARIANT (intype);
 
-  can_convert_intype_to_type = can_convert (type, intype, complain);
+  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)
@@ -449,16 +451,17 @@ convert_to_reference (tree reftype, tree expr, int convtype,
        }
     }
 
-  if (((convtype & CONV_STATIC) && can_convert (intype, type, complain))
+  if (((convtype & CONV_STATIC)
+       && can_convert_standard (intype, type, complain))
       || ((convtype & CONV_IMPLICIT) && can_convert_intype_to_type))
     {
       {
        tree ttl = TREE_TYPE (reftype);
        tree ttr = lvalue_type (expr);
 
-       if ((complain & tf_warning)
+       if ((complain & tf_error)
            && ! real_lvalue_p (expr))
-         warn_ref_binding (loc, reftype, intype, decl);
+         diagnose_ref_binding (loc, reftype, intype, decl);
 
        if (! (convtype & CONV_CONST)
            && !at_least_as_qualified_p (ttl, ttr))
@@ -483,7 +486,7 @@ 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 ((complain & tf_warning)
-         && TREE_CODE (intype) == POINTER_TYPE
+         && TYPE_PTR_P (intype)
          && (comptypes (TREE_TYPE (intype), type,
                         COMPARE_BASE | COMPARE_DERIVED)))
        warning_at (loc, 0, "casting %qT to %qT does not dereference pointer",
@@ -502,8 +505,8 @@ convert_to_reference (tree reftype, tree expr, int convtype,
                                         ICR_CONVERTING, 0, 0, complain);
       if (rval == NULL_TREE || rval == error_mark_node)
        return rval;
-      if (complain & tf_warning)
-       warn_ref_binding (loc, reftype, intype, decl);
+      if (complain & tf_error)
+       diagnose_ref_binding (loc, reftype, intype, decl);
       rval = build_up_reference (reftype, rval, flags, decl, complain);
     }
 
@@ -580,9 +583,7 @@ ignore_overflows (tree expr, tree orig)
     {
       gcc_assert (!TREE_OVERFLOW (orig));
       /* Ensure constant sharing.  */
-      expr = build_int_cst_wide (TREE_TYPE (expr),
-                                TREE_INT_CST_LOW (expr),
-                                TREE_INT_CST_HIGH (expr));
+      expr = wide_int_to_tree (TREE_TYPE (expr), expr);
     }
   return expr;
 }
@@ -624,10 +625,20 @@ cp_convert_and_check (tree type, tree expr, tsubst_flags_t complain)
   result = cp_convert (type, expr, complain);
 
   if ((complain & tf_warning)
-      && c_inhibit_evaluation_warnings == 0
-      && !TREE_OVERFLOW_P (expr)
-      && result != error_mark_node)
-    warnings_for_convert_and_check (type, expr, result);
+      && 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;
 }
@@ -723,7 +734,7 @@ 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 (complain & tf_error)
                permerror (loc, "conversion from %q#T to %q#T", intype, type);
@@ -758,7 +769,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
        }
       if (code == BOOLEAN_TYPE)
        {
-         if (TREE_CODE (intype) == VOID_TYPE)
+         if (VOID_TYPE_P (intype))
            {
              if (complain & tf_error)
                error_at (loc,
@@ -916,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
@@ -1457,8 +1468,7 @@ convert_force (tree type, tree expr, int convtype, tsubst_flags_t complain)
                                                              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)))
@@ -1580,17 +1590,6 @@ build_expr_type_conversion (int desires, tree expr, bool complain)
       if (DECL_NONCONVERTING_P (cand))
        continue;
 
-      if (TREE_CODE (cand) == TEMPLATE_DECL)
-       {
-         if (complain)
-           {
-             error ("ambiguous default type conversion from %qT",
-                    basetype);
-             error ("  candidate conversions include %qD", cand);
-           }
-         return error_mark_node;
-       }
-
       candidate = non_reference (TREE_TYPE (TREE_TYPE (cand)));
 
       switch (TREE_CODE (candidate))
@@ -1624,24 +1623,43 @@ 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;
        }
     }