56class OmpStructureChecker :
public OmpStructureCheckerBase {
58 using Base = OmpStructureCheckerBase;
72 void Enter(
const parser::EndSubroutineStmt &);
74 void Enter(
const parser::EndFunctionStmt &);
75 void Enter(
const parser::MpSubprogramStmt &);
76 void Enter(
const parser::EndMpSubprogramStmt &);
84 void Enter(
const parser::ExecutionPart &);
85 void Leave(
const parser::ExecutionPart &);
144 void Enter(
const parser::OmpContextSelector &);
145 void Leave(
const parser::OmpContextSelector &);
148 void Leave(
const parser::GotoStmt &);
152 void Leave(
const parser::AltReturnSpec &);
153 void Leave(
const parser::ErrLabel &);
154 void Leave(
const parser::EndLabel &);
155 void Leave(
const parser::EorLabel &);
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);
228 std::string_view name,
bool checkTypeOnPointer =
true);
237 void CheckAtomicReadAssignment(
239 void CheckAtomicWriteAssignment(
241 std::optional<evaluate::Assignment> CheckAtomicUpdateAssignment(
243 std::pair<bool, bool> CheckAtomicUpdateAssignmentRhs(
const SomeExpr &atom,
245 void CheckAtomicConditionalUpdateAssignment(
const SomeExpr &cond,
248 void CheckAtomicConditionalUpdateStmt(
256 void CheckAtomicConditionalUpdateCapture(
274 void CheckScanModifier(
const parser::OmpClause::Reduction &x);
278 void CheckOmpDeclareVariantDirective(
280 void CheckDeclareVariantUserConditions(
const parser::OmpContextSelector &);
281 const std::list<parser::OmpTraitProperty> &GetTraitPropertyList(
283 std::optional<llvm::omp::Clause> GetClauseFromProperty(
286 void CheckTraitSelectorList(
const std::list<parser::OmpTraitSelector> &);
287 void CheckContextSelectorSpecification(
const parser::OmpContextSelector &);
290 bool VerifyTraitPropertyLists(
292 void CheckTraitSelector(
296 void CheckTraitCondition(
298 void CheckTraitDeviceNum(
300 void CheckTraitRequires(
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,
312 void CheckDirectiveSpelling(
316 llvm::iterator_range<ClauseIterator> beginClauses,
317 llvm::iterator_range<ClauseIterator> endClauses);
319 std::pair<const parser::OmpClause *, const parser::OmpClause *>
320 FindMutuallyExclusiveClauses(OmpClauseSet exclusive,
321 const std::vector<const parser::OmpClause *> &clauses);
324 void CheckSourceLabel(
const parser::Label &);
328 void CheckMultipleOccurrence(semantics::UnorderedSymbolSet &listVars,
330 const std::string &clauseName);
331 void CheckMultListItems();
332 void CheckStructureComponent(
334 void CheckStructureComponent(
336 bool HasInvalidWorksharingNesting(
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(
345 bool HasRequires(llvm::omp::Clause req);
346 void CheckAllowedMapTypes(
349 llvm::StringRef getClauseName(llvm::omp::Clause clause)
override;
350 llvm::StringRef getDirectiveName(llvm::omp::Directive directive)
override;
353 typename LessTy,
typename RangeTy,
354 typename IterTy =
decltype(std::declval<RangeTy>().begin())>
355 std::optional<IterTy> FindDuplicate(RangeTy &&);
370 void CheckThreadprivateOrDeclareTargetVar(
const parser::Name &);
373 void CheckIntentInPointer(SymbolSourceMap &,
const llvm::omp::Clause);
374 void CheckProcedurePointer(SymbolSourceMap &,
const llvm::omp::Clause);
376 llvm::StringRef clause,
bool suggestToUseCrayPointer =
true);
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 &);
386 void CheckIndividualAllocateDirective(
394 void CheckTargetUpdate();
396 void CheckDependenceType(
const parser::OmpDependenceType::Value &x);
397 void CheckTaskDependenceType(
const parser::OmpTaskDependenceType::Value &x);
398 std::optional<llvm::omp::Directive> GetCancelType(
400 const std::optional<parser::OmpClauseList> &maybeClauses);
401 void CheckCancellationNest(
403 void CheckReductionObjects(
413 void ChecksOnOrderedAsBlock();
416 void ChecksOnOrderedAsStandalone();
417 void CheckOrderedDependClause(std::optional<std::int64_t> orderedValue);
418 void CheckReductionArraySection(
421 const parser::Name &name,
const llvm::omp::Clause clause);
422 void CheckLastPartRefForArraySection(
424 void CheckSharedBindingInOuterContext(
430 void CheckAllowedRequiresClause(llvm::omp::Clause clause);
432 void CheckTempDescriptorMappings();
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]; }
438 bool deviceConstructFound_{
false};
439 enum directiveNestType :
int {
441 TargetBlockOnlyTeams,
446 LastType = MetadirectiveNest,
448 int directiveNest_[LastType + 1] = {0};
450 std::set<std::pair<const Symbol *, const Symbol *>> declareVariantPairs_;
452 int allocateDirectiveLevel_{0};
458 std::map<llvm::omp::Directive, parser::CharBlock> ifLeafs_;
463 std::multimap<const Symbol *, parser::CharBlock> tempDescriptorEnterMaps_;
464 std::set<const Symbol *> tempDescriptorExitMaps_;
469 std::vector<LoopOrConstruct> constructStack_;
471 std::vector<const Scope *> scopeStack_;
475 std::vector<const parser::OmpDirectiveSpecification *> dirStack_;
477 enum class PartKind :
int {
483 std::vector<PartKind> partStack_;
485 std::multimap<
const parser::Label,
486 std::pair<parser::CharBlock, const parser::OpenMPConstruct *>>
488 std::map<
const parser::Label,
489 std::pair<parser::CharBlock, const parser::OpenMPConstruct *>>