Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion src/cxxcompiler/subcompilers/Expressions.hx
Original file line number Diff line number Diff line change
Expand Up @@ -1861,7 +1861,15 @@ class Expressions extends SubCompiler {
result += "switch(" + generateCppForStringLength("__temp") + ") {";
for(length => lengthCases in lengths) {
result += "\n\tcase " + length + ": {\n";
result += compileSwitchAsIfs("__temp", eType, lengthCases, null, false).tab(2);
// Pass `edef` so each length-bucket's if-cascade ends with
// the user's default branch. Without this an input whose
// length matches a bucket but whose value matches no case
// inside it falls through with no statement executed —
// silently breaking `switch (s) { case "A": …; default: … }`
// when `s` is, say, "B" (same length as the case but not
// in the bucket), and tripping `-Werror=return-type` when
// the switch is a value position.
result += compileSwitchAsIfs("__temp", eType, lengthCases, edef, false).tab(2);
result += "\n\t\tbreak;";
result += "\n\t}";
}
Expand Down
35 changes: 35 additions & 0 deletions test/unit_testing/tests/Switch/Main.hx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,29 @@ function assert(b: Bool) {
}
}

// Statement-position string switch with a default. The bucket for
// length 1 contains both "A" and "B"; any other length-1 input
// must hit the default.
function stmtSwitch(s: String): String {
var matched = "?";
switch(s) {
case "A": matched = "A";
case "B": matched = "B";
default: matched = "default";
}
return matched;
}

// Value-position string switch — every path must yield an `Int`,
// otherwise the codegen trips `-Werror=return-type`.
function valueSwitch(s: String): Int {
return switch(s) {
case "A": 1;
case "B": 2;
case _: 99;
}
}

enum Test {
One;
Two;
Expand Down Expand Up @@ -38,6 +61,18 @@ function main() {
case "Blablabla": assert(false);
}

// String switch with same-length cases + default: exercises the
// `compileSwitchOptimizedForStrings` length-bucketed path. Inputs
// matching a bucket's length but no case inside it must fall
// through to `default`. Wrapped in helper functions so each
// emits its own `__temp` (the codegen declares the temp at
// function scope; calling one switch then another from `main`
// would collide).
assert(stmtSwitch("C") == "default");
assert(stmtSwitch("A") == "A");
assert(valueSwitch("C") == 99);
assert(valueSwitch("B") == 2);

// ---

final result = switch(a) {
Expand Down
2 changes: 2 additions & 0 deletions test/unit_testing/tests/Switch/intended/include/Main.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ class Main_Fields_ {
static int returnCode;

static void assert(bool b);
static std::string stmtSwitch(std::string s);
static int valueSwitch(std::string s);
static void main();
};

Expand Down
53 changes: 53 additions & 0 deletions test/unit_testing/tests/Switch/intended/src/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,54 @@ void _Main::Main_Fields_::assert(bool b) {
};
}

std::string _Main::Main_Fields_::stmtSwitch(std::string s) {
std::string matched = "?"s;

auto __temp = s;
switch(__temp.size()) {
case 1: {
if(__temp == "A"s) {
matched = "A"s;
} else if(__temp == "B"s) {
matched = "B"s;
} else {
matched = "default"s;
}
break;
}
default: {
matched = "default"s;
break;
}
};

return matched;
}

int _Main::Main_Fields_::valueSwitch(std::string s) {
int tempResult = 0;

auto __temp = s;
switch(__temp.size()) {
case 1: {
if(__temp == "A"s) {
tempResult = 1;
} else if(__temp == "B"s) {
tempResult = 2;
} else {
tempResult = 99;
}
break;
}
default: {
tempResult = 99;
break;
}
};

return tempResult;
}

void _Main::Main_Fields_::main() {
int a = 123;

Expand Down Expand Up @@ -76,6 +124,11 @@ void _Main::Main_Fields_::main() {
default: {}
};

_Main::Main_Fields_::assert(_Main::Main_Fields_::stmtSwitch("C"s) == "default"s);
_Main::Main_Fields_::assert(_Main::Main_Fields_::stmtSwitch("A"s) == "A"s);
_Main::Main_Fields_::assert(_Main::Main_Fields_::valueSwitch("C"s) == 99);
_Main::Main_Fields_::assert(_Main::Main_Fields_::valueSwitch("B"s) == 2);

int tempNumber = 0;

switch(a) {
Expand Down