From 30f7a6cc42856d2028bfd00321ddb1428e0c46aa Mon Sep 17 00:00:00 2001 From: Asher Mancinelli Date: Thu, 8 May 2025 06:36:39 -0700 Subject: [PATCH] [flang] Correctly prepare allocatable runtime call arguments (#138727) When lowering allocatables, the generated calls to runtime functions were not using the runtime::createArguments utility which handles the required conversions. createArguments is where I added the implicit volatile casts to handle converting volatile variables to the appropriate type based on their volatility in the callee. Because the calls to allocatable runtime functions were not using this function, their arguments were not casted to have the appropriate volatility. Add a test to demonstrate that volatile and allocatable class/box/reference types are appropriately casted before calling into the runtime library. Instead of using a recursive variadic template to perform the conversions in createArguments, map over the arguments directly so that createArguments can be called with an ArrayRef of arguments. Some cases in Allocatable.cpp already had a vector of values at the point where createArguments needed to be called - the new overload allows calling with a vector of args or the variadic version with each argument spelled out at the callsite. This change resulted in the allocatable runtime calls having their arguments converted left-to-right, which changed some of the test results. I used CHECK-DAG to ignore the order. Add some missing handling of volatile class entities, which I previously missed because I had not yet enabled volatile class entities in Lower. --- .../Optimizer/Builder/Runtime/RTBuilder.h | 31 +-- flang/lib/Lower/Allocatable.cpp | 65 +++--- flang/lib/Lower/ConvertExprToHLFIR.cpp | 12 +- flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp | 8 +- flang/test/Lower/allocatable-polymorphic.f90 | 142 ++++++------- .../Lower/allocate-source-allocatables-2.f90 | 24 +-- .../Lower/allocate-source-allocatables.f90 | 14 +- flang/test/Lower/allocate-source-pointers.f90 | 10 +- flang/test/Lower/volatile-allocatable.f90 | 193 ++++++++++++++++++ 9 files changed, 334 insertions(+), 165 deletions(-) create mode 100644 flang/test/Lower/volatile-allocatable.f90 diff --git a/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h b/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h index 5440b36c0c62..98d7de81c7f0 100644 --- a/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h +++ b/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h @@ -26,6 +26,7 @@ #include "flang/Support/Fortran.h" #include "mlir/IR/BuiltinTypes.h" #include "mlir/IR/MLIRContext.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include #include @@ -824,33 +825,23 @@ static mlir::func::FuncOp getIORuntimeFunc(mlir::Location loc, return getRuntimeFunc(loc, builder, /*isIO=*/true); } -namespace helper { -template -void createArguments(llvm::SmallVectorImpl &result, - fir::FirOpBuilder &builder, mlir::Location loc, - mlir::FunctionType fTy, A arg) { - result.emplace_back( - builder.createConvertWithVolatileCast(loc, fTy.getInput(N), arg)); +inline llvm::SmallVector +createArguments(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::FunctionType fTy, llvm::ArrayRef args) { + return llvm::map_to_vector(llvm::zip_equal(fTy.getInputs(), args), + [&](const auto &pair) -> mlir::Value { + auto [type, argument] = pair; + return builder.createConvertWithVolatileCast( + loc, type, argument); + }); } -template -void createArguments(llvm::SmallVectorImpl &result, - fir::FirOpBuilder &builder, mlir::Location loc, - mlir::FunctionType fTy, A arg, As... args) { - result.emplace_back( - builder.createConvertWithVolatileCast(loc, fTy.getInput(N), arg)); - createArguments(result, builder, loc, fTy, args...); -} -} // namespace helper - /// Create a SmallVector of arguments for a runtime call. template llvm::SmallVector createArguments(fir::FirOpBuilder &builder, mlir::Location loc, mlir::FunctionType fTy, As... args) { - llvm::SmallVector result; - helper::createArguments<0>(result, builder, loc, fTy, args...); - return result; + return createArguments(builder, loc, fTy, {args...}); } } // namespace fir::runtime diff --git a/flang/lib/Lower/Allocatable.cpp b/flang/lib/Lower/Allocatable.cpp index 8d0444a6e5bd..7e32575caad9 100644 --- a/flang/lib/Lower/Allocatable.cpp +++ b/flang/lib/Lower/Allocatable.cpp @@ -138,12 +138,10 @@ static void genRuntimeSetBounds(fir::FirOpBuilder &builder, mlir::Location loc, builder) : fir::runtime::getRuntimeFunc( loc, builder); - llvm::SmallVector args{box.getAddr(), dimIndex, lowerBound, - upperBound}; - llvm::SmallVector operands; - for (auto [fst, snd] : llvm::zip(args, callee.getFunctionType().getInputs())) - operands.emplace_back(builder.createConvert(loc, snd, fst)); - builder.create(loc, callee, operands); + const auto args = fir::runtime::createArguments( + builder, loc, callee.getFunctionType(), box.getAddr(), dimIndex, + lowerBound, upperBound); + builder.create(loc, callee, args); } /// Generate runtime call to set the lengths of a character allocatable or @@ -162,9 +160,7 @@ static void genRuntimeInitCharacter(fir::FirOpBuilder &builder, if (inputTypes.size() != 5) fir::emitFatalError( loc, "AllocatableInitCharacter runtime interface not as expected"); - llvm::SmallVector args; - args.push_back(builder.createConvert(loc, inputTypes[0], box.getAddr())); - args.push_back(builder.createConvert(loc, inputTypes[1], len)); + llvm::SmallVector args = {box.getAddr(), len}; if (kind == 0) kind = mlir::cast(box.getEleTy()).getFKind(); args.push_back(builder.createIntegerConstant(loc, inputTypes[2], kind)); @@ -173,7 +169,9 @@ static void genRuntimeInitCharacter(fir::FirOpBuilder &builder, // TODO: coarrays int corank = 0; args.push_back(builder.createIntegerConstant(loc, inputTypes[4], corank)); - builder.create(loc, callee, args); + const auto convertedArgs = fir::runtime::createArguments( + builder, loc, callee.getFunctionType(), args); + builder.create(loc, callee, convertedArgs); } /// Generate a sequence of runtime calls to allocate memory. @@ -194,10 +192,9 @@ static mlir::Value genRuntimeAllocate(fir::FirOpBuilder &builder, args.push_back(errorManager.errMsgAddr); args.push_back(errorManager.sourceFile); args.push_back(errorManager.sourceLine); - llvm::SmallVector operands; - for (auto [fst, snd] : llvm::zip(args, callee.getFunctionType().getInputs())) - operands.emplace_back(builder.createConvert(loc, snd, fst)); - return builder.create(loc, callee, operands).getResult(0); + const auto convertedArgs = fir::runtime::createArguments( + builder, loc, callee.getFunctionType(), args); + return builder.create(loc, callee, convertedArgs).getResult(0); } /// Generate a sequence of runtime calls to allocate memory and assign with the @@ -213,14 +210,11 @@ static mlir::Value genRuntimeAllocateSource(fir::FirOpBuilder &builder, loc, builder) : fir::runtime::getRuntimeFunc( loc, builder); - llvm::SmallVector args{ - box.getAddr(), fir::getBase(source), - errorManager.hasStat, errorManager.errMsgAddr, - errorManager.sourceFile, errorManager.sourceLine}; - llvm::SmallVector operands; - for (auto [fst, snd] : llvm::zip(args, callee.getFunctionType().getInputs())) - operands.emplace_back(builder.createConvert(loc, snd, fst)); - return builder.create(loc, callee, operands).getResult(0); + const auto args = fir::runtime::createArguments( + builder, loc, callee.getFunctionType(), box.getAddr(), + fir::getBase(source), errorManager.hasStat, errorManager.errMsgAddr, + errorManager.sourceFile, errorManager.sourceLine); + return builder.create(loc, callee, args).getResult(0); } /// Generate runtime call to apply mold to the descriptor. @@ -234,14 +228,12 @@ static void genRuntimeAllocateApplyMold(fir::FirOpBuilder &builder, builder) : fir::runtime::getRuntimeFunc( loc, builder); - llvm::SmallVector args{ + const auto args = fir::runtime::createArguments( + builder, loc, callee.getFunctionType(), fir::factory::getMutableIRBox(builder, loc, box), fir::getBase(mold), builder.createIntegerConstant( - loc, callee.getFunctionType().getInputs()[2], rank)}; - llvm::SmallVector operands; - for (auto [fst, snd] : llvm::zip(args, callee.getFunctionType().getInputs())) - operands.emplace_back(builder.createConvert(loc, snd, fst)); - builder.create(loc, callee, operands); + loc, callee.getFunctionType().getInputs()[2], rank)); + builder.create(loc, callee, args); } /// Generate a runtime call to deallocate memory. @@ -669,15 +661,13 @@ private: llvm::ArrayRef inputTypes = callee.getFunctionType().getInputs(); - llvm::SmallVector args; - args.push_back(builder.createConvert(loc, inputTypes[0], box.getAddr())); - args.push_back(builder.createConvert(loc, inputTypes[1], typeDescAddr)); mlir::Value rankValue = builder.createIntegerConstant(loc, inputTypes[2], rank); mlir::Value corankValue = builder.createIntegerConstant(loc, inputTypes[3], corank); - args.push_back(rankValue); - args.push_back(corankValue); + const auto args = fir::runtime::createArguments( + builder, loc, callee.getFunctionType(), box.getAddr(), typeDescAddr, + rankValue, corankValue); builder.create(loc, callee, args); } @@ -696,8 +686,6 @@ private: llvm::ArrayRef inputTypes = callee.getFunctionType().getInputs(); - llvm::SmallVector args; - args.push_back(builder.createConvert(loc, inputTypes[0], box.getAddr())); mlir::Value categoryValue = builder.createIntegerConstant( loc, inputTypes[1], static_cast(category)); mlir::Value kindValue = @@ -706,10 +694,9 @@ private: builder.createIntegerConstant(loc, inputTypes[3], rank); mlir::Value corankValue = builder.createIntegerConstant(loc, inputTypes[4], corank); - args.push_back(categoryValue); - args.push_back(kindValue); - args.push_back(rankValue); - args.push_back(corankValue); + const auto args = fir::runtime::createArguments( + builder, loc, callee.getFunctionType(), box.getAddr(), categoryValue, + kindValue, rankValue, corankValue); builder.create(loc, callee, args); } diff --git a/flang/lib/Lower/ConvertExprToHLFIR.cpp b/flang/lib/Lower/ConvertExprToHLFIR.cpp index 04b63f92a1fb..395f4518efb1 100644 --- a/flang/lib/Lower/ConvertExprToHLFIR.cpp +++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp @@ -227,6 +227,12 @@ private: isVolatile = true; } + // Check if the base type is volatile + if (partInfo.base.has_value()) { + mlir::Type baseType = partInfo.base.value().getType(); + isVolatile = isVolatile || fir::isa_volatile_type(baseType); + } + // Dynamic type of polymorphic base must be kept if the designator is // polymorphic. if (isPolymorphic(designatorNode)) @@ -238,12 +244,6 @@ private: if (charType && charType.hasDynamicLen()) return fir::BoxCharType::get(charType.getContext(), charType.getFKind()); - // Check if the base type is volatile - if (partInfo.base.has_value()) { - mlir::Type baseType = partInfo.base.value().getType(); - isVolatile = isVolatile || fir::isa_volatile_type(baseType); - } - // Arrays with non default lower bounds or dynamic length or dynamic extent // need a fir.box to hold the dynamic or lower bound information. if (fir::hasDynamicSize(resultValueType) || diff --git a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp index eef1377f2696..711d5d1461b0 100644 --- a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp +++ b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp @@ -210,15 +210,14 @@ static bool hasExplicitLowerBounds(mlir::Value shape) { static std::pair updateDeclareInputTypeWithVolatility( mlir::Type inputType, mlir::Value memref, mlir::OpBuilder &builder, fir::FortranVariableFlagsAttr fortran_attrs) { - if (mlir::isa(inputType) && fortran_attrs && + if (fortran_attrs && bitEnumContainsAny(fortran_attrs.getFlags(), fir::FortranVariableFlagsEnum::fortran_volatile)) { const bool isPointer = bitEnumContainsAny( fortran_attrs.getFlags(), fir::FortranVariableFlagsEnum::pointer); auto updateType = [&](auto t) { using FIRT = decltype(t); - // If an entity is a pointer, the entity it points to is volatile, as far - // as consumers of the pointer are concerned. + // A volatile pointer's pointee is volatile. auto elementType = t.getEleTy(); const bool elementTypeIsVolatile = isPointer || fir::isa_volatile_type(elementType); @@ -227,8 +226,7 @@ static std::pair updateDeclareInputTypeWithVolatility( inputType = FIRT::get(newEleTy, true); }; llvm::TypeSwitch(inputType) - .Case(updateType) - .Default([](mlir::Type t) { return t; }); + .Case(updateType); memref = builder.create(memref.getLoc(), inputType, memref); } diff --git a/flang/test/Lower/allocatable-polymorphic.f90 b/flang/test/Lower/allocatable-polymorphic.f90 index dd8671daeaf8..10e703210ea6 100644 --- a/flang/test/Lower/allocatable-polymorphic.f90 +++ b/flang/test/Lower/allocatable-polymorphic.f90 @@ -41,7 +41,7 @@ contains end subroutine ! ------------------------------------------------------------------------------ -! Test lowering of ALLOCATE statement for polymoprhic pointer +! Test lowering of ALLOCATE statement for polymorphic pointer ! ------------------------------------------------------------------------------ subroutine test_pointer() @@ -98,10 +98,10 @@ contains ! CHECK: %[[P_DECL:.*]]:2 = hlfir.declare %[[P_DESC]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QMpolyFtest_pointerEp"} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) ! CHECK: %[[TYPE_DESC_P1:.*]] = fir.type_desc !fir.type<_QMpolyTp1{a:i32,b:i32}> -! CHECK: %[[P_DESC_CAST:.*]] = fir.convert %[[P_DECL]]#0 : (!fir.ref>>>) -> !fir.ref> -! CHECK: %[[TYPE_DESC_P1_CAST:.*]] = fir.convert %[[TYPE_DESC_P1]] : (!fir.tdesc>) -> !fir.ref -! CHECK: %[[RANK:.*]] = arith.constant 0 : i32 -! CHECK: %[[CORANK:.*]] = arith.constant 0 : i32 +! CHECK-DAG: %[[P_DESC_CAST:.*]] = fir.convert %[[P_DECL]]#0 : (!fir.ref>>>) -> !fir.ref> +! CHECK-DAG: %[[TYPE_DESC_P1_CAST:.*]] = fir.convert %[[TYPE_DESC_P1]] : (!fir.tdesc>) -> !fir.ref +! CHECK-DAG: %[[RANK:.*]] = arith.constant 0 : i32 +! CHECK-DAG: %[[CORANK:.*]] = arith.constant 0 : i32 ! CHECK: fir.call @_FortranAPointerNullifyDerived(%[[P_DESC_CAST]], %[[TYPE_DESC_P1_CAST]], %[[RANK]], %[[CORANK]]) {{.*}}: (!fir.ref>, !fir.ref, i32, i32) -> () ! CHECK: %[[P_DESC_CAST:.*]] = fir.convert %[[P_DECL]]#0 : (!fir.ref>>>) -> !fir.ref> ! CHECK: %{{.*}} = fir.call @_FortranAPointerAllocate(%[[P_DESC_CAST]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) {{.*}}: (!fir.ref>, i1, !fir.box, !fir.ref, i32) -> i32 @@ -111,19 +111,19 @@ contains ! CHECK: fir.dispatch "proc1"(%[[P_LOAD]] : !fir.class>>) ! CHECK: %[[TYPE_DESC_P1:.*]] = fir.type_desc !fir.type<_QMpolyTp1{a:i32,b:i32}> -! CHECK: %[[C1_DESC_CAST:.*]] = fir.convert %[[C1_DECL:.*]]#0 : (!fir.ref>>>) -> !fir.ref> -! CHECK: %[[TYPE_DESC_P1_CAST:.*]] = fir.convert %[[TYPE_DESC_P1]] : (!fir.tdesc>) -> !fir.ref -! CHECK: %[[RANK:.*]] = arith.constant 0 : i32 -! CHECK: %[[CORANK:.*]] = arith.constant 0 : i32 +! CHECK-DAG: %[[C1_DESC_CAST:.*]] = fir.convert %[[C1_DECL:.*]]#0 : (!fir.ref>>>) -> !fir.ref> +! CHECK-DAG: %[[TYPE_DESC_P1_CAST:.*]] = fir.convert %[[TYPE_DESC_P1]] : (!fir.tdesc>) -> !fir.ref +! CHECK-DAG: %[[RANK:.*]] = arith.constant 0 : i32 +! CHECK-DAG: %[[CORANK:.*]] = arith.constant 0 : i32 ! CHECK: fir.call @_FortranAPointerNullifyDerived(%[[C1_DESC_CAST]], %[[TYPE_DESC_P1_CAST]], %[[RANK]], %[[CORANK]]) {{.*}}: (!fir.ref>, !fir.ref, i32, i32) -> () ! CHECK: %[[C1_DESC_CAST:.*]] = fir.convert %[[C1_DECL]]#0 : (!fir.ref>>>) -> !fir.ref> ! CHECK: %{{.*}} = fir.call @_FortranAPointerAllocate(%[[C1_DESC_CAST]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) {{.*}}: (!fir.ref>, i1, !fir.box, !fir.ref, i32) -> i32 ! CHECK: %[[TYPE_DESC_P2:.*]] = fir.type_desc !fir.type<_QMpolyTp2{p1:!fir.type<_QMpolyTp1{a:i32,b:i32}>,c:i32}> -! CHECK: %[[C2_DESC_CAST:.*]] = fir.convert %[[C2_DECL]]#0 : (!fir.ref>>>) -> !fir.ref> -! CHECK: %[[TYPE_DESC_P2_CAST:.*]] = fir.convert %[[TYPE_DESC_P2]] : (!fir.tdesc,c:i32}>>) -> !fir.ref -! CHECK: %[[RANK:.*]] = arith.constant 0 : i32 -! CHECK: %[[CORANK:.*]] = arith.constant 0 : i32 +! CHECK-DAG: %[[C2_DESC_CAST:.*]] = fir.convert %[[C2_DECL]]#0 : (!fir.ref>>>) -> !fir.ref> +! CHECK-DAG: %[[TYPE_DESC_P2_CAST:.*]] = fir.convert %[[TYPE_DESC_P2]] : (!fir.tdesc,c:i32}>>) -> !fir.ref +! CHECK-DAG: %[[RANK:.*]] = arith.constant 0 : i32 +! CHECK-DAG: %[[CORANK:.*]] = arith.constant 0 : i32 ! CHECK: fir.call @_FortranAPointerNullifyDerived(%[[C2_DESC_CAST]], %[[TYPE_DESC_P2_CAST]], %[[RANK]], %[[CORANK]]) {{.*}}: (!fir.ref>, !fir.ref, i32, i32) -> () ! CHECK: %[[C2_DESC_CAST:.*]] = fir.convert %[[C2_DECL]]#0 : (!fir.ref>>>) -> !fir.ref> ! CHECK: %{{.*}} = fir.call @_FortranAPointerAllocate(%[[C2_DESC_CAST]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) {{.*}}: (!fir.ref>, i1, !fir.box, !fir.ref, i32) -> i32 @@ -147,10 +147,10 @@ contains ! CHECK: fir.dispatch "proc2"(%[[C2_REBOX]] : !fir.class>) (%[[C2_REBOX]] : !fir.class>) {pass_arg_pos = 0 : i32} ! CHECK: %[[TYPE_DESC_P1:.*]] = fir.type_desc !fir.type<_QMpolyTp1{a:i32,b:i32}> -! CHECK: %[[C3_CAST:.*]] = fir.convert %[[C3_DECL]]#0 : (!fir.ref>>>>) -> !fir.ref> -! CHECK: %[[TYPE_DESC_P1_CAST:.*]] = fir.convert %[[TYPE_DESC_P1]] : (!fir.tdesc>) -> !fir.ref -! CHECK: %[[RANK:.*]] = arith.constant 1 : i32 -! CHECK: %[[CORANK:.*]] = arith.constant 0 : i32 +! CHECK-DAG: %[[C3_CAST:.*]] = fir.convert %[[C3_DECL]]#0 : (!fir.ref>>>>) -> !fir.ref> +! CHECK-DAG: %[[TYPE_DESC_P1_CAST:.*]] = fir.convert %[[TYPE_DESC_P1]] : (!fir.tdesc>) -> !fir.ref +! CHECK-DAG: %[[RANK:.*]] = arith.constant 1 : i32 +! CHECK-DAG: %[[CORANK:.*]] = arith.constant 0 : i32 ! CHECK: fir.call @_FortranAPointerNullifyDerived(%[[C3_CAST]], %[[TYPE_DESC_P1_CAST]], %[[RANK]], %[[CORANK]]) {{.*}}: (!fir.ref>, !fir.ref, i32, i32) -> () ! CHECK: %[[C3_CAST:.*]] = fir.convert %[[C3_DECL]]#0 : (!fir.ref>>>>) -> !fir.ref> ! CHECK: fir.call @_FortranAPointerSetBounds(%[[C3_CAST]], %{{.*}}, %{{.*}}, %{{.*}}) {{.*}}: (!fir.ref>, i32, i64, i64) -> () @@ -158,10 +158,10 @@ contains ! CHECK: %{{.*}} = fir.call @_FortranAPointerAllocate(%[[C3_CAST]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) {{.*}}: (!fir.ref>, i1, !fir.box, !fir.ref, i32) -> i32 ! CHECK: %[[TYPE_DESC_P2:.*]] = fir.type_desc !fir.type<_QMpolyTp2{p1:!fir.type<_QMpolyTp1{a:i32,b:i32}>,c:i32}> -! CHECK: %[[C4_CAST:.*]] = fir.convert %[[C4_DECL]]#0 : (!fir.ref>>>>) -> !fir.ref> -! CHECK: %[[TYPE_DESC_P2_CAST:.*]] = fir.convert %[[TYPE_DESC_P2]] : (!fir.tdesc,c:i32}>>) -> !fir.ref -! CHECK: %[[RANK:.*]] = arith.constant 1 : i32 -! CHECK: %[[CORANK:.*]] = arith.constant 0 : i32 +! CHECK-DAG: %[[C4_CAST:.*]] = fir.convert %[[C4_DECL]]#0 : (!fir.ref>>>>) -> !fir.ref> +! CHECK-DAG: %[[TYPE_DESC_P2_CAST:.*]] = fir.convert %[[TYPE_DESC_P2]] : (!fir.tdesc,c:i32}>>) -> !fir.ref +! CHECK-DAG: %[[RANK:.*]] = arith.constant 1 : i32 +! CHECK-DAG: %[[CORANK:.*]] = arith.constant 0 : i32 ! CHECK: fir.call @_FortranAPointerNullifyDerived(%[[C4_CAST]], %[[TYPE_DESC_P2_CAST]], %[[RANK]], %[[CORANK]]) {{.*}}: (!fir.ref>, !fir.ref, i32, i32) -> () ! CHECK: %[[C4_CAST:.*]] = fir.convert %[[C4_DECL]]#0 : (!fir.ref>>>>) -> !fir.ref> ! CHECK: fir.call @_FortranAPointerSetBounds(%[[C4_CAST]], %{{.*}}, %{{.*}}, %{{.*}}) {{.*}}: (!fir.ref>, i32, i64, i64) -> () @@ -261,59 +261,59 @@ contains ! CHECK-DAG: %[[P_DECL:.*]]:2 = hlfir.declare %[[P]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QMpolyFtest_allocatableEp"} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) ! CHECK: %[[TYPE_DESC_P1:.*]] = fir.type_desc !fir.type<_QMpolyTp1{a:i32,b:i32}> -! CHECK: %[[P_CAST:.*]] = fir.convert %[[P_DECL]]#0 : (!fir.ref>>>) -> !fir.ref> -! CHECK: %[[TYPE_DESC_P1_CAST:.*]] = fir.convert %[[TYPE_DESC_P1]] : (!fir.tdesc>) -> !fir.ref -! CHECK: %[[RANK:.*]] = arith.constant 0 : i32 -! CHECK: %[[C0:.*]] = arith.constant 0 : i32 +! CHECK-DAG: %[[P_CAST:.*]] = fir.convert %[[P_DECL]]#0 : (!fir.ref>>>) -> !fir.ref> +! CHECK-DAG: %[[TYPE_DESC_P1_CAST:.*]] = fir.convert %[[TYPE_DESC_P1]] : (!fir.tdesc>) -> !fir.ref +! CHECK-DAG: %[[RANK:.*]] = arith.constant 0 : i32 +! CHECK-DAG: %[[C0:.*]] = arith.constant 0 : i32 ! CHECK: fir.call @_FortranAAllocatableInitDerivedForAllocate(%[[P_CAST]], %[[TYPE_DESC_P1_CAST]], %[[RANK]], %[[C0]]) {{.*}}: (!fir.ref>, !fir.ref, i32, i32) -> () ! CHECK: %[[P_CAST:.*]] = fir.convert %[[P_DECL]]#0 : (!fir.ref>>>) -> !fir.ref> ! CHECK: %{{.*}} = fir.call @_FortranAAllocatableAllocate(%[[P_CAST]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) {{.*}}: (!fir.ref>, i64, i1, !fir.box, !fir.ref, i32) -> i32 ! CHECK: %[[TYPE_DESC_P1:.*]] = fir.type_desc !fir.type<_QMpolyTp1{a:i32,b:i32}> -! CHECK: %[[C1_CAST:.*]] = fir.convert %[[C1_DECL]]#0 : (!fir.ref>>>) -> !fir.ref> -! CHECK: %[[TYPE_DESC_P1_CAST:.*]] = fir.convert %[[TYPE_DESC_P1]] : (!fir.tdesc>) -> !fir.ref -! CHECK: %[[RANK:.*]] = arith.constant 0 : i32 -! CHECK: %[[C0:.*]] = arith.constant 0 : i32 +! CHECK-DAG: %[[C1_CAST:.*]] = fir.convert %[[C1_DECL]]#0 : (!fir.ref>>>) -> !fir.ref> +! CHECK-DAG: %[[TYPE_DESC_P1_CAST:.*]] = fir.convert %[[TYPE_DESC_P1]] : (!fir.tdesc>) -> !fir.ref +! CHECK-DAG: %[[RANK:.*]] = arith.constant 0 : i32 +! CHECK-DAG: %[[C0:.*]] = arith.constant 0 : i32 ! CHECK: fir.call @_FortranAAllocatableInitDerivedForAllocate(%[[C1_CAST]], %[[TYPE_DESC_P1_CAST]], %[[RANK]], %[[C0]]) {{.*}}: (!fir.ref>, !fir.ref, i32, i32) -> () ! CHECK: %[[C1_CAST:.*]] = fir.convert %[[C1_DECL]]#0 : (!fir.ref>>>) -> !fir.ref> ! CHECK: %{{.*}} = fir.call @_FortranAAllocatableAllocate(%[[C1_CAST]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) {{.*}}: (!fir.ref>, i64, i1, !fir.box, !fir.ref, i32) -> i32 ! CHECK: %[[TYPE_DESC_P2:.*]] = fir.type_desc !fir.type<_QMpolyTp2{p1:!fir.type<_QMpolyTp1{a:i32,b:i32}>,c:i32}> -! CHECK: %[[C2_CAST:.*]] = fir.convert %[[C2_DECL]]#0 : (!fir.ref>>>) -> !fir.ref> -! CHECK: %[[TYPE_DESC_P2_CAST:.*]] = fir.convert %[[TYPE_DESC_P2]] : (!fir.tdesc,c:i32}>>) -> !fir.ref -! CHECK: %[[RANK:.*]] = arith.constant 0 : i32 -! CHECK: %[[C0:.*]] = arith.constant 0 : i32 +! CHECK-DAG: %[[C2_CAST:.*]] = fir.convert %[[C2_DECL]]#0 : (!fir.ref>>>) -> !fir.ref> +! CHECK-DAG: %[[TYPE_DESC_P2_CAST:.*]] = fir.convert %[[TYPE_DESC_P2]] : (!fir.tdesc,c:i32}>>) -> !fir.ref +! CHECK-DAG: %[[RANK:.*]] = arith.constant 0 : i32 +! CHECK-DAG: %[[C0:.*]] = arith.constant 0 : i32 ! CHECK: fir.call @_FortranAAllocatableInitDerivedForAllocate(%[[C2_CAST]], %[[TYPE_DESC_P2_CAST]], %[[RANK]], %[[C0]]) {{.*}}: (!fir.ref>, !fir.ref, i32, i32) -> () ! CHECK: %[[C2_CAST:.*]] = fir.convert %[[C2_DECL]]#0 : (!fir.ref>>>) -> !fir.ref> ! CHECK: %{{.*}} = fir.call @_FortranAAllocatableAllocate(%[[C2_CAST]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) {{.*}}: (!fir.ref>, i64, i1, !fir.box, !fir.ref, i32) -> i32 ! CHECK: %[[TYPE_DESC_P1:.*]] = fir.type_desc !fir.type<_QMpolyTp1{a:i32,b:i32}> -! CHECK: %[[C3_CAST:.*]] = fir.convert %[[C3_DECL]]#0 : (!fir.ref>>>>) -> !fir.ref> -! CHECK: %[[TYPE_DESC_P1_CAST:.*]] = fir.convert %[[TYPE_DESC_P1]] : (!fir.tdesc>) -> !fir.ref -! CHECK: %[[RANK:.*]] = arith.constant 1 : i32 -! CHECK: %[[C0:.*]] = arith.constant 0 : i32 +! CHECK-DAG: %[[C3_CAST:.*]] = fir.convert %[[C3_DECL]]#0 : (!fir.ref>>>>) -> !fir.ref> +! CHECK-DAG: %[[TYPE_DESC_P1_CAST:.*]] = fir.convert %[[TYPE_DESC_P1]] : (!fir.tdesc>) -> !fir.ref +! CHECK-DAG: %[[RANK:.*]] = arith.constant 1 : i32 +! CHECK-DAG: %[[C0:.*]] = arith.constant 0 : i32 ! CHECK: fir.call @_FortranAAllocatableInitDerivedForAllocate(%[[C3_CAST]], %[[TYPE_DESC_P1_CAST]], %[[RANK]], %[[C0]]) {{.*}}: (!fir.ref>, !fir.ref, i32, i32) -> () -! CHECK: %[[C10:.*]] = arith.constant 10 : i32 -! CHECK: %[[C0:.*]] = arith.constant 0 : i32 -! CHECK: %[[C3_CAST:.*]] = fir.convert %[[C3_DECL]]#0 : (!fir.ref>>>>) -> !fir.ref> -! CHECK: %[[C1_I64:.*]] = fir.convert %c1{{.*}} : (index) -> i64 -! CHECK: %[[C10_I64:.*]] = fir.convert %[[C10]] : (i32) -> i64 +! CHECK-DAG: %[[C10:.*]] = arith.constant 10 : i32 +! CHECK-DAG: %[[C0:.*]] = arith.constant 0 : i32 +! CHECK-DAG: %[[C3_CAST:.*]] = fir.convert %[[C3_DECL]]#0 : (!fir.ref>>>>) -> !fir.ref> +! CHECK-DAG: %[[C1_I64:.*]] = fir.convert %c1{{.*}} : (index) -> i64 +! CHECK-DAG: %[[C10_I64:.*]] = fir.convert %[[C10]] : (i32) -> i64 ! CHECK: fir.call @_FortranAAllocatableSetBounds(%[[C3_CAST]], %[[C0]], %[[C1_I64]], %[[C10_I64]]) {{.*}}: (!fir.ref>, i32, i64, i64) -> () ! CHECK: %[[C3_CAST:.*]] = fir.convert %[[C3_DECL]]#0 : (!fir.ref>>>>) -> !fir.ref> ! CHECK: %{{.*}} = fir.call @_FortranAAllocatableAllocate(%[[C3_CAST]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) {{.*}}: (!fir.ref>, i64, i1, !fir.box, !fir.ref, i32) -> i32 ! CHECK: %[[TYPE_DESC_P2:.*]] = fir.type_desc !fir.type<_QMpolyTp2{p1:!fir.type<_QMpolyTp1{a:i32,b:i32}>,c:i32}> -! CHECK: %[[C4_CAST:.*]] = fir.convert %[[C4_DECL]]#0 : (!fir.ref>>>>) -> !fir.ref> -! CHECK: %[[TYPE_DESC_P2_CAST:.*]] = fir.convert %[[TYPE_DESC_P2]] : (!fir.tdesc,c:i32}>>) -> !fir.ref -! CHECK: %[[RANK:.*]] = arith.constant 1 : i32 -! CHECK: %[[C0:.*]] = arith.constant 0 : i32 +! CHECK-DAG: %[[C4_CAST:.*]] = fir.convert %[[C4_DECL]]#0 : (!fir.ref>>>>) -> !fir.ref> +! CHECK-DAG: %[[TYPE_DESC_P2_CAST:.*]] = fir.convert %[[TYPE_DESC_P2]] : (!fir.tdesc,c:i32}>>) -> !fir.ref +! CHECK-DAG: %[[RANK:.*]] = arith.constant 1 : i32 +! CHECK-DAG: %[[C0:.*]] = arith.constant 0 : i32 ! CHECK: fir.call @_FortranAAllocatableInitDerivedForAllocate(%[[C4_CAST]], %[[TYPE_DESC_P2_CAST]], %[[RANK]], %[[C0]]) {{.*}}: (!fir.ref>, !fir.ref, i32, i32) -> () -! CHECK: %[[CST1:.*]] = arith.constant 1 : index -! CHECK: %[[C20:.*]] = arith.constant 20 : i32 -! CHECK: %[[C0:.*]] = arith.constant 0 : i32 -! CHECK: %[[C4_CAST:.*]] = fir.convert %[[C4_DECL]]#0 : (!fir.ref>>>>) -> !fir.ref> -! CHECK: %[[C1_I64:.*]] = fir.convert %[[CST1]] : (index) -> i64 -! CHECK: %[[C20_I64:.*]] = fir.convert %[[C20]] : (i32) -> i64 +! CHECK-DAG: %[[CST1:.*]] = arith.constant 1 : index +! CHECK-DAG: %[[C20:.*]] = arith.constant 20 : i32 +! CHECK-DAG: %[[C0:.*]] = arith.constant 0 : i32 +! CHECK-DAG: %[[C4_CAST:.*]] = fir.convert %[[C4_DECL]]#0 : (!fir.ref>>>>) -> !fir.ref> +! CHECK-DAG: %[[C1_I64:.*]] = fir.convert %[[CST1]] : (index) -> i64 +! CHECK-DAG: %[[C20_I64:.*]] = fir.convert %[[C20]] : (i32) -> i64 ! CHECK: fir.call @_FortranAAllocatableSetBounds(%[[C4_CAST]], %[[C0]], %[[C1_I64]], %[[C20_I64]]) {{.*}}: (!fir.ref>, i32, i64, i64) -> () ! CHECK: %[[C4_CAST:.*]] = fir.convert %[[C4_DECL]]#0 : (!fir.ref>>>>) -> !fir.ref> ! CHECK: %{{.*}} = fir.call @_FortranAAllocatableAllocate(%[[C4_CAST]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) {{.*}}: (!fir.ref>, i64, i1, !fir.box, !fir.ref, i32) -> i32 @@ -383,20 +383,20 @@ contains ! CHECK: %[[P_DECL:.*]]:2 = hlfir.declare %[[P]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QMpolyFtest_unlimited_polymorphic_with_intrinsic_type_specEp"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) ! CHECK: %[[PTR:.*]] = fir.alloca !fir.class> {bindc_name = "ptr", uniq_name = "_QMpolyFtest_unlimited_polymorphic_with_intrinsic_type_specEptr"} ! CHECK: %[[PTR_DECL:.*]]:2 = hlfir.declare %[[PTR]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QMpolyFtest_unlimited_polymorphic_with_intrinsic_type_specEptr"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) -! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[P_DECL]]#0 : (!fir.ref>>) -> !fir.ref> -! CHECK: %[[CAT:.*]] = arith.constant 0 : i32 -! CHECK: %[[KIND:.*]] = arith.constant 4 : i32 -! CHECK: %[[RANK:.*]] = arith.constant 0 : i32 -! CHECK: %[[CORANK:.*]] = arith.constant 0 : i32 +! CHECK-DAG: %[[BOX_NONE:.*]] = fir.convert %[[P_DECL]]#0 : (!fir.ref>>) -> !fir.ref> +! CHECK-DAG: %[[CAT:.*]] = arith.constant 0 : i32 +! CHECK-DAG: %[[KIND:.*]] = arith.constant 4 : i32 +! CHECK-DAG: %[[RANK:.*]] = arith.constant 0 : i32 +! CHECK-DAG: %[[CORANK:.*]] = arith.constant 0 : i32 ! CHECK: fir.call @_FortranAAllocatableInitIntrinsicForAllocate(%[[BOX_NONE]], %[[CAT]], %[[KIND]], %[[RANK]], %[[CORANK]]) {{.*}} : (!fir.ref>, i32, i32, i32, i32) -> () ! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[P_DECL]]#0 : (!fir.ref>>) -> !fir.ref> ! CHECK: %{{.*}} = fir.call @_FortranAAllocatableAllocate(%[[BOX_NONE]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) {{.*}} : (!fir.ref>, i64, i1, !fir.box, !fir.ref, i32) -> i32 -! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[PTR_DECL]]#0 : (!fir.ref>>) -> !fir.ref> -! CHECK: %[[CAT:.*]] = arith.constant 2 : i32 -! CHECK: %[[KIND:.*]] = arith.constant 4 : i32 -! CHECK: %[[RANK:.*]] = arith.constant 0 : i32 -! CHECK: %[[CORANK:.*]] = arith.constant 0 : i32 +! CHECK-DAG: %[[BOX_NONE:.*]] = fir.convert %[[PTR_DECL]]#0 : (!fir.ref>>) -> !fir.ref> +! CHECK-DAG: %[[CAT:.*]] = arith.constant 2 : i32 +! CHECK-DAG: %[[KIND:.*]] = arith.constant 4 : i32 +! CHECK-DAG: %[[RANK:.*]] = arith.constant 0 : i32 +! CHECK-DAG: %[[CORANK:.*]] = arith.constant 0 : i32 ! CHECK: fir.call @_FortranAPointerNullifyIntrinsic(%[[BOX_NONE]], %[[CAT]], %[[KIND]], %[[RANK]], %[[CORANK]]) {{.*}} : (!fir.ref>, i32, i32, i32, i32) -> () ! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[PTR_DECL]]#0 : (!fir.ref>>) -> !fir.ref> ! CHECK: %{{.*}} = fir.call @_FortranAPointerAllocate(%[[BOX_NONE]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) {{.*}} : (!fir.ref>, i1, !fir.box, !fir.ref, i32) -> i32 @@ -431,10 +431,10 @@ contains ! CHECK: %[[ZERO_DESC:.*]] = fir.embox %[[ZERO]] : (!fir.ptr>) -> !fir.class>> ! CHECK: fir.store %[[ZERO_DESC]] to %[[ELEMENT]] : !fir.ref>>> ! CHECK: %[[TYPE_DESC_P1:.*]] = fir.type_desc !fir.type<_QMpolyTp1{a:i32,b:i32}> -! CHECK: %[[ELEMENT_DESC_CAST:.*]] = fir.convert %[[ELEMENT]] : (!fir.ref>>>) -> !fir.ref> -! CHECK: %[[TYPE_DESC_P1_CAST:.*]] = fir.convert %[[TYPE_DESC_P1]] : (!fir.tdesc>) -> !fir.ref -! CHECK: %[[RANK:.*]] = arith.constant 0 : i32 -! CHECK: %[[CORANK:.*]] = arith.constant 0 : i32 +! CHECK-DAG: %[[ELEMENT_DESC_CAST:.*]] = fir.convert %[[ELEMENT]] : (!fir.ref>>>) -> !fir.ref> +! CHECK-DAG: %[[TYPE_DESC_P1_CAST:.*]] = fir.convert %[[TYPE_DESC_P1]] : (!fir.tdesc>) -> !fir.ref +! CHECK-DAG: %[[RANK:.*]] = arith.constant 0 : i32 +! CHECK-DAG: %[[CORANK:.*]] = arith.constant 0 : i32 ! CHECK: fir.call @_FortranAPointerNullifyDerived(%[[ELEMENT_DESC_CAST]], %[[TYPE_DESC_P1_CAST]], %[[RANK]], %[[CORANK]]) {{.*}} : (!fir.ref>, !fir.ref, i32, i32) -> () ! CHECK: %[[ELEMENT_DESC_CAST:.*]] = fir.convert %[[ELEMENT]] : (!fir.ref>>>) -> !fir.ref> ! CHECK: %{{.*}} = fir.call @_FortranAPointerAllocate(%[[ELEMENT_DESC_CAST]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) {{.*}} : (!fir.ref>, i1, !fir.box, !fir.ref, i32) -> i32 @@ -566,11 +566,11 @@ contains ! CHECK-LABEL: func.func @_QMpolyPtest_allocatable_up_character() { ! CHECK: %[[A:.*]] = fir.alloca !fir.class> {bindc_name = "a", uniq_name = "_QMpolyFtest_allocatable_up_characterEa"} ! CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QMpolyFtest_allocatable_up_characterEa"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) -! CHECK: %[[LEN:.*]] = arith.constant 10 : i64 -! CHECK: %[[A_NONE:.*]] = fir.convert %[[A_DECL]]#0 : (!fir.ref>>) -> !fir.ref> -! CHECK: %[[KIND:.*]] = arith.constant 1 : i32 -! CHECK: %[[RANK:.*]] = arith.constant 0 : i32 -! CHECK: %[[CORANK:.*]] = arith.constant 0 : i32 +! CHECK-DAG: %[[LEN:.*]] = arith.constant 10 : i64 +! CHECK-DAG: %[[A_NONE:.*]] = fir.convert %[[A_DECL]]#0 : (!fir.ref>>) -> !fir.ref> +! CHECK-DAG: %[[KIND:.*]] = arith.constant 1 : i32 +! CHECK-DAG: %[[RANK:.*]] = arith.constant 0 : i32 +! CHECK-DAG: %[[CORANK:.*]] = arith.constant 0 : i32 ! CHECK: fir.call @_FortranAAllocatableInitCharacterForAllocate(%[[A_NONE]], %[[LEN]], %[[KIND]], %[[RANK]], %[[CORANK]]) {{.*}} : (!fir.ref>, i64, i32, i32, i32) -> () ! CHECK: %[[A_NONE:.*]] = fir.convert %[[A_DECL]]#0 : (!fir.ref>>) -> !fir.ref> ! CHECK: %{{.*}} = fir.call @_FortranAAllocatableAllocate(%[[A_NONE]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) {{.*}} : (!fir.ref>, i64, i1, !fir.box, !fir.ref, i32) -> i32 diff --git a/flang/test/Lower/allocate-source-allocatables-2.f90 b/flang/test/Lower/allocate-source-allocatables-2.f90 index a4014cc5662d..d7aa365d1a1b 100644 --- a/flang/test/Lower/allocate-source-allocatables-2.f90 +++ b/flang/test/Lower/allocate-source-allocatables-2.f90 @@ -13,26 +13,26 @@ subroutine test() character(2), allocatable :: c_shorter character(:), allocatable :: c_deferred character(7), allocatable :: c_longer -! CHECK: %[[VAL_18:.*]] = arith.constant false +! CHECK-DAG: %[[VAL_18:.*]] = arith.constant false ! CHECK: %[[VAL_22:.*]] = fir.embox %[[VAL_17]]#0 : (!fir.ref>) -> !fir.box> -! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_14]]#0 : (!fir.ref>>>) -> !fir.ref> -! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_22]] : (!fir.box>) -> !fir.box +! CHECK-DAG: %[[VAL_23:.*]] = fir.convert %[[VAL_14]]#0 : (!fir.ref>>>) -> !fir.ref> +! CHECK-DAG: %[[VAL_24:.*]] = fir.convert %[[VAL_22]] : (!fir.box>) -> !fir.box ! CHECK: %[[VAL_26:.*]] = fir.call @_FortranAAllocatableAllocateSource(%[[VAL_23]], %[[VAL_24]], %[[VAL_18]] -! CHECK: %[[VAL_27:.*]] = fir.convert %[[VAL_4]]#0 : (!fir.ref>>>) -> !fir.ref> -! CHECK: %[[VAL_28:.*]] = fir.convert %[[VAL_16]] : (index) -> i64 -! CHECK: %[[VAL_29:.*]] = arith.constant 1 : i32 -! CHECK: %[[VAL_30:.*]] = arith.constant 0 : i32 -! CHECK: %[[VAL_31:.*]] = arith.constant 0 : i32 +! CHECK-DAG: %[[VAL_27:.*]] = fir.convert %[[VAL_4]]#0 : (!fir.ref>>>) -> !fir.ref> +! CHECK-DAG: %[[VAL_28:.*]] = fir.convert %[[VAL_16]] : (index) -> i64 +! CHECK-DAG: %[[VAL_29:.*]] = arith.constant 1 : i32 +! CHECK-DAG: %[[VAL_30:.*]] = arith.constant 0 : i32 +! CHECK-DAG: %[[VAL_31:.*]] = arith.constant 0 : i32 ! CHECK: fir.call @_FortranAAllocatableInitCharacterForAllocate(%[[VAL_27]], %[[VAL_28]], %[[VAL_29]], %[[VAL_30]], %[[VAL_31]] -! CHECK: %[[VAL_33:.*]] = fir.convert %[[VAL_4]]#0 : (!fir.ref>>>) -> !fir.ref> -! CHECK: %[[VAL_34:.*]] = fir.convert %[[VAL_22]] : (!fir.box>) -> !fir.box +! CHECK-DAG: %[[VAL_33:.*]] = fir.convert %[[VAL_4]]#0 : (!fir.ref>>>) -> !fir.ref> +! CHECK-DAG: %[[VAL_34:.*]] = fir.convert %[[VAL_22]] : (!fir.box>) -> !fir.box ! CHECK: %[[VAL_36:.*]] = fir.call @_FortranAAllocatableAllocateSource(%[[VAL_33]], %[[VAL_34]], %[[VAL_18]], ! CHECK-NOT: AllocatableInitCharacterForAllocate -! CHECK: %[[VAL_37:.*]] = fir.convert %[[VAL_9]]#0 : (!fir.ref>>>) -> !fir.ref> -! CHECK: %[[VAL_38:.*]] = fir.convert %[[VAL_22]] : (!fir.box>) -> !fir.box +! CHECK-DAG: %[[VAL_37:.*]] = fir.convert %[[VAL_9]]#0 : (!fir.ref>>>) -> !fir.ref> +! CHECK-DAG: %[[VAL_38:.*]] = fir.convert %[[VAL_22]] : (!fir.box>) -> !fir.box ! CHECK: %[[VAL_40:.*]] = fir.call @_FortranAAllocatableAllocateSource(%[[VAL_37]], %[[VAL_38]], %[[VAL_18]], allocate(c_shorter, c_deferred, c_longer, source=c_source) diff --git a/flang/test/Lower/allocate-source-allocatables.f90 b/flang/test/Lower/allocate-source-allocatables.f90 index 29b00b79a69d..2143d2c61cda 100644 --- a/flang/test/Lower/allocate-source-allocatables.f90 +++ b/flang/test/Lower/allocate-source-allocatables.f90 @@ -306,14 +306,14 @@ end ! CHECK: %[[VAL_14:.*]] = fir.embox %[[VAL_13]] typeparams %[[VAL_12]] : (!fir.heap>, index) -> !fir.box>> ! CHECK: fir.store %[[VAL_14]] to %[[VAL_3]] : !fir.ref>>> ! CHECK: %[[VAL_15:.*]] = fir.box_elesize %[[VAL_11]] : (!fir.box>) -> index -! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_3]] : (!fir.ref>>>) -> !fir.ref> -! CHECK: %[[VAL_17:.*]] = fir.convert %[[VAL_15]] : (index) -> i64 -! CHECK: %[[VAL_18:.*]] = arith.constant 1 : i32 -! CHECK: %[[VAL_19:.*]] = arith.constant 0 : i32 -! CHECK: %[[VAL_20:.*]] = arith.constant 0 : i32 +! CHECK-DAG: %[[VAL_16:.*]] = fir.convert %[[VAL_3]] : (!fir.ref>>>) -> !fir.ref> +! CHECK-DAG: %[[VAL_17:.*]] = fir.convert %[[VAL_15]] : (index) -> i64 +! CHECK-DAG: %[[VAL_18:.*]] = arith.constant 1 : i32 +! CHECK-DAG: %[[VAL_19:.*]] = arith.constant 0 : i32 +! CHECK-DAG: %[[VAL_20:.*]] = arith.constant 0 : i32 ! CHECK: fir.call @_FortranAAllocatableInitCharacterForAllocate(%[[VAL_16]], %[[VAL_17]], %[[VAL_18]], %[[VAL_19]], %[[VAL_20]]) {{.*}}: (!fir.ref>, i64, i32, i32, i32) -> () -! CHECK: %[[VAL_22:.*]] = fir.convert %[[VAL_3]] : (!fir.ref>>>) -> !fir.ref> -! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_11]] : (!fir.box>) -> !fir.box +! CHECK-DAG: %[[VAL_22:.*]] = fir.convert %[[VAL_3]] : (!fir.ref>>>) -> !fir.ref> +! CHECK-DAG: %[[VAL_23:.*]] = fir.convert %[[VAL_11]] : (!fir.box>) -> !fir.box ! CHECK: %[[VAL_25:.*]] = fir.call @_FortranAAllocatableAllocateSource(%[[VAL_22]], %[[VAL_23]], %[[VAL_7]], %[[VAL_8]], %{{.*}}, %{{.*}}) {{.*}}: (!fir.ref>, !fir.box, i1, !fir.box, !fir.ref, i32) -> i32 subroutine test_allocatable_char(n, a) diff --git a/flang/test/Lower/allocate-source-pointers.f90 b/flang/test/Lower/allocate-source-pointers.f90 index e6359dba81eb..7e6ef0c049c0 100644 --- a/flang/test/Lower/allocate-source-pointers.f90 +++ b/flang/test/Lower/allocate-source-pointers.f90 @@ -285,11 +285,11 @@ end ! CHECK: %[[VAL_14:.*]] = fir.embox %[[VAL_12]] typeparams %[[VAL_13]] : (!fir.ptr>, index) -> !fir.box>> ! CHECK: fir.store %[[VAL_14]] to %[[VAL_3]] : !fir.ref>>> ! CHECK: %[[VAL_15:.*]] = fir.box_elesize %[[VAL_11]] : (!fir.box>) -> index -! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_3]] : (!fir.ref>>>) -> !fir.ref> -! CHECK: %[[VAL_17:.*]] = fir.convert %[[VAL_15]] : (index) -> i64 -! CHECK: %[[VAL_18:.*]] = arith.constant 1 : i32 -! CHECK: %[[VAL_19:.*]] = arith.constant 0 : i32 -! CHECK: %[[VAL_20:.*]] = arith.constant 0 : i32 +! CHECK-DAG: %[[VAL_16:.*]] = fir.convert %[[VAL_3]] : (!fir.ref>>>) -> !fir.ref> +! CHECK-DAG: %[[VAL_17:.*]] = fir.convert %[[VAL_15]] : (index) -> i64 +! CHECK-DAG: %[[VAL_18:.*]] = arith.constant 1 : i32 +! CHECK-DAG: %[[VAL_19:.*]] = arith.constant 0 : i32 +! CHECK-DAG: %[[VAL_20:.*]] = arith.constant 0 : i32 ! CHECK: fir.call @_FortranAPointerNullifyCharacter(%[[VAL_16]], %[[VAL_17]], %[[VAL_18]], %[[VAL_19]], %[[VAL_20]]) {{.*}}: (!fir.ref>, i64, i32, i32, i32) -> () ! CHECK: %[[VAL_22:.*]] = fir.convert %[[VAL_3]] : (!fir.ref>>>) -> !fir.ref> ! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_11]] : (!fir.box>) -> !fir.box diff --git a/flang/test/Lower/volatile-allocatable.f90 b/flang/test/Lower/volatile-allocatable.f90 new file mode 100644 index 000000000000..5f75a5425422 --- /dev/null +++ b/flang/test/Lower/volatile-allocatable.f90 @@ -0,0 +1,193 @@ +! RUN: bbc %s -o - --strict-fir-volatile-verifier | FileCheck %s + +! Check that class types, derived types, and polymorphic types can be volatile. +! Check their interaction with allocatable, pointer, and assumed-shape allocatable +! results in values with correctly designated or declared types. + +module derived_types + type :: base_type + integer :: i = 42 + end type + + type, extends(base_type) :: ext_type + integer :: j = 100 + end type + + type :: comp_type + character(10) :: str = "test" + integer :: arr(2) = [1, 2] + end type +end module + +subroutine test_scalar_volatile() + use derived_types + class(base_type), allocatable, volatile :: v1 + type(ext_type), allocatable, volatile :: v2 + type(comp_type), allocatable, volatile :: v3 + character(len=:), allocatable, volatile :: c1 + + ! Allocation without source + allocate(v1) + + ! Allocate polymorphic derived type with dynamic type + allocate(ext_type :: v1) + select type (v1) + type is (ext_type) + v1%j = 2 + end select + + ! Allocation with source + allocate(v2, source=ext_type()) + + ! Deferred-length characters + allocate(character(20) :: c1) + c1 = "volatile character" + + ! Allocation with components + allocate(v3) + deallocate(v1, v2, v3, c1) +end subroutine + +! Test with both volatile and asynchronous attributes +subroutine test_volatile_asynchronous() + use derived_types + class(base_type), allocatable, volatile, asynchronous :: v1(:) + integer, allocatable, volatile, asynchronous :: i1(:) + + allocate(v1(4)) + allocate(i1(4), source=[1, 2, 3, 4]) + + deallocate(v1, i1) +end subroutine + +subroutine test_select_base_type_volatile() + use derived_types + class(base_type), allocatable, volatile :: v(:) + + allocate(v(2)) + + select type(v) + class is (base_type) + v(1)%i = 100 + end select + + deallocate(v) +end subroutine + +! Test allocate with mold +subroutine test_mold_allocation() + use derived_types + type(comp_type) :: template + type(comp_type), allocatable, volatile :: v(:) + + template%str = "mold test" + template%arr = [5, 6] + + allocate(v(3), mold=template) + + deallocate(v) +end subroutine + +! Test unlimited polymorphic allocation +subroutine test_unlimited_polymorphic() + use derived_types + class(*), allocatable, volatile :: up + class(*), allocatable, volatile :: upa(:) + + ! Scalar allocation + allocate(integer :: up) + select type(up) + type is (integer) + up = 123 + end select + + ! Array allocation with source + allocate(character(10) :: up) + select type(up) + type is (character(*)) + up = "class(*)" + end select + + ! Array allocation + allocate(real :: upa(3)) + select type(upa) + type is (real) + upa = [1.1, 2.2, 3.3] + end select + + deallocate(up, upa) +end subroutine + +! CHECK-LABEL: func.func @_QPtest_scalar_volatile() { +! CHECK: %{{.+}}:2 = hlfir.declare %{{.+}} {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest_scalar_volatileEc1"} : (!fir.ref>>, volatile>) -> (!fir.ref>>, volatile>, !fir.ref>>, volatile>) +! CHECK: %{{.+}}:2 = hlfir.declare %{{.+}} {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest_scalar_volatileEv1"} : (!fir.ref>>, volatile>) -> (!fir.ref>>, volatile>, !fir.ref>>, volatile>) +! CHECK: %{{.+}}:2 = hlfir.declare %{{.+}} {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest_scalar_volatileEv2"} : (!fir.ref>>, volatile>) -> (!fir.ref>>, volatile>, !fir.ref>>, volatile>) +! CHECK: %{{.+}}:2 = hlfir.declare %{{.+}} {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest_scalar_volatileEv3"} : (!fir.ref>>, volatile>) -> (!fir.ref>>, volatile>, !fir.ref>>, volatile>) +! CHECK: fir.call @_FortranAAllocatableInitDerivedForAllocate(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, !fir.ref, i32, i32) -> () +! CHECK: %{{.+}} = fir.call @_FortranAAllocatableAllocate(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, i64, i1, !fir.box, !fir.ref, i32) -> i32 +! CHECK: fir.call @_FortranAAllocatableInitDerivedForAllocate(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, !fir.ref, i32, i32) -> () +! CHECK: %{{.+}} = fir.call @_FortranAAllocatableAllocate(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, i64, i1, !fir.box, !fir.ref, i32) -> i32 +! CHECK: %{{.+}}:2 = hlfir.declare %{{.+}} {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest_scalar_volatileEv1"} : (!fir.box>, volatile>) -> (!fir.box>, volatile>, !fir.box>, volatile>) +! CHECK: %{{.+}} = hlfir.designate %{{.+}}#0{"j"} : (!fir.box>, volatile>) -> !fir.ref +! CHECK: %{{.+}}:2 = hlfir.declare %{{.+}} {fortran_attrs = #fir.var_attrs, uniq_name = "_QQro._QMderived_typesText_type.0"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %{{.+}} = fir.call @_FortranAAllocatableAllocateSource(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, !fir.box, i1, !fir.box, !fir.ref, i32) -> i32 +! CHECK: %{{.+}}:2 = hlfir.declare %{{.+}} typeparams %{{.+}} {fortran_attrs = #fir.var_attrs, uniq_name = "_QQclX766F6C6174696C6520636861726163746572"} : (!fir.ref>, index) -> (!fir.ref>, !fir.ref>) +! CHECK: %{{.+}} = fir.call @_FortranAAllocatableAllocate(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, i64, i1, !fir.box, !fir.ref, i32) -> i32 +! CHECK: %{{.+}} = fir.call @_FortranAAllocatableDeallocatePolymorphic(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, !fir.ref, i1, !fir.box, !fir.ref, i32) -> i32 +! CHECK: %{{.+}} = fir.call @_FortranAAllocatableDeallocate(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, i1, !fir.box, !fir.ref, i32) -> i32 +! CHECK: %{{.+}} = fir.call @_FortranAAllocatableDeallocate(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, i1, !fir.box, !fir.ref, i32) -> i32 +! CHECK: %{{.+}} = fir.call @_FortranAAllocatableDeallocate(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, i1, !fir.box, !fir.ref, i32) -> i32 +! CHECK: %{{.+}} = fir.call @_FortranAAllocatableDeallocate(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, i1, !fir.box, !fir.ref, i32) -> i32 +! CHECK: %{{.+}} = fir.call @_FortranAAllocatableDeallocatePolymorphic(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, !fir.ref, i1, !fir.box, !fir.ref, i32) -> i32 +! CHECK-LABEL: func.func @_QPtest_volatile_asynchronous() { +! CHECK: %{{.+}}:2 = hlfir.declare %{{.+}} {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest_volatile_asynchronousEi1"} : (!fir.ref>>, volatile>) -> (!fir.ref>>, volatile>, !fir.ref>>, volatile>) +! CHECK: %{{.+}}:2 = hlfir.declare %{{.+}} {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest_volatile_asynchronousEv1"} : (!fir.ref>>>, volatile>) -> (!fir.ref>>>, volatile>, !fir.ref>>>, volatile>) +! CHECK: fir.call @_FortranAAllocatableInitDerivedForAllocate(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, !fir.ref, i32, i32) -> () +! CHECK: fir.call @_FortranAAllocatableSetBounds(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, i32, i64, i64) -> () +! CHECK: %{{.+}} = fir.call @_FortranAAllocatableAllocate(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, i64, i1, !fir.box, !fir.ref, i32) -> i32 +! CHECK: %{{.+}}:2 = hlfir.declare %{{.+}}(%{{.+}}) {fortran_attrs = #fir.var_attrs, uniq_name = "_QQro.4xi4.1"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) +! CHECK: fir.call @_FortranAAllocatableSetBounds(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, i32, i64, i64) -> () +! CHECK: %{{.+}} = fir.call @_FortranAAllocatableAllocateSource(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, !fir.box, i1, !fir.box, !fir.ref, i32) -> i32 +! CHECK: %{{.+}} = fir.call @_FortranAAllocatableDeallocatePolymorphic(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, !fir.ref, i1, !fir.box, !fir.ref, i32) -> i32 +! CHECK: %{{.+}} = fir.call @_FortranAAllocatableDeallocatePolymorphic(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, !fir.ref, i1, !fir.box, !fir.ref, i32) -> i32 +! CHECK-LABEL: func.func @_QPtest_select_base_type_volatile() { +! CHECK: %{{.+}}:2 = hlfir.declare %{{.+}} {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest_select_base_type_volatileEv"} : (!fir.ref>>>, volatile>) -> (!fir.ref>>>, volatile>, !fir.ref>>>, volatile>) +! CHECK: fir.call @_FortranAAllocatableInitDerivedForAllocate(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, !fir.ref, i32, i32) -> () +! CHECK: fir.call @_FortranAAllocatableSetBounds(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, i32, i64, i64) -> () +! CHECK: %{{.+}} = fir.call @_FortranAAllocatableAllocate(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, i64, i1, !fir.box, !fir.ref, i32) -> i32 +! CHECK: %{{.+}}:2 = hlfir.declare %{{.+}}(%{{.+}}) {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest_select_base_type_volatileEv"} : (!fir.class>>, volatile>, !fir.shift<1>) -> (!fir.class>>, volatile>, !fir.class>>, volatile>) +! CHECK: %{{.+}} = hlfir.designate %{{.+}}#0 (%{{.+}}) : (!fir.class>>, volatile>, index) -> !fir.class, volatile> +! CHECK: %{{.+}} = hlfir.designate %{{.+}}{"i"} : (!fir.class, volatile>) -> !fir.ref +! CHECK: %{{.+}} = fir.call @_FortranAAllocatableDeallocatePolymorphic(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, !fir.ref, i1, !fir.box, !fir.ref, i32) -> i32 +! CHECK: %{{.+}} = fir.call @_FortranAAllocatableDeallocatePolymorphic(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, !fir.ref, i1, !fir.box, !fir.ref, i32) -> i32 +! CHECK-LABEL: func.func @_QPtest_mold_allocation() { +! CHECK: %{{.+}}:2 = hlfir.declare %{{.+}} {uniq_name = "_QFtest_mold_allocationEtemplate"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %{{.+}}:2 = hlfir.declare %{{.+}} {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest_mold_allocationEv"} : (!fir.ref>>>, volatile>) -> (!fir.ref>>>, volatile>, !fir.ref>>>, volatile>) +! CHECK: %{{.+}}:2 = hlfir.declare %{{.+}} typeparams %{{.+}} {fortran_attrs = #fir.var_attrs, uniq_name = "_QQclX6D6F6C642074657374"} : (!fir.ref>, index) -> (!fir.ref>, !fir.ref>) +! CHECK: %{{.+}} = hlfir.designate %{{.+}}#0{"str"} typeparams %{{.+}} : (!fir.ref>, index) -> !fir.ref> +! CHECK: %{{.+}}:2 = hlfir.declare %{{.+}}(%{{.+}}) {fortran_attrs = #fir.var_attrs, uniq_name = "_QQro.2xi4.2"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) +! CHECK: %{{.+}} = hlfir.designate %{{.+}}#0{"arr"} shape %{{.+}} : (!fir.ref>, !fir.shape<1>) -> !fir.ref> +! CHECK: fir.call @_FortranAAllocatableApplyMold(%{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, !fir.box, i32) -> () +! CHECK: fir.call @_FortranAAllocatableSetBounds(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, i32, i64, i64) -> () +! CHECK: %{{.+}} = fir.call @_FortranAAllocatableAllocate(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, i64, i1, !fir.box, !fir.ref, i32) -> i32 +! CHECK: %{{.+}} = fir.call @_FortranAAllocatableDeallocate(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, i1, !fir.box, !fir.ref, i32) -> i32 +! CHECK: %{{.+}} = fir.call @_FortranAAllocatableDeallocate(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, i1, !fir.box, !fir.ref, i32) -> i32 +! CHECK-LABEL: func.func @_QPtest_unlimited_polymorphic() { +! CHECK: %{{.+}}:2 = hlfir.declare %{{.+}} {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest_unlimited_polymorphicEup"} : (!fir.ref>, volatile>) -> (!fir.ref>, volatile>, !fir.ref>, volatile>) +! CHECK: %{{.+}}:2 = hlfir.declare %{{.+}} {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest_unlimited_polymorphicEupa"} : (!fir.ref>>, volatile>) -> (!fir.ref>>, volatile>, !fir.ref>>, volatile>) +! CHECK: fir.call @_FortranAAllocatableInitIntrinsicForAllocate(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, i32, i32, i32, i32) -> () +! CHECK: %{{.+}} = fir.call @_FortranAAllocatableAllocate(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, i64, i1, !fir.box, !fir.ref, i32) -> i32 +! CHECK: %{{.+}}:2 = hlfir.declare %{{.+}} {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest_unlimited_polymorphicEup"} : (!fir.heap) -> (!fir.heap, !fir.heap) +! CHECK: fir.call @_FortranAAllocatableInitCharacterForAllocate(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, i64, i32, i32, i32) -> () +! CHECK: %{{.+}} = fir.call @_FortranAAllocatableAllocate(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, i64, i1, !fir.box, !fir.ref, i32) -> i32 +! CHECK: %{{.+}}:2 = hlfir.declare %{{.+}} typeparams %{{.+}} {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest_unlimited_polymorphicEup"} : (!fir.heap>, index) -> (!fir.boxchar<1>, !fir.heap>) +! CHECK: %{{.+}}:2 = hlfir.declare %{{.+}} typeparams %{{.+}} {fortran_attrs = #fir.var_attrs, uniq_name = "_QQclX636C617373282A29"} : (!fir.ref>, index) -> (!fir.ref>, !fir.ref>) +! CHECK: fir.call @_FortranAAllocatableInitIntrinsicForAllocate(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, i32, i32, i32, i32) -> () +! CHECK: fir.call @_FortranAAllocatableSetBounds(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, i32, i64, i64) -> () +! CHECK: %{{.+}} = fir.call @_FortranAAllocatableAllocate(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, i64, i1, !fir.box, !fir.ref, i32) -> i32 +! CHECK: %{{.+}}:2 = hlfir.declare %{{.+}}(%{{.+}}) {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest_unlimited_polymorphicEupa"} : (!fir.box>, volatile>, !fir.shift<1>) -> (!fir.box>, volatile>, !fir.box>, volatile>) +! CHECK: %{{.+}}:2 = hlfir.declare %{{.+}}(%{{.+}}) {fortran_attrs = #fir.var_attrs, uniq_name = "_QQro.3xr4.3"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) +! CHECK: %{{.+}} = fir.call @_FortranAAllocatableDeallocatePolymorphic(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, !fir.ref, i1, !fir.box, !fir.ref, i32) -> i32 +! CHECK: %{{.+}} = fir.call @_FortranAAllocatableDeallocatePolymorphic(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, !fir.ref, i1, !fir.box, !fir.ref, i32) -> i32 +! CHECK: %{{.+}} = fir.call @_FortranAAllocatableDeallocatePolymorphic(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, !fir.ref, i1, !fir.box, !fir.ref, i32) -> i32 +! CHECK: %{{.+}} = fir.call @_FortranAAllocatableDeallocatePolymorphic(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath : (!fir.ref>, !fir.ref, i1, !fir.box, !fir.ref, i32) -> i32