@@ -970,6 +970,18 @@ mlir::Value static getZeroLowerBounds(mlir::Location loc,
970
970
return builder.genShift (loc, lowerBounds);
971
971
}
972
972
973
+ static bool
974
+ isSimplyContiguous (const Fortran::evaluate::ActualArgument &arg,
975
+ Fortran::evaluate::FoldingContext &foldingContext) {
976
+ if (const auto *expr = arg.UnwrapExpr ())
977
+ return Fortran::evaluate::IsSimplyContiguous (*expr, foldingContext);
978
+ const Fortran::semantics::Symbol *sym = arg.GetAssumedTypeDummy ();
979
+ assert (sym &&
980
+ " expect ActualArguments to be expression or assumed-type symbols" );
981
+ return sym->Rank () == 0 ||
982
+ Fortran::evaluate::IsSimplyContiguous (*sym, foldingContext);
983
+ }
984
+
973
985
// / When dummy is not ALLOCATABLE, POINTER and is not passed in register,
974
986
// / prepare the actual argument according to the interface. Do as needed:
975
987
// / - address element if this is an array argument in an elemental call.
@@ -985,7 +997,7 @@ static PreparedDummyArgument preparePresentUserCallActualArgument(
985
997
const Fortran::lower::PreparedActualArgument &preparedActual,
986
998
mlir::Type dummyType,
987
999
const Fortran::lower::CallerInterface::PassedEntity &arg,
988
- const Fortran::lower::SomeExpr &expr, CallContext &callContext) {
1000
+ CallContext &callContext) {
989
1001
990
1002
Fortran::evaluate::FoldingContext &foldingContext =
991
1003
callContext.converter .getFoldingContext ();
@@ -1036,7 +1048,7 @@ static PreparedDummyArgument preparePresentUserCallActualArgument(
1036
1048
const bool mustDoCopyInOut =
1037
1049
actual.isArray () && arg.mustBeMadeContiguous () &&
1038
1050
(passingPolymorphicToNonPolymorphic ||
1039
- !Fortran::evaluate::IsSimplyContiguous (expr , foldingContext));
1051
+ !isSimplyContiguous (*arg. entity , foldingContext));
1040
1052
1041
1053
const bool actualIsAssumedRank = actual.isAssumedRank ();
1042
1054
// Create dummy type with actual argument rank when the dummy is an assumed
@@ -1114,9 +1126,11 @@ static PreparedDummyArgument preparePresentUserCallActualArgument(
1114
1126
arg.mayBeModifiedByCall () ? copyIn.getVar () : mlir::Value{});
1115
1127
}
1116
1128
} else {
1129
+ const Fortran::lower::SomeExpr *expr = arg.entity ->UnwrapExpr ();
1130
+ assert (expr && " expression actual argument cannot be an assumed type" );
1117
1131
// The actual is an expression value, place it into a temporary
1118
1132
// and register the temporary destruction after the call.
1119
- mlir::Type storageType = callContext.converter .genType (expr);
1133
+ mlir::Type storageType = callContext.converter .genType (* expr);
1120
1134
mlir::NamedAttribute byRefAttr = fir::getAdaptToByRefAttr (builder);
1121
1135
hlfir::AssociateOp associate = hlfir::genAssociateExpr (
1122
1136
loc, builder, entity, storageType, " " , byRefAttr);
@@ -1202,7 +1216,7 @@ static PreparedDummyArgument preparePresentUserCallActualArgument(
1202
1216
if (auto baseBoxDummy = mlir::dyn_cast<fir::BaseBoxType>(dummyType))
1203
1217
if (baseBoxDummy.isAssumedRank ())
1204
1218
if (const Fortran::semantics::Symbol *sym =
1205
- Fortran::evaluate::UnwrapWholeSymbolDataRef (expr ))
1219
+ Fortran::evaluate::UnwrapWholeSymbolDataRef (*arg. entity ))
1206
1220
if (Fortran::semantics::IsAssumedSizeArray (sym->GetUltimate ()))
1207
1221
TODO (loc, " passing assumed-size to assumed-rank array" );
1208
1222
@@ -1224,10 +1238,10 @@ static PreparedDummyArgument prepareUserCallActualArgument(
1224
1238
const Fortran::lower::PreparedActualArgument &preparedActual,
1225
1239
mlir::Type dummyType,
1226
1240
const Fortran::lower::CallerInterface::PassedEntity &arg,
1227
- const Fortran::lower::SomeExpr &expr, CallContext &callContext) {
1241
+ CallContext &callContext) {
1228
1242
if (!preparedActual.handleDynamicOptional ())
1229
- return preparePresentUserCallActualArgument (
1230
- loc, builder, preparedActual, dummyType, arg, expr , callContext);
1243
+ return preparePresentUserCallActualArgument (loc, builder, preparedActual,
1244
+ dummyType, arg, callContext);
1231
1245
1232
1246
// Conditional dummy argument preparation. The actual may be absent
1233
1247
// at runtime, causing any addressing, copy, and packaging to have
@@ -1249,7 +1263,7 @@ static PreparedDummyArgument prepareUserCallActualArgument(
1249
1263
builder.setInsertionPointToStart (preparationBlock);
1250
1264
PreparedDummyArgument unconditionalDummy =
1251
1265
preparePresentUserCallActualArgument (loc, builder, preparedActual,
1252
- dummyType, arg, expr, callContext);
1266
+ dummyType, arg, callContext);
1253
1267
builder.restoreInsertionPoint (insertPt);
1254
1268
1255
1269
// TODO: when forwarding an optional to an optional of the same kind
@@ -1291,10 +1305,11 @@ static PreparedDummyArgument prepareProcedurePointerActualArgument(
1291
1305
const Fortran::lower::PreparedActualArgument &preparedActual,
1292
1306
mlir::Type dummyType,
1293
1307
const Fortran::lower::CallerInterface::PassedEntity &arg,
1294
- const Fortran::lower::SomeExpr &expr, CallContext &callContext) {
1308
+ CallContext &callContext) {
1295
1309
1296
1310
// NULL() actual to procedure pointer dummy
1297
- if (Fortran::evaluate::UnwrapExpr<Fortran::evaluate::NullPointer>(expr) &&
1311
+ if (Fortran::evaluate::UnwrapExpr<Fortran::evaluate::NullPointer>(
1312
+ *arg.entity ) &&
1298
1313
fir::isBoxProcAddressType (dummyType)) {
1299
1314
auto boxTy{Fortran::lower::getUntypedBoxProcType (builder.getContext ())};
1300
1315
auto tempBoxProc{builder.createTemporary (loc, boxTy)};
@@ -1335,9 +1350,6 @@ genUserCall(Fortran::lower::PreparedActualArguments &loweredActuals,
1335
1350
caller.placeInput (arg, builder.genAbsentOp (loc, argTy));
1336
1351
continue ;
1337
1352
}
1338
- const auto *expr = arg.entity ->UnwrapExpr ();
1339
- if (!expr)
1340
- TODO (loc, " assumed type actual argument" );
1341
1353
1342
1354
switch (arg.passBy ) {
1343
1355
case PassBy::Value: {
@@ -1380,15 +1392,15 @@ genUserCall(Fortran::lower::PreparedActualArguments &loweredActuals,
1380
1392
case PassBy::BaseAddress:
1381
1393
case PassBy::BoxChar: {
1382
1394
PreparedDummyArgument preparedDummy = prepareUserCallActualArgument (
1383
- loc, builder, *preparedActual, argTy, arg, *expr, callContext);
1395
+ loc, builder, *preparedActual, argTy, arg, callContext);
1384
1396
callCleanUps.append (preparedDummy.cleanups .rbegin (),
1385
1397
preparedDummy.cleanups .rend ());
1386
1398
caller.placeInput (arg, preparedDummy.dummy );
1387
1399
} break ;
1388
1400
case PassBy::BoxProcRef: {
1389
1401
PreparedDummyArgument preparedDummy =
1390
1402
prepareProcedurePointerActualArgument (loc, builder, *preparedActual,
1391
- argTy, arg, *expr, callContext);
1403
+ argTy, arg, callContext);
1392
1404
callCleanUps.append (preparedDummy.cleanups .rbegin (),
1393
1405
preparedDummy.cleanups .rend ());
1394
1406
caller.placeInput (arg, preparedDummy.dummy );
@@ -1408,6 +1420,9 @@ genUserCall(Fortran::lower::PreparedActualArguments &loweredActuals,
1408
1420
caller.placeInput (arg, actual);
1409
1421
} break ;
1410
1422
case PassBy::MutableBox: {
1423
+ const Fortran::lower::SomeExpr *expr = arg.entity ->UnwrapExpr ();
1424
+ // C709 and C710.
1425
+ assert (expr && " cannot pass TYPE(*) to POINTER or ALLOCATABLE" );
1411
1426
hlfir::Entity actual = preparedActual->getActual (loc, builder);
1412
1427
if (Fortran::evaluate::UnwrapExpr<Fortran::evaluate::NullPointer>(
1413
1428
*expr)) {
@@ -2405,8 +2420,34 @@ genProcedureRef(CallContext &callContext) {
2405
2420
caller.getPassedArguments ())
2406
2421
if (const auto *actual = arg.entity ) {
2407
2422
const auto *expr = actual->UnwrapExpr ();
2408
- if (!expr)
2409
- TODO (loc, " assumed type actual argument" );
2423
+ if (!expr) {
2424
+ // TYPE(*) actual argument.
2425
+ const Fortran::evaluate::Symbol *assumedTypeSym =
2426
+ actual->GetAssumedTypeDummy ();
2427
+ if (!assumedTypeSym)
2428
+ fir::emitFatalError (
2429
+ loc, " expected assumed-type symbol as actual argument" );
2430
+ std::optional<fir::FortranVariableOpInterface> var =
2431
+ callContext.symMap .lookupVariableDefinition (*assumedTypeSym);
2432
+ if (!var)
2433
+ fir::emitFatalError (loc, " assumed-type symbol was not lowered" );
2434
+ hlfir::Entity actual{*var};
2435
+ std::optional<mlir::Value> isPresent;
2436
+ if (arg.isOptional ()) {
2437
+ // Passing an optional TYPE(*) to an optional TYPE(*). Note that
2438
+ // TYPE(*) cannot be ALLOCATABLE/POINTER (C709) so there is no
2439
+ // need to cover the case of passing an ALLOCATABLE/POINTER to an
2440
+ // OPTIONAL.
2441
+ fir::FirOpBuilder &builder = callContext.getBuilder ();
2442
+ isPresent =
2443
+ builder.create <fir::IsPresentOp>(loc, builder.getI1Type (), actual)
2444
+ .getResult ();
2445
+ }
2446
+ loweredActuals.push_back (Fortran::lower::PreparedActualArgument{
2447
+ hlfir::Entity{*var}, isPresent});
2448
+ continue ;
2449
+ }
2450
+
2410
2451
if (Fortran::evaluate::UnwrapExpr<Fortran::evaluate::NullPointer>(
2411
2452
*expr)) {
2412
2453
if ((arg.passBy !=
0 commit comments