Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

gcc 4.1.1 bug / case ranges / unsigned long long

14 views
Skip to first unread message

remi.ch...@gmail.com

unread,
Nov 19, 2007, 7:48:50 AM11/19/07
to
The following switch returns a false result with i =
1000000000000000000, at least (Its goal is to give the number of
digits of an unsigned long long number).

switch( aLL )
{
case 0ULL : return
0 ;
case 1ULL ... 9ULL : return
1 ;
case 10ULL ... 99ULL : return
2 ;
case 100ULL ... 999ULL : return
3 ;
case 1000ULL ... 9999ULL : return
4 ;
... ETC ...
case 1000000000000000ULL ... 9999999999999999ULL : return
16 ;
case 10000000000000000ULL ... 99999999999999999ULL : return
17 ;
case 100000000000000000ULL ... 999999999999999999ULL : return
18 ;
case 1000000000000000000ULL ... 9999999999999999999ULL : return
19 ;
default : return
20 ;
};

The result is 20 instead of 19 for aLL=1000000000000000000ULL with gcc
4.1.1 and gcc 4.2.2, but is correct with gcc 3.3.

I was told by a very helpful person that "ISO/IEC 9899-1999 (aka C99)
at 6.8.4.2.1 says:
"The controlling expression of a switch statement shall have integer
type" - not unsigned long long, this is true.

But things are not totally clear for me:

* the compiler did not complain,
* I cannot see any technical reason why it should not be implemented.
After all, 'case ranges' are a gcc extension so it may be worth to go
a bit beyond C99 requirements.
* it works perfectly for values smaller than 1^19 : the assembly code
produced is made for 64 bits. Here is an example of the generated code
(Pentium):
cmpl $23283064, -20(%ebp)
ja .L44
cmpl $1569325055, -24(%ebp)
jbe .L20
The low and high longwords are compared with 32 bits instructions:

$ expr 4294967296 '*' 23283064 + 1569325055
99999999999999999 ... which is one of the values to compare to.

And, if we investigate the code at the end of the function, there is a
big branch where obviously
the case '19' is missing:

.L3: movl $0, -12(%ebp)
jmp .L46
.L4: movl $1, -12(%ebp)
jmp .L46
.L5: movl $2, -12(%ebp)
jmp .L46
/* 3,4,5,6,7,8,9,10,11,12,13,14 and 15 and 16 */
.L20: movl $17, -12(%ebp)
jmp .L46
.L21: movl $18, -12(%ebp)
jmp .L46
/* WHERE IS '$19' ??? */
.L2: movl $20, -12(%ebp)

Any idea ? Many thanks.

Remi


Mikael Pettersson

unread,
Nov 19, 2007, 8:35:11 AM11/19/07
to
In article <c78b2355-96b5-4885...@c29g2000hsa.googlegroups.com>,

First of all, gcc bug reports should be expressed as
standalone .c files that when compiled trigger the problem.

In this case, I had to add a small main() and some
trivial glue code to make this example compile.

Having said that, this code does produce the value 19
on i686-pc-linux-gnu with gcc 2.95.3, 3.3.6, and 3.4.6,
but the value 20 with gcc 4.0.4, 4.1.2, and 4.2.2.

Even with -Wall -std=gnu99 gcc-4.2.2 doesn't complain
about the code, so I'd say it's a genuine gcc-4.x bug.

Perhaps you should report this to <http://gcc.gnu.org/bugzilla/>.
--
Mikael Pettersson (mi...@it.uu.se)
Computing Science Department, Uppsala University

remi.ch...@gmail.com

unread,
Nov 19, 2007, 4:25:58 PM11/19/07
to
On 19 nov, 13:35, mi...@harpo.csd.uu.se (Mikael Pettersson) wrote:
> In article <c78b2355-96b5-4885-b22e-38cae3290...@c29g2000hsa.googlegroups.com>,


Many thanks Michael, I'll report to Bugzilla.

0 new messages