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 @@ -2007,7 +2007,21 @@ } mlir::Location loc = toLocation(); if (stmt.v) { - TODO(loc, "Alternate return statement"); + // Alternate return statement - If this is a subroutine where some + // alternate entries have alternate returns, but the active entry point + // does not, ignore the alternate return value. Otherwise, assign it + // to the compiler-generated result variable. + const Fortran::semantics::Symbol &symbol = funit->getSubprogramSymbol(); + if (Fortran::semantics::HasAlternateReturns(symbol)) { + Fortran::lower::StatementContext stmtCtx; + const Fortran::lower::SomeExpr *expr = + Fortran::semantics::GetExpr(*stmt.v); + assert(expr && "missing alternate return expression"); + mlir::Value altReturnIndex = builder->createConvert( + loc, builder->getIndexType(), createFIRExpr(loc, expr, stmtCtx)); + builder->create(loc, altReturnIndex, + getAltReturnResult(symbol)); + } } // Branch to the last block of the SUBROUTINE, which has the actual return. if (!funit->finalBlock) { diff --git a/flang/test/Lower/alternate-return.f90 b/flang/test/Lower/alternate-return.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Lower/alternate-return.f90 @@ -0,0 +1,49 @@ +! RUN: bbc -emit-fir -o - %s | FileCheck %s + +! CHECK-LABEL: func @_QPss +subroutine ss(n) + print*, n + ! CHECK: return{{$}} + return + ! CHECK-LABEL: func @_QPee + entry ee(n,*) + print*, n + ! CHECK: return %{{.}} : index + return 1 + end + + ! CHECK-LABEL: func @_QQmain + call ss(7) + call ee(2, *3) + print*, 'default' + 3 print*, 3 + + print*, k(10,20) + print*, k(15,15) + print*, k(20,10) + end + + ! CHECK-LABEL: func @_QPk + function k(n1, n2) + ! CHECK-NOT: ^bb + ! CHECK: [[selector:%[0-9]+]] = fir.call @_QPs + ! CHECK-NEXT: fir.select [[selector]] : index [1, ^[[block1:bb[0-9]+]], 2, ^[[block2:bb[0-9]+]], unit, ^[[blockunit:bb[0-9]+]] + call s(n1, *5, n2, *7) + ! CHECK: ^[[blockunit]]: // pred: ^bb0 + k = 0; return; + ! CHECK: ^[[block1]]: // pred: ^bb0 + 5 k = -1; return; + ! CHECK: ^[[block2]]: // pred: ^bb0 + 7 k = 1; return + end + + ! CHECK-LABEL: func @_QPs + subroutine s(n1, *, n2, *) + ! CHECK: [[retval:%[0-9]+]] = fir.alloca index {{{.*}}bindc_name = "s"} + ! CHECK-COUNT-3: fir.store {{.*}} to [[retval]] : !fir.ref + if (n1 < n2) return 1 + if (n1 > n2) return 2 + ! CHECK: {{.*}} = fir.load [[retval]] : !fir.ref + ! CHECK-NEXT: return {{.*}} : index + return + end