69class OmpStructureChecker :
public OmpStructureCheckerBase {
71 using Base = OmpStructureCheckerBase;
86 void Enter(
const parser::EndSubroutineStmt &);
88 void Enter(
const parser::EndFunctionStmt &);
89 void Enter(
const parser::MpSubprogramStmt &);
90 void Enter(
const parser::EndMpSubprogramStmt &);
91 void Enter(
const parser::Block &);
92 void Leave(
const parser::Block &);
103 void Enter(
const parser::ExecutionPart &);
104 void Leave(
const parser::ExecutionPart &);
166 void Leave(
const parser::OmpClause::When &);
168 void Enter(
const parser::OmpContextSelector &);
169 void Leave(
const parser::OmpContextSelector &);
173 void Enter(
const parser::OmpClause::Apply &);
174 void Leave(
const parser::OmpClause::Apply &);
177 void Leave(
const parser::GotoStmt &);
181 void Leave(
const parser::AltReturnSpec &);
182 void Leave(
const parser::ErrLabel &);
183 void Leave(
const parser::EndLabel &);
184 void Leave(
const parser::EorLabel &);
186 void Enter(
const parser::OmpClause::Affinity &x);
187 void Enter(
const parser::OmpClause::Align &x);
188 void Enter(
const parser::OmpClause::Aligned &x);
189 void Enter(
const parser::OmpClause::Allocate &x);
190 void Enter(
const parser::OmpClause::Allocator &x);
191 void Enter(
const parser::OmpClause::At &x);
192 void Enter(
const parser::OmpClause::AtomicDefaultMemOrder &x);
193 void Enter(
const parser::OmpClause::CancellationConstructType &x);
194 void Enter(
const parser::OmpClause::Collapse &x);
195 void Enter(
const parser::OmpClause::Copyin &x);
196 void Enter(
const parser::OmpClause::Copyprivate &x);
197 void Enter(
const parser::OmpClause::Defaultmap &x);
198 void Enter(
const parser::OmpClause::Depend &x);
199 void Enter(
const parser::OmpClause::Depth &x);
200 void Enter(
const parser::OmpClause::Destroy &x);
201 void Enter(
const parser::OmpClause::Detach &x);
202 void Enter(
const parser::OmpClause::DeviceSafesync &x);
203 void Enter(
const parser::OmpClause::Device &x);
204 void Enter(
const parser::OmpClause::Doacross &x);
205 void Enter(
const parser::OmpClause::DynamicAllocators &x);
206 void Enter(
const parser::OmpClause::DynGroupprivate &x);
207 void Enter(
const parser::OmpClause::Enter &x);
208 void Enter(
const parser::OmpClause::Firstprivate &x);
209 void Enter(
const parser::OmpClause::From &x);
210 void Enter(
const parser::OmpClause::HasDeviceAddr &x);
211 void Enter(
const parser::OmpClause::Hint &x);
212 void Enter(
const parser::OmpClause::If &x);
213 void Enter(
const parser::OmpClause::InReduction &x);
214 void Enter(
const parser::OmpClause::IsDevicePtr &x);
215 void Enter(
const parser::OmpClause::Lastprivate &x);
216 void Enter(
const parser::OmpClause::Linear &x);
217 void Enter(
const parser::OmpClause::Looprange &x);
218 void Enter(
const parser::OmpClause::Map &x);
219 void Enter(
const parser::OmpClause::Message &x);
220 void Enter(
const parser::OmpClause::NumTeams &x);
221 void Enter(
const parser::OmpClause::NumThreads &x);
222 void Enter(
const parser::OmpClause::OmpxBare &x);
223 void Enter(
const parser::OmpClause::OmpxDynCgroupMem &x);
224 void Enter(
const parser::OmpClause::Ordered &x);
225 void Enter(
const parser::OmpClause::Permutation &x);
226 void Enter(
const parser::OmpClause::Priority &x);
227 void Enter(
const parser::OmpClause::Private &x);
228 void Enter(
const parser::OmpClause::Reduction &x);
229 void Enter(
const parser::OmpClause::ReverseOffload &x);
230 void Enter(
const parser::OmpClause::Safelen &x);
231 void Enter(
const parser::OmpClause::Schedule &x);
232 void Enter(
const parser::OmpClause::SelfMaps &x);
233 void Enter(
const parser::OmpClause::Shared &x);
234 void Enter(
const parser::OmpClause::Simdlen &x);
235 void Enter(
const parser::OmpClause::Sizes &x);
236 void Enter(
const parser::OmpClause::TaskReduction &x);
237 void Enter(
const parser::OmpClause::ThreadLimit &x);
238 void Enter(
const parser::OmpClause::To &x);
239 void Enter(
const parser::OmpClause::UnifiedAddress &x);
240 void Enter(
const parser::OmpClause::UnifiedSharedMemory &x);
241 void Enter(
const parser::OmpClause::Update &x);
242 void Enter(
const parser::OmpClause::UseDeviceAddr &x);
243 void Enter(
const parser::OmpClause::UseDevicePtr &x);
244 void Enter(
const parser::OmpClause::When &x);
258 std::string_view name,
bool checkTypeOnPointer =
true);
267 void CheckAtomicReadAssignment(
269 void CheckAtomicWriteAssignment(
271 std::optional<evaluate::Assignment> CheckAtomicUpdateAssignment(
273 std::pair<bool, bool> CheckAtomicUpdateAssignmentRhs(
const SomeExpr &atom,
275 void CheckAtomicConditionalUpdateAssignment(
const SomeExpr &cond,
278 void CheckAtomicConditionalUpdateStmt(
286 void CheckAtomicConditionalUpdateCapture(
304 void CheckScanModifier(
const parser::OmpClause::Reduction &x);
307 void BeginMetadirectiveVariantScope();
308 void EndMetadirectiveVariantScope();
311 void CheckMetadirectiveVariantsWithoutLoop(std::size_t firstVariant = 0);
312 void CheckOmpDeclareVariantDirective(
314 void CheckDeclareVariantUserConditions(
const parser::OmpContextSelector &);
315 const std::list<parser::OmpTraitProperty> &GetTraitPropertyList(
317 std::optional<llvm::omp::Clause> GetClauseFromProperty(
320 void CheckTraitSelectorList(
const std::list<parser::OmpTraitSelector> &);
321 void CheckContextSelectorSpecification(
const parser::OmpContextSelector &);
324 bool VerifyTraitPropertyLists(
326 void CheckTraitSelector(
330 void CheckTraitCondition(
332 void CheckTraitDeviceNum(
334 void CheckTraitRequires(
340 using ClauseIterator =
341 decltype(std::declval<const parser::OmpClauseList>().v.begin());
342 bool IsAllowedClause(llvm::omp::Clause clauseId);
343 bool CheckAllowedClause(llvm::omp::Clause clauseId,
346 void CheckDirectiveSpelling(
350 llvm::iterator_range<ClauseIterator> beginClauses,
351 llvm::iterator_range<ClauseIterator> endClauses);
353 std::pair<const parser::OmpClause *, const parser::OmpClause *>
354 FindMutuallyExclusiveClauses(llvm::omp::ClauseSet exclusive,
355 const std::vector<const parser::OmpClause *> &clauses);
358 void CheckSourceLabel(
const parser::Label &);
362 void CheckMultipleOccurrence(semantics::UnorderedSymbolSet &listVars,
364 const std::string &clauseName);
365 void CheckMultListItems();
366 void CheckStructureComponent(
368 void CheckStructureComponent(
370 bool HasInvalidWorksharingNesting(
373 bool IsCloselyNestedRegion(
const llvm::omp::DirectiveSet &set);
374 bool IsNestedInDirective(llvm::omp::Directive directive);
375 bool IsCombinedParallelWorksharing(llvm::omp::Directive directive)
const;
376 bool InTargetRegion();
377 void HasInvalidTeamsNesting(
379 bool HasRequires(llvm::omp::Clause req);
380 void CheckAllowedMapTypes(
383 llvm::StringRef getClauseName(llvm::omp::Clause clause)
override;
384 llvm::StringRef getDirectiveName(llvm::omp::Directive directive)
override;
387 typename LessTy,
typename RangeTy,
388 typename IterTy =
decltype(std::declval<RangeTy>().begin())>
389 std::optional<IterTy> FindDuplicate(RangeTy &&);
404 void CheckThreadprivateOrDeclareTargetVar(
const parser::Name &);
407 void CheckIntentInPointer(SymbolSourceMap &,
const llvm::omp::Clause);
408 void CheckProcedurePointer(SymbolSourceMap &,
const llvm::omp::Clause);
410 llvm::StringRef clause,
bool suggestToUseCrayPointer =
true);
412 void CheckDefaultNoneInAssociatedLoop(
414 UnorderedSymbolSet &diagnosed);
415 void CheckDefinableObjects(SymbolSourceMap &,
const llvm::omp::Clause);
416 void CheckCopyingPolymorphicAllocatable(
417 SymbolSourceMap &,
const llvm::omp::Clause);
418 void CheckPrivateSymbolsInOuterCxt(
419 SymbolSourceMap &, DirectivesClauseTriple &,
const llvm::omp::Clause);
420 bool CheckTargetBlockOnlyTeams(
const parser::Block &);
423 void CheckIndividualAllocateDirective(
431 void CheckTargetUpdate();
433 void CheckDependenceType(
const parser::OmpDependenceType::Value &x);
434 void CheckTaskDependenceType(
const parser::OmpTaskDependenceType::Value &x);
435 std::optional<llvm::omp::Directive> GetCancelType(
437 const std::optional<parser::OmpClauseList> &maybeClauses);
438 void CheckCancellationNest(
440 void CheckReductionObjects(
450 void ChecksOnOrderedAsBlock();
453 void ChecksOnOrderedAsStandalone();
454 void CheckOrderedDependClause(std::optional<std::int64_t> orderedValue);
455 void CheckReductionArraySection(
458 const parser::Name &name,
const llvm::omp::Clause clause);
459 void CheckLastPartRefForArraySection(
461 void CheckSharedBindingInOuterContext(
467 void CheckAllowedRequiresClause(llvm::omp::Clause clause);
469 void CheckTempDescriptorMappings();
471 void EnterDirectiveNest(
const int index) { directiveNest_[index]++; }
472 void ExitDirectiveNest(
const int index) { directiveNest_[index]--; }
473 int GetDirectiveNest(
const int index) {
return directiveNest_[index]; }
475 bool deviceConstructFound_{
false};
476 enum directiveNestType :
int {
479 TargetBlockOnlyTeams,
484 LastType = MetadirectiveNest,
486 int directiveNest_[LastType + 1] = {0};
488 std::set<std::pair<const Symbol *, const Symbol *>> declareVariantPairs_;
497 declareVariantConstructSets_;
499 std::set<const Symbol *> declareVariantBases_;
501 int allocateDirectiveLevel_{0};
507 std::map<llvm::omp::Directive, parser::CharBlock> ifLeafs_;
512 std::multimap<const Symbol *, parser::CharBlock> tempDescriptorEnterMaps_;
513 std::set<const Symbol *> tempDescriptorExitMaps_;
518 std::vector<LoopOrConstruct> constructStack_;
520 std::vector<const Scope *> scopeStack_;
524 std::vector<const parser::OmpDirectiveSpecification *> dirStack_;
526 enum class PartKind :
int {
532 std::vector<PartKind> partStack_;
534 struct MetadirectiveLoopVariant {
537 bool checkDefaultNoneInAssociatedLoop;
539 std::vector<MetadirectiveLoopVariant> metadirectiveLoopVariants_;
540 std::vector<std::size_t> metadirectiveVariantScopeStarts_;
544 std::multimap<
const parser::Label,
545 std::pair<parser::CharBlock, const parser::OpenMPConstruct *>>
547 std::map<
const parser::Label,
548 std::pair<parser::CharBlock, const parser::OpenMPConstruct *>>