Remove merge assert in block calculation (#2489)
Fixes #2488
* Validator doesn't identify back-edge of the loop, so the merge is
never set
* Construct::blocks() has safe uses of `merge` so the assert can be
removed
* Added a test
diff --git a/source/val/construct.cpp b/source/val/construct.cpp
index 7b0cb2d..e0053ee 100644
--- a/source/val/construct.cpp
+++ b/source/val/construct.cpp
@@ -73,7 +73,6 @@
auto header = entry_block();
auto merge = exit_block();
assert(header);
- assert(merge);
int header_depth = function->GetBlockDepth(const_cast<BasicBlock*>(header));
ConstructBlockSet construct_blocks;
std::unordered_set<BasicBlock*> corresponding_headers;
diff --git a/test/val/val_cfg_test.cpp b/test/val/val_cfg_test.cpp
index 7e7dae8..8f39a00 100644
--- a/test/val/val_cfg_test.cpp
+++ b/test/val/val_cfg_test.cpp
@@ -2987,6 +2987,39 @@
"Statically reachable blocks cannot be terminated by OpUnreachable"));
}
+TEST_F(ValidateCFG, UnreachableLoopBadBackedge) {
+ const std::string text = R"(
+OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %2 "main"
+OpExecutionMode %2 OriginUpperLeft
+%4 = OpTypeVoid
+%5 = OpTypeFunction %4
+%8 = OpTypeBool
+%13 = OpConstantTrue %8
+%2 = OpFunction %4 None %5
+%14 = OpLabel
+OpSelectionMerge %15 None
+OpBranchConditional %13 %15 %15
+%16 = OpLabel
+OpLoopMerge %17 %18 None
+OpBranch %17
+%18 = OpLabel
+OpBranch %17
+%17 = OpLabel
+OpBranch %15
+%15 = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+ // The back-edge in this test is bad, but the validator fails to identify it
+ // because it is in an entirely unreachable section of code. Prior to #2488
+ // this code failed an assert in Construct::blocks().
+ CompileSuccessfully(text);
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
TEST_F(ValidateCFG, OneContinueTwoBackedges) {
const std::string text = R"(
OpCapability Shader