[flang-commits] [flang] [flang] fix ICE with ignore_tkr(tk) character in explicit interface (PR #140885)

via flang-commits flang-commits at lists.llvm.org
Wed May 21 05:15:25 PDT 2025


https://github.com/jeanPerier created https://github.com/llvm/llvm-project/pull/140885

Some MPI libraries use character dummies + ignore(TKR) to allow passing any kind of buffer.
This was meant to already be handled by https://github.com/llvm/llvm-project/pull/108168

However, when the library interface also had an argument requiring an explicit interface,
`builder.convertWithSemantics` was not allowed to properly deal with the actual/dummy type
mismatch and generated bad IR causing errors like: `'fir.convert' op invalid type conversion'!fir.ref' / '!fir.boxchar\<1\>'`.

This restriction was artificial, lowering should just handle any cases allowed by semantics. Just remove it.

>From a7ff1819401b27f3b1c5e7e99eb6cc72bc020d49 Mon Sep 17 00:00:00 2001
From: Jean Perier <jperier at nvidia.com>
Date: Wed, 21 May 2025 04:57:24 -0700
Subject: [PATCH] [flang] fix ignore_tkr(tk) character in explicit interface

---
 flang/lib/Lower/ConvertCall.cpp                 | 12 ++++++++++--
 .../Lower/HLFIR/ignore-type-f77-character.f90   | 17 +++++++++++++++++
 2 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/flang/lib/Lower/ConvertCall.cpp b/flang/lib/Lower/ConvertCall.cpp
index d37d51f6ec634..7378118cfef7f 100644
--- a/flang/lib/Lower/ConvertCall.cpp
+++ b/flang/lib/Lower/ConvertCall.cpp
@@ -486,7 +486,6 @@ Fortran::lower::genCallOpAndResult(
 
   // Deal with potential mismatches in arguments types. Passing an array to a
   // scalar argument should for instance be tolerated here.
-  bool callingImplicitInterface = caller.canBeCalledViaImplicitInterface();
   for (auto [fst, snd] : llvm::zip(caller.getInputs(), funcType.getInputs())) {
     // When passing arguments to a procedure that can be called by implicit
     // interface, allow any character actual arguments to be passed to dummy
@@ -518,10 +517,17 @@ Fortran::lower::genCallOpAndResult(
         // Do not attempt any reboxing here that could break this.
         bool legacyLowering =
             !converter.getLoweringOptions().getLowerToHighLevelFIR();
+        // When dealing with a dummy character argument (fir.boxchar), the
+        // effective argument might be a non-character raw pointer. This may
+        // happen when calling an implicit interface that was previously called
+        // with a character argument, or when calling an explicit interface with
+        // an IgnoreTKR dummy character arguments. Allow creating a fir.boxchar
+        // from the raw pointer, which requires a non-trivial type conversion.
+        const bool allowCharacterConversions = true;
         bool isVolatile = fir::isa_volatile_type(snd);
         cast = builder.createVolatileCast(loc, isVolatile, fst);
         cast = builder.convertWithSemantics(loc, snd, cast,
-                                            callingImplicitInterface,
+                                            allowCharacterConversions,
                                             /*allowRebox=*/legacyLowering);
       }
     }
@@ -1446,6 +1452,8 @@ static PreparedDummyArgument preparePresentUserCallActualArgument(
   // cause the fir.if results to be assumed-rank in case of OPTIONAL dummy,
   // causing extra runtime costs due to the unknown runtime size of assumed-rank
   // descriptors.
+  // For TKR dummy characters, the boxchar creation also happens later when
+  // creating the fir.call .
   preparedDummy.dummy =
       builder.createConvert(loc, dummyTypeWithActualRank, addr);
   return preparedDummy;
diff --git a/flang/test/Lower/HLFIR/ignore-type-f77-character.f90 b/flang/test/Lower/HLFIR/ignore-type-f77-character.f90
index 41dbf82d5789d..6b2041a889e8d 100644
--- a/flang/test/Lower/HLFIR/ignore-type-f77-character.f90
+++ b/flang/test/Lower/HLFIR/ignore-type-f77-character.f90
@@ -8,6 +8,13 @@ subroutine foo(c)
     !dir$ ignore_tkr(tkrdm) c
     end subroutine
   end interface
+  interface
+    subroutine foo_requires_explicit_interface(c, i)
+    character(1)::c(*)
+    !dir$ ignore_tkr(tkrdm) c
+    integer, optional :: i
+    end subroutine
+  end interface
 contains
   subroutine test_normal()
     character(1) :: c(10)
@@ -32,4 +39,14 @@ subroutine test_weird()
 !CHECK:           %[[VAL_5:.*]] = fir.convert %{{.*}} : (!fir.ref<!fir.array<10xf32>>) -> !fir.ref<!fir.char<1,?>>
 !CHECK:           %[[VAL_6:.*]] = fir.emboxchar %[[VAL_5]], %c0{{.*}}: (!fir.ref<!fir.char<1,?>>, index) -> !fir.boxchar<1>
 !CHECK:           fir.call @_QPfoo(%[[VAL_6]]) fastmath<contract> : (!fir.boxchar<1>) -> ()
+
+  subroutine test_requires_explicit_interface(x, i)
+    real :: x(10)
+    integer :: i
+    call foo_requires_explicit_interface(x, i)
+  end subroutine
+!CHECK-LABEL:   func.func @_QMtest_char_tkPtest_requires_explicit_interface(
+!CHECK:           %[[VAL_5:.*]] = fir.convert %{{.*}} : (!fir.ref<!fir.array<10xf32>>) -> !fir.ref<!fir.char<1,?>>
+!CHECK:           %[[VAL_6:.*]] = fir.emboxchar %[[VAL_5]], %c0{{.*}}: (!fir.ref<!fir.char<1,?>>, index) -> !fir.boxchar<1>
+!CHECK:           fir.call @_QPfoo_requires_explicit_interface(%[[VAL_6]], %{{.*}})
 end module



More information about the flang-commits mailing list