Bug 1560 – Skip switch warning for complete enum set
Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D1 (retired)
Platform
x86
OS
Linux
Creation time
2007-10-09T09:36:00Z
Last change time
2014-02-17T22:51:00Z
Keywords
diagnostic
Assigned to
nobody
Creator
david
Comments
Comment #0 by david — 2007-10-09T09:36:11Z
Consider the following:
void main()
{
enum T { RED, GREEN, BLUE }
T t;
switch (t)
{
case T.RED: break;
case T.GREEN: break;
case T.BLUE: break;
}
}
DMD gives two warnings:
warning - foo.d(8): Error: switch statement has no default
warning - foo.d(8): Error: statement is not reachable
A default is not needed as all enum values are handled. Omitting the default and warning here gives us the same functionality as g++:
warning: enumeration value `xxx' not handled in switch
Comment #1 by smjg — 2007-10-10T08:16:41Z
DMD 1.022 (Windows) reports both warnings at line 6.
The more significant bug here is that the second warning is complete nonsense, not to mention that both messages suffer from issue 952.
There are a few issues at work here:
- as you say, all the enum values have been considered
- the second warning is complete nonsense
However, you could debate whether it should still issue the warning nonetheless. There are various reasons that an enum variable might contain a value that isn't one of the named values, for example:
- it's a set of bit flags
- the enum's value list is incomplete (likely when interfacing OS or other foreign APIs)
- some system of enums derived from enums is used to group them into categories
- malformed data read from a file
But should we assume that the programmer knows what he/she is doing in such cases?
Comment #2 by david — 2007-10-10T14:53:28Z
Sorry about the confusion on the line numbers. I was running it as a shell script, thus it had two extra lines above the code shown.
I hadn't considered an enum instance containing an invalid value, though to my knowledge you have to intentionally do that with a cast.
Ignoring the issue of default, it would be still helpful to know at compile time if all enum cases are handled, but perhaps not in all cases. How could this be checked cleanly?
A similar case is when maintaining a parallel array:
char[][] name = [T.RED : "red", T.BLUE : "blue"];
How can we determine that GREEN is missing at compile time?
Comment #3 by smjg — 2007-10-10T18:32:53Z
(In reply to comment #2)
> I hadn't considered an enum instance containing an invalid value, though to my
> knowledge you have to intentionally do that with a cast.
My point is that it isn't necessarily invalid. And you don't need a cast. You can combine enum values with arithmetic or bitwise operations, for example. Hence my mention of bit flags.
> Ignoring the issue of default, it would be still helpful to know at compile
> time if all enum cases are handled, but perhaps not in all cases. How could
> this be checked cleanly?
I don't think there's any way we can be sure of considering all cases. But a possibility is to have a notation such as "switch enum (t)", such that it would be a compile-time error not to consider all named values of the enum (whether individually or with a default). This would be a form of syntactic salt similar to the override attribute.
> A similar case is when maintaining a parallel array:
>
> char[][] name = [T.RED : "red", T.BLUE : "blue"];
>
> How can we determine that GREEN is missing at compile time?
It used to be specified that an array must be initialised completely or not at all. See issue 508. But this was never implemented. Still, to work in this instance, either the array's length would have to be explicitly given as T.max + 1, or it would miss a missing index at the end.
Comment #4 by clugdbug — 2011-12-22T01:10:42Z
Fixed in D2 with 'final switch'.
It's WONTFIX for D1.