[flang-commits] [flang] [Flang][OpenMP] Initial defaultmap(none) implementation (PR #166715)

via flang-commits flang-commits at lists.llvm.org
Thu Nov 6 09:11:07 PST 2025


https://github.com/agozillon updated https://github.com/llvm/llvm-project/pull/166715

>From 2c0281a7615347144a9ffba0d916a7d2d39eb092 Mon Sep 17 00:00:00 2001
From: agozillon <Andrew.Gozillon at amd.com>
Date: Wed, 5 Nov 2025 23:01:14 -0600
Subject: [PATCH] [Flang][OpenMP] Initial defaultmap(none) implementation

This PR adds defaultmap(none) behaviour to Flang, where we emit a semantic error if variables within the target construct do not have an associated data attribute. Similar to the way default behaves, as described by the OpenMP specification.
---
 flang/lib/Lower/OpenMP/OpenMP.cpp             |  7 +-
 flang/lib/Semantics/resolve-directives.cpp    | 96 +++++++++++++++++++
 .../Todo/defaultmap-clause-firstprivate.f90   |  2 +-
 .../OpenMP/Todo/defaultmap-clause-none.f90    | 11 ---
 .../OpenMP/defaultmap-clause-none.f90         | 96 +++++++++++++++++++
 5 files changed, 196 insertions(+), 16 deletions(-)
 delete mode 100644 flang/test/Lower/OpenMP/Todo/defaultmap-clause-none.f90
 create mode 100644 flang/test/Semantics/OpenMP/defaultmap-clause-none.f90

diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index ad456d89bc432..0467b6b46e9f3 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -1008,9 +1008,7 @@ getImplicitMapTypeAndKind(fir::FirOpBuilder &firOpBuilder,
                           mlir::omp::VariableCaptureKind::ByRef);
     break;
   case DefMap::ImplicitBehavior::Firstprivate:
-  case DefMap::ImplicitBehavior::None:
-    TODO(loc, "Firstprivate and None are currently unsupported defaultmap "
-              "behaviour");
+    TODO(loc, "Firstprivate currently unsupported defaultmap behaviour");
     break;
   case DefMap::ImplicitBehavior::From:
     return std::make_pair(mapFlag |= mlir::omp::ClauseMapFlags::from,
@@ -1032,8 +1030,9 @@ getImplicitMapTypeAndKind(fir::FirOpBuilder &firOpBuilder,
                           mlir::omp::VariableCaptureKind::ByRef);
     break;
   case DefMap::ImplicitBehavior::Default:
+  case DefMap::ImplicitBehavior::None:
     llvm_unreachable(
-        "Implicit None Behaviour Should Have Been Handled Earlier");
+        "Implicit None and Default behaviour should have been handled earlier");
     break;
   }
 
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index deb57e005a352..e66c53043e0f5 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -2965,6 +2965,72 @@ void OmpAttributeVisitor::CreateImplicitSymbols(const Symbol *symbol) {
   }
 }
 
+static bool IsOpenMPPointer(const Symbol &symbol) {
+  if (IsPointer(symbol) || IsBuiltinCPtr(symbol))
+    return true;
+  return false;
+}
+
+static bool IsOpenMPAggregate(const Symbol &symbol) {
+  if (IsAllocatable(symbol) || IsOpenMPPointer(symbol))
+    return false;
+
+  const auto *type{symbol.GetType()};
+  // OpenMP categorizes Fortran characters as aggregates.
+  if (type->category() == Fortran::semantics::DeclTypeSpec::Category::Character)
+    return true;
+
+  if (const auto *det = symbol.GetUltimate()
+          .detailsIf<Fortran::semantics::ObjectEntityDetails>())
+    if (det->IsArray())
+      return true;
+
+  if (type->AsDerived())
+    return true;
+
+  if (IsDeferredShape(symbol) || IsAssumedRank(symbol) ||
+      IsAssumedShape(symbol))
+    return true;
+  return false;
+}
+
+static bool IsOpenMPScalar(const Symbol &symbol) {
+  if (IsOpenMPAggregate(symbol) || IsOpenMPPointer(symbol) ||
+      IsAllocatable(symbol))
+    return false;
+  const auto *type{symbol.GetType()};
+  if ((!symbol.GetShape() || symbol.GetShape()->empty()) &&
+      (type->category() ==
+              Fortran::semantics::DeclTypeSpec::Category::Numeric ||
+          type->category() ==
+              Fortran::semantics::DeclTypeSpec::Category::Logical))
+    return true;
+  return false;
+}
+
+static bool DefaultMapCategoryMatchesSymbol(
+    parser::OmpVariableCategory::Value category, const Symbol &symbol) {
+  using varCat = parser::OmpVariableCategory::Value;
+  switch (category) {
+  case varCat::Scalar:
+    return IsOpenMPScalar(symbol);
+    break;
+  case varCat::Allocatable:
+    return IsAllocatable(symbol);
+    break;
+  case varCat::Aggregate:
+    return IsOpenMPAggregate(symbol);
+    break;
+  case varCat::Pointer:
+    return IsOpenMPPointer(symbol);
+    break;
+  case varCat::All:
+    return true;
+    break;
+  }
+  return false;
+}
+
 // For OpenMP constructs, check all the data-refs within the constructs
 // and adjust the symbol for each Name if necessary
 void OmpAttributeVisitor::Post(const parser::Name &name) {
@@ -3000,6 +3066,36 @@ void OmpAttributeVisitor::Post(const parser::Name &name) {
       }
     }
 
+    // TODO: handle case where default and defaultmap are present on the same
+    // construct and conflict, defaultmap should supersede default if they
+    // conflict.
+    if (!GetContext().defaultMap.empty()) {
+      // Checked before implicit data sharing attributes as this rule ignores
+      // them and expects explicit predetermined/specified attributes to be in
+      // place for the types specified.
+      if (Symbol * found{currScope().FindSymbol(name.source)}) {
+        // If the variable has declare target applied to it (enter or link) it
+        // is exempt from defaultmap(none) restrictions
+        if (!symbol->GetUltimate().test(Symbol::Flag::OmpDeclareTarget)) {
+          auto &dMap = GetContext().defaultMap;
+          for (auto defaults : dMap) {
+            if (defaults.second ==
+                parser::OmpDefaultmapClause::ImplicitBehavior::None) {
+              if (DefaultMapCategoryMatchesSymbol(defaults.first, *found)) {
+                if (!IsObjectWithDSA(*symbol)) {
+                  context_.Say(name.source,
+                      "The DEFAULTMAP(NONE) clause requires that '%s' must be "
+                      "listed in a "
+                      "data-sharing attribute, data-mapping attribute, or is_device_ptr clause"_err_en_US,
+                      symbol->name());
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+
     if (Symbol * found{currScope().FindSymbol(name.source)}) {
       if (found->GetUltimate().test(semantics::Symbol::Flag::OmpThreadprivate))
         return;
diff --git a/flang/test/Lower/OpenMP/Todo/defaultmap-clause-firstprivate.f90 b/flang/test/Lower/OpenMP/Todo/defaultmap-clause-firstprivate.f90
index 6818c39f63a3c..ce36dd45e3ab9 100644
--- a/flang/test/Lower/OpenMP/Todo/defaultmap-clause-firstprivate.f90
+++ b/flang/test/Lower/OpenMP/Todo/defaultmap-clause-firstprivate.f90
@@ -6,7 +6,7 @@ subroutine f00
     ! NOTE: This is implemented for scalars as it is the default behaviour, so we utilise
     ! a different data type.
     integer, allocatable :: i
-    !CHECK: not yet implemented: Firstprivate and None are currently unsupported defaultmap behaviour
+    !CHECK: not yet implemented: Firstprivate currently unsupported defaultmap behaviour
     !$omp target defaultmap(firstprivate)
       i = 10
     !$omp end target
diff --git a/flang/test/Lower/OpenMP/Todo/defaultmap-clause-none.f90 b/flang/test/Lower/OpenMP/Todo/defaultmap-clause-none.f90
deleted file mode 100644
index 287eb4a9dfe8f..0000000000000
--- a/flang/test/Lower/OpenMP/Todo/defaultmap-clause-none.f90
+++ /dev/null
@@ -1,11 +0,0 @@
-!RUN: %not_todo_cmd bbc -emit-hlfir -fopenmp -fopenmp-version=51 -o - %s 2>&1 | FileCheck %s
-!RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=51 -o - %s 2>&1 | FileCheck %s
-
-subroutine f00
-  implicit none
-  integer :: i
-  !CHECK: not yet implemented: Firstprivate and None are currently unsupported defaultmap behaviour
-  !$omp target defaultmap(none)
-    i = 10
-  !$omp end target
-end
diff --git a/flang/test/Semantics/OpenMP/defaultmap-clause-none.f90 b/flang/test/Semantics/OpenMP/defaultmap-clause-none.f90
new file mode 100644
index 0000000000000..08e8ebc995097
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/defaultmap-clause-none.f90
@@ -0,0 +1,96 @@
+! RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=51
+
+subroutine defaultmap_all_none_no_errors
+    implicit none
+    real :: array(10)
+    integer,  pointer :: ptr(:)
+    real, allocatable :: alloca
+    integer :: index
+
+    !$omp target defaultmap(none) map(to: index, alloca) map(tofrom: array, ptr)
+        do index = 1, 10
+            ptr(index) = array(index) + alloca
+        end do
+    !$omp end target
+end subroutine defaultmap_all_none_no_errors
+
+subroutine defaultmap_all_none
+    implicit none
+    real :: array(10)
+    integer,  pointer :: ptr(:)
+    real, allocatable :: alloca
+    integer :: index
+    !$omp target defaultmap(none)
+!ERROR: The DEFAULTMAP(NONE) clause requires that 'index' must be listed in a data-sharing attribute, data-mapping attribute, or is_device_ptr clause
+        do index = 1, 10
+!ERROR: The DEFAULTMAP(NONE) clause requires that 'ptr' must be listed in a data-sharing attribute, data-mapping attribute, or is_device_ptr clause
+!ERROR: The DEFAULTMAP(NONE) clause requires that 'index' must be listed in a data-sharing attribute, data-mapping attribute, or is_device_ptr clause
+!ERROR: The DEFAULTMAP(NONE) clause requires that 'array' must be listed in a data-sharing attribute, data-mapping attribute, or is_device_ptr clause
+!ERROR: The DEFAULTMAP(NONE) clause requires that 'index' must be listed in a data-sharing attribute, data-mapping attribute, or is_device_ptr clause
+!ERROR: The DEFAULTMAP(NONE) clause requires that 'alloca' must be listed in a data-sharing attribute, data-mapping attribute, or is_device_ptr clause
+            ptr(index) = array(index) + alloca
+        end do
+    !$omp end target
+end subroutine defaultmap_all_none
+
+subroutine defaultmap_scalar_none
+    implicit none
+    real :: array(10)
+    integer,  pointer :: ptr(:)
+    real, allocatable :: alloca
+    integer :: index
+
+    !$omp target defaultmap(none: scalar)
+!ERROR: The DEFAULTMAP(NONE) clause requires that 'index' must be listed in a data-sharing attribute, data-mapping attribute, or is_device_ptr clause
+        do index = 1, 10
+!ERROR: The DEFAULTMAP(NONE) clause requires that 'index' must be listed in a data-sharing attribute, data-mapping attribute, or is_device_ptr clause
+!ERROR: The DEFAULTMAP(NONE) clause requires that 'index' must be listed in a data-sharing attribute, data-mapping attribute, or is_device_ptr clause
+            ptr(index) = array(index) + alloca
+        end do
+    !$omp end target
+end subroutine defaultmap_scalar_none
+
+subroutine defaultmap_pointer_none
+    implicit none
+    real :: array(10)
+    integer,  pointer :: ptr(:)
+    real, allocatable :: alloca
+    integer :: index
+
+    !$omp target defaultmap(none: pointer)
+        do index = 1, 10
+!ERROR: The DEFAULTMAP(NONE) clause requires that 'ptr' must be listed in a data-sharing attribute, data-mapping attribute, or is_device_ptr clause
+            ptr(index) = array(index) + alloca
+        end do
+    !$omp end target
+end subroutine defaultmap_pointer_none
+
+subroutine defaultmap_allocatable_none
+    implicit none
+    real :: array(10)
+    integer,  pointer :: ptr(:)
+    real, allocatable :: alloca
+    integer :: index
+
+    !$omp target defaultmap(none: allocatable)
+        do index = 1, 10
+!ERROR: The DEFAULTMAP(NONE) clause requires that 'alloca' must be listed in a data-sharing attribute, data-mapping attribute, or is_device_ptr clause
+            ptr(index) = array(index) + alloca
+        end do
+    !$omp end target
+end subroutine defaultmap_allocatable_none
+
+subroutine defaultmap_aggregate_none
+    implicit none
+    real :: array(10)
+    integer,  pointer :: ptr(:)
+    real, allocatable :: alloca
+    integer :: index
+
+    !$omp target defaultmap(none: aggregate)
+        do index = 1, 10
+!ERROR: The DEFAULTMAP(NONE) clause requires that 'array' must be listed in a data-sharing attribute, data-mapping attribute, or is_device_ptr clause
+            ptr(index) = array(index) + alloca
+        end do
+    !$omp end target
+end subroutine defaultmap_aggregate_none



More information about the flang-commits mailing list