diff options
Diffstat (limited to 'flang/lib/Semantics/check-omp-structure.cpp')
-rw-r--r-- | flang/lib/Semantics/check-omp-structure.cpp | 40 |
1 files changed, 37 insertions, 3 deletions
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index 95b962f..6db43cf6 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -614,6 +614,14 @@ void OmpStructureChecker::Leave(const parser::OpenMPConstruct &) { deferredNonVariables_.clear(); } +void OmpStructureChecker::Enter(const parser::OpenMPDeclarativeConstruct &x) { + EnterDirectiveNest(DeclarativeNest); +} + +void OmpStructureChecker::Leave(const parser::OpenMPDeclarativeConstruct &x) { + ExitDirectiveNest(DeclarativeNest); +} + void OmpStructureChecker::Enter(const parser::OpenMPLoopConstruct &x) { loopStack_.push_back(&x); const auto &beginLoopDir{std::get<parser::OmpBeginLoopDirective>(x.t)}; @@ -1481,11 +1489,24 @@ void OmpStructureChecker::Leave(const parser::OpenMPRequiresConstruct &) { dirContext_.pop_back(); } +void OmpStructureChecker::CheckAlignValue(const parser::OmpClause &clause) { + if (auto *align{std::get_if<parser::OmpClause::Align>(&clause.u)}) { + if (const auto &v{GetIntValue(align->v)}; !v || *v <= 0) { + context_.Say(clause.source, + "The alignment value should be a constant positive integer"_err_en_US); + } + } +} + void OmpStructureChecker::Enter(const parser::OpenMPDeclarativeAllocate &x) { isPredefinedAllocator = true; const auto &dir{std::get<parser::Verbatim>(x.t)}; const auto &objectList{std::get<parser::OmpObjectList>(x.t)}; PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_allocate); + const auto &clauseList{std::get<parser::OmpClauseList>(x.t)}; + for (const auto &clause : clauseList.v) { + CheckAlignValue(clause); + } CheckIsVarPartOfAnotherVar(dir.source, objectList); } @@ -1688,20 +1709,34 @@ void OmpStructureChecker::Leave(const parser::OpenMPDeclareTargetConstruct &x) { dirContext_.pop_back(); } -void OmpStructureChecker::Enter(const parser::OpenMPErrorConstruct &x) { +void OmpStructureChecker::Enter(const parser::OmpErrorDirective &x) { const auto &dir{std::get<parser::Verbatim>(x.t)}; PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_error); } -void OmpStructureChecker::Leave(const parser::OpenMPErrorConstruct &x) { +void OmpStructureChecker::Leave(const parser::OmpErrorDirective &x) { dirContext_.pop_back(); } +void OmpStructureChecker::Enter(const parser::OmpClause::At &x) { + CheckAllowedClause(llvm::omp::Clause::OMPC_at); + if (GetDirectiveNest(DeclarativeNest) > 0) { + if (x.v.v == parser::OmpAtClause::ActionTime::Execution) { + context_.Say(GetContext().clauseSource, + "The ERROR directive with AT(EXECUTION) cannot appear in the specification part"_err_en_US); + } + } +} + void OmpStructureChecker::Enter(const parser::OpenMPExecutableAllocate &x) { isPredefinedAllocator = true; const auto &dir{std::get<parser::Verbatim>(x.t)}; const auto &objectList{std::get<std::optional<parser::OmpObjectList>>(x.t)}; PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_allocate); + const auto &clauseList{std::get<parser::OmpClauseList>(x.t)}; + for (const auto &clause : clauseList.v) { + CheckAlignValue(clause); + } if (objectList) { CheckIsVarPartOfAnotherVar(dir.source, *objectList); } @@ -2856,7 +2891,6 @@ CHECK_SIMPLE_CLAUSE(Init, OMPC_init) CHECK_SIMPLE_CLAUSE(Use, OMPC_use) CHECK_SIMPLE_CLAUSE(Novariants, OMPC_novariants) CHECK_SIMPLE_CLAUSE(Nocontext, OMPC_nocontext) -CHECK_SIMPLE_CLAUSE(At, OMPC_at) CHECK_SIMPLE_CLAUSE(Severity, OMPC_severity) CHECK_SIMPLE_CLAUSE(Message, OMPC_message) CHECK_SIMPLE_CLAUSE(Filter, OMPC_filter) |