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/ADT/iterator_range.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} // namespace omp
37} // namespace llvm
38
39namespace Fortran::semantics {
40struct AnalyzedCondStmt;
41
42namespace omp {
43struct LoopSequence;
44}
45
46// Mapping from 'Symbol' to 'Source' to keep track of the variables
47// used in multiple clauses
48using SymbolSourceMap = std::multimap<const Symbol *, parser::CharBlock>;
49// Multimap to check the triple <current_dir, enclosing_dir, enclosing_clause>
50using DirectivesClauseTriple = std::multimap<llvm::omp::Directive,
51 std::pair<llvm::omp::Directive, const OmpClauseSet>>;
52
53using OmpStructureCheckerBase = DirectiveStructureChecker<llvm::omp::Directive,
54 llvm::omp::Clause, parser::OmpClause, llvm::omp::Clause_enumSize>;
55
56class OmpStructureChecker : public OmpStructureCheckerBase {
57public:
58 using Base = OmpStructureCheckerBase;
59
60 OmpStructureChecker(SemanticsContext &context);
61
62 void Enter(const parser::ProgramUnit &);
63 void Enter(const parser::MainProgram &);
64 void Leave(const parser::MainProgram &);
65 void Enter(const parser::BlockData &);
66 void Leave(const parser::BlockData &);
67 void Enter(const parser::Module &);
68 void Leave(const parser::Module &);
69 void Enter(const parser::Submodule &);
70 void Leave(const parser::Submodule &);
71 void Enter(const parser::SubroutineStmt &);
72 void Enter(const parser::EndSubroutineStmt &);
73 void Enter(const parser::FunctionStmt &);
74 void Enter(const parser::EndFunctionStmt &);
75 void Enter(const parser::MpSubprogramStmt &);
76 void Enter(const parser::EndMpSubprogramStmt &);
77 void Enter(const parser::BlockConstruct &);
78 void Leave(const parser::BlockConstruct &);
79 void Enter(const parser::InternalSubprogram &);
80 void Enter(const parser::ModuleSubprogram &);
81
82 void Enter(const parser::SpecificationPart &);
83 void Leave(const parser::SpecificationPart &);
84 void Enter(const parser::ExecutionPart &);
85 void Leave(const parser::ExecutionPart &);
86
87 void Enter(const parser::OpenMPConstruct &);
88 void Leave(const parser::OpenMPConstruct &);
89 void Enter(const parser::OpenMPDeclarativeConstruct &);
90 void Leave(const parser::OpenMPDeclarativeConstruct &);
91
92 void Enter(const parser::OpenMPMisplacedEndDirective &);
93 void Leave(const parser::OpenMPMisplacedEndDirective &);
94 void Enter(const parser::OpenMPInvalidDirective &);
95 void Leave(const parser::OpenMPInvalidDirective &);
96
97 void Enter(const parser::OpenMPLoopConstruct &);
98 void Leave(const parser::OpenMPLoopConstruct &);
99
100 void Enter(const parser::OpenMPInteropConstruct &);
101 void Enter(const parser::OmpBlockConstruct &);
102 void Leave(const parser::OmpBlockConstruct &);
103 void Enter(const parser::OmpBeginDirective &);
104 void Leave(const parser::OmpBeginDirective &);
105
106 void Enter(const parser::OpenMPSectionsConstruct &);
107
108 void Enter(const parser::OmpDeclareVariantDirective &);
109 void Enter(const parser::OmpDeclareSimdDirective &);
110 void Enter(const parser::OmpAllocateDirective &);
111 void Leave(const parser::OmpAllocateDirective &);
112 void Enter(const parser::OmpDeclareMapperDirective &);
113 void Enter(const parser::OmpDeclareReductionDirective &);
114 void Enter(const parser::OmpDeclareTargetDirective &);
115 void Leave(const parser::OmpDeclareTargetDirective &);
116 void Enter(const parser::OpenMPDepobjConstruct &);
117 void Enter(const parser::OpenMPDispatchConstruct &);
118 void Enter(const parser::OpenMPAllocatorsConstruct &);
119 void Enter(const parser::OmpRequiresDirective &);
120 void Enter(const parser::OmpGroupprivateDirective &);
121 void Leave(const parser::OmpThreadprivateDirective &);
122
123 void Enter(const parser::OpenMPSimpleStandaloneConstruct &);
124 void Leave(const parser::OpenMPSimpleStandaloneConstruct &);
125 void Leave(const parser::OpenMPFlushConstruct &);
126 void Enter(const parser::OpenMPCancelConstruct &);
128 void Enter(const parser::OpenMPCriticalConstruct &);
129 void Enter(const parser::OpenMPAtomicConstruct &);
130
131 void Enter(const parser::OmpClauseList &);
132 void Leave(const parser::OmpClauseList &);
133 void Enter(const parser::OmpClause &);
134
135 void Enter(const parser::DoConstruct &);
136 void Leave(const parser::DoConstruct &);
137
138 void Enter(const parser::OmpDirectiveSpecification &);
139 void Leave(const parser::OmpDirectiveSpecification &);
140
141 void Enter(const parser::OmpMetadirectiveDirective &);
142 void Leave(const parser::OmpMetadirectiveDirective &);
143
144 void Enter(const parser::OmpContextSelector &);
145 void Leave(const parser::OmpContextSelector &);
146
147 template <typename A> void Enter(const parser::Statement<A> &);
148 void Leave(const parser::GotoStmt &);
149 void Leave(const parser::ComputedGotoStmt &);
150 void Leave(const parser::ArithmeticIfStmt &);
151 void Leave(const parser::AssignedGotoStmt &);
152 void Leave(const parser::AltReturnSpec &);
153 void Leave(const parser::ErrLabel &);
154 void Leave(const parser::EndLabel &);
155 void Leave(const parser::EorLabel &);
156
157 void Enter(const parser::OmpClause::Affinity &x);
158 void Enter(const parser::OmpClause::Align &x);
159 void Enter(const parser::OmpClause::Aligned &x);
160 void Enter(const parser::OmpClause::Allocate &x);
161 void Enter(const parser::OmpClause::Allocator &x);
162 void Enter(const parser::OmpClause::At &x);
163 void Enter(const parser::OmpClause::AtomicDefaultMemOrder &x);
164 void Enter(const parser::OmpClause::CancellationConstructType &x);
165 void Enter(const parser::OmpClause::Collapse &x);
166 void Enter(const parser::OmpClause::Copyin &x);
167 void Enter(const parser::OmpClause::Copyprivate &x);
168 void Enter(const parser::OmpClause::Defaultmap &x);
169 void Enter(const parser::OmpClause::Depend &x);
170 void Enter(const parser::OmpClause::Depth &x);
171 void Enter(const parser::OmpClause::Destroy &x);
172 void Enter(const parser::OmpClause::Detach &x);
173 void Enter(const parser::OmpClause::DeviceSafesync &x);
174 void Enter(const parser::OmpClause::Device &x);
175 void Enter(const parser::OmpClause::Doacross &x);
176 void Enter(const parser::OmpClause::DynamicAllocators &x);
177 void Enter(const parser::OmpClause::DynGroupprivate &x);
178 void Enter(const parser::OmpClause::Enter &x);
179 void Enter(const parser::OmpClause::Firstprivate &x);
180 void Enter(const parser::OmpClause::From &x);
181 void Enter(const parser::OmpClause::HasDeviceAddr &x);
182 void Enter(const parser::OmpClause::Hint &x);
183 void Enter(const parser::OmpClause::If &x);
184 void Enter(const parser::OmpClause::InReduction &x);
185 void Enter(const parser::OmpClause::IsDevicePtr &x);
186 void Enter(const parser::OmpClause::Lastprivate &x);
187 void Enter(const parser::OmpClause::Linear &x);
188 void Enter(const parser::OmpClause::Looprange &x);
189 void Enter(const parser::OmpClause::Map &x);
190 void Enter(const parser::OmpClause::NumTeams &x);
191 void Enter(const parser::OmpClause::NumThreads &x);
192 void Enter(const parser::OmpClause::OmpxBare &x);
193 void Enter(const parser::OmpClause::OmpxDynCgroupMem &x);
194 void Enter(const parser::OmpClause::Ordered &x);
195 void Enter(const parser::OmpClause::Permutation &x);
196 void Enter(const parser::OmpClause::Priority &x);
197 void Enter(const parser::OmpClause::Private &x);
198 void Enter(const parser::OmpClause::Reduction &x);
199 void Enter(const parser::OmpClause::ReverseOffload &x);
200 void Enter(const parser::OmpClause::Safelen &x);
201 void Enter(const parser::OmpClause::Schedule &x);
202 void Enter(const parser::OmpClause::SelfMaps &x);
203 void Enter(const parser::OmpClause::Shared &x);
204 void Enter(const parser::OmpClause::Simdlen &x);
205 void Enter(const parser::OmpClause::Sizes &x);
206 void Enter(const parser::OmpClause::TaskReduction &x);
207 void Enter(const parser::OmpClause::ThreadLimit &x);
208 void Enter(const parser::OmpClause::To &x);
209 void Enter(const parser::OmpClause::UnifiedAddress &x);
210 void Enter(const parser::OmpClause::UnifiedSharedMemory &x);
211 void Enter(const parser::OmpClause::Update &x);
212 void Enter(const parser::OmpClause::UseDeviceAddr &x);
213 void Enter(const parser::OmpClause::UseDevicePtr &x);
214 void Enter(const parser::OmpClause::When &x);
215
216private:
217 using LoopOrConstruct = std::variant<const parser::DoConstruct *,
219
220 // Most of these functions are defined in check-omp-structure.cpp, but
221 // some groups have their own files.
222
223 // check-omp-atomic.cpp
224 void CheckStorageOverlap(const evaluate::Expr<evaluate::SomeType> &,
226 void ErrorShouldBeVariable(const MaybeExpr &expr, parser::CharBlock source);
227 void CheckAtomicType(SymbolRef sym, parser::CharBlock source,
228 std::string_view name, bool checkTypeOnPointer = true);
229 void CheckAtomicVariable(const evaluate::Expr<evaluate::SomeType> &,
230 parser::CharBlock, bool checkTypeOnPointer = true);
231 std::pair<const parser::ExecutionPartConstruct *,
233 CheckUpdateCapture(const parser::ExecutionPartConstruct *ec1,
235 void CheckAtomicCaptureAssignment(const evaluate::Assignment &capture,
236 const SomeExpr &atom, parser::CharBlock source);
237 void CheckAtomicReadAssignment(
238 const evaluate::Assignment &read, parser::CharBlock source);
239 void CheckAtomicWriteAssignment(
240 const evaluate::Assignment &write, parser::CharBlock source);
241 std::optional<evaluate::Assignment> CheckAtomicUpdateAssignment(
242 const evaluate::Assignment &update, parser::CharBlock source);
243 std::pair<bool, bool> CheckAtomicUpdateAssignmentRhs(const SomeExpr &atom,
244 const SomeExpr &rhs, parser::CharBlock source, bool suppressDiagnostics);
245 void CheckAtomicConditionalUpdateAssignment(const SomeExpr &cond,
246 parser::CharBlock condSource, const evaluate::Assignment &assign,
247 parser::CharBlock assignSource);
248 void CheckAtomicConditionalUpdateStmt(
249 const AnalyzedCondStmt &update, parser::CharBlock source);
250 void CheckAtomicUpdateOnly(const parser::OpenMPAtomicConstruct &x,
251 const parser::Block &body, parser::CharBlock source);
252 void CheckAtomicConditionalUpdate(const parser::OpenMPAtomicConstruct &x,
253 const parser::Block &body, parser::CharBlock source);
254 void CheckAtomicUpdateCapture(const parser::OpenMPAtomicConstruct &x,
255 const parser::Block &body, parser::CharBlock source);
256 void CheckAtomicConditionalUpdateCapture(
257 const parser::OpenMPAtomicConstruct &x, const parser::Block &body,
258 parser::CharBlock source);
259 void CheckAtomicRead(const parser::OpenMPAtomicConstruct &x);
260 void CheckAtomicWrite(const parser::OpenMPAtomicConstruct &x);
261 void CheckAtomicUpdate(const parser::OpenMPAtomicConstruct &x);
262
263 // check-omp-loop.cpp
264 void HasInvalidDistributeNesting(const parser::OpenMPLoopConstruct &x);
265 void HasInvalidLoopBinding(const parser::OpenMPLoopConstruct &x);
266 void CheckSIMDNest(const parser::OpenMPConstruct &x);
267 void CheckRectangularNest(const parser::OmpDirectiveSpecification &spec,
268 const omp::LoopSequence &nest);
269 void CheckNestedConstruct(const parser::OpenMPLoopConstruct &x);
270 const parser::Name GetLoopIndex(const parser::DoConstruct *x);
271 void CheckIterationVariables(const parser::OpenMPLoopConstruct &x);
272 std::int64_t GetOrdCollapseLevel(const parser::OpenMPLoopConstruct &x);
273 void CheckAssociatedLoopConstraints(const parser::OpenMPLoopConstruct &x);
274 void CheckScanModifier(const parser::OmpClause::Reduction &x);
275 void CheckDistLinear(const parser::OpenMPLoopConstruct &x);
276
277 // check-omp-variant.cpp
278 void CheckOmpDeclareVariantDirective(
280 void CheckDeclareVariantUserConditions(const parser::OmpContextSelector &);
281 const std::list<parser::OmpTraitProperty> &GetTraitPropertyList(
283 std::optional<llvm::omp::Clause> GetClauseFromProperty(
285
286 void CheckTraitSelectorList(const std::list<parser::OmpTraitSelector> &);
287 void CheckContextSelectorSpecification(const parser::OmpContextSelector &);
288 void CheckTraitSetSelector(const parser::OmpTraitSetSelector &);
289 void CheckTraitScore(const parser::OmpTraitScore &);
290 bool VerifyTraitPropertyLists(
292 void CheckTraitSelector(
294 void CheckTraitADMO(
296 void CheckTraitCondition(
298 void CheckTraitDeviceNum(
300 void CheckTraitRequires(
302 void CheckTraitSimd(
304
305 // check-omp-structure.cpp
306 using ClauseIterator =
307 decltype(std::declval<const parser::OmpClauseList>().v.begin());
308 bool IsAllowedClause(llvm::omp::Clause clauseId);
309 bool CheckAllowedClause(llvm::omp::Clause clauseId,
310 parser::CharBlock clauseSource, llvm::omp::Directive dirId);
311 void CheckArgumentObjectKind(const parser::OmpClause &x);
312 void CheckDirectiveSpelling(
313 parser::CharBlock spelling, llvm::omp::Directive id);
314 void CheckDirectiveDeprecation(const parser::OpenMPConstruct &x);
315 void CheckClauses(parser::OmpDirectiveName dirName,
316 llvm::iterator_range<ClauseIterator> beginClauses,
317 llvm::iterator_range<ClauseIterator> endClauses);
318 void AnalyzeObject(const parser::OmpObject &object);
319 std::pair<const parser::OmpClause *, const parser::OmpClause *>
320 FindMutuallyExclusiveClauses(OmpClauseSet exclusive,
321 const std::vector<const parser::OmpClause *> &clauses);
322
323 const parser::OpenMPConstruct *GetCurrentConstruct() const;
324 void CheckSourceLabel(const parser::Label &);
325 void CheckLabelContext(const parser::CharBlock, const parser::CharBlock,
327 void ClearLabels();
328 void CheckMultipleOccurrence(semantics::UnorderedSymbolSet &listVars,
329 const std::list<parser::Name> &nameList, const parser::CharBlock &item,
330 const std::string &clauseName);
331 void CheckMultListItems();
332 void CheckStructureComponent(
333 const parser::OmpObject &object, llvm::omp::Clause clauseId);
334 void CheckStructureComponent(
335 const parser::OmpObjectList &objects, llvm::omp::Clause clauseId);
336 bool HasInvalidWorksharingNesting(
337 const parser::OmpDirectiveName &name, const OmpDirectiveSet &);
338
339 bool IsCloselyNestedRegion(const OmpDirectiveSet &set);
340 bool IsNestedInDirective(llvm::omp::Directive directive);
341 bool IsCombinedParallelWorksharing(llvm::omp::Directive directive) const;
342 bool InTargetRegion();
343 void HasInvalidTeamsNesting(
344 const llvm::omp::Directive &dir, const parser::CharBlock &source);
345 bool HasRequires(llvm::omp::Clause req);
346 void CheckAllowedMapTypes(
347 parser::OmpMapType::Value, llvm::ArrayRef<parser::OmpMapType::Value>);
348
349 llvm::StringRef getClauseName(llvm::omp::Clause clause) override;
350 llvm::StringRef getDirectiveName(llvm::omp::Directive directive) override;
351
352 template < //
353 typename LessTy, typename RangeTy,
354 typename IterTy = decltype(std::declval<RangeTy>().begin())>
355 std::optional<IterTy> FindDuplicate(RangeTy &&);
356
357 void CheckDependList(const parser::DataRef &);
358 void CheckDoacross(const parser::OmpDoacross &doa);
359 void CheckDimsModifier(parser::CharBlock source, size_t numValues,
360 const parser::OmpDimsModifier &x);
361 void CheckTypeParamInquiry(const parser::CharBlock &source,
362 const parser::OmpObject &object, llvm::omp::Directive dirId);
363 void CheckTypeParamInquiry(const parser::CharBlock &source,
364 const parser::OmpObject &object, llvm::omp::Clause clauseId);
365 void CheckVarIsNotPartOfAnotherVar(const parser::CharBlock &source,
366 const parser::OmpObject &object, llvm::StringRef clause = "");
367 void CheckVarIsNotPartOfAnotherVar(const parser::CharBlock &source,
368 const parser::OmpObjectList &objList, llvm::StringRef clause = "");
369 void CheckThreadprivateOrDeclareTargetVar(const parser::Designator &);
370 void CheckThreadprivateOrDeclareTargetVar(const parser::Name &);
371 void CheckThreadprivateOrDeclareTargetVar(const parser::OmpObject &);
372 void CheckThreadprivateOrDeclareTargetVar(const parser::OmpObjectList &);
373 void CheckIntentInPointer(SymbolSourceMap &, const llvm::omp::Clause);
374 void CheckProcedurePointer(SymbolSourceMap &, const llvm::omp::Clause);
375 void CheckCrayPointee(const parser::OmpObjectList &objectList,
376 llvm::StringRef clause, bool suggestToUseCrayPointer = true);
377 void GetSymbolsInObjectList(const parser::OmpObjectList &, SymbolSourceMap &);
378 void CheckDefinableObjects(SymbolSourceMap &, const llvm::omp::Clause);
379 void CheckCopyingPolymorphicAllocatable(
380 SymbolSourceMap &, const llvm::omp::Clause);
381 void CheckPrivateSymbolsInOuterCxt(
382 SymbolSourceMap &, DirectivesClauseTriple &, const llvm::omp::Clause);
383 bool CheckTargetBlockOnlyTeams(const parser::Block &);
384 void CheckWorkshareBlockStmts(const parser::Block &, parser::CharBlock);
385 void CheckWorkdistributeBlockStmts(const parser::Block &, parser::CharBlock);
386 void CheckIndividualAllocateDirective(
387 const parser::OmpAllocateDirective &x, bool isExecutable);
388 void CheckExecutableAllocateDirective(const parser::OmpAllocateDirective &x);
389
390 void CheckIteratorRange(const parser::OmpIteratorSpecifier &x);
391 void CheckIteratorModifier(const parser::OmpIterator &x);
392
393 void CheckTargetNest(const parser::OpenMPConstruct &x);
394 void CheckTargetUpdate();
395 void CheckTaskgraph(const parser::OmpBlockConstruct &x);
396 void CheckDependenceType(const parser::OmpDependenceType::Value &x);
397 void CheckTaskDependenceType(const parser::OmpTaskDependenceType::Value &x);
398 std::optional<llvm::omp::Directive> GetCancelType(
399 llvm::omp::Directive cancelDir, const parser::CharBlock &cancelSource,
400 const std::optional<parser::OmpClauseList> &maybeClauses);
401 void CheckCancellationNest(
402 const parser::CharBlock &source, llvm::omp::Directive type);
403 void CheckReductionObjects(
404 const parser::OmpObjectList &objects, llvm::omp::Clause clauseId);
405 bool CheckReductionOperator(const parser::OmpReductionIdentifier &ident,
406 parser::CharBlock source, llvm::omp::Clause clauseId);
407 void CheckReductionObjectTypes(const parser::OmpObjectList &objects,
408 const parser::OmpReductionIdentifier &ident);
409 void CheckReductionModifier(const parser::OmpReductionModifier &);
410 void CheckLastprivateModifier(const parser::OmpLastprivateModifier &);
411 void CheckSingleConstruct(const parser::OmpBlockConstruct &x);
412 void CheckMasterNesting(const parser::OmpBlockConstruct &x);
413 void ChecksOnOrderedAsBlock();
414 void CheckBarrierNesting(const parser::OpenMPSimpleStandaloneConstruct &x);
415 void CheckScan(const parser::OpenMPSimpleStandaloneConstruct &x);
416 void ChecksOnOrderedAsStandalone();
417 void CheckOrderedDependClause(std::optional<std::int64_t> orderedValue);
418 void CheckReductionArraySection(
419 const parser::OmpObjectList &ompObjectList, llvm::omp::Clause clauseId);
420 void CheckArraySection(const parser::ArrayElement &arrayElement,
421 const parser::Name &name, const llvm::omp::Clause clause);
422 void CheckLastPartRefForArraySection(
423 const parser::Designator &designator, llvm::omp::Clause clauseId);
424 void CheckSharedBindingInOuterContext(
425 const parser::OmpObjectList &ompObjectList);
426 void CheckIfContiguous(const parser::OmpObject &object);
427 const parser::Name *GetObjectName(const parser::OmpObject &object);
428 void CheckInitOnDepobj(const parser::OpenMPDepobjConstruct &depobj,
429 const parser::OmpClause &initClause);
430 void CheckAllowedRequiresClause(llvm::omp::Clause clause);
431 void AddEndDirectiveClauses(const parser::OmpClauseList &clauses);
432 void CheckTempDescriptorMappings();
433
434 void EnterDirectiveNest(const int index) { directiveNest_[index]++; }
435 void ExitDirectiveNest(const int index) { directiveNest_[index]--; }
436 int GetDirectiveNest(const int index) { return directiveNest_[index]; }
437
438 bool deviceConstructFound_{false};
439 enum directiveNestType : int {
440 SIMDNest,
441 TargetBlockOnlyTeams,
442 TargetNest,
443 DeclarativeNest,
444 ContextSelectorNest,
445 MetadirectiveNest,
446 LastType = MetadirectiveNest,
447 };
448 int directiveNest_[LastType + 1] = {0};
449
450 std::set<std::pair<const Symbol *, const Symbol *>> declareVariantPairs_;
451
452 int allocateDirectiveLevel_{0};
453 parser::CharBlock visitedAtomicSource_;
454
455 // Mapping of directive-name-modifier constituents to the sources of the
456 // IF clauses that referenced them. If there was no modifier, the entire
457 // directive is assumed to be listed.
458 std::map<llvm::omp::Directive, parser::CharBlock> ifLeafs_;
459
460 // Track symbols with temporary stack descriptors mapped in TARGET ENTER DATA
461 // and symbols mapped in TARGET EXIT DATA within the current function scope.
462 // Used to warn about potential issues with mapping temporary descriptors.
463 std::multimap<const Symbol *, parser::CharBlock> tempDescriptorEnterMaps_;
464 std::set<const Symbol *> tempDescriptorExitMaps_;
465
466 // Stack of nested DO loops and OpenMP constructs.
467 // This is used to verify DO loop nest for DOACROSS, and branches into
468 // and out of OpenMP constructs.
469 std::vector<LoopOrConstruct> constructStack_;
470 // Scopes for scoping units.
471 std::vector<const Scope *> scopeStack_;
472 // Stack of directive specifications (except for SECTION).
473 // This is to allow visitor functions to see all specified clauses, since
474 // they are only recorded in DirectiveContext as they are processed.
475 std::vector<const parser::OmpDirectiveSpecification *> dirStack_;
476
477 enum class PartKind : int {
478 // There are also other "parts", such as internal-subprogram-part, etc,
479 // but we're keeping track of these two for now.
480 SpecificationPart,
481 ExecutionPart,
482 };
483 std::vector<PartKind> partStack_;
484
485 std::multimap<const parser::Label,
486 std::pair<parser::CharBlock, const parser::OpenMPConstruct *>>
487 sourceLabels_;
488 std::map<const parser::Label,
489 std::pair<parser::CharBlock, const parser::OpenMPConstruct *>>
490 targetLabels_;
491 parser::CharBlock currentStatementSource_;
492};
493
494template <typename A>
495void OmpStructureChecker::Enter(const parser::Statement<A> &statement) {
496 currentStatementSource_ = statement.source;
497 // Keep track of the labels in all the labelled statements
498 if (statement.label) {
499 auto label{statement.label.value()};
500 // Get the context to check if the labelled statement is in an
501 // enclosing OpenMP construct
502 auto *thisConstruct{GetCurrentConstruct()};
503 targetLabels_.emplace(
504 label, std::make_pair(currentStatementSource_, thisConstruct));
505 // Check if a statement that causes a jump to the 'label'
506 // has already been encountered
507 auto range{sourceLabels_.equal_range(label)};
508 for (auto it{range.first}; it != range.second; ++it) {
509 // Check if both the statement with 'label' and the statement that
510 // causes a jump to the 'label' are in the same scope
511 CheckLabelContext(it->second.first, currentStatementSource_,
512 it->second.second, thisConstruct);
513 }
514 }
515}
516
519template <typename LessTy, typename RangeTy, typename IterTy>
520std::optional<IterTy> OmpStructureChecker::FindDuplicate(RangeTy &&range) {
521 // Deal with iterators, since the actual elements may be rvalues (i.e.
522 // have no addresses), for example with custom-constructed ranges that
523 // are not simple c.begin()..c.end().
524 std::set<IterTy, LessTy> uniq;
525 for (auto it{range.begin()}, end{range.end()}; it != end; ++it) {
526 if (!uniq.insert(it).second) {
527 return it;
528 }
529 }
530 return std::nullopt;
531}
532} // namespace Fortran::semantics
533#endif // FORTRAN_SEMANTICS_CHECK_OMP_STRUCTURE_H_
Definition enum-set.h:28
Definition expression.h:921
Definition common.h:215
Definition char-block.h:28
Definition check-directive-structure.h:208
Definition semantics.h:68
Definition FIRType.h:103
Definition parse-tree.h:3538
Definition parse-tree.h:1939
Definition parse-tree.h:3548
Definition parse-tree.h:2223
Definition parse-tree.h:3062
Definition parse-tree.h:2551
Definition parse-tree.h:1849
Definition parse-tree.h:1888
Definition parse-tree.h:2366
Definition parse-tree.h:559
Definition parse-tree.h:3182
Definition parse-tree.h:468
Definition parse-tree.h:2970
Definition parse-tree.h:2984
Definition parse-tree.h:3006
Definition parse-tree.h:592
Definition parse-tree.h:5366
Definition parse-tree.h:5155
Definition parse-tree.h:5165
Definition parse-tree.h:5124
Definition parse-tree.h:5108
Definition parse-tree.h:5293
Definition parse-tree.h:5310
Definition parse-tree.h:5285
Definition parse-tree.h:3574
Definition parse-tree.h:5131
Definition parse-tree.h:4555
Definition parse-tree.h:5319
Definition parse-tree.h:5178
Definition parse-tree.h:3629
Definition parse-tree.h:3617
Definition parse-tree.h:3673
Definition parse-tree.h:5326
Definition parse-tree.h:5332
Definition parse-tree.h:5392
Definition parse-tree.h:5397
Definition parse-tree.h:5434
Definition parse-tree.h:5518
Definition parse-tree.h:5382
Definition parse-tree.h:5445
Definition parse-tree.h:5459
Definition parse-tree.h:5475
Definition parse-tree.h:5483
Definition parse-tree.h:5536
Definition parse-tree.h:5504
Definition parse-tree.h:5250
Definition parse-tree.h:576
Definition parse-tree.h:456
Definition parse-tree.h:362
Definition parse-tree.h:3048
Definition parse-tree.h:3201
Definition parse-tree.h:4057
Definition parse-tree.h:4123
Definition parse-tree.h:4133
Definition parse-tree.h:4141
Definition parse-tree.h:4282
Definition parse-tree.h:3810
Definition parse-tree.h:3776
Definition parse-tree.h:3849
Definition parse-tree.h:3871
Definition check-omp-atomic.cpp:242
Definition openmp-utils.h:349