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/canonicalize-omp.cpp b/flang/lib/Semantics/canonicalize-omp.cpp --- a/flang/lib/Semantics/canonicalize-omp.cpp +++ b/flang/lib/Semantics/canonicalize-omp.cpp @@ -7,7 +7,9 @@ //===----------------------------------------------------------------------===// #include "canonicalize-omp.h" +#include "flang/Common/reference.h" #include "flang/Parser/parse-tree-visitor.h" +#include "flang/Parser/tools.h" // After Loop Canonicalization, rewrite OpenMP parse tree to make OpenMP // Constructs more structured which provide explicit scopes for later @@ -46,6 +48,56 @@ } // Block list } + bool Pre(parser::ExecutionPart &x) { + executionPartIndex = 0; + return true; + } + + void 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 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; + } + private: template T *GetConstructIf(parser::ExecutionPartConstruct &x) { if (auto *y{std::get_if(&x.u)}) { @@ -106,6 +158,12 @@ parser::ToUpperCaseLetters(dir.source.ToString())); } + using execPartPair = + std::pair, int>; + std::list executableOmpAllocateCandidates; + std::list movedExecutableOmpAllocateCandidates; + int executionPartIndex{0}; + parser::Messages &messages_; };