[lldb] Add ability to hide the root name of a value
[llvm-project.git] / flang / lib / Semantics / check-omp-structure.h
blob992531a586db80bf4e83a2ca32fa5401406c7951
1 //===-- lib/Semantics/check-omp-structure.h ---------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 // OpenMP structure validity check list
10 // 1. invalid clauses on directive
11 // 2. invalid repeated clauses on directive
12 // 3. TODO: invalid nesting of regions
14 #ifndef FORTRAN_SEMANTICS_CHECK_OMP_STRUCTURE_H_
15 #define FORTRAN_SEMANTICS_CHECK_OMP_STRUCTURE_H_
17 #include "check-directive-structure.h"
18 #include "flang/Common/enum-set.h"
19 #include "flang/Parser/parse-tree.h"
20 #include "flang/Semantics/semantics.h"
21 #include "llvm/Frontend/OpenMP/OMPConstants.h"
23 using OmpDirectiveSet = Fortran::common::EnumSet<llvm::omp::Directive,
24 llvm::omp::Directive_enumSize>;
26 using OmpClauseSet =
27 Fortran::common::EnumSet<llvm::omp::Clause, llvm::omp::Clause_enumSize>;
29 #define GEN_FLANG_DIRECTIVE_CLAUSE_SETS
30 #include "llvm/Frontend/OpenMP/OMP.inc"
32 namespace llvm {
33 namespace omp {
34 static OmpDirectiveSet parallelSet{Directive::OMPD_distribute_parallel_do,
35 Directive::OMPD_distribute_parallel_do_simd, Directive::OMPD_parallel,
36 Directive::OMPD_parallel_do, Directive::OMPD_parallel_do_simd,
37 Directive::OMPD_parallel_sections, Directive::OMPD_parallel_workshare,
38 Directive::OMPD_target_parallel, Directive::OMPD_target_parallel_do,
39 Directive::OMPD_target_parallel_do_simd,
40 Directive::OMPD_target_teams_distribute_parallel_do,
41 Directive::OMPD_target_teams_distribute_parallel_do_simd,
42 Directive::OMPD_teams_distribute_parallel_do,
43 Directive::OMPD_teams_distribute_parallel_do_simd};
44 static OmpDirectiveSet doSet{Directive::OMPD_distribute_parallel_do,
45 Directive::OMPD_distribute_parallel_do_simd, Directive::OMPD_parallel_do,
46 Directive::OMPD_parallel_do_simd, Directive::OMPD_do,
47 Directive::OMPD_do_simd, Directive::OMPD_target_parallel_do,
48 Directive::OMPD_target_parallel_do_simd,
49 Directive::OMPD_target_teams_distribute_parallel_do,
50 Directive::OMPD_target_teams_distribute_parallel_do_simd,
51 Directive::OMPD_teams_distribute_parallel_do,
52 Directive::OMPD_teams_distribute_parallel_do_simd};
53 static OmpDirectiveSet doSimdSet{Directive::OMPD_distribute_parallel_do_simd,
54 Directive::OMPD_parallel_do_simd, Directive::OMPD_do_simd,
55 Directive::OMPD_target_parallel_do_simd,
56 Directive::OMPD_target_teams_distribute_parallel_do_simd,
57 Directive::OMPD_teams_distribute_parallel_do_simd};
58 static OmpDirectiveSet workShareSet{
59 OmpDirectiveSet{Directive::OMPD_workshare,
60 Directive::OMPD_parallel_workshare, Directive::OMPD_parallel_sections,
61 Directive::OMPD_sections, Directive::OMPD_single} |
62 doSet};
63 static OmpDirectiveSet taskloopSet{
64 Directive::OMPD_taskloop, Directive::OMPD_taskloop_simd};
65 static OmpDirectiveSet targetSet{Directive::OMPD_target,
66 Directive::OMPD_target_parallel, Directive::OMPD_target_parallel_do,
67 Directive::OMPD_target_parallel_do_simd, Directive::OMPD_target_simd,
68 Directive::OMPD_target_teams, Directive::OMPD_target_teams_distribute,
69 Directive::OMPD_target_teams_distribute_simd};
70 static OmpDirectiveSet simdSet{Directive::OMPD_distribute_parallel_do_simd,
71 Directive::OMPD_distribute_simd, Directive::OMPD_parallel_do_simd,
72 Directive::OMPD_do_simd, Directive::OMPD_simd,
73 Directive::OMPD_target_parallel_do_simd,
74 Directive::OMPD_target_teams_distribute_parallel_do_simd,
75 Directive::OMPD_target_teams_distribute_simd, Directive::OMPD_target_simd,
76 Directive::OMPD_taskloop_simd,
77 Directive::OMPD_teams_distribute_parallel_do_simd,
78 Directive::OMPD_teams_distribute_simd};
79 static OmpDirectiveSet teamSet{Directive::OMPD_teams,
80 Directive::OMPD_teams_distribute,
81 Directive::OMPD_teams_distribute_parallel_do,
82 Directive::OMPD_teams_distribute_parallel_do_simd,
83 Directive::OMPD_teams_distribute_parallel_for,
84 Directive::OMPD_teams_distribute_parallel_for_simd,
85 Directive::OMPD_teams_distribute_simd};
86 static OmpDirectiveSet taskGeneratingSet{
87 OmpDirectiveSet{Directive::OMPD_task} | taskloopSet};
88 static OmpDirectiveSet nestedOrderedErrSet{Directive::OMPD_critical,
89 Directive::OMPD_ordered, Directive::OMPD_atomic, Directive::OMPD_task,
90 Directive::OMPD_taskloop};
91 static OmpDirectiveSet nestedWorkshareErrSet{
92 OmpDirectiveSet{Directive::OMPD_task, Directive::OMPD_taskloop,
93 Directive::OMPD_critical, Directive::OMPD_ordered,
94 Directive::OMPD_atomic, Directive::OMPD_master} |
95 workShareSet};
96 static OmpDirectiveSet nestedMasterErrSet{
97 OmpDirectiveSet{llvm::omp::Directive::OMPD_atomic} | taskGeneratingSet |
98 workShareSet};
99 static OmpDirectiveSet nestedBarrierErrSet{
100 OmpDirectiveSet{Directive::OMPD_critical, Directive::OMPD_ordered,
101 Directive::OMPD_atomic, Directive::OMPD_master} |
102 taskGeneratingSet | workShareSet};
103 static OmpClauseSet privateSet{
104 Clause::OMPC_private, Clause::OMPC_firstprivate, Clause::OMPC_lastprivate};
105 static OmpClauseSet privateReductionSet{
106 OmpClauseSet{Clause::OMPC_reduction} | privateSet};
107 } // namespace omp
108 } // namespace llvm
110 namespace Fortran::semantics {
112 // Mapping from 'Symbol' to 'Source' to keep track of the variables
113 // used in multiple clauses
114 using SymbolSourceMap = std::multimap<const Symbol *, parser::CharBlock>;
115 // Multimap to check the triple <current_dir, enclosing_dir, enclosing_clause>
116 using DirectivesClauseTriple = std::multimap<llvm::omp::Directive,
117 std::pair<llvm::omp::Directive, const OmpClauseSet>>;
119 class OmpStructureChecker
120 : public DirectiveStructureChecker<llvm::omp::Directive, llvm::omp::Clause,
121 parser::OmpClause, llvm::omp::Clause_enumSize> {
122 public:
123 OmpStructureChecker(SemanticsContext &context)
124 : DirectiveStructureChecker(context,
125 #define GEN_FLANG_DIRECTIVE_CLAUSE_MAP
126 #include "llvm/Frontend/OpenMP/OMP.inc"
129 using llvmOmpClause = const llvm::omp::Clause;
131 void Enter(const parser::OpenMPConstruct &);
132 void Enter(const parser::OpenMPLoopConstruct &);
133 void Leave(const parser::OpenMPLoopConstruct &);
134 void Enter(const parser::OmpEndLoopDirective &);
136 void Enter(const parser::OpenMPBlockConstruct &);
137 void Leave(const parser::OpenMPBlockConstruct &);
138 void Leave(const parser::OmpBeginBlockDirective &);
139 void Enter(const parser::OmpEndBlockDirective &);
140 void Leave(const parser::OmpEndBlockDirective &);
142 void Enter(const parser::OpenMPSectionsConstruct &);
143 void Leave(const parser::OpenMPSectionsConstruct &);
144 void Enter(const parser::OmpEndSectionsDirective &);
145 void Leave(const parser::OmpEndSectionsDirective &);
147 void Enter(const parser::OpenMPDeclareSimdConstruct &);
148 void Leave(const parser::OpenMPDeclareSimdConstruct &);
149 void Enter(const parser::OpenMPDeclarativeAllocate &);
150 void Leave(const parser::OpenMPDeclarativeAllocate &);
151 void Enter(const parser::OpenMPDeclareTargetConstruct &);
152 void Leave(const parser::OpenMPDeclareTargetConstruct &);
153 void Enter(const parser::OpenMPExecutableAllocate &);
154 void Leave(const parser::OpenMPExecutableAllocate &);
155 void Enter(const parser::OpenMPRequiresConstruct &);
156 void Leave(const parser::OpenMPRequiresConstruct &);
157 void Enter(const parser::OpenMPThreadprivate &);
158 void Leave(const parser::OpenMPThreadprivate &);
160 void Enter(const parser::OpenMPSimpleStandaloneConstruct &);
161 void Leave(const parser::OpenMPSimpleStandaloneConstruct &);
162 void Enter(const parser::OpenMPFlushConstruct &);
163 void Leave(const parser::OpenMPFlushConstruct &);
164 void Enter(const parser::OpenMPCancelConstruct &);
165 void Leave(const parser::OpenMPCancelConstruct &);
166 void Enter(const parser::OpenMPCancellationPointConstruct &);
167 void Leave(const parser::OpenMPCancellationPointConstruct &);
168 void Enter(const parser::OpenMPCriticalConstruct &);
169 void Leave(const parser::OpenMPCriticalConstruct &);
170 void Enter(const parser::OpenMPAtomicConstruct &);
171 void Leave(const parser::OpenMPAtomicConstruct &);
173 void Leave(const parser::OmpClauseList &);
174 void Enter(const parser::OmpClause &);
176 void Enter(const parser::OmpAtomicRead &);
177 void Leave(const parser::OmpAtomicRead &);
178 void Enter(const parser::OmpAtomicWrite &);
179 void Leave(const parser::OmpAtomicWrite &);
180 void Enter(const parser::OmpAtomicUpdate &);
181 void Leave(const parser::OmpAtomicUpdate &);
182 void Enter(const parser::OmpAtomicCapture &);
183 void Leave(const parser::OmpAtomic &);
185 #define GEN_FLANG_CLAUSE_CHECK_ENTER
186 #include "llvm/Frontend/OpenMP/OMP.inc"
188 // Get the OpenMP Clause Kind for the corresponding Parser class
189 template <typename A>
190 llvm::omp::Clause GetClauseKindForParserClass(const A &) {
191 #define GEN_FLANG_CLAUSE_PARSER_KIND_MAP
192 #include "llvm/Frontend/OpenMP/OMP.inc"
195 private:
196 void CheckMultListItems();
197 bool HasInvalidWorksharingNesting(
198 const parser::CharBlock &, const OmpDirectiveSet &);
199 bool IsCloselyNestedRegion(const OmpDirectiveSet &set);
200 void HasInvalidTeamsNesting(
201 const llvm::omp::Directive &dir, const parser::CharBlock &source);
202 void HasInvalidDistributeNesting(const parser::OpenMPLoopConstruct &x);
203 // specific clause related
204 bool ScheduleModifierHasType(const parser::OmpScheduleClause &,
205 const parser::OmpScheduleModifierType::ModType &);
206 void CheckAllowedMapTypes(const parser::OmpMapType::Type &,
207 const std::list<parser::OmpMapType::Type> &);
208 llvm::StringRef getClauseName(llvm::omp::Clause clause) override;
209 llvm::StringRef getDirectiveName(llvm::omp::Directive directive) override;
211 void CheckDependList(const parser::DataRef &);
212 void CheckDependArraySection(
213 const common::Indirection<parser::ArrayElement> &, const parser::Name &);
214 bool IsDataRefTypeParamInquiry(const parser::DataRef *dataRef);
215 void CheckIsVarPartOfAnotherVar(
216 const parser::CharBlock &source, const parser::OmpObjectList &objList);
217 void CheckThreadprivateOrDeclareTargetVar(
218 const parser::OmpObjectList &objList);
219 void CheckIntentInPointer(
220 const parser::OmpObjectList &, const llvm::omp::Clause);
221 void GetSymbolsInObjectList(const parser::OmpObjectList &, SymbolSourceMap &);
222 void CheckDefinableObjects(SymbolSourceMap &, const llvm::omp::Clause);
223 void CheckCopyingPolymorphicAllocatable(
224 SymbolSourceMap &, const llvm::omp::Clause);
225 void CheckPrivateSymbolsInOuterCxt(
226 SymbolSourceMap &, DirectivesClauseTriple &, const llvm::omp::Clause);
227 const parser::Name GetLoopIndex(const parser::DoConstruct *x);
228 void SetLoopInfo(const parser::OpenMPLoopConstruct &x);
229 void CheckIsLoopIvPartOfClause(
230 llvmOmpClause clause, const parser::OmpObjectList &ompObjectList);
231 bool CheckTargetBlockOnlyTeams(const parser::Block &);
232 void CheckWorkshareBlockStmts(const parser::Block &, parser::CharBlock);
234 void CheckLoopItrVariableIsInt(const parser::OpenMPLoopConstruct &x);
235 void CheckDoWhile(const parser::OpenMPLoopConstruct &x);
236 void CheckCycleConstraints(const parser::OpenMPLoopConstruct &x);
237 template <typename T, typename D> bool IsOperatorValid(const T &, const D &);
238 void CheckAtomicMemoryOrderClause(
239 const parser::OmpAtomicClauseList *, const parser::OmpAtomicClauseList *);
240 void CheckAtomicUpdateAssignmentStmt(const parser::AssignmentStmt &);
241 void CheckAtomicConstructStructure(const parser::OpenMPAtomicConstruct &);
242 void CheckDistLinear(const parser::OpenMPLoopConstruct &x);
243 void CheckSIMDNest(const parser::OpenMPConstruct &x);
244 void CheckTargetNest(const parser::OpenMPConstruct &x);
245 void CheckCancellationNest(
246 const parser::CharBlock &source, const parser::OmpCancelType::Type &type);
247 std::int64_t GetOrdCollapseLevel(const parser::OpenMPLoopConstruct &x);
248 bool CheckReductionOperators(const parser::OmpClause::Reduction &);
249 bool CheckIntrinsicOperator(
250 const parser::DefinedOperator::IntrinsicOperator &);
251 void CheckReductionTypeList(const parser::OmpClause::Reduction &);
252 void CheckMasterNesting(const parser::OpenMPBlockConstruct &x);
253 void ChecksOnOrderedAsBlock();
254 void CheckBarrierNesting(const parser::OpenMPSimpleStandaloneConstruct &x);
255 void ChecksOnOrderedAsStandalone();
256 void CheckOrderedDependClause(std::optional<std::int64_t> orderedValue);
257 void CheckReductionArraySection(const parser::OmpObjectList &ompObjectList);
258 void CheckIntentInPointerAndDefinable(
259 const parser::OmpObjectList &, const llvm::omp::Clause);
260 void CheckArraySection(const parser::ArrayElement &arrayElement,
261 const parser::Name &name, const llvm::omp::Clause clause);
262 void CheckSharedBindingInOuterContext(
263 const parser::OmpObjectList &ompObjectList);
264 const parser::OmpObjectList *GetOmpObjectList(const parser::OmpClause &);
265 void CheckPredefinedAllocatorRestriction(const parser::CharBlock &source,
266 const parser::OmpObjectList &ompObjectList);
267 void CheckPredefinedAllocatorRestriction(
268 const parser::CharBlock &source, const parser::Name &name);
269 bool isPredefinedAllocator{false};
270 void EnterDirectiveNest(const int index) { directiveNest_[index]++; }
271 void ExitDirectiveNest(const int index) { directiveNest_[index]--; }
272 int GetDirectiveNest(const int index) { return directiveNest_[index]; }
273 template <typename D> void CheckHintClause(D *, D *);
275 enum directiveNestType {
276 SIMDNest,
277 TargetBlockOnlyTeams,
278 TargetNest,
279 LastType
281 int directiveNest_[LastType + 1] = {0};
283 } // namespace Fortran::semantics
284 #endif // FORTRAN_SEMANTICS_CHECK_OMP_STRUCTURE_H_