Fix ForStmt and StmtBlock destructors.

Comments included are self-explanatory.

PiperOrigin-RevId: 207198873
diff --git a/include/mlir/IR/Statements.h b/include/mlir/IR/Statements.h
index 2ce17f5..c324f72 100644
--- a/include/mlir/IR/Statements.h
+++ b/include/mlir/IR/Statements.h
@@ -200,12 +200,14 @@
                    AffineConstantExpr *upperBound, AffineConstantExpr *step,
                    MLIRContext *context);
 
-  // Loop bounds and step are immortal objects and don't need to be deleted.
-  // With this dtor, ForStmt needs to inherit from MLValue before it does from
-  // StmtBlock since an MLValue can't be destroyed before the StmtBlock is ---
-  // the latter has uses for the induction variables, which is actually the
-  // MLValue here. FIXME: this dtor.
-  ~ForStmt() {}
+  ~ForStmt() {
+    // Loop bounds and step are immortal objects and don't need to be deleted.
+
+    // Explicitly erase statements instead of relying of 'StmtBlock' destructor
+    // since child statements need to be destroyed before the MLValue that this
+    // for stmt represents is destroyed.
+    getStatements().clear();
+  }
 
   AffineConstantExpr *getLowerBound() const { return lowerBound; }
   AffineConstantExpr *getUpperBound() const { return upperBound; }
diff --git a/include/mlir/IR/StmtBlock.h b/include/mlir/IR/StmtBlock.h
index fb94e23..609aabb 100644
--- a/include/mlir/IR/StmtBlock.h
+++ b/include/mlir/IR/StmtBlock.h
@@ -40,6 +40,15 @@
     IfClause // IfClause
   };
 
+  ~StmtBlock() { clear(); }
+
+  void clear() {
+    // Clear statements in the reverse order so that uses are destroyed
+    // before their defs.
+    while (!empty())
+      statements.pop_back();
+  }
+
   StmtBlockKind getStmtBlockKind() const { return kind; }
 
   /// Returns the closest surrounding statement that contains this block or