Bug 25019 - Promoting long to long long generates no warning and/or incorrect result.
Summary: Promoting long to long long generates no warning and/or incorrect result.
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 3.3.4
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-11-24 15:15 UTC by Christian van den Bosch
Modified: 2005-11-24 17:28 UTC (History)
1 user (show)

See Also:
Host: i586-pc-linux-gnu
Target: i586-pc-linux-gnu
Build: i586-pc-linux-gnu
Known to work:
Known to fail:
Last reconfirmed:


Attachments
Test case for 32-64 bit promotion bug (342 bytes, text/plain)
2005-11-24 15:21 UTC, Christian van den Bosch
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Christian van den Bosch 2005-11-24 15:15:53 UTC
Promoting of longs to long longs gives incorrect results (i.e. sign extension is not done; upper half of result may in some cases be the upper half of a previous 64-bit computation), and does not give a warning in most cases.

I have tried http://cjb.ie/32-64bug.c on the following, on various 32-bit x86 machines:

gcc (GCC) 3.3.4 20040623 (Gentoo Linux 3.3.4-r1, ssp-3.3.2-2, pie-8.7.6)
gcc-3.3 (GCC) 3.3.5 (Debian 1:3.3.5-8ubuntu2)
gcc-3.3 (GCC) 3.3.6 (Ubuntu 1:3.3.6-8ubuntu1)
gcc-4.0 (GCC) 4.0.0 20050301 (prerelease) (Debian 4.0-0pre6ubuntu7)
gcc-4.0 (GCC) 4.0.2 20050808 (prerelease) (Ubuntu 4.0.1-4ubuntu9)

For all of the above, and different values for -O, results seem to be invariant:

$ gcc -o 32-64bug 32-64bug.c
32-64bug.c: In function ‘main’:
32-64bug.c:13: warning: left shift count >= width of type
32-64bug.c:14: warning: left shift count >= width of type
$ ./32-64bug
    550000000000 expected for 85LL<<40,
    550000000000 obtained.
     10000000000 expected for 1<<40 (const expr as printf arg),
    550000000000 obtained.
     10000000000 expected for 1<<40 (const expr, precomputed),
               0 obtained.

   5500000000000 expected for 85LL<<44,
   5500000000000 obtained.
     10000000000 expected for 1<<40 (variable expr, precomputed),
             100 obtained.
     10000000000 expected for 1<<40 (variable expr, as printf arg),
             100 obtained.

  55000000000000 expected for 85LL<<48,
  55000000000000 obtained.
      1234567800 expected for 0x12345678<<8 (const expr, as printf arg),
  55000034567800 obtained.
      1234567800 expected for 0x12345678<<8 (const expr, precomputed),
        34567800 obtained.
$

Note that a warning is only generated for the 1<<40 constant expression, and others are miscomputed with no warning.

If it's not easy to get the 'expected' and 'obtained' values to match above, would it be possible to just generate a warning any time a 32-bit value is promoted to 64-bit?
Comment 1 Christian van den Bosch 2005-11-24 15:21:40 UTC
Created attachment 10333 [details]
Test case for 32-64 bit promotion bug

Most recent version of this file available at http://cjb.ie/32-64bug.c or http://cjb.ie/32-64bug.c.txt
Comment 2 Andrew Pinski 2005-11-24 16:50:40 UTC
a=1<<b;
is done in the type of b and not of type of a so this is invalid as the behavior is undefined.
Comment 3 Falk Hueffner 2005-11-24 17:01:41 UTC
Well, there's one actual issue here, namely that there is no warning about:

int f() {
    int x = 40;
    return 1 << x;
}

even though we could of course detect this, albeit probably only in the middle-end. It might be difficult to get this warning to be emitted reliably and without false positives from there.
Comment 4 Andreas Schwab 2005-11-24 17:28:10 UTC
(In reply to comment #2)
> a=1<<b;
> is done in the type of b and not of type of a

The type of the right operand of a shift expression has no significance at all.  1 has type int, so has 1<<b.