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
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
Many thanks Michael, I'll report to Bugzilla.