[flang-commits] [flang] [llvm] [Flang] [OpenMP] Add semantic checks for detach clause in task (PR #119172)
Thirumalai Shaktivel via flang-commits
flang-commits at lists.llvm.org
Fri May 2 05:10:30 PDT 2025
https://github.com/Thirumalai-Shaktivel updated https://github.com/llvm/llvm-project/pull/119172
>From 6e491ccd80b902df6946713a372ec9667e0811c3 Mon Sep 17 00:00:00 2001
From: Thirumalai-Shaktivel <thirumalaishaktivel at gmail.com>
Date: Mon, 9 Dec 2024 07:37:01 +0000
Subject: [PATCH 01/15] [Flang] [OpenMP] Add semantic checks for detach clause
in Task
Fixes:
- Add semantic checks along with the tests
- Move the detach clause to allowedOnceClauses list in
Task construct
Restrictions:\
OpenMP 5.0: Task construct
- At most one detach clause can appear on the directive.
- If a detach clause appears on the directive, then a mergeable
clause cannot appear on the same directive.
OpenMP 5.2: Detach contruct
- If a detach clause appears on a directive, then the encountering
task must not be a final task.
- A variable that appears in a detach clause cannot appear as a
list item on a data-environment attribute clause on the same
construct.
- A variable that is part of another variable (as an array element or a
structure element) cannot appear in a detach clause.
- event-handle must not have the POINTER attribute.
---
flang/lib/Semantics/check-omp-structure.cpp | 141 +++++++++++++++-----
flang/lib/Semantics/check-omp-structure.h | 2 +
flang/test/Semantics/OpenMP/detach01.f90 | 65 +++++++++
llvm/include/llvm/Frontend/OpenMP/OMP.td | 2 +-
4 files changed, 179 insertions(+), 31 deletions(-)
create mode 100644 flang/test/Semantics/OpenMP/detach01.f90
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 95b962f5daf57..6641e39c6e358 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -2733,6 +2733,59 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &) {
llvm::omp::Clause::OMPC_copyprivate, {llvm::omp::Clause::OMPC_nowait});
}
+ if (GetContext().directive == llvm::omp::Directive::OMPD_task) {
+ if (auto *d_clause{FindClause(llvm::omp::Clause::OMPC_detach)}) {
+ // OpenMP 5.0: Task construct restrictions
+ CheckNotAllowedIfClause(
+ llvm::omp::Clause::OMPC_detach, {llvm::omp::Clause::OMPC_mergeable});
+
+ // OpenMP 5.2: Task construct restrictions
+ if (FindClause(llvm::omp::Clause::OMPC_final)) {
+ context_.Say(GetContext().clauseSource,
+ "If a DETACH clause appears on a directive, then the encountering task must not be a FINAL task"_err_en_US);
+ }
+
+ const auto &detachClause{
+ std::get<parser::OmpClause::Detach>(d_clause->u)};
+ if (const auto *name{parser::Unwrap<parser::Name>(detachClause.v.v)}) {
+ if (name->symbol) {
+ std::string eventHandleSymName{name->ToString()};
+ auto checkVarAppearsInDataEnvClause = [&](const parser::OmpObjectList
+ &objs,
+ std::string clause) {
+ for (const auto &obj : objs.v) {
+ if (const parser::Name *objName{
+ parser::Unwrap<parser::Name>(obj)}) {
+ if (objName->ToString() == eventHandleSymName) {
+ context_.Say(GetContext().clauseSource,
+ "A variable: `%s` that appears in a DETACH clause cannot appear on %s clause on the same construct"_err_en_US,
+ eventHandleSymName, clause);
+ }
+ }
+ }
+ };
+ if (auto *dataEnvClause{
+ FindClause(llvm::omp::Clause::OMPC_private)}) {
+ const auto &pClause{
+ std::get<parser::OmpClause::Private>(dataEnvClause->u)};
+ checkVarAppearsInDataEnvClause(pClause.v, "PRIVATE");
+ } else if (auto *dataEnvClause{
+ FindClause(llvm::omp::Clause::OMPC_firstprivate)}) {
+ const auto &fpClause{
+ std::get<parser::OmpClause::Firstprivate>(dataEnvClause->u)};
+ checkVarAppearsInDataEnvClause(fpClause.v, "FIRSTPRIVATE");
+ } else if (auto *dataEnvClause{
+ FindClause(llvm::omp::Clause::OMPC_in_reduction)}) {
+ const auto &irClause{
+ std::get<parser::OmpClause::InReduction>(dataEnvClause->u)};
+ checkVarAppearsInDataEnvClause(
+ std::get<parser::OmpObjectList>(irClause.v.t), "IN_REDUCTION");
+ }
+ }
+ }
+ }
+ }
+
auto testThreadprivateVarErr = [&](Symbol sym, parser::Name name,
llvmOmpClause clauseTy) {
if (sym.test(Symbol::Flag::OmpThreadprivate))
@@ -2815,7 +2868,6 @@ CHECK_SIMPLE_CLAUSE(Capture, OMPC_capture)
CHECK_SIMPLE_CLAUSE(Contains, OMPC_contains)
CHECK_SIMPLE_CLAUSE(Default, OMPC_default)
CHECK_SIMPLE_CLAUSE(Depobj, OMPC_depobj)
-CHECK_SIMPLE_CLAUSE(Detach, OMPC_detach)
CHECK_SIMPLE_CLAUSE(DeviceType, OMPC_device_type)
CHECK_SIMPLE_CLAUSE(DistSchedule, OMPC_dist_schedule)
CHECK_SIMPLE_CLAUSE(Exclusive, OMPC_exclusive)
@@ -3386,40 +3438,45 @@ void OmpStructureChecker::CheckIsVarPartOfAnotherVar(
const parser::CharBlock &source, const parser::OmpObjectList &objList,
llvm::StringRef clause) {
for (const auto &ompObject : objList.v) {
- common::visit(
- common::visitors{
- [&](const parser::Designator &designator) {
- if (const auto *dataRef{
- std::get_if<parser::DataRef>(&designator.u)}) {
- if (IsDataRefTypeParamInquiry(dataRef)) {
+ CheckIsVarPartOfAnotherVar(source, ompObject, clause);
+ }
+}
+
+void OmpStructureChecker::CheckIsVarPartOfAnotherVar(
+ const parser::CharBlock &source, const parser::OmpObject &ompObject,
+ llvm::StringRef clause) {
+ common::visit(
+ common::visitors{
+ [&](const parser::Designator &designator) {
+ if (const auto *dataRef{
+ std::get_if<parser::DataRef>(&designator.u)}) {
+ if (IsDataRefTypeParamInquiry(dataRef)) {
+ context_.Say(source,
+ "A type parameter inquiry cannot appear on the %s "
+ "directive"_err_en_US,
+ ContextDirectiveAsFortran());
+ } else if (parser::Unwrap<parser::StructureComponent>(
+ ompObject) ||
+ parser::Unwrap<parser::ArrayElement>(ompObject)) {
+ if (llvm::omp::nonPartialVarSet.test(GetContext().directive)) {
context_.Say(source,
- "A type parameter inquiry cannot appear on the %s "
+ "A variable that is part of another variable (as an "
+ "array or structure element) cannot appear on the %s "
"directive"_err_en_US,
ContextDirectiveAsFortran());
- } else if (parser::Unwrap<parser::StructureComponent>(
- ompObject) ||
- parser::Unwrap<parser::ArrayElement>(ompObject)) {
- if (llvm::omp::nonPartialVarSet.test(
- GetContext().directive)) {
- context_.Say(source,
- "A variable that is part of another variable (as an "
- "array or structure element) cannot appear on the %s "
- "directive"_err_en_US,
- ContextDirectiveAsFortran());
- } else {
- context_.Say(source,
- "A variable that is part of another variable (as an "
- "array or structure element) cannot appear in a "
- "%s clause"_err_en_US,
- clause.data());
- }
+ } else {
+ context_.Say(source,
+ "A variable that is part of another variable (as an "
+ "array or structure element) cannot appear in a "
+ "%s clause"_err_en_US,
+ clause.data());
}
}
- },
- [&](const parser::Name &name) {},
- },
- ompObject.u);
- }
+ }
+ },
+ [&](const parser::Name &name) {},
+ },
+ ompObject.u);
}
void OmpStructureChecker::Enter(const parser::OmpClause::Firstprivate &x) {
@@ -3746,6 +3803,30 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Linear &x) {
}
}
+void OmpStructureChecker::Enter(const parser::OmpClause::Detach &x) {
+ // OpenMP 5.0: Task construct restrictions
+ CheckAllowedClause(llvm::omp::Clause::OMPC_detach);
+
+ // OpenMP 5.2: Detach clause restrictions
+ CheckIsVarPartOfAnotherVar(GetContext().clauseSource, x.v.v, "DETACH");
+ if (const auto *name{parser::Unwrap<parser::Name>(x.v.v)}) {
+ if (name->symbol) {
+ if (IsPointer(*name->symbol)) {
+ context_.Say(GetContext().clauseSource,
+ "The event-handle: `%s` must not have the POINTER attribute"_err_en_US,
+ name->ToString());
+ }
+ }
+ auto type{name->symbol->GetType()};
+ if (!name->symbol->GetType()->IsNumeric(TypeCategory::Integer) ||
+ evaluate::ToInt64(type->numericTypeSpec().kind()) != 8) {
+ context_.Say(GetContext().clauseSource,
+ "The event-handle: `%s` must be of type integer(kind=omp_event_handle_kind)"_err_en_US,
+ name->ToString());
+ }
+ }
+}
+
void OmpStructureChecker::CheckAllowedMapTypes(
const parser::OmpMapType::Value &type,
const std::list<parser::OmpMapType::Value> &allowedMapTypeList) {
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 346a7bed9138f..a8f94992ff091 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -186,6 +186,8 @@ class OmpStructureChecker
const common::Indirection<parser::ArrayElement> &, const parser::Name &);
void CheckDoacross(const parser::OmpDoacross &doa);
bool IsDataRefTypeParamInquiry(const parser::DataRef *dataRef);
+ void CheckIsVarPartOfAnotherVar(const parser::CharBlock &source,
+ const parser::OmpObject &obj, llvm::StringRef clause = "");
void CheckIsVarPartOfAnotherVar(const parser::CharBlock &source,
const parser::OmpObjectList &objList, llvm::StringRef clause = "");
void CheckThreadprivateOrDeclareTargetVar(
diff --git a/flang/test/Semantics/OpenMP/detach01.f90 b/flang/test/Semantics/OpenMP/detach01.f90
new file mode 100644
index 0000000000000..e342fcd1b19b4
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/detach01.f90
@@ -0,0 +1,65 @@
+! REQUIRES: openmp_runtime
+! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags -fopenmp-version=50
+
+! OpenMP Version 5.2
+! Various checks for DETACH Clause (12.5.2)
+
+program test_detach
+ use omp_lib
+ implicit none
+ integer :: e, x
+ integer(omp_event_handle_kind) :: event_01, event_02(2)
+ integer(omp_event_handle_kind), pointer :: event_03
+
+
+ type :: t
+ integer(omp_event_handle_kind) :: event
+ end type
+
+ type(t) :: t_01
+
+ !ERROR: The event-handle: `e` must be of type integer(kind=omp_event_handle_kind)
+ !$omp task detach(e)
+ x = x + 1
+ !$omp end task
+
+ !ERROR: At most one DETACH clause can appear on the TASK directive
+ !$omp task detach(event_01) detach(event_01)
+ x = x + 1
+ !$omp end task
+
+ !ERROR: Clause MERGEABLE is not allowed if clause DETACH appears on the TASK directive
+ !$omp task detach(event_01) mergeable
+ x = x + 1
+ !$omp end task
+
+ !ERROR: If a DETACH clause appears on a directive, then the encountering task must not be a FINAL task
+ !$omp task detach(event_01) final(.false.)
+ x = x + 1
+ !$omp end task
+
+ !ERROR: A variable: `event_01` that appears in a DETACH clause cannot appear on PRIVATE clause on the same construct
+ !$omp task detach(event_01) private(event_01)
+ x = x + 1
+ !$omp end task
+
+ !ERROR: A variable: `event_01` that appears in a DETACH clause cannot appear on IN_REDUCTION clause on the same construct
+ !$omp task detach(event_01) in_reduction(+:event_01)
+ x = x + 1
+ !$omp end task
+
+ !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a DETACH clause
+ !$omp task detach(event_02(1))
+ x = x + 1
+ !$omp end task
+
+ !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a DETACH clause
+ !$omp task detach(t_01%event)
+ x = x + 1
+ !$omp end task
+
+ !ERROR: The event-handle: `event_03` must not have the POINTER attribute
+ !$omp task detach(event_03)
+ x = x + 1
+ !$omp end task
+end program
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td
index e36eb77cefe7e..aec80decf6039 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.td
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td
@@ -1090,7 +1090,6 @@ def OMP_Task : Directive<"task"> {
VersionedClause<OMPC_Affinity, 50>,
VersionedClause<OMPC_Allocate>,
VersionedClause<OMPC_Depend>,
- VersionedClause<OMPC_Detach, 50>,
VersionedClause<OMPC_FirstPrivate>,
VersionedClause<OMPC_InReduction>,
VersionedClause<OMPC_Mergeable>,
@@ -1100,6 +1099,7 @@ def OMP_Task : Directive<"task"> {
];
let allowedOnceClauses = [
VersionedClause<OMPC_Default>,
+ VersionedClause<OMPC_Detach, 50>,
VersionedClause<OMPC_Final>,
VersionedClause<OMPC_If>,
VersionedClause<OMPC_Priority>,
>From fa2b051e724898f3be9b2d74d218816088b3975f Mon Sep 17 00:00:00 2001
From: Thirumalai-Shaktivel <thirumalaishaktivel at gmail.com>
Date: Thu, 26 Dec 2024 05:51:11 +0000
Subject: [PATCH 02/15] Do not check for interger kind
---
flang/lib/Semantics/check-omp-structure.cpp | 4 +---
flang/test/Semantics/OpenMP/detach01.f90 | 4 ++--
2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 6641e39c6e358..e2f897f5c9246 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -3817,9 +3817,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Detach &x) {
name->ToString());
}
}
- auto type{name->symbol->GetType()};
- if (!name->symbol->GetType()->IsNumeric(TypeCategory::Integer) ||
- evaluate::ToInt64(type->numericTypeSpec().kind()) != 8) {
+ if (!name->symbol->GetType()->IsNumeric(TypeCategory::Integer)) {
context_.Say(GetContext().clauseSource,
"The event-handle: `%s` must be of type integer(kind=omp_event_handle_kind)"_err_en_US,
name->ToString());
diff --git a/flang/test/Semantics/OpenMP/detach01.f90 b/flang/test/Semantics/OpenMP/detach01.f90
index e342fcd1b19b4..7ba2888be9237 100644
--- a/flang/test/Semantics/OpenMP/detach01.f90
+++ b/flang/test/Semantics/OpenMP/detach01.f90
@@ -7,8 +7,8 @@
program test_detach
use omp_lib
implicit none
- integer :: e, x
- integer(omp_event_handle_kind) :: event_01, event_02(2)
+ real :: e, x
+ integer(omp_event_handle_kind) :: event_01, event_02(2)
integer(omp_event_handle_kind), pointer :: event_03
>From 569712fc9b14f3a1f4b3a7d2c55febfe216f5e7f Mon Sep 17 00:00:00 2001
From: Thirumalai-Shaktivel <thirumalaishaktivel at gmail.com>
Date: Thu, 26 Dec 2024 06:14:26 +0000
Subject: [PATCH 03/15] Fix snake_case
---
flang/lib/Semantics/check-omp-structure.cpp | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index e2f897f5c9246..aa19b71e69c62 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -2734,7 +2734,7 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &) {
}
if (GetContext().directive == llvm::omp::Directive::OMPD_task) {
- if (auto *d_clause{FindClause(llvm::omp::Clause::OMPC_detach)}) {
+ if (auto *detachClause{FindClause(llvm::omp::Clause::OMPC_detach)}) {
// OpenMP 5.0: Task construct restrictions
CheckNotAllowedIfClause(
llvm::omp::Clause::OMPC_detach, {llvm::omp::Clause::OMPC_mergeable});
@@ -2745,9 +2745,9 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &) {
"If a DETACH clause appears on a directive, then the encountering task must not be a FINAL task"_err_en_US);
}
- const auto &detachClause{
- std::get<parser::OmpClause::Detach>(d_clause->u)};
- if (const auto *name{parser::Unwrap<parser::Name>(detachClause.v.v)}) {
+ const auto &detach{
+ std::get<parser::OmpClause::Detach>(detachClause->u)};
+ if (const auto *name{parser::Unwrap<parser::Name>(detach.v.v)}) {
if (name->symbol) {
std::string eventHandleSymName{name->ToString()};
auto checkVarAppearsInDataEnvClause = [&](const parser::OmpObjectList
>From 42cc3e75d041b9935b38e19cb70d7b3273f4087f Mon Sep 17 00:00:00 2001
From: Thirumalai-Shaktivel <thirumalaishaktivel at gmail.com>
Date: Thu, 26 Dec 2024 06:36:11 +0000
Subject: [PATCH 04/15] Compare symbols instead of name
---
flang/lib/Semantics/check-omp-structure.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index aa19b71e69c62..084dbf48c5c50 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -2749,17 +2749,17 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &) {
std::get<parser::OmpClause::Detach>(detachClause->u)};
if (const auto *name{parser::Unwrap<parser::Name>(detach.v.v)}) {
if (name->symbol) {
- std::string eventHandleSymName{name->ToString()};
+ Symbol *eventHandleSym{name->symbol->GetUltimate()};
auto checkVarAppearsInDataEnvClause = [&](const parser::OmpObjectList
&objs,
std::string clause) {
for (const auto &obj : objs.v) {
if (const parser::Name *objName{
parser::Unwrap<parser::Name>(obj)}) {
- if (objName->ToString() == eventHandleSymName) {
+ if (objName->symbol->GetUltimate() == eventHandleSym) {
context_.Say(GetContext().clauseSource,
"A variable: `%s` that appears in a DETACH clause cannot appear on %s clause on the same construct"_err_en_US,
- eventHandleSymName, clause);
+ objName->source, clause);
}
}
}
>From a3c6a4517354991dc5f166d57d14012571b3f553 Mon Sep 17 00:00:00 2001
From: Thirumalai-Shaktivel <thirumalaishaktivel at gmail.com>
Date: Thu, 26 Dec 2024 09:09:15 +0000
Subject: [PATCH 05/15] Add OpenMP version based checks
---
flang/lib/Semantics/check-omp-structure.cpp | 105 ++++++++++----------
flang/test/Semantics/OpenMP/detach01.f90 | 22 +---
flang/test/Semantics/OpenMP/detach02.f90 | 22 ++++
llvm/include/llvm/Frontend/OpenMP/OMP.td | 2 +-
4 files changed, 83 insertions(+), 68 deletions(-)
create mode 100644 flang/test/Semantics/OpenMP/detach02.f90
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 084dbf48c5c50..41ed858ed650f 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -2735,51 +2735,54 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &) {
if (GetContext().directive == llvm::omp::Directive::OMPD_task) {
if (auto *detachClause{FindClause(llvm::omp::Clause::OMPC_detach)}) {
- // OpenMP 5.0: Task construct restrictions
- CheckNotAllowedIfClause(
- llvm::omp::Clause::OMPC_detach, {llvm::omp::Clause::OMPC_mergeable});
-
- // OpenMP 5.2: Task construct restrictions
- if (FindClause(llvm::omp::Clause::OMPC_final)) {
- context_.Say(GetContext().clauseSource,
- "If a DETACH clause appears on a directive, then the encountering task must not be a FINAL task"_err_en_US);
- }
+ unsigned version{context_.langOptions().OpenMPVersion};
+ if (version == 50 || version == 51) {
+ // OpenMP 5.0: 2.10.1 Task construct restrictions
+ CheckNotAllowedIfClause(
+ llvm::omp::Clause::OMPC_detach, {llvm::omp::Clause::OMPC_mergeable});
+ } else if (version >= 52) {
+ // OpenMP 5.2: 12.5.2 Detach construct restrictions
+ if (FindClause(llvm::omp::Clause::OMPC_final)) {
+ context_.Say(GetContext().clauseSource,
+ "If a DETACH clause appears on a directive, then the encountering task must not be a FINAL task"_err_en_US);
+ }
- const auto &detach{
- std::get<parser::OmpClause::Detach>(detachClause->u)};
- if (const auto *name{parser::Unwrap<parser::Name>(detach.v.v)}) {
- if (name->symbol) {
- Symbol *eventHandleSym{name->symbol->GetUltimate()};
- auto checkVarAppearsInDataEnvClause = [&](const parser::OmpObjectList
- &objs,
- std::string clause) {
- for (const auto &obj : objs.v) {
- if (const parser::Name *objName{
- parser::Unwrap<parser::Name>(obj)}) {
- if (objName->symbol->GetUltimate() == eventHandleSym) {
- context_.Say(GetContext().clauseSource,
- "A variable: `%s` that appears in a DETACH clause cannot appear on %s clause on the same construct"_err_en_US,
- objName->source, clause);
+ const auto &detach{
+ std::get<parser::OmpClause::Detach>(detachClause->u)};
+ if (const auto *name{parser::Unwrap<parser::Name>(detach.v.v)}) {
+ if (name->symbol) {
+ Symbol *eventHandleSym{name->symbol};
+ auto checkVarAppearsInDataEnvClause = [&](const parser::OmpObjectList
+ &objs,
+ std::string clause) {
+ for (const auto &obj : objs.v) {
+ if (const parser::Name *objName{
+ parser::Unwrap<parser::Name>(obj)}) {
+ if (&objName->symbol->GetUltimate() == eventHandleSym) {
+ context_.Say(GetContext().clauseSource,
+ "A variable: `%s` that appears in a DETACH clause cannot appear on %s clause on the same construct"_err_en_US,
+ objName->source, clause);
+ }
}
}
+ };
+ if (auto *dataEnvClause{
+ FindClause(llvm::omp::Clause::OMPC_private)}) {
+ const auto &pClause{
+ std::get<parser::OmpClause::Private>(dataEnvClause->u)};
+ checkVarAppearsInDataEnvClause(pClause.v, "PRIVATE");
+ } else if (auto *dataEnvClause{
+ FindClause(llvm::omp::Clause::OMPC_firstprivate)}) {
+ const auto &fpClause{
+ std::get<parser::OmpClause::Firstprivate>(dataEnvClause->u)};
+ checkVarAppearsInDataEnvClause(fpClause.v, "FIRSTPRIVATE");
+ } else if (auto *dataEnvClause{
+ FindClause(llvm::omp::Clause::OMPC_in_reduction)}) {
+ const auto &irClause{
+ std::get<parser::OmpClause::InReduction>(dataEnvClause->u)};
+ checkVarAppearsInDataEnvClause(
+ std::get<parser::OmpObjectList>(irClause.v.t), "IN_REDUCTION");
}
- };
- if (auto *dataEnvClause{
- FindClause(llvm::omp::Clause::OMPC_private)}) {
- const auto &pClause{
- std::get<parser::OmpClause::Private>(dataEnvClause->u)};
- checkVarAppearsInDataEnvClause(pClause.v, "PRIVATE");
- } else if (auto *dataEnvClause{
- FindClause(llvm::omp::Clause::OMPC_firstprivate)}) {
- const auto &fpClause{
- std::get<parser::OmpClause::Firstprivate>(dataEnvClause->u)};
- checkVarAppearsInDataEnvClause(fpClause.v, "FIRSTPRIVATE");
- } else if (auto *dataEnvClause{
- FindClause(llvm::omp::Clause::OMPC_in_reduction)}) {
- const auto &irClause{
- std::get<parser::OmpClause::InReduction>(dataEnvClause->u)};
- checkVarAppearsInDataEnvClause(
- std::get<parser::OmpObjectList>(irClause.v.t), "IN_REDUCTION");
}
}
}
@@ -3804,23 +3807,25 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Linear &x) {
}
void OmpStructureChecker::Enter(const parser::OmpClause::Detach &x) {
- // OpenMP 5.0: Task construct restrictions
CheckAllowedClause(llvm::omp::Clause::OMPC_detach);
+ unsigned version{context_.langOptions().OpenMPVersion};
+ // OpenMP 5.2: 12.5.2 Detach clause restrictions
+ if (version >= 52) {
+ CheckIsVarPartOfAnotherVar(GetContext().clauseSource, x.v.v, "DETACH");
+ }
- // OpenMP 5.2: Detach clause restrictions
- CheckIsVarPartOfAnotherVar(GetContext().clauseSource, x.v.v, "DETACH");
if (const auto *name{parser::Unwrap<parser::Name>(x.v.v)}) {
if (name->symbol) {
- if (IsPointer(*name->symbol)) {
+ if (version >= 52 && IsPointer(*name->symbol)) {
context_.Say(GetContext().clauseSource,
"The event-handle: `%s` must not have the POINTER attribute"_err_en_US,
name->ToString());
}
- }
- if (!name->symbol->GetType()->IsNumeric(TypeCategory::Integer)) {
- context_.Say(GetContext().clauseSource,
- "The event-handle: `%s` must be of type integer(kind=omp_event_handle_kind)"_err_en_US,
- name->ToString());
+ if (!name->symbol->GetType()->IsNumeric(TypeCategory::Integer)) {
+ context_.Say(GetContext().clauseSource,
+ "The event-handle: `%s` must be of type integer(kind=omp_event_handle_kind)"_err_en_US,
+ name->ToString());
+ }
}
}
}
diff --git a/flang/test/Semantics/OpenMP/detach01.f90 b/flang/test/Semantics/OpenMP/detach01.f90
index 7ba2888be9237..ea8208c022ef1 100644
--- a/flang/test/Semantics/OpenMP/detach01.f90
+++ b/flang/test/Semantics/OpenMP/detach01.f90
@@ -1,21 +1,19 @@
! REQUIRES: openmp_runtime
-! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags -fopenmp-version=50
+! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags -fopenmp-version=52
-! OpenMP Version 5.2
-! Various checks for DETACH Clause (12.5.2)
+! OpenMP Version 5.2: 12.5.2
+! Various checks for DETACH Clause
-program test_detach
- use omp_lib
+program detach01
+ use omp_lib, only: omp_event_handle_kind
implicit none
real :: e, x
integer(omp_event_handle_kind) :: event_01, event_02(2)
integer(omp_event_handle_kind), pointer :: event_03
-
type :: t
integer(omp_event_handle_kind) :: event
end type
-
type(t) :: t_01
!ERROR: The event-handle: `e` must be of type integer(kind=omp_event_handle_kind)
@@ -23,16 +21,6 @@ program test_detach
x = x + 1
!$omp end task
- !ERROR: At most one DETACH clause can appear on the TASK directive
- !$omp task detach(event_01) detach(event_01)
- x = x + 1
- !$omp end task
-
- !ERROR: Clause MERGEABLE is not allowed if clause DETACH appears on the TASK directive
- !$omp task detach(event_01) mergeable
- x = x + 1
- !$omp end task
-
!ERROR: If a DETACH clause appears on a directive, then the encountering task must not be a FINAL task
!$omp task detach(event_01) final(.false.)
x = x + 1
diff --git a/flang/test/Semantics/OpenMP/detach02.f90 b/flang/test/Semantics/OpenMP/detach02.f90
new file mode 100644
index 0000000000000..1304233976351
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/detach02.f90
@@ -0,0 +1,22 @@
+! REQUIRES: openmp_runtime
+! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags -fopenmp-version=50
+! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags -fopenmp-version=51
+
+! OpenMP Version 5.0: 2.10.1
+! Various checks for DETACH Clause
+
+program detach02
+ use omp_lib, only: omp_event_handle_kind
+ integer(omp_event_handle_kind) :: event_01, event_02
+
+ !TODO: Throw following error for the versions 5.0 and 5.1
+ !ERR: At most one DETACH clause can appear on the TASK directive
+ !!$omp task detach(event_01) detach(event_02)
+ ! x = x + 1
+ !!$omp end task
+
+ !ERROR: Clause MERGEABLE is not allowed if clause DETACH appears on the TASK directive
+ !$omp task detach(event_01) mergeable
+ x = x + 1
+ !$omp end task
+end program
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td
index aec80decf6039..e36eb77cefe7e 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.td
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td
@@ -1090,6 +1090,7 @@ def OMP_Task : Directive<"task"> {
VersionedClause<OMPC_Affinity, 50>,
VersionedClause<OMPC_Allocate>,
VersionedClause<OMPC_Depend>,
+ VersionedClause<OMPC_Detach, 50>,
VersionedClause<OMPC_FirstPrivate>,
VersionedClause<OMPC_InReduction>,
VersionedClause<OMPC_Mergeable>,
@@ -1099,7 +1100,6 @@ def OMP_Task : Directive<"task"> {
];
let allowedOnceClauses = [
VersionedClause<OMPC_Default>,
- VersionedClause<OMPC_Detach, 50>,
VersionedClause<OMPC_Final>,
VersionedClause<OMPC_If>,
VersionedClause<OMPC_Priority>,
>From 019a24c814b226352a13c18b840cc22a9b28ec7e Mon Sep 17 00:00:00 2001
From: Thirumalai-Shaktivel <thirumalaishaktivel at gmail.com>
Date: Thu, 26 Dec 2024 09:26:33 +0000
Subject: [PATCH 06/15] Fix formatting
---
flang/lib/Semantics/check-omp-structure.cpp | 19 ++++++++++---------
1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 41ed858ed650f..7ca695acc74b3 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -2738,8 +2738,8 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &) {
unsigned version{context_.langOptions().OpenMPVersion};
if (version == 50 || version == 51) {
// OpenMP 5.0: 2.10.1 Task construct restrictions
- CheckNotAllowedIfClause(
- llvm::omp::Clause::OMPC_detach, {llvm::omp::Clause::OMPC_mergeable});
+ CheckNotAllowedIfClause(llvm::omp::Clause::OMPC_detach,
+ {llvm::omp::Clause::OMPC_mergeable});
} else if (version >= 52) {
// OpenMP 5.2: 12.5.2 Detach construct restrictions
if (FindClause(llvm::omp::Clause::OMPC_final)) {
@@ -2752,12 +2752,12 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &) {
if (const auto *name{parser::Unwrap<parser::Name>(detach.v.v)}) {
if (name->symbol) {
Symbol *eventHandleSym{name->symbol};
- auto checkVarAppearsInDataEnvClause = [&](const parser::OmpObjectList
- &objs,
+ auto checkVarAppearsInDataEnvClause = [&](const parser::
+ OmpObjectList &objs,
std::string clause) {
for (const auto &obj : objs.v) {
- if (const parser::Name *objName{
- parser::Unwrap<parser::Name>(obj)}) {
+ if (const parser::Name *
+ objName{parser::Unwrap<parser::Name>(obj)}) {
if (&objName->symbol->GetUltimate() == eventHandleSym) {
context_.Say(GetContext().clauseSource,
"A variable: `%s` that appears in a DETACH clause cannot appear on %s clause on the same construct"_err_en_US,
@@ -2772,16 +2772,17 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &) {
std::get<parser::OmpClause::Private>(dataEnvClause->u)};
checkVarAppearsInDataEnvClause(pClause.v, "PRIVATE");
} else if (auto *dataEnvClause{
- FindClause(llvm::omp::Clause::OMPC_firstprivate)}) {
+ FindClause(llvm::omp::Clause::OMPC_firstprivate)}) {
const auto &fpClause{
std::get<parser::OmpClause::Firstprivate>(dataEnvClause->u)};
checkVarAppearsInDataEnvClause(fpClause.v, "FIRSTPRIVATE");
} else if (auto *dataEnvClause{
- FindClause(llvm::omp::Clause::OMPC_in_reduction)}) {
+ FindClause(llvm::omp::Clause::OMPC_in_reduction)}) {
const auto &irClause{
std::get<parser::OmpClause::InReduction>(dataEnvClause->u)};
checkVarAppearsInDataEnvClause(
- std::get<parser::OmpObjectList>(irClause.v.t), "IN_REDUCTION");
+ std::get<parser::OmpObjectList>(irClause.v.t),
+ "IN_REDUCTION");
}
}
}
>From 0348571f198063b2358d52435cd0c62c14b89ef9 Mon Sep 17 00:00:00 2001
From: Thirumalai-Shaktivel <thirumalaishaktivel at gmail.com>
Date: Fri, 7 Mar 2025 05:03:09 +0000
Subject: [PATCH 07/15] Allow detach clause only once
---
flang/lib/Semantics/check-omp-structure.cpp | 3 ++-
flang/test/Semantics/OpenMP/detach02.f90 | 9 ++++-----
llvm/include/llvm/Frontend/OpenMP/OMP.td | 2 +-
3 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 7ca695acc74b3..c6a4c2472c4af 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -3808,9 +3808,10 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Linear &x) {
}
void OmpStructureChecker::Enter(const parser::OmpClause::Detach &x) {
+ // OpenMP 5.0: 2.10.1 Task construct restrictions
CheckAllowedClause(llvm::omp::Clause::OMPC_detach);
- unsigned version{context_.langOptions().OpenMPVersion};
// OpenMP 5.2: 12.5.2 Detach clause restrictions
+ unsigned version{context_.langOptions().OpenMPVersion};
if (version >= 52) {
CheckIsVarPartOfAnotherVar(GetContext().clauseSource, x.v.v, "DETACH");
}
diff --git a/flang/test/Semantics/OpenMP/detach02.f90 b/flang/test/Semantics/OpenMP/detach02.f90
index 1304233976351..49d80358fcdb6 100644
--- a/flang/test/Semantics/OpenMP/detach02.f90
+++ b/flang/test/Semantics/OpenMP/detach02.f90
@@ -9,11 +9,10 @@ program detach02
use omp_lib, only: omp_event_handle_kind
integer(omp_event_handle_kind) :: event_01, event_02
- !TODO: Throw following error for the versions 5.0 and 5.1
- !ERR: At most one DETACH clause can appear on the TASK directive
- !!$omp task detach(event_01) detach(event_02)
- ! x = x + 1
- !!$omp end task
+ !ERROR: At most one DETACH clause can appear on the TASK directive
+ !$omp task detach(event_01) detach(event_02)
+ x = x + 1
+ !$omp end task
!ERROR: Clause MERGEABLE is not allowed if clause DETACH appears on the TASK directive
!$omp task detach(event_01) mergeable
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td
index e36eb77cefe7e..aec80decf6039 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.td
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td
@@ -1090,7 +1090,6 @@ def OMP_Task : Directive<"task"> {
VersionedClause<OMPC_Affinity, 50>,
VersionedClause<OMPC_Allocate>,
VersionedClause<OMPC_Depend>,
- VersionedClause<OMPC_Detach, 50>,
VersionedClause<OMPC_FirstPrivate>,
VersionedClause<OMPC_InReduction>,
VersionedClause<OMPC_Mergeable>,
@@ -1100,6 +1099,7 @@ def OMP_Task : Directive<"task"> {
];
let allowedOnceClauses = [
VersionedClause<OMPC_Default>,
+ VersionedClause<OMPC_Detach, 50>,
VersionedClause<OMPC_Final>,
VersionedClause<OMPC_If>,
VersionedClause<OMPC_Priority>,
>From 2c09c87ffd454186d9bd335e09c9bf0cd459c153 Mon Sep 17 00:00:00 2001
From: Thirumalai-Shaktivel <thirumalaishaktivel at gmail.com>
Date: Fri, 7 Mar 2025 05:06:18 +0000
Subject: [PATCH 08/15] Add a test for openmp 52
---
flang/test/Semantics/OpenMP/detach01.f90 | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/flang/test/Semantics/OpenMP/detach01.f90 b/flang/test/Semantics/OpenMP/detach01.f90
index ea8208c022ef1..8f19dfc1f92a7 100644
--- a/flang/test/Semantics/OpenMP/detach01.f90
+++ b/flang/test/Semantics/OpenMP/detach01.f90
@@ -50,4 +50,9 @@ program detach01
!$omp task detach(event_03)
x = x + 1
!$omp end task
+
+ !ERROR: At most one DETACH clause can appear on the TASK directive
+ !$omp task detach(event_01) detach(event_02)
+ x = x + 1
+ !$omp end task
end program
>From 6fc96f7795546aa0771f90d38e83cf3b2fffe32c Mon Sep 17 00:00:00 2001
From: Thirumalai-Shaktivel <thirumalaishaktivel at gmail.com>
Date: Fri, 2 May 2025 11:51:19 +0000
Subject: [PATCH 09/15] Rename a function name
---
flang/lib/Semantics/check-omp-structure.cpp | 32 ++++++++++-----------
flang/lib/Semantics/check-omp-structure.h | 4 +--
2 files changed, 18 insertions(+), 18 deletions(-)
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 346c11e9765b7..012529af0767d 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -1605,7 +1605,7 @@ void OmpStructureChecker::Leave(const parser::OpenMPThreadprivate &c) {
const auto &dir{std::get<parser::Verbatim>(c.t)};
const auto &objectList{std::get<parser::OmpObjectList>(c.t)};
CheckSymbolNames(dir.source, objectList);
- CheckIsVarPartOfAnotherVar(dir.source, objectList);
+ CheckVarIsNotPartOfAnotherVar(dir.source, objectList);
CheckThreadprivateOrDeclareTargetVar(objectList);
dirContext_.pop_back();
}
@@ -1736,7 +1736,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPDeclarativeAllocate &x) {
for (const auto &clause : clauseList.v) {
CheckAlignValue(clause);
}
- CheckIsVarPartOfAnotherVar(dir.source, objectList);
+ CheckVarIsNotPartOfAnotherVar(dir.source, objectList);
}
void OmpStructureChecker::Leave(const parser::OpenMPDeclarativeAllocate &x) {
@@ -1902,7 +1902,7 @@ void OmpStructureChecker::Leave(const parser::OpenMPDeclareTargetConstruct &x) {
if (const auto *objectList{parser::Unwrap<parser::OmpObjectList>(spec.u)}) {
deviceConstructFound_ = true;
CheckSymbolNames(dir.source, *objectList);
- CheckIsVarPartOfAnotherVar(dir.source, *objectList);
+ CheckVarIsNotPartOfAnotherVar(dir.source, *objectList);
CheckThreadprivateOrDeclareTargetVar(*objectList);
} else if (const auto *clauseList{
parser::Unwrap<parser::OmpClauseList>(spec.u)}) {
@@ -1915,18 +1915,18 @@ void OmpStructureChecker::Leave(const parser::OpenMPDeclareTargetConstruct &x) {
toClauseFound = true;
auto &objList{std::get<parser::OmpObjectList>(toClause.v.t)};
CheckSymbolNames(dir.source, objList);
- CheckIsVarPartOfAnotherVar(dir.source, objList);
+ CheckVarIsNotPartOfAnotherVar(dir.source, objList);
CheckThreadprivateOrDeclareTargetVar(objList);
},
[&](const parser::OmpClause::Link &linkClause) {
CheckSymbolNames(dir.source, linkClause.v);
- CheckIsVarPartOfAnotherVar(dir.source, linkClause.v);
+ CheckVarIsNotPartOfAnotherVar(dir.source, linkClause.v);
CheckThreadprivateOrDeclareTargetVar(linkClause.v);
},
[&](const parser::OmpClause::Enter &enterClause) {
enterClauseFound = true;
CheckSymbolNames(dir.source, enterClause.v);
- CheckIsVarPartOfAnotherVar(dir.source, enterClause.v);
+ CheckVarIsNotPartOfAnotherVar(dir.source, enterClause.v);
CheckThreadprivateOrDeclareTargetVar(enterClause.v);
},
[&](const parser::OmpClause::DeviceType &deviceTypeClause) {
@@ -2009,7 +2009,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPExecutableAllocate &x) {
CheckAlignValue(clause);
}
if (objectList) {
- CheckIsVarPartOfAnotherVar(dir.source, *objectList);
+ CheckVarIsNotPartOfAnotherVar(dir.source, *objectList);
}
}
@@ -2029,7 +2029,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPAllocatorsConstruct &x) {
for (const auto &clause : clauseList.v) {
if (const auto *allocClause{
parser::Unwrap<parser::OmpClause::Allocate>(clause)}) {
- CheckIsVarPartOfAnotherVar(
+ CheckVarIsNotPartOfAnotherVar(
dir.source, std::get<parser::OmpObjectList>(allocClause->v.t));
}
}
@@ -3791,14 +3791,14 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Ordered &x) {
void OmpStructureChecker::Enter(const parser::OmpClause::Shared &x) {
CheckAllowedClause(llvm::omp::Clause::OMPC_shared);
- CheckIsVarPartOfAnotherVar(GetContext().clauseSource, x.v, "SHARED");
+ CheckVarIsNotPartOfAnotherVar(GetContext().clauseSource, x.v, "SHARED");
CheckCrayPointee(x.v, "SHARED");
}
void OmpStructureChecker::Enter(const parser::OmpClause::Private &x) {
SymbolSourceMap symbols;
GetSymbolsInObjectList(x.v, symbols);
CheckAllowedClause(llvm::omp::Clause::OMPC_private);
- CheckIsVarPartOfAnotherVar(GetContext().clauseSource, x.v, "PRIVATE");
+ CheckVarIsNotPartOfAnotherVar(GetContext().clauseSource, x.v, "PRIVATE");
CheckIntentInPointer(symbols, llvm::omp::Clause::OMPC_private);
CheckCrayPointee(x.v, "PRIVATE");
}
@@ -3827,15 +3827,15 @@ bool OmpStructureChecker::IsDataRefTypeParamInquiry(
return dataRefIsTypeParamInquiry;
}
-void OmpStructureChecker::CheckIsVarPartOfAnotherVar(
+void OmpStructureChecker::CheckVarIsNotPartOfAnotherVar(
const parser::CharBlock &source, const parser::OmpObjectList &objList,
llvm::StringRef clause) {
for (const auto &ompObject : objList.v) {
- CheckIsVarPartOfAnotherVar(source, ompObject, clause);
+ CheckVarIsNotPartOfAnotherVar(source, ompObject, clause);
}
}
-void OmpStructureChecker::CheckIsVarPartOfAnotherVar(
+void OmpStructureChecker::CheckVarIsNotPartOfAnotherVar(
const parser::CharBlock &source, const parser::OmpObject &ompObject,
llvm::StringRef clause) {
common::visit(
@@ -3875,7 +3875,7 @@ void OmpStructureChecker::CheckIsVarPartOfAnotherVar(
void OmpStructureChecker::Enter(const parser::OmpClause::Firstprivate &x) {
CheckAllowedClause(llvm::omp::Clause::OMPC_firstprivate);
- CheckIsVarPartOfAnotherVar(GetContext().clauseSource, x.v, "FIRSTPRIVATE");
+ CheckVarIsNotPartOfAnotherVar(GetContext().clauseSource, x.v, "FIRSTPRIVATE");
CheckCrayPointee(x.v, "FIRSTPRIVATE");
CheckIsLoopIvPartOfClause(llvmOmpClause::OMPC_firstprivate, x.v);
@@ -4204,7 +4204,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Detach &x) {
// OpenMP 5.2: 12.5.2 Detach clause restrictions
unsigned version{context_.langOptions().OpenMPVersion};
if (version >= 52) {
- CheckIsVarPartOfAnotherVar(GetContext().clauseSource, x.v.v, "DETACH");
+ CheckVarIsNotPartOfAnotherVar(GetContext().clauseSource, x.v.v, "DETACH");
}
if (const auto *name{parser::Unwrap<parser::Name>(x.v.v)}) {
@@ -4571,7 +4571,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Lastprivate &x) {
CheckAllowedClause(llvm::omp::Clause::OMPC_lastprivate);
const auto &objectList{std::get<parser::OmpObjectList>(x.v.t)};
- CheckIsVarPartOfAnotherVar(
+ CheckVarIsNotPartOfAnotherVar(
GetContext().clauseSource, objectList, "LASTPRIVATE");
CheckCrayPointee(objectList, "LASTPRIVATE");
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 1517f89f476f4..be420332d491c 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -231,9 +231,9 @@ class OmpStructureChecker
const common::Indirection<parser::ArrayElement> &, const parser::Name &);
void CheckDoacross(const parser::OmpDoacross &doa);
bool IsDataRefTypeParamInquiry(const parser::DataRef *dataRef);
- void CheckIsVarPartOfAnotherVar(const parser::CharBlock &source,
+ void CheckVarIsNotPartOfAnotherVar(const parser::CharBlock &source,
const parser::OmpObject &obj, llvm::StringRef clause = "");
- void CheckIsVarPartOfAnotherVar(const parser::CharBlock &source,
+ void CheckVarIsNotPartOfAnotherVar(const parser::CharBlock &source,
const parser::OmpObjectList &objList, llvm::StringRef clause = "");
void CheckThreadprivateOrDeclareTargetVar(
const parser::OmpObjectList &objList);
>From 59075c12dd380f607874a4af3e9c0fc0cc67efd6 Mon Sep 17 00:00:00 2001
From: Thirumalai-Shaktivel <thirumalaishaktivel at gmail.com>
Date: Fri, 2 May 2025 11:54:18 +0000
Subject: [PATCH 10/15] Remove the check for symbol's nullptr
---
flang/lib/Semantics/check-omp-structure.cpp | 79 ++++++++++-----------
1 file changed, 37 insertions(+), 42 deletions(-)
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 012529af0767d..e98536fd506cb 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -3163,40 +3163,37 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &) {
const auto &detach{
std::get<parser::OmpClause::Detach>(detachClause->u)};
if (const auto *name{parser::Unwrap<parser::Name>(detach.v.v)}) {
- if (name->symbol) {
- Symbol *eventHandleSym{name->symbol};
- auto checkVarAppearsInDataEnvClause = [&](const parser::
- OmpObjectList &objs,
- std::string clause) {
- for (const auto &obj : objs.v) {
- if (const parser::Name *
- objName{parser::Unwrap<parser::Name>(obj)}) {
- if (&objName->symbol->GetUltimate() == eventHandleSym) {
- context_.Say(GetContext().clauseSource,
- "A variable: `%s` that appears in a DETACH clause cannot appear on %s clause on the same construct"_err_en_US,
- objName->source, clause);
- }
+ Symbol *eventHandleSym{name->symbol};
+ auto checkVarAppearsInDataEnvClause = [&](const parser::OmpObjectList
+ &objs,
+ std::string clause) {
+ for (const auto &obj : objs.v) {
+ if (const parser::Name *objName{
+ parser::Unwrap<parser::Name>(obj)}) {
+ if (&objName->symbol->GetUltimate() == eventHandleSym) {
+ context_.Say(GetContext().clauseSource,
+ "A variable: `%s` that appears in a DETACH clause cannot appear on %s clause on the same construct"_err_en_US,
+ objName->source, clause);
}
}
- };
- if (auto *dataEnvClause{
- FindClause(llvm::omp::Clause::OMPC_private)}) {
- const auto &pClause{
- std::get<parser::OmpClause::Private>(dataEnvClause->u)};
- checkVarAppearsInDataEnvClause(pClause.v, "PRIVATE");
- } else if (auto *dataEnvClause{
- FindClause(llvm::omp::Clause::OMPC_firstprivate)}) {
- const auto &fpClause{
- std::get<parser::OmpClause::Firstprivate>(dataEnvClause->u)};
- checkVarAppearsInDataEnvClause(fpClause.v, "FIRSTPRIVATE");
- } else if (auto *dataEnvClause{
- FindClause(llvm::omp::Clause::OMPC_in_reduction)}) {
- const auto &irClause{
- std::get<parser::OmpClause::InReduction>(dataEnvClause->u)};
- checkVarAppearsInDataEnvClause(
- std::get<parser::OmpObjectList>(irClause.v.t),
- "IN_REDUCTION");
}
+ };
+ if (auto *dataEnvClause{
+ FindClause(llvm::omp::Clause::OMPC_private)}) {
+ const auto &pClause{
+ std::get<parser::OmpClause::Private>(dataEnvClause->u)};
+ checkVarAppearsInDataEnvClause(pClause.v, "PRIVATE");
+ } else if (auto *dataEnvClause{
+ FindClause(llvm::omp::Clause::OMPC_firstprivate)}) {
+ const auto &fpClause{
+ std::get<parser::OmpClause::Firstprivate>(dataEnvClause->u)};
+ checkVarAppearsInDataEnvClause(fpClause.v, "FIRSTPRIVATE");
+ } else if (auto *dataEnvClause{
+ FindClause(llvm::omp::Clause::OMPC_in_reduction)}) {
+ const auto &irClause{
+ std::get<parser::OmpClause::InReduction>(dataEnvClause->u)};
+ checkVarAppearsInDataEnvClause(
+ std::get<parser::OmpObjectList>(irClause.v.t), "IN_REDUCTION");
}
}
}
@@ -4208,17 +4205,15 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Detach &x) {
}
if (const auto *name{parser::Unwrap<parser::Name>(x.v.v)}) {
- if (name->symbol) {
- if (version >= 52 && IsPointer(*name->symbol)) {
- context_.Say(GetContext().clauseSource,
- "The event-handle: `%s` must not have the POINTER attribute"_err_en_US,
- name->ToString());
- }
- if (!name->symbol->GetType()->IsNumeric(TypeCategory::Integer)) {
- context_.Say(GetContext().clauseSource,
- "The event-handle: `%s` must be of type integer(kind=omp_event_handle_kind)"_err_en_US,
- name->ToString());
- }
+ if (version >= 52 && IsPointer(*name->symbol)) {
+ context_.Say(GetContext().clauseSource,
+ "The event-handle: `%s` must not have the POINTER attribute"_err_en_US,
+ name->ToString());
+ }
+ if (!name->symbol->GetType()->IsNumeric(TypeCategory::Integer)) {
+ context_.Say(GetContext().clauseSource,
+ "The event-handle: `%s` must be of type integer(kind=omp_event_handle_kind)"_err_en_US,
+ name->ToString());
}
}
}
>From 965df852abd5ffa1735e19491c0df1b04f58470d Mon Sep 17 00:00:00 2001
From: Thirumalai-Shaktivel <thirumalaishaktivel at gmail.com>
Date: Fri, 2 May 2025 11:54:40 +0000
Subject: [PATCH 11/15] CheckAllowedClause for OpenMP 50 and 51
---
flang/lib/Semantics/check-omp-structure.cpp | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index e98536fd506cb..cb0e06ed6aa32 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -4196,10 +4196,14 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Linear &x) {
}
void OmpStructureChecker::Enter(const parser::OmpClause::Detach &x) {
- // OpenMP 5.0: 2.10.1 Task construct restrictions
- CheckAllowedClause(llvm::omp::Clause::OMPC_detach);
- // OpenMP 5.2: 12.5.2 Detach clause restrictions
unsigned version{context_.langOptions().OpenMPVersion};
+ if (version >= 52) {
+ SetContextClauseInfo(llvm::omp::Clause::OMPC_detach);
+ } else {
+ // OpenMP 5.0: 2.10.1 Task construct restrictions
+ CheckAllowedClause(llvm::omp::Clause::OMPC_detach);
+ }
+ // OpenMP 5.2: 12.5.2 Detach clause restrictions
if (version >= 52) {
CheckVarIsNotPartOfAnotherVar(GetContext().clauseSource, x.v.v, "DETACH");
}
>From d13d267f8d8a5641c4556b98b9e4eea119f21adf Mon Sep 17 00:00:00 2001
From: Thirumalai-Shaktivel <thirumalaishaktivel at gmail.com>
Date: Fri, 2 May 2025 11:55:07 +0000
Subject: [PATCH 12/15] Fix the error message string to be in a single line
---
flang/lib/Semantics/check-omp-structure.cpp | 11 +++--------
1 file changed, 3 insertions(+), 8 deletions(-)
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index cb0e06ed6aa32..06437dc7a8588 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -3842,23 +3842,18 @@ void OmpStructureChecker::CheckVarIsNotPartOfAnotherVar(
std::get_if<parser::DataRef>(&designator.u)}) {
if (IsDataRefTypeParamInquiry(dataRef)) {
context_.Say(source,
- "A type parameter inquiry cannot appear on the %s "
- "directive"_err_en_US,
+ "A type parameter inquiry cannot appear on the %s directive"_err_en_US,
ContextDirectiveAsFortran());
} else if (parser::Unwrap<parser::StructureComponent>(
ompObject) ||
parser::Unwrap<parser::ArrayElement>(ompObject)) {
if (llvm::omp::nonPartialVarSet.test(GetContext().directive)) {
context_.Say(source,
- "A variable that is part of another variable (as an "
- "array or structure element) cannot appear on the %s "
- "directive"_err_en_US,
+ "A variable that is part of another variable (as an array or structure element) cannot appear on the %s directive"_err_en_US,
ContextDirectiveAsFortran());
} else {
context_.Say(source,
- "A variable that is part of another variable (as an "
- "array or structure element) cannot appear in a "
- "%s clause"_err_en_US,
+ "A variable that is part of another variable (as an array or structure element) cannot appear in a %s clause"_err_en_US,
clause.data());
}
}
>From 573580e5526d7981fb93077b5fd05b7a3547ec85 Mon Sep 17 00:00:00 2001
From: Thirumalai-Shaktivel <thirumalaishaktivel at gmail.com>
Date: Fri, 2 May 2025 11:55:40 +0000
Subject: [PATCH 13/15] Add check for shared clause as well
---
flang/lib/Semantics/check-omp-structure.cpp | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 06437dc7a8588..3223652a27187 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -3183,6 +3183,11 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &) {
const auto &pClause{
std::get<parser::OmpClause::Private>(dataEnvClause->u)};
checkVarAppearsInDataEnvClause(pClause.v, "PRIVATE");
+ } else if (auto *dataEnvClause{
+ FindClause(llvm::omp::Clause::OMPC_shared)}) {
+ const auto &sClause{
+ std::get<parser::OmpClause::Shared>(dataEnvClause->u)};
+ checkVarAppearsInDataEnvClause(sClause.v, "SHARED");
} else if (auto *dataEnvClause{
FindClause(llvm::omp::Clause::OMPC_firstprivate)}) {
const auto &fpClause{
>From 5d9be322e9577b4ac7ba6b3b8b30336f2693b588 Mon Sep 17 00:00:00 2001
From: Thirumalai-Shaktivel <thirumalaishaktivel at gmail.com>
Date: Fri, 2 May 2025 11:58:27 +0000
Subject: [PATCH 14/15] Remove a test
---
flang/test/Semantics/OpenMP/detach01.f90 | 5 -----
1 file changed, 5 deletions(-)
diff --git a/flang/test/Semantics/OpenMP/detach01.f90 b/flang/test/Semantics/OpenMP/detach01.f90
index 8f19dfc1f92a7..ea8208c022ef1 100644
--- a/flang/test/Semantics/OpenMP/detach01.f90
+++ b/flang/test/Semantics/OpenMP/detach01.f90
@@ -50,9 +50,4 @@ program detach01
!$omp task detach(event_03)
x = x + 1
!$omp end task
-
- !ERROR: At most one DETACH clause can appear on the TASK directive
- !$omp task detach(event_01) detach(event_02)
- x = x + 1
- !$omp end task
end program
>From 47fbdc4a08a30cfb70545bb1adf1f72a7c67bbd9 Mon Sep 17 00:00:00 2001
From: Thirumalai-Shaktivel <thirumalaishaktivel at gmail.com>
Date: Fri, 2 May 2025 12:10:06 +0000
Subject: [PATCH 15/15] Add some more tests
---
flang/test/Semantics/OpenMP/detach01.f90 | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/flang/test/Semantics/OpenMP/detach01.f90 b/flang/test/Semantics/OpenMP/detach01.f90
index ea8208c022ef1..7729c85ea1128 100644
--- a/flang/test/Semantics/OpenMP/detach01.f90
+++ b/flang/test/Semantics/OpenMP/detach01.f90
@@ -31,6 +31,16 @@ program detach01
x = x + 1
!$omp end task
+ !ERROR: A variable: `event_01` that appears in a DETACH clause cannot appear on FIRSTPRIVATE clause on the same construct
+ !$omp task detach(event_01) firstprivate(event_01)
+ x = x + 1
+ !$omp end task
+
+ !ERROR: A variable: `event_01` that appears in a DETACH clause cannot appear on SHARED clause on the same construct
+ !$omp task detach(event_01) shared(event_01)
+ x = x + 1
+ !$omp end task
+
!ERROR: A variable: `event_01` that appears in a DETACH clause cannot appear on IN_REDUCTION clause on the same construct
!$omp task detach(event_01) in_reduction(+:event_01)
x = x + 1
More information about the flang-commits
mailing list