Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[flang] Correctly prepare allocatable runtime call arguments #138727

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

ashermancinelli
Copy link
Contributor

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.

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 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 in left-to-right order, which changed some of the test results.
I used CHECK-DAG to ignore the order.
@ashermancinelli ashermancinelli self-assigned this May 6, 2025
@llvmbot llvmbot added flang Flang issues not falling into any other category flang:fir-hlfir labels May 6, 2025
@llvmbot
Copy link
Member

llvmbot commented May 6, 2025

@llvm/pr-subscribers-flang-fir-hlfir

Author: Asher Mancinelli (ashermancinelli)

Changes

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.


Patch is 55.61 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/138727.diff

9 Files Affected:

  • (modified) flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h (+11-20)
  • (modified) flang/lib/Lower/Allocatable.cpp (+26-39)
  • (modified) flang/lib/Lower/ConvertExprToHLFIR.cpp (+6-6)
  • (modified) flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp (+3-5)
  • (modified) flang/test/Lower/allocatable-polymorphic.f90 (+71-71)
  • (modified) flang/test/Lower/allocate-source-allocatables-2.f90 (+12-12)
  • (modified) flang/test/Lower/allocate-source-allocatables.f90 (+7-7)
  • (modified) flang/test/Lower/allocate-source-pointers.f90 (+5-5)
  • (added) flang/test/Lower/volatile-allocatable.f90 (+152)
diff --git a/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h b/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h
index 5440b36c0c628..98d7de81c7f08 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 <cstdint>
 #include <functional>
@@ -824,33 +825,23 @@ static mlir::func::FuncOp getIORuntimeFunc(mlir::Location loc,
   return getRuntimeFunc<E>(loc, builder, /*isIO=*/true);
 }
 
-namespace helper {
-template <int N, typename A>
-void createArguments(llvm::SmallVectorImpl<mlir::Value> &result,
-                     fir::FirOpBuilder &builder, mlir::Location loc,
-                     mlir::FunctionType fTy, A arg) {
-  result.emplace_back(
-      builder.createConvertWithVolatileCast(loc, fTy.getInput(N), arg));
-}
-
-template <int N, typename A, typename... As>
-void createArguments(llvm::SmallVectorImpl<mlir::Value> &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<N + 1>(result, builder, loc, fTy, args...);
+inline llvm::SmallVector<mlir::Value>
+createArguments(fir::FirOpBuilder &builder, mlir::Location loc,
+                mlir::FunctionType fTy, llvm::ArrayRef<mlir::Value> 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);
+                             });
 }
-} // namespace helper
 
 /// Create a SmallVector of arguments for a runtime call.
 template <typename... As>
 llvm::SmallVector<mlir::Value>
 createArguments(fir::FirOpBuilder &builder, mlir::Location loc,
                 mlir::FunctionType fTy, As... args) {
-  llvm::SmallVector<mlir::Value> 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 8d0444a6e5bd4..7e32575caad9b 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<mkRTKey(AllocatableSetBounds)>(
                 loc, builder);
-  llvm::SmallVector<mlir::Value> args{box.getAddr(), dimIndex, lowerBound,
-                                      upperBound};
-  llvm::SmallVector<mlir::Value> operands;
-  for (auto [fst, snd] : llvm::zip(args, callee.getFunctionType().getInputs()))
-    operands.emplace_back(builder.createConvert(loc, snd, fst));
-  builder.create<fir::CallOp>(loc, callee, operands);
+  const auto args = fir::runtime::createArguments(
+      builder, loc, callee.getFunctionType(), box.getAddr(), dimIndex,
+      lowerBound, upperBound);
+  builder.create<fir::CallOp>(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<mlir::Value> args;
-  args.push_back(builder.createConvert(loc, inputTypes[0], box.getAddr()));
-  args.push_back(builder.createConvert(loc, inputTypes[1], len));
+  llvm::SmallVector<mlir::Value> args = {box.getAddr(), len};
   if (kind == 0)
     kind = mlir::cast<fir::CharacterType>(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<fir::CallOp>(loc, callee, args);
+  const auto convertedArgs = fir::runtime::createArguments(
+      builder, loc, callee.getFunctionType(), args);
+  builder.create<fir::CallOp>(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<mlir::Value> operands;
-  for (auto [fst, snd] : llvm::zip(args, callee.getFunctionType().getInputs()))
-    operands.emplace_back(builder.createConvert(loc, snd, fst));
-  return builder.create<fir::CallOp>(loc, callee, operands).getResult(0);
+  const auto convertedArgs = fir::runtime::createArguments(
+      builder, loc, callee.getFunctionType(), args);
+  return builder.create<fir::CallOp>(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<mkRTKey(AllocatableAllocateSource)>(
                 loc, builder);
-  llvm::SmallVector<mlir::Value> args{
-      box.getAddr(),           fir::getBase(source),
-      errorManager.hasStat,    errorManager.errMsgAddr,
-      errorManager.sourceFile, errorManager.sourceLine};
-  llvm::SmallVector<mlir::Value> operands;
-  for (auto [fst, snd] : llvm::zip(args, callee.getFunctionType().getInputs()))
-    operands.emplace_back(builder.createConvert(loc, snd, fst));
-  return builder.create<fir::CallOp>(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<fir::CallOp>(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<mkRTKey(AllocatableApplyMold)>(
                 loc, builder);
-  llvm::SmallVector<mlir::Value> 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<mlir::Value> operands;
-  for (auto [fst, snd] : llvm::zip(args, callee.getFunctionType().getInputs()))
-    operands.emplace_back(builder.createConvert(loc, snd, fst));
-  builder.create<fir::CallOp>(loc, callee, operands);
+          loc, callee.getFunctionType().getInputs()[2], rank));
+  builder.create<fir::CallOp>(loc, callee, args);
 }
 
 /// Generate a runtime call to deallocate memory.
@@ -669,15 +661,13 @@ class AllocateStmtHelper {
 
     llvm::ArrayRef<mlir::Type> inputTypes =
         callee.getFunctionType().getInputs();
-    llvm::SmallVector<mlir::Value> 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<fir::CallOp>(loc, callee, args);
   }
 
@@ -696,8 +686,6 @@ class AllocateStmtHelper {
 
     llvm::ArrayRef<mlir::Type> inputTypes =
         callee.getFunctionType().getInputs();
-    llvm::SmallVector<mlir::Value> args;
-    args.push_back(builder.createConvert(loc, inputTypes[0], box.getAddr()));
     mlir::Value categoryValue = builder.createIntegerConstant(
         loc, inputTypes[1], static_cast<int32_t>(category));
     mlir::Value kindValue =
@@ -706,10 +694,9 @@ class AllocateStmtHelper {
         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<fir::CallOp>(loc, callee, args);
   }
 
diff --git a/flang/lib/Lower/ConvertExprToHLFIR.cpp b/flang/lib/Lower/ConvertExprToHLFIR.cpp
index 04b63f92a1fb4..395f4518efb1e 100644
--- a/flang/lib/Lower/ConvertExprToHLFIR.cpp
+++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp
@@ -227,6 +227,12 @@ class HlfirDesignatorBuilder {
         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 @@ class HlfirDesignatorBuilder {
     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 eef1377f26961..711d5d1461b08 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<mlir::Type, mlir::Value> updateDeclareInputTypeWithVolatility(
     mlir::Type inputType, mlir::Value memref, mlir::OpBuilder &builder,
     fir::FortranVariableFlagsAttr fortran_attrs) {
-  if (mlir::isa<fir::BoxType, fir::ReferenceType>(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<mlir::Type, mlir::Value> updateDeclareInputTypeWithVolatility(
       inputType = FIRT::get(newEleTy, true);
     };
     llvm::TypeSwitch<mlir::Type>(inputType)
-        .Case<fir::ReferenceType, fir::BoxType>(updateType)
-        .Default([](mlir::Type t) { return t; });
+        .Case<fir::ReferenceType, fir::BoxType, fir::ClassType>(updateType);
     memref =
         builder.create<fir::VolatileCastOp>(memref.getLoc(), inputType, memref);
   }
diff --git a/flang/test/Lower/allocatable-polymorphic.f90 b/flang/test/Lower/allocatable-polymorphic.f90
index dd8671daeaf8e..10e703210ea61 100644
--- a/flang/test/Lower/allocatable-polymorphic.f90
+++ b/flang/test/Lower/allocatable-polymorphic.f90
@@ -41,7 +41,7 @@ subroutine proc2_p2(this)
   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 @@ subroutine test_pointer()
 ! CHECK: %[[P_DECL:.*]]:2 = hlfir.declare %[[P_DESC]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMpolyFtest_pointerEp"} : (!fir.ref<!fir.class<!fir.ptr<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>) -> (!fir.ref<!fir.class<!fir.ptr<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>, !fir.ref<!fir.class<!fir.ptr<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>)
 
 ! 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.class<!fir.ptr<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>) -> !fir.ref<!fir.box<none>>
-! CHECK: %[[TYPE_DESC_P1_CAST:.*]] = fir.convert %[[TYPE_DESC_P1]] : (!fir.tdesc<!fir.type<_QMpolyTp1{a:i32,b:i32}>>) -> !fir.ref<none>
-! 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.class<!fir.ptr<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>) -> !fir.ref<!fir.box<none>>
+! CHECK-DAG: %[[TYPE_DESC_P1_CAST:.*]] = fir.convert %[[TYPE_DESC_P1]] : (!fir.tdesc<!fir.type<_QMpolyTp1{a:i32,b:i32}>>) -> !fir.ref<none>
+! 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.box<none>>, !fir.ref<none>, i32, i32) -> ()
 ! CHECK: %[[P_DESC_CAST:.*]] = fir.convert %[[P_DECL]]#0 : (!fir.ref<!fir.class<!fir.ptr<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>) -> !fir.ref<!fir.box<none>>
 ! CHECK: %{{.*}} = fir.call @_FortranAPointerAllocate(%[[P_DESC_CAST]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) {{.*}}: (!fir.ref<!fir.box<none>>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
@@ -111,19 +111,19 @@ subroutine test_pointer()
 ! CHECK: fir.dispatch "proc1"(%[[P_LOAD]] : !fir.class<!fir.ptr<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>)
 
 ! 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.class<!fir.ptr<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>) -> !fir.ref<!fir.box<none>>
-! CHECK: %[[TYPE_DESC_P1_CAST:.*]] = fir.convert %[[TYPE_DESC_P1]] : (!fir.tdesc<!fir.type<_QMpolyTp1{a:i32,b:i32}>>) -> !fir.ref<none>
-! 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.class<!fir.ptr<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>) -> !fir.ref<!fir.box<none>>
+! CHECK-DAG: %[[TYPE_DESC_P1_CAST:.*]] = fir.convert %[[TYPE_DESC_P1]] : (!fir.tdesc<!fir.type<_QMpolyTp1{a:i32,b:i32}>>) -> !fir.ref<none>
+! 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.box<none>>, !fir.ref<none>, i32, i32) -> ()
 ! CHECK: %[[C1_DESC_CAST:.*]] = fir.convert %[[C1_DECL]]#0 : (!fir.ref<!fir.class<!fir.ptr<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>) -> !fir.ref<!fir.box<none>>
 ! CHECK: %{{.*}} = fir.call @_FortranAPointerAllocate(%[[C1_DESC_CAST]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) {{.*}}: (!fir.ref<!fir.box<none>>, i1, !fir.box<none>, !fir.ref<i8>, 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.class<!fir.ptr<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>) -> !fir.ref<!fir.box<none>>
-! CHECK: %[[TYPE_DESC_P2_CAST:.*]] = fir.convert %[[TYPE_DESC_P2]] : (!fir.tdesc<!fir.type<_QMpolyTp2{p1:!fir.type<_QMpolyTp1{a:i32,b:i32}>,c:i32}>>) -> !fir.ref<none>
-! 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.class<!fir.ptr<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>) -> !fir.ref<!fir.box<none>>
+! CHECK-DAG: %[[TYPE_DESC_P2_CAST:.*]] = fir.convert %[[TYPE_DESC_P2]] : (!fir.tdesc<!fir.type<_QMpolyTp2{p1:!fir.type<_QMpolyTp1{a:i32,b:i32}>,c:i32}>>) -> !fir.ref<none>
+! 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.box<none>>, !fir.ref<none>, i32, i32) -> ()
 ! CHECK: %[[C2_DESC_CAST:.*]] = fir.convert %[[C2_DECL]]#0 : (!fir.ref<!fir.class<!fir.ptr<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>) -> !fir.ref<!fir.box<none>>
 ! CHECK: %{{.*}} = fir.call @_FortranAPointerAllocate(%[[C2_DESC_CAST]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) {{.*}}: (!fir.ref<!fir.box<none>>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
@@ -147,10 +147,10 @@ subroutine test_pointer()
 ! CHECK: fir.dispatch "proc2"(%[[C2_REBOX]] : !fir.class<!fir.type<_QMpolyTp1{a:i32,b:i32}>>) (%[[C2_REBOX]] : !fir.class<!fir.type<_QMpolyTp1{a:i32,b:i32}>>) {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.class<!fir.ptr<!fir.array<?x!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>>) -> !fir.ref<!fir.box<none>>
-! CHECK: %[[TYPE_DESC_P1_CAST:.*]] = fir.convert %[[TYPE_DESC_P1]] : (!fir.tdesc<!fir.type<_QMpolyTp1{a:i32,b:i32}>>) -> !fir.ref<none>
-! CHECK: %[[RANK:.*]] = arith.constant 1 : i32
-! CHECK: %[[CORANK:.*]] = arith.constant 0 : i32
+! CHECK-DAG: %[[C3_CAST:.*]] = fir.convert %[[C3_DECL]]#0 : (!fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>>) -> !fir.ref<!fir.box<none>>
+! CHECK-DAG: %[[TYPE_DESC_P1_CAST:.*]] = fir.convert %[[TYPE_DESC_P1]] : (!fir.tdesc<!fir.type<_QMpolyTp1{a:i32,b:i32}>>) -> !fir.ref<none>
+! 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.box<none>>, !fir.ref<none>, i32, i32) -> ()
 ! CHECK: %[[C3_CAST:.*]] = fir.convert %[[C3_DECL]]#0 : (!fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>>) -> !fir.ref<!fir.box<none>>
 ! CHECK: fir.call @_FortranAPointerSetBounds(%[[C3_CAST]], %{{.*}}, %{{.*}}, %{{.*}}) {{.*}}: (!fir.ref<!fir.box<none>>, i32, i64, i64) -> ()
@@ -158,10 +158,10 @@ subroutine test_pointer()
 ! CHECK: %{{.*}} = fir.call @_FortranAPointerAllocate(%[[C3_CAST]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) {{.*}}: (!fir.ref<!fir.box<none>>, i1, !fir.box<none>, !fir.ref<i8>, 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.class<!fir.ptr<!fir.array<?x!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>>) -> !fir.ref<!fir.box<none>>
-! CHECK: %[[TYPE_DESC_P2_CAST:.*]] = fir.convert %[[TYPE_DESC_P2]] : (!fir.tdesc<!fir.type<_QMpolyTp2{p1:!fir.type<_QMpolyTp1{a:i32,b:i32}>,c:i32}>>) -> !fir.ref<none>
-! CHECK: %[[RANK:.*]] = arith.constant 1 : i32
-! CHECK: %[[CORANK:.*]] = arith.constant 0 : i32
+! CHECK-DAG: %[[C4_CAST:.*]] = fir.c...
[truncated]

Copy link
Contributor

@jeanPerier jeanPerier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Asher, LGTM!

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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated to your patch, but since you updated the comment :), why doesn't this also apply to the target data of an allocatable descriptor?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pointing this out! I discussed this with Slava, it's next on my volatile todo list :)

Copy link
Contributor

@tblah tblah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
flang:fir-hlfir flang Flang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants