OSDN Git Service

* config/i386/i386.md (splitters for int-float conversion): Use
[pf3gnuchains/gcc-fork.git] / gcc / cp / cvt.c
index c6335a2..3e618d3 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"
 
@@ -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);
            }
@@ -276,7 +276,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.  */
@@ -342,7 +343,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
@@ -513,6 +515,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 +523,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 +533,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);
 
@@ -727,7 +735,13 @@ 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));
 
@@ -813,7 +827,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)
@@ -893,20 +907,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;
       }
@@ -1601,6 +1619,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
@@ -1611,6 +1634,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)