This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Possible type bug in make_range()


(If this goes to a mailing list, I'm not subscribed, so please CC
any replies to me.)

Dear GCC developers,

while tracing a bug in GNU Pascal, I came across some code in the
GCC backend which looks suspicious to me. I've now fixed the GPC
problem by other means, so the following is not really important to
me anymore, but I'd like to let you know, anyway.

make_range() in gcc/fold-const.c, case NOP_EXPR contains the
following code:

: /* If we're converting from an unsigned to a signed type,
:    we will be doing the comparison as unsigned.  The tests above
:    have already verified that LOW and HIGH are both positive.
:
:    So we have to make sure that the original unsigned value will
:    be interpreted as positive.  */
: if (TREE_UNSIGNED (type) && ! TREE_UNSIGNED (TREE_TYPE (exp)))
:   {
:     tree equiv_type = type_for_mode (TYPE_MODE (type), 1);
:     tree high_positive;
:
:     /* A range without an upper bound is, naturally, unbounded.
:        Since convert would have cropped a very large value, use
:        the max value for the destination type.  */
:     high_positive
:       = TYPE_MAX_VALUE (equiv_type) ? TYPE_MAX_VALUE (equiv_type)
:         : TYPE_MAX_VALUE (type);
:
:     high_positive = fold (build (RSHIFT_EXPR, type,
:                                  convert (type, high_positive),
:                                  convert (type, integer_one_node)));

type (i.e., TREE_TYPE (arg0)) is already an unsigned type, and
equiv_type is constructed also as an unsigned type. Also the comment
speaks of "the max value for the destination type", but in fact it
takes TYPE_MAX_VALUE (equiv_type) which is the max value of the
original type (or an equivalent type), not of the destination type
which is TREE_TYPE (exp).

E.g., if we have a conversion from unsigned char to int, equiv_type
would be unsigned char as well, its max value would be 255, and
high_positive would finally be 127 which is wrong since unsigned
char values > 127 are still positive.

So I think that `type' should be replaced with `TREE_TYPE (exp)' in
the definition of equiv_type and the first definition of
high_positive, and with `equiv_type' in the second definition of
high_positive (3 places).

I haven't been successful in reproducing an actual bug with C code,
as an explicit cast like `(int) unsigned_char_variable' introduced
in a test program seems to be removed before the compiler gets here.

Frank

-- 
Frank Heckenbach, frank@g-n-u.de
http://fjf.gnu.de/
GnuPG and PGP keys: http://fjf.gnu.de/plan (7977168E)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]