Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions flang/include/flang/Parser/openmp-utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -110,8 +109,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(
Expand Down
3 changes: 1 addition & 2 deletions flang/include/flang/Parser/parse-tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -5000,9 +5000,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]
Expand Down
3 changes: 2 additions & 1 deletion flang/include/flang/Semantics/openmp-utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
7 changes: 5 additions & 2 deletions flang/lib/Parser/openmp-parsers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1791,8 +1791,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(
Expand Down
7 changes: 3 additions & 4 deletions flang/lib/Parser/unparse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2611,12 +2611,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();
Comment on lines 2613 to 2617
Copy link
Contributor

Choose a reason for hiding this comment

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

Not for this PR but I wonder if we could generalise this as more get converted.

A simple approach would be a helper function for all OmpDirectiveSpecification, but I actually wonder if we could manage that automatically with an overload matching a trait in these wrapped classes?

}

bool Pre(const OmpMessageClause &x) {
Walk(x.v);
return false;
Expand Down
89 changes: 48 additions & 41 deletions flang/lib/Semantics/check-omp-structure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -665,11 +665,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;
Expand Down Expand Up @@ -1294,15 +1289,20 @@ void OmpStructureChecker::CheckThreadprivateOrDeclareTargetVar(
}
}

void OmpStructureChecker::CheckThreadprivateOrDeclareTargetVar(
const parser::OmpObject &object) {
common::visit( //
common::visitors{
[&](auto &&s) { CheckThreadprivateOrDeclareTargetVar(s); },
[&](const parser::OmpObject::Invalid &invalid) {},
},
object.u);
}

void OmpStructureChecker::CheckThreadprivateOrDeclareTargetVar(
const parser::OmpObjectList &objList) {
for (const auto &ompObject : objList.v) {
common::visit( //
common::visitors{
[&](auto &&s) { CheckThreadprivateOrDeclareTargetVar(s); },
[&](const parser::OmpObject::Invalid &invalid) {},
},
ompObject.u);
CheckThreadprivateOrDeclareTargetVar(ompObject);
}
}

Expand Down Expand Up @@ -1362,18 +1362,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();
}

Expand Down Expand Up @@ -1672,30 +1674,35 @@ 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());
}
},
[&](const parser::OmpObject::Invalid &invalid) {},
},
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());
}
},
[&](const parser::OmpObject::Invalid &invalid) {},
},
object.u);
}

void OmpStructureChecker::CheckSymbolNames(
const parser::CharBlock &source, const parser::OmpObjectList &objList) {
for (const auto &ompObject : objList.v) {
CheckSymbolName(source, ompObject);
}
}

Expand Down
3 changes: 3 additions & 0 deletions flang/lib/Semantics/check-omp-structure.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
22 changes: 15 additions & 7 deletions flang/lib/Semantics/openmp-utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)}) {
Expand All @@ -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) {
Expand Down
11 changes: 8 additions & 3 deletions flang/lib/Semantics/resolve-directives.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2342,9 +2342,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;
}

Expand Down
25 changes: 25 additions & 0 deletions flang/test/Parser/OpenMP/threadprivate.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
!RUN: %flang_fc1 -fdebug-unparse -fopenmp -fopenmp-version=60 %s | FileCheck --ignore-case --check-prefix="UNPARSE" %s
!RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp -fopenmp-version=60 %s | FileCheck --check-prefix="PARSE-TREE" %s

module m
implicit none
integer :: a, b
common /blk/ a

!$omp threadprivate(/blk/, b)

end module

!UNPARSE: MODULE m
!UNPARSE: IMPLICIT NONE
!UNPARSE: INTEGER a, b
!UNPARSE: COMMON /blk/a
!UNPARSE: !$OMP THREADPRIVATE(/blk/, b)
!UNPARSE: END MODULE

!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OpenMPThreadprivate -> OmpDirectiveSpecification
!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = threadprivate
!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Name = 'blk'
!PARSE-TREE: | OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'b'
!PARSE-TREE: | OmpClauseList ->
!PARSE-TREE: | Flags = None