[flang-commits] [flang] [flang][OpenMP] Support for "omp assumes no_openmp". (PR #233252)
via flang-commits
flang-commits at lists.llvm.org
Sun Oct 18 09:03:11 PDT 2026
https://github.com/SunilKuravinakop created https://github.com/llvm/llvm-project/pull/233252
Support for "omp assumes no_openmp".
>From e631983e72da223d16243ba1214f978ce03a92c6 Mon Sep 17 00:00:00 2001
From: Sunil Kuravinakop <koops at hpe.com>
Date: Sat, 17 Oct 2026 14:27:35 -0500
Subject: [PATCH] Support for "omp assumes no_openmp".
---
flang/docs/OpenMPSupport.md | 2 +-
flang/include/flang/Semantics/symbol.h | 2 +-
flang/lib/Lower/Bridge.cpp | 18 ++
flang/lib/Lower/OpenMP/OpenMP.cpp | 13 +-
flang/lib/Semantics/mod-file.cpp | 3 +
flang/lib/Semantics/resolve-names.cpp | 10 ++
flang/test/Lower/OpenMP/Todo/assumes.f90 | 47 +++++-
flang/test/Lower/OpenMP/assumption.f90 | 154 +++++++++++++++++-
flang/test/Parser/OpenMP/assumption.f90 | 1 +
.../OpenMP/declarative-directive01.f90 | 23 +++
10 files changed, 261 insertions(+), 12 deletions(-)
diff --git a/flang/docs/OpenMPSupport.md b/flang/docs/OpenMPSupport.md
index 83b0ad96d9ff3a..e56be4a4182e49 100644
--- a/flang/docs/OpenMPSupport.md
+++ b/flang/docs/OpenMPSupport.md
@@ -197,7 +197,7 @@ Parser/Semantics, MLIR, Lowering, or the OpenMPIRBuilder.
| nothing directive | <span class="good">done</span> | | Parser and lowering coverage exists for standalone and metadirective-selected forms (`flang/test/Parser/OpenMP/nothing.f90`, `flang/test/Lower/OpenMP/nothing.f90`, `flang/test/Lower/OpenMP/metadirective-nothing.f90`). | [llvm/llvm-project#193664](https://github.com/llvm/llvm-project/pull/193664), [llvm/llvm-project#202679](https://github.com/llvm/llvm-project/pull/202679) |
| tile and unroll constructs | <span class="part">partial</span> | | Semantics coverage exists across tile/unroll and loop-transformation tests (`flang/test/Semantics/OpenMP/tile01.f90`, `flang/test/Semantics/OpenMP/tile09.f90`, `flang/test/Semantics/OpenMP/loop-transformation-construct01.f90`), with additional lowering/transform completeness work ongoing. The `full` and `partial` clauses on `unroll` are lowered (`flang/test/Lower/OpenMP/unroll-full01.f90`, `flang/test/Lower/OpenMP/unroll-partial01.f90`). | [llvm/llvm-project#160298](https://github.com/llvm/llvm-project/pull/160298), [llvm/llvm-project#185296](https://github.com/llvm/llvm-project/pull/185296), [llvm/llvm-project#188025](https://github.com/llvm/llvm-project/pull/188025) |
| scope construct | <span class="part">partial</span> | | Scope construct support is available, with follow-on completeness work still in progress for some combinations (see also OpenMP 5.2 scope-related rows). | [llvm/llvm-project#113700](https://github.com/llvm/llvm-project/pull/113700), [llvm/llvm-project#193098](https://github.com/llvm/llvm-project/pull/193098) |
-| assumes directives | <span class="none">unclaimed</span> | | Lowering still has explicit TODO (`flang/lib/Lower/OpenMP/OpenMP.cpp` TODO: `OpenMP ASSUMES declaration`; `flang/test/Lower/OpenMP/Todo/assumes.f90`). | [llvm/llvm-project#102008](https://github.com/llvm/llvm-project/pull/102008) |
+| assumes directives | <span class="part">partial</span> | | `no_openmp` is supported. Module-level assumptions are preserved in module files for separately compiled submodules. Other clauses remain TODO-tracked (`flang/test/Lower/OpenMP/assumption.f90`, `flang/test/Lower/OpenMP/Todo/assumes.f90`). | [llvm/llvm-project#102008](https://github.com/llvm/llvm-project/pull/102008) |
| assume directive | <span class="none">unclaimed</span> | | Lowering still has explicit TODO (`flang/lib/Lower/OpenMP/OpenMP.cpp` TODO: `OpenMP ASSUME construct`; `flang/test/Lower/OpenMP/Todo/assume.f90`). | [llvm/llvm-project#102008](https://github.com/llvm/llvm-project/pull/102008) |
| default(firstprivate) | <span class="good">done</span> | | Supported for `default(firstprivate)` clause forms, with semantics and lowering coverage (`flang/test/Semantics/OpenMP/default-clause.f90`, `flang/test/Lower/OpenMP/default-clause.f90`, `flang/test/Lower/OpenMP/default-clause-byref.f90`). | [D123930](https://reviews.llvm.org/D123930) |
| default(private) | <span class="part">partial</span> | | Semantics/default-clause coverage exists (`flang/test/Semantics/OpenMP/default.f90`, `flang/test/Semantics/OpenMP/default02.f90`) with ongoing lowering completeness checks. | [llvm/llvm-project#107586](https://github.com/llvm/llvm-project/pull/107586) |
diff --git a/flang/include/flang/Semantics/symbol.h b/flang/include/flang/Semantics/symbol.h
index 35838b74dd53ee..cf102af95d03f9 100644
--- a/flang/include/flang/Semantics/symbol.h
+++ b/flang/include/flang/Semantics/symbol.h
@@ -971,7 +971,7 @@ class Symbol {
OmpThreadprivate, OmpDeclareReduction, OmpFlushed, OmpCriticalLock,
OmpIfSpecified, OmpNone, OmpPreDetermined, OmpExplicit, OmpImplicit,
OmpDependObject, OmpInclusiveScan, OmpExclusiveScan, OmpInScanReduction,
- OmpUniform);
+ OmpUniform, OmpAssumesNoOpenmp);
using Flags = common::EnumSet<Flag, Flag_enumSize>;
const Scope &owner() const { return *owner_; }
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index e52e690ab4b64f..3d884244270db8 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -77,6 +77,7 @@
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringSet.h"
+#include "llvm/IR/Assumptions.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
@@ -6507,6 +6508,23 @@ class FirConverter : public Fortran::lower::AbstractConverter {
builder->setFPMaxminBehavior(
bridge.getLoweringOptions().getFPMaxminBehavior());
builder->setInsertionPointToStart(&func.front());
+ for (const auto *assumptionScope = &scope;
+ !bridge.getSemanticsContext().langOptions().OpenMPSimd &&
+ !assumptionScope->IsGlobal();
+ assumptionScope = &assumptionScope->parent()) {
+ const auto *symbol = assumptionScope->symbol();
+ if (!symbol ||
+ !symbol->test(Fortran::semantics::Symbol::Flag::OmpAssumesNoOpenmp))
+ continue;
+ llvm::SmallVector<mlir::Attribute> llvmAttrs;
+ if (auto existing =
+ func->getAttrOfType<mlir::ArrayAttr>("llvm.passthrough"))
+ llvm::append_range(llvmAttrs, existing);
+ llvmAttrs.push_back(
+ builder->getStrArrayAttr({llvm::AssumptionAttrKey, "omp_no_openmp"}));
+ func->setAttr("llvm.passthrough", builder->getArrayAttr(llvmAttrs));
+ break;
+ }
if (funit.parent.isA<Fortran::lower::pft::FunctionLikeUnit>()) {
// Give internal linkage to internal functions. There are no name clash
// risks, but giving global linkage to internal procedure will break the
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index 57978826c5d014..5855641e2debf4 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -5889,11 +5889,14 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
semantics::SemanticsContext &semaCtx,
lower::pft::Evaluation &eval,
const parser::OmpAssumesDirective &assumesConstruct) {
- // Assumption clauses are hints with no representation in the OpenMP dialect,
- // so this declarative directive is a no-op.
- if (!semaCtx.langOptions().OpenMPSimd)
- TODO(converter.getCurrentLocation(),
- "assumption clauses on the assumes directive");
+ if (semaCtx.langOptions().OpenMPSimd)
+ return;
+
+ for (const parser::OmpClause &clause : assumesConstruct.v.Clauses().v) {
+ if (!std::holds_alternative<parser::OmpClause::NoOpenmp>(clause.u))
+ TODO(converter.genLocation(clause.source),
+ "assumption clauses on the assumes directive");
+ }
}
static void
diff --git a/flang/lib/Semantics/mod-file.cpp b/flang/lib/Semantics/mod-file.cpp
index c2d5b04a915b61..dae665eb67500e 100644
--- a/flang/lib/Semantics/mod-file.cpp
+++ b/flang/lib/Semantics/mod-file.cpp
@@ -470,6 +470,9 @@ void ModFileWriter::PutSymbols(
PutUse(symbol);
}
PutOpenMPRequirements(decls_, DEREF(scope.symbol()), context_);
+ if (scope.symbol()->test(Symbol::Flag::OmpAssumesNoOpenmp)) {
+ decls_ << "!$omp assumes no_openmp\n";
+ }
PutOpenMPDeclarativeDirectives(decls_, sorted, context_);
for (const auto &set : scope.equivalenceSets()) {
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 30c4466b847cdf..cb13e4f46d9070 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -1864,6 +1864,16 @@ class OmpVisitor : public virtual DeclarationVisitor {
bool Pre(const parser::OmpClause::To &);
bool Pre(const parser::OmpClause::From &);
+ void Post(const parser::OmpAssumesDirective &x) {
+ if (llvm::any_of(x.v.Clauses().v, [](const parser::OmpClause &clause) {
+ return std::holds_alternative<parser::OmpClause::NoOpenmp>(clause.u);
+ })) {
+ if (Symbol * symbol{currScope().symbol()}) {
+ symbol->set(Symbol::Flag::OmpAssumesNoOpenmp);
+ }
+ }
+ }
+
// Make sure that the following code is properly handled:
//
// function baz(a)
diff --git a/flang/test/Lower/OpenMP/Todo/assumes.f90 b/flang/test/Lower/OpenMP/Todo/assumes.f90
index 8ac080cd376be8..256307bb737f70 100644
--- a/flang/test/Lower/OpenMP/Todo/assumes.f90
+++ b/flang/test/Lower/OpenMP/Todo/assumes.f90
@@ -1,6 +1,45 @@
-! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -fopenmp-version=51 -o - %s 2>&1 | FileCheck %s
+! RUN: split-file %s %t
+! RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -o - %t/no-parallelism.f90 2>&1 | FileCheck %s
+! RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -o - %t/no-openmp-first.f90 2>&1 | FileCheck %s
+! RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -o - %t/no-openmp-last.f90 2>&1 | FileCheck %s
+! RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -o - %t/no-openmp-routines.f90 2>&1 | FileCheck %s
+! RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -o - %t/absent.f90 2>&1 | FileCheck %s
+! RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -o - %t/contains.f90 2>&1 | FileCheck %s
+! RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -o - %t/holds.f90 2>&1 | FileCheck %s
! CHECK: not yet implemented: assumption clauses on the assumes directive
-program p
- !$omp assumes no_openmp
-end program p
+
+!--- no-parallelism.f90
+subroutine p
+ !$omp assumes no_parallelism
+end subroutine p
+
+!--- no-openmp-first.f90
+subroutine p
+ !$omp assumes no_openmp no_parallelism
+end subroutine p
+
+!--- no-openmp-last.f90
+subroutine p
+ !$omp assumes no_parallelism no_openmp
+end subroutine p
+
+!--- no-openmp-routines.f90
+subroutine p
+ !$omp assumes no_openmp no_openmp_routines
+end subroutine p
+
+!--- absent.f90
+subroutine p
+ !$omp assumes no_openmp absent(parallel)
+end subroutine p
+
+!--- contains.f90
+subroutine p
+ !$omp assumes no_openmp contains(parallel)
+end subroutine p
+
+!--- holds.f90
+subroutine p
+ !$omp assumes no_openmp holds(.true.)
+end subroutine p
diff --git a/flang/test/Lower/OpenMP/assumption.f90 b/flang/test/Lower/OpenMP/assumption.f90
index 3cf51efd59decf..0fca20da0355d0 100644
--- a/flang/test/Lower/OpenMP/assumption.f90
+++ b/flang/test/Lower/OpenMP/assumption.f90
@@ -1,4 +1,24 @@
-! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=51 -o - %s 2>&1 | FileCheck %s
+! RUN: split-file %s %t
+! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=51 -o - %t/source.f90 2>&1 | FileCheck %s
+! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -o - %t/source.f90 2>&1 | FileCheck %s
+! RUN: %flang_fc1 -emit-llvm -fopenmp -fopenmp-version=51 -o - %t/source.f90 | FileCheck %s --check-prefix=LLVM
+! RUN: %flang_fc1 -emit-llvm -fopenmp-simd -fopenmp-version=51 -o - %t/source.f90 | FileCheck %s --check-prefix=SIMD
+! RUN: %flang_fc1 -fdebug-dump-symbols -fopenmp -fopenmp-version=51 %t/source.f90 | FileCheck %s --check-prefix=SYMBOLS
+! RUN: %flang_fc1 -fsyntax-only -fopenmp -fopenmp-version=51 -module-dir %t %t/source.f90
+! RUN: FileCheck %s --check-prefix=MODFILE --input-file=%t/assumes_module.mod
+! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=51 -I %t -module-dir %t -o - %t/submodule.f90 | FileCheck %s --check-prefix=SUBMODULE
+! RUN: %flang_fc1 -emit-llvm -fopenmp -fopenmp-version=51 -I %t -module-dir %t -o - %t/submodule.f90 | FileCheck %s --check-prefix=SUBMODULE-LLVM
+
+!--- source.f90
+! SIMD: target triple =
+! SIMD-NOT: "llvm.assume"="omp_no_openmp"
+
+! SYMBOLS-DAG: assume_block (Subroutine): Subprogram
+! SYMBOLS-DAG: assumes_module (OmpAssumesNoOpenmp): Module
+! SYMBOLS-DAG: assumes_no_openmp (Subroutine, OmpAssumesNoOpenmp): Subprogram
+! SYMBOLS-DAG: assumes_no_openmp_parallel (Subroutine, OmpAssumesNoOpenmp): Subprogram
+! SYMBOLS-DAG: assumes_no_openmp_host (Subroutine, OmpAssumesNoOpenmp): Subprogram
+! SYMBOLS-DAG: uses_assumes_module (Subroutine): Subprogram
! Lowering of the OpenMP ASSUME construct. The HOLDS clause asserts a scalar
! logical expression, which is lowered to an llvm.assume intrinsic. The block is
@@ -19,3 +39,135 @@ subroutine assume_block(x)
x = 2
end block
end subroutine assume_block
+
+module assumes_module
+ implicit none
+ !$omp assumes no_openmp
+ interface
+ module subroutine separate_work()
+ end subroutine separate_work
+ end interface
+contains
+ ! CHECK-LABEL: func.func @_QMassumes_modulePset_value
+ ! CHECK-SAME: llvm.passthrough = {{\[\[}}"llvm.assume", "omp_no_openmp"]]
+ subroutine set_value(x)
+ integer :: x
+ ! CHECK: %[[VALUE:.*]] = arith.constant 7 : i32
+ ! CHECK: hlfir.assign %[[VALUE]] to %{{.*}} : i32, !fir.ref<i32>
+ ! CHECK: return
+ x = 7
+ end subroutine set_value
+end module assumes_module
+
+! CHECK-LABEL: func.func @_QPassumes_no_openmp
+! CHECK-SAME: llvm.passthrough = {{\[\[}}"llvm.assume", "omp_no_openmp"]]
+subroutine assumes_no_openmp(x)
+ use assumes_module, only: set_value
+ implicit none
+ !$omp assumes no_openmp
+ integer :: x
+ ! CHECK: fir.call @_QMassumes_modulePset_value(%{{.*}}) {{.*}} : (!fir.ref<i32>) -> ()
+ ! CHECK: fir.call @_QPexternal_helper(%{{.*}}) {{.*}} : (!fir.ref<i32>) -> ()
+ ! CHECK: return
+ call set_value(x)
+ call external_helper(x)
+end subroutine assumes_no_openmp
+
+! Compile-only: executing this region would violate the assumption.
+! CHECK-LABEL: func.func @_QPassumes_no_openmp_parallel
+! CHECK-SAME: llvm.passthrough = {{\[\[}}"llvm.assume", "omp_no_openmp"]]
+subroutine assumes_no_openmp_parallel
+ implicit none
+ !$omp assumes no_openmp
+ ! CHECK: omp.parallel {
+ !$omp parallel
+ ! CHECK: omp.barrier
+ !$omp barrier
+ ! CHECK: omp.terminator
+ ! CHECK-NEXT: }
+ !$omp end parallel
+ ! CHECK: return
+end subroutine assumes_no_openmp_parallel
+
+! CHECK-LABEL: func.func @_QPassumes_no_openmp_host
+! CHECK-SAME: llvm.passthrough = {{\[\[}}"llvm.assume", "omp_no_openmp"]]
+subroutine assumes_no_openmp_host(x)
+ implicit none
+ !$omp assumes no_openmp
+ integer :: x
+ call internal_work(x)
+contains
+ ! CHECK-LABEL: func.func {{.*}}@_QFassumes_no_openmp_hostPinternal_work
+ ! CHECK-SAME: llvm.passthrough = {{\[\[}}"llvm.assume", "omp_no_openmp"]]
+ subroutine internal_work(value)
+ integer :: value
+ value = 9
+ end subroutine internal_work
+end subroutine assumes_no_openmp_host
+
+! CHECK-LABEL: func.func @_QPuses_assumes_module
+subroutine uses_assumes_module(x)
+ use assumes_module, only: set_value
+ implicit none
+ integer :: x
+ ! CHECK: fir.call @_QMassumes_modulePset_value(%{{.*}}) {{.*}} : (!fir.ref<i32>) -> ()
+ ! CHECK: return
+ call set_value(x)
+end subroutine uses_assumes_module
+
+! CHECK-LABEL: func.func @_QPassumes_no_openmp_local
+! CHECK-SAME: llvm.passthrough = {{\[\[}}"llvm.assume", "omp_no_openmp"]]
+subroutine assumes_no_openmp_local
+ use assumes_module, only: set_value
+ implicit none
+ !$omp assumes no_openmp
+ integer :: x
+ ! CHECK: fir.call @_QMassumes_modulePset_value(%{{.*}}) {{.*}} : (!fir.ref<i32>) -> ()
+ ! CHECK: return
+ call set_value(x)
+end subroutine assumes_no_openmp_local
+
+!--- submodule.f90
+submodule (assumes_module) assumes_implementation
+contains
+ module procedure separate_work
+ end procedure separate_work
+end submodule assumes_implementation
+
+subroutine uses_assumes_module_reload()
+ use assumes_module, only: separate_work
+ implicit none
+ call separate_work()
+end subroutine uses_assumes_module_reload
+
+! MODFILE: module assumes_module
+! MODFILE: !$omp assumes no_openmp
+
+! SUBMODULE-LABEL: func.func @_QMassumes_modulePseparate_work()
+! SUBMODULE-SAME: llvm.passthrough = {{\[\[}}"llvm.assume", "omp_no_openmp"]]
+! SUBMODULE-LABEL: func.func @_QPuses_assumes_module_reload() {
+
+! LLVM-LABEL: define void @assume_block_(
+! LLVM-SAME: {{.*}}) {
+! LLVM-LABEL: define void @_QMassumes_modulePset_value(
+! LLVM-SAME: {{.*}}) #[[NO_OPENMP:[0-9]+]] {
+! LLVM-LABEL: define void @assumes_no_openmp_(
+! LLVM-SAME: {{.*}}) #[[NO_OPENMP]] {
+! LLVM-LABEL: define void @assumes_no_openmp_parallel_(
+! LLVM-SAME: ) #[[NO_OPENMP]] {
+! LLVM: call void {{.*}}@__kmpc_fork_call
+! LLVM-LABEL: define void @assumes_no_openmp_host_(
+! LLVM-SAME: {{.*}}) #[[NO_OPENMP]] {
+! LLVM-LABEL: define internal void @_QFassumes_no_openmp_hostPinternal_work(
+! LLVM-SAME: {{.*}}) #[[NO_OPENMP]] {
+! LLVM-LABEL: define void @uses_assumes_module_(
+! LLVM-SAME: {{.*}}) {
+! LLVM-LABEL: define void @assumes_no_openmp_local_(
+! LLVM-SAME: ) #[[NO_OPENMP]] {
+! LLVM-LABEL: declare void @external_helper_(ptr)
+! LLVM: attributes #[[NO_OPENMP]] = { "llvm.assume"="omp_no_openmp" }
+
+! SUBMODULE-LLVM-LABEL: define void @_QMassumes_modulePseparate_work()
+! SUBMODULE-LLVM-SAME: #[[ATTR:[0-9]+]] {
+! SUBMODULE-LLVM-LABEL: define void @uses_assumes_module_reload_() {
+! SUBMODULE-LLVM: attributes #[[ATTR]] = { "llvm.assume"="omp_no_openmp" }
diff --git a/flang/test/Parser/OpenMP/assumption.f90 b/flang/test/Parser/OpenMP/assumption.f90
index 664fb7eee865b0..676674188b6f2b 100644
--- a/flang/test/Parser/OpenMP/assumption.f90
+++ b/flang/test/Parser/OpenMP/assumption.f90
@@ -1,5 +1,6 @@
!RUN: %flang_fc1 -fopenmp-version=51 -fopenmp -fdebug-unparse-no-sema %s | FileCheck --check-prefix="UNPARSE" %s
!RUN: %flang_fc1 -fopenmp-version=51 -fopenmp -fdebug-dump-parse-tree-no-sema %s | FileCheck --check-prefix="PARSE-TREE" %s
+!RUN: %flang_fc1 -fopenmp-version=52 -fopenmp -fdebug-unparse-no-sema %s | FileCheck --check-prefix="UNPARSE" %s
subroutine sub1
integer :: r
diff --git a/flang/test/Semantics/OpenMP/declarative-directive01.f90 b/flang/test/Semantics/OpenMP/declarative-directive01.f90
index 9e0612b5c8b53b..523d212277e828 100644
--- a/flang/test/Semantics/OpenMP/declarative-directive01.f90
+++ b/flang/test/Semantics/OpenMP/declarative-directive01.f90
@@ -96,4 +96,27 @@ subroutine declare_red_1()
print *, "sum of thread numbers is ", my_var
end subroutine declare_red_1
+module assumes_no_openmp_module
+ implicit none
+ !$omp assumes no_openmp
+contains
+ subroutine set_value(value)
+ integer :: value
+ value = 7
+ end subroutine set_value
+end module assumes_no_openmp_module
+
+subroutine assumes_no_openmp_procedure(value)
+ use assumes_no_openmp_module, only: set_value
+ implicit none
+ !$omp assumes no_openmp
+ integer :: value
+ call set_value(value)
+end subroutine assumes_no_openmp_procedure
+
+subroutine assumes_no_openmp_duplicate
+ !ERROR: At most one NO_OPENMP clause can appear on ASSUMES directive
+ !$omp assumes no_openmp no_openmp
+end subroutine assumes_no_openmp_duplicate
+
end
More information about the flang-commits
mailing list