template <typename TerminatorTy>
static TerminatorTy verifyAndGetTerminator(scf::WhileOp op, Region ®ion,
StringRef errorMessage) {
- Operation *terminatorOperation = region.front().getTerminator();
- if (auto yield = dyn_cast_or_null<TerminatorTy>(terminatorOperation))
- return yield;
-
+ Operation *terminatorOperation = nullptr;
+ if (!region.empty() && !region.front().empty()) {
+ terminatorOperation = ®ion.front().back();
+ if (auto yield = dyn_cast_or_null<TerminatorTy>(terminatorOperation))
+ return yield;
+ }
auto diag = op.emitOpError(errorMessage);
if (terminatorOperation)
diag.attachNote(terminatorOperation->getLoc()) << "terminator here";
// -----
+func.func @while_empty_region() {
+ // expected-error@+1 {{'scf.while' op region #0 ('before') failed to verify constraint: region with 1 blocks}}
+ scf.while : () -> () {
+ } do {
+ }
+}
+
+// -----
+
+func.func @while_empty_block() {
+ // expected-error@+1 {{expects the 'before' region to terminate with 'scf.condition'}}
+ scf.while : () -> () {
+ ^bb0:
+ } do {
+ ^bb0:
+ }
+}
+
+// -----
+
func.func @while_cross_region_type_mismatch() {
%true = arith.constant true
// expected-error@+1 {{'scf.while' op region control flow edge from Region #0 to Region #1: source has 0 operands, but target successor needs 1}}