Source code: 1.cpp #include <stdio.h> static int i; int main (void) { i = -1; switch ((signed char) i) { case 255: printf("255\n"); break; default: printf("default\n"); break; } } Compiling command : g++ 1.cpp && ./a.out result : 255 The expected result: default According to C++ standard, an integral promotion of expression "(signed char) i" should be performed firstly, the result of control expression should be 0xffff; then the label of case statment will be converted to int-type. So the expected result should be default in my opinion. Thanks very much. C++ standard: The condition shall be of integral type, enumeration type, or of a class type for which a single conversion function to integral or enumeration type exists (12.3). If the condition is of class type, the condition is converted by calling that conversion function, and the result of the conversion is used in place of the original condition for the remainder of this section. Integral promotions are performed. Any statement within the switch statement can be labeled with one or more case labels as follows: case constant-expression : where the constant-expression shall be an integral constant-expression. The integral constant-expression (5.19) is implicitly converted to the promoted type of the switch condition.
Integral promotion is performed on the switch argument, thus signed char -1 is sign-extended to int -1. You probably want (unsigned char) i instead.
The expected result should be -1, not 255. But the result is 255 when I use g++ to compiling this code.
I have debug the C++ front-end of gcc3.3.5. In function finish_switch_cond: if (cond != error_mark_node) { cond = default_conversion (cond); cond = fold (build1 (CLEANUP_POINT_EXPR, TREE_TYPE (cond), cond)); } SRF: the type of cond is "int" if (cond != error_mark_node) { index = get_unwidened (cond, NULL_TREE); /* We can't strip a conversion from a signed type to an unsigned, because if we did, int_fits_type_p would do the wrong thing when checking case values for being in range, and it's too hard to do the right thing. */ if (TREE_UNSIGNED (TREE_TYPE (cond)) == TREE_UNSIGNED (TREE_TYPE (index))) cond = index; } SRF: bug the type of cond is back to "signed char" here..... Maybe there is something error in function "get_unwidened"
GCC 3.3 is very old and no longer maintained. > g++-4.4 -o t t.C t.C: In function ‘int main()’: t.C:9: warning: case label value exceeds maximum value for type which seems indeed bogus (but hints at what happens). The C frontend correctly dispatches to the default case but still warns: > gcc-4.4 -o t t.c -Wall t.c: In function ‘main’: t.c:9: warning: case label value exceeds maximum value for type t.c:16: warning: control reaches end of non-void function
Thanks very much. Waiting for your patch. the patch of gcc3.3.5 is also expected if you have enough time to do it. it should be similar with gcc4.** Thanks agian.
Note that 3_4-branch, 4_0-branch, 4_1-branch, 4_2-branch are all closed.
Oh, 4.4 and 4.5 already work. *** This bug has been marked as a duplicate of 39371 ***