OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / cp / cvt.c
index 4fcba45..fddba51 100644 (file)
@@ -1,7 +1,7 @@
 /* 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.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+   2011 Free Software Foundation, Inc.
    Hacked by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GCC.
@@ -35,7 +35,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "cp-tree.h"
 #include "intl.h"
 #include "convert.h"
-#include "toplev.h"
 #include "decl.h"
 #include "target.h"
 
@@ -88,7 +87,7 @@ 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",
+         error ("can%'t convert from incomplete type %qT to %qT",
                 intype, type);
          return error_mark_node;
        }
@@ -158,7 +157,8 @@ 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,
+                                       tf_warning_or_error);
              /* Add any qualifier conversions.  */
              return build_nop (type, expr);
            }
@@ -176,7 +176,7 @@ cp_convert_to_pointer (tree type, tree expr)
   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);
+                          /*c_cast_p=*/false, tf_warning_or_error);
   else if (TYPE_PTRMEMFUNC_P (intype))
     {
       if (!warn_pmf2ptr)
@@ -198,20 +198,25 @@ cp_convert_to_pointer (tree type, tree expr)
 
   if (null_ptr_cst_p (expr))
     {
+      tree val;
+
+      if (c_inhibit_evaluation_warnings == 0
+         && !NULLPTR_TYPE_P (TREE_TYPE (expr)))
+       warning (OPT_Wzero_as_null_pointer_constant,
+                "zero as null pointer constant");
+
       if (TYPE_PTRMEMFUNC_P (type))
        return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0,
-                                /*c_cast_p=*/false);
+                                /*c_cast_p=*/false, tf_warning_or_error);
 
-      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);
+      /* A NULL pointer-to-data-member is represented by -1, not by
+        zero.  */
+      val = (TYPE_PTRMEM_P (type)
+            ? build_int_cst_type (type, -1)
+            : build_int_cst (type, 0));
 
-      return expr;
+      return (TREE_SIDE_EFFECTS (expr)
+             ? build2 (COMPOUND_EXPR, type, expr, val) : val);
     }
   else if (TYPE_PTR_TO_MEMBER_P (type) && INTEGRAL_CODE_P (form))
     {
@@ -276,7 +281,8 @@ convert_to_pointer_force (tree type, tree expr)
            return error_mark_node;
          if (binfo)
            {
-             expr = build_base_path (code, expr, binfo, 0);
+             expr = build_base_path (code, expr, binfo, 0,
+                                     tf_warning_or_error);
              if (expr == error_mark_node)
                 return error_mark_node;
              /* Add any qualifier conversions.  */
@@ -314,7 +320,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;
@@ -327,7 +333,7 @@ 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 = cp_build_unary_op (ADDR_EXPR, arg, 1, tf_warning_or_error);
+  rval = cp_build_addr_expr (arg, tf_warning_or_error);
   if (rval == error_mark_node)
     return error_mark_node;
 
@@ -342,7 +348,8 @@ build_up_reference (tree type, tree arg, int flags, tree decl)
        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,
+                             tf_warning_or_error);
     }
   else
     rval
@@ -471,7 +478,7 @@ convert_to_reference (tree reftype, tree expr, int convtype,
        warning (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, tf_warning_or_error);
       if (rval != error_mark_node)
        rval = convert_force (build_pointer_type (TREE_TYPE (reftype)),
                              rval, 0);
@@ -513,6 +520,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 +528,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,11 +538,17 @@ 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,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);
 
@@ -543,12 +556,35 @@ force_rvalue (tree 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 = build_int_cst_wide (TREE_TYPE (expr),
+                                TREE_INT_CST_LOW (expr),
+                                TREE_INT_CST_HIGH (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.  */
@@ -609,7 +645,10 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
       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;
 
@@ -658,6 +697,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
   if (INTEGRAL_CODE_P (code))
     {
       tree intype = TREE_TYPE (e);
+      tree converted;
 
       if (TREE_CODE (type) == ENUMERAL_TYPE)
        {
@@ -700,9 +740,18 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
          return error_mark_node;
        }
       if (code == BOOLEAN_TYPE)
-       return cp_truthvalue_conversion (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));
 
-      return 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;
@@ -783,7 +832,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
          release_tree_vector (ctor_vec);
        }
       if (ctor)
-       return build_cplus_new (type, ctor);
+       return build_cplus_new (type, ctor, tf_warning_or_error);
     }
 
   if (flags & LOOKUP_COMPLAIN)
@@ -863,20 +912,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;
       }
@@ -1376,7 +1429,7 @@ convert_force (tree type, tree expr, int convtype)
       && TYPE_PTRMEMFUNC_P (type))
     /* compatible pointer to member functions.  */
     return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), e, 1,
-                            /*c_cast_p=*/1);
+                            /*c_cast_p=*/1, tf_warning_or_error);
 
   return ocp_convert (type, e, CONV_C_CAST|convtype, LOOKUP_NORMAL);
 }
@@ -1468,14 +1521,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,11 +1572,23 @@ 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 (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)
            {
              if (complain)
@@ -1573,6 +1636,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 +1651,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)