diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -2265,6 +2265,13 @@ EndOpenMP(); } void Unparse(const OpenMPExecutableAllocate &x) { + auto &optionalList{ + std::get>>(x.t)}; + if (optionalList.has_value()) { + for (auto &declarativeAllocate : optionalList.value()) { + Walk(declarativeAllocate); + } + } BeginOpenMP(); Word("!$OMP ALLOCATE"); Walk(" (", std::get>(x.t), ")"); diff --git a/flang/lib/Semantics/rewrite-parse-tree.cpp b/flang/lib/Semantics/rewrite-parse-tree.cpp --- a/flang/lib/Semantics/rewrite-parse-tree.cpp +++ b/flang/lib/Semantics/rewrite-parse-tree.cpp @@ -15,6 +15,7 @@ #include "flang/Semantics/semantics.h" #include "flang/Semantics/symbol.h" #include "flang/Semantics/tools.h" +#include #include namespace Fortran::semantics { @@ -40,9 +41,11 @@ void Post(parser::Name &); void Post(parser::SpecificationPart &); bool Pre(parser::ExecutionPart &); + void Post(parser::ExecutionPart &); void Post(parser::IoUnit &); void Post(parser::ReadStmt &); void Post(parser::WriteStmt &); + void Post(parser::ExecutionPartConstruct &); // Name resolution yet implemented: // TODO: Can some/all of these now be enabled? @@ -68,6 +71,11 @@ bool errorOnUnresolvedName_{true}; parser::Messages &messages_; std::list stmtFuncsToConvert_; + using execPartType = common::Reference; + using execPartPair = std::pair; + std::list executableOmpAllocateCandidates; + std::list movedExecutableOmpAllocateCandidates; + int executionPartIndex{0}; }; // Check that name has been resolved to a symbol @@ -106,9 +114,54 @@ parser::ExecutableConstruct{std::move(stmt)}}); } stmtFuncsToConvert_.clear(); + executionPartIndex = 0; return true; } +void RewriteMutator::Post(parser::ExecutionPart &x) { + auto it{x.v.begin()}; + int previousExecutableCandidate{0}; + for (auto &executableCandidate : movedExecutableOmpAllocateCandidates) { + std::advance(it, executableCandidate - previousExecutableCandidate); + x.v.erase(it++); + previousExecutableCandidate = executableCandidate + 1; + } + movedExecutableOmpAllocateCandidates.clear(); +} + +void RewriteMutator::Post(parser::ExecutionPartConstruct &x) { + auto *declarativeAllocate{ + parser::Unwrap(x)}; + auto *executableAllocate{parser::Unwrap(x)}; + if (declarativeAllocate) { + executableOmpAllocateCandidates.push_back( + execPartPair{x, executionPartIndex}); + + } else if (executableAllocate && + std::get>(executableAllocate->t) + .has_value() && + executableOmpAllocateCandidates.size() > 0) { + auto &declarativeList{ + std::get>>( + executableAllocate->t)}; + // OpenMPExecutable allocate's list of child declaratives is an optional so + // this list needs to be set here + declarativeList = std::list(); + for (auto &executableCandidate : executableOmpAllocateCandidates) { + auto *declarativeCandidate{ + parser::Unwrap( + *(std::get<0>(executableCandidate)))}; + declarativeList.value().push_back(std::move(*declarativeCandidate)); + movedExecutableOmpAllocateCandidates.push_back( + std::get<1>(executableCandidate)); + } + executableOmpAllocateCandidates.clear(); + } else { + executableOmpAllocateCandidates.clear(); + } + ++executionPartIndex; +} + // Convert a syntactically ambiguous io-unit internal-file-variable to a // file-unit-number. void RewriteMutator::Post(parser::IoUnit &x) {