@@ -1708,26 +1708,46 @@ void OmpAttributeVisitor::ResolveSeqLoopIndexInParallelOrTaskConstruct(
1708
1708
// Use of DO CONCURRENT inside OpenMP construct is unspecified behavior
1709
1709
// till OpenMP-5.0 standard.
1710
1710
// In above both cases we skip the privatization of iteration variables.
1711
+ // [OpenMP 5.1] DO CONCURRENT indices are private
1711
1712
bool 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 () ) {
1715
1716
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 ());
1731
1751
}
1732
1752
}
1733
1753
}
0 commit comments