@@ -145,7 +145,7 @@ class OmpWorkshareBlockChecker {
145145
146146// 'OmpWorkdistributeBlockChecker' is used to check the validity of the
147147// assignment statements and the expressions enclosed in an OpenMP
148- // workdistribute construct
148+ // WORKDISTRIBUTE construct
149149class OmpWorkdistributeBlockChecker {
150150public:
151151 OmpWorkdistributeBlockChecker (
@@ -165,34 +165,31 @@ class OmpWorkdistributeBlockChecker {
165165 lhs->GetType (), lhs->Rank (), rhs->GetType (), rhs->Rank ())};
166166 if (isDefined == Tristate::Yes) {
167167 context_.Say (expr.source ,
168- " Defined assignment statement is not "
169- " allowed in a WORKDISTRIBUTE construct" _err_en_US);
168+ " Defined assignment statement is not allowed in a WORKDISTRIBUTE construct" _err_en_US);
170169 }
171170 }
172171 return true ;
173172 }
174173
175174 bool Pre (const parser::Expr &expr) {
176175 if (const auto *e{GetExpr (context_, expr)}) {
176+ if (!e)
177+ return false ;
177178 for (const Symbol &symbol : evaluate::CollectSymbols (*e)) {
178179 const Symbol &root{GetAssociationRoot (symbol)};
179180 if (IsFunction (root)) {
180- std::string attrs{ " " } ;
181+ std::vector<std:: string> attrs;
181182 if (!IsElementalProcedure (root)) {
182- attrs = " non-ELEMENTAL" ;
183+ attrs. push_back ( " non-ELEMENTAL" ) ;
183184 }
184185 if (root.attrs ().test (Attr::IMPURE)) {
185- if (attrs != " " ) {
186- attrs = " ," + attrs;
187- }
188- attrs = " IMPURE" + attrs;
189- }
190- if (attrs != " " ) {
191- context_.Say (expr.source ,
192- " User defined%s function '%s' is not allowed in a "
193- " WORKDISTRIBUTE construct" _err_en_US,
194- attrs, root.name ());
186+ attrs.push_back (" IMPURE" );
195187 }
188+ std::string attrsStr =
189+ attrs.empty () ? " " : " " + llvm::join (attrs, " , " );
190+ context_.Say (expr.source ,
191+ " User defined%s function '%s' is not allowed in a WORKDISTRIBUTE construct" _err_en_US,
192+ attrsStr, root.name ());
196193 }
197194 }
198195 }
@@ -879,8 +876,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPBlockConstruct &x) {
879876 if (GetContext ().directive == llvm::omp::Directive::OMPD_workdistribute &&
880877 GetContextParent ().directive != llvm::omp::Directive::OMPD_teams) {
881878 context_.Say (x.BeginDir ().DirName ().source ,
882- " %s region can only be strictly nested within the "
883- " teams region" _err_en_US,
879+ " %s region can only be strictly nested within TEAMS region" _err_en_US,
884880 ContextDirectiveAsFortran ());
885881 }
886882 }
@@ -969,7 +965,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPBlockConstruct &x) {
969965 case llvm::omp::OMPD_workdistribute:
970966 if (!CurrentDirectiveIsNested ()) {
971967 context_.Say (beginSpec.source ,
972- " A workdistribute region must be nested inside teams region only." _err_en_US);
968+ " A WORKDISTRIBUTE region must be nested inside TEAMS region only." _err_en_US);
973969 }
974970 CheckWorkdistributeBlockStmts (block, beginSpec.source );
975971 break ;
@@ -4627,16 +4623,19 @@ void OmpStructureChecker::CheckWorkshareBlockStmts(
46274623
46284624void OmpStructureChecker::CheckWorkdistributeBlockStmts (
46294625 const parser::Block &block, parser::CharBlock source) {
4626+ unsigned version{context_.langOptions ().OpenMPVersion };
4627+ if (version < 60 )
4628+ context_.Say (source,
4629+ " WORKDISTRIBUTE construct is only supported from openMP 6.0" _err_en_US);
4630+
46304631 OmpWorkdistributeBlockChecker ompWorkdistributeBlockChecker{context_, source};
46314632
46324633 for (auto it{block.begin ()}; it != block.end (); ++it) {
46334634 if (parser::Unwrap<parser::AssignmentStmt>(*it)) {
46344635 parser::Walk (*it, ompWorkdistributeBlockChecker);
46354636 } else {
46364637 context_.Say (source,
4637- " The structured block in a WORKDISTRIBUTE construct may consist of "
4638- " only "
4639- " SCALAR or ARRAY assignments" _err_en_US);
4638+ " The structured block in a WORKDISTRIBUTE construct may consist of only SCALAR or ARRAY assignments" _err_en_US);
46404639 }
46414640 }
46424641}
0 commit comments