[flang-commits] [flang] [flang] Don't pass a hidden length for BIND(C) character dummy arguments (PR #224582)

via flang-commits flang-commits at lists.llvm.org
Fri Sep 18 02:48:10 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

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

Author: Martin Schlipf (martin-schlipf)

<details>
<summary>Changes</summary>

A BIND(C) procedure uses the C calling convention, which has no hidden character length argument. Lowering nevertheless passed a character dummy as a fir.boxchar<1>, that is an address plus a length, for every dummy without the VALUE attribute. A call to a C function declared

  void takes_char(const char *);

was emitted as

  declare void @<!-- -->takes_char(ptr, i64)

which matches neither C nor what other Fortran compilers pass.

Semantics already requires a BIND(C) character dummy to have an interoperable type and rejects any length other than one, so the hidden length carries no information, and the BIND(C) character *result* path already omits it. Pass the address alone for a BIND(C) character dummy whose length is known to be one, leaving assumed-length dummies unchanged.

---
Full diff: https://github.com/llvm/llvm-project/pull/224582.diff


2 Files Affected:

- (modified) flang/lib/Lower/CallInterface.cpp (+9) 
- (added) flang/test/Lower/bindc-char-dummy.f90 (+31) 


``````````diff
diff --git a/flang/lib/Lower/CallInterface.cpp b/flang/lib/Lower/CallInterface.cpp
index 9885345bed3a5..c5b1a175564c8 100644
--- a/flang/lib/Lower/CallInterface.cpp
+++ b/flang/lib/Lower/CallInterface.cpp
@@ -1274,6 +1274,15 @@ class Fortran::lower::CallInterfaceImpl {
             fir::CharacterType::getSingleton(&mlirContext, dynamicType.kind());
         addFirOperand(charTy, nextPassedArgPosition(), Property::Value, attrs);
         addPassedArg(PassEntityBy::Value, entity, characteristics);
+      } else if (isBindC && dynamicType.knownLength().value_or(0) == 1) {
+        // Pass as fir.ref: a BIND(C) procedure uses the C calling convention,
+        // which has no hidden length argument. Semantics requires a BIND(C)
+        // character dummy to have a length of 1, so the length is already
+        // known to both sides and carries no information.
+        mlir::Type refTy = fir::ReferenceType::get(type);
+        addFirOperand(refTy, nextPassedArgPosition(), Property::BaseAddress,
+                      attrs);
+        addPassedArg(PassEntityBy::BaseAddress, entity, characteristics);
       } else {
         // Pass as fir.box_char
         mlir::Type boxCharTy =
diff --git a/flang/test/Lower/bindc-char-dummy.f90 b/flang/test/Lower/bindc-char-dummy.f90
new file mode 100644
index 0000000000000..c3311f1937ac8
--- /dev/null
+++ b/flang/test/Lower/bindc-char-dummy.f90
@@ -0,0 +1,31 @@
+! Test that a BIND(C) procedure does not pass a hidden length for a character
+! dummy argument. A BIND(C) procedure uses the C calling convention, which has
+! no such argument, and semantics already requires a BIND(C) character dummy to
+! have a length of one, so the length carries no information.
+
+! RUN: bbc -emit-hlfir %s -o - | FileCheck %s
+
+subroutine call_bindc_char_dummy(c, a)
+  interface
+    subroutine takes_char(s) bind(C, name="takes_char")
+      character(kind=1, len=1), intent(in) :: s
+    end subroutine
+    subroutine takes_char_array(s) bind(C, name="takes_char_array")
+      character(kind=1, len=1), intent(in) :: s(*)
+    end subroutine
+  end interface
+  character(kind=1, len=1) :: c
+  character(kind=1, len=1) :: a(10)
+  call takes_char(c)
+  call takes_char_array(a)
+end subroutine
+! CHECK-LABEL:   func.func @_QPcall_bindc_char_dummy(
+! CHECK:           fir.call @takes_char(%{{[^)]*}}) proc_attrs<bind_c>{{.*}} : (!fir.ref<!fir.char<1>>) -> ()
+! CHECK:           fir.call @takes_char_array(%{{[^)]*}}) proc_attrs<bind_c>{{.*}} : (!fir.ref<!fir.array<?x!fir.char<1>>>) -> ()
+
+subroutine defines_char(s) bind(C, name="defines_char")
+  character(kind=1, len=1), intent(inout) :: s
+  s = 'x'
+end subroutine
+! CHECK-LABEL:   func.func @defines_char(
+! CHECK-SAME:      %{{[^:]*}}: !fir.ref<!fir.char<1>>

``````````

</details>


https://github.com/llvm/llvm-project/pull/224582


More information about the flang-commits mailing list