88class OmpStructureChecker :
public OmpStructureCheckerBase {
90 using Base = OmpStructureCheckerBase;
105 void Enter(
const parser::EndSubroutineStmt &);
107 void Enter(
const parser::EndFunctionStmt &);
108 void Enter(
const parser::MpSubprogramStmt &);
109 void Enter(
const parser::EndMpSubprogramStmt &);
110 void Enter(
const parser::Block &);
111 void Leave(
const parser::Block &);
122 void Enter(
const parser::ExecutionPart &);
123 void Leave(
const parser::ExecutionPart &);
185 void Leave(
const parser::OmpClause::When &);
187 void Enter(
const parser::OmpContextSelector &);
188 void Leave(
const parser::OmpContextSelector &);
192 void Enter(
const parser::OmpClause::Apply &);
193 void Leave(
const parser::OmpClause::Apply &);
196 void Leave(
const parser::GotoStmt &);
200 void Leave(
const parser::AltReturnSpec &);
201 void Leave(
const parser::ErrLabel &);
202 void Leave(
const parser::EndLabel &);
203 void Leave(
const parser::EorLabel &);
205 void Enter(
const parser::OmpClause::Affinity &x);
206 void Enter(
const parser::OmpClause::Align &x);
207 void Enter(
const parser::OmpClause::Aligned &x);
208 void Enter(
const parser::OmpClause::Allocate &x);
209 void Enter(
const parser::OmpClause::Allocator &x);
210 void Enter(
const parser::OmpClause::At &x);
211 void Enter(
const parser::OmpClause::AtomicDefaultMemOrder &x);
212 void Enter(
const parser::OmpClause::CancellationConstructType &x);
213 void Enter(
const parser::OmpClause::Collapse &x);
214 void Enter(
const parser::OmpClause::Copyin &x);
215 void Enter(
const parser::OmpClause::Copyprivate &x);
216 void Enter(
const parser::OmpClause::Defaultmap &x);
217 void Enter(
const parser::OmpClause::Depend &x);
218 void Enter(
const parser::OmpClause::Depth &x);
219 void Enter(
const parser::OmpClause::Destroy &x);
220 void Enter(
const parser::OmpClause::Detach &x);
221 void Enter(
const parser::OmpClause::DeviceSafesync &x);
222 void Enter(
const parser::OmpClause::Device &x);
223 void Enter(
const parser::OmpClause::Doacross &x);
224 void Enter(
const parser::OmpClause::DynamicAllocators &x);
225 void Enter(
const parser::OmpClause::Firstprivate &x);
226 void Enter(
const parser::OmpClause::From &x);
227 void Enter(
const parser::OmpClause::HasDeviceAddr &x);
228 void Enter(
const parser::OmpClause::Hint &x);
229 void Enter(
const parser::OmpClause::If &x);
230 void Enter(
const parser::OmpClause::InReduction &x);
231 void Enter(
const parser::OmpClause::IsDevicePtr &x);
232 void Enter(
const parser::OmpClause::Lastprivate &x);
233 void Enter(
const parser::OmpClause::Linear &x);
234 void Enter(
const parser::OmpClause::Looprange &x);
235 void Enter(
const parser::OmpClause::Map &x);
236 void Enter(
const parser::OmpClause::Message &x);
237 void Enter(
const parser::OmpClause::NumTeams &x);
238 void Enter(
const parser::OmpClause::NumThreads &x);
239 void Enter(
const parser::OmpClause::OmpxBare &x);
240 void Enter(
const parser::OmpClause::OmpxDynCgroupMem &x);
241 void Enter(
const parser::OmpClause::Ordered &x);
242 void Enter(
const parser::OmpClause::Permutation &x);
243 void Enter(
const parser::OmpClause::Priority &x);
244 void Enter(
const parser::OmpClause::Private &x);
245 void Enter(
const parser::OmpClause::Reduction &x);
246 void Enter(
const parser::OmpClause::ReverseOffload &x);
247 void Enter(
const parser::OmpClause::Safelen &x);
248 void Enter(
const parser::OmpClause::Schedule &x);
249 void Enter(
const parser::OmpClause::SelfMaps &x);
250 void Enter(
const parser::OmpClause::Shared &x);
251 void Enter(
const parser::OmpClause::Simdlen &x);
252 void Enter(
const parser::OmpClause::Sizes &x);
253 void Enter(
const parser::OmpClause::TaskReduction &x);
254 void Enter(
const parser::OmpClause::ThreadLimit &x);
255 void Enter(
const parser::OmpClause::To &x);
256 void Enter(
const parser::OmpClause::UnifiedAddress &x);
257 void Enter(
const parser::OmpClause::UnifiedSharedMemory &x);
258 void Enter(
const parser::OmpClause::UpdateDependObjects &x);
259 void Enter(
const parser::OmpClause::UseDeviceAddr &x);
260 void Enter(
const parser::OmpClause::UseDevicePtr &x);
261 void Enter(
const parser::OmpClause::UsesAllocators &x);
262 void Enter(
const parser::OmpClause::When &x);
274 bool isError =
false);
277 std::string_view name,
bool checkTypeOnPointer =
true);
286 void CheckAtomicReadAssignment(
288 void CheckAtomicWriteAssignment(
290 std::optional<evaluate::Assignment> CheckAtomicUpdateAssignment(
292 std::pair<bool, bool> CheckAtomicUpdateAssignmentRhs(
const SomeExpr &atom,
294 void CheckAtomicConditionalUpdateAssignment(
const SomeExpr &cond,
297 void CheckAtomicConditionalUpdateStmt(
305 void CheckAtomicConditionalUpdateCapture(
323 void CheckScanModifier(
const parser::OmpClause::Reduction &x);
329 void BeginMetadirectiveVariantScope();
330 void EndMetadirectiveVariantScope();
333 void CheckMetadirectiveVariantsWithoutLoop(std::size_t firstVariant = 0);
334 void CheckOmpDeclareVariantDirective(
336 void CheckDeclareVariantUserConditions(
const parser::OmpContextSelector &);
337 const std::list<parser::OmpTraitProperty> &GetTraitPropertyList(
339 std::optional<llvm::omp::Clause> GetClauseFromProperty(
342 void CheckTraitSelectorList(
const std::list<parser::OmpTraitSelector> &);
343 void CheckContextSelectorSpecification(
const parser::OmpContextSelector &);
346 bool VerifyTraitPropertyLists(
348 void CheckTraitSelector(
352 void CheckTraitCondition(
354 void CheckTraitDeviceNum(
356 void CheckTraitRequires(
362 bool VerifyClauseVersion(
365 const AppliedClauseInfo &info, llvm::omp::Version version);
367 const AppliedClauseInfo &info, llvm::omp::Version version);
369 const AppliedClauseInfo &info, llvm::omp::Version version);
371 const AppliedClauseInfo &info, llvm::omp::Version version);
373 const AppliedClauseInfo &info, llvm::omp::Version version);
378 const AppliedModifierInfo &info);
380 const AppliedModifierInfo &info, llvm::omp::Version version);
382 const AppliedModifierInfo &info, llvm::omp::Version version);
383 bool VerifyModifierExclusive(
385 const AppliedModifierInfo &info, llvm::omp::Version version);
387 const AppliedModifierInfo &info, llvm::omp::Version version);
389 const AppliedModifierInfo &info, llvm::omp::Version version);
392 void SetAllowedClauseOverride(llvm::omp::Clause clauseId,
393 llvm::omp::Directive dirId,
394 llvm::omp::Version since = llvm::omp::Version());
397 using ClauseIterator =
398 decltype(std::declval<const parser::OmpClauseList>().v.begin());
399 bool IsAllowedClause(llvm::omp::Clause clauseId);
401 void CheckDirectiveSpelling(
403 void CheckCompoundDirective(
408 llvm::omp::Directive
id,
const char *where,
414 void AddClauses(llvm::iterator_range<ClauseIterator> beginClauses,
415 llvm::iterator_range<ClauseIterator> endClauses);
420 void CheckSourceLabel(
const parser::Label &);
424 void CheckMultipleOccurrence(semantics::UnorderedSymbolSet &listVars,
426 const std::string &clauseName);
427 void CheckMultListItems();
428 void CheckStructureComponent(
430 void CheckStructureComponent(
432 bool HasInvalidWorksharingNesting(
435 bool IsCloselyNestedRegion(
const llvm::omp::Directives &set);
436 bool IsNestedInDirective(llvm::omp::Directive directive);
437 bool IsCombinedParallelWorksharing(llvm::omp::Directive directive)
const;
438 bool InTargetRegion();
439 void HasInvalidTeamsNesting(
441 bool HasRequires(llvm::omp::Clause req);
442 void CheckAllowedMapTypes(
444 void CheckCloseModifierOnMapMembers();
446 llvm::StringRef getClauseName(llvm::omp::Clause clause)
override;
447 llvm::StringRef getDirectiveName(llvm::omp::Directive directive)
override;
450 typename LessTy,
typename RangeTy,
451 typename IterTy =
decltype(std::declval<RangeTy>().begin())>
452 std::optional<IterTy> FindDuplicate(RangeTy &&);
463 bool checkSubstrings =
true);
466 bool checkSubstrings =
true);
468 void CheckThreadprivateOrDeclareTargetVar(
const parser::Name &);
471 void CheckIntentInPointer(SymbolSourceMap &,
const llvm::omp::Clause);
472 void CheckProcedurePointer(SymbolSourceMap &,
const llvm::omp::Clause);
474 llvm::StringRef clause,
bool suggestToUseCrayPointer =
true);
476 void CheckDefaultNoneInAssociatedLoop(
478 UnorderedSymbolSet &diagnosed);
479 void CheckDefinableObjects(SymbolSourceMap &,
const llvm::omp::Clause);
480 void CheckCopyingPolymorphicAllocatable(
481 SymbolSourceMap &,
const llvm::omp::Clause);
482 void CheckPrivateSymbolsInOuterCxt(
483 SymbolSourceMap &, DirectivesClauseTriple &,
const llvm::omp::Clause);
484 bool CheckTargetBlockOnlyTeams(
const parser::Block &);
487 void CheckIndividualAllocateDirective(
491 void CheckUsesAllocatorsSpec(
493 void CheckUsesAllocatorsTraits(
500 void CheckTargetUpdate();
502 void CheckTaskDependenceType(
const parser::OmpTaskDependenceType::Value &x);
503 std::optional<llvm::omp::Directive> GetCancelType(
505 const std::optional<parser::OmpClauseList> &maybeClauses);
506 void CheckCancellationNest(
508 void CheckReductionObjects(
520 void ChecksOnOrderedAsBlock();
523 void ChecksOnOrderedAsStandalone();
524 void CheckOrderedDependClause(std::optional<std::int64_t> orderedValue);
525 void CheckReductionArraySection(
528 const parser::Name &name,
const llvm::omp::Clause clause);
529 void CheckArraySectionStrides(
const parser::DataRef &, llvm::omp::Clause);
530 void CheckLastPartRefForArraySection(
532 void CheckSharedBindingInOuterContext(
538 void CheckAllowedRequiresClause(llvm::omp::Clause clause);
540 void CheckTempDescriptorMappings();
542 void EnterDirectiveNest(
const int index) { directiveNest_[index]++; }
543 void ExitDirectiveNest(
const int index) { directiveNest_[index]--; }
544 int GetDirectiveNest(
const int index) {
return directiveNest_[index]; }
546 bool deviceConstructFound_{
false};
547 enum directiveNestType :
int {
550 TargetBlockOnlyTeams,
555 LastType = MetadirectiveNest,
557 int directiveNest_[LastType + 1] = {0};
559 std::set<std::pair<const Symbol *, const Symbol *>> declareVariantPairs_;
568 declareVariantConstructSets_;
570 std::set<const Symbol *> declareVariantBases_;
572 int allocateDirectiveLevel_{0};
578 std::map<llvm::omp::Directive, parser::CharBlock> ifLeafs_;
583 std::multimap<const Symbol *, parser::CharBlock> tempDescriptorEnterMaps_;
584 std::set<const Symbol *> tempDescriptorExitMaps_;
589 std::vector<LoopOrConstruct> constructStack_;
591 std::vector<const Scope *> scopeStack_;
595 std::vector<const parser::OmpDirectiveSpecification *> dirStack_;
597 enum class PartKind :
int {
603 std::vector<PartKind> partStack_;
605 struct MetadirectiveLoopVariant {
608 bool checkDefaultNoneInAssociatedLoop;
610 std::vector<MetadirectiveLoopVariant> metadirectiveLoopVariants_;
611 std::vector<std::size_t> metadirectiveVariantScopeStarts_;
615 std::multimap<
const parser::Label,
616 std::pair<parser::CharBlock, const parser::OpenMPConstruct *>>
618 std::map<
const parser::Label,
619 std::pair<parser::CharBlock, const parser::OpenMPConstruct *>>