[flang-commits] [flang] [flang][OpenMP] Move check for substring to semantic checks (PR #201384)
Krzysztof Parzyszek via flang-commits
flang-commits at lists.llvm.org
Tue Jun 9 08:13:45 PDT 2026
https://github.com/kparzysz updated https://github.com/llvm/llvm-project/pull/201384
>From 9877fa75ab9e63b8c705ddaf9e840781975c732c Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Sun, 17 May 2026 07:18:36 -0500
Subject: [PATCH 1/5] [flang][OpenMP] Separate checks for type-parameter
inquiry and subobject
This will make it possible to diagnose these situations independently.
This isn't perfect, but will be improved gradually in the future.
---
flang/lib/Semantics/check-omp-structure.cpp | 77 +++++++++++++--------
flang/lib/Semantics/check-omp-structure.h | 6 +-
2 files changed, 54 insertions(+), 29 deletions(-)
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 1ac43b666977b..055fa2325f5a1 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -1630,6 +1630,7 @@ 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);
CheckVarIsNotPartOfAnotherVar(dirSpec.source, *object);
CheckThreadprivateOrDeclareTargetVar(*object);
}
@@ -2007,6 +2008,7 @@ void OmpStructureChecker::CheckIndividualAllocateDirective(
if (!IsTypeParamInquiry(*symbol)) {
checkSymbol(*symbol, arg.source);
}
+ CheckTypeParamInquiry(dirName.source, *object);
CheckVarIsNotPartOfAnotherVar(dirName.source, *object);
}
}
@@ -2337,6 +2339,7 @@ void OmpStructureChecker::Leave(const parser::OmpDeclareTargetDirective &x) {
if (auto *object{GetArgumentObject(arg)}) {
deviceConstructFound_ = true;
CheckSymbolName(dirName.source, *object);
+ CheckTypeParamInquiry(dirName.source, *object);
CheckVarIsNotPartOfAnotherVar(dirName.source, *object);
CheckThreadprivateOrDeclareTargetVar(*object);
}
@@ -2382,6 +2385,7 @@ void OmpStructureChecker::Leave(const parser::OmpDeclareTargetDirective &x) {
std::is_same_v<TypeC, parser::OmpClause::To>) {
auto &objList{*GetOmpObjectList(c)};
CheckSymbolNames(dirName.source, objList);
+ CheckTypeParamInquiry(dirName.source, objList);
CheckVarIsNotPartOfAnotherVar(dirName.source, objList);
CheckThreadprivateOrDeclareTargetVar(objList);
}
@@ -2530,6 +2534,7 @@ 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)) {
@@ -4171,6 +4176,7 @@ void OmpStructureChecker::CheckSharedBindingInOuterContext(
void OmpStructureChecker::Enter(const parser::OmpClause::Shared &x) {
CheckAllowedClause(llvm::omp::Clause::OMPC_shared);
+ CheckTypeParamInquiry(GetContext().clauseSource, x.v);
CheckVarIsNotPartOfAnotherVar(GetContext().clauseSource, x.v, "SHARED");
CheckCrayPointee(x.v, "SHARED");
}
@@ -4178,6 +4184,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Private &x) {
SymbolSourceMap symbols;
GetSymbolsInObjectList(x.v, symbols);
CheckAllowedClause(llvm::omp::Clause::OMPC_private);
+ CheckTypeParamInquiry(GetContext().clauseSource, x.v);
CheckVarIsNotPartOfAnotherVar(GetContext().clauseSource, x.v, "PRIVATE");
CheckIntentInPointer(symbols, llvm::omp::Clause::OMPC_private);
CheckCrayPointee(x.v, "PRIVATE");
@@ -4188,6 +4195,24 @@ 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) {
+ 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());
+ }
+ }
+}
+
+void OmpStructureChecker::CheckTypeParamInquiry(
+ const parser::CharBlock &source, const parser::OmpObjectList &objects) {
+ for (const parser::OmpObject &object : objects.v) {
+ CheckTypeParamInquiry(source, object);
+ }
+}
+
void OmpStructureChecker::CheckVarIsNotPartOfAnotherVar(
const parser::CharBlock &source, const parser::OmpObjectList &objList,
llvm::StringRef clause) {
@@ -4197,40 +4222,33 @@ void OmpStructureChecker::CheckVarIsNotPartOfAnotherVar(
}
void OmpStructureChecker::CheckVarIsNotPartOfAnotherVar(
- const parser::CharBlock &source, const parser::OmpObject &ompObject,
+ const parser::CharBlock &source, const parser::OmpObject &object,
llvm::StringRef clause) {
- common::visit(
- common::visitors{
- [&](const parser::Designator &designator) {
- if (auto *symbol{GetLastName(designator).symbol};
- symbol && IsTypeParamInquiry(*symbol)) {
- context_.Say(source,
- "A type parameter inquiry cannot appear on the %s directive"_err_en_US,
- ContextDirectiveAsFortran());
- } else if (std::holds_alternative<parser::DataRef>(designator.u)) {
- 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());
- }
- }
- }
- },
- [&](const parser::Name &name) {},
- [&](const parser::OmpObject::Invalid &invalid) {},
- },
- ompObject.u);
+ bool report{false};
+ if (auto *symbol{GetObjectSymbol(object)}) {
+ if (IsTypeParamInquiry(*symbol)) {
+ return;
+ }
+ report = IsStructureComponent(*symbol);
+ }
+
+ if (report || parser::Unwrap<parser::ArrayElement>(object)) {
+ 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.str());
+ }
+ }
}
void OmpStructureChecker::Enter(const parser::OmpClause::Firstprivate &x) {
CheckAllowedClause(llvm::omp::Clause::OMPC_firstprivate);
+ CheckTypeParamInquiry(GetContext().clauseSource, x.v);
CheckVarIsNotPartOfAnotherVar(GetContext().clauseSource, x.v, "FIRSTPRIVATE");
CheckCrayPointee(x.v, "FIRSTPRIVATE");
@@ -4434,6 +4452,8 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Detach &x) {
// OpenMP 5.0: 2.10.1 Task construct restrictions
CheckAllowedClause(llvm::omp::Clause::OMPC_detach);
}
+
+ CheckTypeParamInquiry(GetContext().clauseSource, x.v.v);
// OpenMP 5.2: 12.5.2 Detach clause restrictions
if (version >= 52) {
CheckVarIsNotPartOfAnotherVar(GetContext().clauseSource, x.v.v, "DETACH");
@@ -4899,6 +4919,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Lastprivate &x) {
CheckAllowedClause(llvm::omp::Clause::OMPC_lastprivate);
const auto &objectList{*GetOmpObjectList(x)};
+ CheckTypeParamInquiry(GetContext().clauseSource, objectList);
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 6e693fa7b8e48..2baec90c90ca6 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -334,8 +334,12 @@ class OmpStructureChecker : public OmpStructureCheckerBase {
void CheckDoacross(const parser::OmpDoacross &doa);
void CheckDimsModifier(parser::CharBlock source, size_t numValues,
const parser::OmpDimsModifier &x);
+ void CheckTypeParamInquiry(const parser::CharBlock &source,
+ const parser::OmpObject &object);
+ void CheckTypeParamInquiry(const parser::CharBlock &source,
+ const parser::OmpObjectList &objects);
void CheckVarIsNotPartOfAnotherVar(const parser::CharBlock &source,
- const parser::OmpObject &obj, llvm::StringRef clause = "");
+ const parser::OmpObject &object, llvm::StringRef clause = "");
void CheckVarIsNotPartOfAnotherVar(const parser::CharBlock &source,
const parser::OmpObjectList &objList, llvm::StringRef clause = "");
void CheckThreadprivateOrDeclareTargetVar(const parser::Designator &);
>From 5961e1fe9432d66242e3cbbda04765ac37e77b65 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Wed, 3 Jun 2026 06:32:25 -0500
Subject: [PATCH 2/5] format
---
flang/lib/Semantics/check-omp-structure.h | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 2baec90c90ca6..8a85f489eeb4c 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -334,10 +334,10 @@ class OmpStructureChecker : public OmpStructureCheckerBase {
void CheckDoacross(const parser::OmpDoacross &doa);
void CheckDimsModifier(parser::CharBlock source, size_t numValues,
const parser::OmpDimsModifier &x);
- void CheckTypeParamInquiry(const parser::CharBlock &source,
- const parser::OmpObject &object);
- void CheckTypeParamInquiry(const parser::CharBlock &source,
- const parser::OmpObjectList &objects);
+ void CheckTypeParamInquiry(
+ const parser::CharBlock &source, const parser::OmpObject &object);
+ void CheckTypeParamInquiry(
+ const parser::CharBlock &source, const parser::OmpObjectList &objects);
void CheckVarIsNotPartOfAnotherVar(const parser::CharBlock &source,
const parser::OmpObject &object, llvm::StringRef clause = "");
void CheckVarIsNotPartOfAnotherVar(const parser::CharBlock &source,
>From 93b141d5416e1dbb07fb42c0074acdff3f9e60e1 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Sun, 17 May 2026 07:18:36 -0500
Subject: [PATCH 3/5] [flang][OpenMP] More detailed checks for argument list
items in clauses
For clauses that take list of variable, locator, and extended list
items, perform checks that the actual arguments meet the corresponding
requirements. This is version-based, since clause requirements have
changed over time.
---
flang/include/flang/Semantics/openmp-utils.h | 25 ++
flang/lib/Semantics/check-omp-structure.cpp | 212 ++++++++++-------
flang/lib/Semantics/check-omp-structure.h | 2 +-
flang/lib/Semantics/openmp-utils.cpp | 225 +++++++++++++++++-
flang/test/Semantics/OpenMP/copyprivate04.f90 | 2 +-
flang/test/Semantics/OpenMP/copyprivate05.f90 | 2 +-
.../Semantics/OpenMP/declare-target01.f90 | 30 +--
.../test/Semantics/OpenMP/from-clause-v45.f90 | 2 +-
.../test/Semantics/OpenMP/from-clause-v51.f90 | 2 +-
flang/test/Semantics/OpenMP/in-reduction.f90 | 2 +-
flang/test/Semantics/OpenMP/lastprivate01.f90 | 3 +-
flang/test/Semantics/OpenMP/name-conflict.f90 | 4 +-
.../test/Semantics/OpenMP/named-constants.f90 | 8 +-
flang/test/Semantics/OpenMP/reduction04.f90 | 3 +-
flang/test/Semantics/OpenMP/reduction16.f90 | 2 +-
.../test/Semantics/OpenMP/task-reduction.f90 | 2 +-
flang/test/Semantics/OpenMP/to-clause-v45.f90 | 2 +-
flang/test/Semantics/OpenMP/to-clause-v51.f90 | 2 +-
18 files changed, 405 insertions(+), 125 deletions(-)
diff --git a/flang/include/flang/Semantics/openmp-utils.h b/flang/include/flang/Semantics/openmp-utils.h
index 4001b337193a1..0b6bd40ad84c2 100644
--- a/flang/include/flang/Semantics/openmp-utils.h
+++ b/flang/include/flang/Semantics/openmp-utils.h
@@ -95,12 +95,20 @@ bool IsCommonBlock(const Symbol &sym);
bool IsExtendedListItem(const Symbol &sym);
bool IsVariableListItem(const Symbol &sym);
bool IsTypeParamInquiry(const Symbol &sym);
+bool IsComplexPart(const Symbol &sym);
bool IsStructureComponent(const Symbol &sym);
bool IsPrivatizable(const Symbol &sym);
bool IsVarOrFunctionRef(const MaybeExpr &expr);
bool IsWholeAssumedSizeArray(const parser::OmpObject &object);
+bool IsExtendedListItem(
+ const parser::OmpObject &object, SemanticsContext *semaCtx);
+bool IsLocatorListItem(
+ const parser::OmpObject &object, SemanticsContext *semaCtx);
+bool IsVariableListItem(
+ const parser::OmpObject &object, SemanticsContext *semaCtx);
+
const Symbol *GetHostSymbol(const Symbol &sym);
bool IsMapEnteringType(parser::OmpMapType::Value type);
@@ -139,6 +147,23 @@ bool IsPointerAssignment(const evaluate::Assignment &x);
MaybeExpr MakeEvaluateExpr(const parser::OmpStylizedInstance &inp);
+enum struct ListItemKind : uint32_t {
+ Depend,
+ DirectiveName,
+ DirectiveSpecification,
+ Extended,
+ IntegerExpression,
+ Interop,
+ Locator,
+ Operation,
+ Parameter,
+ ProcedureArgument,
+ Variable,
+};
+
+std::optional<ListItemKind> GetArgumentListItemKind(
+ llvm::omp::Clause clause, unsigned version);
+
bool IsLoopTransforming(llvm::omp::Directive dir);
bool HasDataEnvironment(llvm::omp::Directive dir);
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 055fa2325f5a1..94187aff125ee 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -424,12 +424,6 @@ void OmpStructureChecker::AnalyzeObject(const parser::OmpObject &object) {
object.u);
}
-void OmpStructureChecker::AnalyzeObjects(const parser::OmpObjectList &objects) {
- for (const parser::OmpObject &object : objects.v) {
- AnalyzeObject(object);
- }
-}
-
const parser::OpenMPConstruct *
OmpStructureChecker::GetCurrentConstruct() const {
for (const LoopOrConstruct &c : llvm::reverse(constructStack_)) {
@@ -624,12 +618,120 @@ bool OmpStructureChecker::HasRequires(llvm::omp::Clause req) {
DEREF(unit.symbol()).details());
}
-void OmpStructureChecker::CheckVariableListItem(
- const SymbolSourceMap &symbols) {
- for (auto &[symbol, source] : symbols) {
- if (!IsVariableListItem(*symbol)) {
- context_.SayWithDecl(
- *symbol, source, "'%s' must be a variable"_err_en_US, symbol->name());
+void OmpStructureChecker::CheckArgumentObjectKind(const parser::OmpClause &x) {
+ unsigned version{context_.langOptions().OpenMPVersion};
+ llvm::omp::Directive dirId{GetContext().directive};
+ llvm::omp::Clause clauseId{x.Id()};
+
+ // Filter out clauses that don't take OmpObjectList.
+ version = std::max(version, 45u);
+ auto argType{GetArgumentListItemKind(clauseId, version)};
+ if (!argType) {
+ return;
+ }
+ switch (*argType) {
+ case ListItemKind::Extended:
+ case ListItemKind::Locator:
+ case ListItemKind::Variable:
+ break;
+ default:
+ return;
+ }
+
+ // Corner cases:
+ if (clauseId == llvm::omp::Clause::OMPC_to) {
+ // 4.5 5+
+ // TO (declare target) extended extended
+ // TO (target update) variable locator
+ if (dirId == llvm::omp::Directive::OMPD_declare_target) {
+ argType = ListItemKind::Extended;
+ } else {
+ assert(dirId == llvm::omp::Directive::OMPD_target_update &&
+ "Unexpected directive");
+ argType = version < 50 ? ListItemKind::Variable : ListItemKind::Locator;
+ }
+ } else if (clauseId == llvm::omp::Clause::OMPC_uniform) {
+ // 4.5 5+
+ // UNIFORM variable parameter
+ // The uniform clause takes std::list<Name> at the moment and cannot
+ // be verified here.
+ return;
+ } else if (clauseId == llvm::omp::Clause::OMPC_depend) {
+ // 6.0- 6.1+
+ // DEPEND locator/doacross depend
+ if (version >= 61) {
+ return;
+ }
+ // The DEPEND clause with SINK/SOURCE will not have an object list.
+ if (auto *depend{parser::Unwrap<parser::OmpDependClause>(x)}) {
+ if (parser::Unwrap<parser::OmpDoacross>(*depend)) {
+ return;
+ }
+ }
+ }
+
+ // Named constants are OK to be used within 'shared' and 'firstprivate'
+ // clauses. The check for this happens a few lines below.
+ bool NamedConstantAllowed{false};
+ switch (clauseId) {
+ case llvm::omp::Clause::OMPC_shared:
+ case llvm::omp::Clause::OMPC_firstprivate:
+ NamedConstantAllowed = true;
+ break;
+ default:
+ break;
+ }
+
+ for (auto &object : DEREF(GetOmpObjectList(x)).v) {
+ AnalyzeObject(object);
+ // substring
+ const Symbol *symbol{GetObjectSymbol(object, /*ultimate=*/true)};
+ if (symbol == nullptr) {
+ // This may happen with a blank common block. Skip these cases.
+ continue;
+ }
+ auto source{*parser::omp::GetObjectSource(object)};
+ if (NamedConstantAllowed && IsNamedConstant(*symbol)) {
+ continue;
+ }
+ // Emit a more user-friendly diagnostic than "'kind' must be a variable
+ // list item" for x%kind, or for cplx%re.
+ if (IsTypeParamInquiry(*symbol)) {
+ context_.Say(source,
+ "Type parameter inquiry is not allowed as a list item on %s clause"_err_en_US,
+ parser::omp::GetUpperName(clauseId, version));
+ continue;
+ }
+ if (IsComplexPart(*symbol)) {
+ // We have been tolerating complex part designators.
+ continue;
+ }
+
+ const char *neededType{nullptr};
+
+ switch (*argType) {
+ case ListItemKind::Extended:
+ if (!IsExtendedListItem(object, &context_)) {
+ neededType = "an extended";
+ }
+ break;
+ case ListItemKind::Locator:
+ if (!IsLocatorListItem(object, &context_)) {
+ neededType = "a locator";
+ }
+ break;
+ case ListItemKind::Variable:
+ if (!IsVariableListItem(object, &context_)) {
+ neededType = "a variable";
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (neededType) {
+ context_.SayWithDecl(*symbol, source,
+ "'%s' must be %s list item"_err_en_US, symbol->name(), neededType);
}
}
}
@@ -2385,7 +2487,6 @@ void OmpStructureChecker::Leave(const parser::OmpDeclareTargetDirective &x) {
std::is_same_v<TypeC, parser::OmpClause::To>) {
auto &objList{*GetOmpObjectList(c)};
CheckSymbolNames(dirName.source, objList);
- CheckTypeParamInquiry(dirName.source, objList);
CheckVarIsNotPartOfAnotherVar(dirName.source, objList);
CheckThreadprivateOrDeclareTargetVar(objList);
}
@@ -3627,44 +3728,7 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &x) {
void OmpStructureChecker::Enter(const parser::OmpClause &x) {
SetContextClause(x);
-
- llvm::omp::Clause id{x.Id()};
- // The visitors for these clauses do their own checks.
- switch (id) {
- case llvm::omp::Clause::OMPC_copyprivate:
- case llvm::omp::Clause::OMPC_enter:
- case llvm::omp::Clause::OMPC_lastprivate:
- case llvm::omp::Clause::OMPC_reduction:
- case llvm::omp::Clause::OMPC_to:
- return;
- default:
- break;
- }
-
- // Named constants are OK to be used within 'shared' and 'firstprivate'
- // clauses. The check for this happens a few lines below.
- bool SharedOrFirstprivate = false;
- switch (id) {
- case llvm::omp::Clause::OMPC_shared:
- case llvm::omp::Clause::OMPC_firstprivate:
- SharedOrFirstprivate = true;
- break;
- default:
- break;
- }
-
- if (const parser::OmpObjectList *objList{GetOmpObjectList(x)}) {
- AnalyzeObjects(*objList);
- SymbolSourceMap symbols;
- GetSymbolsInObjectList(*objList, symbols);
- for (const auto &[symbol, source] : symbols) {
- if (!IsVariableListItem(*symbol) &&
- !(IsNamedConstant(*symbol) && SharedOrFirstprivate)) {
- context_.SayWithDecl(*symbol, source,
- "'%s' must be a variable"_err_en_US, symbol->name());
- }
- }
- }
+ CheckArgumentObjectKind(x);
}
// Restrictions specific to each clause are implemented apart from the
@@ -3884,17 +3948,6 @@ void OmpStructureChecker::CheckReductionObjects(
}
}
}
- // Type parameter inquiries are not allowed.
- for (const parser::OmpObject &object : objects.v) {
- if (auto *symbol{GetObjectSymbol(object)}) {
- if (IsTypeParamInquiry(*symbol)) {
- auto source{GetObjectSource(object)};
- context_.Say(source ? *source : GetContext().clauseSource,
- "Type parameter inquiry is not permitted in %s clause"_err_en_US,
- parser::omp::GetUpperName(clauseId, version));
- }
- }
- }
}
}
@@ -4176,15 +4229,14 @@ void OmpStructureChecker::CheckSharedBindingInOuterContext(
void OmpStructureChecker::Enter(const parser::OmpClause::Shared &x) {
CheckAllowedClause(llvm::omp::Clause::OMPC_shared);
- CheckTypeParamInquiry(GetContext().clauseSource, x.v);
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);
- CheckTypeParamInquiry(GetContext().clauseSource, x.v);
CheckVarIsNotPartOfAnotherVar(GetContext().clauseSource, x.v, "PRIVATE");
CheckIntentInPointer(symbols, llvm::omp::Clause::OMPC_private);
CheckCrayPointee(x.v, "PRIVATE");
@@ -4233,7 +4285,8 @@ void OmpStructureChecker::CheckVarIsNotPartOfAnotherVar(
}
if (report || parser::Unwrap<parser::ArrayElement>(object)) {
- if (llvm::omp::nonPartialVarSet.test(GetContext().directive)) {
+ if (clause.empty() &&
+ 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());
@@ -4248,7 +4301,6 @@ void OmpStructureChecker::CheckVarIsNotPartOfAnotherVar(
void OmpStructureChecker::Enter(const parser::OmpClause::Firstprivate &x) {
CheckAllowedClause(llvm::omp::Clause::OMPC_firstprivate);
- CheckTypeParamInquiry(GetContext().clauseSource, x.v);
CheckVarIsNotPartOfAnotherVar(GetContext().clauseSource, x.v, "FIRSTPRIVATE");
CheckCrayPointee(x.v, "FIRSTPRIVATE");
@@ -4453,7 +4505,6 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Detach &x) {
CheckAllowedClause(llvm::omp::Clause::OMPC_detach);
}
- CheckTypeParamInquiry(GetContext().clauseSource, x.v.v);
// OpenMP 5.2: 12.5.2 Detach clause restrictions
if (version >= 52) {
CheckVarIsNotPartOfAnotherVar(GetContext().clauseSource, x.v.v, "DETACH");
@@ -4909,7 +4960,6 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Copyprivate &x) {
CheckAllowedClause(llvm::omp::Clause::OMPC_copyprivate);
SymbolSourceMap symbols;
GetSymbolsInObjectList(x.v, symbols);
- CheckVariableListItem(symbols);
CheckIntentInPointer(symbols, llvm::omp::Clause::OMPC_copyprivate);
CheckCopyingPolymorphicAllocatable(
symbols, llvm::omp::Clause::OMPC_copyprivate);
@@ -4919,7 +4969,6 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Lastprivate &x) {
CheckAllowedClause(llvm::omp::Clause::OMPC_lastprivate);
const auto &objectList{*GetOmpObjectList(x)};
- CheckTypeParamInquiry(GetContext().clauseSource, objectList);
CheckVarIsNotPartOfAnotherVar(
GetContext().clauseSource, objectList, "LASTPRIVATE");
CheckCrayPointee(objectList, "LASTPRIVATE");
@@ -5161,18 +5210,8 @@ void OmpStructureChecker::Enter(const parser::OmpClause::HasDeviceAddr &x) {
void OmpStructureChecker::Enter(const parser::OmpClause::Enter &x) {
CheckAllowedClause(llvm::omp::Clause::OMPC_enter);
- if (!OmpVerifyModifiers(
- x.v, llvm::omp::OMPC_enter, GetContext().clauseSource, context_)) {
- return;
- }
- SymbolSourceMap symbols;
- GetSymbolsInObjectList(*GetOmpObjectList(x), symbols);
- for (const auto &[symbol, source] : symbols) {
- if (!IsExtendedListItem(*symbol)) {
- context_.SayWithDecl(*symbol, source,
- "'%s' must be a variable or a procedure"_err_en_US, symbol->name());
- }
- }
+ OmpVerifyModifiers(
+ x.v, llvm::omp::OMPC_enter, GetContext().clauseSource, context_);
}
void OmpStructureChecker::Enter(const parser::OmpClause::From &x) {
@@ -5190,10 +5229,6 @@ void OmpStructureChecker::Enter(const parser::OmpClause::From &x) {
}
const auto &objList{*GetOmpObjectList(x)};
- SymbolSourceMap symbols;
- GetSymbolsInObjectList(objList, symbols);
- CheckVariableListItem(symbols);
-
// Ref: [4.5:109:19]
// If a list item is an array section it must specify contiguous storage.
if (version <= 45) {
@@ -5230,10 +5265,6 @@ void OmpStructureChecker::Enter(const parser::OmpClause::To &x) {
}
const auto &objList{*GetOmpObjectList(x)};
- SymbolSourceMap symbols;
- GetSymbolsInObjectList(objList, symbols);
- CheckVariableListItem(symbols);
-
// Ref: [4.5:109:19]
// If a list item is an array section it must specify contiguous storage.
if (version <= 45) {
@@ -5467,6 +5498,9 @@ void OmpStructureChecker::CheckDefinableObjects(
SymbolSourceMap &symbols, const llvm::omp::Clause clause) {
unsigned version{context_.langOptions().OpenMPVersion};
for (auto &[symbol, source] : symbols) {
+ if (!IsVariableListItem(*symbol)) {
+ continue;
+ }
if (auto msg{WhyNotDefinable(source, context_.FindScope(source),
DefinabilityFlags{}, *symbol)}) {
context_
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 8a85f489eeb4c..f1f210e047a38 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -289,7 +289,7 @@ class OmpStructureChecker : public OmpStructureCheckerBase {
// check-omp-structure.cpp
bool IsAllowedClause(llvm::omp::Clause clauseId);
bool CheckAllowedClause(llvm::omp::Clause clause);
- void CheckVariableListItem(const SymbolSourceMap &symbols);
+ void CheckArgumentObjectKind(const parser::OmpClause &x);
void CheckDirectiveSpelling(
parser::CharBlock spelling, llvm::omp::Directive id);
void CheckDirectiveDeprecation(const parser::OpenMPConstruct &x);
diff --git a/flang/lib/Semantics/openmp-utils.cpp b/flang/lib/Semantics/openmp-utils.cpp
index 51dd08d0924b1..d2f26b70c60ae 100644
--- a/flang/lib/Semantics/openmp-utils.cpp
+++ b/flang/lib/Semantics/openmp-utils.cpp
@@ -154,7 +154,8 @@ bool IsCommonBlock(const Symbol &sym) {
}
bool IsVariableListItem(const Symbol &sym) {
- return evaluate::IsVariable(sym) || sym.attrs().test(Attr::POINTER);
+ return evaluate::IsVariable(sym) || IsCommonBlock(sym) ||
+ sym.attrs().test(Attr::POINTER);
}
bool IsExtendedListItem(const Symbol &sym) {
@@ -174,6 +175,14 @@ bool IsTypeParamInquiry(const Symbol &sym) {
sym.details());
}
+bool IsComplexPart(const Symbol &sym) {
+ if (auto *misc{sym.detailsIf<MiscDetails>()}) {
+ return misc->kind() == MiscDetails::Kind::ComplexPartRe ||
+ misc->kind() == MiscDetails::Kind::ComplexPartIm;
+ }
+ return false;
+}
+
bool IsStructureComponent(const Symbol &sym) {
return sym.owner().kind() == Scope::Kind::DerivedType;
}
@@ -217,6 +226,38 @@ bool IsWholeAssumedSizeArray(const parser::OmpObject &object) {
return false;
}
+bool IsExtendedListItem(
+ const parser::OmpObject &object, SemanticsContext *semaCtx) {
+ if (IsVariableListItem(object, semaCtx)) {
+ return true;
+ }
+ if (auto *sym{GetObjectSymbol(object, /*ultimate=*/true)}) {
+ return IsProcedure(*sym);
+ }
+ return false;
+}
+
+bool IsLocatorListItem(
+ const parser::OmpObject &object, SemanticsContext *semaCtx) {
+ if (IsVariableListItem(object, semaCtx)) {
+ return true;
+ }
+ if (auto *desg{parser::Unwrap<parser::Designator>(object)}) {
+ evaluate::ExpressionAnalyzer ea(*semaCtx);
+ auto restorer{ea.GetContextualMessages().DiscardMessages()};
+ return IsVarOrFunctionRef(ea.Analyze(*desg));
+ }
+ return false;
+}
+
+bool IsVariableListItem(
+ const parser::OmpObject &object, SemanticsContext *semaCtx) {
+ if (auto *sym{GetObjectSymbol(object, /*ultimate=*/true)}) {
+ return IsVariableListItem(*sym);
+ }
+ return false;
+}
+
const Symbol *GetHostSymbol(const Symbol &sym) {
if (auto *details{sym.detailsIf<HostAssocDetails>()}) {
return &details->symbol();
@@ -554,6 +595,188 @@ MaybeExpr MakeEvaluateExpr(const parser::OmpStylizedInstance &inp) {
instance.u);
}
+/// For clauses that take argument lists, return the type of the argument
+/// list item. For other clauses return std::nullopt.
+std::optional<ListItemKind> GetArgumentListItemKind(
+ llvm::omp::Clause clause, unsigned version) {
+ switch (clause) {
+ case llvm::omp::Clause::OMPC_absent:
+ if (version >= 51) {
+ return ListItemKind::DirectiveName;
+ }
+ break;
+ case llvm::omp::Clause::OMPC_adjust_args:
+ if (version >= 61) {
+ return ListItemKind::ProcedureArgument;
+ }
+ if (version >= 51) {
+ return ListItemKind::Parameter;
+ }
+ break;
+ case llvm::omp::Clause::OMPC_affinity:
+ if (version >= 50) {
+ return ListItemKind::Locator;
+ }
+ break;
+ case llvm::omp::Clause::OMPC_aligned:
+ return ListItemKind::Variable;
+ case llvm::omp::Clause::OMPC_allocate:
+ if (version >= 50) {
+ return ListItemKind::Variable;
+ }
+ break;
+ case llvm::omp::Clause::OMPC_append_args:
+ if (version >= 51) {
+ return ListItemKind::Operation;
+ }
+ break;
+ case llvm::omp::Clause::OMPC_apply:
+ if (version >= 60) {
+ return ListItemKind::DirectiveSpecification;
+ }
+ break;
+ case llvm::omp::Clause::OMPC_contains:
+ if (version >= 51) {
+ return ListItemKind::DirectiveName;
+ }
+ break;
+ case llvm::omp::Clause::OMPC_copyin:
+ return ListItemKind::Variable;
+ case llvm::omp::Clause::OMPC_copyprivate:
+ return ListItemKind::Variable;
+ case llvm::omp::Clause::OMPC_counts:
+ if (version >= 60) {
+ return ListItemKind::IntegerExpression;
+ }
+ break;
+ case llvm::omp::Clause::OMPC_depend:
+ if (version >= 61) {
+ return ListItemKind::Depend;
+ }
+ if (version >= 50) {
+ return ListItemKind::Locator;
+ }
+ return ListItemKind::Variable;
+ case llvm::omp::Clause::OMPC_enter:
+ if (version >= 52) {
+ return ListItemKind::Extended;
+ }
+ break;
+ case llvm::omp::Clause::OMPC_exclusive:
+ if (version >= 50) {
+ return ListItemKind::Variable;
+ }
+ break;
+ case llvm::omp::Clause::OMPC_firstprivate:
+ return ListItemKind::Variable;
+ case llvm::omp::Clause::OMPC_from:
+ if (version >= 50) {
+ return ListItemKind::Locator;
+ }
+ return ListItemKind::Variable;
+ case llvm::omp::Clause::OMPC_has_device_addr:
+ if (version >= 51) {
+ return ListItemKind::Variable;
+ }
+ break;
+ case llvm::omp::Clause::OMPC_in_reduction:
+ if (version >= 50) {
+ return ListItemKind::Variable;
+ }
+ break;
+ case llvm::omp::Clause::OMPC_inclusive:
+ if (version >= 50) {
+ return ListItemKind::Variable;
+ }
+ break;
+ case llvm::omp::Clause::OMPC_induction:
+ if (version >= 60) {
+ return ListItemKind::Variable;
+ }
+ break;
+ case llvm::omp::Clause::OMPC_interop:
+ if (version >= 60) {
+ return ListItemKind::Interop;
+ }
+ break;
+ case llvm::omp::Clause::OMPC_is_device_ptr:
+ return ListItemKind::Variable;
+ case llvm::omp::Clause::OMPC_lastprivate:
+ return ListItemKind::Variable;
+ case llvm::omp::Clause::OMPC_linear:
+ return ListItemKind::Variable;
+ case llvm::omp::Clause::OMPC_link:
+ return ListItemKind::Variable;
+ case llvm::omp::Clause::OMPC_local:
+ if (version >= 60) {
+ return ListItemKind::Variable;
+ }
+ break;
+ case llvm::omp::Clause::OMPC_map:
+ if (version >= 50) {
+ return ListItemKind::Locator;
+ }
+ return ListItemKind::Variable;
+ case llvm::omp::Clause::OMPC_nontemporal:
+ if (version >= 50) {
+ return ListItemKind::Variable;
+ }
+ break;
+ case llvm::omp::Clause::OMPC_num_threads:
+ if (version >= 60) {
+ return ListItemKind::IntegerExpression;
+ }
+ break;
+ case llvm::omp::Clause::OMPC_permutation:
+ if (version >= 60) {
+ return ListItemKind::IntegerExpression;
+ }
+ break;
+ case llvm::omp::Clause::OMPC_private:
+ return ListItemKind::Variable;
+ case llvm::omp::Clause::OMPC_reduction:
+ return ListItemKind::Variable;
+ case llvm::omp::Clause::OMPC_shared:
+ return ListItemKind::Variable;
+ // TODO 6.1
+ // case llvm::omp::Clause::OMPC_shift:
+ // if (version >= 61) {
+ // return ListItemKind::IntegerExpression;
+ // }
+ // break;
+ case llvm::omp::Clause::OMPC_sizes:
+ if (version >= 51) {
+ return ListItemKind::IntegerExpression;
+ }
+ break;
+ case llvm::omp::Clause::OMPC_task_reduction:
+ if (version >= 50) {
+ return ListItemKind::Variable;
+ }
+ break;
+ case llvm::omp::Clause::OMPC_to:
+ if (version >= 50) {
+ return ListItemKind::Locator;
+ }
+ return ListItemKind::Extended;
+ case llvm::omp::Clause::OMPC_uniform:
+ if (version >= 50) {
+ return ListItemKind::Parameter;
+ }
+ return ListItemKind::Variable;
+ case llvm::omp::Clause::OMPC_use_device_addr:
+ if (version >= 50) {
+ return ListItemKind::Variable;
+ }
+ break;
+ case llvm::omp::Clause::OMPC_use_device_ptr:
+ return ListItemKind::Variable;
+ default:
+ break;
+ }
+ return std::nullopt;
+}
+
bool IsLoopTransforming(llvm::omp::Directive dir) {
switch (dir) {
// TODO case llvm::omp::Directive::OMPD_flatten:
diff --git a/flang/test/Semantics/OpenMP/copyprivate04.f90 b/flang/test/Semantics/OpenMP/copyprivate04.f90
index 8d7800229bc5f..56e37c3a5df1c 100644
--- a/flang/test/Semantics/OpenMP/copyprivate04.f90
+++ b/flang/test/Semantics/OpenMP/copyprivate04.f90
@@ -70,7 +70,7 @@ program omp_copyprivate
! Named constants are shared.
!$omp single
!ERROR: COPYPRIVATE variable 'pi' is not PRIVATE or THREADPRIVATE in outer context
- !ERROR: 'pi' must be a variable
+ !ERROR: 'pi' must be a variable list item
!$omp end single copyprivate(pi)
!$omp parallel do
diff --git a/flang/test/Semantics/OpenMP/copyprivate05.f90 b/flang/test/Semantics/OpenMP/copyprivate05.f90
index 129f8f0b5144e..222628d3e65d9 100644
--- a/flang/test/Semantics/OpenMP/copyprivate05.f90
+++ b/flang/test/Semantics/OpenMP/copyprivate05.f90
@@ -6,7 +6,7 @@ subroutine f00
type t
end type
-!ERROR: 't' must be a variable
+!ERROR: 't' must be a variable list item
!$omp single copyprivate(t)
!$omp end single
end
diff --git a/flang/test/Semantics/OpenMP/declare-target01.f90 b/flang/test/Semantics/OpenMP/declare-target01.f90
index 9bbd66ad5ec43..ddd48c5a96820 100644
--- a/flang/test/Semantics/OpenMP/declare-target01.f90
+++ b/flang/test/Semantics/OpenMP/declare-target01.f90
@@ -75,18 +75,18 @@ module declare_target01
!ERROR: A variable that is part of another variable (as an array or structure element) cannot appear on the DECLARE TARGET directive
!$omp declare target enter (my_var%t_arr)
- !ERROR: A type parameter inquiry cannot appear on the DECLARE TARGET directive
+ !ERROR: Type parameter inquiry is not allowed as a list item on TO clause
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-usage]
!$omp declare target to (my_var%kind_param)
- !ERROR: A type parameter inquiry cannot appear on the DECLARE TARGET directive
+ !ERROR: Type parameter inquiry is not allowed as a list item on ENTER clause
!$omp declare target enter (my_var%kind_param)
- !ERROR: A type parameter inquiry cannot appear on the DECLARE TARGET directive
+ !ERROR: Type parameter inquiry is not allowed as a list item on TO clause
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-usage]
!$omp declare target to (my_var%len_param)
- !ERROR: A type parameter inquiry cannot appear on the DECLARE TARGET directive
+ !ERROR: Type parameter inquiry is not allowed as a list item on ENTER clause
!$omp declare target enter (my_var%len_param)
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-usage]
@@ -113,25 +113,25 @@ module declare_target01
!ERROR: A variable that is part of another variable (as an array or structure element) cannot appear on the DECLARE TARGET directive
!$omp declare target enter (arr(1:2))
- !ERROR: A type parameter inquiry cannot appear on the DECLARE TARGET directive
+ !ERROR: Type parameter inquiry is not allowed as a list item on TO clause
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-usage]
!$omp declare target to (x%KIND)
- !ERROR: A type parameter inquiry cannot appear on the DECLARE TARGET directive
+ !ERROR: Type parameter inquiry is not allowed as a list item on ENTER clause
!$omp declare target enter (x%KIND)
- !ERROR: A type parameter inquiry cannot appear on the DECLARE TARGET directive
+ !ERROR: Type parameter inquiry is not allowed as a list item on TO clause
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-usage]
!$omp declare target to (w%LEN)
- !ERROR: A type parameter inquiry cannot appear on the DECLARE TARGET directive
+ !ERROR: Type parameter inquiry is not allowed as a list item on ENTER clause
!$omp declare target enter (w%LEN)
- !ERROR: A type parameter inquiry cannot appear on the DECLARE TARGET directive
+ !ERROR: Type parameter inquiry is not allowed as a list item on TO clause
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-usage]
!$omp declare target to (y%KIND)
- !ERROR: A type parameter inquiry cannot appear on the DECLARE TARGET directive
+ !ERROR: Type parameter inquiry is not allowed as a list item on ENTER clause
!$omp declare target enter (y%KIND)
!$omp declare target link (my_var2)
@@ -144,10 +144,10 @@ module declare_target01
!ERROR: A variable that is part of another variable (as an array or structure element) cannot appear on the DECLARE TARGET directive
!$omp declare target link (my_var2%t_arr)
- !ERROR: A type parameter inquiry cannot appear on the DECLARE TARGET directive
+ !ERROR: Type parameter inquiry is not allowed as a list item on LINK clause
!$omp declare target link (my_var2%kind_param)
- !ERROR: A type parameter inquiry cannot appear on the DECLARE TARGET directive
+ !ERROR: Type parameter inquiry is not allowed as a list item on LINK clause
!$omp declare target link (my_var2%len_param)
!$omp declare target link (arr2)
@@ -158,12 +158,12 @@ module declare_target01
!ERROR: A variable that is part of another variable (as an array or structure element) cannot appear on the DECLARE TARGET directive
!$omp declare target link (arr2(1:2))
- !ERROR: A type parameter inquiry cannot appear on the DECLARE TARGET directive
+ !ERROR: Type parameter inquiry is not allowed as a list item on LINK clause
!$omp declare target link (x2%KIND)
- !ERROR: A type parameter inquiry cannot appear on the DECLARE TARGET directive
+ !ERROR: Type parameter inquiry is not allowed as a list item on LINK clause
!$omp declare target link (w2%LEN)
- !ERROR: A type parameter inquiry cannot appear on the DECLARE TARGET directive
+ !ERROR: Type parameter inquiry is not allowed as a list item on LINK clause
!$omp declare target link (y2%KIND)
end
diff --git a/flang/test/Semantics/OpenMP/from-clause-v45.f90 b/flang/test/Semantics/OpenMP/from-clause-v45.f90
index 201128fc3031c..654af4b7dd9b7 100644
--- a/flang/test/Semantics/OpenMP/from-clause-v45.f90
+++ b/flang/test/Semantics/OpenMP/from-clause-v45.f90
@@ -28,6 +28,6 @@ subroutine f03(x)
end
subroutine f04
-!ERROR: 'f04' must be a variable
+!ERROR: 'f04' must be a variable list item
!$omp target update from(f04)
end
diff --git a/flang/test/Semantics/OpenMP/from-clause-v51.f90 b/flang/test/Semantics/OpenMP/from-clause-v51.f90
index 70c00823d073e..8771f519fec03 100644
--- a/flang/test/Semantics/OpenMP/from-clause-v51.f90
+++ b/flang/test/Semantics/OpenMP/from-clause-v51.f90
@@ -13,6 +13,6 @@ subroutine f03(x)
end
subroutine f04
-!ERROR: 'f04' must be a variable
+!ERROR: 'f04' must be a locator list item
!$omp target update from(f04)
end
diff --git a/flang/test/Semantics/OpenMP/in-reduction.f90 b/flang/test/Semantics/OpenMP/in-reduction.f90
index c3fe7fee73c24..0472774704334 100644
--- a/flang/test/Semantics/OpenMP/in-reduction.f90
+++ b/flang/test/Semantics/OpenMP/in-reduction.f90
@@ -66,7 +66,7 @@ subroutine f07
subroutine f08
integer :: x
-!ERROR: Type parameter inquiry is not permitted in IN_REDUCTION clause
+!ERROR: Type parameter inquiry is not allowed as a list item on IN_REDUCTION clause
!$omp target in_reduction(+: x%kind)
!$omp end target
end
diff --git a/flang/test/Semantics/OpenMP/lastprivate01.f90 b/flang/test/Semantics/OpenMP/lastprivate01.f90
index 4fae4829d8862..4248a34e702c7 100644
--- a/flang/test/Semantics/OpenMP/lastprivate01.f90
+++ b/flang/test/Semantics/OpenMP/lastprivate01.f90
@@ -15,8 +15,7 @@ program omp_lastprivate
a = 10
b = 20
- !ERROR: Variable 'k' on the LASTPRIVATE clause is not definable
- !BECAUSE: 'k' is not a variable
+ !ERROR: 'k' must be a variable list item
!$omp parallel do lastprivate(k)
do i = 1, 10
c(i) = a(i) + b(i) + k
diff --git a/flang/test/Semantics/OpenMP/name-conflict.f90 b/flang/test/Semantics/OpenMP/name-conflict.f90
index 5babc3c6d3886..267e9774e3e4b 100644
--- a/flang/test/Semantics/OpenMP/name-conflict.f90
+++ b/flang/test/Semantics/OpenMP/name-conflict.f90
@@ -5,7 +5,7 @@ module m
subroutine foo1()
integer :: baz1
-!ERROR: 'baz1' must be a variable
+!ERROR: 'baz1' must be a variable list item
!$omp parallel do shared(baz1)
baz1: do i = 1, 100
enddo baz1
@@ -14,7 +14,7 @@ subroutine foo1()
subroutine foo2()
!implicit baz2
-!ERROR: 'baz2' must be a variable
+!ERROR: 'baz2' must be a variable list item
!$omp parallel do shared(baz2)
baz2: do i = 1, 100
enddo baz2
diff --git a/flang/test/Semantics/OpenMP/named-constants.f90 b/flang/test/Semantics/OpenMP/named-constants.f90
index ac0850066cebe..759560e0a495c 100644
--- a/flang/test/Semantics/OpenMP/named-constants.f90
+++ b/flang/test/Semantics/OpenMP/named-constants.f90
@@ -33,10 +33,10 @@ subroutine prvt()
real, parameter :: m = 7.0
logical, parameter :: l = .false.
integer, dimension(3), parameter :: a = [1, 2, 3]
- !ERROR: 'n' must be a variable
- !ERROR: 'm' must be a variable
- !ERROR: 'l' must be a variable
- !ERROR: 'a' must be a variable
+ !ERROR: 'n' must be a variable list item
+ !ERROR: 'm' must be a variable list item
+ !ERROR: 'l' must be a variable list item
+ !ERROR: 'a' must be a variable list item
!$omp parallel private(n, m, l, a)
print *, n, m, l, a
!$omp end parallel
diff --git a/flang/test/Semantics/OpenMP/reduction04.f90 b/flang/test/Semantics/OpenMP/reduction04.f90
index e86b67b6efa96..f1c8a0de6cb19 100644
--- a/flang/test/Semantics/OpenMP/reduction04.f90
+++ b/flang/test/Semantics/OpenMP/reduction04.f90
@@ -6,8 +6,7 @@ program omp_Reduction
integer, parameter :: k = 10
common /c/ a, b
- !ERROR: Variable 'k' on the REDUCTION clause is not definable
- !BECAUSE: 'k' is not a variable
+ !ERROR: 'k' must be a variable list item
!$omp parallel do reduction(+:k)
do i = 1, 10
l = k + 1
diff --git a/flang/test/Semantics/OpenMP/reduction16.f90 b/flang/test/Semantics/OpenMP/reduction16.f90
index 6bb218e306128..0c92a5b9d2d6d 100644
--- a/flang/test/Semantics/OpenMP/reduction16.f90
+++ b/flang/test/Semantics/OpenMP/reduction16.f90
@@ -5,7 +5,7 @@
subroutine f00
integer :: x
-!ERROR: Type parameter inquiry is not permitted in REDUCTION clause
+!ERROR: Type parameter inquiry is not allowed as a list item on REDUCTION clause
!$omp do reduction (+ : x%kind)
do i = 1, 10
end do
diff --git a/flang/test/Semantics/OpenMP/task-reduction.f90 b/flang/test/Semantics/OpenMP/task-reduction.f90
index baa363bdd00ad..7e43332d53fe1 100644
--- a/flang/test/Semantics/OpenMP/task-reduction.f90
+++ b/flang/test/Semantics/OpenMP/task-reduction.f90
@@ -66,7 +66,7 @@ subroutine f07
subroutine f08
integer :: x
-!ERROR: Type parameter inquiry is not permitted in TASK_REDUCTION clause
+!ERROR: Type parameter inquiry is not allowed as a list item on TASK_REDUCTION clause
!$omp taskgroup task_reduction(+: x%kind)
!$omp end taskgroup
end
diff --git a/flang/test/Semantics/OpenMP/to-clause-v45.f90 b/flang/test/Semantics/OpenMP/to-clause-v45.f90
index 9797c06cdeddf..7e56817e1ff7c 100644
--- a/flang/test/Semantics/OpenMP/to-clause-v45.f90
+++ b/flang/test/Semantics/OpenMP/to-clause-v45.f90
@@ -28,6 +28,6 @@ subroutine f03(x)
end
subroutine f04
-!ERROR: 'f04' must be a variable
+!ERROR: 'f04' must be a variable list item
!$omp target update to(f04)
end
diff --git a/flang/test/Semantics/OpenMP/to-clause-v51.f90 b/flang/test/Semantics/OpenMP/to-clause-v51.f90
index 8abbca3bb07cd..0db292a22238b 100644
--- a/flang/test/Semantics/OpenMP/to-clause-v51.f90
+++ b/flang/test/Semantics/OpenMP/to-clause-v51.f90
@@ -13,6 +13,6 @@ subroutine f03(x)
end
subroutine f04
-!ERROR: 'f04' must be a variable
+!ERROR: 'f04' must be a locator list item
!$omp target update to(f04)
end
>From 4c502a55db3be6537403737e99990f1f86f2851e Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Sun, 17 May 2026 07:18:36 -0500
Subject: [PATCH 4/5] [flang][OpenMP] Move check for substring to semantic
checks
Move it to CheckVarIsNotPartOfAnotherVar, which is also refactored a bit.
---
flang/include/flang/Semantics/openmp-utils.h | 3 ++
flang/lib/Semantics/check-omp-structure.cpp | 32 +++++++++++--------
flang/lib/Semantics/openmp-utils.cpp | 20 ++++++++++++
flang/lib/Semantics/resolve-directives.cpp | 8 -----
flang/test/Semantics/OpenMP/allocate03.f90 | 4 +--
flang/test/Semantics/OpenMP/allocators02.f90 | 2 +-
.../Semantics/OpenMP/declare-target01.f90 | 32 +++++++++----------
flang/test/Semantics/OpenMP/detach01.f90 | 4 +--
.../test/Semantics/OpenMP/firstprivate02.f90 | 4 +--
flang/test/Semantics/OpenMP/lastprivate03.f90 | 4 +--
.../OpenMP/linear-clause-array-section.f90 | 6 ++--
.../Semantics/OpenMP/parallel-private01.f90 | 2 +-
.../Semantics/OpenMP/parallel-private02.f90 | 2 +-
.../Semantics/OpenMP/parallel-private03.f90 | 2 +-
.../Semantics/OpenMP/parallel-private04.f90 | 2 +-
.../Semantics/OpenMP/parallel-sections01.f90 | 8 ++---
.../Semantics/OpenMP/parallel-shared01.f90 | 2 +-
.../Semantics/OpenMP/parallel-shared02.f90 | 2 +-
.../Semantics/OpenMP/parallel-shared03.f90 | 2 +-
.../Semantics/OpenMP/parallel-shared04.f90 | 2 +-
flang/test/Semantics/OpenMP/resolve01.f90 | 2 +-
.../test/Semantics/OpenMP/threadprivate01.f90 | 8 ++---
22 files changed, 86 insertions(+), 67 deletions(-)
diff --git a/flang/include/flang/Semantics/openmp-utils.h b/flang/include/flang/Semantics/openmp-utils.h
index 0b6bd40ad84c2..de6c4294e957d 100644
--- a/flang/include/flang/Semantics/openmp-utils.h
+++ b/flang/include/flang/Semantics/openmp-utils.h
@@ -109,6 +109,9 @@ bool IsLocatorListItem(
bool IsVariableListItem(
const parser::OmpObject &object, SemanticsContext *semaCtx);
+bool IsSubstring(const parser::OmpObject &object, SemanticsContext *semaCtx);
+bool IsArrayElement(const parser::OmpObject &object, SemanticsContext *semaCtx);
+
const Symbol *GetHostSymbol(const Symbol &sym);
bool IsMapEnteringType(parser::OmpMapType::Value type);
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 94187aff125ee..dfebf398801e7 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -4276,24 +4276,28 @@ void OmpStructureChecker::CheckVarIsNotPartOfAnotherVar(
void OmpStructureChecker::CheckVarIsNotPartOfAnotherVar(
const parser::CharBlock &source, const parser::OmpObject &object,
llvm::StringRef clause) {
- bool report{false};
- if (auto *symbol{GetObjectSymbol(object)}) {
+ if (const Symbol *symbol{GetObjectSymbol(object)}) {
if (IsTypeParamInquiry(*symbol)) {
return;
}
- report = IsStructureComponent(*symbol);
- }
+ llvm::StringRef kind{};
+ if (IsStructureComponent(*symbol)) {
+ kind = "A structure component";
+ } else if (IsSubstring(object, &context_)) {
+ kind = "A substrincg";
+ } else if (IsArrayElement(object, &context_)) {
+ kind = "An array element";
+ }
- if (report || parser::Unwrap<parser::ArrayElement>(object)) {
- if (clause.empty() &&
- 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.str());
+ if (!kind.empty()) {
+ if (clause.empty() &&
+ llvm::omp::nonPartialVarSet.test(GetContext().directive)) {
+ context_.Say(source, "%s cannot appear on the %s directive"_err_en_US,
+ kind.str(), ContextDirectiveAsFortran());
+ } else {
+ context_.Say(source, "%s cannot appear in a %s clause"_err_en_US,
+ kind.str(), clause.str());
+ }
}
}
}
diff --git a/flang/lib/Semantics/openmp-utils.cpp b/flang/lib/Semantics/openmp-utils.cpp
index d2f26b70c60ae..f1a50d30fd316 100644
--- a/flang/lib/Semantics/openmp-utils.cpp
+++ b/flang/lib/Semantics/openmp-utils.cpp
@@ -258,6 +258,26 @@ bool IsVariableListItem(
return false;
}
+bool IsSubstring(const parser::OmpObject &object, SemanticsContext *semaCtx) {
+ if (auto *desg{parser::Unwrap<parser::Designator>(object)}) {
+ evaluate::ExpressionAnalyzer ea(*semaCtx);
+ auto restorer{ea.GetContextualMessages().DiscardMessages()};
+ if (MaybeExpr expr{ea.Analyze(*desg)}) {
+ return ExtractSubstring(*expr).has_value();
+ }
+ }
+ return false;
+}
+
+bool IsArrayElement(
+ const parser::OmpObject &object, SemanticsContext *semaCtx) {
+ if (auto *sym{GetObjectSymbol(object, /*ultimate=*/true)}) {
+ return !IsTypeParamInquiry(*sym) &&
+ parser::Unwrap<parser::ArrayElement>(object);
+ }
+ return false;
+}
+
const Symbol *GetHostSymbol(const Symbol &sym) {
if (auto *details{sym.detailsIf<HostAssocDetails>()}) {
return &details->symbol();
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index 2fa59adf7f3af..8bfb6687ea58f 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -2856,14 +2856,6 @@ void OmpAttributeVisitor::ResolveOmpDesignator(
const auto *name{parser::GetDesignatorNameIfDataRef(designator)};
if (!name) {
- // Array sections to be changed to substrings as needed
- if (AnalyzeExpr(context_, designator)) {
- if (std::holds_alternative<parser::Substring>(designator.u)) {
- context_.Say(designator.source,
- "Substrings are not allowed on OpenMP directives or clauses"_err_en_US);
- }
- }
- // other checks, more TBD
return;
}
diff --git a/flang/test/Semantics/OpenMP/allocate03.f90 b/flang/test/Semantics/OpenMP/allocate03.f90
index 3609f38eb6ee7..f2d48b5e7cbbe 100644
--- a/flang/test/Semantics/OpenMP/allocate03.f90
+++ b/flang/test/Semantics/OpenMP/allocate03.f90
@@ -15,11 +15,11 @@ subroutine allocate()
real, dimension (:,:), allocatable :: darray
integer :: a, b
- !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear on the ALLOCATE directive
+ !ERROR: A structure component cannot appear on the ALLOCATE directive
!$omp allocate(my_var%array)
continue
- !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear on the ALLOCATE directive
+ !ERROR: A structure component cannot appear on the ALLOCATE directive
!$omp allocate(darray, my_var%array) allocator(omp_default_mem_alloc)
allocate ( darray(a, b) )
diff --git a/flang/test/Semantics/OpenMP/allocators02.f90 b/flang/test/Semantics/OpenMP/allocators02.f90
index 8055d21c68095..ce6315556f493 100644
--- a/flang/test/Semantics/OpenMP/allocators02.f90
+++ b/flang/test/Semantics/OpenMP/allocators02.f90
@@ -15,7 +15,7 @@ subroutine allocate()
type(my_type) :: my_var
- !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear on the ALLOCATORS directive
+ !ERROR: A structure component cannot appear on the ALLOCATORS directive
!$omp allocators allocate(my_var%array)
allocate(my_var%array(10))
diff --git a/flang/test/Semantics/OpenMP/declare-target01.f90 b/flang/test/Semantics/OpenMP/declare-target01.f90
index ddd48c5a96820..e1c7cfaf092bb 100644
--- a/flang/test/Semantics/OpenMP/declare-target01.f90
+++ b/flang/test/Semantics/OpenMP/declare-target01.f90
@@ -22,10 +22,10 @@ module declare_target01
!$omp declare target (my_var)
- !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear on the DECLARE TARGET directive
+ !ERROR: A structure component cannot appear on the DECLARE TARGET directive
!$omp declare target (my_var%t_i)
- !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear on the DECLARE TARGET directive
+ !ERROR: A structure component cannot appear on the DECLARE TARGET directive
!$omp declare target (my_var%t_arr)
!ERROR: A type parameter inquiry cannot appear on the DECLARE TARGET directive
@@ -36,10 +36,10 @@ module declare_target01
!$omp declare target (arr)
- !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear on the DECLARE TARGET directive
+ !ERROR: An array element cannot appear on the DECLARE TARGET directive
!$omp declare target (arr(1))
- !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear on the DECLARE TARGET directive
+ !ERROR: An array element cannot appear on the DECLARE TARGET directive
!$omp declare target (arr(1:2))
!ERROR: A type parameter inquiry cannot appear on the DECLARE TARGET directive
@@ -61,18 +61,18 @@ module declare_target01
!$omp declare target enter (my_var) device_type(host)
- !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear on the DECLARE TARGET directive
+ !ERROR: A structure component cannot appear on the DECLARE TARGET directive
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-usage]
!$omp declare target to (my_var%t_i)
- !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear on the DECLARE TARGET directive
+ !ERROR: A structure component cannot appear on the DECLARE TARGET directive
!$omp declare target enter (my_var%t_i)
- !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear on the DECLARE TARGET directive
+ !ERROR: A structure component cannot appear on the DECLARE TARGET directive
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-usage]
!$omp declare target to (my_var%t_arr)
- !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear on the DECLARE TARGET directive
+ !ERROR: A structure component cannot appear on the DECLARE TARGET directive
!$omp declare target enter (my_var%t_arr)
!ERROR: Type parameter inquiry is not allowed as a list item on TO clause
@@ -99,18 +99,18 @@ module declare_target01
!$omp declare target enter (arr) device_type(nohost)
- !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear on the DECLARE TARGET directive
+ !ERROR: An array element cannot appear on the DECLARE TARGET directive
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-usage]
!$omp declare target to (arr(1))
- !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear on the DECLARE TARGET directive
+ !ERROR: An array element cannot appear on the DECLARE TARGET directive
!$omp declare target enter (arr(1))
- !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear on the DECLARE TARGET directive
+ !ERROR: An array element cannot appear on the DECLARE TARGET directive
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-usage]
!$omp declare target to (arr(1:2))
- !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear on the DECLARE TARGET directive
+ !ERROR: An array element cannot appear on the DECLARE TARGET directive
!$omp declare target enter (arr(1:2))
!ERROR: Type parameter inquiry is not allowed as a list item on TO clause
@@ -138,10 +138,10 @@ module declare_target01
!$omp declare target link (my_var2) device_type(any)
- !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear on the DECLARE TARGET directive
+ !ERROR: A structure component cannot appear on the DECLARE TARGET directive
!$omp declare target link (my_var2%t_i)
- !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear on the DECLARE TARGET directive
+ !ERROR: A structure component cannot appear on the DECLARE TARGET directive
!$omp declare target link (my_var2%t_arr)
!ERROR: Type parameter inquiry is not allowed as a list item on LINK clause
@@ -152,10 +152,10 @@ module declare_target01
!$omp declare target link (arr2)
- !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear on the DECLARE TARGET directive
+ !ERROR: An array element cannot appear on the DECLARE TARGET directive
!$omp declare target link (arr2(1))
- !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear on the DECLARE TARGET directive
+ !ERROR: An array element cannot appear on the DECLARE TARGET directive
!$omp declare target link (arr2(1:2))
!ERROR: Type parameter inquiry is not allowed as a list item on LINK clause
diff --git a/flang/test/Semantics/OpenMP/detach01.f90 b/flang/test/Semantics/OpenMP/detach01.f90
index 7729c85ea1128..f70f139b2de7d 100644
--- a/flang/test/Semantics/OpenMP/detach01.f90
+++ b/flang/test/Semantics/OpenMP/detach01.f90
@@ -46,12 +46,12 @@ program detach01
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
+ !ERROR: An array 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
+ !ERROR: A structure component cannot appear in a DETACH clause
!$omp task detach(t_01%event)
x = x + 1
!$omp end task
diff --git a/flang/test/Semantics/OpenMP/firstprivate02.f90 b/flang/test/Semantics/OpenMP/firstprivate02.f90
index eb2597cb1cc40..61033b89f5513 100644
--- a/flang/test/Semantics/OpenMP/firstprivate02.f90
+++ b/flang/test/Semantics/OpenMP/firstprivate02.f90
@@ -8,12 +8,12 @@ subroutine omp_firstprivate(init)
end type my_type
type(my_type) :: my_var
- !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a FIRSTPRIVATE clause
+ !ERROR: An array element cannot appear in a FIRSTPRIVATE clause
!$omp parallel firstprivate(a(2))
a(2) = init
!$omp end parallel
- !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a FIRSTPRIVATE clause
+ !ERROR: A structure component cannot appear in a FIRSTPRIVATE clause
!$omp parallel firstprivate(my_var%val)
my_var%val = init
!$omp end parallel
diff --git a/flang/test/Semantics/OpenMP/lastprivate03.f90 b/flang/test/Semantics/OpenMP/lastprivate03.f90
index d7fe0c162f27c..348bcb747b0dd 100644
--- a/flang/test/Semantics/OpenMP/lastprivate03.f90
+++ b/flang/test/Semantics/OpenMP/lastprivate03.f90
@@ -8,14 +8,14 @@ subroutine omp_lastprivate(init)
end type my_type
type(my_type) :: my_var
- !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a LASTPRIVATE clause
+ !ERROR: An array element cannot appear in a LASTPRIVATE clause
!$omp do lastprivate(a(2))
do i=1, 10
a(2) = init
end do
!$omp end do
- !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a LASTPRIVATE clause
+ !ERROR: A structure component cannot appear in a LASTPRIVATE clause
!$omp do lastprivate(my_var%val)
do i=1, 10
my_var%val = init
diff --git a/flang/test/Semantics/OpenMP/linear-clause-array-section.f90 b/flang/test/Semantics/OpenMP/linear-clause-array-section.f90
index cdcf9df723334..0749ea44db659 100644
--- a/flang/test/Semantics/OpenMP/linear-clause-array-section.f90
+++ b/flang/test/Semantics/OpenMP/linear-clause-array-section.f90
@@ -8,7 +8,7 @@ subroutine test_array_section_in_linear()
integer, dimension(0:99, -99:10, 200) :: a, b, c
!$omp parallel
- !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a LINEAR clause
+ !ERROR: An array element cannot appear in a LINEAR clause
!$omp do linear(a(:,1,1))
do i = 0, 99
c(i, 1, 1) = a(i, 1, 1) + b(i, 1, 1)
@@ -23,7 +23,7 @@ subroutine test_array_element_in_linear()
integer :: arr(10)
!$omp parallel
- !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a LINEAR clause
+ !ERROR: An array element cannot appear in a LINEAR clause
!$omp do linear(arr(1))
do i = 1, 10
arr(i) = i
@@ -41,7 +41,7 @@ subroutine test_structure_component_in_linear()
type(my_type) :: obj
!$omp parallel
- !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a LINEAR clause
+ !ERROR: A structure component cannot appear in a LINEAR clause
!$omp do linear(obj%field)
do i = 1, 10
end do
diff --git a/flang/test/Semantics/OpenMP/parallel-private01.f90 b/flang/test/Semantics/OpenMP/parallel-private01.f90
index a3d332c95ed25..76bf581b82abf 100644
--- a/flang/test/Semantics/OpenMP/parallel-private01.f90
+++ b/flang/test/Semantics/OpenMP/parallel-private01.f90
@@ -10,7 +10,7 @@ program omp_parallel_private
type(my_type) :: my_var
- !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a PRIVATE clause
+ !ERROR: A structure component cannot appear in a PRIVATE clause
!$omp parallel private(my_var%array)
do i = 1, 10
c(i) = a(i) + b(i) + k
diff --git a/flang/test/Semantics/OpenMP/parallel-private02.f90 b/flang/test/Semantics/OpenMP/parallel-private02.f90
index 8cb72159d6ab5..655487dc1045d 100644
--- a/flang/test/Semantics/OpenMP/parallel-private02.f90
+++ b/flang/test/Semantics/OpenMP/parallel-private02.f90
@@ -10,7 +10,7 @@ program omp_parallel_private
array(i) = i
end do
- !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a PRIVATE clause
+ !ERROR: An array element cannot appear in a PRIVATE clause
!$omp parallel private(array(i))
do i = 1, 10
c(i) = a(i) + b(i) + k
diff --git a/flang/test/Semantics/OpenMP/parallel-private03.f90 b/flang/test/Semantics/OpenMP/parallel-private03.f90
index 24a096302e53d..2442281a0e211 100644
--- a/flang/test/Semantics/OpenMP/parallel-private03.f90
+++ b/flang/test/Semantics/OpenMP/parallel-private03.f90
@@ -17,7 +17,7 @@ program omp_parallel_private
arr(i) = 0.0
end do
- !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a PRIVATE clause
+ !ERROR: An array element cannot appear in a PRIVATE clause
!$omp parallel private(arr(i),intx)
do i = 1, 10
c(i) = a(i) + b(i) + k
diff --git a/flang/test/Semantics/OpenMP/parallel-private04.f90 b/flang/test/Semantics/OpenMP/parallel-private04.f90
index 67a669c9882a5..50e1d267e1ca9 100644
--- a/flang/test/Semantics/OpenMP/parallel-private04.f90
+++ b/flang/test/Semantics/OpenMP/parallel-private04.f90
@@ -17,7 +17,7 @@ program omp_parallel_private
arr(i) = 0.0
end do
- !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a PRIVATE clause
+ !ERROR: A structure component cannot appear in a PRIVATE clause
!$omp parallel private(arr,intx,my_var%array(1))
do i = 1, 10
c(i) = a(i) + b(i) + k
diff --git a/flang/test/Semantics/OpenMP/parallel-sections01.f90 b/flang/test/Semantics/OpenMP/parallel-sections01.f90
index 19448258af766..0e4facac9831a 100644
--- a/flang/test/Semantics/OpenMP/parallel-sections01.f90
+++ b/flang/test/Semantics/OpenMP/parallel-sections01.f90
@@ -17,10 +17,10 @@ program OmpConstructSections01
do i = 1, 10
array(i) = i
end do
-!ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a SHARED clause
+!ERROR: An array element cannot appear in a SHARED clause
!$omp parallel sections shared(array(i))
!$omp end parallel sections
-!ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a SHARED clause
+!ERROR: A structure component cannot appear in a SHARED clause
!$omp parallel sections shared(my_var%array)
!$omp end parallel sections
@@ -30,7 +30,7 @@ program OmpConstructSections01
if (NT) 20, 30, 40
!ERROR: invalid branch into an OpenMP structured block
goto 20
-!ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a PRIVATE clause
+!ERROR: A structure component cannot appear in a PRIVATE clause
!$omp parallel sections private(my_var%array)
!$omp section
print *, "This is a single statement structured block"
@@ -55,7 +55,7 @@ program OmpConstructSections01
30 print *, "Error in opening file"
!$omp end parallel sections
10 print *, 'Jump from section'
-!ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a PRIVATE clause
+!ERROR: An array element cannot appear in a PRIVATE clause
!$omp parallel sections private(array(i))
!$omp section
40 print *, 'Error in opening file'
diff --git a/flang/test/Semantics/OpenMP/parallel-shared01.f90 b/flang/test/Semantics/OpenMP/parallel-shared01.f90
index 7abfe1f7b1637..253d0723e3e91 100644
--- a/flang/test/Semantics/OpenMP/parallel-shared01.f90
+++ b/flang/test/Semantics/OpenMP/parallel-shared01.f90
@@ -10,7 +10,7 @@ program omp_parallel_shared
type(my_type) :: my_var
- !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a SHARED clause
+ !ERROR: A structure component cannot appear in a SHARED clause
!$omp parallel shared(my_var%array)
do i = 1, 10
c(i) = a(i) + b(i) + k
diff --git a/flang/test/Semantics/OpenMP/parallel-shared02.f90 b/flang/test/Semantics/OpenMP/parallel-shared02.f90
index f59f5236dfd93..f82cd6e643ad2 100644
--- a/flang/test/Semantics/OpenMP/parallel-shared02.f90
+++ b/flang/test/Semantics/OpenMP/parallel-shared02.f90
@@ -10,7 +10,7 @@ program omp_parallel_shared
array(i) = i
end do
- !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a SHARED clause
+ !ERROR: An array element cannot appear in a SHARED clause
!$omp parallel shared(array(i))
do i = 1, 10
c(i) = a(i) + b(i) + k
diff --git a/flang/test/Semantics/OpenMP/parallel-shared03.f90 b/flang/test/Semantics/OpenMP/parallel-shared03.f90
index 3d9111c7aaf10..f334a6caabda4 100644
--- a/flang/test/Semantics/OpenMP/parallel-shared03.f90
+++ b/flang/test/Semantics/OpenMP/parallel-shared03.f90
@@ -17,7 +17,7 @@ program omp_parallel_shared
arr(i) = 0.0
end do
- !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a SHARED clause
+ !ERROR: An array element cannot appear in a SHARED clause
!$omp parallel shared(arr(i),intx)
do i = 1, 10
c(i) = a(i) + b(i) + k
diff --git a/flang/test/Semantics/OpenMP/parallel-shared04.f90 b/flang/test/Semantics/OpenMP/parallel-shared04.f90
index 06b7fcfa01d7a..552b4df928c63 100644
--- a/flang/test/Semantics/OpenMP/parallel-shared04.f90
+++ b/flang/test/Semantics/OpenMP/parallel-shared04.f90
@@ -17,7 +17,7 @@ program omp_parallel_shared
arr(i) = 0.0
end do
- !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear in a SHARED clause
+ !ERROR: A structure component cannot appear in a SHARED clause
!$omp parallel shared(arr,intx,my_var%array(1))
do i = 1, 10
c(i) = a(i) + b(i) + k
diff --git a/flang/test/Semantics/OpenMP/resolve01.f90 b/flang/test/Semantics/OpenMP/resolve01.f90
index 79b67885b8b9c..95e473d30cd91 100644
--- a/flang/test/Semantics/OpenMP/resolve01.f90
+++ b/flang/test/Semantics/OpenMP/resolve01.f90
@@ -8,7 +8,7 @@
b = "HIFROMPGI"
c = b(2:7)
- !ERROR: Substrings are not allowed on OpenMP directives or clauses
+ !ERROR: A substrincg cannot appear in a PRIVATE clause
!$omp parallel private(c(1:3))
a = c(1:1)
!$omp end parallel
diff --git a/flang/test/Semantics/OpenMP/threadprivate01.f90 b/flang/test/Semantics/OpenMP/threadprivate01.f90
index c2cf9ba99ab04..ebccaaa99d62a 100644
--- a/flang/test/Semantics/OpenMP/threadprivate01.f90
+++ b/flang/test/Semantics/OpenMP/threadprivate01.f90
@@ -22,10 +22,10 @@ module thread_private01
!$omp threadprivate(my_var)
- !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear on the THREADPRIVATE directive
+ !ERROR: A structure component cannot appear on the THREADPRIVATE directive
!$omp threadprivate(my_var%t_i)
- !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear on the THREADPRIVATE directive
+ !ERROR: A structure component cannot appear on the THREADPRIVATE directive
!$omp threadprivate(my_var%t_arr)
!ERROR: A type parameter inquiry cannot appear on the THREADPRIVATE directive
@@ -36,10 +36,10 @@ module thread_private01
!$omp threadprivate(arr)
- !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear on the THREADPRIVATE directive
+ !ERROR: An array element cannot appear on the THREADPRIVATE directive
!$omp threadprivate(arr(1))
- !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear on the THREADPRIVATE directive
+ !ERROR: An array element cannot appear on the THREADPRIVATE directive
!$omp threadprivate(arr(1:2))
!ERROR: A type parameter inquiry cannot appear on the THREADPRIVATE directive
>From 16198c7c076589e54179b5a83067a1289e8776a6 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Thu, 4 Jun 2026 11:47:25 -0500
Subject: [PATCH 5/5] Apply suggestions from code review
Co-authored-by: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
---
flang/lib/Semantics/check-omp-structure.cpp | 2 +-
flang/test/Semantics/OpenMP/resolve01.f90 | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index dfebf398801e7..03f83184aa6ce 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -4284,7 +4284,7 @@ void OmpStructureChecker::CheckVarIsNotPartOfAnotherVar(
if (IsStructureComponent(*symbol)) {
kind = "A structure component";
} else if (IsSubstring(object, &context_)) {
- kind = "A substrincg";
+ kind = "A substring";
} else if (IsArrayElement(object, &context_)) {
kind = "An array element";
}
diff --git a/flang/test/Semantics/OpenMP/resolve01.f90 b/flang/test/Semantics/OpenMP/resolve01.f90
index 95e473d30cd91..fcccb8f6bd577 100644
--- a/flang/test/Semantics/OpenMP/resolve01.f90
+++ b/flang/test/Semantics/OpenMP/resolve01.f90
@@ -8,7 +8,7 @@
b = "HIFROMPGI"
c = b(2:7)
- !ERROR: A substrincg cannot appear in a PRIVATE clause
+ !ERROR: A substring cannot appear in a PRIVATE clause
!$omp parallel private(c(1:3))
a = c(1:1)
!$omp end parallel
More information about the flang-commits
mailing list