|
15 | 15 | #include "flang/Common/indirection.h" |
16 | 16 | #include "flang/Common/template.h" |
17 | 17 | #include "flang/Common/visit.h" |
| 18 | +#include "flang/Parser/tools.h" |
18 | 19 |
|
19 | 20 | #include <tuple> |
20 | 21 | #include <type_traits> |
@@ -58,6 +59,63 @@ const DoConstruct *GetDoConstruct(const ExecutionPartConstruct &x) { |
58 | 59 | return nullptr; |
59 | 60 | } |
60 | 61 |
|
| 62 | +// Get the Label from a Statement<...> contained in an ExecutionPartConstruct, |
| 63 | +// or std::nullopt, if there is no Statement<...> contained in there. |
| 64 | +template <typename T> |
| 65 | +static std::optional<Label> GetStatementLabelHelper(const T &stmt) { |
| 66 | + if constexpr (IsStatement<T>::value) { |
| 67 | + return stmt.label; |
| 68 | + } else if constexpr (WrapperTrait<T>) { |
| 69 | + return GetStatementLabelHelper(stmt.v); |
| 70 | + } else if constexpr (UnionTrait<T>) { |
| 71 | + return common::visit( |
| 72 | + [&](auto &&s) { return GetStatementLabelHelper(s); }, stmt.u); |
| 73 | + } |
| 74 | + return std::nullopt; |
| 75 | +} |
| 76 | + |
| 77 | +std::optional<Label> GetStatementLabel(const ExecutionPartConstruct &x) { |
| 78 | + return GetStatementLabelHelper(x); |
| 79 | +} |
| 80 | + |
| 81 | +static std::optional<Label> GetFinalLabel(const Block &x) { |
| 82 | + if (!x.empty()) { |
| 83 | + const ExecutionPartConstruct &last{x.back()}; |
| 84 | + if (auto *omp{Unwrap<OpenMPConstruct>(last)}) { |
| 85 | + return GetFinalLabel(*omp); |
| 86 | + } else if (auto *doLoop{Unwrap<DoConstruct>(last)}) { |
| 87 | + return GetFinalLabel(std::get<Block>(doLoop->t)); |
| 88 | + } else { |
| 89 | + return GetStatementLabel(x.back()); |
| 90 | + } |
| 91 | + } else { |
| 92 | + return std::nullopt; |
| 93 | + } |
| 94 | +} |
| 95 | + |
| 96 | +std::optional<Label> GetFinalLabel(const OpenMPConstruct &x) { |
| 97 | + return common::visit( |
| 98 | + [](auto &&s) -> std::optional<Label> { |
| 99 | + using TypeS = llvm::remove_cvref_t<decltype(s)>; |
| 100 | + if constexpr (std::is_same_v<TypeS, OpenMPSectionsConstruct>) { |
| 101 | + auto &list{std::get<std::list<OpenMPConstruct>>(s.t)}; |
| 102 | + if (!list.empty()) { |
| 103 | + return GetFinalLabel(list.back()); |
| 104 | + } else { |
| 105 | + return std::nullopt; |
| 106 | + } |
| 107 | + } else if constexpr ( // |
| 108 | + std::is_same_v<TypeS, OpenMPLoopConstruct> || |
| 109 | + std::is_same_v<TypeS, OpenMPSectionConstruct> || |
| 110 | + std::is_base_of_v<OmpBlockConstruct, TypeS>) { |
| 111 | + return GetFinalLabel(std::get<Block>(s.t)); |
| 112 | + } else { |
| 113 | + return std::nullopt; |
| 114 | + } |
| 115 | + }, |
| 116 | + x.u); |
| 117 | +} |
| 118 | + |
61 | 119 | const OmpObjectList *GetOmpObjectList(const OmpClause &clause) { |
62 | 120 | // Clauses with OmpObjectList as its data member |
63 | 121 | using MemberObjectListClauses = std::tuple<OmpClause::Copyin, |
|
0 commit comments