Commit 89d12f5d by Zdenek Dvorak Committed by Zdenek Dvorak

tree.c (build_int_cst_type): Take sign of the value into account when deciding…

tree.c (build_int_cst_type): Take sign of the value into account when deciding whether sign extend the value.

	* tree.c (build_int_cst_type): Take sign of the value into account
	when deciding whether sign extend the value.

From-SVN: r94633
parent 740ca4b2
2005-02-02 Zdenek Dvorak <dvorakz@suse.cz>
* tree.c (build_int_cst_type): Take sign of the value into account
when deciding whether sign extend the value.
2005-02-02 Joseph S. Myers <joseph@codesourcery.com> 2005-02-02 Joseph S. Myers <joseph@codesourcery.com>
PR c/18502 PR c/18502
......
...@@ -497,39 +497,62 @@ build_int_cstu (tree type, unsigned HOST_WIDE_INT low) ...@@ -497,39 +497,62 @@ build_int_cstu (tree type, unsigned HOST_WIDE_INT low)
return build_int_cst_wide (type, low, 0); return build_int_cst_wide (type, low, 0);
} }
/* Create an INT_CST node with a LOW value zero or sign extended depending /* Create an INT_CST node with a LOW value in TYPE. The value is sign extended
on the type. */ if it is negative. This function is similar to build_int_cst, but
the extra bits outside of the type precision are cleared. Constants
with these extra bits may confuse the fold so that it detects overflows
even in cases when they do not occur, and in general should be avoided.
We cannot however make this a default behavior of build_int_cst without
more intrusive changes, since there are parts of gcc that rely on the extra
precision of the integer constants. */
tree tree
build_int_cst_type (tree type, HOST_WIDE_INT low) build_int_cst_type (tree type, HOST_WIDE_INT low)
{ {
unsigned HOST_WIDE_INT val = (unsigned HOST_WIDE_INT) low; unsigned HOST_WIDE_INT val = (unsigned HOST_WIDE_INT) low;
unsigned HOST_WIDE_INT hi;
unsigned bits; unsigned bits;
bool signed_p; bool signed_p;
bool negative; bool negative;
tree ret;
if (!type) if (!type)
type = integer_type_node; type = integer_type_node;
bits = TYPE_PRECISION (type); bits = TYPE_PRECISION (type);
signed_p = !TYPE_UNSIGNED (type); signed_p = !TYPE_UNSIGNED (type);
negative = ((val >> (bits - 1)) & 1) != 0;
if (signed_p && negative) if (bits >= HOST_BITS_PER_WIDE_INT)
negative = (low < 0);
else
{ {
if (bits < HOST_BITS_PER_WIDE_INT) /* If the sign bit is inside precision of LOW, use it to determine
the sign of the constant. */
negative = ((val >> (bits - 1)) & 1) != 0;
/* Mask out the bits outside of the precision of the constant. */
if (signed_p && negative)
val = val | ((~(unsigned HOST_WIDE_INT) 0) << bits); val = val | ((~(unsigned HOST_WIDE_INT) 0) << bits);
ret = build_int_cst_wide (type, val, ~(unsigned HOST_WIDE_INT) 0); else
val = val & ~((~(unsigned HOST_WIDE_INT) 0) << bits);
} }
else
/* Determine the high bits. */
hi = (negative ? ~(unsigned HOST_WIDE_INT) 0 : 0);
/* For unsigned type we need to mask out the bits outside of the type
precision. */
if (!signed_p)
{ {
if (bits < HOST_BITS_PER_WIDE_INT) if (bits <= HOST_BITS_PER_WIDE_INT)
val = val & ~((~(unsigned HOST_WIDE_INT) 0) << bits); hi = 0;
ret = build_int_cst_wide (type, val, 0); else
{
bits -= HOST_BITS_PER_WIDE_INT;
hi = hi & ~((~(unsigned HOST_WIDE_INT) 0) << bits);
}
} }
return ret; return build_int_cst_wide (type, val, hi);
} }
/* These are the hash table functions for the hash table of INTEGER_CST /* These are the hash table functions for the hash table of INTEGER_CST
......
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