@@ -1708,26 +1708,46 @@ void OmpAttributeVisitor::ResolveSeqLoopIndexInParallelOrTaskConstruct(
17081708// Use of DO CONCURRENT inside OpenMP construct is unspecified behavior
17091709// till OpenMP-5.0 standard.
17101710// In above both cases we skip the privatization of iteration variables.
1711+ // [OpenMP 5.1] DO CONCURRENT indices are private
17111712bool OmpAttributeVisitor::Pre (const parser::DoConstruct &x) {
1712- // TODO:[OpenMP 5.1] DO CONCURRENT indices are private
1713- if (x. IsDoNormal ()) {
1714- if (!dirContext_. empty () && GetContext (). withinConstruct ) {
1713+ if (!dirContext_. empty () && GetContext (). withinConstruct ) {
1714+ llvm::SmallVector< const parser::Name *> ivs;
1715+ if (x. IsDoNormal () ) {
17151716 const parser::Name *iv{GetLoopIndex (x)};
1716- if (iv && iv->symbol ) {
1717- if (!iv->symbol ->test (Symbol::Flag::OmpPreDetermined)) {
1718- ResolveSeqLoopIndexInParallelOrTaskConstruct (*iv);
1719- } else {
1720- // TODO: conflict checks with explicitly determined DSA
1721- }
1722- ordCollapseLevel--;
1723- if (ordCollapseLevel) {
1724- if (const auto *details{iv->symbol ->detailsIf <HostAssocDetails>()}) {
1725- const Symbol *tpSymbol = &details->symbol ();
1726- if (tpSymbol->test (Symbol::Flag::OmpThreadprivate)) {
1727- context_.Say (iv->source ,
1728- " Loop iteration variable %s is not allowed in THREADPRIVATE." _err_en_US,
1729- iv->ToString ());
1730- }
1717+ if (iv && iv->symbol )
1718+ ivs.push_back (iv);
1719+ } else if (x.IsDoConcurrent ()) {
1720+ const Fortran::parser::LoopControl *loopControl = &*x.GetLoopControl ();
1721+ const Fortran::parser::LoopControl::Concurrent &concurrent =
1722+ std::get<Fortran::parser::LoopControl::Concurrent>(loopControl->u );
1723+ const Fortran::parser::ConcurrentHeader &concurrentHeader =
1724+ std::get<Fortran::parser::ConcurrentHeader>(concurrent.t );
1725+ const std::list<Fortran::parser::ConcurrentControl> &controls =
1726+ std::get<std::list<Fortran::parser::ConcurrentControl>>(
1727+ concurrentHeader.t );
1728+ for (const auto &control : controls) {
1729+ const parser::Name *iv{&std::get<0 >(control.t )};
1730+ if (iv && iv->symbol )
1731+ ivs.push_back (iv);
1732+ }
1733+ }
1734+ ordCollapseLevel--;
1735+ for (auto iv : ivs) {
1736+ if (!iv->symbol ->test (Symbol::Flag::OmpPreDetermined)) {
1737+ ResolveSeqLoopIndexInParallelOrTaskConstruct (*iv);
1738+ } else {
1739+ // TODO: conflict checks with explicitly determined DSA
1740+ }
1741+ if (ordCollapseLevel) {
1742+ if (const auto *details{iv->symbol ->detailsIf <HostAssocDetails>()}) {
1743+ const Symbol *tpSymbol = &details->symbol ();
1744+ // TODO: DoConcurrent won't capture the following check because a new
1745+ // symbol is declared in ResolveIndexName(), which will not have the
1746+ // OmpThreadprivate flag.
1747+ if (tpSymbol->test (Symbol::Flag::OmpThreadprivate)) {
1748+ context_.Say (iv->source ,
1749+ " Loop iteration variable %s is not allowed in THREADPRIVATE." _err_en_US,
1750+ iv->ToString ());
17311751 }
17321752 }
17331753 }
0 commit comments