Repository navigation
cc: a 64-bit case TYPE is not a 64-bit case VALUE - #616
Merged
Merged
Conversation
The chicken rebuild went from 8 `duplicate cases in switch 0' to 4. The four that went were runtime.c:12578, the switch on 64-bit `bits', which is the L-suffix fix confirmed where it was predicted. The four that remain are 12525, the switch on a plain int, and they were never the suffix: the same four were there before. Two defects in cc/pswt.c, and only the second was audible. pgen.c:342 sets a case's `isv' from typev[type] alone -- the TYPE -- and doswit discarded every such case in a switch whose expression is 32 bits, under the comment "can never match". That sentence is about a VALUE too wide to appear; it was being applied to a small number with a wide type. chicken.h writes every immediate as ((C_word)(C_SPECIAL_BITS | 0x10)) and C_word is 64 bits here, so four of decode_literal2's eight labels are 0x0e/0x1e/0x3e/0x4e wearing int64_t, and the switch would have fallen to default for all four at run time. Silent: the file compiles. And `nc' was the number of non-default cases, counted before that loop could drop any, while alloc() is a hunk bump allocator that does not zero. So qsort and the duplicate scan ran over nc entries of which the last few had never been written, and reported those against each other -- naming a case the program does not contain. Five dropped labels give exactly four reports, all of value 0, which is the arithmetic in the message. C 6.8.4.2p5 decides it and gcc agrees when asked: a case label "is converted to the promoted type of the controlling expression", so a wide label is truncated and then compared like any other -- case 0x100000001LL: in a switch on an int is reached by 1, and a label that truncates onto another one is a genuine duplicate rather than something to throw away. The (long) cast already performed exactly that conversion, so the fix is deleting the drop plus nc = q - iq. The warning stays and is now about the value, guarded by c->isv so an ordinary case 0xffffffffU: in an unsigned switch does not warn on sign extension. My first fix and my first test were both the other rule -- drop only what does not survive truncation -- and gcc refused to compile the test that asserted it, because case 0x100000000LL: truncates onto case 0:. Checking against the host first changed what the fix should be, not just whether the test was right. switchcase-test.c is the regression test. Section 2 is the one that matters: a compiler with only the loud half fixed compiles cleanly and selects the wrong arm, so the error going away is not evidence -- only asking which arm ran separates them. 0 failures on gcc, where long is 64 bits so neither bug can arise, which says the test is written correctly and nothing more. Watch the first full rebuild: a 64-bit-typed label that truncates onto another one used to be dropped silently and is now a duplicate cases error, so a package that relied on that fails loudly rather than quietly. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGAwvvTwDg2yknFkmZ3qzs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The chicken rebuild went from 8
duplicate cases in switch 0' to 4. The four that went were runtime.c:12578, the switch on 64-bitbits', which is the L-suffix fix confirmed where it was predicted. The four that remain are 12525, the switch on a plain int, and they were never the suffix: the same four were there before.Two defects in cc/pswt.c, and only the second was audible.
pgen.c:342 sets a case's `isv' from typev[type] alone -- the TYPE -- and doswit discarded every such case in a switch whose expression is 32 bits, under the comment "can never match". That sentence is about a VALUE too wide to appear; it was being applied to a small number with a wide type. chicken.h writes every immediate as ((C_word)(C_SPECIAL_BITS | 0x10)) and C_word is 64 bits here, so four of decode_literal2's eight labels are 0x0e/0x1e/0x3e/0x4e wearing int64_t, and the switch would have fallen to default for all four at run time. Silent: the file compiles.
And `nc' was the number of non-default cases, counted before that loop could drop any, while alloc() is a hunk bump allocator that does not zero. So qsort and the duplicate scan ran over nc entries of which the last few had never been written, and reported those against each other -- naming a case the program does not contain. Five dropped labels give exactly four reports, all of value 0, which is the arithmetic in the message.
C 6.8.4.2p5 decides it and gcc agrees when asked: a case label "is converted to the promoted type of the controlling expression", so a wide label is truncated and then compared like any other -- case 0x100000001LL: in a switch on an int is reached by 1, and a label that truncates onto another one is a genuine duplicate rather than something to throw away. The (long) cast already performed exactly that conversion, so the fix is deleting the drop plus nc = q - iq. The warning stays and is now about the value, guarded by c->isv so an ordinary case 0xffffffffU: in an unsigned switch does not warn on sign extension.
My first fix and my first test were both the other rule -- drop only what does not survive truncation -- and gcc refused to compile the test that asserted it, because case 0x100000000LL: truncates onto case 0:. Checking against the host first changed what the fix should be, not just whether the test was right.
switchcase-test.c is the regression test. Section 2 is the one that matters: a compiler with only the loud half fixed compiles cleanly and selects the wrong arm, so the error going away is not evidence -- only asking which arm ran separates them. 0 failures on gcc, where long is 64 bits so neither bug can arise, which says the test is written correctly and nothing more.
Watch the first full rebuild: a 64-bit-typed label that truncates onto another one used to be dropped silently and is now a duplicate cases error, so a package that relied on that fails loudly rather than quietly.
Claude-Session: https://claude.ai/code/session_01WGAwvvTwDg2yknFkmZ3qzs