[Target] Use range-based for loops (NFC)
[llvm-project.git] / flang / lib / Semantics / check-omp-structure.h
blob33243d926cf1671f5cfa274665b1bb585b3ac22f
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/openmp-directive-sets.h"
21 #include "flang/Semantics/semantics.h"
22 #include "llvm/Frontend/OpenMP/OMPConstants.h"
24 using OmpClauseSet =
25 Fortran::common::EnumSet<llvm::omp::Clause, llvm::omp::Clause_enumSize>;
27 #define GEN_FLANG_DIRECTIVE_CLAUSE_SETS
28 #include "llvm/Frontend/OpenMP/OMP.inc"
30 namespace llvm {
31 namespace omp {
32 static OmpClauseSet privateSet{
33 Clause::OMPC_private, Clause::OMPC_firstprivate, Clause::OMPC_lastprivate};
34 static OmpClauseSet privateReductionSet{
35 OmpClauseSet{Clause::OMPC_reduction} | privateSet};
36 // omp.td cannot differentiate allowed/not allowed clause list for few
37 // directives for fortran. nowait is not allowed on begin directive clause list
38 // for below list of directives. Directives with conflicting list of clauses are
39 // included in below list.
40 static const OmpDirectiveSet noWaitClauseNotAllowedSet{
41 Directive::OMPD_do,
42 Directive::OMPD_do_simd,
43 Directive::OMPD_sections,
44 Directive::OMPD_single,
46 } // namespace omp
47 } // namespace llvm
49 namespace Fortran::semantics {
51 // Mapping from 'Symbol' to 'Source' to keep track of the variables
52 // used in multiple clauses
53 using SymbolSourceMap = std::multimap<const Symbol *, parser::CharBlock>;
54 // Multimap to check the triple <current_dir, enclosing_dir, enclosing_clause>
55 using DirectivesClauseTriple = std::multimap<llvm::omp::Directive,
56 std::pair<llvm::omp::Directive, const OmpClauseSet>>;
58 class OmpStructureChecker
59 : public DirectiveStructureChecker<llvm::omp::Directive, llvm::omp::Clause,
60 parser::OmpClause, llvm::omp::Clause_enumSize> {
61 public:
62 OmpStructureChecker(SemanticsContext &context)
63 : DirectiveStructureChecker(context,
64 #define GEN_FLANG_DIRECTIVE_CLAUSE_MAP
65 #include "llvm/Frontend/OpenMP/OMP.inc"
66 ) {
68 using llvmOmpClause = const llvm::omp::Clause;
70 void Enter(const parser::OpenMPConstruct &);
71 void Enter(const parser::OpenMPLoopConstruct &);
72 void Leave(const parser::OpenMPLoopConstruct &);
73 void Enter(const parser::OmpEndLoopDirective &);
74 void Leave(const parser::OmpEndLoopDirective &);
76 void Enter(const parser::OpenMPBlockConstruct &);
77 void Leave(const parser::OpenMPBlockConstruct &);
78 void Leave(const parser::OmpBeginBlockDirective &);
79 void Enter(const parser::OmpEndBlockDirective &);
80 void Leave(const parser::OmpEndBlockDirective &);
82 void Enter(const parser::OpenMPSectionsConstruct &);
83 void Leave(const parser::OpenMPSectionsConstruct &);
84 void Enter(const parser::OmpEndSectionsDirective &);
85 void Leave(const parser::OmpEndSectionsDirective &);
87 void Enter(const parser::OpenMPDeclareSimdConstruct &);
88 void Leave(const parser::OpenMPDeclareSimdConstruct &);
89 void Enter(const parser::OpenMPDeclarativeAllocate &);
90 void Leave(const parser::OpenMPDeclarativeAllocate &);
91 void Enter(const parser::OpenMPDeclareTargetConstruct &);
92 void Leave(const parser::OpenMPDeclareTargetConstruct &);
93 void Enter(const parser::OmpDeclareTargetWithList &);
94 void Enter(const parser::OmpDeclareTargetWithClause &);
95 void Leave(const parser::OmpDeclareTargetWithClause &);
96 void Enter(const parser::OpenMPExecutableAllocate &);
97 void Leave(const parser::OpenMPExecutableAllocate &);
98 void Enter(const parser::OpenMPAllocatorsConstruct &);
99 void Leave(const parser::OpenMPAllocatorsConstruct &);
100 void Enter(const parser::OpenMPRequiresConstruct &);
101 void Leave(const parser::OpenMPRequiresConstruct &);
102 void Enter(const parser::OpenMPThreadprivate &);
103 void Leave(const parser::OpenMPThreadprivate &);
105 void Enter(const parser::OpenMPSimpleStandaloneConstruct &);
106 void Leave(const parser::OpenMPSimpleStandaloneConstruct &);
107 void Enter(const parser::OpenMPFlushConstruct &);
108 void Leave(const parser::OpenMPFlushConstruct &);
109 void Enter(const parser::OpenMPCancelConstruct &);
110 void Leave(const parser::OpenMPCancelConstruct &);
111 void Enter(const parser::OpenMPCancellationPointConstruct &);
112 void Leave(const parser::OpenMPCancellationPointConstruct &);
113 void Enter(const parser::OpenMPCriticalConstruct &);
114 void Leave(const parser::OpenMPCriticalConstruct &);
115 void Enter(const parser::OpenMPAtomicConstruct &);
116 void Leave(const parser::OpenMPAtomicConstruct &);
118 void Leave(const parser::OmpClauseList &);
119 void Enter(const parser::OmpClause &);
121 void Enter(const parser::OmpAtomicRead &);
122 void Leave(const parser::OmpAtomicRead &);
123 void Enter(const parser::OmpAtomicWrite &);
124 void Leave(const parser::OmpAtomicWrite &);
125 void Enter(const parser::OmpAtomicUpdate &);
126 void Leave(const parser::OmpAtomicUpdate &);
127 void Enter(const parser::OmpAtomicCapture &);
128 void Leave(const parser::OmpAtomic &);
130 #define GEN_FLANG_CLAUSE_CHECK_ENTER
131 #include "llvm/Frontend/OpenMP/OMP.inc"
133 // Get the OpenMP Clause Kind for the corresponding Parser class
134 template <typename A>
135 llvm::omp::Clause GetClauseKindForParserClass(const A &) {
136 #define GEN_FLANG_CLAUSE_PARSER_KIND_MAP
137 #include "llvm/Frontend/OpenMP/OMP.inc"
140 private:
141 void CheckMultipleOccurrence(semantics::UnorderedSymbolSet &listVars,
142 const std::list<parser::Name> &nameList, const parser::CharBlock &item,
143 const std::string &clauseName);
144 void CheckMultListItems();
145 void CheckStructureElement(const parser::OmpObjectList &ompObjectList,
146 const llvm::omp::Clause clause);
147 bool HasInvalidWorksharingNesting(
148 const parser::CharBlock &, const OmpDirectiveSet &);
149 bool IsCloselyNestedRegion(const OmpDirectiveSet &set);
150 void HasInvalidTeamsNesting(
151 const llvm::omp::Directive &dir, const parser::CharBlock &source);
152 void HasInvalidDistributeNesting(const parser::OpenMPLoopConstruct &x);
153 // specific clause related
154 bool ScheduleModifierHasType(const parser::OmpScheduleClause &,
155 const parser::OmpScheduleModifierType::ModType &);
156 void CheckAllowedMapTypes(const parser::OmpMapType::Type &,
157 const std::list<parser::OmpMapType::Type> &);
158 llvm::StringRef getClauseName(llvm::omp::Clause clause) override;
159 llvm::StringRef getDirectiveName(llvm::omp::Directive directive) override;
161 void CheckDependList(const parser::DataRef &);
162 void CheckDependArraySection(
163 const common::Indirection<parser::ArrayElement> &, const parser::Name &);
164 bool IsDataRefTypeParamInquiry(const parser::DataRef *dataRef);
165 void CheckIsVarPartOfAnotherVar(
166 const parser::CharBlock &source, const parser::OmpObjectList &objList);
167 void CheckThreadprivateOrDeclareTargetVar(
168 const parser::OmpObjectList &objList);
169 void CheckSymbolNames(
170 const parser::CharBlock &source, const parser::OmpObjectList &objList);
171 void CheckIntentInPointer(
172 const parser::OmpObjectList &, const llvm::omp::Clause);
173 void GetSymbolsInObjectList(const parser::OmpObjectList &, SymbolSourceMap &);
174 void CheckDefinableObjects(SymbolSourceMap &, const llvm::omp::Clause);
175 void CheckCopyingPolymorphicAllocatable(
176 SymbolSourceMap &, const llvm::omp::Clause);
177 void CheckPrivateSymbolsInOuterCxt(
178 SymbolSourceMap &, DirectivesClauseTriple &, const llvm::omp::Clause);
179 const parser::Name GetLoopIndex(const parser::DoConstruct *x);
180 void SetLoopInfo(const parser::OpenMPLoopConstruct &x);
181 void CheckIsLoopIvPartOfClause(
182 llvmOmpClause clause, const parser::OmpObjectList &ompObjectList);
183 bool CheckTargetBlockOnlyTeams(const parser::Block &);
184 void CheckWorkshareBlockStmts(const parser::Block &, parser::CharBlock);
186 void CheckLoopItrVariableIsInt(const parser::OpenMPLoopConstruct &x);
187 void CheckDoWhile(const parser::OpenMPLoopConstruct &x);
188 void CheckCycleConstraints(const parser::OpenMPLoopConstruct &x);
189 template <typename T, typename D> bool IsOperatorValid(const T &, const D &);
190 void CheckAtomicMemoryOrderClause(
191 const parser::OmpAtomicClauseList *, const parser::OmpAtomicClauseList *);
192 void CheckAtomicUpdateStmt(const parser::AssignmentStmt &);
193 void CheckAtomicCaptureStmt(const parser::AssignmentStmt &);
194 void CheckAtomicWriteStmt(const parser::AssignmentStmt &);
195 void CheckAtomicConstructStructure(const parser::OpenMPAtomicConstruct &);
196 void CheckDistLinear(const parser::OpenMPLoopConstruct &x);
197 void CheckSIMDNest(const parser::OpenMPConstruct &x);
198 void CheckTargetNest(const parser::OpenMPConstruct &x);
199 void CheckTargetUpdate();
200 void CheckCancellationNest(
201 const parser::CharBlock &source, const parser::OmpCancelType::Type &type);
202 std::int64_t GetOrdCollapseLevel(const parser::OpenMPLoopConstruct &x);
203 bool CheckReductionOperators(const parser::OmpClause::Reduction &);
204 bool CheckIntrinsicOperator(
205 const parser::DefinedOperator::IntrinsicOperator &);
206 void CheckReductionTypeList(const parser::OmpClause::Reduction &);
207 void CheckMasterNesting(const parser::OpenMPBlockConstruct &x);
208 void ChecksOnOrderedAsBlock();
209 void CheckBarrierNesting(const parser::OpenMPSimpleStandaloneConstruct &x);
210 void ChecksOnOrderedAsStandalone();
211 void CheckOrderedDependClause(std::optional<std::int64_t> orderedValue);
212 void CheckReductionArraySection(const parser::OmpObjectList &ompObjectList);
213 void CheckIntentInPointerAndDefinable(
214 const parser::OmpObjectList &, const llvm::omp::Clause);
215 void CheckArraySection(const parser::ArrayElement &arrayElement,
216 const parser::Name &name, const llvm::omp::Clause clause);
217 void CheckSharedBindingInOuterContext(
218 const parser::OmpObjectList &ompObjectList);
219 const parser::OmpObjectList *GetOmpObjectList(const parser::OmpClause &);
220 void CheckPredefinedAllocatorRestriction(const parser::CharBlock &source,
221 const parser::OmpObjectList &ompObjectList);
222 void CheckPredefinedAllocatorRestriction(
223 const parser::CharBlock &source, const parser::Name &name);
224 bool isPredefinedAllocator{false};
226 void CheckAllowedRequiresClause(llvmOmpClause clause);
227 bool deviceConstructFound_{false};
229 void EnterDirectiveNest(const int index) { directiveNest_[index]++; }
230 void ExitDirectiveNest(const int index) { directiveNest_[index]--; }
231 int GetDirectiveNest(const int index) { return directiveNest_[index]; }
232 template <typename D> void CheckHintClause(D *, D *);
233 inline void ErrIfAllocatableVariable(const parser::Variable &);
234 inline void ErrIfLHSAndRHSSymbolsMatch(
235 const parser::Variable &, const parser::Expr &);
236 inline void ErrIfNonScalarAssignmentStmt(
237 const parser::Variable &, const parser::Expr &);
238 enum directiveNestType {
239 SIMDNest,
240 TargetBlockOnlyTeams,
241 TargetNest,
242 LastType
244 int directiveNest_[LastType + 1] = {0};
246 } // namespace Fortran::semantics
247 #endif // FORTRAN_SEMANTICS_CHECK_OMP_STRUCTURE_H_