DavidKinder / Inform6

The latest version of the Inform 6 compiler, used for generating interactive fiction games.
http://inform-fiction.org/
Other
208 stars 35 forks source link

Empty statement "can never be reached" #295

Open tustin2121 opened 4 months ago

tustin2121 commented 4 months ago
Property adj; ! For adjectives
[ ParseNoun obj   word n m;
    while ((word = NextWord()) ~= 0) {
        if (WordInProperty(word, obj, adj)) { n++; continue; }
        break;
-   }
    wn--;
    while ((word = NextWord()) ~= 0) {
        if (WordInProperty(word, obj, name)) { m++; continue; }
        break;
-   }
    if (m == 0) return 0; 
    return n+m;
];

The compiler issues "This statement can never be reached" warnings for the above code, pointing at the ending brace for the while loops (which I marked in red). It seems like this warning is issued during assembly output, so presumably it outputs the end-of-loop jump back to the top of the loop after the unconditional jump out of the loop, and that is what it is warning on.

But in practical terms, it looks like it is issuing a warning for the white space prior to the end of the loop. And there's no way to suppress that useless warning without suppressing otherwise useful warnings about unreachable code.

Related to #87, in that I imagine the optimizations that come out of that thread would indirectly solve this issue.

erkyrath commented 4 months ago

Let's see. I rewrote that warning (and dead-code stripping) in 6.40, but the problem here goes back to 6.31, probably farther.

For simplicity I'm reducing the example to this:


[ WordInProperty;
    return true;
];

[ ParseNoun word n;
    while (word--) {
        if (WordInProperty()) { n++; continue; }
        break;
    }     ! Warning:  This statement can never be reached
    return n;
];
erkyrath commented 4 months ago

I think it's reasoning incorrectly about the continue statement. If you change the function to this (logically equivalent):


[ ParseNoun2 word n;
    while (word--) {
        if (~~WordInProperty()) { break; }
        n++;
        continue;
    }
    return n;
];

...then the warning persists. But if you remove the continue line (which is now redundant), there is no warning and you get the behavior you want.

I'd say for now rewrite the ParseNoun() function in this way. I may be able to improve this in a future release, but it's not a high priority. The warning logic is a big fussy mess and it would be easy to break some cases while fixing others.

erkyrath commented 4 months ago

The warning occurs on the "jump to top of loop" opcode (i.e. states.c:1745, etc) if it's impossible for execution to reach the end of the loop body. This is a simpler example:

[ ParseNoun4 word;
    while (word--) {
        if (word < 3) {
            break;
        }
        else {
            break;
        }
    }
];

It may be sufficient to put an if (!execution_never_reaches_here) on that statement, but I'll have to check all the other warning test cases.