[flang-commits] [flang] [Flang] External subprograms should be allowed as proc_target in procedure pointers. (PR #183268)
via flang-commits
flang-commits at lists.llvm.org
Thu Mar 12 08:22:29 PDT 2026
https://github.com/ShashwathiNavada updated https://github.com/llvm/llvm-project/pull/183268
>From dc876977bdf7e5c7ed8639047829a8dc1e93c7e5 Mon Sep 17 00:00:00 2001
From: ShashwathiNavada <shashwathinavada at gmail.com>
Date: Wed, 25 Feb 2026 04:00:02 -0600
Subject: [PATCH 1/3] External subprograms should be allowed as proc_target in
procedure pointers
---
flang/lib/Lower/CallInterface.cpp | 15 +++++++++++++++
flang/test/Semantics/extrn_subp.f90 | 20 ++++++++++++++++++++
2 files changed, 35 insertions(+)
create mode 100644 flang/test/Semantics/extrn_subp.f90
diff --git a/flang/lib/Lower/CallInterface.cpp b/flang/lib/Lower/CallInterface.cpp
index f5ae2de5cad8b..65cac0466d5ea 100644
--- a/flang/lib/Lower/CallInterface.cpp
+++ b/flang/lib/Lower/CallInterface.cpp
@@ -695,6 +695,21 @@ void Fortran::lower::CallInterface<T>::declare() {
mlir::ModuleOp module = converter.getModuleOp();
mlir::SymbolTable *symbolTable = converter.getMLIRSymbolTable();
func = fir::FirOpBuilder::getNamedFunction(module, symbolTable, name);
+ if (func) {
+ if constexpr (std::is_same_v<T, Fortran::lower::CalleeInterface>) {
+ mlir::FunctionType ty = genFunctionType();
+ if (!func.getBlocks().empty())
+ fir::emitFatalError(
+ func.getLoc(),
+ "conflicting procedure definition with mismatched signature");
+ if (func.getFunctionType() != ty) {
+ func.setType(ty);
+ for (const auto &placeHolder : llvm::enumerate(inputs))
+ func.setArgAttrs(placeHolder.index(),
+ placeHolder.value().attributes);
+ }
+ }
+ }
if (!func) {
mlir::Location loc = side().getCalleeLocation();
mlir::MLIRContext &mlirContext = converter.getMLIRContext();
diff --git a/flang/test/Semantics/extrn_subp.f90 b/flang/test/Semantics/extrn_subp.f90
new file mode 100644
index 0000000000000..67b3b02a85363
--- /dev/null
+++ b/flang/test/Semantics/extrn_subp.f90
@@ -0,0 +1,20 @@
+! RUN: flang %s
+
+Module m1
+ external::sub
+ type ty
+ procedure(),pointer,nopass :: ptr5=>sub
+ end type
+ procedure(),pointer:: ptr6=>sub
+end module
+
+use m1
+ integer::jj =4
+ call ptr6(10)
+ print*,"Pass"
+end
+
+subroutine sub(a)
+ integer::a
+ print*,"sub"
+end subroutine
\ No newline at end of file
>From 2fe4d47094b0e5bc9cbc9271f95f2833a3966774 Mon Sep 17 00:00:00 2001
From: ShashwathiNavada <shashwathinavada at gmail.com>
Date: Wed, 25 Feb 2026 06:31:09 -0600
Subject: [PATCH 2/3] Simple changes
---
flang/test/Semantics/extrn_subp.f90 | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/flang/test/Semantics/extrn_subp.f90 b/flang/test/Semantics/extrn_subp.f90
index 67b3b02a85363..5336daf22d248 100644
--- a/flang/test/Semantics/extrn_subp.f90
+++ b/flang/test/Semantics/extrn_subp.f90
@@ -1,4 +1,4 @@
-! RUN: flang %s
+! RUN: %python %S/test_errors.py %s %flang_fc1
Module m1
external::sub
>From 2bf192fff0669703fb080bbf1f032a199eb3be63 Mon Sep 17 00:00:00 2001
From: ShashwathiNavada <shashwathinavada at gmail.com>
Date: Thu, 12 Mar 2026 10:21:33 -0500
Subject: [PATCH 3/3] Suggested change
---
flang/lib/Lower/Bridge.cpp | 19 +++++++++++++++++-
flang/lib/Lower/CallInterface.cpp | 15 ---------------
flang/test/Lower/extrn_subp.f90 | 30 +++++++++++++++++++++++++++++
flang/test/Semantics/extrn_subp.f90 | 2 +-
4 files changed, 49 insertions(+), 17 deletions(-)
create mode 100644 flang/test/Lower/extrn_subp.f90
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 687c2f0f4a42a..10999e38883ba 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -507,7 +507,6 @@ class FirConverter : public Fortran::lower::AbstractConverter {
globalOmpRequiresSymbol = f.getScope().symbol();
},
[&](Fortran::lower::pft::ModuleLikeUnit &m) {
- lowerModuleDeclScope(m);
for (Fortran::lower::pft::ContainedUnit &unit :
m.containedUnitList)
if (auto *f =
@@ -526,6 +525,24 @@ class FirConverter : public Fortran::lower::AbstractConverter {
}
});
+ // Lower module declaration scopes now that all function
+ // declarations are available with their final signatures.
+ createBuilderOutsideOfFuncOpAndDo([&]() {
+ for (Fortran::lower::pft::Program::Units &u : pft.getUnits()) {
+ Fortran::common::visit(
+ Fortran::common::visitors{
+ [&](Fortran::lower::pft::FunctionLikeUnit &f) {},
+ [&](Fortran::lower::pft::ModuleLikeUnit &m) {
+ lowerModuleDeclScope(m);
+ },
+ [&](Fortran::lower::pft::BlockDataUnit &b) {},
+ [&](Fortran::lower::pft::CompilerDirectiveUnit &d) {},
+ [&](Fortran::lower::pft::OpenACCDirectiveUnit &d) {},
+ },
+ u);
+ }
+ });
+
// Ensure imported OpenMP declare mappers are materialized at module
// scope before lowering any constructs that may reference them.
createBuilderOutsideOfFuncOpAndDo([&]() {
diff --git a/flang/lib/Lower/CallInterface.cpp b/flang/lib/Lower/CallInterface.cpp
index 65cac0466d5ea..f5ae2de5cad8b 100644
--- a/flang/lib/Lower/CallInterface.cpp
+++ b/flang/lib/Lower/CallInterface.cpp
@@ -695,21 +695,6 @@ void Fortran::lower::CallInterface<T>::declare() {
mlir::ModuleOp module = converter.getModuleOp();
mlir::SymbolTable *symbolTable = converter.getMLIRSymbolTable();
func = fir::FirOpBuilder::getNamedFunction(module, symbolTable, name);
- if (func) {
- if constexpr (std::is_same_v<T, Fortran::lower::CalleeInterface>) {
- mlir::FunctionType ty = genFunctionType();
- if (!func.getBlocks().empty())
- fir::emitFatalError(
- func.getLoc(),
- "conflicting procedure definition with mismatched signature");
- if (func.getFunctionType() != ty) {
- func.setType(ty);
- for (const auto &placeHolder : llvm::enumerate(inputs))
- func.setArgAttrs(placeHolder.index(),
- placeHolder.value().attributes);
- }
- }
- }
if (!func) {
mlir::Location loc = side().getCalleeLocation();
mlir::MLIRContext &mlirContext = converter.getMLIRContext();
diff --git a/flang/test/Lower/extrn_subp.f90 b/flang/test/Lower/extrn_subp.f90
new file mode 100644
index 0000000000000..c43f65a72d766
--- /dev/null
+++ b/flang/test/Lower/extrn_subp.f90
@@ -0,0 +1,30 @@
+! RUN: bbc -emit-hlfir -o - %s | FileCheck %s
+
+module m1
+ external :: sub
+ type ty
+ procedure(), pointer, nopass :: ptr5 => sub
+ end type
+ procedure(), pointer :: ptr6 => sub
+end module
+
+use m1
+integer :: jj = 4
+call ptr6(10)
+print *, "Pass"
+end
+
+subroutine sub(a)
+ integer :: a
+ print *, "sub"
+end subroutine
+
+! CHECK-LABEL: func.func @_QQmain() {
+! CHECK: %[[PTR6_ADDR:.*]] = fir.address_of(@_QMm1Eptr6) : !fir.ref<!fir.boxproc<() -> ()>>
+! CHECK: %[[PTR6:.*]]:2 = hlfir.declare %[[PTR6_ADDR]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMm1Eptr6"}
+! CHECK: %[[C10:.*]] = arith.constant 10 : i32
+! CHECK: %[[TMP:.*]]:3 = hlfir.associate %[[C10]] {adapt.valuebyref} : (i32) -> (!fir.ref<i32>, !fir.ref<i32>, i1)
+! CHECK: %[[P:.*]] = fir.load %[[PTR6]]#0 : !fir.ref<!fir.boxproc<() -> ()>>
+! CHECK: %[[F:.*]] = fir.box_addr %[[P]] : (!fir.boxproc<() -> ()>) -> ((!fir.ref<i32>) -> ())
+! CHECK: fir.call %[[F]](%[[TMP]]#0) fastmath<contract> : (!fir.ref<i32>) -> ()
+! CHECK: hlfir.end_associate %[[TMP]]#1, %[[TMP]]#2 : !fir.ref<i32>, i1
\ No newline at end of file
diff --git a/flang/test/Semantics/extrn_subp.f90 b/flang/test/Semantics/extrn_subp.f90
index 5336daf22d248..2624fa4cb3a90 100644
--- a/flang/test/Semantics/extrn_subp.f90
+++ b/flang/test/Semantics/extrn_subp.f90
@@ -17,4 +17,4 @@ Module m1
subroutine sub(a)
integer::a
print*,"sub"
-end subroutine
\ No newline at end of file
+end subroutine
More information about the flang-commits
mailing list