Verify that ReturnOp only appears within the region of a FuncOp.
authorRiver Riddle <riverriddle@google.com>
Tue, 16 Jul 2019 19:45:05 +0000 (12:45 -0700)
committerMehdi Amini <joker.eph@gmail.com>
Tue, 16 Jul 2019 20:45:54 +0000 (13:45 -0700)
The invariants of ReturnOp are directly tied to FuncOp, making ReturnOp invalid in any other context.

PiperOrigin-RevId: 258421200

mlir/include/mlir/IR/OpDefinition.h
mlir/lib/StandardOps/Ops.cpp
mlir/test/IR/invalid-ops.mlir

index 32f7efa..c275d03 100644 (file)
@@ -71,7 +71,11 @@ public:
   /// Return the operation that this refers to.
   Operation *getOperation() { return state; }
 
-  /// Return the closes surrounding parent operation that is of type 'OpTy'.
+  /// Returns the closest surrounding operation that contains this operation
+  /// or nullptr if this is a top-level operation.
+  Operation *getParentOp() { return getOperation()->getParentOp(); }
+
+  /// Return the closest surrounding parent operation that is of type 'OpTy'.
   template <typename OpTy> OpTy getParentOfType() {
     return getOperation()->getParentOfType<OpTy>();
   }
index 2fa37ff..738446a 100644 (file)
@@ -1868,9 +1868,9 @@ static void print(OpAsmPrinter *p, ReturnOp op) {
 }
 
 static LogicalResult verify(ReturnOp op) {
-  // TODO(b/137008268): Return op should verify that it is nested directly
-  // within a function operation.
-  auto function = op.getParentOfType<FuncOp>();
+  auto function = dyn_cast_or_null<FuncOp>(op.getParentOp());
+  if (!function)
+    return op.emitOpError() << "must be nested within a 'func' region";
 
   // The operand number and types must match the function signature.
   const auto &results = function.getType().getResults();
index c13514f..2991d12 100644 (file)
@@ -811,3 +811,13 @@ func @std_if_illegal_block_argument(%arg0: i1) {
   }, {}): (i1) -> ()
   return
 }
+
+// -----
+
+func @return_not_in_function() {
+  "foo.region"() ({
+    // expected-error@+1 {{must be nested within a 'func' region}}
+    return
+  }): () -> ()
+  return
+}