diff options
Diffstat (limited to 'flang/lib/Semantics/check-omp-structure.cpp')
-rw-r--r-- | flang/lib/Semantics/check-omp-structure.cpp | 156 |
1 files changed, 74 insertions, 82 deletions
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index d214d22..a9c56c3 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -498,7 +498,7 @@ template <typename Checker> struct DirectiveSpellingVisitor { template <typename... Ts> static const parser::OmpDirectiveName &GetDirName( const std::tuple<Ts...> &t) { - return std::get<parser::OmpDirectiveSpecification>(t).DirName(); + return std::get<parser::OmpBeginDirective>(t).DirName(); } bool Pre(const parser::OmpSectionsDirective &x) { @@ -588,12 +588,14 @@ template <typename Checker> struct DirectiveSpellingVisitor { checker_(std::get<parser::Verbatim>(x.t).source, Directive::OMPD_requires); return false; } - - bool Pre(const parser::OmpBlockDirective &x) { - checker_(x.source, x.v); + bool Pre(const parser::OmpBeginDirective &x) { + checker_(x.DirName().source, x.DirId()); + return false; + } + bool Pre(const parser::OmpEndDirective &x) { + checker_(x.DirName().source, x.DirId()); return false; } - bool Pre(const parser::OmpLoopDirective &x) { checker_(x.source, x.v); return false; @@ -726,22 +728,22 @@ void OmpStructureChecker::CheckTargetNest(const parser::OpenMPConstruct &c) { // 2.12.5 Target Construct Restriction bool eligibleTarget{true}; llvm::omp::Directive ineligibleTargetDir; + parser::CharBlock source; common::visit( common::visitors{ [&](const parser::OpenMPBlockConstruct &c) { - const auto &beginBlockDir{ - std::get<parser::OmpBeginBlockDirective>(c.t)}; - const auto &beginDir{ - std::get<parser::OmpBlockDirective>(beginBlockDir.t)}; - if (beginDir.v == llvm::omp::Directive::OMPD_target_data) { + const parser::OmpDirectiveSpecification &beginSpec{c.BeginDir()}; + source = beginSpec.DirName().source; + if (beginSpec.DirId() == llvm::omp::Directive::OMPD_target_data) { eligibleTarget = false; - ineligibleTargetDir = beginDir.v; + ineligibleTargetDir = beginSpec.DirId(); } }, [&](const parser::OpenMPStandaloneConstruct &c) { common::visit( common::visitors{ [&](const parser::OpenMPSimpleStandaloneConstruct &c) { + source = c.v.DirName().source; switch (llvm::omp::Directive dirId{c.v.DirId()}) { case llvm::omp::Directive::OMPD_target_update: case llvm::omp::Directive::OMPD_target_enter_data: @@ -762,6 +764,7 @@ void OmpStructureChecker::CheckTargetNest(const parser::OpenMPConstruct &c) { std::get<parser::OmpBeginLoopDirective>(c.t)}; const auto &beginDir{ std::get<parser::OmpLoopDirective>(beginLoopDir.t)}; + source = beginLoopDir.source; if (llvm::omp::allTargetSet.test(beginDir.v)) { eligibleTarget = false; ineligibleTargetDir = beginDir.v; @@ -771,8 +774,7 @@ void OmpStructureChecker::CheckTargetNest(const parser::OpenMPConstruct &c) { }, c.u); if (!eligibleTarget) { - context_.Warn(common::UsageWarning::OpenMPUsage, - parser::FindSourceLocation(c), + context_.Warn(common::UsageWarning::OpenMPUsage, source, "If %s directive is nested inside TARGET region, the behaviour is unspecified"_port_en_US, parser::ToUpperCaseLetters( getDirectiveName(ineligibleTargetDir).str())); @@ -780,25 +782,18 @@ void OmpStructureChecker::CheckTargetNest(const parser::OpenMPConstruct &c) { } void OmpStructureChecker::Enter(const parser::OpenMPBlockConstruct &x) { - const auto &beginBlockDir{std::get<parser::OmpBeginBlockDirective>(x.t)}; - const auto &endBlockDir{ - std::get<std::optional<parser::OmpEndBlockDirective>>(x.t)}; - const auto &beginDir{std::get<parser::OmpBlockDirective>(beginBlockDir.t)}; + const parser::OmpDirectiveSpecification &beginSpec{x.BeginDir()}; + const std::optional<parser::OmpEndDirective> &endSpec{x.EndDir()}; const parser::Block &block{std::get<parser::Block>(x.t)}; - if (endBlockDir) { - const auto &endDir{std::get<parser::OmpBlockDirective>(endBlockDir->t)}; - CheckMatching<parser::OmpBlockDirective>(beginDir, endDir); - } - - PushContextAndClauseSets(beginDir.source, beginDir.v); + PushContextAndClauseSets(beginSpec.DirName().source, beginSpec.DirId()); if (llvm::omp::allTargetSet.test(GetContext().directive)) { EnterDirectiveNest(TargetNest); } if (CurrentDirectiveIsNested()) { if (llvm::omp::bottomTeamsSet.test(GetContextParent().directive)) { - HasInvalidTeamsNesting(beginDir.v, beginDir.source); + HasInvalidTeamsNesting(beginSpec.DirId(), beginSpec.source); } if (GetContext().directive == llvm::omp::Directive::OMPD_master) { CheckMasterNesting(x); @@ -807,7 +802,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPBlockConstruct &x) { // region or a target region. if (GetContext().directive == llvm::omp::Directive::OMPD_teams && GetContextParent().directive != llvm::omp::Directive::OMPD_target) { - context_.Say(parser::FindSourceLocation(x), + context_.Say(x.BeginDir().DirName().source, "%s region can only be strictly nested within the implicit parallel " "region or TARGET region"_err_en_US, ContextDirectiveAsFortran()); @@ -824,12 +819,12 @@ void OmpStructureChecker::Enter(const parser::OpenMPBlockConstruct &x) { } } - CheckNoBranching(block, beginDir.v, beginDir.source); + CheckNoBranching(block, beginSpec.DirId(), beginSpec.source); // Target block constructs are target device constructs. Keep track of // whether any such construct has been visited to later check that REQUIRES // directives for target-related options don't appear after them. - if (llvm::omp::allTargetSet.test(beginDir.v)) { + if (llvm::omp::allTargetSet.test(beginSpec.DirId())) { deviceConstructFound_ = true; } @@ -839,8 +834,8 @@ void OmpStructureChecker::Enter(const parser::OpenMPBlockConstruct &x) { bool foundNowait{false}; parser::CharBlock NowaitSource; - auto catchCopyPrivateNowaitClauses = [&](const auto &dir, bool isEnd) { - for (auto &clause : std::get<parser::OmpClauseList>(dir.t).v) { + auto catchCopyPrivateNowaitClauses = [&](const auto &dirSpec, bool isEnd) { + for (auto &clause : dirSpec.Clauses().v) { if (clause.Id() == llvm::omp::Clause::OMPC_copyprivate) { for (const auto &ompObject : GetOmpObjectList(clause)->v) { const auto *name{parser::Unwrap<parser::Name>(ompObject)}; @@ -881,9 +876,9 @@ void OmpStructureChecker::Enter(const parser::OpenMPBlockConstruct &x) { } } }; - catchCopyPrivateNowaitClauses(beginBlockDir, false); - if (endBlockDir) { - catchCopyPrivateNowaitClauses(*endBlockDir, true); + catchCopyPrivateNowaitClauses(beginSpec, false); + if (endSpec) { + catchCopyPrivateNowaitClauses(*endSpec, true); } unsigned version{context_.langOptions().OpenMPVersion}; if (version <= 52 && NowaitSource.ToString().size() && @@ -893,7 +888,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPBlockConstruct &x) { } } - switch (beginDir.v) { + switch (beginSpec.DirId()) { case llvm::omp::Directive::OMPD_target: if (CheckTargetBlockOnlyTeams(block)) { EnterDirectiveNest(TargetBlockOnlyTeams); @@ -901,27 +896,25 @@ void OmpStructureChecker::Enter(const parser::OpenMPBlockConstruct &x) { break; case llvm::omp::OMPD_workshare: case llvm::omp::OMPD_parallel_workshare: - CheckWorkshareBlockStmts(block, beginDir.source); + CheckWorkshareBlockStmts(block, beginSpec.source); HasInvalidWorksharingNesting( - beginDir.source, llvm::omp::nestedWorkshareErrSet); + beginSpec.source, llvm::omp::nestedWorkshareErrSet); break; case llvm::omp::Directive::OMPD_scope: case llvm::omp::Directive::OMPD_single: // TODO: This check needs to be extended while implementing nesting of // regions checks. HasInvalidWorksharingNesting( - beginDir.source, llvm::omp::nestedWorkshareErrSet); + beginSpec.source, llvm::omp::nestedWorkshareErrSet); break; - case llvm::omp::Directive::OMPD_task: { - const auto &clauses{std::get<parser::OmpClauseList>(beginBlockDir.t)}; - for (const auto &clause : clauses.v) { + case llvm::omp::Directive::OMPD_task: + for (const auto &clause : beginSpec.Clauses().v) { if (std::get_if<parser::OmpClause::Untied>(&clause.u)) { OmpUnitedTaskDesignatorChecker check{context_}; parser::Walk(block, check); } } break; - } default: break; } @@ -934,7 +927,7 @@ void OmpStructureChecker::CheckMasterNesting( // TODO: Expand the check to include `LOOP` construct as well when it is // supported. if (IsCloselyNestedRegion(llvm::omp::nestedMasterErrSet)) { - context_.Say(parser::FindSourceLocation(x), + context_.Say(x.BeginDir().source, "`MASTER` region may not be closely nested inside of `WORKSHARING`, " "`LOOP`, `TASK`, `TASKLOOP`," " or `ATOMIC` region."_err_en_US); @@ -1034,7 +1027,7 @@ void OmpStructureChecker::ChecksOnOrderedAsBlock() { } } -void OmpStructureChecker::Leave(const parser::OmpBeginBlockDirective &) { +void OmpStructureChecker::Leave(const parser::OmpBeginDirective &) { switch (GetContext().directive) { case llvm::omp::Directive::OMPD_ordered: // [5.1] 2.19.9 Ordered Construct Restriction @@ -1057,10 +1050,11 @@ void OmpStructureChecker::Enter(const parser::OpenMPSectionsConstruct &x) { PushContextAndClauseSets(beginDir.source, beginDir.v); AddEndDirectiveClauses(std::get<parser::OmpClauseList>(endSectionsDir.t)); - const auto §ionBlocks{std::get<parser::OmpSectionBlocks>(x.t)}; - for (const parser::OpenMPConstruct &block : sectionBlocks.v) { - CheckNoBranching(std::get<parser::OpenMPSectionConstruct>(block.u).v, - beginDir.v, beginDir.source); + const auto §ionBlocks{std::get<std::list<parser::OpenMPConstruct>>(x.t)}; + for (const parser::OpenMPConstruct &construct : sectionBlocks) { + auto §ion{std::get<parser::OpenMPSectionConstruct>(construct.u)}; + CheckNoBranching( + std::get<parser::Block>(section.t), beginDir.v, beginDir.source); } HasInvalidWorksharingNesting( beginDir.source, llvm::omp::nestedWorkshareErrSet); @@ -1568,9 +1562,10 @@ void OmpStructureChecker::Leave(const parser::OpenMPDeclareTargetConstruct &x) { }, [&](const parser::OmpClause::Enter &enterClause) { enterClauseFound = true; - CheckSymbolNames(dir.source, enterClause.v); - CheckVarIsNotPartOfAnotherVar(dir.source, enterClause.v); - CheckThreadprivateOrDeclareTargetVar(enterClause.v); + auto &objList{std::get<parser::OmpObjectList>(enterClause.v.t)}; + CheckSymbolNames(dir.source, objList); + CheckVarIsNotPartOfAnotherVar(dir.source, objList); + CheckThreadprivateOrDeclareTargetVar(objList); }, [&](const parser::OmpClause::DeviceType &deviceTypeClause) { deviceTypeClauseFound = true; @@ -1599,7 +1594,7 @@ void OmpStructureChecker::Enter(const parser::OmpErrorDirective &x) { } void OmpStructureChecker::Enter(const parser::OpenMPDispatchConstruct &x) { - auto &dirSpec{std::get<parser::OmpDirectiveSpecification>(x.t)}; + const parser::OmpDirectiveSpecification &dirSpec{x.BeginDir()}; const auto &block{std::get<parser::Block>(x.t)}; PushContextAndClauseSets( dirSpec.DirName().source, llvm::omp::Directive::OMPD_dispatch); @@ -1670,7 +1665,7 @@ void OmpStructureChecker::Leave(const parser::OpenMPExecutableAllocate &x) { void OmpStructureChecker::Enter(const parser::OpenMPAllocatorsConstruct &x) { isPredefinedAllocator = true; - auto &dirSpec{std::get<parser::OmpDirectiveSpecification>(x.t)}; + const parser::OmpDirectiveSpecification &dirSpec{x.BeginDir()}; auto &block{std::get<parser::Block>(x.t)}; PushContextAndClauseSets( dirSpec.DirName().source, llvm::omp::Directive::OMPD_allocators); @@ -1701,7 +1696,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPAllocatorsConstruct &x) { } void OmpStructureChecker::Leave(const parser::OpenMPAllocatorsConstruct &x) { - auto &dirSpec{std::get<parser::OmpDirectiveSpecification>(x.t)}; + const parser::OmpDirectiveSpecification &dirSpec{x.BeginDir()}; for (const auto &clause : dirSpec.Clauses().v) { if (const auto *allocClause{ @@ -1735,7 +1730,7 @@ void OmpStructureChecker::CheckBarrierNesting( // TODO: Expand the check to include `LOOP` construct as well when it is // supported. if (IsCloselyNestedRegion(llvm::omp::nestedBarrierErrSet)) { - context_.Say(parser::FindSourceLocation(x), + context_.Say(x.v.DirName().source, "`BARRIER` region may not be closely nested inside of `WORKSHARING`, " "`LOOP`, `TASK`, `TASKLOOP`," "`CRITICAL`, `ORDERED`, `ATOMIC` or `MASTER` region."_err_en_US); @@ -2275,22 +2270,21 @@ void OmpStructureChecker::CheckCancellationNest( } } -void OmpStructureChecker::Enter(const parser::OmpEndBlockDirective &x) { - const auto &dir{std::get<parser::OmpBlockDirective>(x.t)}; - ResetPartialContext(dir.source); - switch (dir.v) { +void OmpStructureChecker::Enter(const parser::OmpEndDirective &x) { + parser::CharBlock source{x.DirName().source}; + ResetPartialContext(source); + switch (x.DirId()) { case llvm::omp::Directive::OMPD_scope: - PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_end_scope); + PushContextAndClauseSets(source, llvm::omp::Directive::OMPD_end_scope); break; // 2.7.3 end-single-clause -> copyprivate-clause | // nowait-clause case llvm::omp::Directive::OMPD_single: - PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_end_single); + PushContextAndClauseSets(source, llvm::omp::Directive::OMPD_end_single); break; // 2.7.4 end-workshare -> END WORKSHARE [nowait-clause] case llvm::omp::Directive::OMPD_workshare: - PushContextAndClauseSets( - dir.source, llvm::omp::Directive::OMPD_end_workshare); + PushContextAndClauseSets(source, llvm::omp::Directive::OMPD_end_workshare); break; default: // no clauses are allowed @@ -2303,7 +2297,7 @@ void OmpStructureChecker::Enter(const parser::OmpEndBlockDirective &x) { // constructs unless a nowait clause is specified. Only OMPD_end_single and // end_workshareare popped as they are pushed while entering the // EndBlockDirective. -void OmpStructureChecker::Leave(const parser::OmpEndBlockDirective &x) { +void OmpStructureChecker::Leave(const parser::OmpEndDirective &x) { if ((GetContext().directive == llvm::omp::Directive::OMPD_end_scope) || (GetContext().directive == llvm::omp::Directive::OMPD_end_single) || (GetContext().directive == llvm::omp::Directive::OMPD_end_workshare)) { @@ -4028,7 +4022,11 @@ void OmpStructureChecker::Enter(const parser::OmpClause::HasDeviceAddr &x) { void OmpStructureChecker::Enter(const parser::OmpClause::Enter &x) { CheckAllowedClause(llvm::omp::Clause::OMPC_enter); - const parser::OmpObjectList &objList{x.v}; + if (!OmpVerifyModifiers( + x.v, llvm::omp::OMPC_enter, GetContext().clauseSource, context_)) { + return; + } + const parser::OmpObjectList &objList{std::get<parser::OmpObjectList>(x.v.t)}; SymbolSourceMap symbols; GetSymbolsInObjectList(objList, symbols); for (const auto &[symbol, source] : symbols) { @@ -4352,11 +4350,8 @@ bool OmpStructureChecker::CheckTargetBlockOnlyTeams( parser::Unwrap<parser::OpenMPConstruct>(*it)}) { if (const auto *ompBlockConstruct{ std::get_if<parser::OpenMPBlockConstruct>(&ompConstruct->u)}) { - const auto &beginBlockDir{ - std::get<parser::OmpBeginBlockDirective>(ompBlockConstruct->t)}; - const auto &beginDir{ - std::get<parser::OmpBlockDirective>(beginBlockDir.t)}; - if (beginDir.v == llvm::omp::Directive::OMPD_teams) { + llvm::omp::Directive dirId{ompBlockConstruct->BeginDir().DirId()}; + if (dirId == llvm::omp::Directive::OMPD_teams) { nestedTeams = true; } } @@ -4402,11 +4397,7 @@ void OmpStructureChecker::CheckWorkshareBlockStmts( auto currentDir{llvm::omp::Directive::OMPD_unknown}; if (const auto *ompBlockConstruct{ std::get_if<parser::OpenMPBlockConstruct>(&ompConstruct->u)}) { - const auto &beginBlockDir{ - std::get<parser::OmpBeginBlockDirective>(ompBlockConstruct->t)}; - const auto &beginDir{ - std::get<parser::OmpBlockDirective>(beginBlockDir.t)}; - currentDir = beginDir.v; + currentDir = ompBlockConstruct->BeginDir().DirId(); } else if (const auto *ompLoopConstruct{ std::get_if<parser::OpenMPLoopConstruct>( &ompConstruct->u)}) { @@ -4488,17 +4479,18 @@ const parser::OmpObjectList *OmpStructureChecker::GetOmpObjectList( const parser::OmpClause &clause) { // Clauses with OmpObjectList as its data member - using MemberObjectListClauses = std::tuple<parser::OmpClause::Copyprivate, - parser::OmpClause::Copyin, parser::OmpClause::Enter, - parser::OmpClause::Firstprivate, parser::OmpClause::Link, - parser::OmpClause::Private, parser::OmpClause::Shared, - parser::OmpClause::UseDevicePtr, parser::OmpClause::UseDeviceAddr>; + using MemberObjectListClauses = + std::tuple<parser::OmpClause::Copyprivate, parser::OmpClause::Copyin, + parser::OmpClause::Firstprivate, parser::OmpClause::Link, + parser::OmpClause::Private, parser::OmpClause::Shared, + parser::OmpClause::UseDevicePtr, parser::OmpClause::UseDeviceAddr>; // Clauses with OmpObjectList in the tuple - using TupleObjectListClauses = std::tuple<parser::OmpClause::Aligned, - parser::OmpClause::Allocate, parser::OmpClause::From, - parser::OmpClause::Lastprivate, parser::OmpClause::Map, - parser::OmpClause::Reduction, parser::OmpClause::To>; + using TupleObjectListClauses = + std::tuple<parser::OmpClause::Aligned, parser::OmpClause::Allocate, + parser::OmpClause::From, parser::OmpClause::Lastprivate, + parser::OmpClause::Map, parser::OmpClause::Reduction, + parser::OmpClause::To, parser::OmpClause::Enter>; // TODO:: Generate the tuples using TableGen. // Handle other constructs with OmpObjectList such as OpenMPThreadprivate. |