/* Utility routines for data type conversion for GCC.
- Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1997, 1998,
- 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
- Free Software Foundation, Inc.
+ Copyright (C) 1987-2015 Free Software Foundation, Inc.
This file is part of GCC.
#include "system.h"
#include "coretypes.h"
#include "tm.h"
+#include "alias.h"
+#include "symtab.h"
#include "tree.h"
+#include "fold-const.h"
+#include "stor-layout.h"
#include "flags.h"
#include "convert.h"
-#include "toplev.h"
+#include "diagnostic-core.h"
+#include "target.h"
#include "langhooks.h"
-#include "real.h"
-#include "fixed-value.h"
+#include "builtins.h"
+#include "ubsan.h"
/* Convert EXPR to some pointer or reference type TYPE.
EXPR must be pointer, reference, integer, enumeral, or literal zero;
if (TREE_TYPE (expr) == type)
return expr;
- /* Propagate overflow to the NULL pointer. */
- if (integer_zerop (expr))
- return force_fit_type_double (type, 0, 0, 0, TREE_OVERFLOW (expr));
-
switch (TREE_CODE (TREE_TYPE (expr)))
{
case POINTER_TYPE:
}
}
-/* Avoid any floating point extensions from EXP. */
-tree
-strip_float_extensions (tree exp)
-{
- tree sub, expt, subt;
-
- /* For floating point constant look up the narrowest type that can hold
- it properly and handle it like (type)(narrowest_type)constant.
- This way we can optimize for instance a=a*2.0 where "a" is float
- but 2.0 is double constant. */
- if (TREE_CODE (exp) == REAL_CST && !DECIMAL_FLOAT_TYPE_P (TREE_TYPE (exp)))
- {
- REAL_VALUE_TYPE orig;
- tree type = NULL;
-
- orig = TREE_REAL_CST (exp);
- if (TYPE_PRECISION (TREE_TYPE (exp)) > TYPE_PRECISION (float_type_node)
- && exact_real_truncate (TYPE_MODE (float_type_node), &orig))
- type = float_type_node;
- else if (TYPE_PRECISION (TREE_TYPE (exp))
- > TYPE_PRECISION (double_type_node)
- && exact_real_truncate (TYPE_MODE (double_type_node), &orig))
- type = double_type_node;
- if (type)
- return build_real (type, real_value_truncate (TYPE_MODE (type), orig));
- }
-
- if (!CONVERT_EXPR_P (exp))
- return exp;
-
- sub = TREE_OPERAND (exp, 0);
- subt = TREE_TYPE (sub);
- expt = TREE_TYPE (exp);
-
- if (!FLOAT_TYPE_P (subt))
- return exp;
-
- if (DECIMAL_FLOAT_TYPE_P (expt) != DECIMAL_FLOAT_TYPE_P (subt))
- return exp;
-
- if (TYPE_PRECISION (subt) > TYPE_PRECISION (expt))
- return exp;
-
- return strip_float_extensions (sub);
-}
-
/* Convert EXPR to some floating-point type TYPE.
enum built_in_function fcode = builtin_mathfn_code (expr);
tree itype = TREE_TYPE (expr);
+ if (TREE_CODE (expr) == COMPOUND_EXPR)
+ {
+ tree t = convert_to_real (type, TREE_OPERAND (expr, 1));
+ if (t == TREE_OPERAND (expr, 1))
+ return expr;
+ return build2_loc (EXPR_LOCATION (expr), COMPOUND_EXPR, TREE_TYPE (t),
+ TREE_OPERAND (expr, 0), t);
+ }
+
/* Disable until we figure out how to decide whether the functions are
present in runtime. */
/* Convert (float)sqrt((double)x) where x is float into sqrtf(x) */
CASE_MATHFN (COS)
CASE_MATHFN (ERF)
CASE_MATHFN (ERFC)
- CASE_MATHFN (FABS)
CASE_MATHFN (LOG)
CASE_MATHFN (LOG10)
CASE_MATHFN (LOG2)
CASE_MATHFN (LOG1P)
- CASE_MATHFN (LOGB)
CASE_MATHFN (SIN)
- CASE_MATHFN (SQRT)
CASE_MATHFN (TAN)
CASE_MATHFN (TANH)
+ /* The above functions are not safe to do this conversion. */
+ if (!flag_unsafe_math_optimizations)
+ break;
+ CASE_MATHFN (SQRT)
+ CASE_MATHFN (FABS)
+ CASE_MATHFN (LOGB)
#undef CASE_MATHFN
{
tree arg0 = strip_float_extensions (CALL_EXPR_ARG (expr, 0));
if (TYPE_PRECISION (TREE_TYPE (arg0)) > TYPE_PRECISION (type))
newtype = TREE_TYPE (arg0);
+ /* We consider to convert
+
+ (T1) sqrtT2 ((T2) exprT3)
+ to
+ (T1) sqrtT4 ((T4) exprT3)
+
+ , where T1 is TYPE, T2 is ITYPE, T3 is TREE_TYPE (ARG0),
+ and T4 is NEWTYPE. All those types are of floating point types.
+ T4 (NEWTYPE) should be narrower than T2 (ITYPE). This conversion
+ is safe only if P1 >= P2*2+2, where P1 and P2 are precisions of
+ T2 and T4. See the following URL for a reference:
+ http://stackoverflow.com/questions/9235456/determining-
+ floating-point-square-root
+ */
+ if ((fcode == BUILT_IN_SQRT || fcode == BUILT_IN_SQRTL)
+ && !flag_unsafe_math_optimizations)
+ {
+ /* The following conversion is unsafe even the precision condition
+ below is satisfied:
+
+ (float) sqrtl ((long double) double_val) -> (float) sqrt (double_val)
+ */
+ if (TYPE_MODE (type) != TYPE_MODE (newtype))
+ break;
+
+ int p1 = REAL_MODE_FORMAT (TYPE_MODE (itype))->p;
+ int p2 = REAL_MODE_FORMAT (TYPE_MODE (newtype))->p;
+ if (p1 < p2 * 2 + 2)
+ break;
+ }
+
/* Be careful about integer to fp conversions.
These may overflow still. */
if (FLOAT_TYPE_P (TREE_TYPE (arg0))
&& TYPE_PRECISION (newtype) < TYPE_PRECISION (itype)
&& (TYPE_MODE (newtype) == TYPE_MODE (double_type_node)
|| TYPE_MODE (newtype) == TYPE_MODE (float_type_node)))
- {
+ {
tree fn = mathfn_built_in (newtype, fcode);
if (fn)
switch (TREE_CODE (expr))
{
/* Convert (float)-x into -(float)x. This is safe for
- round-to-nearest rounding mode. */
+ round-to-nearest rounding mode when the inner type is float. */
case ABS_EXPR:
case NEGATE_EXPR:
if (!flag_rounding_math
- && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (expr)))
+ && FLOAT_TYPE_P (itype)
+ && TYPE_PRECISION (type) < TYPE_PRECISION (itype))
return build1 (TREE_CODE (expr), type,
fold (convert_to_real (type,
TREE_OPERAND (expr, 0))));
{
enum tree_code ex_form = TREE_CODE (expr);
tree intype = TREE_TYPE (expr);
- unsigned int inprec = TYPE_PRECISION (intype);
- unsigned int outprec = TYPE_PRECISION (type);
+ unsigned int inprec = element_precision (intype);
+ unsigned int outprec = element_precision (type);
+ location_t loc = EXPR_LOCATION (expr);
/* An INTEGER_TYPE cannot be incomplete, but an ENUMERAL_TYPE can
be. Consider `enum E = { a, b = (enum E) 3 };'. */
return error_mark_node;
}
+ if (ex_form == COMPOUND_EXPR)
+ {
+ tree t = convert_to_integer (type, TREE_OPERAND (expr, 1));
+ if (t == TREE_OPERAND (expr, 1))
+ return expr;
+ return build2_loc (EXPR_LOCATION (expr), COMPOUND_EXPR, TREE_TYPE (t),
+ TREE_OPERAND (expr, 0), t);
+ }
+
/* Convert e.g. (long)round(d) -> lround(d). */
/* If we're converting to char, we may encounter differing behavior
between converting from double->char vs double->long->char.
{
CASE_FLT_FN (BUILT_IN_CEIL):
/* Only convert in ISO C99 mode. */
- if (!TARGET_C99_FUNCTIONS)
+ if (!targetm.libc_has_function (function_c99_misc))
break;
- if (outprec < TYPE_PRECISION (long_integer_type_node)
- || (outprec == TYPE_PRECISION (long_integer_type_node)
+ if (outprec < TYPE_PRECISION (integer_type_node)
+ || (outprec == TYPE_PRECISION (integer_type_node)
&& !TYPE_UNSIGNED (type)))
+ fn = mathfn_built_in (s_intype, BUILT_IN_ICEIL);
+ else if (outprec == TYPE_PRECISION (long_integer_type_node)
+ && !TYPE_UNSIGNED (type))
fn = mathfn_built_in (s_intype, BUILT_IN_LCEIL);
else if (outprec == TYPE_PRECISION (long_long_integer_type_node)
&& !TYPE_UNSIGNED (type))
CASE_FLT_FN (BUILT_IN_FLOOR):
/* Only convert in ISO C99 mode. */
- if (!TARGET_C99_FUNCTIONS)
+ if (!targetm.libc_has_function (function_c99_misc))
break;
- if (outprec < TYPE_PRECISION (long_integer_type_node)
- || (outprec == TYPE_PRECISION (long_integer_type_node)
+ if (outprec < TYPE_PRECISION (integer_type_node)
+ || (outprec == TYPE_PRECISION (integer_type_node)
&& !TYPE_UNSIGNED (type)))
+ fn = mathfn_built_in (s_intype, BUILT_IN_IFLOOR);
+ else if (outprec == TYPE_PRECISION (long_integer_type_node)
+ && !TYPE_UNSIGNED (type))
fn = mathfn_built_in (s_intype, BUILT_IN_LFLOOR);
else if (outprec == TYPE_PRECISION (long_long_integer_type_node)
&& !TYPE_UNSIGNED (type))
break;
CASE_FLT_FN (BUILT_IN_ROUND):
- if (outprec < TYPE_PRECISION (long_integer_type_node)
- || (outprec == TYPE_PRECISION (long_integer_type_node)
+ /* Only convert in ISO C99 mode and with -fno-math-errno. */
+ if (!targetm.libc_has_function (function_c99_misc) || flag_errno_math)
+ break;
+ if (outprec < TYPE_PRECISION (integer_type_node)
+ || (outprec == TYPE_PRECISION (integer_type_node)
&& !TYPE_UNSIGNED (type)))
+ fn = mathfn_built_in (s_intype, BUILT_IN_IROUND);
+ else if (outprec == TYPE_PRECISION (long_integer_type_node)
+ && !TYPE_UNSIGNED (type))
fn = mathfn_built_in (s_intype, BUILT_IN_LROUND);
else if (outprec == TYPE_PRECISION (long_long_integer_type_node)
&& !TYPE_UNSIGNED (type))
break;
/* ... Fall through ... */
CASE_FLT_FN (BUILT_IN_RINT):
- if (outprec < TYPE_PRECISION (long_integer_type_node)
- || (outprec == TYPE_PRECISION (long_integer_type_node)
+ /* Only convert in ISO C99 mode and with -fno-math-errno. */
+ if (!targetm.libc_has_function (function_c99_misc) || flag_errno_math)
+ break;
+ if (outprec < TYPE_PRECISION (integer_type_node)
+ || (outprec == TYPE_PRECISION (integer_type_node)
&& !TYPE_UNSIGNED (type)))
+ fn = mathfn_built_in (s_intype, BUILT_IN_IRINT);
+ else if (outprec == TYPE_PRECISION (long_integer_type_node)
+ && !TYPE_UNSIGNED (type))
fn = mathfn_built_in (s_intype, BUILT_IN_LRINT);
else if (outprec == TYPE_PRECISION (long_long_integer_type_node)
&& !TYPE_UNSIGNED (type))
else if (outprec >= inprec)
{
enum tree_code code;
- tree tem;
/* If the precision of the EXPR's type is K bits and the
destination mode has more bits, and the sign is changing,
be cleared. */
if (TYPE_UNSIGNED (type) != TYPE_UNSIGNED (TREE_TYPE (expr))
&& (TYPE_PRECISION (TREE_TYPE (expr))
- != GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (expr)))))
+ != GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (expr)))))
code = CONVERT_EXPR;
else
code = NOP_EXPR;
- tem = fold_unary (code, type, expr);
- if (tem)
- return tem;
-
- tem = build1 (code, type, expr);
- TREE_NO_WARNING (tem) = 1;
- return tem;
+ return fold_build1 (code, type, expr);
}
/* If TYPE is an enumeral type or a type with a precision less
type corresponding to its mode, then do a nop conversion
to TYPE. */
else if (TREE_CODE (type) == ENUMERAL_TYPE
- || outprec != GET_MODE_BITSIZE (TYPE_MODE (type)))
+ || outprec != GET_MODE_PRECISION (TYPE_MODE (type)))
return build1 (NOP_EXPR, type,
convert (lang_hooks.types.type_for_mode
(TYPE_MODE (type), TYPE_UNSIGNED (type)),
tree arg0 = get_unwidened (TREE_OPERAND (expr, 0), type);
tree arg1 = get_unwidened (TREE_OPERAND (expr, 1), type);
+ /* Do not try to narrow operands of pointer subtraction;
+ that will interfere with other folding. */
+ if (ex_form == MINUS_EXPR
+ && CONVERT_EXPR_P (arg0)
+ && CONVERT_EXPR_P (arg1)
+ && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (arg0, 0)))
+ && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (arg1, 0))))
+ break;
+
if (outprec >= BITS_PER_WORD
|| TRULY_NOOP_TRUNCATION (outprec, inprec)
|| inprec > TYPE_PRECISION (TREE_TYPE (arg0))
/* Can't do arithmetic in enumeral types
so use an integer type that will hold the values. */
if (TREE_CODE (typex) == ENUMERAL_TYPE)
- typex = lang_hooks.types.type_for_size
- (TYPE_PRECISION (typex), TYPE_UNSIGNED (typex));
+ typex
+ = lang_hooks.types.type_for_size (TYPE_PRECISION (typex),
+ TYPE_UNSIGNED (typex));
/* But now perhaps TYPEX is as wide as INPREC.
In that case, do nothing special here.
|| ex_form == LSHIFT_EXPR
/* If we have !flag_wrapv, and either ARG0 or
ARG1 is of a signed type, we have to do
- PLUS_EXPR or MINUS_EXPR in an unsigned
- type. Otherwise, we would introduce
+ PLUS_EXPR, MINUS_EXPR or MULT_EXPR in an unsigned
+ type in case the operation in outprec precision
+ could overflow. Otherwise, we would introduce
signed-overflow undefinedness. */
|| ((!TYPE_OVERFLOW_WRAPS (TREE_TYPE (arg0))
|| !TYPE_OVERFLOW_WRAPS (TREE_TYPE (arg1)))
+ && ((TYPE_PRECISION (TREE_TYPE (arg0)) * 2u
+ > outprec)
+ || (TYPE_PRECISION (TREE_TYPE (arg1)) * 2u
+ > outprec))
&& (ex_form == PLUS_EXPR
- || ex_form == MINUS_EXPR)))
- typex = unsigned_type_for (typex);
+ || ex_form == MINUS_EXPR
+ || ex_form == MULT_EXPR)))
+ {
+ if (!TYPE_UNSIGNED (typex))
+ typex = unsigned_type_for (typex);
+ }
else
- typex = signed_type_for (typex);
+ {
+ if (TYPE_UNSIGNED (typex))
+ typex = signed_type_for (typex);
+ }
return convert (type,
fold_build2 (ex_form, typex,
convert (typex, arg0),
/* This is not correct for ABS_EXPR,
since we must test the sign before truncation. */
{
- tree typex;
-
- /* Don't do unsigned arithmetic where signed was wanted,
- or vice versa. */
- if (TYPE_UNSIGNED (TREE_TYPE (expr)))
- typex = unsigned_type_for (type);
- else
- typex = signed_type_for (type);
+ /* Do the arithmetic in type TYPEX,
+ then convert result to TYPE. */
+ tree typex = type;
+
+ /* Can't do arithmetic in enumeral types
+ so use an integer type that will hold the values. */
+ if (TREE_CODE (typex) == ENUMERAL_TYPE)
+ typex
+ = lang_hooks.types.type_for_size (TYPE_PRECISION (typex),
+ TYPE_UNSIGNED (typex));
+
+ if (!TYPE_UNSIGNED (typex))
+ typex = unsigned_type_for (typex);
return convert (type,
fold_build1 (ex_form, typex,
convert (typex,
TREE_OPERAND (expr, 0))));
}
- case NOP_EXPR:
+ CASE_CONVERT:
/* Don't introduce a
"can't convert between vector values of different size" error. */
if (TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == VECTOR_TYPE
break;
}
+ /* When parsing long initializers, we might end up with a lot of casts.
+ Shortcut this. */
+ if (TREE_CODE (expr) == INTEGER_CST)
+ return fold_convert (type, expr);
return build1 (CONVERT_EXPR, type, expr);
case REAL_TYPE:
- return build1 (FIX_TRUNC_EXPR, type, expr);
+ if (flag_sanitize & SANITIZE_FLOAT_CAST
+ && do_ubsan_in_current_function ())
+ {
+ expr = save_expr (expr);
+ tree check = ubsan_instrument_float_cast (loc, type, expr, expr);
+ expr = build1 (FIX_TRUNC_EXPR, type, expr);
+ if (check == NULL)
+ return expr;
+ return fold_build2 (COMPOUND_EXPR, TREE_TYPE (expr), check, expr);
+ }
+ else
+ return build1 (FIX_TRUNC_EXPR, type, expr);
case FIXED_POINT_TYPE:
return build1 (FIXED_CONVERT_EXPR, type, expr);
case VECTOR_TYPE:
if (!tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (TREE_TYPE (expr))))
{
- error ("can't convert between vector values of different size");
+ error ("can%'t convert a vector of type %qT"
+ " to type %qT which has different size",
+ TREE_TYPE (expr), type);
return error_mark_node;
}
return build1 (VIEW_CONVERT_EXPR, type, expr);
if (TYPE_MAIN_VARIANT (elt_type) == TYPE_MAIN_VARIANT (subtype))
return expr;
+ else if (TREE_CODE (expr) == COMPOUND_EXPR)
+ {
+ tree t = convert_to_complex (type, TREE_OPERAND (expr, 1));
+ if (t == TREE_OPERAND (expr, 1))
+ return expr;
+ return build2_loc (EXPR_LOCATION (expr), COMPOUND_EXPR,
+ TREE_TYPE (t), TREE_OPERAND (expr, 0), t);
+ }
else if (TREE_CODE (expr) == COMPLEX_EXPR)
return fold_build2 (COMPLEX_EXPR, type,
convert (subtype, TREE_OPERAND (expr, 0)),
case VECTOR_TYPE:
if (!tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (TREE_TYPE (expr))))
{
- error ("can't convert between vector values of different size");
+ error ("can%'t convert a value of type %qT"
+ " to vector type %qT which has different size",
+ TREE_TYPE (expr), type);
return error_mark_node;
}
return build1 (VIEW_CONVERT_EXPR, type, expr);
default:
- error ("can't convert value to a vector");
+ error ("can%'t convert value to a vector");
return error_mark_node;
}
}