Commit 269e63b7 by Kai Tietz Committed by Jason Merrill

Add non-folding variants for convert_to_*.

2015-11-13  Kai Tietz  <ktietz70@googlemail.com>
	    Marek Polacek  <polacek@redhat.com>
	    Jason Merrill  <jason@redhat.com>

gcc/
	* convert.c (maybe_fold_build1_loc): New.
	(maybe_fold_build2_loc): New.
	(convert_to_pointer_1): Split out from convert_to_pointer.
	(convert_to_pointer_nofold): New.
	(convert_to_real_1): Split out from convert_to_real.
	(convert_to_real_nofold): New.
	(convert_to_integer_1): Split out from convert_to_integer.
	(convert_to_integer_nofold): New.
	(convert_to_complex_1): Split out from convert_to_complex.
	(convert_to_complex_nofold): New.
	* convert.h: Declare new functions.
	* tree-complex.c (create_one_component_var): Break up line to
	avoid sequence point issues.
gcc/c-family/
	* c-lex.c (interpret_float): Use fold_convert.

Co-Authored-By: Jason Merrill <jason@redhat.com>
Co-Authored-By: Marek Polacek <polacek@redhat.com>

From-SVN: r230359
parent 9514e74f
2015-11-13 Kai Tietz <ktietz70@googlemail.com>
Marek Polacek <polacek@redhat.com>
Jason Merrill <jason@redhat.com>
* convert.c (maybe_fold_build1_loc): New.
(maybe_fold_build2_loc): New.
(convert_to_pointer_1): Split out from convert_to_pointer.
(convert_to_pointer_nofold): New.
(convert_to_real_1): Split out from convert_to_real.
(convert_to_real_nofold): New.
(convert_to_integer_1): Split out from convert_to_integer.
(convert_to_integer_nofold): New.
(convert_to_complex_1): Split out from convert_to_complex.
(convert_to_complex_nofold): New.
* convert.h: Declare new functions.
* tree-complex.c (create_one_component_var): Break up line to
avoid sequence point issues.
2015-11-13 Jason Merrill <jason@redhat.com> 2015-11-13 Jason Merrill <jason@redhat.com>
* fold-const.c (fold_convert_const): Fold changing cv-quals on * fold-const.c (fold_convert_const): Fold changing cv-quals on
2015-11-13 Kai Tietz <ktietz70@googlemail.com>
* c-lex.c (interpret_float): Use fold_convert.
2015-11-13 David Malcolm <dmalcolm@redhat.com> 2015-11-13 David Malcolm <dmalcolm@redhat.com>
* c-common.c (c_fully_fold_internal): Capture existing souce_range, * c-common.c (c_fully_fold_internal): Capture existing souce_range,
......
...@@ -926,8 +926,9 @@ interpret_float (const cpp_token *token, unsigned int flags, ...@@ -926,8 +926,9 @@ interpret_float (const cpp_token *token, unsigned int flags,
value = build_real (const_type, real); value = build_real (const_type, real);
if (flags & CPP_N_IMAGINARY) if (flags & CPP_N_IMAGINARY)
{ {
value = build_complex (NULL_TREE, convert (const_type, value = build_complex (NULL_TREE,
integer_zero_node), value); fold_convert (const_type,
integer_zero_node), value);
if (type != const_type) if (type != const_type)
{ {
const_type = TREE_TYPE (value); const_type = TREE_TYPE (value);
......
...@@ -34,12 +34,20 @@ along with GCC; see the file COPYING3. If not see ...@@ -34,12 +34,20 @@ along with GCC; see the file COPYING3. If not see
#include "builtins.h" #include "builtins.h"
#include "ubsan.h" #include "ubsan.h"
#define maybe_fold_build1_loc(FOLD_P, LOC, CODE, TYPE, EXPR) \
((FOLD_P) ? fold_build1_loc (LOC, CODE, TYPE, EXPR) \
: build1_loc (LOC, CODE, TYPE, EXPR))
#define maybe_fold_build2_loc(FOLD_P, LOC, CODE, TYPE, EXPR1, EXPR2) \
((FOLD_P) ? fold_build2_loc (LOC, CODE, TYPE, EXPR1, EXPR2) \
: build2_loc (LOC, CODE, TYPE, EXPR1, EXPR2))
/* Convert EXPR to some pointer or reference type TYPE. /* Convert EXPR to some pointer or reference type TYPE.
EXPR must be pointer, reference, integer, enumeral, or literal zero; EXPR must be pointer, reference, integer, enumeral, or literal zero;
in other cases error is called. */ in other cases error is called. If FOLD_P is true, try to fold the
expression. */
tree static tree
convert_to_pointer (tree type, tree expr) convert_to_pointer_1 (tree type, tree expr, bool fold_p)
{ {
location_t loc = EXPR_LOCATION (expr); location_t loc = EXPR_LOCATION (expr);
if (TREE_TYPE (expr) == type) if (TREE_TYPE (expr) == type)
...@@ -56,9 +64,10 @@ convert_to_pointer (tree type, tree expr) ...@@ -56,9 +64,10 @@ convert_to_pointer (tree type, tree expr)
addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (expr))); addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (expr)));
if (to_as == from_as) if (to_as == from_as)
return fold_build1_loc (loc, NOP_EXPR, type, expr); return maybe_fold_build1_loc (fold_p, loc, NOP_EXPR, type, expr);
else else
return fold_build1_loc (loc, ADDR_SPACE_CONVERT_EXPR, type, expr); return maybe_fold_build1_loc (fold_p, loc, ADDR_SPACE_CONVERT_EXPR,
type, expr);
} }
case INTEGER_TYPE: case INTEGER_TYPE:
...@@ -72,35 +81,54 @@ convert_to_pointer (tree type, tree expr) ...@@ -72,35 +81,54 @@ convert_to_pointer (tree type, tree expr)
unsigned int pprec = TYPE_PRECISION (type); unsigned int pprec = TYPE_PRECISION (type);
unsigned int eprec = TYPE_PRECISION (TREE_TYPE (expr)); unsigned int eprec = TYPE_PRECISION (TREE_TYPE (expr));
if (eprec != pprec) if (eprec != pprec)
expr = fold_build1_loc (loc, NOP_EXPR, expr
lang_hooks.types.type_for_size (pprec, 0), = maybe_fold_build1_loc (fold_p, loc, NOP_EXPR,
expr); lang_hooks.types.type_for_size (pprec, 0),
expr);
} }
return maybe_fold_build1_loc (fold_p, loc, CONVERT_EXPR, type, expr);
return fold_build1_loc (loc, CONVERT_EXPR, type, expr);
default: default:
error ("cannot convert to a pointer type"); error ("cannot convert to a pointer type");
return convert_to_pointer (type, integer_zero_node); return convert_to_pointer_1 (type, integer_zero_node, fold_p);
} }
} }
/* A wrapper around convert_to_pointer_1 that always folds the
expression. */
tree
convert_to_pointer (tree type, tree expr)
{
return convert_to_pointer_1 (type, expr, true);
}
/* A wrapper around convert_to_pointer_1 that only folds the
expression if it is CONSTANT_CLASS_P. */
tree
convert_to_pointer_nofold (tree type, tree expr)
{
return convert_to_pointer_1 (type, expr, CONSTANT_CLASS_P (expr));
}
/* Convert EXPR to some floating-point type TYPE. /* Convert EXPR to some floating-point type TYPE.
EXPR must be float, fixed-point, integer, or enumeral; EXPR must be float, fixed-point, integer, or enumeral;
in other cases error is called. */ in other cases error is called. If FOLD_P is true, try to fold
the expression. */
tree static tree
convert_to_real (tree type, tree expr) convert_to_real_1 (tree type, tree expr, bool fold_p)
{ {
enum built_in_function fcode = builtin_mathfn_code (expr); enum built_in_function fcode = builtin_mathfn_code (expr);
tree itype = TREE_TYPE (expr); tree itype = TREE_TYPE (expr);
location_t loc = EXPR_LOCATION (expr);
if (TREE_CODE (expr) == COMPOUND_EXPR) if (TREE_CODE (expr) == COMPOUND_EXPR)
{ {
tree t = convert_to_real (type, TREE_OPERAND (expr, 1)); tree t = convert_to_real_1 (type, TREE_OPERAND (expr, 1), fold_p);
if (t == TREE_OPERAND (expr, 1)) if (t == TREE_OPERAND (expr, 1))
return expr; return expr;
return build2_loc (EXPR_LOCATION (expr), COMPOUND_EXPR, TREE_TYPE (t), return build2_loc (EXPR_LOCATION (expr), COMPOUND_EXPR, TREE_TYPE (t),
...@@ -208,14 +236,13 @@ convert_to_real (tree type, tree expr) ...@@ -208,14 +236,13 @@ convert_to_real (tree type, tree expr)
|| TYPE_MODE (newtype) == TYPE_MODE (float_type_node))) || TYPE_MODE (newtype) == TYPE_MODE (float_type_node)))
{ {
tree fn = mathfn_built_in (newtype, fcode); tree fn = mathfn_built_in (newtype, fcode);
if (fn) if (fn)
{ {
tree arg = fold (convert_to_real (newtype, arg0)); tree arg = convert_to_real_1 (newtype, arg0, fold_p);
expr = build_call_expr (fn, 1, arg); expr = build_call_expr (fn, 1, arg);
if (newtype == type) if (newtype == type)
return expr; return expr;
} }
} }
} }
default: default:
...@@ -234,9 +261,11 @@ convert_to_real (tree type, tree expr) ...@@ -234,9 +261,11 @@ convert_to_real (tree type, tree expr)
if (!flag_rounding_math if (!flag_rounding_math
&& FLOAT_TYPE_P (itype) && FLOAT_TYPE_P (itype)
&& TYPE_PRECISION (type) < TYPE_PRECISION (itype)) && TYPE_PRECISION (type) < TYPE_PRECISION (itype))
return build1 (TREE_CODE (expr), type, {
fold (convert_to_real (type, tree arg = convert_to_real_1 (type, TREE_OPERAND (expr, 0),
TREE_OPERAND (expr, 0)))); fold_p);
return build1 (TREE_CODE (expr), type, arg);
}
break; break;
/* Convert (outertype)((innertype0)a+(innertype1)b) /* Convert (outertype)((innertype0)a+(innertype1)b)
into ((newtype)a+(newtype)b) where newtype into ((newtype)a+(newtype)b) where newtype
...@@ -272,8 +301,10 @@ convert_to_real (tree type, tree expr) ...@@ -272,8 +301,10 @@ convert_to_real (tree type, tree expr)
|| newtype == dfloat128_type_node) || newtype == dfloat128_type_node)
{ {
expr = build2 (TREE_CODE (expr), newtype, expr = build2 (TREE_CODE (expr), newtype,
fold (convert_to_real (newtype, arg0)), convert_to_real_1 (newtype, arg0,
fold (convert_to_real (newtype, arg1))); fold_p),
convert_to_real_1 (newtype, arg1,
fold_p));
if (newtype == type) if (newtype == type)
return expr; return expr;
break; break;
...@@ -312,8 +343,10 @@ convert_to_real (tree type, tree expr) ...@@ -312,8 +343,10 @@ convert_to_real (tree type, tree expr)
&& !excess_precision_type (newtype)))) && !excess_precision_type (newtype))))
{ {
expr = build2 (TREE_CODE (expr), newtype, expr = build2 (TREE_CODE (expr), newtype,
fold (convert_to_real (newtype, arg0)), convert_to_real_1 (newtype, arg0,
fold (convert_to_real (newtype, arg1))); fold_p),
convert_to_real_1 (newtype, arg1,
fold_p));
if (newtype == type) if (newtype == type)
return expr; return expr;
} }
...@@ -344,30 +377,51 @@ convert_to_real (tree type, tree expr) ...@@ -344,30 +377,51 @@ convert_to_real (tree type, tree expr)
case COMPLEX_TYPE: case COMPLEX_TYPE:
return convert (type, return convert (type,
fold_build1 (REALPART_EXPR, maybe_fold_build1_loc (fold_p, loc, REALPART_EXPR,
TREE_TYPE (TREE_TYPE (expr)), expr)); TREE_TYPE (TREE_TYPE (expr)),
expr));
case POINTER_TYPE: case POINTER_TYPE:
case REFERENCE_TYPE: case REFERENCE_TYPE:
error ("pointer value used where a floating point value was expected"); error ("pointer value used where a floating point value was expected");
return convert_to_real (type, integer_zero_node); return convert_to_real_1 (type, integer_zero_node, fold_p);
default: default:
error ("aggregate value used where a float was expected"); error ("aggregate value used where a float was expected");
return convert_to_real (type, integer_zero_node); return convert_to_real_1 (type, integer_zero_node, fold_p);
} }
} }
/* A wrapper around convert_to_real_1 that always folds the
expression. */
tree
convert_to_real (tree type, tree expr)
{
return convert_to_real_1 (type, expr, true);
}
/* A wrapper around convert_to_real_1 that only folds the
expression if it is CONSTANT_CLASS_P. */
tree
convert_to_real_nofold (tree type, tree expr)
{
return convert_to_real_1 (type, expr, CONSTANT_CLASS_P (expr));
}
/* Convert EXPR to some integer (or enum) type TYPE. /* Convert EXPR to some integer (or enum) type TYPE.
EXPR must be pointer, integer, discrete (enum, char, or bool), float, EXPR must be pointer, integer, discrete (enum, char, or bool), float,
fixed-point or vector; in other cases error is called. fixed-point or vector; in other cases error is called.
If DOFOLD is TRUE, we try to simplify newly-created patterns by folding.
The result of this is always supposed to be a newly created tree node The result of this is always supposed to be a newly created tree node
not in use in any existing structure. */ not in use in any existing structure. */
tree static tree
convert_to_integer (tree type, tree expr) convert_to_integer_1 (tree type, tree expr, bool dofold)
{ {
enum tree_code ex_form = TREE_CODE (expr); enum tree_code ex_form = TREE_CODE (expr);
tree intype = TREE_TYPE (expr); tree intype = TREE_TYPE (expr);
...@@ -385,7 +439,7 @@ convert_to_integer (tree type, tree expr) ...@@ -385,7 +439,7 @@ convert_to_integer (tree type, tree expr)
if (ex_form == COMPOUND_EXPR) if (ex_form == COMPOUND_EXPR)
{ {
tree t = convert_to_integer (type, TREE_OPERAND (expr, 1)); tree t = convert_to_integer_1 (type, TREE_OPERAND (expr, 1), dofold);
if (t == TREE_OPERAND (expr, 1)) if (t == TREE_OPERAND (expr, 1))
return expr; return expr;
return build2_loc (EXPR_LOCATION (expr), COMPOUND_EXPR, TREE_TYPE (t), return build2_loc (EXPR_LOCATION (expr), COMPOUND_EXPR, TREE_TYPE (t),
...@@ -479,7 +533,7 @@ convert_to_integer (tree type, tree expr) ...@@ -479,7 +533,7 @@ convert_to_integer (tree type, tree expr)
break; break;
CASE_FLT_FN (BUILT_IN_TRUNC): CASE_FLT_FN (BUILT_IN_TRUNC):
return convert_to_integer (type, CALL_EXPR_ARG (s_expr, 0)); return convert_to_integer_1 (type, CALL_EXPR_ARG (s_expr, 0), dofold);
default: default:
break; break;
...@@ -488,7 +542,7 @@ convert_to_integer (tree type, tree expr) ...@@ -488,7 +542,7 @@ convert_to_integer (tree type, tree expr)
if (fn) if (fn)
{ {
tree newexpr = build_call_expr (fn, 1, CALL_EXPR_ARG (s_expr, 0)); tree newexpr = build_call_expr (fn, 1, CALL_EXPR_ARG (s_expr, 0));
return convert_to_integer (type, newexpr); return convert_to_integer_1 (type, newexpr, dofold);
} }
} }
...@@ -519,7 +573,7 @@ convert_to_integer (tree type, tree expr) ...@@ -519,7 +573,7 @@ convert_to_integer (tree type, tree expr)
if (fn) if (fn)
{ {
tree newexpr = build_call_expr (fn, 1, CALL_EXPR_ARG (s_expr, 0)); tree newexpr = build_call_expr (fn, 1, CALL_EXPR_ARG (s_expr, 0));
return convert_to_integer (type, newexpr); return convert_to_integer_1 (type, newexpr, dofold);
} }
} }
...@@ -534,6 +588,8 @@ convert_to_integer (tree type, tree expr) ...@@ -534,6 +588,8 @@ convert_to_integer (tree type, tree expr)
there widen/truncate to the required type. Some targets support the there widen/truncate to the required type. Some targets support the
coexistence of multiple valid pointer sizes, so fetch the one we need coexistence of multiple valid pointer sizes, so fetch the one we need
from the type. */ from the type. */
if (!dofold)
return build1 (CONVERT_EXPR, type, expr);
expr = fold_build1 (CONVERT_EXPR, expr = fold_build1 (CONVERT_EXPR,
lang_hooks.types.type_for_size lang_hooks.types.type_for_size
(TYPE_PRECISION (intype), 0), (TYPE_PRECISION (intype), 0),
...@@ -578,7 +634,7 @@ convert_to_integer (tree type, tree expr) ...@@ -578,7 +634,7 @@ convert_to_integer (tree type, tree expr)
else else
code = NOP_EXPR; code = NOP_EXPR;
return fold_build1 (code, type, expr); return maybe_fold_build1_loc (dofold, loc, code, type, expr);
} }
/* If TYPE is an enumeral type or a type with a precision less /* If TYPE is an enumeral type or a type with a precision less
...@@ -784,10 +840,12 @@ convert_to_integer (tree type, tree expr) ...@@ -784,10 +840,12 @@ convert_to_integer (tree type, tree expr)
if (TYPE_UNSIGNED (typex)) if (TYPE_UNSIGNED (typex))
typex = signed_type_for (typex); typex = signed_type_for (typex);
} }
return convert (type, /* We should do away with all this once we have a proper
fold_build2 (ex_form, typex, type promotion/demotion pass, see PR45397. */
convert (typex, arg0), expr = maybe_fold_build2_loc (dofold, loc, ex_form, typex,
convert (typex, arg1))); convert (typex, arg0),
convert (typex, arg1));
return convert (type, expr);
} }
} }
} }
...@@ -798,6 +856,9 @@ convert_to_integer (tree type, tree expr) ...@@ -798,6 +856,9 @@ convert_to_integer (tree type, tree expr)
/* This is not correct for ABS_EXPR, /* This is not correct for ABS_EXPR,
since we must test the sign before truncation. */ since we must test the sign before truncation. */
{ {
if (!dofold)
break;
/* Do the arithmetic in type TYPEX, /* Do the arithmetic in type TYPEX,
then convert result to TYPE. */ then convert result to TYPE. */
tree typex = type; tree typex = type;
...@@ -833,13 +894,15 @@ convert_to_integer (tree type, tree expr) ...@@ -833,13 +894,15 @@ convert_to_integer (tree type, tree expr)
the conditional and never loses. A COND_EXPR may have a throw the conditional and never loses. A COND_EXPR may have a throw
as one operand, which then has void type. Just leave void as one operand, which then has void type. Just leave void
operands as they are. */ operands as they are. */
return fold_build3 (COND_EXPR, type, TREE_OPERAND (expr, 0), if (dofold)
VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 1))) return
? TREE_OPERAND (expr, 1) fold_build3 (COND_EXPR, type, TREE_OPERAND (expr, 0),
: convert (type, TREE_OPERAND (expr, 1)), VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 1)))
VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 2))) ? TREE_OPERAND (expr, 1)
? TREE_OPERAND (expr, 2) : convert (type, TREE_OPERAND (expr, 1)),
: convert (type, TREE_OPERAND (expr, 2))); VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 2)))
? TREE_OPERAND (expr, 2)
: convert (type, TREE_OPERAND (expr, 2)));
default: default:
break; break;
...@@ -860,7 +923,8 @@ convert_to_integer (tree type, tree expr) ...@@ -860,7 +923,8 @@ convert_to_integer (tree type, tree expr)
expr = build1 (FIX_TRUNC_EXPR, type, expr); expr = build1 (FIX_TRUNC_EXPR, type, expr);
if (check == NULL) if (check == NULL)
return expr; return expr;
return fold_build2 (COMPOUND_EXPR, TREE_TYPE (expr), check, expr); return maybe_fold_build2_loc (dofold, loc, COMPOUND_EXPR,
TREE_TYPE (expr), check, expr);
} }
else else
return build1 (FIX_TRUNC_EXPR, type, expr); return build1 (FIX_TRUNC_EXPR, type, expr);
...@@ -869,9 +933,9 @@ convert_to_integer (tree type, tree expr) ...@@ -869,9 +933,9 @@ convert_to_integer (tree type, tree expr)
return build1 (FIXED_CONVERT_EXPR, type, expr); return build1 (FIXED_CONVERT_EXPR, type, expr);
case COMPLEX_TYPE: case COMPLEX_TYPE:
return convert (type, expr = maybe_fold_build1_loc (dofold, loc, REALPART_EXPR,
fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (expr)), expr);
TREE_TYPE (TREE_TYPE (expr)), expr)); return convert (type, expr);
case VECTOR_TYPE: case VECTOR_TYPE:
if (!tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (TREE_TYPE (expr)))) if (!tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (TREE_TYPE (expr))))
...@@ -889,11 +953,42 @@ convert_to_integer (tree type, tree expr) ...@@ -889,11 +953,42 @@ convert_to_integer (tree type, tree expr)
} }
} }
/* Convert EXPR to the complex type TYPE in the usual ways. */ /* Convert EXPR to some integer (or enum) type TYPE.
EXPR must be pointer, integer, discrete (enum, char, or bool), float,
fixed-point or vector; in other cases error is called.
The result of this is always supposed to be a newly created tree node
not in use in any existing structure. */
tree tree
convert_to_complex (tree type, tree expr) convert_to_integer (tree type, tree expr)
{
return convert_to_integer_1 (type, expr, true);
}
/* Convert EXPR to some integer (or enum) type TYPE.
EXPR must be pointer, integer, discrete (enum, char, or bool), float,
fixed-point or vector; in other cases error is called.
The result of this is always supposed to be a newly created tree node
not in use in any existing structure. The tree node isn't folded,
beside EXPR is of constant class. */
tree
convert_to_integer_nofold (tree type, tree expr)
{ {
return convert_to_integer_1 (type, expr, CONSTANT_CLASS_P (expr));
}
/* Convert EXPR to the complex type TYPE in the usual ways. If FOLD_P is
true, try to fold the expression. */
static tree
convert_to_complex_1 (tree type, tree expr, bool fold_p)
{
location_t loc = EXPR_LOCATION (expr);
tree subtype = TREE_TYPE (type); tree subtype = TREE_TYPE (type);
switch (TREE_CODE (TREE_TYPE (expr))) switch (TREE_CODE (TREE_TYPE (expr)))
...@@ -914,43 +1009,63 @@ convert_to_complex (tree type, tree expr) ...@@ -914,43 +1009,63 @@ convert_to_complex (tree type, tree expr)
return expr; return expr;
else if (TREE_CODE (expr) == COMPOUND_EXPR) else if (TREE_CODE (expr) == COMPOUND_EXPR)
{ {
tree t = convert_to_complex (type, TREE_OPERAND (expr, 1)); tree t = convert_to_complex_1 (type, TREE_OPERAND (expr, 1),
fold_p);
if (t == TREE_OPERAND (expr, 1)) if (t == TREE_OPERAND (expr, 1))
return expr; return expr;
return build2_loc (EXPR_LOCATION (expr), COMPOUND_EXPR, return build2_loc (EXPR_LOCATION (expr), COMPOUND_EXPR,
TREE_TYPE (t), TREE_OPERAND (expr, 0), t); TREE_TYPE (t), TREE_OPERAND (expr, 0), t);
} }
else if (TREE_CODE (expr) == COMPLEX_EXPR) else if (TREE_CODE (expr) == COMPLEX_EXPR)
return fold_build2 (COMPLEX_EXPR, type, return maybe_fold_build2_loc (fold_p, loc, COMPLEX_EXPR, type,
convert (subtype, TREE_OPERAND (expr, 0)), convert (subtype,
convert (subtype, TREE_OPERAND (expr, 1))); TREE_OPERAND (expr, 0)),
convert (subtype,
TREE_OPERAND (expr, 1)));
else else
{ {
expr = save_expr (expr); expr = save_expr (expr);
return tree realp = maybe_fold_build1_loc (fold_p, loc, REALPART_EXPR,
fold_build2 (COMPLEX_EXPR, type, TREE_TYPE (TREE_TYPE (expr)),
convert (subtype, expr);
fold_build1 (REALPART_EXPR, tree imagp = maybe_fold_build1_loc (fold_p, loc, IMAGPART_EXPR,
TREE_TYPE (TREE_TYPE (expr)), TREE_TYPE (TREE_TYPE (expr)),
expr)), expr);
convert (subtype, return maybe_fold_build2_loc (fold_p, loc, COMPLEX_EXPR, type,
fold_build1 (IMAGPART_EXPR, convert (subtype, realp),
TREE_TYPE (TREE_TYPE (expr)), convert (subtype, imagp));
expr)));
} }
} }
case POINTER_TYPE: case POINTER_TYPE:
case REFERENCE_TYPE: case REFERENCE_TYPE:
error ("pointer value used where a complex was expected"); error ("pointer value used where a complex was expected");
return convert_to_complex (type, integer_zero_node); return convert_to_complex_1 (type, integer_zero_node, fold_p);
default: default:
error ("aggregate value used where a complex was expected"); error ("aggregate value used where a complex was expected");
return convert_to_complex (type, integer_zero_node); return convert_to_complex_1 (type, integer_zero_node, fold_p);
} }
} }
/* A wrapper around convert_to_complex_1 that always folds the
expression. */
tree
convert_to_complex (tree type, tree expr)
{
return convert_to_complex_1 (type, expr, true);
}
/* A wrapper around convert_to_complex_1 that only folds the
expression if it is CONSTANT_CLASS_P. */
tree
convert_to_complex_nofold (tree type, tree expr)
{
return convert_to_complex_1 (type, expr, CONSTANT_CLASS_P (expr));
}
/* Convert EXPR to the vector type TYPE in the usual ways. */ /* Convert EXPR to the vector type TYPE in the usual ways. */
tree tree
......
...@@ -21,10 +21,14 @@ along with GCC; see the file COPYING3. If not see ...@@ -21,10 +21,14 @@ along with GCC; see the file COPYING3. If not see
#define GCC_CONVERT_H #define GCC_CONVERT_H
extern tree convert_to_integer (tree, tree); extern tree convert_to_integer (tree, tree);
extern tree convert_to_integer_nofold (tree, tree);
extern tree convert_to_pointer (tree, tree); extern tree convert_to_pointer (tree, tree);
extern tree convert_to_pointer_nofold (tree, tree);
extern tree convert_to_real (tree, tree); extern tree convert_to_real (tree, tree);
extern tree convert_to_real_nofold (tree, tree);
extern tree convert_to_fixed (tree, tree); extern tree convert_to_fixed (tree, tree);
extern tree convert_to_complex (tree, tree); extern tree convert_to_complex (tree, tree);
extern tree convert_to_complex_nofold (tree, tree);
extern tree convert_to_vector (tree, tree); extern tree convert_to_vector (tree, tree);
#endif /* GCC_CONVERT_H */ #endif /* GCC_CONVERT_H */
...@@ -432,8 +432,8 @@ create_one_component_var (tree type, tree orig, const char *prefix, ...@@ -432,8 +432,8 @@ create_one_component_var (tree type, tree orig, const char *prefix,
if (DECL_NAME (orig) && !DECL_IGNORED_P (orig)) if (DECL_NAME (orig) && !DECL_IGNORED_P (orig))
{ {
const char *name = IDENTIFIER_POINTER (DECL_NAME (orig)); const char *name = IDENTIFIER_POINTER (DECL_NAME (orig));
name = ACONCAT ((name, suffix, NULL));
DECL_NAME (r) = get_identifier (ACONCAT ((name, suffix, NULL))); DECL_NAME (r) = get_identifier (name);
SET_DECL_DEBUG_EXPR (r, build1 (code, type, orig)); SET_DECL_DEBUG_EXPR (r, build1 (code, type, orig));
DECL_HAS_DEBUG_EXPR_P (r) = 1; DECL_HAS_DEBUG_EXPR_P (r) = 1;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment