spirv-reader: add test for bad continue-block from single-block loop

Prove this error is caught by SPIR-V validation.
This requires a recent version of SPIRV-Tools.

Fixed: tint:793
Change-Id: I30977de7c4d1c291ab9ea13df80189426a842521
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/51040
Auto-Submit: David Neto <dneto@google.com>
Commit-Queue: Alan Baker <alanbaker@google.com>
Reviewed-by: Alan Baker <alanbaker@google.com>
diff --git a/src/reader/spirv/function_cfg_test.cc b/src/reader/spirv/function_cfg_test.cc
index ca042cf..044e7ae 100644
--- a/src/reader/spirv/function_cfg_test.cc
+++ b/src/reader/spirv/function_cfg_test.cc
@@ -14759,6 +14759,52 @@
   ASSERT_EQ(expect, got) << got;
 }
 
+TEST_F(SpvParserCFGTest,
+       EmitBody_ContinueFromSingleBlockLoopToOuterLoop_IsError) {
+  // crbug.com/tint/793
+  // This is invalid SPIR-V but the validator was only recently upgraded
+  // to catch it.
+  auto assembly = CommonTypes() + R"(
+  %100 = OpFunction %void None %voidfn
+  %5 = OpLabel
+  OpBranch %10
+
+  %10 = OpLabel ; outer loop header
+  OpLoopMerge %99 %89 None
+  OpBranchConditional %cond %99 %20
+
+  %20 = OpLabel ; inner loop single block loop
+  OpLoopMerge %79 %20 None
+
+  ; true -> continue to outer loop
+  ; false -> self-loop
+  ; The true branch is invalid because a "continue block", i.e. the block
+  ; containing the branch to the continue target, "is valid only for the
+  ; innermost loop it is nested inside of".
+  ; So it can't branch to the continue target of an outer loop.
+  OpBranchConditional %cond %89 %20
+
+  %79 = OpLabel ; merge for outer loop
+  OpUnreachable
+
+  %89 = OpLabel
+  OpBranch %10 ; backedge for outer loop
+
+  %99 = OpLabel ; merge for outer
+  OpReturn
+
+  OpFunctionEnd
+
+)";
+  auto p = parser(test::Assemble(assembly));
+  EXPECT_FALSE(p->Parse());
+  EXPECT_FALSE(p->success());
+  EXPECT_THAT(p->error(),
+              HasSubstr("block <ID> 20[%20] exits the continue headed by <ID> "
+                        "20[%20], but not via a structured exit"))
+      << p->error();
+}
+
 }  // namespace
 }  // namespace spirv
 }  // namespace reader