FLANG
check-omp-structure.h
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//===----------------------------------------------------------------------===//
8
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
13
14#ifndef FORTRAN_SEMANTICS_CHECK_OMP_STRUCTURE_H_
15#define FORTRAN_SEMANTICS_CHECK_OMP_STRUCTURE_H_
16
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"
23
24using OmpClauseSet =
26
27#define GEN_FLANG_DIRECTIVE_CLAUSE_SETS
28#include "llvm/Frontend/OpenMP/OMP.inc"
29
30namespace llvm {
31namespace omp {
32static OmpClauseSet privateSet{
33 Clause::OMPC_private, Clause::OMPC_firstprivate, Clause::OMPC_lastprivate};
34static 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.
40static const OmpDirectiveSet noWaitClauseNotAllowedSet{
41 Directive::OMPD_do,
42 Directive::OMPD_do_simd,
43 Directive::OMPD_sections,
44 Directive::OMPD_single,
45 Directive::OMPD_workshare,
46};
47} // namespace omp
48} // namespace llvm
49
50namespace Fortran::semantics {
51
52// Mapping from 'Symbol' to 'Source' to keep track of the variables
53// used in multiple clauses
54using SymbolSourceMap = std::multimap<const Symbol *, parser::CharBlock>;
55// Multimap to check the triple <current_dir, enclosing_dir, enclosing_clause>
56using DirectivesClauseTriple = std::multimap<llvm::omp::Directive,
57 std::pair<llvm::omp::Directive, const OmpClauseSet>>;
58
60 : public DirectiveStructureChecker<llvm::omp::Directive, llvm::omp::Clause,
61 parser::OmpClause, llvm::omp::Clause_enumSize> {
62public:
63 using Base = DirectiveStructureChecker<llvm::omp::Directive,
64 llvm::omp::Clause, parser::OmpClause, llvm::omp::Clause_enumSize>;
65
68#define GEN_FLANG_DIRECTIVE_CLAUSE_MAP
69#include "llvm/Frontend/OpenMP/OMP.inc"
70 ) {
71 }
72 using llvmOmpClause = const llvm::omp::Clause;
73
74 void Enter(const parser::OpenMPConstruct &);
75 void Leave(const parser::OpenMPConstruct &);
76 void Enter(const parser::OpenMPDeclarativeConstruct &);
77 void Leave(const parser::OpenMPDeclarativeConstruct &);
78
79 void Enter(const parser::OpenMPLoopConstruct &);
80 void Leave(const parser::OpenMPLoopConstruct &);
81 void Enter(const parser::OmpEndLoopDirective &);
82 void Leave(const parser::OmpEndLoopDirective &);
83
84 void Enter(const parser::OpenMPBlockConstruct &);
85 void Leave(const parser::OpenMPBlockConstruct &);
86 void Leave(const parser::OmpBeginBlockDirective &);
87 void Enter(const parser::OmpEndBlockDirective &);
88 void Leave(const parser::OmpEndBlockDirective &);
89
90 void Enter(const parser::OpenMPSectionsConstruct &);
91 void Leave(const parser::OpenMPSectionsConstruct &);
92 void Enter(const parser::OmpEndSectionsDirective &);
93 void Leave(const parser::OmpEndSectionsDirective &);
94
95 void Enter(const parser::OpenMPDeclareSimdConstruct &);
96 void Leave(const parser::OpenMPDeclareSimdConstruct &);
97 void Enter(const parser::OpenMPDeclarativeAllocate &);
98 void Leave(const parser::OpenMPDeclarativeAllocate &);
99 void Enter(const parser::OpenMPDeclareMapperConstruct &);
100 void Leave(const parser::OpenMPDeclareMapperConstruct &);
101 void Enter(const parser::OpenMPDeclareTargetConstruct &);
102 void Leave(const parser::OpenMPDeclareTargetConstruct &);
103 void Enter(const parser::OpenMPDepobjConstruct &);
104 void Leave(const parser::OpenMPDepobjConstruct &);
105 void Enter(const parser::OmpDeclareTargetWithList &);
106 void Enter(const parser::OmpDeclareTargetWithClause &);
107 void Leave(const parser::OmpDeclareTargetWithClause &);
108 void Enter(const parser::OpenMPDispatchConstruct &);
109 void Leave(const parser::OpenMPDispatchConstruct &);
110 void Enter(const parser::OmpErrorDirective &);
111 void Leave(const parser::OmpErrorDirective &);
112 void Enter(const parser::OpenMPExecutableAllocate &);
113 void Leave(const parser::OpenMPExecutableAllocate &);
114 void Enter(const parser::OpenMPAllocatorsConstruct &);
115 void Leave(const parser::OpenMPAllocatorsConstruct &);
116 void Enter(const parser::OpenMPRequiresConstruct &);
117 void Leave(const parser::OpenMPRequiresConstruct &);
118 void Enter(const parser::OpenMPThreadprivate &);
119 void Leave(const parser::OpenMPThreadprivate &);
120
121 void Enter(const parser::OpenMPSimpleStandaloneConstruct &);
122 void Leave(const parser::OpenMPSimpleStandaloneConstruct &);
123 void Enter(const parser::OpenMPFlushConstruct &);
124 void Leave(const parser::OpenMPFlushConstruct &);
125 void Enter(const parser::OpenMPCancelConstruct &);
126 void Leave(const parser::OpenMPCancelConstruct &);
129 void Enter(const parser::OpenMPCriticalConstruct &);
130 void Leave(const parser::OpenMPCriticalConstruct &);
131 void Enter(const parser::OpenMPAtomicConstruct &);
132 void Leave(const parser::OpenMPAtomicConstruct &);
133
134 void Leave(const parser::OmpClauseList &);
135 void Enter(const parser::OmpClause &);
136
137 void Enter(const parser::OmpAtomicRead &);
138 void Leave(const parser::OmpAtomicRead &);
139 void Enter(const parser::OmpAtomicWrite &);
140 void Leave(const parser::OmpAtomicWrite &);
141 void Enter(const parser::OmpAtomicUpdate &);
142 void Leave(const parser::OmpAtomicUpdate &);
143 void Enter(const parser::OmpAtomicCapture &);
144 void Leave(const parser::OmpAtomic &);
145
146 void Enter(const parser::DoConstruct &);
147 void Leave(const parser::DoConstruct &);
148
149 void Enter(const parser::OmpDirectiveSpecification &);
150 void Leave(const parser::OmpDirectiveSpecification &);
151
152 void Enter(const parser::OmpMetadirectiveDirective &);
153 void Leave(const parser::OmpMetadirectiveDirective &);
154
155 void Enter(const parser::OmpContextSelector &);
156 void Leave(const parser::OmpContextSelector &);
157
158#define GEN_FLANG_CLAUSE_CHECK_ENTER
159#include "llvm/Frontend/OpenMP/OMP.inc"
160
161 void Leave(const parser::OmpClause::Fail &);
162 void Enter(const parser::OmpFailClause &);
163 void Leave(const parser::OmpFailClause &);
164
165private:
166 bool CheckAllowedClause(llvmOmpClause clause);
167 bool IsVariableListItem(const Symbol &sym);
168 bool IsExtendedListItem(const Symbol &sym);
169 bool IsCommonBlock(const Symbol &sym);
170 std::optional<bool> IsContiguous(const parser::OmpObject &object);
171 void CheckMultipleOccurrence(semantics::UnorderedSymbolSet &listVars,
172 const std::list<parser::Name> &nameList, const parser::CharBlock &item,
173 const std::string &clauseName);
174 void CheckMultListItems();
175 void CheckStructureComponent(
176 const parser::OmpObjectList &objects, llvm::omp::Clause clauseId);
177 bool HasInvalidWorksharingNesting(
178 const parser::CharBlock &, const OmpDirectiveSet &);
179 bool IsCloselyNestedRegion(const OmpDirectiveSet &set);
180 void HasInvalidTeamsNesting(
181 const llvm::omp::Directive &dir, const parser::CharBlock &source);
182 void HasInvalidDistributeNesting(const parser::OpenMPLoopConstruct &x);
183 void HasInvalidLoopBinding(const parser::OpenMPLoopConstruct &x);
184 // specific clause related
185 void CheckAllowedMapTypes(const parser::OmpMapType::Value &,
186 const std::list<parser::OmpMapType::Value> &);
187 llvm::StringRef getClauseName(llvm::omp::Clause clause) override;
188 llvm::StringRef getDirectiveName(llvm::omp::Directive directive) override;
189
190 template < //
191 typename LessTy, typename RangeTy,
192 typename IterTy = decltype(std::declval<RangeTy>().begin())>
193 std::optional<IterTy> FindDuplicate(RangeTy &&);
194
195 const Symbol *GetObjectSymbol(const parser::OmpObject &object);
196 std::optional<parser::CharBlock> GetObjectSource(
197 const parser::OmpObject &object);
198 void CheckDependList(const parser::DataRef &);
199 void CheckDependArraySection(
201 void CheckDoacross(const parser::OmpDoacross &doa);
202 bool IsDataRefTypeParamInquiry(const parser::DataRef *dataRef);
203 void CheckIsVarPartOfAnotherVar(const parser::CharBlock &source,
204 const parser::OmpObjectList &objList, llvm::StringRef clause = "");
205 void CheckThreadprivateOrDeclareTargetVar(
206 const parser::OmpObjectList &objList);
207 void CheckSymbolNames(
208 const parser::CharBlock &source, const parser::OmpObjectList &objList);
209 void CheckIntentInPointer(SymbolSourceMap &, const llvm::omp::Clause);
210 void CheckProcedurePointer(SymbolSourceMap &, const llvm::omp::Clause);
211 void CheckCrayPointee(const parser::OmpObjectList &objectList,
212 llvm::StringRef clause, bool suggestToUseCrayPointer = true);
213 void GetSymbolsInObjectList(const parser::OmpObjectList &, SymbolSourceMap &);
214 void CheckDefinableObjects(SymbolSourceMap &, const llvm::omp::Clause);
215 void CheckCopyingPolymorphicAllocatable(
216 SymbolSourceMap &, const llvm::omp::Clause);
217 void CheckPrivateSymbolsInOuterCxt(
218 SymbolSourceMap &, DirectivesClauseTriple &, const llvm::omp::Clause);
219 const parser::Name GetLoopIndex(const parser::DoConstruct *x);
220 void SetLoopInfo(const parser::OpenMPLoopConstruct &x);
221 void CheckIsLoopIvPartOfClause(
222 llvmOmpClause clause, const parser::OmpObjectList &ompObjectList);
223 bool CheckTargetBlockOnlyTeams(const parser::Block &);
224 void CheckWorkshareBlockStmts(const parser::Block &, parser::CharBlock);
225
226 void CheckIteratorRange(const parser::OmpIteratorSpecifier &x);
227 void CheckIteratorModifier(const parser::OmpIterator &x);
228 void CheckLoopItrVariableIsInt(const parser::OpenMPLoopConstruct &x);
229 void CheckDoWhile(const parser::OpenMPLoopConstruct &x);
230 void CheckAssociatedLoopConstraints(const parser::OpenMPLoopConstruct &x);
231 template <typename T, typename D> bool IsOperatorValid(const T &, const D &);
232 void CheckAtomicMemoryOrderClause(
234 void CheckAtomicUpdateStmt(const parser::AssignmentStmt &);
235 void CheckAtomicCaptureStmt(const parser::AssignmentStmt &);
236 void CheckAtomicWriteStmt(const parser::AssignmentStmt &);
237 void CheckAtomicCaptureConstruct(const parser::OmpAtomicCapture &);
238 void CheckAtomicCompareConstruct(const parser::OmpAtomicCompare &);
239 void CheckAtomicConstructStructure(const parser::OpenMPAtomicConstruct &);
240 void CheckDistLinear(const parser::OpenMPLoopConstruct &x);
241 void CheckSIMDNest(const parser::OpenMPConstruct &x);
242 void CheckTargetNest(const parser::OpenMPConstruct &x);
243 void CheckTargetUpdate();
244 void CheckDependenceType(const parser::OmpDependenceType::Value &x);
245 void CheckTaskDependenceType(const parser::OmpTaskDependenceType::Value &x);
246 void CheckCancellationNest(
247 const parser::CharBlock &source, const parser::OmpCancelType::Type &type);
248 std::int64_t GetOrdCollapseLevel(const parser::OpenMPLoopConstruct &x);
249 void CheckReductionObjects(
250 const parser::OmpObjectList &objects, llvm::omp::Clause clauseId);
251 bool CheckReductionOperator(const parser::OmpReductionIdentifier &ident,
252 parser::CharBlock source, llvm::omp::Clause clauseId);
253 void CheckReductionObjectTypes(const parser::OmpObjectList &objects,
254 const parser::OmpReductionIdentifier &ident);
255 void CheckReductionModifier(const parser::OmpReductionModifier &);
256 void CheckMasterNesting(const parser::OpenMPBlockConstruct &x);
257 void ChecksOnOrderedAsBlock();
258 void CheckBarrierNesting(const parser::OpenMPSimpleStandaloneConstruct &x);
259 void CheckScan(const parser::OpenMPSimpleStandaloneConstruct &x);
260 void ChecksOnOrderedAsStandalone();
261 void CheckOrderedDependClause(std::optional<std::int64_t> orderedValue);
262 void CheckReductionArraySection(
263 const parser::OmpObjectList &ompObjectList, llvm::omp::Clause clauseId);
264 void CheckArraySection(const parser::ArrayElement &arrayElement,
265 const parser::Name &name, const llvm::omp::Clause clause);
266 void CheckSharedBindingInOuterContext(
267 const parser::OmpObjectList &ompObjectList);
268 void CheckIfContiguous(const parser::OmpObject &object);
269 const parser::Name *GetObjectName(const parser::OmpObject &object);
270 const parser::OmpObjectList *GetOmpObjectList(const parser::OmpClause &);
271 void CheckPredefinedAllocatorRestriction(const parser::CharBlock &source,
272 const parser::OmpObjectList &ompObjectList);
273 void CheckPredefinedAllocatorRestriction(
274 const parser::CharBlock &source, const parser::Name &name);
275 bool isPredefinedAllocator{false};
276
277 void CheckAllowedRequiresClause(llvmOmpClause clause);
278 bool deviceConstructFound_{false};
279
280 void CheckAlignValue(const parser::OmpClause &);
281
282 void EnterDirectiveNest(const int index) { directiveNest_[index]++; }
283 void ExitDirectiveNest(const int index) { directiveNest_[index]--; }
284 int GetDirectiveNest(const int index) { return directiveNest_[index]; }
285 template <typename D> void CheckHintClause(D *, D *);
286 inline void ErrIfAllocatableVariable(const parser::Variable &);
287 inline void ErrIfLHSAndRHSSymbolsMatch(
288 const parser::Variable &, const parser::Expr &);
289 inline void ErrIfNonScalarAssignmentStmt(
290 const parser::Variable &, const parser::Expr &);
291 enum directiveNestType : int {
292 SIMDNest,
293 TargetBlockOnlyTeams,
294 TargetNest,
295 DeclarativeNest,
296 ContextSelectorNest,
297 LastType = ContextSelectorNest,
298 };
299 int directiveNest_[LastType + 1] = {0};
300
301 SymbolSourceMap deferredNonVariables_;
302
303 using LoopConstruct = std::variant<const parser::DoConstruct *,
305 std::vector<LoopConstruct> loopStack_;
306 bool isFailClause{false};
307};
308
311template <typename LessTy, typename RangeTy, typename IterTy>
312std::optional<IterTy> OmpStructureChecker::FindDuplicate(RangeTy &&range) {
313 // Deal with iterators, since the actual elements may be rvalues (i.e.
314 // have no addresses), for example with custom-constructed ranges that
315 // are not simple c.begin()..c.end().
316 std::set<IterTy, LessTy> uniq;
317 for (auto it{range.begin()}, end{range.end()}; it != end; ++it) {
318 if (!uniq.insert(it).second) {
319 return it;
320 }
321 }
322 return std::nullopt;
323}
324
325} // namespace Fortran::semantics
326#endif // FORTRAN_SEMANTICS_CHECK_OMP_STRUCTURE_H_
Definition: enum-set.h:28
Definition: indirection.h:31
Definition: char-block.h:28
Definition: check-directive-structure.h:181
Definition: check-omp-structure.h:61
Definition: semantics.h:67
Definition: symbol.h:712
Definition: parse-tree.h:1911
Definition: parse-tree.h:2016
Definition: parse-tree.h:1818
Definition: parse-tree.h:2338
Definition: parse-tree.h:1700
Definition: parse-tree.h:580
Definition: parse-tree.h:4646
Definition: parse-tree.h:4610
Definition: parse-tree.h:4662
Definition: parse-tree.h:4619
Definition: parse-tree.h:4637
Definition: parse-tree.h:4628
Definition: parse-tree.h:4671
Definition: parse-tree.h:4796
Definition: parse-tree.h:4369
Definition: parse-tree.h:4353
Definition: parse-tree.h:4460
Definition: parse-tree.h:4455
Definition: parse-tree.h:3462
Definition: parse-tree.h:4037
Definition: parse-tree.h:4802
Definition: parse-tree.h:4790
Definition: parse-tree.h:4418
Definition: parse-tree.h:4394
Definition: parse-tree.h:4110
Definition: parse-tree.h:4376
Definition: parse-tree.h:3474
Definition: parse-tree.h:4581
Definition: parse-tree.h:4683
Definition: parse-tree.h:4808
Definition: parse-tree.h:4711
Definition: parse-tree.h:4823
Definition: parse-tree.h:4557
Definition: parse-tree.h:4530
Definition: parse-tree.h:4536
Definition: parse-tree.h:4509
Definition: parse-tree.h:4724
Definition: parse-tree.h:4747
Definition: parse-tree.h:4566
Definition: parse-tree.h:4756
Definition: parse-tree.h:4814
Definition: parse-tree.h:4516
Definition: parse-tree.h:4439
Definition: parse-tree.h:4523
Definition: parse-tree.h:1865
Definition: parse-tree.h:3678
Definition: parse-tree.h:3750
Definition: parse-tree.h:3840
Definition: parse-tree.h:3849