[flang-commits] [flang] [flang][OpenMP] Add type-param-inquiry checks for non-list clauses (PR #203059)
via flang-commits
flang-commits at lists.llvm.org
Wed Jun 10 10:50:20 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-semantics
Author: Krzysztof Parzyszek (kparzysz)
<details>
<summary>Changes</summary>
Clauses that take lists of objects have these objects checked in a single place. There are still several clauses that take variables, but not via a list. Those clauses still need individual checks for type-param inquiries.
---
Full diff: https://github.com/llvm/llvm-project/pull/203059.diff
3 Files Affected:
- (modified) flang/lib/Semantics/check-omp-structure.cpp (+57-35)
- (modified) flang/lib/Semantics/check-omp-structure.h (+4-2)
- (added) flang/test/Semantics/OpenMP/type-param-inquiry.f90 (+42)
``````````diff
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 8651678bb2f8a..99f43160ddd7b 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -1768,7 +1768,8 @@ void OmpStructureChecker::Leave(const parser::OmpThreadprivateDirective &x) {
for (const parser::OmpArgument &arg : x.v.Arguments().v) {
if (auto *object{GetArgumentObject(arg)}) {
CheckSymbolName(dirSpec.source, *object);
- CheckTypeParamInquiry(dirSpec.source, *object);
+ CheckTypeParamInquiry(
+ dirSpec.source, *object, llvm::omp::Directive::OMPD_threadprivate);
CheckVarIsNotPartOfAnotherVar(dirSpec.source, *object);
CheckThreadprivateOrDeclareTargetVar(*object);
}
@@ -1867,6 +1868,9 @@ void OmpStructureChecker::CheckInitOnDepobj(
"The INIT clause is not allowed when the DEPOBJ directive has an argument"_err_en_US);
}
+ CheckTypeParamInquiry(initClause.source, std::get<parser::OmpObject>(init.t),
+ llvm::omp::Clause::OMPC_init);
+
if (!OmpVerifyModifiers(
init, llvm::omp::Clause::OMPC_init, initClause.source, context_)) {
return;
@@ -2146,7 +2150,8 @@ void OmpStructureChecker::CheckIndividualAllocateDirective(
if (!IsTypeParamInquiry(*symbol)) {
checkSymbol(*symbol, arg.source);
}
- CheckTypeParamInquiry(dirName.source, *object);
+ CheckTypeParamInquiry(
+ dirName.source, *object, llvm::omp::Directive::OMPD_allocate);
CheckVarIsNotPartOfAnotherVar(dirName.source, *object);
}
}
@@ -2477,7 +2482,8 @@ void OmpStructureChecker::Leave(const parser::OmpDeclareTargetDirective &x) {
if (auto *object{GetArgumentObject(arg)}) {
deviceConstructFound_ = true;
CheckSymbolName(dirName.source, *object);
- CheckTypeParamInquiry(dirName.source, *object);
+ CheckTypeParamInquiry(
+ dirName.source, *object, llvm::omp::Directive::OMPD_declare_target);
CheckVarIsNotPartOfAnotherVar(dirName.source, *object);
CheckThreadprivateOrDeclareTargetVar(*object);
}
@@ -2671,7 +2677,6 @@ void OmpStructureChecker::Enter(const parser::OpenMPAllocatorsConstruct &x) {
continue;
}
for (auto &object : DEREF(GetOmpObjectList(clause)).v) {
- CheckTypeParamInquiry(dirName.source, object);
CheckVarIsNotPartOfAnotherVar(dirName.source, object);
if (auto *symbol{GetObjectSymbol(object, /*ultimate=*/true)}) {
if (IsStructureComponent(*symbol)) {
@@ -3772,6 +3777,10 @@ void OmpStructureChecker::Enter(const parser::OmpClause &x) {
void OmpStructureChecker::Enter(const parser::OmpClause::Destroy &x) {
CheckAllowedClause(llvm::omp::Clause::OMPC_destroy);
+ if (auto &present{x.v}) {
+ CheckTypeParamInquiry(
+ GetContext().clauseSource, present->v, llvm::omp::Clause::OMPC_destroy);
+ }
llvm::omp::Directive dir{GetContext().directive};
unsigned version{context_.langOptions().OpenMPVersion};
@@ -4282,21 +4291,25 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Nowait &x) {
CheckAllowedClause(llvm::omp::Clause::OMPC_nowait);
}
-void OmpStructureChecker::CheckTypeParamInquiry(
- const parser::CharBlock &source, const parser::OmpObject &object) {
+void OmpStructureChecker::CheckTypeParamInquiry(const parser::CharBlock &source,
+ const parser::OmpObject &object, llvm::omp::Directive dirId) {
if (const Symbol *symbol{GetObjectSymbol(object)}) {
if (IsTypeParamInquiry(*symbol)) {
context_.Say(source,
"A type parameter inquiry cannot appear on the %s directive"_err_en_US,
- ContextDirectiveAsFortran());
+ GetUpperName(dirId, context_.langOptions().OpenMPVersion));
}
}
}
-void OmpStructureChecker::CheckTypeParamInquiry(
- const parser::CharBlock &source, const parser::OmpObjectList &objects) {
- for (const parser::OmpObject &object : objects.v) {
- CheckTypeParamInquiry(source, object);
+void OmpStructureChecker::CheckTypeParamInquiry(const parser::CharBlock &source,
+ const parser::OmpObject &object, llvm::omp::Clause clauseId) {
+ if (const Symbol *symbol{GetObjectSymbol(object)}) {
+ if (IsTypeParamInquiry(*symbol)) {
+ context_.Say(source,
+ "A type parameter inquiry cannot appear on the %s clause"_err_en_US,
+ GetUpperName(clauseId, context_.langOptions().OpenMPVersion));
+ }
}
}
@@ -4543,6 +4556,8 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Detach &x) {
CheckAllowedClause(llvm::omp::Clause::OMPC_detach);
}
+ CheckTypeParamInquiry(
+ GetContext().clauseSource, x.v.v, llvm::omp::Clause::OMPC_detach);
// OpenMP 5.2: 12.5.2 Detach clause restrictions
if (version >= 52) {
CheckVarIsNotPartOfAnotherVar(GetContext().clauseSource, x.v.v, "DETACH");
@@ -5900,42 +5915,49 @@ void OmpStructureChecker::Enter(const parser::OpenMPInteropConstruct &x) {
desc.name.str());
}
}
- const auto &interopVar{parser::Unwrap<parser::OmpObject>(
+ const auto *interopVar{parser::Unwrap<parser::OmpObject>(
std::get<parser::OmpObject>(initClause.v.t))};
- const auto *name{parser::Unwrap<parser::Name>(interopVar)};
- const auto *objectSymbol{name->symbol};
- if (llvm::is_contained(objectSymbolList, objectSymbol)) {
- context_.Say(GetContext().directiveSource,
- "Each interop-var may be specified for at most one action-clause of each INTEROP construct."_err_en_US);
- } else {
- objectSymbolList.insert(objectSymbol);
+ CheckTypeParamInquiry(
+ clause.source, *interopVar, llvm::omp::Clause::OMPC_init);
+ if (const auto *name{parser::Unwrap<parser::Name>(interopVar)}) {
+ const auto *objectSymbol{name->symbol};
+ if (llvm::is_contained(objectSymbolList, objectSymbol)) {
+ context_.Say(GetContext().directiveSource,
+ "Each interop-var may be specified for at most one action-clause of each INTEROP construct."_err_en_US);
+ } else {
+ objectSymbolList.insert(objectSymbol);
+ }
}
},
[&](const parser::OmpClause::Depend &dependClause) {
isDependClauseOccurred = true;
},
[&](const parser::OmpClause::Destroy &destroyClause) {
- const auto &interopVar{
+ const auto *interopVar{
parser::Unwrap<parser::OmpObject>(destroyClause.v)};
- const auto *name{parser::Unwrap<parser::Name>(interopVar)};
- const auto *objectSymbol{name->symbol};
- if (llvm::is_contained(objectSymbolList, objectSymbol)) {
- context_.Say(GetContext().directiveSource,
- "Each interop-var may be specified for at most one action-clause of each INTEROP construct."_err_en_US);
- } else {
- objectSymbolList.insert(objectSymbol);
+ if (const auto *name{parser::Unwrap<parser::Name>(interopVar)}) {
+ const auto *objectSymbol{name->symbol};
+ if (llvm::is_contained(objectSymbolList, objectSymbol)) {
+ context_.Say(GetContext().directiveSource,
+ "Each interop-var may be specified for at most one action-clause of each INTEROP construct."_err_en_US);
+ } else {
+ objectSymbolList.insert(objectSymbol);
+ }
}
},
[&](const parser::OmpClause::Use &useClause) {
- const auto &interopVar{
+ const auto *interopVar{
parser::Unwrap<parser::OmpObject>(useClause.v)};
- const auto *name{parser::Unwrap<parser::Name>(interopVar)};
- const auto *objectSymbol{name->symbol};
- if (llvm::is_contained(objectSymbolList, objectSymbol)) {
- context_.Say(GetContext().directiveSource,
- "Each interop-var may be specified for at most one action-clause of each INTEROP construct."_err_en_US);
- } else {
- objectSymbolList.insert(objectSymbol);
+ CheckTypeParamInquiry(
+ clause.source, *interopVar, llvm::omp::Clause::OMPC_use);
+ if (const auto *name{parser::Unwrap<parser::Name>(interopVar)}) {
+ const auto *objectSymbol{name->symbol};
+ if (llvm::is_contained(objectSymbolList, objectSymbol)) {
+ context_.Say(GetContext().directiveSource,
+ "Each interop-var may be specified for at most one action-clause of each INTEROP construct."_err_en_US);
+ } else {
+ objectSymbolList.insert(objectSymbol);
+ }
}
},
[&](const auto &) {},
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index e601273d81f67..3c8ae4043071e 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -334,9 +334,11 @@ class OmpStructureChecker : public OmpStructureCheckerBase {
void CheckDimsModifier(parser::CharBlock source, size_t numValues,
const parser::OmpDimsModifier &x);
void CheckTypeParamInquiry(
- const parser::CharBlock &source, const parser::OmpObject &object);
+ const parser::CharBlock &source, const parser::OmpObject &object,
+ llvm::omp::Directive dirId);
void CheckTypeParamInquiry(
- const parser::CharBlock &source, const parser::OmpObjectList &objects);
+ const parser::CharBlock &source, const parser::OmpObject &object,
+ llvm::omp::Clause clauseId);
void CheckVarIsNotPartOfAnotherVar(const parser::CharBlock &source,
const parser::OmpObject &object, llvm::StringRef clause = "");
void CheckVarIsNotPartOfAnotherVar(const parser::CharBlock &source,
diff --git a/flang/test/Semantics/OpenMP/type-param-inquiry.f90 b/flang/test/Semantics/OpenMP/type-param-inquiry.f90
new file mode 100644
index 0000000000000..913682f7d6af0
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/type-param-inquiry.f90
@@ -0,0 +1,42 @@
+!RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags -fopenmp-version=60
+
+subroutine f00
+ integer :: x
+!ERROR: A type parameter inquiry cannot appear on the INIT clause
+ !$omp interop init(x%kind)
+end
+
+subroutine f01
+ integer :: x
+!ERROR: A type parameter inquiry cannot appear on the USE clause
+ !$omp interop use(x%kind)
+end
+
+subroutine f02
+ integer :: x
+!ERROR: A type parameter inquiry cannot appear on the DESTROY clause
+ !$omp interop destroy(x%kind)
+end
+
+subroutine f03
+ integer :: x
+!ERROR: A type parameter inquiry cannot appear on the DETACH clause
+ !$omp task detach(x%kind)
+ !$omp end task
+end
+
+subroutine f04
+ integer :: x
+!ERROR: DEPOBJ syntax with no argument is not handled yet
+!ERROR: A type parameter inquiry cannot appear on the INIT clause
+!ERROR: The 'depinfo-modifier' modifier is required on a DEPOBJ construct
+ !$omp depobj init(x%kind)
+end
+
+subroutine f05
+ integer :: x
+!ERROR: DEPOBJ syntax with no argument is not handled yet
+!ERROR: A type parameter inquiry cannot appear on the DESTROY clause
+ !$omp depobj destroy(x%kind)
+end
+
``````````
</details>
https://github.com/llvm/llvm-project/pull/203059
More information about the flang-commits
mailing list