diff --git a/flang/lib/Optimizer/Builder/MutableBox.cpp b/flang/lib/Optimizer/Builder/MutableBox.cpp --- a/flang/lib/Optimizer/Builder/MutableBox.cpp +++ b/flang/lib/Optimizer/Builder/MutableBox.cpp @@ -640,14 +640,17 @@ auto idxTy = builder.getIndexType(); if (auto charTy = box.getEleTy().dyn_cast()) { if (charTy.getLen() == fir::CharacterType::unknownLen()) { - if (box.hasNonDeferredLenParams()) + if (box.hasNonDeferredLenParams()) { lengths.emplace_back( builder.createConvert(loc, idxTy, box.nonDeferredLenParams()[0])); - else if (!lenParams.empty()) - lengths.emplace_back(builder.createConvert(loc, idxTy, lenParams[0])); - else + } else if (!lenParams.empty()) { + mlir::Value len = + fir::factory::genMaxWithZero(builder, loc, lenParams[0]); + lengths.emplace_back(builder.createConvert(loc, idxTy, len)); + } else { fir::emitFatalError( loc, "could not deduce character lengths in character allocation"); + } } } return lengths; @@ -682,10 +685,13 @@ mlir::ValueRange lenParams, llvm::StringRef allocName) { auto lengths = getNewLengths(builder, loc, box, lenParams); + llvm::SmallVector safeExtents; + for (mlir::Value extent : extents) + safeExtents.push_back(fir::factory::genMaxWithZero(builder, loc, extent)); auto heap = builder.create(loc, box.getBaseTy(), allocName, - lengths, extents); - MutablePropertyWriter{builder, loc, box}.updateMutableBox(heap, lbounds, - extents, lengths); + lengths, safeExtents); + MutablePropertyWriter{builder, loc, box}.updateMutableBox( + heap, lbounds, safeExtents, lengths); if (box.getEleTy().isa()) { // TODO: skip runtime initialization if this is not required. Currently, // there is no way to know here if a derived type needs it or not. But the diff --git a/flang/test/Lower/allocatables.f90 b/flang/test/Lower/allocatables.f90 --- a/flang/test/Lower/allocatables.f90 +++ b/flang/test/Lower/allocatables.f90 @@ -42,7 +42,9 @@ ! CHECK-DAG: %[[c42:.*]] = fir.convert %c42{{.*}} : (i32) -> index ! CHECK-DAG: %[[c100:.*]] = fir.convert %c100_i32 : (i32) -> index ! CHECK-DAG: %[[diff:.*]] = arith.subi %[[c100]], %[[c42]] : index - ! CHECK: %[[extent:.*]] = arith.addi %[[diff]], %c1{{.*}} : index + ! CHECK: %[[rawExtent:.*]] = arith.addi %[[diff]], %c1{{.*}} : index + ! CHECK: %[[extentPositive:.*]] = arith.cmpi sgt, %[[rawExtent]], %c0{{.*}} : index + ! CHECK: %[[extent:.*]] = arith.select %[[extentPositive]], %[[rawExtent]], %c0{{.*}} : index ! CHECK: %[[alloc:.*]] = fir.allocmem !fir.array, %[[extent]] {{{.*}}uniq_name = "_QFfoodim1Ex.alloc"} ! CHECK-DAG: fir.store %[[alloc]] to %[[xAddrVar]] : !fir.ref>> ! CHECK-DAG: fir.store %[[extent]] to %[[xExtVar]] : !fir.ref @@ -86,7 +88,9 @@ ! CHECK: fir.freemem %{{.*}} allocate(character(n):: c) ! CHECK: %[[n:.*]] = fir.load %arg0 : !fir.ref - ! CHECK: %[[ni:.*]] = fir.convert %[[n]] : (i32) -> index + ! CHECK: %[[nPositive:.*]] = arith.cmpi sgt, %[[n]], %c0{{.*}} : i32 + ! CHECK: %[[ns:.*]] = arith.select %[[nPositive]], %[[n]], %c0{{.*}} : i32 + ! CHECK: %[[ni:.*]] = fir.convert %[[ns]] : (i32) -> index ! CHECK: fir.allocmem !fir.char<1,?>(%[[ni]] : index) {{{.*}}uniq_name = "_QFchar_deferredEc.alloc"} ! CHECK: fir.store %[[ni]] to %[[cLenVar]] : !fir.ref