2020-02-25 23:11:52 +08:00
|
|
|
//===-- lib/Semantics/check-omp-structure.h ---------------------*- C++ -*-===//
|
2019-06-26 07:18:51 +08:00
|
|
|
//
|
2019-12-21 04:52:07 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2019-06-26 07:18:51 +08:00
|
|
|
//
|
2020-01-11 04:12:03 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2019-06-26 07:18:51 +08:00
|
|
|
|
|
|
|
// OpenMP structure validity check list
|
|
|
|
// 1. invalid clauses on directive
|
|
|
|
// 2. invalid repeated clauses on directive
|
|
|
|
// 3. TODO: invalid nesting of regions
|
|
|
|
|
|
|
|
#ifndef FORTRAN_SEMANTICS_CHECK_OMP_STRUCTURE_H_
|
|
|
|
#define FORTRAN_SEMANTICS_CHECK_OMP_STRUCTURE_H_
|
|
|
|
|
2020-02-25 23:11:52 +08:00
|
|
|
#include "flang/Common/enum-set.h"
|
|
|
|
#include "flang/Parser/parse-tree.h"
|
|
|
|
#include "flang/Semantics/semantics.h"
|
2019-06-26 07:18:51 +08:00
|
|
|
|
|
|
|
namespace Fortran::semantics {
|
|
|
|
|
2020-07-02 06:49:07 +08:00
|
|
|
ENUM_CLASS(OmpDirective, ATOMIC, BARRIER, CANCEL, CANCELLATION_POINT, CRITICAL,
|
|
|
|
DECLARE_REDUCTION, DECLARE_SIMD, DECLARE_TARGET, DISTRIBUTE,
|
|
|
|
DISTRIBUTE_PARALLEL_DO, DISTRIBUTE_PARALLEL_DO_SIMD, DISTRIBUTE_SIMD, DO,
|
|
|
|
DO_SIMD, END_CRITICAL, END_DO, END_DO_SIMD, END_SECTIONS, END_SINGLE,
|
|
|
|
END_WORKSHARE, FLUSH, MASTER, ORDERED, PARALLEL, PARALLEL_DO,
|
|
|
|
PARALLEL_DO_SIMD, PARALLEL_SECTIONS, PARALLEL_WORKSHARE, SECTION, SECTIONS,
|
|
|
|
SIMD, SINGLE, TARGET, TARGET_DATA, TARGET_ENTER_DATA, TARGET_EXIT_DATA,
|
|
|
|
TARGET_PARALLEL, TARGET_PARALLEL_DO, TARGET_PARALLEL_DO_SIMD, TARGET_SIMD,
|
|
|
|
TARGET_TEAMS, TARGET_TEAMS_DISTRIBUTE, TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO,
|
|
|
|
TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD, TARGET_TEAMS_DISTRIBUTE_SIMD,
|
|
|
|
TARGET_UPDATE, TASK, TASKGROUP, TASKLOOP, TASKLOOP_SIMD, TASKWAIT,
|
|
|
|
TASKYIELD, TEAMS, TEAMS_DISTRIBUTE, TEAMS_DISTRIBUTE_PARALLEL_DO,
|
|
|
|
TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD, TEAMS_DISTRIBUTE_SIMD, THREADPRIVATE,
|
|
|
|
WORKSHARE)
|
|
|
|
|
|
|
|
using OmpDirectiveSet = common::EnumSet<OmpDirective, OmpDirective_enumSize>;
|
|
|
|
|
|
|
|
ENUM_CLASS(OmpClause, ALIGNED, COLLAPSE, COPYIN, COPYPRIVATE, DEFAULT,
|
|
|
|
DEFAULTMAP, DEPEND, DEVICE, DIST_SCHEDULE, FINAL, FIRSTPRIVATE, FROM,
|
|
|
|
GRAINSIZE, IF, INBRANCH, IS_DEVICE_PTR, LASTPRIVATE, LINEAR, LINK, MAP,
|
|
|
|
MERGEABLE, NOGROUP, NOTINBRANCH, NOWAIT, NUM_TASKS, NUM_TEAMS, NUM_THREADS,
|
|
|
|
ORDERED, PRIORITY, PRIVATE, PROC_BIND, REDUCTION, SAFELEN, SCHEDULE, SHARED,
|
|
|
|
SIMD, SIMDLEN, THREAD_LIMIT, THREADS, TO, UNIFORM, UNTIED, USE_DEVICE_PTR)
|
|
|
|
|
|
|
|
using OmpClauseSet = common::EnumSet<OmpClause, OmpClause_enumSize>;
|
|
|
|
|
|
|
|
static constexpr OmpDirectiveSet parallelSet{
|
|
|
|
OmpDirective::DISTRIBUTE_PARALLEL_DO,
|
|
|
|
OmpDirective::DISTRIBUTE_PARALLEL_DO_SIMD, OmpDirective::PARALLEL,
|
|
|
|
OmpDirective::PARALLEL_DO, OmpDirective::PARALLEL_DO_SIMD,
|
|
|
|
OmpDirective::PARALLEL_SECTIONS, OmpDirective::PARALLEL_WORKSHARE,
|
|
|
|
OmpDirective::TARGET_PARALLEL, OmpDirective::TARGET_PARALLEL_DO,
|
|
|
|
OmpDirective::TARGET_PARALLEL_DO_SIMD,
|
|
|
|
OmpDirective::TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO,
|
|
|
|
OmpDirective::TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
|
|
|
|
OmpDirective::TEAMS_DISTRIBUTE_PARALLEL_DO,
|
|
|
|
OmpDirective::TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD};
|
|
|
|
static constexpr OmpDirectiveSet doSet{OmpDirective::DISTRIBUTE_PARALLEL_DO,
|
|
|
|
OmpDirective::DISTRIBUTE_PARALLEL_DO_SIMD, OmpDirective::PARALLEL_DO,
|
|
|
|
OmpDirective::PARALLEL_DO_SIMD, OmpDirective::DO, OmpDirective::DO_SIMD,
|
|
|
|
OmpDirective::TARGET_PARALLEL_DO, OmpDirective::TARGET_PARALLEL_DO_SIMD,
|
|
|
|
OmpDirective::TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO,
|
|
|
|
OmpDirective::TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
|
|
|
|
OmpDirective::TEAMS_DISTRIBUTE_PARALLEL_DO,
|
|
|
|
OmpDirective::TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD};
|
|
|
|
static constexpr OmpDirectiveSet doSimdSet{
|
|
|
|
OmpDirective::DISTRIBUTE_PARALLEL_DO_SIMD, OmpDirective::PARALLEL_DO_SIMD,
|
|
|
|
OmpDirective::DO_SIMD, OmpDirective::TARGET_PARALLEL_DO_SIMD,
|
|
|
|
OmpDirective::TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
|
|
|
|
OmpDirective::TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD};
|
|
|
|
static constexpr OmpDirectiveSet taskloopSet{
|
|
|
|
OmpDirective::TASKLOOP, OmpDirective::TASKLOOP_SIMD};
|
|
|
|
static constexpr OmpDirectiveSet targetSet{OmpDirective::TARGET,
|
|
|
|
OmpDirective::TARGET_PARALLEL, OmpDirective::TARGET_PARALLEL_DO,
|
|
|
|
OmpDirective::TARGET_PARALLEL_DO_SIMD, OmpDirective::TARGET_SIMD,
|
|
|
|
OmpDirective::TARGET_TEAMS, OmpDirective::TARGET_TEAMS_DISTRIBUTE,
|
|
|
|
OmpDirective::TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO,
|
|
|
|
OmpDirective::TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
|
|
|
|
OmpDirective::TARGET_TEAMS_DISTRIBUTE_SIMD};
|
|
|
|
static constexpr OmpDirectiveSet simdSet{
|
|
|
|
OmpDirective::DISTRIBUTE_PARALLEL_DO_SIMD, OmpDirective::DISTRIBUTE_SIMD,
|
|
|
|
OmpDirective::PARALLEL_DO_SIMD, OmpDirective::DO_SIMD, OmpDirective::SIMD,
|
|
|
|
OmpDirective::TARGET_PARALLEL_DO_SIMD,
|
|
|
|
OmpDirective::TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
|
|
|
|
OmpDirective::TARGET_TEAMS_DISTRIBUTE_SIMD, OmpDirective::TARGET_SIMD,
|
|
|
|
OmpDirective::TASKLOOP_SIMD,
|
|
|
|
OmpDirective::TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
|
|
|
|
OmpDirective::TEAMS_DISTRIBUTE_SIMD};
|
|
|
|
static constexpr OmpDirectiveSet taskGeneratingSet{
|
|
|
|
OmpDirectiveSet{OmpDirective::TASK} | taskloopSet};
|
|
|
|
|
2019-06-26 07:18:51 +08:00
|
|
|
class OmpStructureChecker : public virtual BaseChecker {
|
|
|
|
public:
|
|
|
|
OmpStructureChecker(SemanticsContext &context) : context_{context} {}
|
|
|
|
|
2019-07-10 05:08:50 +08:00
|
|
|
void Enter(const parser::OpenMPConstruct &);
|
2019-06-26 07:18:51 +08:00
|
|
|
void Enter(const parser::OpenMPLoopConstruct &);
|
|
|
|
void Leave(const parser::OpenMPLoopConstruct &);
|
[flang] [OpenMP] parse tree changes for `OpenMPLoopConstruct` (flang-compiler/f18#656)
1. Following Block and Sections constructs, re-structure loop related
constructs into `{Begin, Loop, End}`. Being part of the work in
PR flang-compiler/f18#599, the `Loop` and `End` nodes are optional during parser. They
should be filled in during the phase of `CanonicalizationOfOmp`. This
commit is solely for the parse tree change. So, after this commit,
PR flang-compiler/f18#599 needs to be changed accordingly.
2. Removed parse tree nodes for `END DO` and `END DO SIMD`. Similar to
Block and Sections constructs, `End` node now accepts clauses too,
the validity checks are deferred into Semantics. This is more genernal
and error message could be better.
3. With this commit alone, assertion error would occur when `End` directive
is present, for example `!$OMP END DO` because the `End` node is not
moved into `OpenMPLoopConstruct` yet. Again, PR flang-compiler/f18#599 will handle that.
More tests will be added in PR flang-compiler/f18#599 and during the future Semantics work.
Original-commit: flang-compiler/f18@8cd1932fd61fa67f8ad5abfd337cf7a223ea89f4
Reviewed-on: https://github.com/flang-compiler/f18/pull/656
2019-08-15 06:16:27 +08:00
|
|
|
void Enter(const parser::OmpEndLoopDirective &);
|
2019-06-26 07:18:51 +08:00
|
|
|
|
|
|
|
void Enter(const parser::OpenMPBlockConstruct &);
|
|
|
|
void Leave(const parser::OpenMPBlockConstruct &);
|
[flang] [OpenMP] parse tree changes for `OpenMPBlockConstruct` (flang-compiler/f18#632)
* [OpenMP] parse tree changes for `OpenMPBlockConstruct`
1. merge `Workshare` and `Single` into `OpenMPBlockConstruct` because
they both accept structured-block and syntax is similar to other block
directives.
2. `OpenMPBlockConstruct` changes to structure like `{Begin, Block, End}`,
where `Begin` and `End` are tuple of `{Directive, ClauseList}`.
3. Updated the check-omp-structure.* for necessary parts. Added all the END
directive enumeration types that may have clauses.
More tests will be added during Semantics.
* [OpenMP] Update on Tim's suggestion
1. Fix unspecified enumeration for `OmpDirective` in the `OmpContext`.
This is through getting rid of `PushContext(source)` function to
make sure whenever it is about to push a NEW context, directive
source location and enumeration are available. To do that, I moved
around all the switches for directive into high level `Construct`'s
`Enter` node. Besides fixing the issue, the side benefit is that
whenever we call `GetContext().directive`, we are sure that the
`directive` here was set already.
2. When `Enter` the `OmpEndBlockDirective` node, partial context
information, such as directive source location or legal clause lists,
needs to be reset. The new directive source location should be
`OmpEndBlockDirective`'s `source`. The enumeration `directive`
should not be reset for the END directives that do not accept
clauses because nothing needs to be checked (for example any clause
that is on `END PARALLEL` is illegal).
Original-commit: flang-compiler/f18@e5bd6b7ba0fbe9006f3e431260428b194f2d2616
Reviewed-on: https://github.com/flang-compiler/f18/pull/632
2019-08-10 06:11:20 +08:00
|
|
|
void Enter(const parser::OmpEndBlockDirective &);
|
2019-06-26 07:18:51 +08:00
|
|
|
|
2019-08-02 05:32:33 +08:00
|
|
|
void Enter(const parser::OpenMPSectionsConstruct &);
|
|
|
|
void Leave(const parser::OpenMPSectionsConstruct &);
|
2019-08-14 23:42:28 +08:00
|
|
|
void Enter(const parser::OmpEndSectionsDirective &);
|
2019-08-02 05:32:33 +08:00
|
|
|
|
2019-08-06 05:51:02 +08:00
|
|
|
void Enter(const parser::OpenMPDeclareSimdConstruct &);
|
|
|
|
void Leave(const parser::OpenMPDeclareSimdConstruct &);
|
2019-08-21 01:23:56 +08:00
|
|
|
void Enter(const parser::OpenMPDeclareTargetConstruct &);
|
|
|
|
void Leave(const parser::OpenMPDeclareTargetConstruct &);
|
2019-08-02 05:32:33 +08:00
|
|
|
|
2019-08-07 02:59:40 +08:00
|
|
|
void Enter(const parser::OpenMPSimpleStandaloneConstruct &);
|
|
|
|
void Leave(const parser::OpenMPSimpleStandaloneConstruct &);
|
|
|
|
void Enter(const parser::OpenMPFlushConstruct &);
|
|
|
|
void Leave(const parser::OpenMPFlushConstruct &);
|
|
|
|
void Enter(const parser::OpenMPCancelConstruct &);
|
|
|
|
void Leave(const parser::OpenMPCancelConstruct &);
|
|
|
|
void Enter(const parser::OpenMPCancellationPointConstruct &);
|
|
|
|
void Leave(const parser::OpenMPCancellationPointConstruct &);
|
|
|
|
|
2019-07-02 04:55:06 +08:00
|
|
|
void Leave(const parser::OmpClauseList &);
|
2019-06-26 07:18:51 +08:00
|
|
|
void Enter(const parser::OmpClause &);
|
2019-08-02 05:32:33 +08:00
|
|
|
void Enter(const parser::OmpNowait &);
|
2019-06-26 07:18:51 +08:00
|
|
|
void Enter(const parser::OmpClause::Inbranch &);
|
|
|
|
void Enter(const parser::OmpClause::Mergeable &);
|
|
|
|
void Enter(const parser::OmpClause::Nogroup &);
|
|
|
|
void Enter(const parser::OmpClause::Notinbranch &);
|
|
|
|
void Enter(const parser::OmpClause::Untied &);
|
|
|
|
void Enter(const parser::OmpClause::Collapse &);
|
|
|
|
void Enter(const parser::OmpClause::Copyin &);
|
|
|
|
void Enter(const parser::OmpClause::Copyprivate &);
|
|
|
|
void Enter(const parser::OmpClause::Device &);
|
|
|
|
void Enter(const parser::OmpClause::DistSchedule &);
|
|
|
|
void Enter(const parser::OmpClause::Final &);
|
|
|
|
void Enter(const parser::OmpClause::Firstprivate &);
|
|
|
|
void Enter(const parser::OmpClause::From &);
|
|
|
|
void Enter(const parser::OmpClause::Grainsize &);
|
|
|
|
void Enter(const parser::OmpClause::Lastprivate &);
|
|
|
|
void Enter(const parser::OmpClause::NumTasks &);
|
|
|
|
void Enter(const parser::OmpClause::NumTeams &);
|
|
|
|
void Enter(const parser::OmpClause::NumThreads &);
|
|
|
|
void Enter(const parser::OmpClause::Ordered &);
|
|
|
|
void Enter(const parser::OmpClause::Priority &);
|
|
|
|
void Enter(const parser::OmpClause::Private &);
|
|
|
|
void Enter(const parser::OmpClause::Safelen &);
|
|
|
|
void Enter(const parser::OmpClause::Shared &);
|
|
|
|
void Enter(const parser::OmpClause::Simdlen &);
|
|
|
|
void Enter(const parser::OmpClause::ThreadLimit &);
|
|
|
|
void Enter(const parser::OmpClause::To &);
|
|
|
|
void Enter(const parser::OmpClause::Link &);
|
|
|
|
void Enter(const parser::OmpClause::Uniform &);
|
|
|
|
void Enter(const parser::OmpClause::UseDevicePtr &);
|
|
|
|
void Enter(const parser::OmpClause::IsDevicePtr &);
|
|
|
|
|
|
|
|
void Enter(const parser::OmpAlignedClause &);
|
|
|
|
void Enter(const parser::OmpDefaultClause &);
|
2019-09-09 05:52:43 +08:00
|
|
|
void Enter(const parser::OmpDefaultmapClause &);
|
2019-06-26 07:18:51 +08:00
|
|
|
void Enter(const parser::OmpDependClause &);
|
|
|
|
void Enter(const parser::OmpIfClause &);
|
|
|
|
void Enter(const parser::OmpLinearClause &);
|
|
|
|
void Enter(const parser::OmpMapClause &);
|
|
|
|
void Enter(const parser::OmpProcBindClause &);
|
|
|
|
void Enter(const parser::OmpReductionClause &);
|
|
|
|
void Enter(const parser::OmpScheduleClause &);
|
|
|
|
|
|
|
|
private:
|
|
|
|
struct OmpContext {
|
2020-07-02 06:49:07 +08:00
|
|
|
OmpContext(parser::CharBlock source, OmpDirective d)
|
2020-03-29 12:00:16 +08:00
|
|
|
: directiveSource{source}, directive{d} {}
|
2019-06-26 07:18:51 +08:00
|
|
|
parser::CharBlock directiveSource{nullptr};
|
|
|
|
parser::CharBlock clauseSource{nullptr};
|
2020-07-02 06:49:07 +08:00
|
|
|
OmpDirective directive;
|
2019-08-16 02:54:51 +08:00
|
|
|
OmpClauseSet allowedClauses{};
|
|
|
|
OmpClauseSet allowedOnceClauses{};
|
2019-08-27 16:34:29 +08:00
|
|
|
OmpClauseSet allowedExclusiveClauses{};
|
2019-09-13 22:42:19 +08:00
|
|
|
OmpClauseSet requiredClauses{};
|
2019-07-02 04:55:06 +08:00
|
|
|
|
|
|
|
const parser::OmpClause *clause{nullptr};
|
2020-07-02 06:49:07 +08:00
|
|
|
std::multimap<OmpClause, const parser::OmpClause *> clauseInfo;
|
2019-06-26 07:18:51 +08:00
|
|
|
};
|
|
|
|
// back() is the top of the stack
|
2019-08-02 05:32:33 +08:00
|
|
|
OmpContext &GetContext() {
|
|
|
|
CHECK(!ompContext_.empty());
|
|
|
|
return ompContext_.back();
|
|
|
|
}
|
[flang] [OpenMP] parse tree changes for `OpenMPBlockConstruct` (flang-compiler/f18#632)
* [OpenMP] parse tree changes for `OpenMPBlockConstruct`
1. merge `Workshare` and `Single` into `OpenMPBlockConstruct` because
they both accept structured-block and syntax is similar to other block
directives.
2. `OpenMPBlockConstruct` changes to structure like `{Begin, Block, End}`,
where `Begin` and `End` are tuple of `{Directive, ClauseList}`.
3. Updated the check-omp-structure.* for necessary parts. Added all the END
directive enumeration types that may have clauses.
More tests will be added during Semantics.
* [OpenMP] Update on Tim's suggestion
1. Fix unspecified enumeration for `OmpDirective` in the `OmpContext`.
This is through getting rid of `PushContext(source)` function to
make sure whenever it is about to push a NEW context, directive
source location and enumeration are available. To do that, I moved
around all the switches for directive into high level `Construct`'s
`Enter` node. Besides fixing the issue, the side benefit is that
whenever we call `GetContext().directive`, we are sure that the
`directive` here was set already.
2. When `Enter` the `OmpEndBlockDirective` node, partial context
information, such as directive source location or legal clause lists,
needs to be reset. The new directive source location should be
`OmpEndBlockDirective`'s `source`. The enumeration `directive`
should not be reset for the END directives that do not accept
clauses because nothing needs to be checked (for example any clause
that is on `END PARALLEL` is illegal).
Original-commit: flang-compiler/f18@e5bd6b7ba0fbe9006f3e431260428b194f2d2616
Reviewed-on: https://github.com/flang-compiler/f18/pull/632
2019-08-10 06:11:20 +08:00
|
|
|
// reset source location, check information, and
|
|
|
|
// collected information for END directive
|
|
|
|
void ResetPartialContext(const parser::CharBlock &source) {
|
|
|
|
CHECK(!ompContext_.empty());
|
|
|
|
SetContextDirectiveSource(source);
|
|
|
|
GetContext().allowedClauses = {};
|
|
|
|
GetContext().allowedOnceClauses = {};
|
2019-08-27 16:34:29 +08:00
|
|
|
GetContext().allowedExclusiveClauses = {};
|
2019-09-13 22:42:19 +08:00
|
|
|
GetContext().requiredClauses = {};
|
[flang] [OpenMP] parse tree changes for `OpenMPBlockConstruct` (flang-compiler/f18#632)
* [OpenMP] parse tree changes for `OpenMPBlockConstruct`
1. merge `Workshare` and `Single` into `OpenMPBlockConstruct` because
they both accept structured-block and syntax is similar to other block
directives.
2. `OpenMPBlockConstruct` changes to structure like `{Begin, Block, End}`,
where `Begin` and `End` are tuple of `{Directive, ClauseList}`.
3. Updated the check-omp-structure.* for necessary parts. Added all the END
directive enumeration types that may have clauses.
More tests will be added during Semantics.
* [OpenMP] Update on Tim's suggestion
1. Fix unspecified enumeration for `OmpDirective` in the `OmpContext`.
This is through getting rid of `PushContext(source)` function to
make sure whenever it is about to push a NEW context, directive
source location and enumeration are available. To do that, I moved
around all the switches for directive into high level `Construct`'s
`Enter` node. Besides fixing the issue, the side benefit is that
whenever we call `GetContext().directive`, we are sure that the
`directive` here was set already.
2. When `Enter` the `OmpEndBlockDirective` node, partial context
information, such as directive source location or legal clause lists,
needs to be reset. The new directive source location should be
`OmpEndBlockDirective`'s `source`. The enumeration `directive`
should not be reset for the END directives that do not accept
clauses because nothing needs to be checked (for example any clause
that is on `END PARALLEL` is illegal).
Original-commit: flang-compiler/f18@e5bd6b7ba0fbe9006f3e431260428b194f2d2616
Reviewed-on: https://github.com/flang-compiler/f18/pull/632
2019-08-10 06:11:20 +08:00
|
|
|
GetContext().clauseInfo = {};
|
|
|
|
}
|
2019-06-26 07:18:51 +08:00
|
|
|
void SetContextDirectiveSource(const parser::CharBlock &directive) {
|
2019-08-02 05:32:33 +08:00
|
|
|
GetContext().directiveSource = directive;
|
2019-06-26 07:18:51 +08:00
|
|
|
}
|
2019-07-02 04:55:06 +08:00
|
|
|
void SetContextClause(const parser::OmpClause &clause) {
|
2019-08-02 05:32:33 +08:00
|
|
|
GetContext().clauseSource = clause.source;
|
|
|
|
GetContext().clause = &clause;
|
2019-06-26 07:18:51 +08:00
|
|
|
}
|
2020-07-02 06:49:07 +08:00
|
|
|
void SetContextDirectiveEnum(OmpDirective dir) {
|
2019-08-02 05:32:33 +08:00
|
|
|
GetContext().directive = dir;
|
2019-06-26 07:18:51 +08:00
|
|
|
}
|
|
|
|
void SetContextAllowed(const OmpClauseSet &allowed) {
|
2019-08-02 05:32:33 +08:00
|
|
|
GetContext().allowedClauses = allowed;
|
2019-06-26 07:18:51 +08:00
|
|
|
}
|
|
|
|
void SetContextAllowedOnce(const OmpClauseSet &allowedOnce) {
|
2019-08-02 05:32:33 +08:00
|
|
|
GetContext().allowedOnceClauses = allowedOnce;
|
2019-06-26 07:18:51 +08:00
|
|
|
}
|
2019-08-27 16:34:29 +08:00
|
|
|
void SetContextAllowedExclusive(const OmpClauseSet &allowedExclusive) {
|
|
|
|
GetContext().allowedExclusiveClauses = allowedExclusive;
|
|
|
|
}
|
2019-09-13 22:42:19 +08:00
|
|
|
void SetContextRequired(const OmpClauseSet &required) {
|
|
|
|
GetContext().requiredClauses = required;
|
|
|
|
}
|
2020-07-02 06:49:07 +08:00
|
|
|
void SetContextClauseInfo(OmpClause type) {
|
2019-08-02 05:32:33 +08:00
|
|
|
GetContext().clauseInfo.emplace(type, GetContext().clause);
|
2019-07-02 04:55:06 +08:00
|
|
|
}
|
2020-07-02 06:49:07 +08:00
|
|
|
const parser::OmpClause *FindClause(OmpClause type) {
|
2019-07-02 04:55:06 +08:00
|
|
|
auto it{GetContext().clauseInfo.find(type)};
|
|
|
|
if (it != GetContext().clauseInfo.end()) {
|
|
|
|
return it->second;
|
|
|
|
}
|
|
|
|
return nullptr;
|
2019-06-26 07:18:51 +08:00
|
|
|
}
|
2020-07-02 06:49:07 +08:00
|
|
|
void PushContext(const parser::CharBlock &source, OmpDirective dir) {
|
2019-08-16 02:54:51 +08:00
|
|
|
ompContext_.emplace_back(source, dir);
|
2019-08-02 05:32:33 +08:00
|
|
|
}
|
2019-06-26 07:18:51 +08:00
|
|
|
|
2019-08-27 16:34:29 +08:00
|
|
|
void RequiresConstantPositiveParameter(
|
2020-07-02 06:49:07 +08:00
|
|
|
const OmpClause &clause, const parser::ScalarIntConstantExpr &i);
|
2019-08-27 16:34:29 +08:00
|
|
|
void RequiresPositiveParameter(
|
2020-07-02 06:49:07 +08:00
|
|
|
const OmpClause &clause, const parser::ScalarIntExpr &i);
|
2019-08-27 16:34:29 +08:00
|
|
|
|
2019-06-26 07:18:51 +08:00
|
|
|
bool CurrentDirectiveIsNested() { return ompContext_.size() > 0; };
|
|
|
|
bool HasInvalidWorksharingNesting(
|
|
|
|
const parser::CharBlock &, const OmpDirectiveSet &);
|
2020-07-02 06:49:07 +08:00
|
|
|
void CheckAllowed(OmpClause);
|
|
|
|
void CheckRequired(OmpClause);
|
2019-07-12 06:18:09 +08:00
|
|
|
std::string ContextDirectiveAsFortran();
|
2019-08-28 04:30:38 +08:00
|
|
|
void SayNotMatching(const parser::CharBlock &, const parser::CharBlock &);
|
2020-03-29 12:00:16 +08:00
|
|
|
template <typename A, typename B, typename C>
|
2019-08-28 07:52:12 +08:00
|
|
|
const A &CheckMatching(const B &beginDir, const C &endDir) {
|
|
|
|
const A &begin{std::get<A>(beginDir.t)};
|
|
|
|
const A &end{std::get<A>(endDir.t)};
|
2019-08-28 04:30:38 +08:00
|
|
|
if (begin.v != end.v) {
|
|
|
|
SayNotMatching(begin.source, end.source);
|
|
|
|
}
|
2019-08-28 07:52:12 +08:00
|
|
|
return begin;
|
2019-08-28 04:30:38 +08:00
|
|
|
}
|
2019-06-26 07:18:51 +08:00
|
|
|
|
2019-07-02 04:55:06 +08:00
|
|
|
// specific clause related
|
|
|
|
bool ScheduleModifierHasType(const parser::OmpScheduleClause &,
|
|
|
|
const parser::OmpScheduleModifierType::ModType &);
|
|
|
|
|
2019-06-26 07:18:51 +08:00
|
|
|
SemanticsContext &context_;
|
2020-03-29 12:00:16 +08:00
|
|
|
std::vector<OmpContext> ompContext_; // used as a stack
|
2019-06-26 07:18:51 +08:00
|
|
|
};
|
2020-03-29 12:00:16 +08:00
|
|
|
} // namespace Fortran::semantics
|
|
|
|
#endif // FORTRAN_SEMANTICS_CHECK_OMP_STRUCTURE_H_
|