@@ -1796,10 +1796,13 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPLoopConstruct &x) {
17961796 SetContextAssociatedLoopLevel (GetAssociatedLoopLevelFromClauses (clauseList));
17971797
17981798 if (beginDir.v == llvm::omp::Directive::OMPD_do) {
1799- if (const auto &doConstruct{
1800- std::get<std::optional<parser::DoConstruct>>(x.t )}) {
1801- if (doConstruct.value ().IsDoWhile ()) {
1802- return true ;
1799+ auto &optLoopCons = std::get<1 >(x.t );
1800+ if (optLoopCons.has_value ()) {
1801+ if (const auto &doConstruct{
1802+ std::get_if<parser::DoConstruct>(&*optLoopCons)}) {
1803+ if (doConstruct->IsDoWhile ()) {
1804+ return true ;
1805+ }
18031806 }
18041807 }
18051808 }
@@ -1962,48 +1965,64 @@ void OmpAttributeVisitor::PrivatizeAssociatedLoopIndexAndCheckLoopLevel(
19621965 bool hasCollapseClause{
19631966 clause ? (clause->Id () == llvm::omp::OMPC_collapse) : false };
19641967
1965- const auto &outer{std::get<std::optional<parser::DoConstruct>>(x.t )};
1966- if (outer.has_value ()) {
1967- for (const parser::DoConstruct *loop{&*outer}; loop && level > 0 ; --level) {
1968- if (loop->IsDoConcurrent ()) {
1969- // DO CONCURRENT is explicitly allowed for the LOOP construct so long as
1970- // there isn't a COLLAPSE clause
1971- if (isLoopConstruct) {
1972- if (hasCollapseClause) {
1973- // hasCollapseClause implies clause != nullptr
1974- context_.Say (clause->source ,
1975- " DO CONCURRENT loops cannot be used with the COLLAPSE clause." _err_en_US);
1968+ auto &optLoopCons = std::get<1 >(x.t );
1969+ if (optLoopCons.has_value ()) {
1970+ if (const auto &outer{std::get_if<parser::DoConstruct>(&*optLoopCons)}) {
1971+ for (const parser::DoConstruct *loop{&*outer}; loop && level > 0 ; --level) {
1972+ if (loop->IsDoConcurrent ()) {
1973+ // DO CONCURRENT is explicitly allowed for the LOOP construct so long as
1974+ // there isn't a COLLAPSE clause
1975+ if (isLoopConstruct) {
1976+ if (hasCollapseClause) {
1977+ // hasCollapseClause implies clause != nullptr
1978+ context_.Say (clause->source ,
1979+ " DO CONCURRENT loops cannot be used with the COLLAPSE clause." _err_en_US);
1980+ }
1981+ } else {
1982+ auto &stmt =
1983+ std::get<parser::Statement<parser::NonLabelDoStmt>>(loop->t );
1984+ context_.Say (stmt.source ,
1985+ " DO CONCURRENT loops cannot form part of a loop nest." _err_en_US);
19761986 }
1977- } else {
1978- auto &stmt =
1979- std::get<parser::Statement<parser::NonLabelDoStmt>>(loop->t );
1980- context_.Say (stmt.source ,
1981- " DO CONCURRENT loops cannot form part of a loop nest." _err_en_US);
1982- }
1983- }
1984- // go through all the nested do-loops and resolve index variables
1985- const parser::Name *iv{GetLoopIndex (*loop)};
1986- if (iv) {
1987- if (auto *symbol{ResolveOmp (*iv, ivDSA, currScope ())}) {
1988- SetSymbolDSA (*symbol, {Symbol::Flag::OmpPreDetermined, ivDSA});
1989- iv->symbol = symbol; // adjust the symbol within region
1990- AddToContextObjectWithDSA (*symbol, ivDSA);
19911987 }
1988+ // go through all the nested do-loops and resolve index variables
1989+ const parser::Name *iv{GetLoopIndex (*loop)};
1990+ if (iv) {
1991+ if (auto *symbol{ResolveOmp (*iv, ivDSA, currScope ())}) {
1992+ SetSymbolDSA (*symbol, {Symbol::Flag::OmpPreDetermined, ivDSA});
1993+ iv->symbol = symbol; // adjust the symbol within region
1994+ AddToContextObjectWithDSA (*symbol, ivDSA);
1995+ }
19921996
1993- const auto &block{std::get<parser::Block>(loop->t )};
1994- const auto it{block.begin ()};
1995- loop = it != block.end () ? GetDoConstructIf (*it) : nullptr ;
1997+ const auto &block{std::get<parser::Block>(loop->t )};
1998+ const auto it{block.begin ()};
1999+ loop = it != block.end () ? GetDoConstructIf (*it) : nullptr ;
2000+ }
2001+ }
2002+ CheckAssocLoopLevel (level, GetAssociatedClause ());
2003+ } else if (const auto &loop{std::get_if<common::Indirection<parser::OpenMPLoopConstruct>>(&*optLoopCons)}) {
2004+ auto &beginDirective =
2005+ std::get<parser::OmpBeginLoopDirective>(loop->value ().t );
2006+ auto &beginLoopDirective =
2007+ std::get<parser::OmpLoopDirective>(beginDirective.t );
2008+ if ((beginLoopDirective.v != llvm::omp::Directive::OMPD_unroll &&
2009+ beginLoopDirective.v != llvm::omp::Directive::OMPD_tile)) {
2010+ context_.Say (GetContext ().directiveSource ,
2011+ " Only UNROLL or TILE constructs are allowed between an OpenMP Loop Construct and a DO construct" _err_en_US,
2012+ parser::ToUpperCaseLetters (llvm::omp::getOpenMPDirectiveName (GetContext ().directive , version).str ()));
2013+ } else {
2014+ PrivatizeAssociatedLoopIndexAndCheckLoopLevel (loop->value ());
19962015 }
2016+ } else {
2017+ context_.Say (GetContext ().directiveSource ,
2018+ " A DO loop must follow the %s directive" _err_en_US,
2019+ parser::ToUpperCaseLetters (
2020+ llvm::omp::getOpenMPDirectiveName (GetContext ().directive , version)
2021+ .str ()));
19972022 }
1998- CheckAssocLoopLevel (level, GetAssociatedClause ());
1999- } else {
2000- context_.Say (GetContext ().directiveSource ,
2001- " A DO loop must follow the %s directive" _err_en_US,
2002- parser::ToUpperCaseLetters (
2003- llvm::omp::getOpenMPDirectiveName (GetContext ().directive , version)
2004- .str ()));
20052023 }
20062024}
2025+
20072026void OmpAttributeVisitor::CheckAssocLoopLevel (
20082027 std::int64_t level, const parser::OmpClause *clause) {
20092028 if (clause && level != 0 ) {
0 commit comments