diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -2133,6 +2133,7 @@ llvm::SmallVector attrList; llvm::SmallVector blockList; unsigned typeGuardIdx = 0; + std::size_t defaultAttrPos = std::numeric_limits::max(); bool hasLocalScope = false; for (Fortran::lower::pft::Evaluation &eval : @@ -2162,6 +2163,9 @@ // CLASS DEFAULT if (std::holds_alternative(guard.u)) { defaultBlock = e->block; + // Keep track of the actual position of the CLASS DEFAULT type guard + // in the SELECT TYPE construct. + defaultAttrPos = attrList.size(); continue; } @@ -2197,6 +2201,21 @@ blockList.push_back(defaultBlock); builder->create(loc, fir::getBase(selector), attrList, blockList); + + // If the actual position of CLASS DEFAULT type guard is not the last + // one, it needs to be put back at its correct position for the rest of + // the processing. TypeGuardStmt are processed in the same order they + // appear in the Fortran code. + if (defaultAttrPos < attrList.size() - 1) { + auto attrIt = attrList.begin(); + attrIt = attrIt + defaultAttrPos; + auto blockIt = blockList.begin(); + blockIt = blockIt + defaultAttrPos; + attrList.insert(attrIt, mlir::UnitAttr::get(context)); + blockList.insert(blockIt, defaultBlock); + attrList.pop_back(); + blockList.pop_back(); + } } else if (auto *typeGuardStmt = eval.getIf()) { // Map the type guard local symbol for the selector to a more precise diff --git a/flang/test/Lower/select-type.f90 b/flang/test/Lower/select-type.f90 --- a/flang/test/Lower/select-type.f90 +++ b/flang/test/Lower/select-type.f90 @@ -722,6 +722,40 @@ ! CHECK: ^bb{{.*}}: // pred: ^bb0 ! CHECK: %[[EXACT_BOX:.*]] = fir.convert %[[SELECTOR]] : (!fir.class>>) -> !fir.box>> + + ! Test correct lowering when CLASS DEFAULT is not at the last position in the + ! SELECT TYPE construct. + subroutine select_type13(a) + class(p1), pointer :: a(:) + select type (a) + class default + print*, 'default' + class is (p1) + print*, 'class' + end select + + select type (a) + type is (p1) + print*, 'type' + class default + print*, 'default' + class is (p1) + print*, 'class' + end select + + end subroutine + +! CHECK-LABEL: func.func @_QMselect_type_lower_testPselect_type13 +! CHECK: fir.select_type %{{.*}} : !fir.class>> [#fir.class_is>, ^bb2, unit, ^bb1] +! CHECK: ^bb1: +! CHECK: ^bb2: +! CHECK: ^bb3: +! CHECK: fir.select_type %{{.*}} : !fir.class>> [#fir.type_is>, ^bb4, #fir.class_is>, ^bb6, unit, ^bb5] +! CHECK: ^bb4: +! CHECK: ^bb5: +! CHECK: ^bb6: +! CHECK: ^bb7: + end module program test_select_type