diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index e2f8796aeb5e7..be10669ac2536 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -1562,20 +1562,11 @@ void OmpStructureChecker::Leave(const parser::OpenMPRequiresConstruct &) { dirContext_.pop_back(); } -void OmpStructureChecker::CheckAlignValue(const parser::OmpClause &clause) { - if (auto *align{std::get_if(&clause.u)}) { - if (const auto &v{GetIntValue(align->v)}; v && *v <= 0) { - context_.Say(clause.source, "The alignment should be positive"_err_en_US); - } - } -} - void OmpStructureChecker::Enter(const parser::OpenMPDeclarativeAllocate &x) { isPredefinedAllocator = true; const auto &dir{std::get(x.t)}; const auto &objectList{std::get(x.t)}; PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_allocate); - const auto &clauseList{std::get(x.t)}; SymbolSourceMap currSymbols; GetSymbolsInObjectList(objectList, currSymbols); for (auto &[symbol, source] : currSymbols) { @@ -1598,9 +1589,6 @@ void OmpStructureChecker::Enter(const parser::OpenMPDeclarativeAllocate &x) { source.ToString()); } } - for (const auto &clause : clauseList.v) { - CheckAlignValue(clause); - } CheckVarIsNotPartOfAnotherVar(dir.source, objectList); } @@ -2007,9 +1995,6 @@ void OmpStructureChecker::Enter(const parser::OpenMPExecutableAllocate &x) { isPredefinedAllocator = true; const auto &objectList{std::get>(x.t)}; - for (const auto &clause : clauseList.v) { - CheckAlignValue(clause); - } if (objectList) { CheckVarIsNotPartOfAnotherVar(dir.source, *objectList); } @@ -3234,7 +3219,6 @@ CHECK_SIMPLE_CLAUSE(AdjustArgs, OMPC_adjust_args) CHECK_SIMPLE_CLAUSE(AppendArgs, OMPC_append_args) CHECK_SIMPLE_CLAUSE(MemoryOrder, OMPC_memory_order) CHECK_SIMPLE_CLAUSE(Bind, OMPC_bind) -CHECK_SIMPLE_CLAUSE(Align, OMPC_align) CHECK_SIMPLE_CLAUSE(Compare, OMPC_compare) CHECK_SIMPLE_CLAUSE(OmpxAttribute, OMPC_ompx_attribute) CHECK_SIMPLE_CLAUSE(Weak, OMPC_weak) @@ -3898,6 +3882,19 @@ void OmpStructureChecker::CheckIsLoopIvPartOfClause( } } +void OmpStructureChecker::Enter(const parser::OmpClause::Align &x) { + CheckAllowedClause(llvm::omp::Clause::OMPC_align); + if (const auto &v{GetIntValue(x.v.v)}) { + if (*v <= 0) { + context_.Say(GetContext().clauseSource, + "The alignment should be positive"_err_en_US); + } else if (!llvm::isPowerOf2_64(*v)) { + context_.Say(GetContext().clauseSource, + "The alignment should be a power of 2"_err_en_US); + } + } +} + // Restrictions specific to each clause are implemented apart from the // generalized restrictions. void OmpStructureChecker::Enter(const parser::OmpClause::Aligned &x) { diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h index 543642ff322aa..4cb0b743107d2 100644 --- a/flang/lib/Semantics/check-omp-structure.h +++ b/flang/lib/Semantics/check-omp-structure.h @@ -347,8 +347,6 @@ class OmpStructureChecker void CheckAllowedRequiresClause(llvmOmpClause clause); bool deviceConstructFound_{false}; - void CheckAlignValue(const parser::OmpClause &); - void AddEndDirectiveClauses(const parser::OmpClauseList &clauses); void EnterDirectiveNest(const int index) { directiveNest_[index]++; } diff --git a/flang/test/Semantics/OpenMP/align-clause.f90 b/flang/test/Semantics/OpenMP/align-clause.f90 new file mode 100644 index 0000000000000..2638eece144c7 --- /dev/null +++ b/flang/test/Semantics/OpenMP/align-clause.f90 @@ -0,0 +1,20 @@ +!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=51 + +subroutine f00(y) + integer :: x(10), y + !ERROR: Must be a constant value + !$omp allocate(x) align(y) +end + +subroutine f01() + integer :: x(10) + !ERROR: The alignment should be a power of 2 + !$omp allocate(x) align(7) +end + +subroutine f02() + integer :: x(10) + !ERROR: The alignment should be positive + !$omp allocate(x) align(-8) +end +