OSDN Git Service

PR c++/47132
[pf3gnuchains/gcc-fork.git] / gcc / c-convert.c
index 4fb6800..f4583c5 100644 (file)
@@ -1,6 +1,6 @@
 /* Language-level data type conversion for GNU C.
    Copyright (C) 1987, 1988, 1991, 1998, 2002, 2003, 2004, 2005, 2007, 2008,
-   2009 Free Software Foundation, Inc.
+   2009, 2010 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -31,10 +31,9 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree.h"
 #include "flags.h"
 #include "convert.h"
-#include "c-common.h"
+#include "c-family/c-common.h"
 #include "c-tree.h"
 #include "langhooks.h"
-#include "toplev.h"
 #include "target.h"
 
 /* Change of width--truncation and extension of integers or reals--
@@ -71,6 +70,7 @@ convert (tree type, tree expr)
   enum tree_code code = TREE_CODE (type);
   const char *invalid_conv_diag;
   tree ret;
+  location_t loc = EXPR_LOCATION (expr);
 
   if (type == error_mark_node
       || expr == error_mark_node
@@ -86,11 +86,14 @@ convert (tree type, tree expr)
 
   if (type == TREE_TYPE (expr))
     return expr;
+  ret = targetm.convert_to_type (type, expr);
+  if (ret)
+      return ret;
 
   STRIP_TYPE_NOPS (e);
 
   if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (expr)))
-    return fold_convert (type, expr);
+    return fold_convert_loc (loc, type, expr);
   if (TREE_CODE (TREE_TYPE (expr)) == ERROR_MARK)
     return error_mark_node;
   if (TREE_CODE (TREE_TYPE (expr)) == VOID_TYPE)
@@ -102,7 +105,7 @@ convert (tree type, tree expr)
   switch (code)
     {
     case VOID_TYPE:
-      return fold_convert (type, e);
+      return fold_convert_loc (loc, type, e);
 
     case INTEGER_TYPE:
     case ENUMERAL_TYPE:
@@ -110,8 +113,8 @@ convert (tree type, tree expr)
       goto maybe_fold;
 
     case BOOLEAN_TYPE:
-      return fold_convert 
-       (type, c_objc_common_truthvalue_conversion (input_location, expr));
+      return fold_convert_loc
+       (loc, type, c_objc_common_truthvalue_conversion (input_location, expr));
 
     case POINTER_TYPE:
     case REFERENCE_TYPE:
@@ -127,6 +130,32 @@ convert (tree type, tree expr)
       goto maybe_fold;
 
     case COMPLEX_TYPE:
+      /* If converting from COMPLEX_TYPE to a different COMPLEX_TYPE
+        and e is not COMPLEX_EXPR, convert_to_complex uses save_expr,
+        but for the C FE c_save_expr needs to be called instead.  */
+      if (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE)
+       {
+         tree subtype = TREE_TYPE (type);
+         tree elt_type = TREE_TYPE (TREE_TYPE (e));
+
+         if (TYPE_MAIN_VARIANT (elt_type) != TYPE_MAIN_VARIANT (subtype)
+             && TREE_CODE (e) != COMPLEX_EXPR)
+           {
+             if (in_late_binary_op)
+               e = save_expr (e);
+             else
+               e = c_save_expr (e);
+             ret
+               = fold_build2 (COMPLEX_EXPR, type,
+                              convert (subtype,
+                                       fold_build1 (REALPART_EXPR,
+                                                    elt_type, e)),
+                              convert (subtype,
+                                       fold_build1 (IMAGPART_EXPR,
+                                                    elt_type, e)));
+             goto maybe_fold;
+           }
+       }
       ret = convert_to_complex (type, e);
       goto maybe_fold;