-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[flang][OpenMP] Use OmpDirectiveSpecification in THREADPRIVATE #159601
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Since ODS doesn't store a list of OmpObjects (i.e. not as OmpObjectList), some semantics-checking functions needed to be updated to operate on a single object at a time.
@llvm/pr-subscribers-flang-parser @llvm/pr-subscribers-flang-semantics Author: Krzysztof Parzyszek (kparzysz) ChangesSince ODS doesn't store a list of OmpObjects (i.e. not as OmpObjectList), some semantics-checking functions needed to be updated to operate on a single object at a time. Full diff: https://github.com/llvm/llvm-project/pull/159601.diff 10 Files Affected:
diff --git a/flang/include/flang/Parser/openmp-utils.h b/flang/include/flang/Parser/openmp-utils.h
index 032fb8996fe48..1372945427955 100644
--- a/flang/include/flang/Parser/openmp-utils.h
+++ b/flang/include/flang/Parser/openmp-utils.h
@@ -49,7 +49,6 @@ MAKE_CONSTR_ID(OpenMPDeclareSimdConstruct, D::OMPD_declare_simd);
MAKE_CONSTR_ID(OpenMPDeclareTargetConstruct, D::OMPD_declare_target);
MAKE_CONSTR_ID(OpenMPExecutableAllocate, D::OMPD_allocate);
MAKE_CONSTR_ID(OpenMPRequiresConstruct, D::OMPD_requires);
-MAKE_CONSTR_ID(OpenMPThreadprivate, D::OMPD_threadprivate);
#undef MAKE_CONSTR_ID
@@ -111,8 +110,7 @@ struct DirectiveNameScope {
std::is_same_v<T, OpenMPDeclareSimdConstruct> ||
std::is_same_v<T, OpenMPDeclareTargetConstruct> ||
std::is_same_v<T, OpenMPExecutableAllocate> ||
- std::is_same_v<T, OpenMPRequiresConstruct> ||
- std::is_same_v<T, OpenMPThreadprivate>) {
+ std::is_same_v<T, OpenMPRequiresConstruct>) {
return MakeName(std::get<Verbatim>(x.t).source, ConstructId<T>::id);
} else {
return GetFromTuple(
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index 7307283eb91ec..ad81f2cb094ad 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -4994,9 +4994,8 @@ struct OpenMPRequiresConstruct {
// 2.15.2 threadprivate -> THREADPRIVATE (variable-name-list)
struct OpenMPThreadprivate {
- TUPLE_CLASS_BOILERPLATE(OpenMPThreadprivate);
+ WRAPPER_CLASS_BOILERPLATE(OpenMPThreadprivate, OmpDirectiveSpecification);
CharBlock source;
- std::tuple<Verbatim, OmpObjectList> t;
};
// 2.11.3 allocate -> ALLOCATE (variable-name-list) [clause]
diff --git a/flang/include/flang/Semantics/openmp-utils.h b/flang/include/flang/Semantics/openmp-utils.h
index 68318d6093a1e..65441728c5549 100644
--- a/flang/include/flang/Semantics/openmp-utils.h
+++ b/flang/include/flang/Semantics/openmp-utils.h
@@ -58,9 +58,10 @@ const parser::DataRef *GetDataRefFromObj(const parser::OmpObject &object);
const parser::ArrayElement *GetArrayElementFromObj(
const parser::OmpObject &object);
const Symbol *GetObjectSymbol(const parser::OmpObject &object);
-const Symbol *GetArgumentSymbol(const parser::OmpArgument &argument);
std::optional<parser::CharBlock> GetObjectSource(
const parser::OmpObject &object);
+const Symbol *GetArgumentSymbol(const parser::OmpArgument &argument);
+const parser::OmpObject *GetArgumentObject(const parser::OmpArgument &argument);
bool IsCommonBlock(const Symbol &sym);
bool IsExtendedListItem(const Symbol &sym);
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index c6d4de108fb59..169bbf5935068 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -1788,8 +1788,11 @@ TYPE_PARSER(sourced(construct<OpenMPRequiresConstruct>(
verbatim("REQUIRES"_tok), Parser<OmpClauseList>{})))
// 2.15.2 Threadprivate directive
-TYPE_PARSER(sourced(construct<OpenMPThreadprivate>(
- verbatim("THREADPRIVATE"_tok), parenthesized(Parser<OmpObjectList>{}))))
+TYPE_PARSER(sourced( //
+ construct<OpenMPThreadprivate>(
+ predicated(OmpDirectiveNameParser{},
+ IsDirective(llvm::omp::Directive::OMPD_threadprivate)) >=
+ Parser<OmpDirectiveSpecification>{})))
// 2.11.3 Declarative Allocate directive
TYPE_PARSER(
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index 73bbbc04f46b1..9be2ce5533516 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2599,12 +2599,11 @@ class UnparseVisitor {
}
void Unparse(const OpenMPThreadprivate &x) {
BeginOpenMP();
- Word("!$OMP THREADPRIVATE (");
- Walk(std::get<parser::OmpObjectList>(x.t));
- Put(")\n");
+ Word("!$OMP ");
+ Walk(x.v);
+ Put("\n");
EndOpenMP();
}
-
bool Pre(const OmpMessageClause &x) {
Walk(x.v);
return false;
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 4c7cd1734e0e7..f16782d286dea 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -662,11 +662,6 @@ template <typename Checker> struct DirectiveSpellingVisitor {
checker_(x.v.DirName().source, Directive::OMPD_groupprivate);
return false;
}
- bool Pre(const parser::OpenMPThreadprivate &x) {
- checker_(
- std::get<parser::Verbatim>(x.t).source, Directive::OMPD_threadprivate);
- return false;
- }
bool Pre(const parser::OpenMPRequiresConstruct &x) {
checker_(std::get<parser::Verbatim>(x.t).source, Directive::OMPD_requires);
return false;
@@ -1299,11 +1294,16 @@ void OmpStructureChecker::CheckThreadprivateOrDeclareTargetVar(
}
}
+void OmpStructureChecker::CheckThreadprivateOrDeclareTargetVar(
+ const parser::OmpObject &object) {
+ common::visit(
+ [&](auto &&s) { CheckThreadprivateOrDeclareTargetVar(s); }, object.u);
+}
+
void OmpStructureChecker::CheckThreadprivateOrDeclareTargetVar(
const parser::OmpObjectList &objList) {
for (const auto &ompObject : objList.v) {
- common::visit([&](auto &&s) { CheckThreadprivateOrDeclareTargetVar(s); },
- ompObject.u);
+ CheckThreadprivateOrDeclareTargetVar(ompObject);
}
}
@@ -1363,18 +1363,20 @@ void OmpStructureChecker::Leave(const parser::OpenMPGroupprivate &x) {
dirContext_.pop_back();
}
-void OmpStructureChecker::Enter(const parser::OpenMPThreadprivate &c) {
- const auto &dir{std::get<parser::Verbatim>(c.t)};
- PushContextAndClauseSets(
- dir.source, llvm::omp::Directive::OMPD_threadprivate);
+void OmpStructureChecker::Enter(const parser::OpenMPThreadprivate &x) {
+ const parser::OmpDirectiveName &dirName{x.v.DirName()};
+ PushContextAndClauseSets(dirName.source, dirName.v);
}
-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);
- CheckVarIsNotPartOfAnotherVar(dir.source, objectList);
- CheckThreadprivateOrDeclareTargetVar(objectList);
+void OmpStructureChecker::Leave(const parser::OpenMPThreadprivate &x) {
+ const parser::OmpDirectiveSpecification &dirSpec{x.v};
+ for (const parser::OmpArgument &arg : x.v.Arguments().v) {
+ if (auto *object{GetArgumentObject(arg)}) {
+ CheckSymbolName(dirSpec.source, *object);
+ CheckVarIsNotPartOfAnotherVar(dirSpec.source, *object);
+ CheckThreadprivateOrDeclareTargetVar(*object);
+ }
+ }
dirContext_.pop_back();
}
@@ -1669,29 +1671,34 @@ void OmpStructureChecker::Enter(const parser::OmpDeclareTargetWithList &x) {
}
}
-void OmpStructureChecker::CheckSymbolNames(
- const parser::CharBlock &source, const parser::OmpObjectList &objList) {
- for (const auto &ompObject : objList.v) {
- common::visit(
- common::visitors{
- [&](const parser::Designator &designator) {
- if (const auto *name{parser::Unwrap<parser::Name>(ompObject)}) {
- if (!name->symbol) {
- context_.Say(source,
- "The given %s directive clause has an invalid argument"_err_en_US,
- ContextDirectiveAsFortran());
- }
- }
- },
- [&](const parser::Name &name) {
- if (!name.symbol) {
+void OmpStructureChecker::CheckSymbolName(
+ const parser::CharBlock &source, const parser::OmpObject &object) {
+ common::visit(
+ common::visitors{
+ [&](const parser::Designator &designator) {
+ if (const auto *name{parser::Unwrap<parser::Name>(object)}) {
+ if (!name->symbol) {
context_.Say(source,
"The given %s directive clause has an invalid argument"_err_en_US,
ContextDirectiveAsFortran());
}
- },
- },
- ompObject.u);
+ }
+ },
+ [&](const parser::Name &name) {
+ if (!name.symbol) {
+ context_.Say(source,
+ "The given %s directive clause has an invalid argument"_err_en_US,
+ ContextDirectiveAsFortran());
+ }
+ },
+ },
+ object.u);
+}
+
+void OmpStructureChecker::CheckSymbolNames(
+ const parser::CharBlock &source, const parser::OmpObjectList &objList) {
+ for (const auto &ompObject : objList.v) {
+ CheckSymbolName(source, ompObject);
}
}
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index ce074f5f3f86e..6de69e1a8e4f1 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -228,7 +228,10 @@ class OmpStructureChecker
const parser::OmpObjectList &objList, llvm::StringRef clause = "");
void CheckThreadprivateOrDeclareTargetVar(const parser::Designator &);
void CheckThreadprivateOrDeclareTargetVar(const parser::Name &);
+ void CheckThreadprivateOrDeclareTargetVar(const parser::OmpObject &);
void CheckThreadprivateOrDeclareTargetVar(const parser::OmpObjectList &);
+ void CheckSymbolName(
+ const parser::CharBlock &source, const parser::OmpObject &object);
void CheckSymbolNames(
const parser::CharBlock &source, const parser::OmpObjectList &objList);
void CheckIntentInPointer(SymbolSourceMap &, const llvm::omp::Clause);
diff --git a/flang/lib/Semantics/openmp-utils.cpp b/flang/lib/Semantics/openmp-utils.cpp
index 2980f827d3ef3..58a09ad75fea0 100644
--- a/flang/lib/Semantics/openmp-utils.cpp
+++ b/flang/lib/Semantics/openmp-utils.cpp
@@ -105,6 +105,16 @@ const Symbol *GetObjectSymbol(const parser::OmpObject &object) {
return nullptr;
}
+std::optional<parser::CharBlock> GetObjectSource(
+ const parser::OmpObject &object) {
+ if (auto *name{std::get_if<parser::Name>(&object.u)}) {
+ return name->source;
+ } else if (auto *desg{std::get_if<parser::Designator>(&object.u)}) {
+ return GetLastName(*desg).source;
+ }
+ return std::nullopt;
+}
+
const Symbol *GetArgumentSymbol(const parser::OmpArgument &argument) {
if (auto *locator{std::get_if<parser::OmpLocator>(&argument.u)}) {
if (auto *object{std::get_if<parser::OmpObject>(&locator->u)}) {
@@ -114,14 +124,12 @@ const Symbol *GetArgumentSymbol(const parser::OmpArgument &argument) {
return nullptr;
}
-std::optional<parser::CharBlock> GetObjectSource(
- const parser::OmpObject &object) {
- if (auto *name{std::get_if<parser::Name>(&object.u)}) {
- return name->source;
- } else if (auto *desg{std::get_if<parser::Designator>(&object.u)}) {
- return GetLastName(*desg).source;
+const parser::OmpObject *GetArgumentObject(
+ const parser::OmpArgument &argument) {
+ if (auto *locator{std::get_if<parser::OmpLocator>(&argument.u)}) {
+ return std::get_if<parser::OmpObject>(&locator->u);
}
- return std::nullopt;
+ return nullptr;
}
bool IsCommonBlock(const Symbol &sym) {
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index abb8f6430b29b..83461fcc3c592 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -2344,9 +2344,14 @@ bool OmpAttributeVisitor::Pre(
}
bool OmpAttributeVisitor::Pre(const parser::OpenMPThreadprivate &x) {
- PushContext(x.source, llvm::omp::Directive::OMPD_threadprivate);
- const auto &list{std::get<parser::OmpObjectList>(x.t)};
- ResolveOmpObjectList(list, Symbol::Flag::OmpThreadprivate);
+ const parser::OmpDirectiveName &dirName{x.v.DirName()};
+ PushContext(dirName.source, dirName.v);
+
+ for (const parser::OmpArgument &arg : x.v.Arguments().v) {
+ if (auto *object{omp::GetArgumentObject(arg)}) {
+ ResolveOmpObject(*object, Symbol::Flag::OmpThreadprivate);
+ }
+ }
return true;
}
diff --git a/flang/test/Parser/OpenMP/threadprivate-blank-common-block.f90 b/flang/test/Parser/OpenMP/threadprivate-blank-common-block.f90
index 6317258e6ec8d..d0698b9e60d68 100644
--- a/flang/test/Parser/OpenMP/threadprivate-blank-common-block.f90
+++ b/flang/test/Parser/OpenMP/threadprivate-blank-common-block.f90
@@ -4,6 +4,6 @@
program main
integer :: a
common//a
- !CHECK: error: expected one of '$@ABCDEFGHIJKLMNOPQRSTUVWXYZ_'
+ !CHECK: error: expected end of line
!$omp threadprivate(//)
end
|
@llvm/pr-subscribers-flang-openmp Author: Krzysztof Parzyszek (kparzysz) ChangesSince ODS doesn't store a list of OmpObjects (i.e. not as OmpObjectList), some semantics-checking functions needed to be updated to operate on a single object at a time. Full diff: https://github.com/llvm/llvm-project/pull/159601.diff 10 Files Affected:
diff --git a/flang/include/flang/Parser/openmp-utils.h b/flang/include/flang/Parser/openmp-utils.h
index 032fb8996fe48..1372945427955 100644
--- a/flang/include/flang/Parser/openmp-utils.h
+++ b/flang/include/flang/Parser/openmp-utils.h
@@ -49,7 +49,6 @@ MAKE_CONSTR_ID(OpenMPDeclareSimdConstruct, D::OMPD_declare_simd);
MAKE_CONSTR_ID(OpenMPDeclareTargetConstruct, D::OMPD_declare_target);
MAKE_CONSTR_ID(OpenMPExecutableAllocate, D::OMPD_allocate);
MAKE_CONSTR_ID(OpenMPRequiresConstruct, D::OMPD_requires);
-MAKE_CONSTR_ID(OpenMPThreadprivate, D::OMPD_threadprivate);
#undef MAKE_CONSTR_ID
@@ -111,8 +110,7 @@ struct DirectiveNameScope {
std::is_same_v<T, OpenMPDeclareSimdConstruct> ||
std::is_same_v<T, OpenMPDeclareTargetConstruct> ||
std::is_same_v<T, OpenMPExecutableAllocate> ||
- std::is_same_v<T, OpenMPRequiresConstruct> ||
- std::is_same_v<T, OpenMPThreadprivate>) {
+ std::is_same_v<T, OpenMPRequiresConstruct>) {
return MakeName(std::get<Verbatim>(x.t).source, ConstructId<T>::id);
} else {
return GetFromTuple(
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index 7307283eb91ec..ad81f2cb094ad 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -4994,9 +4994,8 @@ struct OpenMPRequiresConstruct {
// 2.15.2 threadprivate -> THREADPRIVATE (variable-name-list)
struct OpenMPThreadprivate {
- TUPLE_CLASS_BOILERPLATE(OpenMPThreadprivate);
+ WRAPPER_CLASS_BOILERPLATE(OpenMPThreadprivate, OmpDirectiveSpecification);
CharBlock source;
- std::tuple<Verbatim, OmpObjectList> t;
};
// 2.11.3 allocate -> ALLOCATE (variable-name-list) [clause]
diff --git a/flang/include/flang/Semantics/openmp-utils.h b/flang/include/flang/Semantics/openmp-utils.h
index 68318d6093a1e..65441728c5549 100644
--- a/flang/include/flang/Semantics/openmp-utils.h
+++ b/flang/include/flang/Semantics/openmp-utils.h
@@ -58,9 +58,10 @@ const parser::DataRef *GetDataRefFromObj(const parser::OmpObject &object);
const parser::ArrayElement *GetArrayElementFromObj(
const parser::OmpObject &object);
const Symbol *GetObjectSymbol(const parser::OmpObject &object);
-const Symbol *GetArgumentSymbol(const parser::OmpArgument &argument);
std::optional<parser::CharBlock> GetObjectSource(
const parser::OmpObject &object);
+const Symbol *GetArgumentSymbol(const parser::OmpArgument &argument);
+const parser::OmpObject *GetArgumentObject(const parser::OmpArgument &argument);
bool IsCommonBlock(const Symbol &sym);
bool IsExtendedListItem(const Symbol &sym);
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index c6d4de108fb59..169bbf5935068 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -1788,8 +1788,11 @@ TYPE_PARSER(sourced(construct<OpenMPRequiresConstruct>(
verbatim("REQUIRES"_tok), Parser<OmpClauseList>{})))
// 2.15.2 Threadprivate directive
-TYPE_PARSER(sourced(construct<OpenMPThreadprivate>(
- verbatim("THREADPRIVATE"_tok), parenthesized(Parser<OmpObjectList>{}))))
+TYPE_PARSER(sourced( //
+ construct<OpenMPThreadprivate>(
+ predicated(OmpDirectiveNameParser{},
+ IsDirective(llvm::omp::Directive::OMPD_threadprivate)) >=
+ Parser<OmpDirectiveSpecification>{})))
// 2.11.3 Declarative Allocate directive
TYPE_PARSER(
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index 73bbbc04f46b1..9be2ce5533516 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2599,12 +2599,11 @@ class UnparseVisitor {
}
void Unparse(const OpenMPThreadprivate &x) {
BeginOpenMP();
- Word("!$OMP THREADPRIVATE (");
- Walk(std::get<parser::OmpObjectList>(x.t));
- Put(")\n");
+ Word("!$OMP ");
+ Walk(x.v);
+ Put("\n");
EndOpenMP();
}
-
bool Pre(const OmpMessageClause &x) {
Walk(x.v);
return false;
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 4c7cd1734e0e7..f16782d286dea 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -662,11 +662,6 @@ template <typename Checker> struct DirectiveSpellingVisitor {
checker_(x.v.DirName().source, Directive::OMPD_groupprivate);
return false;
}
- bool Pre(const parser::OpenMPThreadprivate &x) {
- checker_(
- std::get<parser::Verbatim>(x.t).source, Directive::OMPD_threadprivate);
- return false;
- }
bool Pre(const parser::OpenMPRequiresConstruct &x) {
checker_(std::get<parser::Verbatim>(x.t).source, Directive::OMPD_requires);
return false;
@@ -1299,11 +1294,16 @@ void OmpStructureChecker::CheckThreadprivateOrDeclareTargetVar(
}
}
+void OmpStructureChecker::CheckThreadprivateOrDeclareTargetVar(
+ const parser::OmpObject &object) {
+ common::visit(
+ [&](auto &&s) { CheckThreadprivateOrDeclareTargetVar(s); }, object.u);
+}
+
void OmpStructureChecker::CheckThreadprivateOrDeclareTargetVar(
const parser::OmpObjectList &objList) {
for (const auto &ompObject : objList.v) {
- common::visit([&](auto &&s) { CheckThreadprivateOrDeclareTargetVar(s); },
- ompObject.u);
+ CheckThreadprivateOrDeclareTargetVar(ompObject);
}
}
@@ -1363,18 +1363,20 @@ void OmpStructureChecker::Leave(const parser::OpenMPGroupprivate &x) {
dirContext_.pop_back();
}
-void OmpStructureChecker::Enter(const parser::OpenMPThreadprivate &c) {
- const auto &dir{std::get<parser::Verbatim>(c.t)};
- PushContextAndClauseSets(
- dir.source, llvm::omp::Directive::OMPD_threadprivate);
+void OmpStructureChecker::Enter(const parser::OpenMPThreadprivate &x) {
+ const parser::OmpDirectiveName &dirName{x.v.DirName()};
+ PushContextAndClauseSets(dirName.source, dirName.v);
}
-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);
- CheckVarIsNotPartOfAnotherVar(dir.source, objectList);
- CheckThreadprivateOrDeclareTargetVar(objectList);
+void OmpStructureChecker::Leave(const parser::OpenMPThreadprivate &x) {
+ const parser::OmpDirectiveSpecification &dirSpec{x.v};
+ for (const parser::OmpArgument &arg : x.v.Arguments().v) {
+ if (auto *object{GetArgumentObject(arg)}) {
+ CheckSymbolName(dirSpec.source, *object);
+ CheckVarIsNotPartOfAnotherVar(dirSpec.source, *object);
+ CheckThreadprivateOrDeclareTargetVar(*object);
+ }
+ }
dirContext_.pop_back();
}
@@ -1669,29 +1671,34 @@ void OmpStructureChecker::Enter(const parser::OmpDeclareTargetWithList &x) {
}
}
-void OmpStructureChecker::CheckSymbolNames(
- const parser::CharBlock &source, const parser::OmpObjectList &objList) {
- for (const auto &ompObject : objList.v) {
- common::visit(
- common::visitors{
- [&](const parser::Designator &designator) {
- if (const auto *name{parser::Unwrap<parser::Name>(ompObject)}) {
- if (!name->symbol) {
- context_.Say(source,
- "The given %s directive clause has an invalid argument"_err_en_US,
- ContextDirectiveAsFortran());
- }
- }
- },
- [&](const parser::Name &name) {
- if (!name.symbol) {
+void OmpStructureChecker::CheckSymbolName(
+ const parser::CharBlock &source, const parser::OmpObject &object) {
+ common::visit(
+ common::visitors{
+ [&](const parser::Designator &designator) {
+ if (const auto *name{parser::Unwrap<parser::Name>(object)}) {
+ if (!name->symbol) {
context_.Say(source,
"The given %s directive clause has an invalid argument"_err_en_US,
ContextDirectiveAsFortran());
}
- },
- },
- ompObject.u);
+ }
+ },
+ [&](const parser::Name &name) {
+ if (!name.symbol) {
+ context_.Say(source,
+ "The given %s directive clause has an invalid argument"_err_en_US,
+ ContextDirectiveAsFortran());
+ }
+ },
+ },
+ object.u);
+}
+
+void OmpStructureChecker::CheckSymbolNames(
+ const parser::CharBlock &source, const parser::OmpObjectList &objList) {
+ for (const auto &ompObject : objList.v) {
+ CheckSymbolName(source, ompObject);
}
}
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index ce074f5f3f86e..6de69e1a8e4f1 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -228,7 +228,10 @@ class OmpStructureChecker
const parser::OmpObjectList &objList, llvm::StringRef clause = "");
void CheckThreadprivateOrDeclareTargetVar(const parser::Designator &);
void CheckThreadprivateOrDeclareTargetVar(const parser::Name &);
+ void CheckThreadprivateOrDeclareTargetVar(const parser::OmpObject &);
void CheckThreadprivateOrDeclareTargetVar(const parser::OmpObjectList &);
+ void CheckSymbolName(
+ const parser::CharBlock &source, const parser::OmpObject &object);
void CheckSymbolNames(
const parser::CharBlock &source, const parser::OmpObjectList &objList);
void CheckIntentInPointer(SymbolSourceMap &, const llvm::omp::Clause);
diff --git a/flang/lib/Semantics/openmp-utils.cpp b/flang/lib/Semantics/openmp-utils.cpp
index 2980f827d3ef3..58a09ad75fea0 100644
--- a/flang/lib/Semantics/openmp-utils.cpp
+++ b/flang/lib/Semantics/openmp-utils.cpp
@@ -105,6 +105,16 @@ const Symbol *GetObjectSymbol(const parser::OmpObject &object) {
return nullptr;
}
+std::optional<parser::CharBlock> GetObjectSource(
+ const parser::OmpObject &object) {
+ if (auto *name{std::get_if<parser::Name>(&object.u)}) {
+ return name->source;
+ } else if (auto *desg{std::get_if<parser::Designator>(&object.u)}) {
+ return GetLastName(*desg).source;
+ }
+ return std::nullopt;
+}
+
const Symbol *GetArgumentSymbol(const parser::OmpArgument &argument) {
if (auto *locator{std::get_if<parser::OmpLocator>(&argument.u)}) {
if (auto *object{std::get_if<parser::OmpObject>(&locator->u)}) {
@@ -114,14 +124,12 @@ const Symbol *GetArgumentSymbol(const parser::OmpArgument &argument) {
return nullptr;
}
-std::optional<parser::CharBlock> GetObjectSource(
- const parser::OmpObject &object) {
- if (auto *name{std::get_if<parser::Name>(&object.u)}) {
- return name->source;
- } else if (auto *desg{std::get_if<parser::Designator>(&object.u)}) {
- return GetLastName(*desg).source;
+const parser::OmpObject *GetArgumentObject(
+ const parser::OmpArgument &argument) {
+ if (auto *locator{std::get_if<parser::OmpLocator>(&argument.u)}) {
+ return std::get_if<parser::OmpObject>(&locator->u);
}
- return std::nullopt;
+ return nullptr;
}
bool IsCommonBlock(const Symbol &sym) {
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index abb8f6430b29b..83461fcc3c592 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -2344,9 +2344,14 @@ bool OmpAttributeVisitor::Pre(
}
bool OmpAttributeVisitor::Pre(const parser::OpenMPThreadprivate &x) {
- PushContext(x.source, llvm::omp::Directive::OMPD_threadprivate);
- const auto &list{std::get<parser::OmpObjectList>(x.t)};
- ResolveOmpObjectList(list, Symbol::Flag::OmpThreadprivate);
+ const parser::OmpDirectiveName &dirName{x.v.DirName()};
+ PushContext(dirName.source, dirName.v);
+
+ for (const parser::OmpArgument &arg : x.v.Arguments().v) {
+ if (auto *object{omp::GetArgumentObject(arg)}) {
+ ResolveOmpObject(*object, Symbol::Flag::OmpThreadprivate);
+ }
+ }
return true;
}
diff --git a/flang/test/Parser/OpenMP/threadprivate-blank-common-block.f90 b/flang/test/Parser/OpenMP/threadprivate-blank-common-block.f90
index 6317258e6ec8d..d0698b9e60d68 100644
--- a/flang/test/Parser/OpenMP/threadprivate-blank-common-block.f90
+++ b/flang/test/Parser/OpenMP/threadprivate-blank-common-block.f90
@@ -4,6 +4,6 @@
program main
integer :: a
common//a
- !CHECK: error: expected one of '$@ABCDEFGHIJKLMNOPQRSTUVWXYZ_'
+ !CHECK: error: expected end of line
!$omp threadprivate(//)
end
|
integer :: a | ||
common//a | ||
!CHECK: error: expected one of '$@ABCDEFGHIJKLMNOPQRSTUVWXYZ_' | ||
!CHECK: error: expected end of line |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm going to see if we can be more meaningful (than either case) about blank common blocks...
Superseded by #159632. |
Since ODS doesn't store a list of OmpObjects (i.e. not as OmpObjectList), some semantics-checking functions needed to be updated to operate on a single object at a time.