Skip to content

Commit

Permalink
MDEV-7973 bigint fail with gcc 5.0
Browse files Browse the repository at this point in the history
-LONGLONG_MIN is the undefined behavior in C.
longlong2decimal() used to do this:

  int longlong2decimal(longlong from, decimal_t *to) {
    if ((to->sign= from < 0))
      return ull2dec(-from, to);
    return ull2dec(from, to);

and later in ull2dec() (DIG_BASE is 1000000000):

  static int ull2dec(ulonglong from, decimal_t *to) {
    for (intg1=1; from >= DIG_BASE; intg1++, from/=DIG_BASE) {}

this breaks in gcc-5 at -O3. Here ull2dec is inlined into
longlong2decimal. And gcc-5 believes that 'from' in the
inlined ull2dec is always a positive integer (indeed, if it was
negative, then -from was used instead). So gcc-5 uses
*signed* comparison with DIG_BASE.

Fix: make a special case for LONGLONG_MIN, don't negate it
  • Loading branch information
vuvova committed May 4, 2015
1 parent 2983686 commit ae18a28
Showing 1 changed file with 4 additions and 0 deletions.
4 changes: 4 additions & 0 deletions strings/decimal.c
Expand Up @@ -1024,7 +1024,11 @@ int ulonglong2decimal(ulonglong from, decimal_t *to)
int longlong2decimal(longlong from, decimal_t *to)
{
if ((to->sign= from < 0))
{
if (from == LONGLONG_MIN) // avoid undefined behavior
return ull2dec((ulonglong)LONGLONG_MIN, to);
return ull2dec(-from, to);
}
return ull2dec(from, to);
}

Expand Down

0 comments on commit ae18a28

Please sign in to comment.