[flang-commits] [flang] [flang] get rid of descriptor in scalar type is (PR #188762)

via flang-commits flang-commits at lists.llvm.org
Fri Mar 27 03:07:01 PDT 2026


https://github.com/jeanPerier updated https://github.com/llvm/llvm-project/pull/188762

>From ca04e01c5bec22417652976be1b56a125daeb455 Mon Sep 17 00:00:00 2001
From: Jean Perier <jperier at nvidia.com>
Date: Thu, 26 Mar 2026 07:38:35 -0700
Subject: [PATCH 1/2] [flang] get rid of descriptor in scalar type is

---
 .../include/flang/Optimizer/Dialect/FIRType.h | 13 +++-
 flang/lib/Lower/Bridge.cpp                    | 77 +++++++------------
 flang/lib/Optimizer/Dialect/FIRType.cpp       | 49 +++++++++---
 .../acc-data-operands-remapping-selector.f90  | 24 ++++++
 flang/test/Lower/polymorphic.f90              |  6 +-
 flang/test/Lower/select-type.f90              | 16 ++--
 flang/test/Lower/volatile-allocatable.f90     |  9 ++-
 7 files changed, 117 insertions(+), 77 deletions(-)
 create mode 100644 flang/test/Lower/OpenACC/acc-data-operands-remapping-selector.f90

diff --git a/flang/include/flang/Optimizer/Dialect/FIRType.h b/flang/include/flang/Optimizer/Dialect/FIRType.h
index a94842d82cef3..ef3328e9799bb 100644
--- a/flang/include/flang/Optimizer/Dialect/FIRType.h
+++ b/flang/include/flang/Optimizer/Dialect/FIRType.h
@@ -48,7 +48,9 @@ class BaseBoxType : public mlir::Type {
   mlir::Type getEleTy() const;
 
   /// Get the raw address type of the memory described by the box.
-  mlir::Type getBaseAddressType() const;
+  /// When \p dropHeapOrPtr is true, the returned type is always and
+  /// fir::ReferenceType.
+  mlir::Type getBaseAddressType(bool dropHeapOrPtr = false) const;
 
   /// Unwrap element type from fir.heap, fir.ptr and fir.array.
   mlir::Type unwrapInnerType() const;
@@ -68,11 +70,20 @@ class BaseBoxType : public mlir::Type {
   /// Is this a box describing volatile memory?
   bool isVolatile() const;
 
+  /// Is this a box describing an array or assumed-rank?
+  bool isArray() const;
+
   /// Return the same type, except for the shape, that is taken the shape
   /// of shapeMold.
   BaseBoxType getBoxTypeWithNewShape(mlir::Type shapeMold) const;
   BaseBoxType getBoxTypeWithNewShape(int rank) const;
 
+  /// Return a box type with the same attributes and shape, except that the
+  /// element type that is changed to the provided one. The returned box will be
+  /// a fir.class if \p polymorphic is true and a fir.box otherwise.
+  BaseBoxType getBoxTypeWithNewElementType(mlir::Type elementType,
+                                           bool polymorphic) const;
+
   /// Return the same type, except for the attribute (fir.heap/fir.ptr).
   BaseBoxType getBoxTypeWithNewAttr(Attribute attr) const;
 
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 7459f814a0d4d..1cd4d64d40336 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -4503,10 +4503,6 @@ class FirConverter : public Fortran::lower::AbstractConverter {
     bool hasLocalScope = false;
     llvm::SmallVector<const Fortran::semantics::Scope *> typeCaseScopes;
 
-    const auto selectorIsVolatile = [&selector]() {
-      return fir::isa_volatile_type(fir::getBase(selector).getType());
-    };
-
     const auto &typeCaseList =
         std::get<std::list<Fortran::parser::SelectTypeConstruct::TypeCase>>(
             selectTypeConstruct.t);
@@ -4634,10 +4630,8 @@ class FirConverter : public Fortran::lower::AbstractConverter {
         };
 
         mlir::Type baseTy = fir::getBase(selector).getType();
-        bool isPointer = fir::isPointerType(baseTy);
-        bool isAllocatable = fir::isAllocatableType(baseTy);
-        bool isArray =
-            mlir::isa<fir::SequenceType>(fir::dyn_cast_ptrOrBoxEleTy(baseTy));
+        auto selectorBoxType = llvm::cast<fir::BaseBoxType>(baseTy);
+        bool isArray = selectorBoxType.isArray();
         const fir::BoxValue *selectorBox = selector.getBoxOf<fir::BoxValue>();
         if (std::holds_alternative<Fortran::parser::Default>(guard.u)) {
           // CLASS DEFAULT
@@ -4647,72 +4641,55 @@ class FirConverter : public Fortran::lower::AbstractConverter {
           // TYPE IS
           fir::ExactTypeAttr attr =
               mlir::dyn_cast<fir::ExactTypeAttr>(typeGuardAttr);
-          mlir::Value exactValue;
-          mlir::Type addrTy = attr.getType();
-          if (isArray) {
-            auto seqTy = mlir::dyn_cast<fir::SequenceType>(
-                fir::dyn_cast_ptrOrBoxEleTy(baseTy));
-            addrTy = fir::SequenceType::get(seqTy.getShape(), attr.getType());
-          }
-          if (isPointer)
-            addrTy = fir::PointerType::get(addrTy);
-          if (isAllocatable)
-            addrTy = fir::HeapType::get(addrTy);
+          fir::BaseBoxType newBoxType =
+              selectorBoxType.getBoxTypeWithNewElementType(
+                  attr.getType(), /*polymorphic=*/false);
+          mlir::Type addrTy =
+              newBoxType.getBaseAddressType(/*dropHeapOrPtr=*/true);
+
+          mlir::Value rawPointer = fir::BoxAddrOp::create(
+              *builder, loc, addrTy, fir::getBase(selector));
           if (std::holds_alternative<Fortran::parser::IntrinsicTypeSpec>(
                   typeSpec->u)) {
-            mlir::Type refTy =
-                fir::ReferenceType::get(addrTy, selectorIsVolatile());
-            if (isPointer || isAllocatable)
-              refTy = addrTy;
-            exactValue = fir::BoxAddrOp::create(*builder, loc, refTy,
-                                                fir::getBase(selector));
             const Fortran::semantics::IntrinsicTypeSpec *intrinsic =
                 typeSpec->declTypeSpec->AsIntrinsic();
             if (isArray) {
-              mlir::Value exact = fir::ConvertOp::create(
-                  *builder, loc,
-                  fir::BoxType::get(addrTy, selectorIsVolatile()),
-                  fir::getBase(selector));
-              addAssocEntitySymbol(selectorBox->clone(exact));
+              mlir::Value boxCast = fir::ConvertOp::create(
+                  *builder, loc, newBoxType, fir::getBase(selector));
+              addAssocEntitySymbol(selectorBox->clone(boxCast));
             } else if (intrinsic->category() ==
                        Fortran::common::TypeCategory::Character) {
               auto charTy = mlir::dyn_cast<fir::CharacterType>(attr.getType());
               mlir::Value charLen =
                   fir::factory::CharacterExprHelper(*builder, loc)
                       .readLengthFromBox(fir::getBase(selector), charTy);
-              addAssocEntitySymbol(fir::CharBoxValue(exactValue, charLen));
+              addAssocEntitySymbol(fir::CharBoxValue(rawPointer, charLen));
             } else {
-              addAssocEntitySymbol(exactValue);
+              addAssocEntitySymbol(rawPointer);
             }
           } else if (std::holds_alternative<Fortran::parser::DerivedTypeSpec>(
                          typeSpec->u)) {
-            exactValue = fir::ConvertOp::create(
-                *builder, loc, fir::BoxType::get(addrTy, selectorIsVolatile()),
-                fir::getBase(selector));
-            addAssocEntitySymbol(selectorBox->clone(exactValue));
+            if (isArray) {
+              mlir::Value boxCast = fir::ConvertOp::create(
+                  *builder, loc, newBoxType, fir::getBase(selector));
+              addAssocEntitySymbol(selectorBox->clone(boxCast));
+            } else {
+              addAssocEntitySymbol(rawPointer);
+            }
           }
         } else if (std::holds_alternative<Fortran::parser::DerivedTypeSpec>(
                        guard.u)) {
           // CLASS IS
           fir::SubclassAttr attr =
               mlir::dyn_cast<fir::SubclassAttr>(typeGuardAttr);
-          mlir::Type addrTy = attr.getType();
-          if (isArray) {
-            auto seqTy = mlir::dyn_cast<fir::SequenceType>(
-                fir::dyn_cast_ptrOrBoxEleTy(baseTy));
-            addrTy = fir::SequenceType::get(seqTy.getShape(), attr.getType());
-          }
-          if (isPointer)
-            addrTy = fir::PointerType::get(addrTy);
-          if (isAllocatable)
-            addrTy = fir::HeapType::get(addrTy);
-          mlir::Type classTy =
-              fir::ClassType::get(addrTy, selectorIsVolatile());
-          if (classTy == baseTy) {
+          fir::BaseBoxType newClassType =
+              selectorBoxType.getBoxTypeWithNewElementType(
+                  attr.getType(), /*polymorphic=*/true);
+          if (newClassType == baseTy) {
             addAssocEntitySymbol(selector);
           } else {
             mlir::Value derived = fir::ConvertOp::create(
-                *builder, loc, classTy, fir::getBase(selector));
+                *builder, loc, newClassType, fir::getBase(selector));
             addAssocEntitySymbol(selectorBox->clone(derived));
           }
         }
diff --git a/flang/lib/Optimizer/Dialect/FIRType.cpp b/flang/lib/Optimizer/Dialect/FIRType.cpp
index ccdc8e45feede..9c058289075fa 100644
--- a/flang/lib/Optimizer/Dialect/FIRType.cpp
+++ b/flang/lib/Optimizer/Dialect/FIRType.cpp
@@ -684,30 +684,39 @@ std::string getTypeAsString(mlir::Type ty, const fir::KindMapping &kindMap,
   return buf;
 }
 
-mlir::Type changeElementType(mlir::Type type, mlir::Type newElementType,
-                             bool turnBoxIntoClass) {
+static mlir::Type changeElementTypeImpl(mlir::Type type,
+                                        mlir::Type newElementType,
+                                        bool turnBoxIntoClass,
+                                        bool turnClassIntoBox) {
   return llvm::TypeSwitch<mlir::Type, mlir::Type>(type)
       .Case([&](fir::SequenceType seqTy) -> mlir::Type {
         return fir::SequenceType::get(seqTy.getShape(), newElementType);
       })
-      .Case<fir::ReferenceType, fir::ClassType>([&](auto t) -> mlir::Type {
+      .Case<fir::ReferenceType>([&](auto t) -> mlir::Type {
         using FIRT = decltype(t);
-        auto newEleTy =
-            changeElementType(t.getEleTy(), newElementType, turnBoxIntoClass);
+        auto newEleTy = changeElementTypeImpl(
+            t.getEleTy(), newElementType, turnBoxIntoClass, turnClassIntoBox);
         return FIRT::get(newEleTy, t.isVolatile());
       })
       .Case<fir::PointerType, fir::HeapType>([&](auto t) -> mlir::Type {
         using FIRT = decltype(t);
-        return FIRT::get(
-            changeElementType(t.getEleTy(), newElementType, turnBoxIntoClass));
+        return FIRT::get(changeElementTypeImpl(
+            t.getEleTy(), newElementType, turnBoxIntoClass, turnClassIntoBox));
       })
       .Case([&](fir::BoxType t) -> mlir::Type {
         mlir::Type newInnerType =
-            changeElementType(t.getEleTy(), newElementType, false);
+            changeElementTypeImpl(t.getEleTy(), newElementType, false, false);
         if (turnBoxIntoClass)
           return fir::ClassType::get(newInnerType, t.isVolatile());
         return fir::BoxType::get(newInnerType, t.isVolatile());
       })
+      .Case([&](fir::ClassType t) -> mlir::Type {
+        mlir::Type newInnerType =
+            changeElementTypeImpl(t.getEleTy(), newElementType, false, false);
+        if (turnClassIntoBox)
+          return fir::BoxType::get(newInnerType, t.isVolatile());
+        return fir::ClassType::get(newInnerType, t.isVolatile());
+      })
       .Default([&](mlir::Type t) -> mlir::Type {
         assert((fir::isa_trivial(t) || llvm::isa<fir::RecordType>(t) ||
                 llvm::isa<mlir::NoneType>(t)) &&
@@ -716,6 +725,12 @@ mlir::Type changeElementType(mlir::Type type, mlir::Type newElementType,
       });
 }
 
+mlir::Type changeElementType(mlir::Type type, mlir::Type newElementType,
+                             bool turnBoxIntoClass) {
+  return changeElementTypeImpl(type, newElementType, turnBoxIntoClass,
+                               /*turnClassIntoBox=*/false);
+}
+
 } // namespace fir
 
 namespace {
@@ -1432,11 +1447,11 @@ mlir::Type BaseBoxType::getEleTy() const {
           [](auto type) { return type.getEleTy(); });
 }
 
-mlir::Type BaseBoxType::getBaseAddressType() const {
+mlir::Type BaseBoxType::getBaseAddressType(bool dropHeapOrPtr) const {
   mlir::Type eleTy = getEleTy();
-  if (fir::isa_ref_type(eleTy))
+  if (!dropHeapOrPtr && fir::isa_ref_type(eleTy))
     return eleTy;
-  return fir::ReferenceType::get(eleTy, isVolatile());
+  return fir::ReferenceType::get(getElementOrSequenceType(), isVolatile());
 }
 
 mlir::Type BaseBoxType::unwrapInnerType() const {
@@ -1500,6 +1515,14 @@ fir::BaseBoxType fir::BaseBoxType::getBoxTypeWithNewShape(int rank) const {
   return mlir::cast<fir::BaseBoxType>(changeTypeShape(*this, newShape));
 }
 
+fir::BaseBoxType
+fir::BaseBoxType::getBoxTypeWithNewElementType(mlir::Type elementType,
+                                               bool polymorphic) const {
+  return llvm::cast<fir::BaseBoxType>(changeElementTypeImpl(
+      *this, elementType, /*turnBoxIntoClass=*/polymorphic,
+      /*turnClassIntoBox=*/!polymorphic));
+}
+
 fir::BaseBoxType fir::BaseBoxType::getBoxTypeWithNewAttr(
     fir::BaseBoxType::Attribute attr) const {
   mlir::Type baseType = fir::unwrapRefType(getEleTy());
@@ -1539,6 +1562,10 @@ bool fir::BaseBoxType::isPointerOrAllocatable() const {
 
 bool BaseBoxType::isVolatile() const { return fir::isa_volatile_type(*this); }
 
+bool BaseBoxType::isArray() const {
+  return llvm::isa<fir::SequenceType>(getElementOrSequenceType());
+}
+
 //===----------------------------------------------------------------------===//
 // FIROpsDialect
 //===----------------------------------------------------------------------===//
diff --git a/flang/test/Lower/OpenACC/acc-data-operands-remapping-selector.f90 b/flang/test/Lower/OpenACC/acc-data-operands-remapping-selector.f90
new file mode 100644
index 0000000000000..5d7f5ee9a5ae6
--- /dev/null
+++ b/flang/test/Lower/OpenACC/acc-data-operands-remapping-selector.f90
@@ -0,0 +1,24 @@
+! Test remapping of select type selector.
+! RUN: %flang_fc1 -fopenacc -emit-hlfir %s -o - | FileCheck %s
+
+module copyin_selector
+  type t
+    integer :: i
+  end type
+contains
+subroutine foo(x)
+  class(*) :: x
+  select type(x)
+    type is (t)
+      !$acc parallel copyin(x)
+        call bar(x)
+      !$acc end parallel
+  end select
+end subroutine
+end module
+! CHECK-LABEL:  func.func @_QMcopyin_selectorPfoo(
+! CHECK:    fir.select_type
+! CHECK:    %[[COPYIN:.*]] = acc.copyin varPtr(%{{.*}} : !fir.ref<!fir.type<_QMcopyin_selectorTt{i:i32}>>) -> !fir.ref<!fir.type<_QMcopyin_selectorTt{i:i32}>> {name = "x"}
+! CHECK:    acc.parallel dataOperands(%[[COPYIN]] : !fir.ref<!fir.type<_QMcopyin_selectorTt{i:i32}>>) {
+! CHECK:      %[[DECL:.*]]:2 = hlfir.declare %[[COPYIN]] {uniq_name = "_QMcopyin_selectorFfooEx"} : (!fir.ref<!fir.type<_QMcopyin_selectorTt{i:i32}>>) -> (!fir.ref<!fir.type<_QMcopyin_selectorTt{i:i32}>>, !fir.ref<!fir.type<_QMcopyin_selectorTt{i:i32}>>)
+! CHECK:      fir.call @_QPbar(%[[DECL]]#0)
diff --git a/flang/test/Lower/polymorphic.f90 b/flang/test/Lower/polymorphic.f90
index d8e800771c433..6e84bec14420b 100644
--- a/flang/test/Lower/polymorphic.f90
+++ b/flang/test/Lower/polymorphic.f90
@@ -1014,10 +1014,10 @@ subroutine test_parent_comp_in_select_type(s)
 ! CHECK:  %[[LOAD_S:.*]] = fir.load %[[S]] : !fir.ref<!fir.class<!fir.heap<!fir.type<_QMpolymorphic_testTp1{{(,sequence)?}}{a:i32,b:i32}>>>>
 ! CHECK:  fir.select_type %[[LOAD_S]] : !fir.class<!fir.heap<!fir.type<_QMpolymorphic_testTp1{{(,sequence)?}}{a:i32,b:i32}>>> [#fir.type_is<!fir.type<_QMpolymorphic_testTp2{{(,sequence)?}}{a:i32,b:i32,c:f32}>>, ^bb1, unit, ^bb2]
 ! CHECK: ^bb1:
-! CHECK:  %[[CONV_S:.*]] = fir.convert %[[LOAD_S]] : (!fir.class<!fir.heap<!fir.type<_QMpolymorphic_testTp1{{(,sequence)?}}{a:i32,b:i32}>>>) -> !fir.box<!fir.heap<!fir.type<_QMpolymorphic_testTp2{{(,sequence)?}}{a:i32,b:i32,c:f32}>>>
-! CHECK:  %[[REBOX_P1:.*]] = fir.rebox %[[CONV_S]] : (!fir.box<!fir.heap<!fir.type<_QMpolymorphic_testTp2{{(,sequence)?}}{a:i32,b:i32,c:f32}>>>) -> !fir.box<!fir.type<_QMpolymorphic_testTp1{{(,sequence)?}}{a:i32,b:i32}>>
+! CHECK:  %[[CONV_S:.*]] = fir.box_addr %[[LOAD_S]] : (!fir.class<!fir.heap<!fir.type<_QMpolymorphic_testTp1{{(,sequence)?}}{a:i32,b:i32}>>>) -> !fir.ref<!fir.type<_QMpolymorphic_testTp2{{(,sequence)?}}{a:i32,b:i32,c:f32}>>
+! CHECK:  %[[EMBOX_P1:.*]] = fir.embox %[[CONV_S]] : (!fir.ref<!fir.type<_QMpolymorphic_testTp2{{(,sequence)?}}{a:i32,b:i32,c:f32}>>) -> !fir.box<!fir.type<_QMpolymorphic_testTp1{{(,sequence)?}}{a:i32,b:i32}>>
 ! CHECK:  %[[LOAD_P:.*]] = fir.load %[[P]] : !fir.ref<!fir.class<!fir.heap<!fir.type<_QMpolymorphic_testTp1{{(,sequence)?}}{a:i32,b:i32}>>>>
-! CHECK:  %[[LHS_CONV:.*]] = fir.convert %[[REBOX_P1]] : (!fir.box<!fir.type<_QMpolymorphic_testTp1{{(,sequence)?}}{a:i32,b:i32}>>) -> !fir.ref<!fir.box<none>>
+! CHECK:  %[[LHS_CONV:.*]] = fir.convert %[[EMBOX_P1]] : (!fir.box<!fir.type<_QMpolymorphic_testTp1{{(,sequence)?}}{a:i32,b:i32}>>) -> !fir.ref<!fir.box<none>>
 ! CHECK:  %[[RHS_CONV:.*]] = fir.convert %[[LOAD_P]] : (!fir.class<!fir.heap<!fir.type<_QMpolymorphic_testTp1{{(,sequence)?}}{a:i32,b:i32}>>>) -> !fir.box<none>
 ! CHECK:  fir.call @_FortranAAssign(%[[LHS_CONV]], %[[RHS_CONV]], %{{.*}}, %{{.*}}) {{.*}} : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> ()
 
diff --git a/flang/test/Lower/select-type.f90 b/flang/test/Lower/select-type.f90
index 246b653390b59..871b084950688 100644
--- a/flang/test/Lower/select-type.f90
+++ b/flang/test/Lower/select-type.f90
@@ -660,15 +660,15 @@ subroutine select_type10(a)
 ! CHECK:  %[[SELECTOR:.*]] = fir.load %[[ARG0]] : !fir.ref<!fir.class<!fir.ptr<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>>
 ! CHECK:  fir.select_type %[[SELECTOR]] : !fir.class<!fir.ptr<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>> [#fir.type_is<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>, ^bb{{.*}}, #fir.type_is<!fir.type<_QMselect_type_lower_testTp2{a:i32,b:i32,c:i32}>>, ^bb{{.*}}, #fir.class_is<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>, ^bb{{.*}}, unit, ^bb{{.*}}]
 ! CHECK: ^bb{{.*}}:
-! CHECK:  %[[EXACT_BOX:.*]] = fir.convert %[[SELECTOR]] : (!fir.class<!fir.ptr<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>) -> !fir.box<!fir.ptr<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>
+! CHECK:  %[[EXACT_BOX:.*]] = fir.box_addr %[[SELECTOR]] : (!fir.class<!fir.ptr<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>) -> !fir.ref<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>
 ! CHECK:  %[[C1:.*]] = arith.constant 1 : i32
-! CHECK:  %[[COORD_A:.*]] = fir.coordinate_of %[[EXACT_BOX]], a : (!fir.box<!fir.ptr<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>) -> !fir.ref<i32>
+! CHECK:  %[[COORD_A:.*]] = fir.coordinate_of %[[EXACT_BOX]], a : (!fir.ref<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>) -> !fir.ref<i32>
 ! CHECK:  fir.store %[[C1]] to %[[COORD_A]] : !fir.ref<i32>
 ! CHECK:  cf.br ^bb{{.*}}
 ! CHECK: ^bb{{.*}}:
-! CHECK:  %[[EXACT_BOX:.*]] = fir.convert %[[SELECTOR]] : (!fir.class<!fir.ptr<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>) -> !fir.box<!fir.ptr<!fir.type<_QMselect_type_lower_testTp2{a:i32,b:i32,c:i32}>>>
+! CHECK:  %[[EXACT_BOX:.*]] = fir.box_addr %[[SELECTOR]] : (!fir.class<!fir.ptr<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>) -> !fir.ref<!fir.type<_QMselect_type_lower_testTp2{a:i32,b:i32,c:i32}>>
 ! CHECK:  %[[C3:.*]] = arith.constant 3 : i32
-! CHECK:  %[[COORD_C:.*]] = fir.coordinate_of %[[EXACT_BOX]], c : (!fir.box<!fir.ptr<!fir.type<_QMselect_type_lower_testTp2{a:i32,b:i32,c:i32}>>>) -> !fir.ref<i32>
+! CHECK:  %[[COORD_C:.*]] = fir.coordinate_of %[[EXACT_BOX]], c : (!fir.ref<!fir.type<_QMselect_type_lower_testTp2{a:i32,b:i32,c:i32}>>) -> !fir.ref<i32>
 ! CHECK:  fir.store %[[C3]] to %[[COORD_C]] : !fir.ref<i32>
 ! CHECK:  cf.br ^bb{{.*}}
 ! CHECK: ^bb{{.*}}
@@ -693,15 +693,15 @@ subroutine select_type11(a)
 ! CHECK: %[[SELECTOR:.*]] = fir.load %[[ARG0]] : !fir.ref<!fir.class<!fir.heap<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>>
 ! CHECK: fir.select_type %[[SELECTOR]] : !fir.class<!fir.heap<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>> [#fir.type_is<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>, ^bb1, #fir.type_is<!fir.type<_QMselect_type_lower_testTp2{a:i32,b:i32,c:i32}>>, ^bb2, unit, ^bb3]
 ! CHECK: ^bb{{.*}}:
-! CHECK:  %[[EXACT_BOX:.*]] = fir.convert %[[SELECTOR]] : (!fir.class<!fir.heap<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>) -> !fir.box<!fir.heap<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>
+! CHECK:  %[[EXACT_BOX:.*]] = fir.box_addr %[[SELECTOR]] : (!fir.class<!fir.heap<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>) -> !fir.ref<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>
 ! CHECK:  %[[C1:.*]] = arith.constant 1 : i32
-! CHECK:  %[[COORD_A:.*]] = fir.coordinate_of %[[EXACT_BOX]], a : (!fir.box<!fir.heap<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>) -> !fir.ref<i32>
+! CHECK:  %[[COORD_A:.*]] = fir.coordinate_of %[[EXACT_BOX]], a : (!fir.ref<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>) -> !fir.ref<i32>
 ! CHECK:  fir.store %[[C1]] to %[[COORD_A]] : !fir.ref<i32>
 ! CHECK:  cf.br ^bb{{.*}}
 ! CHECK: ^bb{{.*}}:
-! CHECK:  %[[EXACT_BOX:.*]] = fir.convert %[[SELECTOR]] : (!fir.class<!fir.heap<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>) -> !fir.box<!fir.heap<!fir.type<_QMselect_type_lower_testTp2{a:i32,b:i32,c:i32}>>>
+! CHECK:  %[[EXACT_BOX:.*]] = fir.box_addr %[[SELECTOR]] : (!fir.class<!fir.heap<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>) -> !fir.ref<!fir.type<_QMselect_type_lower_testTp2{a:i32,b:i32,c:i32}>>
 ! CHECK:  %[[C3:.*]] = arith.constant 3 : i32
-! CHECK:  %[[COORD_C:.*]] = fir.coordinate_of %[[EXACT_BOX]], c : (!fir.box<!fir.heap<!fir.type<_QMselect_type_lower_testTp2{a:i32,b:i32,c:i32}>>>) -> !fir.ref<i32>
+! CHECK:  %[[COORD_C:.*]] = fir.coordinate_of %[[EXACT_BOX]], c : (!fir.ref<!fir.type<_QMselect_type_lower_testTp2{a:i32,b:i32,c:i32}>>) -> !fir.ref<i32>
 ! CHECK:  fir.store %[[C3]] to %[[COORD_C]] : !fir.ref<i32>
 ! CHECK:  cf.br ^bb{{.*}}
 
diff --git a/flang/test/Lower/volatile-allocatable.f90 b/flang/test/Lower/volatile-allocatable.f90
index 4c0bea60ecaa1..496dfbd8c498c 100644
--- a/flang/test/Lower/volatile-allocatable.f90
+++ b/flang/test/Lower/volatile-allocatable.f90
@@ -127,8 +127,9 @@ subroutine test_unlimited_polymorphic()
 ! CHECK:           %{{.+}} = fir.call @_FortranAAllocatableAllocate(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.ref<i64>, i1, !fir.box<none>, !fir.ref<i8>, i32, {{.*}}) -> i32
 ! CHECK:           fir.call @_FortranAAllocatableInitDerivedForAllocate(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.ref<none>, i32, i32) -> ()
 ! CHECK:           %{{.+}} = fir.call @_FortranAAllocatableAllocate(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.ref<i64>, i1, !fir.box<none>, !fir.ref<i8>, i32, {{.*}}) -> i32
-! CHECK:           %{{.+}}:2 = hlfir.declare %{{.+}} {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFtest_scalar_volatileEv1"} : (!fir.box<!fir.heap<!fir.type<{{.*}}>>, volatile>) -> (!fir.box<!fir.type<{{.*}}>, volatile>, !fir.box<!fir.type<{{.*}}>, volatile>)
-! CHECK:           %{{.+}} = hlfir.designate %{{.+}}#0{"j"}   : (!fir.box<!fir.type<{{.*}}>, volatile>) -> !fir.ref<i32, volatile>
+! CHECK:           %{{.+}}:2 = hlfir.declare %{{.+}} {fortran_attrs = #fir.var_attrs<volatile>, uniq_name =
+! "_QFtest_scalar_volatileEv1"} : (!fir.ref<!fir.type<{{.*}}, volatile>) -> (!fir.ref<!fir.type<{{.*}}>, volatile>, !fir.ref<!fir.type<{{.*}}>, volatile>)
+! CHECK:           %{{.+}} = hlfir.designate %{{.+}}#0{"j"}   : (!fir.ref<!fir.type<{{.*}}>, volatile>) -> !fir.ref<i32, volatile>
 ! CHECK:           %{{.+}}:2 = hlfir.declare %{{.+}} {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQro._QMderived_typesText_type.0"} : (!fir.ref<!fir.type<{{.*}}>>) -> (!fir.ref<!fir.type<{{.*}}>>, !fir.ref<!fir.type<{{.*}}>>)
 ! CHECK:           %{{.+}} = fir.call @_FortranAAllocatableAllocateSource(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.box<none>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
 ! CHECK:           %{{.+}}:2 = hlfir.declare %{{.+}} typeparams %{{.+}} {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQclX766F6C6174696C6520636861726163746572"} : (!fir.ref<!fir.char<1,18>>, index) -> (!fir.ref<!fir.char<1,18>>, !fir.ref<!fir.char<1,18>>)
@@ -178,10 +179,10 @@ subroutine test_unlimited_polymorphic()
 ! CHECK:           %{{.+}}:2 = hlfir.declare %{{.+}} {fortran_attrs = #fir.var_attrs<allocatable, volatile>, uniq_name = "_QFtest_unlimited_polymorphicEupa"} : (!fir.ref<!fir.class<!fir.heap<!fir.array<?xnone>>, volatile>, volatile>) -> (!fir.ref<!fir.class<!fir.heap<!fir.array<?xnone>>, volatile>, volatile>, !fir.ref<!fir.class<!fir.heap<!fir.array<?xnone>>, volatile>, volatile>)
 ! CHECK:           fir.call @_FortranAAllocatableInitIntrinsicForAllocate(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath<contract> : (!fir.ref<!fir.box<none>>, i32, i32, i32, i32) -> ()
 ! CHECK:           %{{.+}} = fir.call @_FortranAAllocatableAllocate(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.ref<i64>, i1, !fir.box<none>, !fir.ref<i8>, i32, {{.*}}) -> i32
-! CHECK:           %{{.+}}:2 = hlfir.declare %{{.+}} {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFtest_unlimited_polymorphicEup"} : (!fir.heap<i32>) -> (!fir.heap<i32>, !fir.heap<i32>)
+! CHECK:           %{{.+}}:2 = hlfir.declare %{{.+}} {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFtest_unlimited_polymorphicEup"} : (!fir.ref<i32, volatile>) -> (!fir.ref<i32, volatile>, !fir.ref<i32, volatile>)
 ! CHECK:           fir.call @_FortranAAllocatableInitCharacterForAllocate(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath<contract> : (!fir.ref<!fir.box<none>>, i64, i32, i32, i32) -> ()
 ! CHECK:           %{{.+}} = fir.call @_FortranAAllocatableAllocate(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.ref<i64>, i1, !fir.box<none>, !fir.ref<i8>, i32, {{.*}}) -> i32
-! CHECK:           %{{.+}}:2 = hlfir.declare %{{.+}} typeparams %{{.+}} {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFtest_unlimited_polymorphicEup"} : (!fir.heap<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.heap<!fir.char<1,?>>)
+! CHECK:           %{{.+}}:2 = hlfir.declare %{{.+}} typeparams %{{.+}} {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFtest_unlimited_polymorphicEup"} : (!fir.ref<!fir.char<1,?>, volatile>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>, volatile>)
 ! CHECK:           %{{.+}}:2 = hlfir.declare %{{.+}} typeparams %{{.+}} {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQclX636C617373282A29"} : (!fir.ref<!fir.char<1,8>>, index) -> (!fir.ref<!fir.char<1,8>>, !fir.ref<!fir.char<1,8>>)
 ! CHECK:           fir.call @_FortranAAllocatableInitIntrinsicForAllocate(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath<contract> : (!fir.ref<!fir.box<none>>, i32, i32, i32, i32) -> ()
 ! CHECK:           fir.call @_FortranAAllocatableSetBounds(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) fastmath<contract> : (!fir.ref<!fir.box<none>>, i32, i64, i64) -> ()

>From 2ea7a17c4cca8bcc789ed7c94279205789c931d9 Mon Sep 17 00:00:00 2001
From: Jean Perier <jperier at nvidia.com>
Date: Fri, 27 Mar 2026 03:02:53 -0700
Subject: [PATCH 2/2] address comments

---
 flang/include/flang/Optimizer/Dialect/FIRType.h | 2 +-
 flang/lib/Lower/Bridge.cpp                      | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/flang/include/flang/Optimizer/Dialect/FIRType.h b/flang/include/flang/Optimizer/Dialect/FIRType.h
index ef3328e9799bb..05f6a0746876f 100644
--- a/flang/include/flang/Optimizer/Dialect/FIRType.h
+++ b/flang/include/flang/Optimizer/Dialect/FIRType.h
@@ -48,7 +48,7 @@ class BaseBoxType : public mlir::Type {
   mlir::Type getEleTy() const;
 
   /// Get the raw address type of the memory described by the box.
-  /// When \p dropHeapOrPtr is true, the returned type is always and
+  /// When \p dropHeapOrPtr is true, the returned type is always a
   /// fir::ReferenceType.
   mlir::Type getBaseAddressType(bool dropHeapOrPtr = false) const;
 
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 1cd4d64d40336..647bc741e7edc 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -4631,7 +4631,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
 
         mlir::Type baseTy = fir::getBase(selector).getType();
         auto selectorBoxType = llvm::cast<fir::BaseBoxType>(baseTy);
-        bool isArray = selectorBoxType.isArray();
+        const bool isArray = selectorBoxType.isArray();
         const fir::BoxValue *selectorBox = selector.getBoxOf<fir::BoxValue>();
         if (std::holds_alternative<Fortran::parser::Default>(guard.u)) {
           // CLASS DEFAULT



More information about the flang-commits mailing list