Skip to content

[flang][OpenMP] Support custom mappers in target update to/from clauses#169673

Open
KrxGu wants to merge 12 commits intollvm:mainfrom
KrxGu:fix-issue-168701-target-update-mapper
Open

[flang][OpenMP] Support custom mappers in target update to/from clauses#169673
KrxGu wants to merge 12 commits intollvm:mainfrom
KrxGu:fix-issue-168701-target-update-mapper

Conversation

@KrxGu
Copy link
Contributor

@KrxGu KrxGu commented Nov 26, 2025

Fixes #168701

This patch adds support for custom mappers in OpenMP target update to() and from() clauses, implementing the OpenMP 5.2 specification.

Previously, custom mappers were only supported in map clauses. This change extends mapper resolution to target update constructs by:

  • Adding Pre(OmpClause::To) and Pre(OmpClause::From) handlers in resolve-names.cpp
  • Following the same pattern as the existing OmpMapClause handler
  • Supporting both custom mappers and the special default mapper
  • Adding proper diagnostics for undefined mappers and non-mapper symbols

Testing:

  • Semantic tests verify custom/default mapper usage and error detection
  • Lowering tests verify MLIR generation with mapper attributes
image

@llvmbot llvmbot added flang Flang issues not falling into any other category flang:fir-hlfir flang:openmp flang:semantics labels Nov 26, 2025
@llvmbot
Copy link
Member

llvmbot commented Nov 26, 2025

@llvm/pr-subscribers-flang-semantics

@llvm/pr-subscribers-flang-openmp

Author: Krish Gupta (KrxGu)

Changes

Fixes #168701

This patch adds support for custom mappers in OpenMP target update to() and from() clauses, implementing the OpenMP 5.2 specification.

Previously, custom mappers were only supported in map clauses. This change extends mapper resolution to target update constructs by:

  • Adding Pre(OmpClause::To) and Pre(OmpClause::From) handlers in resolve-names.cpp
  • Following the same pattern as the existing OmpMapClause handler
  • Supporting both custom mappers and the special default mapper
  • Adding proper diagnostics for undefined mappers and non-mapper symbols

Testing:


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

3 Files Affected:

  • (modified) flang/lib/Semantics/resolve-names.cpp (+60)
  • (added) flang/test/Lower/OpenMP/target-update-mapper.f90 (+52)
  • (added) flang/test/Semantics/OpenMP/target-update-mapper.f90 (+54)
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 2a487a6d39d51..ca17767dce924 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -1631,6 +1631,8 @@ class OmpVisitor : public virtual DeclarationVisitor {
     return true;
   }
   bool Pre(const parser::OmpMapClause &);
+  bool Pre(const parser::OmpClause::To &);
+  bool Pre(const parser::OmpClause::From &);
 
   bool Pre(const parser::OpenMPSectionsConstruct &) {
     PushScope(Scope::Kind::OtherConstruct, nullptr);
@@ -1876,6 +1878,64 @@ bool OmpVisitor::Pre(const parser::OmpMapClause &x) {
   return true;
 }
 
+bool OmpVisitor::Pre(const parser::OmpClause::To &x) {
+  // Resolve mapper names in "to" clauses (e.g., for target update)
+  auto &mods{OmpGetModifiers(x.v)};
+  if (auto *mapper{OmpGetUniqueModifier<parser::OmpMapper>(mods)}) {
+    if (auto *symbol{FindSymbol(currScope(), mapper->v)}) {
+      auto &ultimate{symbol->GetUltimate()};
+      auto *misc{ultimate.detailsIf<MiscDetails>()};
+      auto *md{ultimate.detailsIf<MapperDetails>()};
+      if (!md && (!misc || misc->kind() != MiscDetails::Kind::ConstructName))
+        context().Say(mapper->v.source,
+            "Name '%s' should be a mapper name"_err_en_US, mapper->v.source);
+      else
+        mapper->v.symbol = symbol;
+    } else {
+      // Allow the special 'default' mapper identifier without prior
+      // declaration so lowering can recognize and handle it. Emit an
+      // error for any other missing mapper identifier.
+      if (mapper->v.source.ToString() == "default") {
+        mapper->v.symbol = &MakeSymbol(
+            mapper->v, MiscDetails{MiscDetails::Kind::ConstructName});
+      } else {
+        context().Say(
+            mapper->v.source, "'%s' not declared"_err_en_US, mapper->v.source);
+      }
+    }
+  }
+  return true;
+}
+
+bool OmpVisitor::Pre(const parser::OmpClause::From &x) {
+  // Resolve mapper names in "from" clauses (e.g., for target update)
+  auto &mods{OmpGetModifiers(x.v)};
+  if (auto *mapper{OmpGetUniqueModifier<parser::OmpMapper>(mods)}) {
+    if (auto *symbol{FindSymbol(currScope(), mapper->v)}) {
+      auto &ultimate{symbol->GetUltimate()};
+      auto *misc{ultimate.detailsIf<MiscDetails>()};
+      auto *md{ultimate.detailsIf<MapperDetails>()};
+      if (!md && (!misc || misc->kind() != MiscDetails::Kind::ConstructName))
+        context().Say(mapper->v.source,
+            "Name '%s' should be a mapper name"_err_en_US, mapper->v.source);
+      else
+        mapper->v.symbol = symbol;
+    } else {
+      // Allow the special 'default' mapper identifier without prior
+      // declaration so lowering can recognize and handle it. Emit an
+      // error for any other missing mapper identifier.
+      if (mapper->v.source.ToString() == "default") {
+        mapper->v.symbol = &MakeSymbol(
+            mapper->v, MiscDetails{MiscDetails::Kind::ConstructName});
+      } else {
+        context().Say(
+            mapper->v.source, "'%s' not declared"_err_en_US, mapper->v.source);
+      }
+    }
+  }
+  return true;
+}
+
 void OmpVisitor::ProcessMapperSpecifier(const parser::OmpMapperSpecifier &spec,
     const parser::OmpClauseList &clauses) {
   // This "manually" walks the tree of the construct, because we need
diff --git a/flang/test/Lower/OpenMP/target-update-mapper.f90 b/flang/test/Lower/OpenMP/target-update-mapper.f90
new file mode 100644
index 0000000000000..d49ad51343679
--- /dev/null
+++ b/flang/test/Lower/OpenMP/target-update-mapper.f90
@@ -0,0 +1,52 @@
+! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 %s -o - | FileCheck %s
+
+! Test mapper usage in target update to/from clauses
+
+program target_update_mapper
+  implicit none
+
+  integer, parameter :: n = 4
+
+  type :: typ
+    integer, allocatable :: a(:)
+    integer, allocatable :: b(:)
+  end type typ
+
+  !$omp declare mapper(custom: typ :: t) map(t%a)
+
+  ! CHECK-LABEL: omp.declare_mapper @_QQFcustom : !fir.type<_QFTtyp{a:!fir.box<!fir.heap<!fir.array<?xi32>>>,b:!fir.box<!fir.heap<!fir.array<?xi32>>>}>
+
+  type(typ) :: t
+
+  allocate(t%a(n), source=1)
+  allocate(t%b(n), source=2)
+
+  !$omp target enter data map(alloc: t)
+
+  ! Test target update to with custom mapper
+  ! CHECK: %[[T_VAR:.*]] = fir.declare %{{.*}} {uniq_name = "_QFtarget_update_mapperEt"} : (!fir.ref<!fir.type<_QFTtyp{a:!fir.box<!fir.heap<!fir.array<?xi32>>>,b:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>) -> !fir.ref<!fir.type<_QFTtyp{a:!fir.box<!fir.heap<!fir.array<?xi32>>>,b:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>
+  ! CHECK: %[[MAP_INFO:.*]] = omp.map.info var_ptr(%[[T_VAR]] : {{.*}}, {{.*}}) map_clauses(to) capture(ByRef) mapper(@_QQFcustom) -> {{.*}}
+  ! CHECK: omp.target_update motion_entries(%[[MAP_INFO]] : {{.*}})
+  t%a = 42
+  !$omp target update to(mapper(custom): t)
+
+  !$omp target
+    t%a(:) = t%a(:) / 2
+    t%b(:) = -1
+  !$omp end target
+
+  ! Test target update from with custom mapper
+  ! CHECK: %[[MAP_INFO2:.*]] = omp.map.info var_ptr(%{{.*}} : {{.*}}, {{.*}}) map_clauses(from) capture(ByRef) mapper(@_QQFcustom) -> {{.*}}
+  ! CHECK: omp.target_update motion_entries(%[[MAP_INFO2]] : {{.*}})
+  !$omp target update from(mapper(custom): t)
+
+  ! Test target update to with default mapper
+  ! CHECK: %[[MAP_INFO3:.*]] = omp.map.info var_ptr(%{{.*}} : {{.*}}, {{.*}}) map_clauses(to) capture(ByRef) mapper(@_QQFtyp_omp_default_mapper) -> {{.*}}
+  ! CHECK: omp.target_update motion_entries(%[[MAP_INFO3]] : {{.*}})
+  !$omp target update to(mapper(default): t)
+
+  !$omp target exit data map(delete: t)
+  deallocate(t%a)
+  deallocate(t%b)
+
+end program target_update_mapper
diff --git a/flang/test/Semantics/OpenMP/target-update-mapper.f90 b/flang/test/Semantics/OpenMP/target-update-mapper.f90
new file mode 100644
index 0000000000000..f03496e155568
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/target-update-mapper.f90
@@ -0,0 +1,54 @@
+! RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=52
+
+! Test mapper usage in target update to/from clauses
+
+program target_update_mapper
+  implicit none
+
+  integer, parameter :: n = 4
+
+  type :: typ
+    integer, allocatable :: a(:)
+    integer, allocatable :: b(:)
+  end type typ
+
+  !$omp declare mapper(custom: typ :: t) map(t%a)
+
+  type(typ) :: t
+  integer :: not_a_mapper
+  allocate(t%a(n), source=1)
+  allocate(t%b(n), source=2)
+
+  !$omp target enter data map(alloc: t)
+
+  ! Valid: using custom mapper with target update to
+  t%a = 42
+  !$omp target update to(mapper(custom): t)
+
+  !$omp target
+    t%a(:) = t%a(:) / 2
+    t%b(:) = -1
+  !$omp end target
+
+  ! Valid: using custom mapper with target update from
+  !$omp target update from(mapper(custom): t)
+
+  ! Valid: using default mapper explicitly
+  !$omp target update to(mapper(default): t)
+
+  print*, t%a
+  print*, t%b
+
+  !$omp target exit data map(delete: t)
+  deallocate(t%a)
+  deallocate(t%b)
+
+  ! Test error case: undefined mapper
+  !ERROR: 'undefined_mapper' not declared
+  !$omp target update to(mapper(undefined_mapper): t)
+
+  ! Test error case: wrong kind of symbol
+  !ERROR: Name 'not_a_mapper' should be a mapper name
+  !$omp target update from(mapper(not_a_mapper): t)
+
+end program target_update_mapper

@llvmbot
Copy link
Member

llvmbot commented Nov 26, 2025

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

Author: Krish Gupta (KrxGu)

Changes

Fixes #168701

This patch adds support for custom mappers in OpenMP target update to() and from() clauses, implementing the OpenMP 5.2 specification.

Previously, custom mappers were only supported in map clauses. This change extends mapper resolution to target update constructs by:

  • Adding Pre(OmpClause::To) and Pre(OmpClause::From) handlers in resolve-names.cpp
  • Following the same pattern as the existing OmpMapClause handler
  • Supporting both custom mappers and the special default mapper
  • Adding proper diagnostics for undefined mappers and non-mapper symbols

Testing:


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

3 Files Affected:

  • (modified) flang/lib/Semantics/resolve-names.cpp (+60)
  • (added) flang/test/Lower/OpenMP/target-update-mapper.f90 (+52)
  • (added) flang/test/Semantics/OpenMP/target-update-mapper.f90 (+54)
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 2a487a6d39d51..ca17767dce924 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -1631,6 +1631,8 @@ class OmpVisitor : public virtual DeclarationVisitor {
     return true;
   }
   bool Pre(const parser::OmpMapClause &);
+  bool Pre(const parser::OmpClause::To &);
+  bool Pre(const parser::OmpClause::From &);
 
   bool Pre(const parser::OpenMPSectionsConstruct &) {
     PushScope(Scope::Kind::OtherConstruct, nullptr);
@@ -1876,6 +1878,64 @@ bool OmpVisitor::Pre(const parser::OmpMapClause &x) {
   return true;
 }
 
+bool OmpVisitor::Pre(const parser::OmpClause::To &x) {
+  // Resolve mapper names in "to" clauses (e.g., for target update)
+  auto &mods{OmpGetModifiers(x.v)};
+  if (auto *mapper{OmpGetUniqueModifier<parser::OmpMapper>(mods)}) {
+    if (auto *symbol{FindSymbol(currScope(), mapper->v)}) {
+      auto &ultimate{symbol->GetUltimate()};
+      auto *misc{ultimate.detailsIf<MiscDetails>()};
+      auto *md{ultimate.detailsIf<MapperDetails>()};
+      if (!md && (!misc || misc->kind() != MiscDetails::Kind::ConstructName))
+        context().Say(mapper->v.source,
+            "Name '%s' should be a mapper name"_err_en_US, mapper->v.source);
+      else
+        mapper->v.symbol = symbol;
+    } else {
+      // Allow the special 'default' mapper identifier without prior
+      // declaration so lowering can recognize and handle it. Emit an
+      // error for any other missing mapper identifier.
+      if (mapper->v.source.ToString() == "default") {
+        mapper->v.symbol = &MakeSymbol(
+            mapper->v, MiscDetails{MiscDetails::Kind::ConstructName});
+      } else {
+        context().Say(
+            mapper->v.source, "'%s' not declared"_err_en_US, mapper->v.source);
+      }
+    }
+  }
+  return true;
+}
+
+bool OmpVisitor::Pre(const parser::OmpClause::From &x) {
+  // Resolve mapper names in "from" clauses (e.g., for target update)
+  auto &mods{OmpGetModifiers(x.v)};
+  if (auto *mapper{OmpGetUniqueModifier<parser::OmpMapper>(mods)}) {
+    if (auto *symbol{FindSymbol(currScope(), mapper->v)}) {
+      auto &ultimate{symbol->GetUltimate()};
+      auto *misc{ultimate.detailsIf<MiscDetails>()};
+      auto *md{ultimate.detailsIf<MapperDetails>()};
+      if (!md && (!misc || misc->kind() != MiscDetails::Kind::ConstructName))
+        context().Say(mapper->v.source,
+            "Name '%s' should be a mapper name"_err_en_US, mapper->v.source);
+      else
+        mapper->v.symbol = symbol;
+    } else {
+      // Allow the special 'default' mapper identifier without prior
+      // declaration so lowering can recognize and handle it. Emit an
+      // error for any other missing mapper identifier.
+      if (mapper->v.source.ToString() == "default") {
+        mapper->v.symbol = &MakeSymbol(
+            mapper->v, MiscDetails{MiscDetails::Kind::ConstructName});
+      } else {
+        context().Say(
+            mapper->v.source, "'%s' not declared"_err_en_US, mapper->v.source);
+      }
+    }
+  }
+  return true;
+}
+
 void OmpVisitor::ProcessMapperSpecifier(const parser::OmpMapperSpecifier &spec,
     const parser::OmpClauseList &clauses) {
   // This "manually" walks the tree of the construct, because we need
diff --git a/flang/test/Lower/OpenMP/target-update-mapper.f90 b/flang/test/Lower/OpenMP/target-update-mapper.f90
new file mode 100644
index 0000000000000..d49ad51343679
--- /dev/null
+++ b/flang/test/Lower/OpenMP/target-update-mapper.f90
@@ -0,0 +1,52 @@
+! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 %s -o - | FileCheck %s
+
+! Test mapper usage in target update to/from clauses
+
+program target_update_mapper
+  implicit none
+
+  integer, parameter :: n = 4
+
+  type :: typ
+    integer, allocatable :: a(:)
+    integer, allocatable :: b(:)
+  end type typ
+
+  !$omp declare mapper(custom: typ :: t) map(t%a)
+
+  ! CHECK-LABEL: omp.declare_mapper @_QQFcustom : !fir.type<_QFTtyp{a:!fir.box<!fir.heap<!fir.array<?xi32>>>,b:!fir.box<!fir.heap<!fir.array<?xi32>>>}>
+
+  type(typ) :: t
+
+  allocate(t%a(n), source=1)
+  allocate(t%b(n), source=2)
+
+  !$omp target enter data map(alloc: t)
+
+  ! Test target update to with custom mapper
+  ! CHECK: %[[T_VAR:.*]] = fir.declare %{{.*}} {uniq_name = "_QFtarget_update_mapperEt"} : (!fir.ref<!fir.type<_QFTtyp{a:!fir.box<!fir.heap<!fir.array<?xi32>>>,b:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>) -> !fir.ref<!fir.type<_QFTtyp{a:!fir.box<!fir.heap<!fir.array<?xi32>>>,b:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>
+  ! CHECK: %[[MAP_INFO:.*]] = omp.map.info var_ptr(%[[T_VAR]] : {{.*}}, {{.*}}) map_clauses(to) capture(ByRef) mapper(@_QQFcustom) -> {{.*}}
+  ! CHECK: omp.target_update motion_entries(%[[MAP_INFO]] : {{.*}})
+  t%a = 42
+  !$omp target update to(mapper(custom): t)
+
+  !$omp target
+    t%a(:) = t%a(:) / 2
+    t%b(:) = -1
+  !$omp end target
+
+  ! Test target update from with custom mapper
+  ! CHECK: %[[MAP_INFO2:.*]] = omp.map.info var_ptr(%{{.*}} : {{.*}}, {{.*}}) map_clauses(from) capture(ByRef) mapper(@_QQFcustom) -> {{.*}}
+  ! CHECK: omp.target_update motion_entries(%[[MAP_INFO2]] : {{.*}})
+  !$omp target update from(mapper(custom): t)
+
+  ! Test target update to with default mapper
+  ! CHECK: %[[MAP_INFO3:.*]] = omp.map.info var_ptr(%{{.*}} : {{.*}}, {{.*}}) map_clauses(to) capture(ByRef) mapper(@_QQFtyp_omp_default_mapper) -> {{.*}}
+  ! CHECK: omp.target_update motion_entries(%[[MAP_INFO3]] : {{.*}})
+  !$omp target update to(mapper(default): t)
+
+  !$omp target exit data map(delete: t)
+  deallocate(t%a)
+  deallocate(t%b)
+
+end program target_update_mapper
diff --git a/flang/test/Semantics/OpenMP/target-update-mapper.f90 b/flang/test/Semantics/OpenMP/target-update-mapper.f90
new file mode 100644
index 0000000000000..f03496e155568
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/target-update-mapper.f90
@@ -0,0 +1,54 @@
+! RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=52
+
+! Test mapper usage in target update to/from clauses
+
+program target_update_mapper
+  implicit none
+
+  integer, parameter :: n = 4
+
+  type :: typ
+    integer, allocatable :: a(:)
+    integer, allocatable :: b(:)
+  end type typ
+
+  !$omp declare mapper(custom: typ :: t) map(t%a)
+
+  type(typ) :: t
+  integer :: not_a_mapper
+  allocate(t%a(n), source=1)
+  allocate(t%b(n), source=2)
+
+  !$omp target enter data map(alloc: t)
+
+  ! Valid: using custom mapper with target update to
+  t%a = 42
+  !$omp target update to(mapper(custom): t)
+
+  !$omp target
+    t%a(:) = t%a(:) / 2
+    t%b(:) = -1
+  !$omp end target
+
+  ! Valid: using custom mapper with target update from
+  !$omp target update from(mapper(custom): t)
+
+  ! Valid: using default mapper explicitly
+  !$omp target update to(mapper(default): t)
+
+  print*, t%a
+  print*, t%b
+
+  !$omp target exit data map(delete: t)
+  deallocate(t%a)
+  deallocate(t%b)
+
+  ! Test error case: undefined mapper
+  !ERROR: 'undefined_mapper' not declared
+  !$omp target update to(mapper(undefined_mapper): t)
+
+  ! Test error case: wrong kind of symbol
+  !ERROR: Name 'not_a_mapper' should be a mapper name
+  !$omp target update from(mapper(not_a_mapper): t)
+
+end program target_update_mapper

@TIFitis TIFitis requested review from TIFitis and Copilot November 26, 2025 16:37
@github-actions
Copy link

github-actions bot commented Nov 26, 2025

🐧 Linux x64 Test Results

  • 3920 tests passed
  • 201 tests skipped
  • 2 tests failed

Failed Tests

(click on a test name to see its output)

Flang

Flang.Lower/CUDA/cuda-gpu-managed.cuf
Exit Code: 1

Command Output (stdout):
--
# RUN: at line 1
bbc -emit-hlfir -fcuda -gpu=managed /home/gha/actions-runner/_work/llvm-project/llvm-project/flang/test/Lower/CUDA/cuda-gpu-managed.cuf -o - | /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/FileCheck /home/gha/actions-runner/_work/llvm-project/llvm-project/flang/test/Lower/CUDA/cuda-gpu-managed.cuf
# executed command: bbc -emit-hlfir -fcuda -gpu=managed /home/gha/actions-runner/_work/llvm-project/llvm-project/flang/test/Lower/CUDA/cuda-gpu-managed.cuf -o -
# note: command had no output on stdout or stderr
# executed command: /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/FileCheck /home/gha/actions-runner/_work/llvm-project/llvm-project/flang/test/Lower/CUDA/cuda-gpu-managed.cuf
# .---command stderr------------
# | /home/gha/actions-runner/_work/llvm-project/llvm-project/flang/test/Lower/CUDA/cuda-gpu-managed.cuf:17:10: error: CHECK: expected string not found in input
# | ! CHECK: %[[BOX:.*]] = cuf.alloc !fir.box<!fir.heap<!fir.array<?xf32>>> {bindc_name = "a", data_attr = #cuf.cuda<managed>, uniq_name = "_QFtest_implicit_managedEa"}
# |          ^
# | <stdin>:2:39: note: scanning from here
# |  func.func @_QPtest_implicit_managed() {
# |                                       ^
# | <stdin>:4:2: note: possible intended match here
# |  %1 = fir.alloca !fir.box<!fir.heap<!fir.array<?xf32>>> {bindc_name = "a", uniq_name = "_QFtest_implicit_managedEa"}
# |  ^
# | /home/gha/actions-runner/_work/llvm-project/llvm-project/flang/test/Lower/CUDA/cuda-gpu-managed.cuf:97:10: error: CHECK: expected string not found in input
# | ! CHECK: cuf.alloc {{.*}} {bindc_name = "a", data_attr = #cuf.cuda<managed>, uniq_name = "_QFtest_mixed_allocatablesEa"}
# |          ^
# | <stdin>:176:41: note: scanning from here
# |  func.func @_QPtest_mixed_allocatables() {
# |                                         ^
# | <stdin>:192:40: note: possible intended match here
# |  %11 = cuf.alloc !fir.box<!fir.heap<!fir.array<?xf32>>> {bindc_name = "m", data_attr = #cuf.cuda<managed>, uniq_name = "_QFtest_mixed_allocatablesEm"} -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
# |                                        ^
# | /home/gha/actions-runner/_work/llvm-project/llvm-project/flang/test/Lower/CUDA/cuda-gpu-managed.cuf:113:10: error: CHECK: expected string not found in input
# | ! CHECK: cuf.alloc {{.*}} {bindc_name = "arr", data_attr = #cuf.cuda<managed>, uniq_name = "_QFtest_multidimEarr"}
# |          ^
# | <stdin>:294:31: note: scanning from here
# |  func.func @_QPtest_multidim() {
# |                               ^
# | <stdin>:296:52: note: possible intended match here
# |  %1 = fir.alloca !fir.box<!fir.heap<!fir.array<?x?x?xf32>>> {bindc_name = "arr", uniq_name = "_QFtest_multidimEarr"}
# |                                                    ^
# | /home/gha/actions-runner/_work/llvm-project/llvm-project/flang/test/Lower/CUDA/cuda-gpu-managed.cuf:139:15: error: CHECK-SAME: expected string not found in input
# | ! CHECK-SAME: %{{.*}}: !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {cuf.data_attr = #cuf.cuda<managed>, fir.bindc_name = "arr"})
# |               ^
# | <stdin>:378:39: note: scanning from here
# |  func.func @_QPtest_dummy_allocatable(%arg0: !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {fir.bindc_name = "arr"}) {
# |                                       ^
# | /home/gha/actions-runner/_work/llvm-project/llvm-project/flang/test/Lower/CUDA/cuda-gpu-managed.cuf:165:10: error: CHECK: expected string not found in input
# | ! CHECK: cuf.allocate {{.*}} {data_attr = #cuf.cuda<managed>, hasDoubleDescriptor}
# |          ^
# | <stdin>:417:33: note: scanning from here
# |  func.func @_QPtest_module_var() {
# |                                 ^
# | <stdin>:439:56: note: possible intended match here
# |  %14 = cuf.allocate %4#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {data_attr = #cuf.cuda<device>, hasDoubleDescriptor} -> i32
# |                                                        ^
# | 
# | Input file: <stdin>
# | Check file: /home/gha/actions-runner/_work/llvm-project/llvm-project/flang/test/Lower/CUDA/cuda-gpu-managed.cuf
# | 
# | -dump-input=help explains the following input dump.
# | 
# | Input was:
# | <<<<<<
# |              1: module attributes {dlti.dl_spec = #dlti.dl_spec<!llvm.ptr<270> = dense<32> : vector<4xi64>, !llvm.ptr<271> = dense<32> : vector<4xi64>, !llvm.ptr<272> = dense<64> : vector<4xi64>, i64 = dense<64> : vector<2xi64>, i128 = dense<128> : vector<2xi64>, f80 = dense<128> : vector<2xi64>, !llvm.ptr = dense<64> : vector<4xi64>, i1 = dense<8> : vector<2xi64>, i8 = dense<8> : vector<2xi64>, i16 = dense<16> : vector<2xi64>, i32 = dense<32> : vector<2xi64>, f16 = dense<16> : vector<2xi64>, f64 = dense<64> : vector<2xi64>, f128 = dense<128> : vector<2xi64>, "dlti.endianness" = "little", "dlti.mangling_mode" = "e", "dlti.legal_int_widths" = array<i32: 8, 16, 32, 64>, "dlti.stack_alignment" = 128 : i64>, fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", llvm.data_layout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", llvm.ident = "flang version 23.0.0 (https://github.com/llvm/llvm-project 02437e6e959af5d31200e7df2c3e3da18416294d)", llvm.target_triple = "x86_64-unknown-linux-gnu"} { 
# |              2:  func.func @_QPtest_implicit_managed() { 
# | check:17'0                                            X~~ error: no match found
# |              3:  %0 = fir.dummy_scope : !fir.dscope 
# | check:17'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |              4:  %1 = fir.alloca !fir.box<!fir.heap<!fir.array<?xf32>>> {bindc_name = "a", uniq_name = "_QFtest_implicit_managedEa"} 
# | check:17'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# | check:17'1       ?                                                                                                                    possible intended match
# |              5:  %2 = fir.zero_bits !fir.heap<!fir.array<?xf32>> 
# | check:17'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |              6:  %c0 = arith.constant 0 : index 
# | check:17'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |              7:  %3 = fir.shape %c0 : (index) -> !fir.shape<1> 
# | check:17'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |              8:  %4 = fir.embox %2(%3) : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<?xf32>>> 
# | check:17'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |              9:  fir.store %4 to %1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> 
# | check:17'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |              .
# |              .
# |              .
# |            171:  %21 = fir.convert %5#0 : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) -> !fir.ref<!fir.box<none>> 
# |            172:  %22 = fir.convert %20 : (!fir.ref<!fir.char<1,100>>) -> !fir.ref<i8> 
# |            173:  %23 = fir.call @_FortranAPointerDeallocate(%21, %false_2, %19, %22, %c74_i32) fastmath<contract> : (!fir.ref<!fir.box<none>>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32 
# |            174:  return 
# |            175:  } 
# |            176:  func.func @_QPtest_mixed_allocatables() { 
# | check:97'0                                              X~~ error: no match found
# |            177:  %0 = fir.dummy_scope : !fir.dscope 
# | check:97'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            178:  %1 = fir.alloca !fir.box<!fir.heap<!fir.array<?xf32>>> {bindc_name = "a", uniq_name = "_QFtest_mixed_allocatablesEa"} 
# | check:97'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            179:  %2 = fir.zero_bits !fir.heap<!fir.array<?xf32>> 
# | check:97'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            180:  %c0 = arith.constant 0 : index 
# | check:97'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            181:  %3 = fir.shape %c0 : (index) -> !fir.shape<1> 
# | check:97'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |              .
# |              .
# |              .
# |            187:  %c0_0 = arith.constant 0 : index 
# | check:97'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            188:  %8 = fir.shape %c0_0 : (index) -> !fir.shape<1> 
# | check:97'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            189:  %9 = fir.embox %7(%8) {allocator_idx = 2 : i32} : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<?xf32>>> 
# | check:97'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            190:  fir.store %9 to %6 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> 
# | check:97'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            191:  %10:2 = hlfir.declare %6 {data_attr = #cuf.cuda<device>, fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest_mixed_allocatablesEd"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) 
# | check:97'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            192:  %11 = cuf.alloc !fir.box<!fir.heap<!fir.array<?xf32>>> {bindc_name = "m", data_attr = #cuf.cuda<managed>, uniq_name = "_QFtest_mixed_allocatablesEm"} -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> 
# | check:97'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# | check:97'1                                             ?                                                                                                                                                                    possible intended match
# |            193:  %12 = fir.zero_bits !fir.heap<!fir.array<?xf32>> 
# | check:97'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            194:  %c0_1 = arith.constant 0 : index 
# | check:97'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            195:  %13 = fir.shape %c0_1 : (index) -> !fir.shape<1> 
# | check:97'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            196:  %14 = fir.embox %12(%13) {allocator_idx = 3 : i32} : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<?xf32>>> 
# | check:97'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            197:  fir.store %14 to %11 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> 
# | check:97'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |              .
# |              .
# |              .
# |            289:  %67 = fir.embox %65(%66) : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<?xf32>>> 
# | check:97'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            290:  fir.store %67 to %5#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> 
# | check:97'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            291:  } 
# | check:97'0      ~~~
# |            292:  return 
# | check:97'0      ~~~~~~~~
# |            293:  } 
# | check:97'0      ~~~
# |            294:  func.func @_QPtest_multidim() { 
# | check:97'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# | check:113'0                                   X~~ error: no match found
# |            295:  %0 = fir.dummy_scope : !fir.dscope 
# | check:113'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            296:  %1 = fir.alloca !fir.box<!fir.heap<!fir.array<?x?x?xf32>>> {bindc_name = "arr", uniq_name = "_QFtest_multidimEarr"} 
# | check:113'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# | check:113'1                                                        ?                                                                  possible intended match
# |            297:  %2 = fir.zero_bits !fir.heap<!fir.array<?x?x?xf32>> 
# | check:113'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            298:  %c0 = arith.constant 0 : index 
# | check:113'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            299:  %3 = fir.shape %c0, %c0, %c0 : (index, index, index) -> !fir.shape<3> 
# | check:113'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            300:  %4 = fir.embox %2(%3) : (!fir.heap<!fir.array<?x?x?xf32>>, !fir.shape<3>) -> !fir.box<!fir.heap<!fir.array<?x?x?xf32>>> 
# | check:113'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            301:  fir.store %4 to %1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?xf32>>>> 
# | check:113'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |              .
# |              .
# |              .
# |            373:  %15 = cuf.deallocate %5#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {data_attr = #cuf.cuda<unified>} -> i32 
# |            374:  } 
# |            375:  cuf.free %5#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {data_attr = #cuf.cuda<unified>} 
# |            376:  return 
# |            377:  } 
# |            378:  func.func @_QPtest_dummy_allocatable(%arg0: !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {fir.bindc_name = "arr"}) { 
# | same:139                                              X~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: no match found
# |            379:  %0 = fir.dummy_scope : !fir.dscope 
# | same:139        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            380:  %1:2 = hlfir.declare %arg0 dummy_scope %0 arg 1 {fortran_attrs = #fir.var_attrs<allocatable, intent_inout>, uniq_name = "_QFtest_dummy_allocatableEarr"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) 
# | same:139        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            381:  %2 = fir.load %1#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> 
# | same:139        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            382:  %3 = fir.box_addr %2 : (!fir.box<!fir.heap<!fir.array<?xf32>>>) -> !fir.heap<!fir.array<?xf32>> 
# | same:139        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            383:  %4 = fir.convert %3 : (!fir.heap<!fir.array<?xf32>>) -> i64 
# | same:139        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |              .
# |              .
# |              .
# |            412:  %c0 = arith.constant 0 : index 
# | same:139        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            413:  %1 = fir.shape %c0 : (index) -> !fir.shape<1> 
# | same:139        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            414:  %2 = fir.embox %0(%1) {allocator_idx = 2 : i32} : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<?xf32>>> 
# | same:139        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            415:  fir.has_value %2 : !fir.box<!fir.heap<!fir.array<?xf32>>> 
# | same:139        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            416:  } 
# | same:139        ~~~
# |            417:  func.func @_QPtest_module_var() { 
# | same:139        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# | check:165'0                                     X~~ error: no match found
# |            418:  %0 = fir.dummy_scope : !fir.dscope 
# | check:165'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            419:  %1 = fir.address_of(@_QMmod_globalsEglobal_arr) : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> 
# | check:165'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            420:  %2:2 = hlfir.declare %1 {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMmod_globalsEglobal_arr"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) 
# | check:165'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            421:  %3 = fir.address_of(@_QMmod_globalsEglobal_device) : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> 
# | check:165'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            422:  %4:2 = hlfir.declare %3 {data_attr = #cuf.cuda<device>, fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMmod_globalsEglobal_device"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) 
# | check:165'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |              .
# |              .
# |              .
# |            434:  %c0_i32 = arith.constant 0 : i32 
# | check:165'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            435:  %11 = fir.convert %4#0 : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> !fir.ref<!fir.box<none>> 
# | check:165'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            436:  %12 = fir.convert %c1 : (index) -> i64 
# | check:165'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            437:  %13 = fir.convert %c50_i32_0 : (i32) -> i64 
# | check:165'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            438:  fir.call @_FortranAAllocatableSetBounds(%11, %c0_i32, %12, %13) fastmath<contract> : (!fir.ref<!fir.box<none>>, i32, i64, i64) -> () 
# | check:165'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            439:  %14 = cuf.allocate %4#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {data_attr = #cuf.cuda<device>, hasDoubleDescriptor} -> i32 
# | check:165'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# | check:165'1                                                            ?                                                                                 possible intended match
# |            440:  %15 = fir.load %2#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> 
# | check:165'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            441:  %16 = fir.box_addr %15 : (!fir.box<!fir.heap<!fir.array<?xf32>>>) -> !fir.heap<!fir.array<?xf32>> 
# | check:165'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            442:  fir.freemem %16 : !fir.heap<!fir.array<?xf32>> 
# | check:165'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            443:  %17 = fir.zero_bits !fir.heap<!fir.array<?xf32>> 
# | check:165'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            444:  %c0_1 = arith.constant 0 : index 
# | check:165'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |              .
# |              .
# |              .
# | >>>>>>
# `-----------------------------
# error: command failed with exit status: 1

--

Flang.Semantics/bug175207.f90
Exit Code: 1

Command Output (stdout):
--
# RUN: at line 1
"/usr/bin/python3" /home/gha/actions-runner/_work/llvm-project/llvm-project/flang/test/Semantics/test_errors.py /home/gha/actions-runner/_work/llvm-project/llvm-project/flang/test/Semantics/bug175207.f90 /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/flang -fc1
# executed command: /usr/bin/python3 /home/gha/actions-runner/_work/llvm-project/llvm-project/flang/test/Semantics/test_errors.py /home/gha/actions-runner/_work/llvm-project/llvm-project/flang/test/Semantics/bug175207.f90 /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/flang -fc1
# .---command stdout------------
# | --- 
# | +++ 
# | @@ -1,2 +1 @@
# | 
# | actual at 5: Internal: no symbol found for 'x'
# | actual at 7: Internal: no symbol found for 'sub'
# | expect at 7: 'sub' is not a variable
# | 
# | FAIL
# `-----------------------------
# error: command failed with exit status: 1

--

If these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the infrastructure label.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends OpenMP custom mapper support to target update directives' to() and from() clauses, implementing the OpenMP 5.2 specification. Previously, custom mappers were only available in map clauses.

Key Changes:

  • Added mapper resolution for to() and from() clauses in target update directives
  • Introduced semantic validation for undefined mappers and non-mapper symbols
  • Added comprehensive test coverage for both semantic analysis and MLIR lowering

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
flang/lib/Semantics/resolve-names.cpp Adds Pre(OmpClause::To) and Pre(OmpClause::From) handlers to resolve mapper names in target update clauses
flang/test/Semantics/OpenMP/target-update-mapper.f90 Semantic tests verifying custom/default mapper usage and error detection in target update constructs
flang/test/Lower/OpenMP/target-update-mapper.f90 Lowering tests verifying correct MLIR generation with mapper attributes for target update operations

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Member

@TIFitis TIFitis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR. I've added some review comments below...

@TIFitis TIFitis requested a review from kparzysz November 27, 2025 15:56
@github-actions
Copy link

github-actions bot commented Nov 27, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@KrxGu
Copy link
Contributor Author

KrxGu commented Nov 27, 2025

@TIFitis @kparzysz.
Thanks for the review! I've addressed all the feedback:

  1. Extracted ResolveMapperModifier helper to eliminate code duplication
  2. Simplified the semantics test
  3. Moved the lowering test to declare-mapper.f90

Also fixed the test expectations - they were using incorrect mangled names for program-scoped mappers.

CI all green, Good To Merge!!

@KrxGu KrxGu requested a review from TIFitis November 28, 2025 20:26
@KrxGu KrxGu force-pushed the fix-issue-168701-target-update-mapper branch from a770cf2 to c620237 Compare December 4, 2025 18:20
@KrxGu KrxGu requested a review from TIFitis December 4, 2025 19:05
@KrxGu
Copy link
Contributor Author

KrxGu commented Dec 9, 2025

@kparzysz , @TIFitis would love to get this merged!!

Copy link
Member

@skatrak skatrak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for this work. I have some minor comments, but I'll leave approval to @TIFitis and @kparzysz.

@KrxGu
Copy link
Contributor Author

KrxGu commented Jan 15, 2026

@kparzysz @skatrak i have addressed all the reviews and made the required changes.

CI is green, Good To Merge!!

@TIFitis
Copy link
Member

TIFitis commented Jan 15, 2026

What happened to the offloading test? Please resolve the merge conflict so I can test it.

Krish Gupta added 4 commits January 16, 2026 00:04
Krish Gupta and others added 4 commits January 16, 2026 00:05
- Use early return in getMapperIdentifier to reduce nesting
- Remove redundant if constexpr with identical branches
- Make ResolveMapperModifier parameter const
- Remove unnecessary const_cast at call sites
The symbol field is already marked mutable in the Name struct,
so it can be modified directly through a const reference.
@KrxGu KrxGu force-pushed the fix-issue-168701-target-update-mapper branch from e4af0a2 to e5a71f3 Compare January 15, 2026 18:36
KrxGu added 2 commits January 16, 2026 00:07
Use separate objects (obj1, obj2) for custom and default mapper
tests to avoid device memory mapping conflicts.
@github-actions
Copy link

github-actions bot commented Jan 15, 2026

🪟 Windows x64 Test Results

  • 3876 tests passed
  • 245 tests skipped
  • 2 tests failed

Failed Tests

(click on a test name to see its output)

Flang

Flang.Lower/CUDA/cuda-gpu-managed.cuf
Exit Code: 1

Command Output (stdout):
--
# RUN: at line 1
bbc -emit-hlfir -fcuda -gpu=managed C:\_work\llvm-project\llvm-project\flang\test\Lower\CUDA\cuda-gpu-managed.cuf -o - | c:\_work\llvm-project\llvm-project\build\bin\filecheck.exe C:\_work\llvm-project\llvm-project\flang\test\Lower\CUDA\cuda-gpu-managed.cuf
# executed command: bbc -emit-hlfir -fcuda -gpu=managed 'C:\_work\llvm-project\llvm-project\flang\test\Lower\CUDA\cuda-gpu-managed.cuf' -o -
# note: command had no output on stdout or stderr
# executed command: 'c:\_work\llvm-project\llvm-project\build\bin\filecheck.exe' 'C:\_work\llvm-project\llvm-project\flang\test\Lower\CUDA\cuda-gpu-managed.cuf'
# .---command stderr------------
# | C:\_work\llvm-project\llvm-project\flang\test\Lower\CUDA\cuda-gpu-managed.cuf:17:10: error: CHECK: expected string not found in input
# | ! CHECK: %[[BOX:.*]] = cuf.alloc !fir.box<!fir.heap<!fir.array<?xf32>>> {bindc_name = "a", data_attr = #cuf.cuda<managed>, uniq_name = "_QFtest_implicit_managedEa"}
# |          ^
# | <stdin>:2:39: note: scanning from here
# |  func.func @_QPtest_implicit_managed() {
# |                                       ^
# | <stdin>:4:2: note: possible intended match here
# |  %1 = fir.alloca !fir.box<!fir.heap<!fir.array<?xf32>>> {bindc_name = "a", uniq_name = "_QFtest_implicit_managedEa"}
# |  ^
# | C:\_work\llvm-project\llvm-project\flang\test\Lower\CUDA\cuda-gpu-managed.cuf:97:10: error: CHECK: expected string not found in input
# | ! CHECK: cuf.alloc {{.*}} {bindc_name = "a", data_attr = #cuf.cuda<managed>, uniq_name = "_QFtest_mixed_allocatablesEa"}
# |          ^
# | <stdin>:176:41: note: scanning from here
# |  func.func @_QPtest_mixed_allocatables() {
# |                                         ^
# | <stdin>:192:40: note: possible intended match here
# |  %11 = cuf.alloc !fir.box<!fir.heap<!fir.array<?xf32>>> {bindc_name = "m", data_attr = #cuf.cuda<managed>, uniq_name = "_QFtest_mixed_allocatablesEm"} -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
# |                                        ^
# | C:\_work\llvm-project\llvm-project\flang\test\Lower\CUDA\cuda-gpu-managed.cuf:113:10: error: CHECK: expected string not found in input
# | ! CHECK: cuf.alloc {{.*}} {bindc_name = "arr", data_attr = #cuf.cuda<managed>, uniq_name = "_QFtest_multidimEarr"}
# |          ^
# | <stdin>:294:31: note: scanning from here
# |  func.func @_QPtest_multidim() {
# |                               ^
# | <stdin>:296:52: note: possible intended match here
# |  %1 = fir.alloca !fir.box<!fir.heap<!fir.array<?x?x?xf32>>> {bindc_name = "arr", uniq_name = "_QFtest_multidimEarr"}
# |                                                    ^
# | C:\_work\llvm-project\llvm-project\flang\test\Lower\CUDA\cuda-gpu-managed.cuf:139:15: error: CHECK-SAME: expected string not found in input
# | ! CHECK-SAME: %{{.*}}: !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {cuf.data_attr = #cuf.cuda<managed>, fir.bindc_name = "arr"})
# |               ^
# | <stdin>:378:39: note: scanning from here
# |  func.func @_QPtest_dummy_allocatable(%arg0: !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {fir.bindc_name = "arr"}) {
# |                                       ^
# | C:\_work\llvm-project\llvm-project\flang\test\Lower\CUDA\cuda-gpu-managed.cuf:165:10: error: CHECK: expected string not found in input
# | ! CHECK: cuf.allocate {{.*}} {data_attr = #cuf.cuda<managed>, hasDoubleDescriptor}
# |          ^
# | <stdin>:417:33: note: scanning from here
# |  func.func @_QPtest_module_var() {
# |                                 ^
# | <stdin>:439:56: note: possible intended match here
# |  %14 = cuf.allocate %4#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {data_attr = #cuf.cuda<device>, hasDoubleDescriptor} -> i32
# |                                                        ^
# | 
# | Input file: <stdin>
# | Check file: C:\_work\llvm-project\llvm-project\flang\test\Lower\CUDA\cuda-gpu-managed.cuf
# | 
# | -dump-input=help explains the following input dump.
# | 
# | Input was:
# | <<<<<<
# |              1: module attributes {dlti.dl_spec = #dlti.dl_spec<!llvm.ptr<270> = dense<32> : vector<4xi64>, !llvm.ptr<271> = dense<32> : vector<4xi64>, !llvm.ptr<272> = dense<64> : vector<4xi64>, i64 = dense<64> : vector<2xi64>, i128 = dense<128> : vector<2xi64>, f80 = dense<128> : vector<2xi64>, !llvm.ptr = dense<64> : vector<4xi64>, i1 = dense<8> : vector<2xi64>, i8 = dense<8> : vector<2xi64>, i16 = dense<16> : vector<2xi64>, i32 = dense<32> : vector<2xi64>, f16 = dense<16> : vector<2xi64>, f64 = dense<64> : vector<2xi64>, f128 = dense<128> : vector<2xi64>, "dlti.endianness" = "little", "dlti.mangling_mode" = "w", "dlti.legal_int_widths" = array<i32: 8, 16, 32, 64>, "dlti.stack_alignment" = 128 : i64>, fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", llvm.data_layout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", llvm.ident = "flang version 23.0.0 (https://github.com/llvm/llvm-project 02437e6e959af5d31200e7df2c3e3da18416294d)", llvm.target_triple = "x86_64-pc-windows-msvc"} { 
# |              2:  func.func @_QPtest_implicit_managed() { 
# | check:17'0                                            X~~ error: no match found
# |              3:  %0 = fir.dummy_scope : !fir.dscope 
# | check:17'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |              4:  %1 = fir.alloca !fir.box<!fir.heap<!fir.array<?xf32>>> {bindc_name = "a", uniq_name = "_QFtest_implicit_managedEa"} 
# | check:17'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# | check:17'1       ?                                                                                                                    possible intended match
# |              5:  %2 = fir.zero_bits !fir.heap<!fir.array<?xf32>> 
# | check:17'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |              6:  %c0 = arith.constant 0 : index 
# | check:17'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |              7:  %3 = fir.shape %c0 : (index) -> !fir.shape<1> 
# | check:17'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |              8:  %4 = fir.embox %2(%3) : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<?xf32>>> 
# | check:17'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |              9:  fir.store %4 to %1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> 
# | check:17'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |              .
# |              .
# |              .
# |            171:  %21 = fir.convert %5#0 : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) -> !fir.ref<!fir.box<none>> 
# |            172:  %22 = fir.convert %20 : (!fir.ref<!fir.char<1,78>>) -> !fir.ref<i8> 
# |            173:  %23 = fir.call @_FortranAPointerDeallocate(%21, %false_2, %19, %22, %c74_i32) fastmath<contract> : (!fir.ref<!fir.box<none>>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32 
# |            174:  return 
# |            175:  } 
# |            176:  func.func @_QPtest_mixed_allocatables() { 
# | check:97'0                                              X~~ error: no match found
# |            177:  %0 = fir.dummy_scope : !fir.dscope 
# | check:97'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            178:  %1 = fir.alloca !fir.box<!fir.heap<!fir.array<?xf32>>> {bindc_name = "a", uniq_name = "_QFtest_mixed_allocatablesEa"} 
# | check:97'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            179:  %2 = fir.zero_bits !fir.heap<!fir.array<?xf32>> 
# | check:97'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            180:  %c0 = arith.constant 0 : index 
# | check:97'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            181:  %3 = fir.shape %c0 : (index) -> !fir.shape<1> 
# | check:97'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |              .
# |              .
# |              .
# |            187:  %c0_0 = arith.constant 0 : index 
# | check:97'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            188:  %8 = fir.shape %c0_0 : (index) -> !fir.shape<1> 
# | check:97'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            189:  %9 = fir.embox %7(%8) {allocator_idx = 2 : i32} : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<?xf32>>> 
# | check:97'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            190:  fir.store %9 to %6 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> 
# | check:97'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            191:  %10:2 = hlfir.declare %6 {data_attr = #cuf.cuda<device>, fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest_mixed_allocatablesEd"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) 
# | check:97'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            192:  %11 = cuf.alloc !fir.box<!fir.heap<!fir.array<?xf32>>> {bindc_name = "m", data_attr = #cuf.cuda<managed>, uniq_name = "_QFtest_mixed_allocatablesEm"} -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> 
# | check:97'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# | check:97'1                                             ?                                                                                                                                                                    possible intended match
# |            193:  %12 = fir.zero_bits !fir.heap<!fir.array<?xf32>> 
# | check:97'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            194:  %c0_1 = arith.constant 0 : index 
# | check:97'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            195:  %13 = fir.shape %c0_1 : (index) -> !fir.shape<1> 
# | check:97'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            196:  %14 = fir.embox %12(%13) {allocator_idx = 3 : i32} : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<?xf32>>> 
# | check:97'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            197:  fir.store %14 to %11 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> 
# | check:97'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |              .
# |              .
# |              .
# |            289:  %67 = fir.embox %65(%66) : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<?xf32>>> 
# | check:97'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            290:  fir.store %67 to %5#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> 
# | check:97'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            291:  } 
# | check:97'0      ~~~
# |            292:  return 
# | check:97'0      ~~~~~~~~
# |            293:  } 
# | check:97'0      ~~~
# |            294:  func.func @_QPtest_multidim() { 
# | check:97'0      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# | check:113'0                                   X~~ error: no match found
# |            295:  %0 = fir.dummy_scope : !fir.dscope 
# | check:113'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            296:  %1 = fir.alloca !fir.box<!fir.heap<!fir.array<?x?x?xf32>>> {bindc_name = "arr", uniq_name = "_QFtest_multidimEarr"} 
# | check:113'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# | check:113'1                                                        ?                                                                  possible intended match
# |            297:  %2 = fir.zero_bits !fir.heap<!fir.array<?x?x?xf32>> 
# | check:113'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            298:  %c0 = arith.constant 0 : index 
# | check:113'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            299:  %3 = fir.shape %c0, %c0, %c0 : (index, index, index) -> !fir.shape<3> 
# | check:113'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            300:  %4 = fir.embox %2(%3) : (!fir.heap<!fir.array<?x?x?xf32>>, !fir.shape<3>) -> !fir.box<!fir.heap<!fir.array<?x?x?xf32>>> 
# | check:113'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            301:  fir.store %4 to %1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?xf32>>>> 
# | check:113'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |              .
# |              .
# |              .
# |            373:  %15 = cuf.deallocate %5#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {data_attr = #cuf.cuda<unified>} -> i32 
# |            374:  } 
# |            375:  cuf.free %5#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {data_attr = #cuf.cuda<unified>} 
# |            376:  return 
# |            377:  } 
# |            378:  func.func @_QPtest_dummy_allocatable(%arg0: !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {fir.bindc_name = "arr"}) { 
# | same:139                                              X~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: no match found
# |            379:  %0 = fir.dummy_scope : !fir.dscope 
# | same:139        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            380:  %1:2 = hlfir.declare %arg0 dummy_scope %0 arg 1 {fortran_attrs = #fir.var_attrs<allocatable, intent_inout>, uniq_name = "_QFtest_dummy_allocatableEarr"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) 
# | same:139        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            381:  %2 = fir.load %1#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> 
# | same:139        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            382:  %3 = fir.box_addr %2 : (!fir.box<!fir.heap<!fir.array<?xf32>>>) -> !fir.heap<!fir.array<?xf32>> 
# | same:139        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            383:  %4 = fir.convert %3 : (!fir.heap<!fir.array<?xf32>>) -> i64 
# | same:139        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |              .
# |              .
# |              .
# |            412:  %c0 = arith.constant 0 : index 
# | same:139        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            413:  %1 = fir.shape %c0 : (index) -> !fir.shape<1> 
# | same:139        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            414:  %2 = fir.embox %0(%1) {allocator_idx = 2 : i32} : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<?xf32>>> 
# | same:139        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            415:  fir.has_value %2 : !fir.box<!fir.heap<!fir.array<?xf32>>> 
# | same:139        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            416:  } 
# | same:139        ~~~
# |            417:  func.func @_QPtest_module_var() { 
# | same:139        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# | check:165'0                                     X~~ error: no match found
# |            418:  %0 = fir.dummy_scope : !fir.dscope 
# | check:165'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            419:  %1 = fir.address_of(@_QMmod_globalsEglobal_arr) : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> 
# | check:165'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            420:  %2:2 = hlfir.declare %1 {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMmod_globalsEglobal_arr"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) 
# | check:165'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            421:  %3 = fir.address_of(@_QMmod_globalsEglobal_device) : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> 
# | check:165'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            422:  %4:2 = hlfir.declare %3 {data_attr = #cuf.cuda<device>, fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMmod_globalsEglobal_device"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) 
# | check:165'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |              .
# |              .
# |              .
# |            434:  %c0_i32 = arith.constant 0 : i32 
# | check:165'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            435:  %11 = fir.convert %4#0 : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> !fir.ref<!fir.box<none>> 
# | check:165'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            436:  %12 = fir.convert %c1 : (index) -> i64 
# | check:165'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            437:  %13 = fir.convert %c50_i32_0 : (i32) -> i64 
# | check:165'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            438:  fir.call @_FortranAAllocatableSetBounds(%11, %c0_i32, %12, %13) fastmath<contract> : (!fir.ref<!fir.box<none>>, i32, i64, i64) -> () 
# | check:165'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            439:  %14 = cuf.allocate %4#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {data_attr = #cuf.cuda<device>, hasDoubleDescriptor} -> i32 
# | check:165'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# | check:165'1                                                            ?                                                                                 possible intended match
# |            440:  %15 = fir.load %2#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> 
# | check:165'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            441:  %16 = fir.box_addr %15 : (!fir.box<!fir.heap<!fir.array<?xf32>>>) -> !fir.heap<!fir.array<?xf32>> 
# | check:165'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            442:  fir.freemem %16 : !fir.heap<!fir.array<?xf32>> 
# | check:165'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            443:  %17 = fir.zero_bits !fir.heap<!fir.array<?xf32>> 
# | check:165'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            444:  %c0_1 = arith.constant 0 : index 
# | check:165'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |              .
# |              .
# |              .
# | >>>>>>
# `-----------------------------
# error: command failed with exit status: 1

--

Flang.Semantics/bug175207.f90
Exit Code: 1

Command Output (stdout):
--
# RUN: at line 1
"C:\Python312\python.exe" C:\_work\llvm-project\llvm-project\flang\test\Semantics/test_errors.py C:\_work\llvm-project\llvm-project\flang\test\Semantics\bug175207.f90 c:\_work\llvm-project\llvm-project\build\bin\flang.exe -fc1
# executed command: 'C:\Python312\python.exe' 'C:\_work\llvm-project\llvm-project\flang\test\Semantics/test_errors.py' 'C:\_work\llvm-project\llvm-project\flang\test\Semantics\bug175207.f90' 'c:\_work\llvm-project\llvm-project\build\bin\flang.exe' -fc1
# .---command stdout------------
# | --- 
# | +++ 
# | @@ -1,2 +1 @@
# | 
# | actual at 5: Internal: no symbol found for 'x'
# | actual at 7: Internal: no symbol found for 'sub'
# | expect at 7: 'sub' is not a variable
# | 
# | FAIL
# `-----------------------------
# error: command failed with exit status: 1

--

If these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the infrastructure label.

DeclarationTypeSpec::Type is a WRAPPER_CLASS with member 'v',
not 'derived'. Corrects build failure on CI.
@KrxGu
Copy link
Contributor Author

KrxGu commented Jan 15, 2026

@TIFitis I have adressed all the reviews and have added the required test too(which you can test at your end and lemme know if something needs to be changed).

CI all green, Good To Merge!!

Copy link
Member

@TIFitis TIFitis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM overall minus the nit. Please allow another +1.

The offload test is passing on my end, thanks for the PR.

Per review feedback, removed all pointer-style and indentation
changes that were picked up during rebase. Kept only functional
changes for mapper support in target update.
@KrxGu
Copy link
Contributor Author

KrxGu commented Jan 16, 2026

The CI failures (CUDA managed memory and namelist tests) are unrelated to this PR's
changes. This PR only modifies OpenMP mapper support, not CUDA or namelist functionality.

The failures appear to be from commits that came in during rebase. Could you please
re-run the CI or confirm these are known issues on main? @kparzysz @TIFitis @skatrak

Files actually modified by this PR:

  • flang/lib/Lower/OpenMP/ClauseProcessor.cpp
  • flang/lib/Semantics/resolve-names.cpp
  • OpenMP test files
  • offload/test/offloading/fortran/target-update-custom-mapper.f90

@KrxGu
Copy link
Contributor Author

KrxGu commented Jan 21, 2026

CI Failures are Unrelated to This PR

The failing tests are in areas not touched by this PR:

Failing Tests:

  • Flang :: Lower/CUDA/cuda-gpu-managed.cuf - CUDA managed memory
  • Flang :: Semantics/bug175207.f90 - Namelist semantics

This PR's Scope:

  • OpenMP mapper support for target update constructs
  • Files modified:
    • flang/lib/Lower/OpenMP/ClauseProcessor.cpp
    • flang/lib/Semantics/resolve-names.cpp
    • OpenMP test files only

These failures appear to be from recent CUDA commits on main (e.g., #175243, #175225)
that were picked up during rebase. The failures are present on the base branch and
not introduced by this PR's changes.

Could you please either:

  1. Re-trigger CI after main is fixed
  2. Approve with a note that failures are known/unrelated

The OpenMP-specific changes in this PR are ready for review.
cc: @tblah @kparzysz @TIFitis @skatrak

@TIFitis
Copy link
Member

TIFitis commented Jan 21, 2026

I've already accepted the PR.

Parser/semantics isn't my area, so please feel to merge it once one other reviewer has accepted as well 👍🏽

@KrxGu KrxGu requested a review from skatrak January 23, 2026 18:16
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

flang:fir-hlfir flang:openmp flang:semantics flang Flang issues not falling into any other category

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[flang][OpenMP] Custom mappers not supported in target update construct

5 participants