Repository: llvm/llvm-project
File: mlir/lib/Dialect/Func/IR/FuncOps.cpp (C++)

Code before:

  /// Clone the current function into the new one and return it.
  cloneInto(newFunc, mapper);
  return newFunc;
}
FuncOp FuncOp::clone() {
  IRMapping mapper;
  return clone(mapper);
}

//===----------------------------------------------------------------------===//
// ReturnOp
//===----------------------------------------------------------------------===//

LogicalResult ReturnOp::verify() {
  auto function = cast<FuncOp>((*this)->getParentOp());

  // The operand number and types must match the function signature.
  const auto &results = function.getFunctionType().getResults();
  if (getNumOperands() != results.size())
    return emitOpError("has ")
           << getNumOperands() << " operands, but enclosing function (@"
           << function.getName() << ") returns " << results.size();

  for (unsigned i = 0, e = results.size(); i != e; ++i)
    if (getOperand(i).getType() != results[i])
      return emitError() << "type of return operand " << i << " ("
                         << getOperand(i).getType()
                         << ") doesn't match function result type ("
                         << results[i] << ")"
                         << " in function @" << function.getName();

  return success();
}

//===----------------------------------------------------------------------===//
// TableGen'd op method definitions
//===----------------------------------------------------------------------===//

#define GET_OP_CLASSES
#include "mlir/Dialect/Func/IR/FuncOps.cpp.inc"


Review comment (suggestion):
Would be nice if we could limit return-like terminators to `func.return` in the future.

Code after:

  /// Clone the current function into the new one and return it.
  cloneInto(newFunc, mapper);
  return newFunc;
}
FuncOp FuncOp::clone() {
  IRMapping mapper;
  return clone(mapper);
}

//===----------------------------------------------------------------------===//
// ReturnOp
//===----------------------------------------------------------------------===//

LogicalResult FuncOp::verify() {
  // External declarations have no body to check.
  if (isDeclaration())
    return success();
  // Hoist the result types once; they are the same for every return site.
  auto resultTypes = getFunctionType().getResults();
  for (Block &block : getBody()) {
    if (block.empty())
      continue;
    // Check func.return or other return-like terminators ops (e.g.
    // llvm.return, test.return).
    auto returnOp = dyn_cast<RegionBranchTerminatorOpInterface>(&block.back());
    if (!returnOp)
      continue;

    if (returnOp->getNumOperands() != resultTypes.size())
      return returnOp->emitOpError("has ")
             << returnOp->getNumOperands()
             << " operands, but enclosing function (@" << getName()
             << ") returns " << resultTypes.size();

    for (auto [i, opType] :
         llvm::enumerate(llvm::zip(returnOp->getOperandTypes(), resultTypes))) {
      auto [opTy, resTy] = opType;
      if (opTy != resTy)
        return returnOp->emitError()
               << "type of return operand " << i << " (" << opTy
               << ") doesn't match function result type (" << resTy
               << ") in function @" << getName();
    }
  }

  return success();
}

//===----------------------------------------------------------------------===//
// TableGen'd op method definitions