Skip to content

Commit

Permalink
[flang] Handle mismatches of procedure type args
Browse files Browse the repository at this point in the history
Fortran allows type mismatch when passing actual arguments to
procedures and most cases were already being handled correctly by
Flang. However, conversion of data types to and from procedures and
conversion between procedures and char procedures were not always
handled properly. The missing cases were added and these
conversions are supported now.

Fixes #60550

Reviewed By: jeanPerier

Differential Revision: https://reviews.llvm.org/D145601
  • Loading branch information
luporl committed Mar 14, 2023
1 parent 6603c68 commit bd94662
Show file tree
Hide file tree
Showing 3 changed files with 399 additions and 1 deletion.
29 changes: 28 additions & 1 deletion flang/lib/Lower/ConvertExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,18 @@ createBoxProcCharTuple(Fortran::lower::AbstractConverter &converter,
argTy.cast<mlir::TupleType>().getType(0).cast<fir::BoxProcType>();
mlir::Location loc = converter.getCurrentLocation();
auto &builder = converter.getFirOpBuilder();

// While character procedure arguments are expected here, Fortran allows
// actual arguments of other types to be passed instead.
// To support this, we cast any reference to the expected type or extract
// procedures from their boxes if needed.
mlir::Type fromTy = funcAddr.getType();
mlir::Type toTy = boxTy.getEleTy();
if (fir::isa_ref_type(fromTy))
funcAddr = builder.createConvert(loc, toTy, funcAddr);
else if (fromTy.isa<fir::BoxProcType>())
funcAddr = builder.create<fir::BoxAddrOp>(loc, toTy, funcAddr);

auto boxProc = [&]() -> mlir::Value {
if (auto host = Fortran::lower::argumentHostAssocs(converter, funcAddr))
return builder.create<fir::EmboxProcOp>(
Expand Down Expand Up @@ -2554,7 +2566,22 @@ class ScalarExprLowering {
arg.passBy == PassBy::CharBoxValueAttribute);
auto helper = fir::factory::CharacterExprHelper{builder, loc};
auto boxChar = argAddr.match(
[&](const fir::CharBoxValue &x) { return helper.createEmbox(x); },
[&](const fir::CharBoxValue &x) -> mlir::Value {
// If a character procedure was passed instead, handle the
// mismatch.
auto funcTy =
x.getAddr().getType().dyn_cast<mlir::FunctionType>();
if (funcTy && funcTy.getNumResults() == 1 &&
funcTy.getResult(0).isa<fir::BoxCharType>()) {
auto boxTy = funcTy.getResult(0).cast<fir::BoxCharType>();
mlir::Value ref = builder.createConvert(
loc, builder.getRefType(boxTy.getEleTy()), x.getAddr());
auto len = builder.create<fir::UndefOp>(
loc, builder.getCharacterLengthType());
return builder.create<fir::EmboxCharOp>(loc, boxTy, ref, len);
}
return helper.createEmbox(x);
},
[&](const fir::CharArrayBoxValue &x) {
return helper.createEmbox(x);
},
Expand Down
7 changes: 7 additions & 0 deletions flang/lib/Optimizer/Builder/FIRBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,13 @@ fir::FirOpBuilder::convertWithSemantics(mlir::Location loc, mlir::Type toTy,
"element types expected to match"));
return create<fir::BoxAddrOp>(loc, toTy, val);
}
if (fir::isa_ref_type(fromTy) && toTy.isa<fir::BoxProcType>()) {
// Call is expecting a boxed procedure, not a reference to other data type.
// Convert the reference to a procedure and embox it.
mlir::Type procTy = toTy.cast<fir::BoxProcType>().getEleTy();
mlir::Value proc = createConvert(loc, procTy, val);
return create<fir::EmboxProcOp>(loc, toTy, proc);
}

if ((fir::isPolymorphicType(fromTy) &&
(fir::isAllocatableType(fromTy) || fir::isPointerType(fromTy)) &&
Expand Down
Loading

0 comments on commit bd94662

Please sign in to comment.