@@ -495,6 +495,12 @@ template <typename Checker> struct DirectiveSpellingVisitor {
495495 template <typename T> bool Pre (const T &) { return true ; }
496496 template <typename T> void Post (const T &) {}
497497
498+ template <typename ... Ts>
499+ static const parser::OmpDirectiveName &GetDirName (
500+ const std::tuple<Ts...> &t) {
501+ return std::get<parser::OmpDirectiveSpecification>(t).DirName ();
502+ }
503+
498504 bool Pre (const parser::OmpSectionsDirective &x) {
499505 checker_ (x.source , x.v );
500506 return false ;
@@ -520,8 +526,7 @@ template <typename Checker> struct DirectiveSpellingVisitor {
520526 return false ;
521527 }
522528 bool Pre (const parser::OpenMPAllocatorsConstruct &x) {
523- checker_ (
524- std::get<parser::Verbatim>(x.t ).source , Directive::OMPD_allocators);
529+ checker_ (GetDirName (x.t ).source , Directive::OMPD_allocators);
525530 return false ;
526531 }
527532 bool Pre (const parser::OmpAssumeDirective &x) {
@@ -1657,26 +1662,45 @@ void OmpStructureChecker::Leave(const parser::OpenMPExecutableAllocate &x) {
16571662
16581663void OmpStructureChecker::Enter (const parser::OpenMPAllocatorsConstruct &x) {
16591664 isPredefinedAllocator = true ;
1660- const auto &dir{std::get<parser::Verbatim>(x.t )};
1661- PushContextAndClauseSets (dir.source , llvm::omp::Directive::OMPD_allocators);
1662- const auto &clauseList{std::get<parser::OmpClauseList>(x.t )};
1663- for (const auto &clause : clauseList.v ) {
1665+
1666+ auto &dirSpec{std::get<parser::OmpDirectiveSpecification>(x.t )};
1667+ auto &block{std::get<parser::Block>(x.t )};
1668+ PushContextAndClauseSets (
1669+ dirSpec.DirName ().source , llvm::omp::Directive::OMPD_allocators);
1670+
1671+ if (block.empty ()) {
1672+ context_.Say (dirSpec.source ,
1673+ " The ALLOCATORS construct should contain a single ALLOCATE statement" _err_en_US);
1674+ return ;
1675+ }
1676+
1677+ omp::SourcedActionStmt action{omp::GetActionStmt (block)};
1678+ const auto *allocate{
1679+ action ? parser::Unwrap<parser::AllocateStmt>(action.stmt ) : nullptr };
1680+
1681+ if (!allocate) {
1682+ const parser::CharBlock &source = action ? action.source : x.source ;
1683+ context_.Say (source,
1684+ " The body of the ALLOCATORS construct should be an ALLOCATE statement" _err_en_US);
1685+ }
1686+
1687+ for (const auto &clause : dirSpec.Clauses ().v ) {
16641688 if (const auto *allocClause{
16651689 parser::Unwrap<parser::OmpClause::Allocate>(clause)}) {
16661690 CheckVarIsNotPartOfAnotherVar (
1667- dir .source , std::get<parser::OmpObjectList>(allocClause->v .t ));
1691+ dirSpec .source , std::get<parser::OmpObjectList>(allocClause->v .t ));
16681692 }
16691693 }
16701694}
16711695
16721696void OmpStructureChecker::Leave (const parser::OpenMPAllocatorsConstruct &x) {
1673- const auto &dir {std::get<parser::Verbatim >(x.t )};
1674- const auto &clauseList{std::get<parser::OmpClauseList>(x. t )};
1675- for (const auto &clause : clauseList .v ) {
1697+ auto &dirSpec {std::get<parser::OmpDirectiveSpecification >(x.t )};
1698+
1699+ for (const auto &clause : dirSpec. Clauses () .v ) {
16761700 if (const auto *allocClause{
16771701 std::get_if<parser::OmpClause::Allocate>(&clause.u )}) {
16781702 CheckPredefinedAllocatorRestriction (
1679- dir .source , std::get<parser::OmpObjectList>(allocClause->v .t ));
1703+ dirSpec .source , std::get<parser::OmpObjectList>(allocClause->v .t ));
16801704 }
16811705 }
16821706 dirContext_.pop_back ();
0 commit comments