Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
2 changes: 2 additions & 0 deletions flang/include/flang/Parser/dump-parse-tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,8 @@ class ParseTreeDumper {
NODE(parser, OmpNumTasksClause)
NODE(OmpNumTasksClause, Modifier)
NODE(parser, OmpObject)
NODE(OmpObject, Invalid)
NODE_ENUM(OmpObject::Invalid, Kind)
NODE(parser, OmpObjectList)
NODE(parser, OmpOrderClause)
NODE(OmpOrderClause, Modifier)
Expand Down
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 @@ -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(
Expand Down
12 changes: 9 additions & 3 deletions flang/include/flang/Parser/parse-tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -3505,8 +3505,15 @@ struct OmpDirectiveName {
// in slashes). An extended list item is a list item or a procedure Name.
// variable-name | / common-block / | array-sections
struct OmpObject {
// Blank common blocks are not valid objects. Parse them to emit meaningful
// diagnostics.
struct Invalid {
ENUM_CLASS(Kind, BlankCommonBlock);
WRAPPER_CLASS_BOILERPLATE(Invalid, Kind);
CharBlock source;
};
UNION_CLASS_BOILERPLATE(OmpObject);
std::variant<Designator, /*common block*/ Name> u;
std::variant<Designator, /*common block*/ Name, Invalid> u;
};

WRAPPER_CLASS(OmpObjectList, std::list<OmpObject>);
Expand Down Expand Up @@ -4994,9 +5001,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
14 changes: 10 additions & 4 deletions flang/lib/Parser/openmp-parsers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1024,8 +1024,11 @@ TYPE_PARSER(construct<OmpNumTasksClause>(
maybe(nonemptyList(Parser<OmpNumTasksClause::Modifier>{}) / ":"),
scalarIntExpr))

TYPE_PARSER(
construct<OmpObject>(designator) || "/" >> construct<OmpObject>(name) / "/")
TYPE_PARSER( //
construct<OmpObject>(designator) ||
"/" >> construct<OmpObject>(name) / "/" ||
construct<OmpObject>(sourced(construct<OmpObject::Invalid>(
"//"_tok >> pure(OmpObject::Invalid::Kind::BlankCommonBlock)))))

// OMP 5.0 2.19.4.5 LASTPRIVATE ([lastprivate-modifier :] list)
TYPE_PARSER(construct<OmpLastprivateClause>(
Expand Down Expand Up @@ -1788,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
27 changes: 19 additions & 8 deletions flang/lib/Parser/unparse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2168,10 +2168,22 @@ class UnparseVisitor {
void Unparse(const OmpContextSelectorSpecification &x) { Walk(x.v, ", "); }

void Unparse(const OmpObject &x) {
common::visit(common::visitors{
[&](const Designator &y) { Walk(y); },
[&](const Name &y) { Put("/"), Walk(y), Put("/"); },
},
common::visit( //
common::visitors{
[&](const Designator &y) { Walk(y); },
[&](const Name &y) {
Put("/");
Walk(y);
Put("/");
},
[&](const OmpObject::Invalid &y) {
switch (y.v) {
case OmpObject::Invalid::Kind::BlankCommonBlock:
Put("//");
break;
}
},
},
x.u);
}
void Unparse(const OmpDirectiveNameModifier &x) {
Expand Down Expand Up @@ -2599,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
5 changes: 4 additions & 1 deletion flang/lib/Semantics/check-omp-loop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,10 @@ void OmpStructureChecker::Leave(const parser::OpenMPLoopConstruct &x) {
checkReductionSymbolInScan(name);
}
},
[&](const auto &name) { checkReductionSymbolInScan(&name); },
[&](const parser::Name &name) {
checkReductionSymbolInScan(&name);
},
[&](const parser::OmpObject::Invalid &invalid) {},
},
ompObj.u);
}
Expand Down
121 changes: 73 additions & 48 deletions flang/lib/Semantics/check-omp-structure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,8 @@ bool OmpStructureChecker::CheckAllowedClause(llvmOmpClause clause) {
}

void OmpStructureChecker::AnalyzeObject(const parser::OmpObject &object) {
if (std::holds_alternative<parser::Name>(object.u)) {
if (std::holds_alternative<parser::Name>(object.u) ||
std::holds_alternative<parser::OmpObject::Invalid>(object.u)) {
// Do not analyze common block names. The analyzer will flag an error
// on those.
return;
Expand All @@ -294,7 +295,12 @@ void OmpStructureChecker::AnalyzeObject(const parser::OmpObject &object) {
}
evaluate::ExpressionAnalyzer ea{context_};
auto restore{ea.AllowWholeAssumedSizeArray(true)};
common::visit([&](auto &&s) { ea.Analyze(s); }, object.u);
common::visit( //
common::visitors{
[&](auto &&s) { ea.Analyze(s); },
[&](const parser::OmpObject::Invalid &invalid) {},
},
object.u);
}

void OmpStructureChecker::AnalyzeObjects(const parser::OmpObjectList &objects) {
Expand Down Expand Up @@ -538,6 +544,7 @@ void OmpStructureChecker::CheckPredefinedAllocatorRestriction(
[&](const parser::Name &name) {
CheckPredefinedAllocatorRestriction(source, name);
},
[&](const parser::OmpObject::Invalid &invalid) {},
},
ompObject.u);
}
Expand Down Expand Up @@ -662,11 +669,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 @@ -1299,11 +1301,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([&](auto &&s) { CheckThreadprivateOrDeclareTargetVar(s); },
ompObject.u);
CheckThreadprivateOrDeclareTargetVar(ompObject);
}
}

Expand Down Expand Up @@ -1363,18 +1374,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 @@ -1434,8 +1447,14 @@ void OmpStructureChecker::Enter(const parser::OpenMPDepobjConstruct &x) {
// refer to the same depend object as the depobj argument of the construct.
if (clause.Id() == llvm::omp::Clause::OMPC_destroy) {
auto getObjSymbol{[&](const parser::OmpObject &obj) {
return common::visit(
[&](auto &&s) { return GetLastName(s).symbol; }, obj.u);
return common::visit( //
common::visitors{
[&](auto &&s) { return GetLastName(s).symbol; },
[&](const parser::OmpObject::Invalid &invalid) {
return static_cast<Symbol *>(nullptr);
},
},
obj.u);
}};
auto getArgSymbol{[&](const parser::OmpArgument &arg) {
if (auto *locator{std::get_if<parser::OmpLocator>(&arg.u)}) {
Expand All @@ -1450,9 +1469,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPDepobjConstruct &x) {
if (const std::optional<parser::OmpDestroyClause> &destroy{wrapper.v}) {
const Symbol *constrSym{getArgSymbol(arguments.v.front())};
const Symbol *clauseSym{getObjSymbol(destroy->v)};
assert(constrSym && "Unresolved depobj construct symbol");
assert(clauseSym && "Unresolved destroy symbol on depobj construct");
if (constrSym != clauseSym) {
if (constrSym && clauseSym && constrSym != clauseSym) {
context_.Say(x.source,
"The DESTROY clause must refer to the same object as the "
"DEPOBJ construct"_err_en_US);
Expand Down Expand Up @@ -1669,29 +1686,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());
}
},
},
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 Expand Up @@ -2710,6 +2733,7 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &) {
}
}
},
[&](const parser::OmpObject::Invalid &invalid) {},
},
ompObject.u);
}
Expand Down Expand Up @@ -3417,6 +3441,7 @@ void OmpStructureChecker::CheckVarIsNotPartOfAnotherVar(
}
},
[&](const parser::Name &name) {},
[&](const parser::OmpObject::Invalid &invalid) {},
},
ompObject.u);
}
Expand Down Expand Up @@ -4102,11 +4127,11 @@ void OmpStructureChecker::CheckStructureComponent(
}};

for (const auto &object : objects.v) {
common::visit(
common::visitors{
CheckComponent,
[&](const parser::Name &name) {},
},
common::visit(common::visitors{
CheckComponent,
[&](const parser::Name &name) {},
[&](const parser::OmpObject::Invalid &invalid) {},
},
object.u);
}
}
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
Loading