[flang-commits] [flang] [Flang][OpenMP] Implement OMP 5.2 implicit DECLARE TARGET procedure handling (PR #196826)
via flang-commits
flang-commits at lists.llvm.org
Sun May 10 11:25:20 PDT 2026
https://github.com/blazie2004 updated https://github.com/llvm/llvm-project/pull/196826
>From c7e1e05d63da480e83cda910ba97ec47cdd35767 Mon Sep 17 00:00:00 2001
From: Jay Satish Kumar Patel <kumarpat at pe31.hpc.amslabs.hpecorp.net>
Date: Sun, 10 May 2026 13:04:32 -0500
Subject: [PATCH] Implement OMP 5.2 implicit DECLARE TARGET procedure handling
---
flang/lib/Semantics/check-omp-structure.cpp | 6 +++--
flang/lib/Semantics/openmp-utils.cpp | 4 ++-
flang/lib/Semantics/resolve-directives.cpp | 13 ++++++++++
flang/lib/Semantics/resolve-names.cpp | 25 ++++++++++++++++---
.../OpenMP/declare-target-implicit-proc.f90 | 21 ++++++++++++++++
5 files changed, 63 insertions(+), 6 deletions(-)
create mode 100644 flang/test/Semantics/OpenMP/declare-target-implicit-proc.f90
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 33ea727343cf4..4792aa6b36bbf 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -1297,11 +1297,13 @@ void OmpStructureChecker::CheckThreadprivateOrDeclareTargetVar(
llvm::omp::Directive directive{GetContext().directive};
if (name->symbol->GetUltimate().IsSubprogram()) {
- if (directive == llvm::omp::Directive::OMPD_threadprivate)
+ if (directive == llvm::omp::Directive::OMPD_threadprivate) {
context_.Say(name->source,
"The procedure name cannot be in a %s directive"_err_en_US,
ContextDirectiveAsFortran());
- // TODO: Check for procedure name in declare target directive.
+ }
+ // OMP 5.2 7.8.2 p10: a procedure name in DECLARE TARGET is valid
+ // (treated as external subroutine if not otherwise specified).
} else if (name->symbol->attrs().test(Attr::PARAMETER)) {
if (directive == llvm::omp::Directive::OMPD_threadprivate)
context_.Say(name->source,
diff --git a/flang/lib/Semantics/openmp-utils.cpp b/flang/lib/Semantics/openmp-utils.cpp
index 58aefe2e1fc52..167d4dc936d7e 100644
--- a/flang/lib/Semantics/openmp-utils.cpp
+++ b/flang/lib/Semantics/openmp-utils.cpp
@@ -190,7 +190,9 @@ bool IsVariableListItem(const Symbol &sym) {
}
bool IsExtendedListItem(const Symbol &sym) {
- return IsVariableListItem(sym) || sym.IsSubprogram();
+ // Extended-list item: variable, procedure, or procedure pointer
+ return IsVariableListItem(sym) || sym.IsSubprogram() ||
+ sym.has<ProcEntityDetails>();
}
bool IsTypeParamInquiry(const Symbol &sym) {
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index b97f7ce58a1c0..495c128ee3275 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -2972,6 +2972,19 @@ void OmpAttributeVisitor::ResolveOmpDesignator(
name->symbol = func;
}
}
+ // OMP 5.2 §7.8.2 ¶10: If a name appears in a declare target directive
+ // and has not been explicitly typed as a variable or procedure, and
+ // no other declaration gives it a procedure property, treat it as an
+ // external subroutine.
+ if (symbol->has<EntityDetails>() &&
+ !symbol->attrs().test(Attr::EXTERNAL) &&
+ !symbol->test(Symbol::Flag::Function) &&
+ !symbol->test(Symbol::Flag::Subroutine)) {
+ // Symbol is still unspecialized EntityDetails - promote to external proc
+ symbol->attrs().set(Attr::EXTERNAL);
+ symbol->set_details(ProcEntityDetails{});
+ symbol->set(Symbol::Flag::Subroutine);
+ }
}
if (directive == llvm::omp::Directive::OMPD_target_data) {
checkExclusivelists(symbol, Symbol::Flag::OmpUseDevicePtr, symbol,
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 4f824ef1321e9..7558e5ae9d8da 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -9165,18 +9165,37 @@ bool DeclarationVisitor::FindAndMarkDeclareTargetSymbol(
return true;
}
// if we find a symbol that is not a function or subroutine, we
- // currently escape without doing anything.
- break;
+ // currently escape without doing anything. Do NOT fall through
+ // to create an implicit external procedure.
+ return false;
}
// This is our loop exit condition, as parent() has an inbuilt assert
// if you call it on a top level scope, rather than returning a null
// value.
if (scope->IsTopLevel()) {
- return false;
+ break;
}
}
}
+
+ // OpenMP 5.2, 7.8.2 p10: a procedure name in DECLARE TARGET with no
+ // explicit data/procedure properties is treated as an external
+ // subroutine. Only apply this at program/module scope level, not inside
+ // subprograms where local variables could be forward-declared.
+ if (!isImplicitNoneType() &&
+ currScope().kind() != Scope::Kind::Subprogram &&
+ currScope().kind() != Scope::Kind::BlockConstruct) {
+ auto [it, inserted]{
+ currScope().try_emplace(name.source, Attrs{}, ProcEntityDetails{})};
+ Symbol &symbol{*it->second};
+ if (inserted || symbol.has<ProcEntityDetails>()) {
+ name.symbol = &symbol;
+ symbol.set(Symbol::Flag::Subroutine);
+ SetImplicitAttr(symbol, Attr::EXTERNAL);
+ return true;
+ }
+ }
}
}
return false;
diff --git a/flang/test/Semantics/OpenMP/declare-target-implicit-proc.f90 b/flang/test/Semantics/OpenMP/declare-target-implicit-proc.f90
new file mode 100644
index 0000000000000..84f270fa511b9
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/declare-target-implicit-proc.f90
@@ -0,0 +1,21 @@
+! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenmp -fopenmp-version=52
+
+! Test OpenMP 5.2 §7.8.2 ¶10: implicit external procedure in DECLARE TARGET
+
+program test_implicit_declare_target
+ integer :: n = 10
+ !DEF: /test_implicit_declare_target/ext_sub (Subroutine) EXTERNAL ProcEntity
+ !$omp declare target(ext_sub)
+
+ !$omp target
+ !REF: /test_implicit_declare_target/ext_sub
+ call ext_sub(n)
+ !$omp end target
+end program
+
+! Verify the external subroutine definition works
+subroutine ext_sub(x)
+ !$omp declare target
+ integer, intent(in) :: x
+ print *, "Called with:", x
+end subroutine
\ No newline at end of file
More information about the flang-commits
mailing list