Add validator test for OpBranch

Add test for case where OpBranch branches to a value (a function value).
Previous tests only checked a label value (name of a block.).

Update validate_id.cpp to remove the TODO for OpBranch and say that it
is already checked in validate_cfg.cpp
This commit is contained in:
David Neto 2018-04-12 14:47:53 -04:00
parent d42f65e7c1
commit e8814be732
3 changed files with 35 additions and 11 deletions

View File

@ -261,11 +261,16 @@ spv_result_t PerformCfgChecks(ValidationState_t& _) {
// Check all referenced blocks are defined within a function
if (function.undefined_block_count() != 0) {
string undef_blocks("{");
bool first = true;
for (auto undefined_block : function.undefined_blocks()) {
undef_blocks += _.getIdName(undefined_block) + " ";
undef_blocks += _.getIdName(undefined_block);
if (!first) {
undef_blocks += " ";
}
first = false;
}
return _.diag(SPV_ERROR_INVALID_CFG)
<< "Block(s) " << undef_blocks << "\b}"
<< "Block(s) " << undef_blocks << "}"
<< " are referenced but not defined in function "
<< _.getIdName(function.id());
}

View File

@ -1870,12 +1870,6 @@ bool idUsage::isValid<OpSelectionMerge>(
const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
#endif
#if 0
template <>
bool idUsage::isValid<OpBranch>(const spv_instruction_t *inst,
const spv_opcode_desc opcodeEntry) {}
#endif
template <>
bool idUsage::isValid<SpvOpBranchConditional>(const spv_instruction_t* inst,
const spv_opcode_desc) {
@ -2426,7 +2420,8 @@ bool idUsage::isValid(const spv_instruction_t* inst) {
CASE(OpPhi)
TODO(OpLoopMerge)
TODO(OpSelectionMerge)
TODO(OpBranch)
// OpBranch is validated in validate_cfg.cpp.
// See tests in test/val/val_cfg_test.cpp.
CASE(OpBranchConditional)
TODO(OpSwitch)
CASE(OpReturnValue)

View File

@ -453,7 +453,7 @@ TEST_P(ValidateCFG, MergeBlockTargetedByMultipleHeaderBlocksSelectionBad) {
}
}
TEST_P(ValidateCFG, BranchTargetFirstBlockBad) {
TEST_P(ValidateCFG, BranchTargetFirstBlockBadSinceEntryBlock) {
Block entry("entry");
Block bad("bad");
Block end("end", SpvOpReturn);
@ -473,6 +473,30 @@ TEST_P(ValidateCFG, BranchTargetFirstBlockBad) {
"is targeted by block .\\[bad\\]"));
}
TEST_P(ValidateCFG, BranchTargetFirstBlockBadSinceValue) {
Block entry("entry");
Block bad("bad");
Block end("end", SpvOpReturn);
Block badvalue("func"); // This referenes the function name.
string str = header(GetParam()) +
nameOps("entry", "bad", make_pair("func", "Main")) +
types_consts() + "%func = OpFunction %voidt None %funct\n";
str += entry >> bad;
str +=
bad >> badvalue; // Check branch to a function value (it's not a block!)
str += end;
str += "OpFunctionEnd\n";
CompileSuccessfully(str);
ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
EXPECT_THAT(
getDiagnosticString(),
MatchesRegex("Block\\(s\\) \\{.\\[Main\\]\\} are referenced but not "
"defined in function .\\[Main\\]"))
<< str;
}
TEST_P(ValidateCFG, BranchConditionalTrueTargetFirstBlockBad) {
Block entry("entry");
Block bad("bad", SpvOpBranchConditional);
@ -589,7 +613,7 @@ TEST_P(ValidateCFG, BranchToBlockInOtherFunctionBad) {
ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
EXPECT_THAT(
getDiagnosticString(),
MatchesRegex("Block\\(s\\) \\{.\\[middle2\\] .\\} are referenced but not "
MatchesRegex("Block\\(s\\) \\{.\\[middle2\\]\\} are referenced but not "
"defined in function .\\[Main\\]"));
}