This code used to work (dmd circa 2.077):
-------
class B {
int w, h;
this(int width, int height) {
w = width;
h = height;
}
}
class C : B {
this(int size) {
int w, h;
if (size == 0) {
w = 10;
h = 20;
} else {
w = 20;
h = 10;
}
super(w, h); // OK
}
}
class D : B {
enum E { portrait, landscape }
this(E type) {
int w, h;
final switch (type) {
case E.portrait:
w = 10;
h = 20;
break;
case E.landscape:
w = 20;
h = 10;
break;
}
super(w, h); // NG (this is line 37)
}
}
-------
Now (on dmd git master) it triggers the following error:
-------
test.d(37): Error: constructor calls not allowed in loops or after labels
-------
Expected behaviour: since the switch statement has ended, the fact that there are switch labels ought not to influence whether calls to the superclass ctor are allowed or not, since it's not possible to jump out of the switch statement somewhere else. Furthermore, there are no loops involved, so there is no reason the superclass ctor can't be called at this point.
The switch is also functionally equivalent to the if-statement in class C's ctor, so there is no reason why it should make a difference in whether the superclass ctor can be called.
Comment #1 by hsteoh — 2018-08-29T18:42:54Z
This regression was introduced in 2.081. The code compiles fine in 2.080.
Comment #2 by razvan.nitu1305 — 2018-09-06T15:03:08Z
The constructor flow analysis is primitive, and whenever it sees a label it decides "could be a loop" and treats it as a loop. Case statements are indeed labels, as one can goto them.
The reason this code used to compile is because case statements were not checked - there could have been loops. This problem was fixed.
I'm going to redo this as an Enhancement Request for flow analysis in the constructors.
Comment #4 by robert.schadek — 2024-12-13T19:00:27Z