This was left as a TODO in the code. Move the type verification from
MLFuncVerifier::verifyReturn to ReturnOp::verify. Since the return operation
can only appear as the last statement of an MLFunction, i.e. where the
surrounding block is the function itself, it is easy to access the function
descriptor (ReturnOp::verify already relies on this). From the function
descriptor, one can easily access the type information. Note that this
slightly modifies the error message due to the use of emitOpError instead of a
plain emitError.
Drop the obsolete TODO comment in MLFunction::verify about checking that
"return" only appears as the last operation of an MLFunction since
ReturnOp::verify explicitly checks for that.
PiperOrigin-RevId:
218347843
if (hadError)
return true;
- // TODO: check that operation is not a return statement unless it's
- // the last one in the function.
// TODO: check that loop bounds and if conditions are properly formed.
if (verifyReturn())
return true;
if (!op->isReturn())
return failure(missingReturnMsg, fn);
- // The operand number and types must match the function signature.
- // TODO: move this verification in ReturnOp::verify() if printing
- // of the error messages below can be made to work there.
- const auto &results = fn.getType()->getResults();
- if (op->getNumOperands() != results.size())
- return failure("return has " + Twine(op->getNumOperands()) +
- " operands, but enclosing function returns " +
- Twine(results.size()),
- *op);
-
- for (unsigned i = 0, e = results.size(); i != e; ++i)
- if (op->getOperand(i)->getType() != results[i])
- return failure("type of return operand " + Twine(i) +
- " doesn't match function result type",
- *op);
return false;
}
return failure(missingReturnMsg, fn);
if (!block || !isa<MLFunction>(block) || &block->back() != stmt)
return emitOpError("must be the last statement in the ML function");
+ // The operand number and types must match the function signature.
+ MLFunction *function = cast<MLFunction>(block);
+ const auto &results = function->getType()->getResults();
+ if (stmt->getNumOperands() != results.size())
+ return emitOpError("has " + Twine(stmt->getNumOperands()) +
+ " operands, but enclosing function returns " +
+ Twine(results.size()));
+
+ for (unsigned i = 0, e = results.size(); i != e; ++i)
+ if (stmt->getOperand(i)->getType() != results[i]) {
+ emitError("type of return operand " + Twine(i) +
+ " doesn't match function result type");
+ return true;
+ }
+
// Return success. Checking that operand types match those in the function
// signature is performed in the ML function verifier.
return false;
}
return emitOpError("cannot occur in a CFG function");
}
-
// -----
mlfunc @mlfunc_resulterror() -> i32 {
- return // expected-error {{return has 0 operands, but enclosing function returns 1}}
+ return // expected-error {{'return' op has 0 operands, but enclosing function returns 1}}
}
// -----