[flang][OpenMP] Normalize clause modifiers that exist on their own (#116655)
This is the first part of the effort to make parsing of clause modifiers more uniform and robust. Currently, when multiple modifiers are allowed, the parser will expect them to appear in a hard-coded order. Additionally, modifier properties (such as "ultimate") are checked separately for each case. The overall plan is 1. Extract all modifiers into their own top-level classes, and then equip them with sets of common properties that will allow performing the property checks generically, without refering to the specific kind of the modifier. 2. Define a parser (as a separate class) for each modifier. 3. For each clause define a union (std::variant) of all allowable modifiers, and parse the modifiers as a list of these unions. The intent is also to isolate parts of the code that could eventually be auto-generated. OpenMP modifier overhaul: #1/3
This commit is contained in:
parent
b49c4af186
commit
cfd67c2149
@ -475,9 +475,9 @@ public:
|
|||||||
READ_FEATURE(OmpDoacross::Source)
|
READ_FEATURE(OmpDoacross::Source)
|
||||||
READ_FEATURE(OmpDoacrossClause)
|
READ_FEATURE(OmpDoacrossClause)
|
||||||
READ_FEATURE(OmpDependenceType)
|
READ_FEATURE(OmpDependenceType)
|
||||||
READ_FEATURE(OmpDependenceType::Type)
|
READ_FEATURE(OmpDependenceType::Value)
|
||||||
READ_FEATURE(OmpTaskDependenceType)
|
READ_FEATURE(OmpTaskDependenceType)
|
||||||
READ_FEATURE(OmpTaskDependenceType::Type)
|
READ_FEATURE(OmpTaskDependenceType::Value)
|
||||||
READ_FEATURE(OmpIteration)
|
READ_FEATURE(OmpIteration)
|
||||||
READ_FEATURE(OmpIterationOffset)
|
READ_FEATURE(OmpIterationOffset)
|
||||||
READ_FEATURE(OmpIterationVector)
|
READ_FEATURE(OmpIterationVector)
|
||||||
@ -495,7 +495,7 @@ public:
|
|||||||
READ_FEATURE(OmpLinearClause::WithModifier)
|
READ_FEATURE(OmpLinearClause::WithModifier)
|
||||||
READ_FEATURE(OmpLinearClause::WithoutModifier)
|
READ_FEATURE(OmpLinearClause::WithoutModifier)
|
||||||
READ_FEATURE(OmpLinearModifier)
|
READ_FEATURE(OmpLinearModifier)
|
||||||
READ_FEATURE(OmpLinearModifier::Type)
|
READ_FEATURE(OmpLinearModifier::Value)
|
||||||
READ_FEATURE(OmpLoopDirective)
|
READ_FEATURE(OmpLoopDirective)
|
||||||
READ_FEATURE(OmpMapClause)
|
READ_FEATURE(OmpMapClause)
|
||||||
READ_FEATURE(OmpMapClause::TypeModifier)
|
READ_FEATURE(OmpMapClause::TypeModifier)
|
||||||
@ -515,7 +515,7 @@ public:
|
|||||||
READ_FEATURE(OmpReductionCombiner)
|
READ_FEATURE(OmpReductionCombiner)
|
||||||
READ_FEATURE(OmpReductionCombiner::FunctionCombiner)
|
READ_FEATURE(OmpReductionCombiner::FunctionCombiner)
|
||||||
READ_FEATURE(OmpReductionInitializerClause)
|
READ_FEATURE(OmpReductionInitializerClause)
|
||||||
READ_FEATURE(OmpReductionOperator)
|
READ_FEATURE(OmpReductionIdentifier)
|
||||||
READ_FEATURE(OmpAllocateClause)
|
READ_FEATURE(OmpAllocateClause)
|
||||||
READ_FEATURE(OmpAllocateClause::AllocateModifier)
|
READ_FEATURE(OmpAllocateClause::AllocateModifier)
|
||||||
READ_FEATURE(OmpAllocateClause::AllocateModifier::Allocator)
|
READ_FEATURE(OmpAllocateClause::AllocateModifier::Allocator)
|
||||||
|
@ -218,11 +218,11 @@ void OpenMPCounterVisitor::Post(const OmpScheduleModifierType::ModType &c) {
|
|||||||
clauseDetails +=
|
clauseDetails +=
|
||||||
"modifier=" + std::string{OmpScheduleModifierType::EnumToString(c)} + ";";
|
"modifier=" + std::string{OmpScheduleModifierType::EnumToString(c)} + ";";
|
||||||
}
|
}
|
||||||
void OpenMPCounterVisitor::Post(const OmpLinearModifier::Type &c) {
|
void OpenMPCounterVisitor::Post(const OmpLinearModifier::Value &c) {
|
||||||
clauseDetails +=
|
clauseDetails +=
|
||||||
"modifier=" + std::string{OmpLinearModifier::EnumToString(c)} + ";";
|
"modifier=" + std::string{OmpLinearModifier::EnumToString(c)} + ";";
|
||||||
}
|
}
|
||||||
void OpenMPCounterVisitor::Post(const OmpTaskDependenceType::Type &c) {
|
void OpenMPCounterVisitor::Post(const OmpTaskDependenceType::Value &c) {
|
||||||
clauseDetails +=
|
clauseDetails +=
|
||||||
"type=" + std::string{OmpTaskDependenceType::EnumToString(c)} + ";";
|
"type=" + std::string{OmpTaskDependenceType::EnumToString(c)} + ";";
|
||||||
}
|
}
|
||||||
|
@ -72,8 +72,8 @@ struct OpenMPCounterVisitor {
|
|||||||
void Post(const OmpDefaultmapClause::VariableCategory &c);
|
void Post(const OmpDefaultmapClause::VariableCategory &c);
|
||||||
void Post(const OmpDeviceTypeClause::Type &c);
|
void Post(const OmpDeviceTypeClause::Type &c);
|
||||||
void Post(const OmpScheduleModifierType::ModType &c);
|
void Post(const OmpScheduleModifierType::ModType &c);
|
||||||
void Post(const OmpLinearModifier::Type &c);
|
void Post(const OmpLinearModifier::Value &c);
|
||||||
void Post(const OmpTaskDependenceType::Type &c);
|
void Post(const OmpTaskDependenceType::Value &c);
|
||||||
void Post(const OmpMapClause::Type &c);
|
void Post(const OmpMapClause::Type &c);
|
||||||
void Post(const OmpScheduleClause::ScheduleType &c);
|
void Post(const OmpScheduleClause::ScheduleType &c);
|
||||||
void Post(const OmpIfClause::DirectiveNameModifier &c);
|
void Post(const OmpIfClause::DirectiveNameModifier &c);
|
||||||
|
@ -477,7 +477,7 @@ public:
|
|||||||
NODE(parser, ObjectDecl)
|
NODE(parser, ObjectDecl)
|
||||||
NODE(parser, OldParameterStmt)
|
NODE(parser, OldParameterStmt)
|
||||||
NODE(parser, OmpIteratorSpecifier)
|
NODE(parser, OmpIteratorSpecifier)
|
||||||
NODE(parser, OmpIteratorModifier)
|
NODE(parser, OmpIterator)
|
||||||
NODE(parser, OmpAffinityClause)
|
NODE(parser, OmpAffinityClause)
|
||||||
NODE(parser, OmpAlignedClause)
|
NODE(parser, OmpAlignedClause)
|
||||||
NODE(parser, OmpAtomic)
|
NODE(parser, OmpAtomic)
|
||||||
@ -513,9 +513,9 @@ public:
|
|||||||
NODE_ENUM(OmpDefaultmapClause, ImplicitBehavior)
|
NODE_ENUM(OmpDefaultmapClause, ImplicitBehavior)
|
||||||
NODE_ENUM(OmpDefaultmapClause, VariableCategory)
|
NODE_ENUM(OmpDefaultmapClause, VariableCategory)
|
||||||
NODE(parser, OmpDependenceType)
|
NODE(parser, OmpDependenceType)
|
||||||
NODE_ENUM(OmpDependenceType, Type)
|
NODE_ENUM(OmpDependenceType, Value)
|
||||||
NODE(parser, OmpTaskDependenceType)
|
NODE(parser, OmpTaskDependenceType)
|
||||||
NODE_ENUM(OmpTaskDependenceType, Type)
|
NODE_ENUM(OmpTaskDependenceType, Value)
|
||||||
NODE(parser, OmpIterationOffset)
|
NODE(parser, OmpIterationOffset)
|
||||||
NODE(parser, OmpIteration)
|
NODE(parser, OmpIteration)
|
||||||
NODE(parser, OmpIterationVector)
|
NODE(parser, OmpIterationVector)
|
||||||
@ -543,7 +543,7 @@ public:
|
|||||||
NODE(OmpLinearClause, WithModifier)
|
NODE(OmpLinearClause, WithModifier)
|
||||||
NODE(OmpLinearClause, WithoutModifier)
|
NODE(OmpLinearClause, WithoutModifier)
|
||||||
NODE(parser, OmpLinearModifier)
|
NODE(parser, OmpLinearModifier)
|
||||||
NODE_ENUM(OmpLinearModifier, Type)
|
NODE_ENUM(OmpLinearModifier, Value)
|
||||||
NODE(parser, OmpLoopDirective)
|
NODE(parser, OmpLoopDirective)
|
||||||
NODE(parser, OmpMapClause)
|
NODE(parser, OmpMapClause)
|
||||||
NODE(parser, OmpMapperIdentifier)
|
NODE(parser, OmpMapperIdentifier)
|
||||||
@ -574,7 +574,7 @@ public:
|
|||||||
NODE(parser, OmpReductionCombiner)
|
NODE(parser, OmpReductionCombiner)
|
||||||
NODE(OmpReductionCombiner, FunctionCombiner)
|
NODE(OmpReductionCombiner, FunctionCombiner)
|
||||||
NODE(parser, OmpReductionInitializerClause)
|
NODE(parser, OmpReductionInitializerClause)
|
||||||
NODE(parser, OmpReductionOperator)
|
NODE(parser, OmpReductionIdentifier)
|
||||||
NODE(parser, OmpAllocateClause)
|
NODE(parser, OmpAllocateClause)
|
||||||
NODE(OmpAllocateClause, AllocateModifier)
|
NODE(OmpAllocateClause, AllocateModifier)
|
||||||
NODE(OmpAllocateClause::AllocateModifier, Allocator)
|
NODE(OmpAllocateClause::AllocateModifier, Allocator)
|
||||||
|
@ -3440,13 +3440,33 @@ struct OmpObject {
|
|||||||
|
|
||||||
WRAPPER_CLASS(OmpObjectList, std::list<OmpObject>);
|
WRAPPER_CLASS(OmpObjectList, std::list<OmpObject>);
|
||||||
|
|
||||||
|
inline namespace modifier {
|
||||||
|
// For uniformity, in all keyword modifiers the name of the type defined
|
||||||
|
// by ENUM_CLASS is "Value", e.g.
|
||||||
|
// struct Foo {
|
||||||
|
// ENUM_CLASS(Value, Keyword1, Keyword2);
|
||||||
|
// };
|
||||||
|
|
||||||
|
// Ref: [5.0:47-49], [5.1:49-51], [5.2:67-69]
|
||||||
|
//
|
||||||
|
// iterator-specifier ->
|
||||||
|
// [iterator-type] iterator-identifier
|
||||||
|
// = range-specification | // since 5.0
|
||||||
|
// [iterator-type ::] iterator-identifier
|
||||||
|
// = range-specification // since 5.2
|
||||||
|
struct OmpIteratorSpecifier {
|
||||||
|
TUPLE_CLASS_BOILERPLATE(OmpIteratorSpecifier);
|
||||||
|
CharBlock source;
|
||||||
|
std::tuple<TypeDeclarationStmt, SubscriptTriplet> t;
|
||||||
|
};
|
||||||
|
|
||||||
// Ref: [4.5:169-170], [5.0:255-256], [5.1:288-289]
|
// Ref: [4.5:169-170], [5.0:255-256], [5.1:288-289]
|
||||||
//
|
//
|
||||||
// dependence-type ->
|
// dependence-type ->
|
||||||
// SINK | SOURCE | // since 4.5
|
// SINK | SOURCE | // since 4.5
|
||||||
// IN | OUT | INOUT | // since 4.5, until 5.1
|
// IN | OUT | INOUT | // since 4.5, until 5.1
|
||||||
// MUTEXINOUTSET | DEPOBJ | // since 5.0, until 5.1
|
// MUTEXINOUTSET | DEPOBJ | // since 5.0, until 5.1
|
||||||
// INOUTSET // since 5.1, until 5.1
|
// INOUTSET // since 5.1, until 5.1
|
||||||
//
|
//
|
||||||
// All of these, except SINK and SOURCE became task-dependence-type in 5.2.
|
// All of these, except SINK and SOURCE became task-dependence-type in 5.2.
|
||||||
//
|
//
|
||||||
@ -3457,37 +3477,51 @@ WRAPPER_CLASS(OmpObjectList, std::list<OmpObject>);
|
|||||||
// vector). This would accept the vector "i, j, k" (although interpreted
|
// vector). This would accept the vector "i, j, k" (although interpreted
|
||||||
// incorrectly), while flagging a syntax error for "i+1, j, k".
|
// incorrectly), while flagging a syntax error for "i+1, j, k".
|
||||||
struct OmpDependenceType {
|
struct OmpDependenceType {
|
||||||
ENUM_CLASS(Type, Sink, Source);
|
ENUM_CLASS(Value, Sink, Source);
|
||||||
WRAPPER_CLASS_BOILERPLATE(OmpDependenceType, Type);
|
WRAPPER_CLASS_BOILERPLATE(OmpDependenceType, Value);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Ref: [5.0:47-49], [5.1:49-51], [5.2:67-69]
|
||||||
|
//
|
||||||
|
// iterator-modifier ->
|
||||||
|
// ITERATOR(iterator-specifier [, ...]) // since 5.0
|
||||||
|
struct OmpIterator {
|
||||||
|
WRAPPER_CLASS_BOILERPLATE(OmpIterator, std::list<OmpIteratorSpecifier>);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Ref: [4.5:207-210], [5.0:290-293], [5.1:323-325], [5.2:117-120]
|
||||||
|
//
|
||||||
|
// linear-modifier ->
|
||||||
|
// REF | UVAL | VAL // since 4.5
|
||||||
|
struct OmpLinearModifier {
|
||||||
|
ENUM_CLASS(Value, Ref, Uval, Val);
|
||||||
|
WRAPPER_CLASS_BOILERPLATE(OmpLinearModifier, Value);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Ref: [4.5:201-207], [5.0:293-299], [5.1:325-331], [5.2:124]
|
||||||
|
//
|
||||||
|
// reduction-identifier ->
|
||||||
|
// base-language-identifier | // since 4.5
|
||||||
|
// - | // since 4.5, until 5.2
|
||||||
|
// + | * | .AND. | .OR. | .EQV. | .NEQV. | // since 4.5
|
||||||
|
// MIN | MAX | IAND | IOR | IEOR // since 4.5
|
||||||
|
//
|
||||||
|
struct OmpReductionIdentifier {
|
||||||
|
UNION_CLASS_BOILERPLATE(OmpReductionIdentifier);
|
||||||
|
std::variant<DefinedOperator, ProcedureDesignator> u;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Ref: [4.5:169-170], [5.0:254-256], [5.1:287-289], [5.2:321]
|
// Ref: [4.5:169-170], [5.0:254-256], [5.1:287-289], [5.2:321]
|
||||||
//
|
//
|
||||||
// task-dependence-type -> // "dependence-type" in 5.1 and before
|
// task-dependence-type -> // "dependence-type" in 5.1 and before
|
||||||
// IN | OUT | INOUT | // since 4.5
|
// IN | OUT | INOUT | // since 4.5
|
||||||
// MUTEXINOUTSET | DEPOBJ | // since 5.0
|
// MUTEXINOUTSET | DEPOBJ | // since 5.0
|
||||||
// INOUTSET // since 5.2
|
// INOUTSET // since 5.2
|
||||||
struct OmpTaskDependenceType {
|
struct OmpTaskDependenceType {
|
||||||
ENUM_CLASS(Type, In, Out, Inout, Inoutset, Mutexinoutset, Depobj)
|
ENUM_CLASS(Value, In, Out, Inout, Inoutset, Mutexinoutset, Depobj)
|
||||||
WRAPPER_CLASS_BOILERPLATE(OmpTaskDependenceType, Type);
|
WRAPPER_CLASS_BOILERPLATE(OmpTaskDependenceType, Value);
|
||||||
};
|
|
||||||
|
|
||||||
// [5.0] 2.1.6 iterator-specifier -> type-declaration-stmt = subscript-triple
|
|
||||||
// iterator-modifier -> iterator-specifier-list
|
|
||||||
struct OmpIteratorSpecifier {
|
|
||||||
TUPLE_CLASS_BOILERPLATE(OmpIteratorSpecifier);
|
|
||||||
CharBlock source;
|
|
||||||
std::tuple<TypeDeclarationStmt, SubscriptTriplet> t;
|
|
||||||
};
|
|
||||||
|
|
||||||
WRAPPER_CLASS(OmpIteratorModifier, std::list<OmpIteratorSpecifier>);
|
|
||||||
|
|
||||||
// 2.15.3.6 reduction-identifier -> + | - | * | .AND. | .OR. | .EQV. | .NEQV. |
|
|
||||||
// MAX | MIN | IAND | IOR | IEOR
|
|
||||||
struct OmpReductionOperator {
|
|
||||||
UNION_CLASS_BOILERPLATE(OmpReductionOperator);
|
|
||||||
std::variant<DefinedOperator, ProcedureDesignator> u;
|
|
||||||
};
|
};
|
||||||
|
} // namespace modifier
|
||||||
|
|
||||||
// --- Clauses
|
// --- Clauses
|
||||||
|
|
||||||
@ -3495,7 +3529,7 @@ struct OmpReductionOperator {
|
|||||||
// aff-modifier: interator-modifier
|
// aff-modifier: interator-modifier
|
||||||
struct OmpAffinityClause {
|
struct OmpAffinityClause {
|
||||||
TUPLE_CLASS_BOILERPLATE(OmpAffinityClause);
|
TUPLE_CLASS_BOILERPLATE(OmpAffinityClause);
|
||||||
std::tuple<std::optional<OmpIteratorModifier>, OmpObjectList> t;
|
std::tuple<std::optional<OmpIterator>, OmpObjectList> t;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 2.8.1 aligned-clause -> ALIGNED (variable-name-list[ : scalar-constant])
|
// 2.8.1 aligned-clause -> ALIGNED (variable-name-list[ : scalar-constant])
|
||||||
@ -3566,7 +3600,7 @@ WRAPPER_CLASS(OmpIterationVector, std::list<OmpIteration>);
|
|||||||
// OmpDoacrossClause), so that the context in TYPE_CONTEXT_PARSER can be set
|
// OmpDoacrossClause), so that the context in TYPE_CONTEXT_PARSER can be set
|
||||||
// separately for OmpDependClause and OmpDoacrossClause.
|
// separately for OmpDependClause and OmpDoacrossClause.
|
||||||
struct OmpDoacross {
|
struct OmpDoacross {
|
||||||
OmpDependenceType::Type GetDepType() const;
|
OmpDependenceType::Value GetDepType() const;
|
||||||
|
|
||||||
WRAPPER_CLASS(Sink, OmpIterationVector);
|
WRAPPER_CLASS(Sink, OmpIterationVector);
|
||||||
EMPTY_CLASS(Source);
|
EMPTY_CLASS(Source);
|
||||||
@ -3586,10 +3620,9 @@ struct OmpDoacross {
|
|||||||
struct OmpDependClause {
|
struct OmpDependClause {
|
||||||
UNION_CLASS_BOILERPLATE(OmpDependClause);
|
UNION_CLASS_BOILERPLATE(OmpDependClause);
|
||||||
struct TaskDep {
|
struct TaskDep {
|
||||||
OmpTaskDependenceType::Type GetTaskDepType() const;
|
OmpTaskDependenceType::Value GetTaskDepType() const;
|
||||||
TUPLE_CLASS_BOILERPLATE(TaskDep);
|
TUPLE_CLASS_BOILERPLATE(TaskDep);
|
||||||
std::tuple<std::optional<OmpIteratorModifier>, OmpTaskDependenceType,
|
std::tuple<std::optional<OmpIterator>, OmpTaskDependenceType, OmpObjectList>
|
||||||
OmpObjectList>
|
|
||||||
t;
|
t;
|
||||||
};
|
};
|
||||||
std::variant<TaskDep, OmpDoacross> u;
|
std::variant<TaskDep, OmpDoacross> u;
|
||||||
@ -3632,7 +3665,7 @@ struct OmpFromClause {
|
|||||||
// As in the case of MAP, modifiers are parsed as lists, even if they
|
// As in the case of MAP, modifiers are parsed as lists, even if they
|
||||||
// are unique. These restrictions will be checked in semantic checks.
|
// are unique. These restrictions will be checked in semantic checks.
|
||||||
std::tuple<std::optional<std::list<Expectation>>,
|
std::tuple<std::optional<std::list<Expectation>>,
|
||||||
std::optional<std::list<OmpIteratorModifier>>, OmpObjectList,
|
std::optional<std::list<OmpIterator>>, OmpObjectList,
|
||||||
bool> // were the modifiers comma-separated?
|
bool> // were the modifiers comma-separated?
|
||||||
t;
|
t;
|
||||||
};
|
};
|
||||||
@ -3661,7 +3694,7 @@ struct OmpDetachClause {
|
|||||||
// variable-name-list)
|
// variable-name-list)
|
||||||
struct OmpInReductionClause {
|
struct OmpInReductionClause {
|
||||||
TUPLE_CLASS_BOILERPLATE(OmpInReductionClause);
|
TUPLE_CLASS_BOILERPLATE(OmpInReductionClause);
|
||||||
std::tuple<OmpReductionOperator, OmpObjectList> t;
|
std::tuple<OmpReductionIdentifier, OmpObjectList> t;
|
||||||
};
|
};
|
||||||
|
|
||||||
// OMP 5.0 2.19.4.5 lastprivate-clause ->
|
// OMP 5.0 2.19.4.5 lastprivate-clause ->
|
||||||
@ -3673,12 +3706,6 @@ struct OmpLastprivateClause {
|
|||||||
std::tuple<std::optional<LastprivateModifier>, OmpObjectList> t;
|
std::tuple<std::optional<LastprivateModifier>, OmpObjectList> t;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 2.15.3.7 linear-modifier -> REF | VAL | UVAL
|
|
||||||
struct OmpLinearModifier {
|
|
||||||
ENUM_CLASS(Type, Ref, Val, Uval)
|
|
||||||
WRAPPER_CLASS_BOILERPLATE(OmpLinearModifier, Type);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 2.15.3.7 linear-clause -> LINEAR (linear-list[ : linear-step])
|
// 2.15.3.7 linear-clause -> LINEAR (linear-list[ : linear-step])
|
||||||
// linear-list -> list | linear-modifier(list)
|
// linear-list -> list | linear-modifier(list)
|
||||||
struct OmpLinearClause {
|
struct OmpLinearClause {
|
||||||
@ -3723,7 +3750,7 @@ struct OmpMapClause {
|
|||||||
// information about separator presence to emit a diagnostic if needed.
|
// information about separator presence to emit a diagnostic if needed.
|
||||||
std::tuple<OmpMapperIdentifier, // Mapper name
|
std::tuple<OmpMapperIdentifier, // Mapper name
|
||||||
std::optional<std::list<TypeModifier>>,
|
std::optional<std::list<TypeModifier>>,
|
||||||
std::optional<std::list<OmpIteratorModifier>>, // unique
|
std::optional<std::list<OmpIterator>>, // unique
|
||||||
std::optional<std::list<Type>>, // unique
|
std::optional<std::list<Type>>, // unique
|
||||||
OmpObjectList,
|
OmpObjectList,
|
||||||
bool> // were the modifiers comma-separated?
|
bool> // were the modifiers comma-separated?
|
||||||
@ -3753,7 +3780,7 @@ struct OmpProcBindClause {
|
|||||||
struct OmpReductionClause {
|
struct OmpReductionClause {
|
||||||
TUPLE_CLASS_BOILERPLATE(OmpReductionClause);
|
TUPLE_CLASS_BOILERPLATE(OmpReductionClause);
|
||||||
ENUM_CLASS(ReductionModifier, Inscan, Task, Default)
|
ENUM_CLASS(ReductionModifier, Inscan, Task, Default)
|
||||||
std::tuple<std::optional<ReductionModifier>, OmpReductionOperator,
|
std::tuple<std::optional<ReductionModifier>, OmpReductionIdentifier,
|
||||||
OmpObjectList>
|
OmpObjectList>
|
||||||
t;
|
t;
|
||||||
};
|
};
|
||||||
@ -3798,7 +3825,7 @@ struct OmpToClause {
|
|||||||
// As in the case of MAP, modifiers are parsed as lists, even if they
|
// As in the case of MAP, modifiers are parsed as lists, even if they
|
||||||
// are unique. These restrictions will be checked in semantic checks.
|
// are unique. These restrictions will be checked in semantic checks.
|
||||||
std::tuple<std::optional<std::list<Expectation>>,
|
std::tuple<std::optional<std::list<Expectation>>,
|
||||||
std::optional<std::list<OmpIteratorModifier>>, OmpObjectList,
|
std::optional<std::list<OmpIterator>>, OmpObjectList,
|
||||||
bool> // were the modifiers comma-separated?
|
bool> // were the modifiers comma-separated?
|
||||||
t;
|
t;
|
||||||
};
|
};
|
||||||
@ -3946,7 +3973,7 @@ WRAPPER_CLASS(OmpReductionInitializerClause, Expr);
|
|||||||
struct OpenMPDeclareReductionConstruct {
|
struct OpenMPDeclareReductionConstruct {
|
||||||
TUPLE_CLASS_BOILERPLATE(OpenMPDeclareReductionConstruct);
|
TUPLE_CLASS_BOILERPLATE(OpenMPDeclareReductionConstruct);
|
||||||
CharBlock source;
|
CharBlock source;
|
||||||
std::tuple<Verbatim, OmpReductionOperator, std::list<DeclarationTypeSpec>,
|
std::tuple<Verbatim, OmpReductionIdentifier, std::list<DeclarationTypeSpec>,
|
||||||
OmpReductionCombiner, std::optional<OmpReductionInitializerClause>>
|
OmpReductionCombiner, std::optional<OmpReductionInitializerClause>>
|
||||||
t;
|
t;
|
||||||
};
|
};
|
||||||
|
@ -265,7 +265,7 @@ makeIteratorSpecifiers(const parser::OmpIteratorSpecifier &inp,
|
|||||||
return specifiers;
|
return specifiers;
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator makeIterator(const parser::OmpIteratorModifier &inp,
|
Iterator makeIterator(const parser::OmpIterator &inp,
|
||||||
semantics::SemanticsContext &semaCtx) {
|
semantics::SemanticsContext &semaCtx) {
|
||||||
Iterator iterator;
|
Iterator iterator;
|
||||||
for (auto &&spec : inp.v)
|
for (auto &&spec : inp.v)
|
||||||
@ -325,8 +325,9 @@ makeProcedureDesignator(const parser::ProcedureDesignator &inp,
|
|||||||
inp.u)};
|
inp.u)};
|
||||||
}
|
}
|
||||||
|
|
||||||
ReductionOperator makeReductionOperator(const parser::OmpReductionOperator &inp,
|
ReductionOperator
|
||||||
semantics::SemanticsContext &semaCtx) {
|
makeReductionOperator(const parser::OmpReductionIdentifier &inp,
|
||||||
|
semantics::SemanticsContext &semaCtx) {
|
||||||
return Fortran::common::visit(
|
return Fortran::common::visit(
|
||||||
common::visitors{
|
common::visitors{
|
||||||
[&](const parser::DefinedOperator &s) {
|
[&](const parser::DefinedOperator &s) {
|
||||||
@ -341,9 +342,9 @@ ReductionOperator makeReductionOperator(const parser::OmpReductionOperator &inp,
|
|||||||
|
|
||||||
clause::DependenceType makeDepType(const parser::OmpDependenceType &inp) {
|
clause::DependenceType makeDepType(const parser::OmpDependenceType &inp) {
|
||||||
switch (inp.v) {
|
switch (inp.v) {
|
||||||
case parser::OmpDependenceType::Type::Sink:
|
case parser::OmpDependenceType::Value::Sink:
|
||||||
return clause::DependenceType::Sink;
|
return clause::DependenceType::Sink;
|
||||||
case parser::OmpDependenceType::Type::Source:
|
case parser::OmpDependenceType::Value::Source:
|
||||||
return clause::DependenceType::Source;
|
return clause::DependenceType::Source;
|
||||||
}
|
}
|
||||||
llvm_unreachable("Unexpected dependence type");
|
llvm_unreachable("Unexpected dependence type");
|
||||||
@ -351,17 +352,17 @@ clause::DependenceType makeDepType(const parser::OmpDependenceType &inp) {
|
|||||||
|
|
||||||
clause::DependenceType makeDepType(const parser::OmpTaskDependenceType &inp) {
|
clause::DependenceType makeDepType(const parser::OmpTaskDependenceType &inp) {
|
||||||
switch (inp.v) {
|
switch (inp.v) {
|
||||||
case parser::OmpTaskDependenceType::Type::Depobj:
|
case parser::OmpTaskDependenceType::Value::Depobj:
|
||||||
return clause::DependenceType::Depobj;
|
return clause::DependenceType::Depobj;
|
||||||
case parser::OmpTaskDependenceType::Type::In:
|
case parser::OmpTaskDependenceType::Value::In:
|
||||||
return clause::DependenceType::In;
|
return clause::DependenceType::In;
|
||||||
case parser::OmpTaskDependenceType::Type::Inout:
|
case parser::OmpTaskDependenceType::Value::Inout:
|
||||||
return clause::DependenceType::Inout;
|
return clause::DependenceType::Inout;
|
||||||
case parser::OmpTaskDependenceType::Type::Inoutset:
|
case parser::OmpTaskDependenceType::Value::Inoutset:
|
||||||
return clause::DependenceType::Inoutset;
|
return clause::DependenceType::Inoutset;
|
||||||
case parser::OmpTaskDependenceType::Type::Mutexinoutset:
|
case parser::OmpTaskDependenceType::Value::Mutexinoutset:
|
||||||
return clause::DependenceType::Mutexinoutset;
|
return clause::DependenceType::Mutexinoutset;
|
||||||
case parser::OmpTaskDependenceType::Type::Out:
|
case parser::OmpTaskDependenceType::Value::Out:
|
||||||
return clause::DependenceType::Out;
|
return clause::DependenceType::Out;
|
||||||
}
|
}
|
||||||
llvm_unreachable("Unexpected task dependence type");
|
llvm_unreachable("Unexpected task dependence type");
|
||||||
@ -382,7 +383,7 @@ Absent make(const parser::OmpClause::Absent &inp,
|
|||||||
Affinity make(const parser::OmpClause::Affinity &inp,
|
Affinity make(const parser::OmpClause::Affinity &inp,
|
||||||
semantics::SemanticsContext &semaCtx) {
|
semantics::SemanticsContext &semaCtx) {
|
||||||
// inp.v -> parser::OmpAffinityClause
|
// inp.v -> parser::OmpAffinityClause
|
||||||
auto &t0 = std::get<std::optional<parser::OmpIteratorModifier>>(inp.v.t);
|
auto &t0 = std::get<std::optional<parser::OmpIterator>>(inp.v.t);
|
||||||
auto &t1 = std::get<parser::OmpObjectList>(inp.v.t);
|
auto &t1 = std::get<parser::OmpObjectList>(inp.v.t);
|
||||||
|
|
||||||
auto &&maybeIter =
|
auto &&maybeIter =
|
||||||
@ -627,7 +628,7 @@ Depend make(const parser::OmpClause::Depend &inp,
|
|||||||
using Variant = decltype(Depend::u);
|
using Variant = decltype(Depend::u);
|
||||||
|
|
||||||
auto visitTaskDep = [&](const wrapped::TaskDep &s) -> Variant {
|
auto visitTaskDep = [&](const wrapped::TaskDep &s) -> Variant {
|
||||||
auto &t0 = std::get<std::optional<parser::OmpIteratorModifier>>(s.t);
|
auto &t0 = std::get<std::optional<parser::OmpIterator>>(s.t);
|
||||||
auto &t1 = std::get<parser::OmpTaskDependenceType>(s.t);
|
auto &t1 = std::get<parser::OmpTaskDependenceType>(s.t);
|
||||||
auto &t2 = std::get<parser::OmpObjectList>(s.t);
|
auto &t2 = std::get<parser::OmpObjectList>(s.t);
|
||||||
|
|
||||||
@ -770,8 +771,7 @@ From make(const parser::OmpClause::From &inp,
|
|||||||
);
|
);
|
||||||
|
|
||||||
auto &t0 = std::get<std::optional<std::list<wrapped::Expectation>>>(inp.v.t);
|
auto &t0 = std::get<std::optional<std::list<wrapped::Expectation>>>(inp.v.t);
|
||||||
auto &t1 =
|
auto &t1 = std::get<std::optional<std::list<parser::OmpIterator>>>(inp.v.t);
|
||||||
std::get<std::optional<std::list<parser::OmpIteratorModifier>>>(inp.v.t);
|
|
||||||
auto &t2 = std::get<parser::OmpObjectList>(inp.v.t);
|
auto &t2 = std::get<parser::OmpObjectList>(inp.v.t);
|
||||||
|
|
||||||
assert((!t0 || t0->size() == 1) && "Only one expectation modifier allowed");
|
assert((!t0 || t0->size() == 1) && "Only one expectation modifier allowed");
|
||||||
@ -882,7 +882,7 @@ Init make(const parser::OmpClause::Init &inp,
|
|||||||
InReduction make(const parser::OmpClause::InReduction &inp,
|
InReduction make(const parser::OmpClause::InReduction &inp,
|
||||||
semantics::SemanticsContext &semaCtx) {
|
semantics::SemanticsContext &semaCtx) {
|
||||||
// inp.v -> parser::OmpInReductionClause
|
// inp.v -> parser::OmpInReductionClause
|
||||||
auto &t0 = std::get<parser::OmpReductionOperator>(inp.v.t);
|
auto &t0 = std::get<parser::OmpReductionIdentifier>(inp.v.t);
|
||||||
auto &t1 = std::get<parser::OmpObjectList>(inp.v.t);
|
auto &t1 = std::get<parser::OmpObjectList>(inp.v.t);
|
||||||
return InReduction{
|
return InReduction{
|
||||||
{/*ReductionIdentifiers=*/{makeReductionOperator(t0, semaCtx)},
|
{/*ReductionIdentifiers=*/{makeReductionOperator(t0, semaCtx)},
|
||||||
@ -921,7 +921,7 @@ Linear make(const parser::OmpClause::Linear &inp,
|
|||||||
using wrapped = parser::OmpLinearClause;
|
using wrapped = parser::OmpLinearClause;
|
||||||
|
|
||||||
CLAUSET_ENUM_CONVERT( //
|
CLAUSET_ENUM_CONVERT( //
|
||||||
convert, parser::OmpLinearModifier::Type, Linear::LinearModifier,
|
convert, parser::OmpLinearModifier::Value, Linear::LinearModifier,
|
||||||
// clang-format off
|
// clang-format off
|
||||||
MS(Ref, Ref)
|
MS(Ref, Ref)
|
||||||
MS(Val, Val)
|
MS(Val, Val)
|
||||||
@ -985,8 +985,7 @@ Map make(const parser::OmpClause::Map &inp,
|
|||||||
);
|
);
|
||||||
|
|
||||||
auto &t0 = std::get<std::optional<std::list<wrapped::TypeModifier>>>(inp.v.t);
|
auto &t0 = std::get<std::optional<std::list<wrapped::TypeModifier>>>(inp.v.t);
|
||||||
auto &t1 =
|
auto &t1 = std::get<std::optional<std::list<parser::OmpIterator>>>(inp.v.t);
|
||||||
std::get<std::optional<std::list<parser::OmpIteratorModifier>>>(inp.v.t);
|
|
||||||
auto &t2 = std::get<std::optional<std::list<wrapped::Type>>>(inp.v.t);
|
auto &t2 = std::get<std::optional<std::list<wrapped::Type>>>(inp.v.t);
|
||||||
auto &t3 = std::get<parser::OmpObjectList>(inp.v.t);
|
auto &t3 = std::get<parser::OmpObjectList>(inp.v.t);
|
||||||
auto &t4 = std::get<parser::OmpMapperIdentifier>(inp.v.t);
|
auto &t4 = std::get<parser::OmpMapperIdentifier>(inp.v.t);
|
||||||
@ -1193,7 +1192,7 @@ Reduction make(const parser::OmpClause::Reduction &inp,
|
|||||||
auto &t0 =
|
auto &t0 =
|
||||||
std::get<std::optional<parser::OmpReductionClause::ReductionModifier>>(
|
std::get<std::optional<parser::OmpReductionClause::ReductionModifier>>(
|
||||||
inp.v.t);
|
inp.v.t);
|
||||||
auto &t1 = std::get<parser::OmpReductionOperator>(inp.v.t);
|
auto &t1 = std::get<parser::OmpReductionIdentifier>(inp.v.t);
|
||||||
auto &t2 = std::get<parser::OmpObjectList>(inp.v.t);
|
auto &t2 = std::get<parser::OmpObjectList>(inp.v.t);
|
||||||
return Reduction{
|
return Reduction{
|
||||||
{/*ReductionModifier=*/t0
|
{/*ReductionModifier=*/t0
|
||||||
@ -1320,7 +1319,7 @@ Permutation make(const parser::OmpClause::Permutation &inp,
|
|||||||
TaskReduction make(const parser::OmpClause::TaskReduction &inp,
|
TaskReduction make(const parser::OmpClause::TaskReduction &inp,
|
||||||
semantics::SemanticsContext &semaCtx) {
|
semantics::SemanticsContext &semaCtx) {
|
||||||
// inp.v -> parser::OmpReductionClause
|
// inp.v -> parser::OmpReductionClause
|
||||||
auto &t0 = std::get<parser::OmpReductionOperator>(inp.v.t);
|
auto &t0 = std::get<parser::OmpReductionIdentifier>(inp.v.t);
|
||||||
auto &t1 = std::get<parser::OmpObjectList>(inp.v.t);
|
auto &t1 = std::get<parser::OmpObjectList>(inp.v.t);
|
||||||
return TaskReduction{
|
return TaskReduction{
|
||||||
{/*ReductionIdentifiers=*/{makeReductionOperator(t0, semaCtx)},
|
{/*ReductionIdentifiers=*/{makeReductionOperator(t0, semaCtx)},
|
||||||
@ -1349,8 +1348,7 @@ To make(const parser::OmpClause::To &inp,
|
|||||||
);
|
);
|
||||||
|
|
||||||
auto &t0 = std::get<std::optional<std::list<wrapped::Expectation>>>(inp.v.t);
|
auto &t0 = std::get<std::optional<std::list<wrapped::Expectation>>>(inp.v.t);
|
||||||
auto &t1 =
|
auto &t1 = std::get<std::optional<std::list<parser::OmpIterator>>>(inp.v.t);
|
||||||
std::get<std::optional<std::list<parser::OmpIteratorModifier>>>(inp.v.t);
|
|
||||||
auto &t2 = std::get<parser::OmpObjectList>(inp.v.t);
|
auto &t2 = std::get<parser::OmpObjectList>(inp.v.t);
|
||||||
|
|
||||||
assert((!t0 || t0->size() == 1) && "Only one expectation modifier allowed");
|
assert((!t0 || t0->size() == 1) && "Only one expectation modifier allowed");
|
||||||
|
@ -97,7 +97,7 @@ template <typename Separator> struct MapModifiers {
|
|||||||
|
|
||||||
// Parsing of mappers is not supported yet.
|
// Parsing of mappers is not supported yet.
|
||||||
using TypeModParser = Parser<OmpMapClause::TypeModifier>;
|
using TypeModParser = Parser<OmpMapClause::TypeModifier>;
|
||||||
using IterParser = Parser<OmpIteratorModifier>;
|
using IterParser = Parser<OmpIterator>;
|
||||||
using TypeParser = Parser<OmpMapClause::Type>;
|
using TypeParser = Parser<OmpMapClause::Type>;
|
||||||
using ModParser =
|
using ModParser =
|
||||||
ConcatSeparated<Separator, TypeModParser, IterParser, TypeParser>;
|
ConcatSeparated<Separator, TypeModParser, IterParser, TypeParser>;
|
||||||
@ -132,7 +132,7 @@ template <typename Separator> struct MotionModifiers {
|
|||||||
constexpr MotionModifiers(MotionModifiers &&) = default;
|
constexpr MotionModifiers(MotionModifiers &&) = default;
|
||||||
|
|
||||||
using ExpParser = Parser<OmpFromClause::Expectation>;
|
using ExpParser = Parser<OmpFromClause::Expectation>;
|
||||||
using IterParser = Parser<OmpIteratorModifier>;
|
using IterParser = Parser<OmpIterator>;
|
||||||
using ModParser = ConcatSeparated<Separator, ExpParser, IterParser>;
|
using ModParser = ConcatSeparated<Separator, ExpParser, IterParser>;
|
||||||
|
|
||||||
using resultType = typename ModParser::resultType;
|
using resultType = typename ModParser::resultType;
|
||||||
@ -190,6 +190,8 @@ static TypeDeclarationStmt makeIterSpecDecl(std::list<ObjectName> &&names) {
|
|||||||
makeEntityList(std::move(names)));
|
makeEntityList(std::move(names)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- Parsers for clause modifiers -----------------------------------
|
||||||
|
|
||||||
TYPE_PARSER(construct<OmpIteratorSpecifier>(
|
TYPE_PARSER(construct<OmpIteratorSpecifier>(
|
||||||
// Using Parser<TypeDeclarationStmt> or Parser<EntityDecl> has the problem
|
// Using Parser<TypeDeclarationStmt> or Parser<EntityDecl> has the problem
|
||||||
// that they will attempt to treat what follows the '=' as initialization.
|
// that they will attempt to treat what follows the '=' as initialization.
|
||||||
@ -206,14 +208,40 @@ TYPE_PARSER(construct<OmpIteratorSpecifier>(
|
|||||||
makeIterSpecDecl, nonemptyList(Parser<ObjectName>{}) / "="_tok)),
|
makeIterSpecDecl, nonemptyList(Parser<ObjectName>{}) / "="_tok)),
|
||||||
subscriptTriplet))
|
subscriptTriplet))
|
||||||
|
|
||||||
|
TYPE_PARSER(construct<OmpDependenceType>(
|
||||||
|
"SINK" >> pure(OmpDependenceType::Value::Sink) ||
|
||||||
|
"SOURCE" >> pure(OmpDependenceType::Value::Source)))
|
||||||
|
|
||||||
// [5.0] 2.1.6 iterator -> iterator-specifier-list
|
// [5.0] 2.1.6 iterator -> iterator-specifier-list
|
||||||
TYPE_PARSER(construct<OmpIteratorModifier>("ITERATOR" >>
|
TYPE_PARSER(construct<OmpIterator>("ITERATOR" >>
|
||||||
parenthesized(nonemptyList(sourced(Parser<OmpIteratorSpecifier>{})))))
|
parenthesized(nonemptyList(sourced(Parser<OmpIteratorSpecifier>{})))))
|
||||||
|
|
||||||
|
// 2.15.3.7 LINEAR (linear-list: linear-step)
|
||||||
|
// linear-list -> list | modifier(list)
|
||||||
|
// linear-modifier -> REF | VAL | UVAL
|
||||||
|
TYPE_PARSER(construct<OmpLinearModifier>( //
|
||||||
|
"REF" >> pure(OmpLinearModifier::Value::Ref) ||
|
||||||
|
"VAL" >> pure(OmpLinearModifier::Value::Val) ||
|
||||||
|
"UVAL" >> pure(OmpLinearModifier::Value::Uval)))
|
||||||
|
|
||||||
|
// 2.15.3.6 REDUCTION (reduction-identifier: variable-name-list)
|
||||||
|
TYPE_PARSER(construct<OmpReductionIdentifier>(Parser<DefinedOperator>{}) ||
|
||||||
|
construct<OmpReductionIdentifier>(Parser<ProcedureDesignator>{}))
|
||||||
|
|
||||||
|
TYPE_PARSER(construct<OmpTaskDependenceType>(
|
||||||
|
"DEPOBJ" >> pure(OmpTaskDependenceType::Value::Depobj) ||
|
||||||
|
"IN"_id >> pure(OmpTaskDependenceType::Value::In) ||
|
||||||
|
"INOUT"_id >> pure(OmpTaskDependenceType::Value::Inout) ||
|
||||||
|
"INOUTSET"_id >> pure(OmpTaskDependenceType::Value::Inoutset) ||
|
||||||
|
"MUTEXINOUTSET" >> pure(OmpTaskDependenceType::Value::Mutexinoutset) ||
|
||||||
|
"OUT" >> pure(OmpTaskDependenceType::Value::Out)))
|
||||||
|
|
||||||
|
// --- Parsers for clauses --------------------------------------------
|
||||||
|
|
||||||
// [5.0] 2.10.1 affinity([aff-modifier:] locator-list)
|
// [5.0] 2.10.1 affinity([aff-modifier:] locator-list)
|
||||||
// aff-modifier: interator-modifier
|
// aff-modifier: interator-modifier
|
||||||
TYPE_PARSER(construct<OmpAffinityClause>(
|
TYPE_PARSER(construct<OmpAffinityClause>(
|
||||||
maybe(Parser<OmpIteratorModifier>{} / ":"), Parser<OmpObjectList>{}))
|
maybe(Parser<OmpIterator>{} / ":"), Parser<OmpObjectList>{}))
|
||||||
|
|
||||||
// 2.15.3.1 DEFAULT (PRIVATE | FIRSTPRIVATE | SHARED | NONE)
|
// 2.15.3.1 DEFAULT (PRIVATE | FIRSTPRIVATE | SHARED | NONE)
|
||||||
TYPE_PARSER(construct<OmpDefaultClause>(
|
TYPE_PARSER(construct<OmpDefaultClause>(
|
||||||
@ -251,7 +279,7 @@ TYPE_PARSER(
|
|||||||
template <bool CommasEverywhere>
|
template <bool CommasEverywhere>
|
||||||
static inline OmpMapClause makeMapClause(OmpMapperIdentifier &&mm,
|
static inline OmpMapClause makeMapClause(OmpMapperIdentifier &&mm,
|
||||||
std::tuple<std::optional<std::list<OmpMapClause::TypeModifier>>,
|
std::tuple<std::optional<std::list<OmpMapClause::TypeModifier>>,
|
||||||
std::optional<std::list<OmpIteratorModifier>>,
|
std::optional<std::list<OmpIterator>>,
|
||||||
std::optional<std::list<OmpMapClause::Type>>> &&mods,
|
std::optional<std::list<OmpMapClause::Type>>> &&mods,
|
||||||
OmpObjectList &&objs) {
|
OmpObjectList &&objs) {
|
||||||
auto &&[tm, it, ty] = std::move(mods);
|
auto &&[tm, it, ty] = std::move(mods);
|
||||||
@ -350,21 +378,17 @@ TYPE_PARSER(construct<OmpIfClause>(
|
|||||||
":"),
|
":"),
|
||||||
scalarLogicalExpr))
|
scalarLogicalExpr))
|
||||||
|
|
||||||
// 2.15.3.6 REDUCTION (reduction-identifier: variable-name-list)
|
|
||||||
TYPE_PARSER(construct<OmpReductionOperator>(Parser<DefinedOperator>{}) ||
|
|
||||||
construct<OmpReductionOperator>(Parser<ProcedureDesignator>{}))
|
|
||||||
|
|
||||||
TYPE_PARSER(construct<OmpReductionClause>(
|
TYPE_PARSER(construct<OmpReductionClause>(
|
||||||
maybe(
|
maybe(
|
||||||
("INSCAN" >> pure(OmpReductionClause::ReductionModifier::Inscan) ||
|
("INSCAN" >> pure(OmpReductionClause::ReductionModifier::Inscan) ||
|
||||||
"TASK" >> pure(OmpReductionClause::ReductionModifier::Task) ||
|
"TASK" >> pure(OmpReductionClause::ReductionModifier::Task) ||
|
||||||
"DEFAULT" >> pure(OmpReductionClause::ReductionModifier::Default)) /
|
"DEFAULT" >> pure(OmpReductionClause::ReductionModifier::Default)) /
|
||||||
","),
|
","),
|
||||||
Parser<OmpReductionOperator>{} / ":", Parser<OmpObjectList>{}))
|
Parser<OmpReductionIdentifier>{} / ":", Parser<OmpObjectList>{}))
|
||||||
|
|
||||||
// OMP 5.0 2.19.5.6 IN_REDUCTION (reduction-identifier: variable-name-list)
|
// OMP 5.0 2.19.5.6 IN_REDUCTION (reduction-identifier: variable-name-list)
|
||||||
TYPE_PARSER(construct<OmpInReductionClause>(
|
TYPE_PARSER(construct<OmpInReductionClause>(
|
||||||
Parser<OmpReductionOperator>{} / ":", Parser<OmpObjectList>{}))
|
Parser<OmpReductionIdentifier>{} / ":", Parser<OmpObjectList>{}))
|
||||||
|
|
||||||
// OMP 5.0 2.11.4 allocate-clause -> ALLOCATE ([allocator:] variable-name-list)
|
// OMP 5.0 2.11.4 allocate-clause -> ALLOCATE ([allocator:] variable-name-list)
|
||||||
// OMP 5.2 2.13.4 allocate-clause -> ALLOCATE ([allocate-modifier
|
// OMP 5.2 2.13.4 allocate-clause -> ALLOCATE ([allocate-modifier
|
||||||
@ -397,18 +421,6 @@ TYPE_PARSER(construct<OmpAllocateClause>(
|
|||||||
":"),
|
":"),
|
||||||
Parser<OmpObjectList>{}))
|
Parser<OmpObjectList>{}))
|
||||||
|
|
||||||
TYPE_PARSER(construct<OmpDependenceType>(
|
|
||||||
"SINK" >> pure(OmpDependenceType::Type::Sink) ||
|
|
||||||
"SOURCE" >> pure(OmpDependenceType::Type::Source)))
|
|
||||||
|
|
||||||
TYPE_PARSER(construct<OmpTaskDependenceType>(
|
|
||||||
"DEPOBJ" >> pure(OmpTaskDependenceType::Type::Depobj) ||
|
|
||||||
"IN"_id >> pure(OmpTaskDependenceType::Type::In) ||
|
|
||||||
"INOUT"_id >> pure(OmpTaskDependenceType::Type::Inout) ||
|
|
||||||
"INOUTSET"_id >> pure(OmpTaskDependenceType::Type::Inoutset) ||
|
|
||||||
"MUTEXINOUTSET" >> pure(OmpTaskDependenceType::Type::Mutexinoutset) ||
|
|
||||||
"OUT" >> pure(OmpTaskDependenceType::Type::Out)))
|
|
||||||
|
|
||||||
// iteration-offset -> +/- non-negative-constant-expr
|
// iteration-offset -> +/- non-negative-constant-expr
|
||||||
TYPE_PARSER(construct<OmpIterationOffset>(
|
TYPE_PARSER(construct<OmpIterationOffset>(
|
||||||
Parser<DefinedOperator>{}, scalarIntConstantExpr))
|
Parser<DefinedOperator>{}, scalarIntConstantExpr))
|
||||||
@ -426,7 +438,7 @@ TYPE_PARSER(construct<OmpDoacross>(
|
|||||||
TYPE_CONTEXT_PARSER("Omp Depend clause"_en_US,
|
TYPE_CONTEXT_PARSER("Omp Depend clause"_en_US,
|
||||||
construct<OmpDependClause>(
|
construct<OmpDependClause>(
|
||||||
construct<OmpDependClause>(construct<OmpDependClause::TaskDep>(
|
construct<OmpDependClause>(construct<OmpDependClause::TaskDep>(
|
||||||
maybe(Parser<OmpIteratorModifier>{} / ","_tok),
|
maybe(Parser<OmpIterator>{} / ","_tok),
|
||||||
Parser<OmpTaskDependenceType>{} / ":", Parser<OmpObjectList>{})) ||
|
Parser<OmpTaskDependenceType>{} / ":", Parser<OmpObjectList>{})) ||
|
||||||
construct<OmpDependClause>(Parser<OmpDoacross>{})))
|
construct<OmpDependClause>(Parser<OmpDoacross>{})))
|
||||||
|
|
||||||
@ -439,7 +451,7 @@ TYPE_PARSER(construct<OmpFromClause::Expectation>(
|
|||||||
template <typename MotionClause, bool CommasEverywhere>
|
template <typename MotionClause, bool CommasEverywhere>
|
||||||
static inline MotionClause makeMotionClause(
|
static inline MotionClause makeMotionClause(
|
||||||
std::tuple<std::optional<std::list<typename MotionClause::Expectation>>,
|
std::tuple<std::optional<std::list<typename MotionClause::Expectation>>,
|
||||||
std::optional<std::list<OmpIteratorModifier>>> &&mods,
|
std::optional<std::list<OmpIterator>>> &&mods,
|
||||||
OmpObjectList &&objs) {
|
OmpObjectList &&objs) {
|
||||||
auto &&[exp, iter] = std::move(mods);
|
auto &&[exp, iter] = std::move(mods);
|
||||||
return MotionClause(
|
return MotionClause(
|
||||||
@ -458,14 +470,6 @@ TYPE_PARSER(construct<OmpToClause>(
|
|||||||
applyFunction<OmpToClause>(makeMotionClause<OmpToClause, false>,
|
applyFunction<OmpToClause>(makeMotionClause<OmpToClause, false>,
|
||||||
MotionModifiers(maybe(","_tok)), Parser<OmpObjectList>{})))
|
MotionModifiers(maybe(","_tok)), Parser<OmpObjectList>{})))
|
||||||
|
|
||||||
// 2.15.3.7 LINEAR (linear-list: linear-step)
|
|
||||||
// linear-list -> list | modifier(list)
|
|
||||||
// linear-modifier -> REF | VAL | UVAL
|
|
||||||
TYPE_PARSER(
|
|
||||||
construct<OmpLinearModifier>("REF" >> pure(OmpLinearModifier::Type::Ref) ||
|
|
||||||
"VAL" >> pure(OmpLinearModifier::Type::Val) ||
|
|
||||||
"UVAL" >> pure(OmpLinearModifier::Type::Uval)))
|
|
||||||
|
|
||||||
TYPE_CONTEXT_PARSER("Omp LINEAR clause"_en_US,
|
TYPE_CONTEXT_PARSER("Omp LINEAR clause"_en_US,
|
||||||
construct<OmpLinearClause>(
|
construct<OmpLinearClause>(
|
||||||
construct<OmpLinearClause>(construct<OmpLinearClause::WithModifier>(
|
construct<OmpLinearClause>(construct<OmpLinearClause::WithModifier>(
|
||||||
@ -848,7 +852,7 @@ TYPE_PARSER(construct<OmpReductionInitializerClause>(
|
|||||||
// 2.16 Declare Reduction Construct
|
// 2.16 Declare Reduction Construct
|
||||||
TYPE_PARSER(sourced(construct<OpenMPDeclareReductionConstruct>(
|
TYPE_PARSER(sourced(construct<OpenMPDeclareReductionConstruct>(
|
||||||
verbatim("DECLARE REDUCTION"_tok),
|
verbatim("DECLARE REDUCTION"_tok),
|
||||||
"(" >> Parser<OmpReductionOperator>{} / ":",
|
"(" >> Parser<OmpReductionIdentifier>{} / ":",
|
||||||
nonemptyList(Parser<DeclarationTypeSpec>{}) / ":",
|
nonemptyList(Parser<DeclarationTypeSpec>{}) / ":",
|
||||||
Parser<OmpReductionCombiner>{} / ")",
|
Parser<OmpReductionCombiner>{} / ")",
|
||||||
maybe(Parser<OmpReductionInitializerClause>{}))))
|
maybe(Parser<OmpReductionInitializerClause>{}))))
|
||||||
|
@ -253,20 +253,20 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const Name &x) {
|
|||||||
return os << x.ToString();
|
return os << x.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
OmpDependenceType::Type OmpDoacross::GetDepType() const {
|
OmpDependenceType::Value OmpDoacross::GetDepType() const {
|
||||||
return common::visit( //
|
return common::visit( //
|
||||||
common::visitors{
|
common::visitors{
|
||||||
[](const OmpDoacross::Sink &) {
|
[](const OmpDoacross::Sink &) {
|
||||||
return OmpDependenceType::Type::Sink;
|
return OmpDependenceType::Value::Sink;
|
||||||
},
|
},
|
||||||
[](const OmpDoacross::Source &) {
|
[](const OmpDoacross::Source &) {
|
||||||
return OmpDependenceType::Type::Source;
|
return OmpDependenceType::Value::Source;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
u);
|
u);
|
||||||
}
|
}
|
||||||
|
|
||||||
OmpTaskDependenceType::Type OmpDependClause::TaskDep::GetTaskDepType() const {
|
OmpTaskDependenceType::Value OmpDependClause::TaskDep::GetTaskDepType() const {
|
||||||
return std::get<parser::OmpTaskDependenceType>(t).v;
|
return std::get<parser::OmpTaskDependenceType>(t).v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2079,7 +2079,7 @@ public:
|
|||||||
Put(" = ");
|
Put(" = ");
|
||||||
Walk(std::get<SubscriptTriplet>(x.t));
|
Walk(std::get<SubscriptTriplet>(x.t));
|
||||||
}
|
}
|
||||||
void Unparse(const OmpIteratorModifier &x) {
|
void Unparse(const OmpIterator &x) {
|
||||||
Word("ITERATOR(");
|
Word("ITERATOR(");
|
||||||
Walk(x.v);
|
Walk(x.v);
|
||||||
Put(")");
|
Put(")");
|
||||||
@ -2093,7 +2093,7 @@ public:
|
|||||||
void Unparse(const OmpMapClause &x) {
|
void Unparse(const OmpMapClause &x) {
|
||||||
auto &typeMod =
|
auto &typeMod =
|
||||||
std::get<std::optional<std::list<OmpMapClause::TypeModifier>>>(x.t);
|
std::get<std::optional<std::list<OmpMapClause::TypeModifier>>>(x.t);
|
||||||
auto &iter = std::get<std::optional<std::list<OmpIteratorModifier>>>(x.t);
|
auto &iter = std::get<std::optional<std::list<OmpIterator>>>(x.t);
|
||||||
auto &type = std::get<std::optional<std::list<OmpMapClause::Type>>>(x.t);
|
auto &type = std::get<std::optional<std::list<OmpMapClause::Type>>>(x.t);
|
||||||
auto &mapper = std::get<OmpMapperIdentifier>(x.t);
|
auto &mapper = std::get<OmpMapperIdentifier>(x.t);
|
||||||
|
|
||||||
@ -2147,7 +2147,7 @@ public:
|
|||||||
Walk(std::get<ScalarIntExpr>(x.t));
|
Walk(std::get<ScalarIntExpr>(x.t));
|
||||||
}
|
}
|
||||||
void Unparse(const OmpAffinityClause &x) {
|
void Unparse(const OmpAffinityClause &x) {
|
||||||
Walk(std::get<std::optional<OmpIteratorModifier>>(x.t), ":");
|
Walk(std::get<std::optional<OmpIterator>>(x.t), ":");
|
||||||
Walk(std::get<OmpObjectList>(x.t));
|
Walk(std::get<OmpObjectList>(x.t));
|
||||||
}
|
}
|
||||||
void Unparse(const OmpAlignedClause &x) {
|
void Unparse(const OmpAlignedClause &x) {
|
||||||
@ -2158,7 +2158,7 @@ public:
|
|||||||
void Unparse(const OmpFromClause &x) {
|
void Unparse(const OmpFromClause &x) {
|
||||||
auto &expect{
|
auto &expect{
|
||||||
std::get<std::optional<std::list<OmpFromClause::Expectation>>>(x.t)};
|
std::get<std::optional<std::list<OmpFromClause::Expectation>>>(x.t)};
|
||||||
auto &iter{std::get<std::optional<std::list<OmpIteratorModifier>>>(x.t)};
|
auto &iter{std::get<std::optional<std::list<OmpIterator>>>(x.t)};
|
||||||
bool needComma{false};
|
bool needComma{false};
|
||||||
if (expect) {
|
if (expect) {
|
||||||
Walk(*expect);
|
Walk(*expect);
|
||||||
@ -2191,13 +2191,13 @@ public:
|
|||||||
void Unparse(const OmpReductionClause &x) {
|
void Unparse(const OmpReductionClause &x) {
|
||||||
Walk(std::get<std::optional<OmpReductionClause::ReductionModifier>>(x.t),
|
Walk(std::get<std::optional<OmpReductionClause::ReductionModifier>>(x.t),
|
||||||
",");
|
",");
|
||||||
Walk(std::get<OmpReductionOperator>(x.t));
|
Walk(std::get<OmpReductionIdentifier>(x.t));
|
||||||
Put(":");
|
Put(":");
|
||||||
Walk(std::get<OmpObjectList>(x.t));
|
Walk(std::get<OmpObjectList>(x.t));
|
||||||
}
|
}
|
||||||
void Unparse(const OmpDetachClause &x) { Walk(x.v); }
|
void Unparse(const OmpDetachClause &x) { Walk(x.v); }
|
||||||
void Unparse(const OmpInReductionClause &x) {
|
void Unparse(const OmpInReductionClause &x) {
|
||||||
Walk(std::get<OmpReductionOperator>(x.t));
|
Walk(std::get<OmpReductionIdentifier>(x.t));
|
||||||
Put(":");
|
Put(":");
|
||||||
Walk(std::get<OmpObjectList>(x.t));
|
Walk(std::get<OmpObjectList>(x.t));
|
||||||
}
|
}
|
||||||
@ -2263,7 +2263,7 @@ public:
|
|||||||
void Unparse(const OmpToClause &x) {
|
void Unparse(const OmpToClause &x) {
|
||||||
auto &expect{
|
auto &expect{
|
||||||
std::get<std::optional<std::list<OmpToClause::Expectation>>>(x.t)};
|
std::get<std::optional<std::list<OmpToClause::Expectation>>>(x.t)};
|
||||||
auto &iter{std::get<std::optional<std::list<OmpIteratorModifier>>>(x.t)};
|
auto &iter{std::get<std::optional<std::list<OmpIterator>>>(x.t)};
|
||||||
bool needComma{false};
|
bool needComma{false};
|
||||||
if (expect) {
|
if (expect) {
|
||||||
Walk(*expect);
|
Walk(*expect);
|
||||||
@ -2645,7 +2645,7 @@ public:
|
|||||||
}
|
}
|
||||||
void Unparse(const OpenMPDeclareReductionConstruct &x) {
|
void Unparse(const OpenMPDeclareReductionConstruct &x) {
|
||||||
Put("(");
|
Put("(");
|
||||||
Walk(std::get<OmpReductionOperator>(x.t)), Put(" : ");
|
Walk(std::get<OmpReductionIdentifier>(x.t)), Put(" : ");
|
||||||
Walk(std::get<std::list<DeclarationTypeSpec>>(x.t), ","), Put(" : ");
|
Walk(std::get<std::list<DeclarationTypeSpec>>(x.t), ","), Put(" : ");
|
||||||
Walk(std::get<OmpReductionCombiner>(x.t));
|
Walk(std::get<OmpReductionCombiner>(x.t));
|
||||||
Put(")");
|
Put(")");
|
||||||
@ -2910,8 +2910,8 @@ public:
|
|||||||
WALK_NESTED_ENUM(
|
WALK_NESTED_ENUM(
|
||||||
OmpLastprivateClause, LastprivateModifier) // OMP lastprivate-modifier
|
OmpLastprivateClause, LastprivateModifier) // OMP lastprivate-modifier
|
||||||
WALK_NESTED_ENUM(OmpScheduleModifierType, ModType) // OMP schedule-modifier
|
WALK_NESTED_ENUM(OmpScheduleModifierType, ModType) // OMP schedule-modifier
|
||||||
WALK_NESTED_ENUM(OmpLinearModifier, Type) // OMP linear-modifier
|
WALK_NESTED_ENUM(OmpLinearModifier, Value) // OMP linear-modifier
|
||||||
WALK_NESTED_ENUM(OmpTaskDependenceType, Type) // OMP task-dependence-type
|
WALK_NESTED_ENUM(OmpTaskDependenceType, Value) // OMP task-dependence-type
|
||||||
WALK_NESTED_ENUM(OmpScheduleClause, ScheduleType) // OMP schedule-type
|
WALK_NESTED_ENUM(OmpScheduleClause, ScheduleType) // OMP schedule-type
|
||||||
WALK_NESTED_ENUM(OmpDeviceClause, DeviceModifier) // OMP device modifier
|
WALK_NESTED_ENUM(OmpDeviceClause, DeviceModifier) // OMP device modifier
|
||||||
WALK_NESTED_ENUM(OmpDeviceTypeClause, Type) // OMP DEVICE_TYPE
|
WALK_NESTED_ENUM(OmpDeviceTypeClause, Type) // OMP DEVICE_TYPE
|
||||||
|
@ -683,8 +683,7 @@ void OmpStructureChecker::CheckIteratorRange(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OmpStructureChecker::CheckIteratorModifier(
|
void OmpStructureChecker::CheckIteratorModifier(const parser::OmpIterator &x) {
|
||||||
const parser::OmpIteratorModifier &x) {
|
|
||||||
// Check if all iterator variables have integer type.
|
// Check if all iterator variables have integer type.
|
||||||
for (auto &&iterSpec : x.v) {
|
for (auto &&iterSpec : x.v) {
|
||||||
bool isInteger{true};
|
bool isInteger{true};
|
||||||
@ -1859,21 +1858,21 @@ void OmpStructureChecker::CheckTargetUpdate() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void OmpStructureChecker::CheckTaskDependenceType(
|
void OmpStructureChecker::CheckTaskDependenceType(
|
||||||
const parser::OmpTaskDependenceType::Type &x) {
|
const parser::OmpTaskDependenceType::Value &x) {
|
||||||
// Common checks for task-dependence-type (DEPEND and UPDATE clauses).
|
// Common checks for task-dependence-type (DEPEND and UPDATE clauses).
|
||||||
unsigned version{context_.langOptions().OpenMPVersion};
|
unsigned version{context_.langOptions().OpenMPVersion};
|
||||||
unsigned since{0};
|
unsigned since{0};
|
||||||
|
|
||||||
switch (x) {
|
switch (x) {
|
||||||
case parser::OmpTaskDependenceType::Type::In:
|
case parser::OmpTaskDependenceType::Value::In:
|
||||||
case parser::OmpTaskDependenceType::Type::Out:
|
case parser::OmpTaskDependenceType::Value::Out:
|
||||||
case parser::OmpTaskDependenceType::Type::Inout:
|
case parser::OmpTaskDependenceType::Value::Inout:
|
||||||
break;
|
break;
|
||||||
case parser::OmpTaskDependenceType::Type::Mutexinoutset:
|
case parser::OmpTaskDependenceType::Value::Mutexinoutset:
|
||||||
case parser::OmpTaskDependenceType::Type::Depobj:
|
case parser::OmpTaskDependenceType::Value::Depobj:
|
||||||
since = 50;
|
since = 50;
|
||||||
break;
|
break;
|
||||||
case parser::OmpTaskDependenceType::Type::Inoutset:
|
case parser::OmpTaskDependenceType::Value::Inoutset:
|
||||||
since = 52;
|
since = 52;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1888,14 +1887,14 @@ void OmpStructureChecker::CheckTaskDependenceType(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void OmpStructureChecker::CheckDependenceType(
|
void OmpStructureChecker::CheckDependenceType(
|
||||||
const parser::OmpDependenceType::Type &x) {
|
const parser::OmpDependenceType::Value &x) {
|
||||||
// Common checks for dependence-type (DEPEND and UPDATE clauses).
|
// Common checks for dependence-type (DEPEND and UPDATE clauses).
|
||||||
unsigned version{context_.langOptions().OpenMPVersion};
|
unsigned version{context_.langOptions().OpenMPVersion};
|
||||||
unsigned deprecatedIn{~0u};
|
unsigned deprecatedIn{~0u};
|
||||||
|
|
||||||
switch (x) {
|
switch (x) {
|
||||||
case parser::OmpDependenceType::Type::Source:
|
case parser::OmpDependenceType::Value::Source:
|
||||||
case parser::OmpDependenceType::Type::Sink:
|
case parser::OmpDependenceType::Value::Sink:
|
||||||
deprecatedIn = 52;
|
deprecatedIn = 52;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2864,7 +2863,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Reduction &x) {
|
|||||||
bool OmpStructureChecker::CheckReductionOperators(
|
bool OmpStructureChecker::CheckReductionOperators(
|
||||||
const parser::OmpClause::Reduction &x) {
|
const parser::OmpClause::Reduction &x) {
|
||||||
|
|
||||||
const auto &definedOp{std::get<parser::OmpReductionOperator>(x.v.t)};
|
const auto &definedOp{std::get<parser::OmpReductionIdentifier>(x.v.t)};
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
common::visit(
|
common::visit(
|
||||||
common::visitors{
|
common::visitors{
|
||||||
@ -2929,7 +2928,7 @@ bool OmpStructureChecker::CheckIntrinsicOperator(
|
|||||||
|
|
||||||
static bool IsReductionAllowedForType(
|
static bool IsReductionAllowedForType(
|
||||||
const parser::OmpClause::Reduction &x, const DeclTypeSpec &type) {
|
const parser::OmpClause::Reduction &x, const DeclTypeSpec &type) {
|
||||||
const auto &definedOp{std::get<parser::OmpReductionOperator>(x.v.t)};
|
const auto &definedOp{std::get<parser::OmpReductionIdentifier>(x.v.t)};
|
||||||
// TODO: user defined reduction operators. Just allow everything for now.
|
// TODO: user defined reduction operators. Just allow everything for now.
|
||||||
bool ok{true};
|
bool ok{true};
|
||||||
|
|
||||||
@ -3484,7 +3483,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Map &x) {
|
|||||||
CheckAllowedClause(llvm::omp::Clause::OMPC_map);
|
CheckAllowedClause(llvm::omp::Clause::OMPC_map);
|
||||||
using TypeMod = parser::OmpMapClause::TypeModifier;
|
using TypeMod = parser::OmpMapClause::TypeModifier;
|
||||||
using Type = parser::OmpMapClause::Type;
|
using Type = parser::OmpMapClause::Type;
|
||||||
using IterMod = parser::OmpIteratorModifier;
|
using IterMod = parser::OmpIterator;
|
||||||
|
|
||||||
unsigned version{context_.langOptions().OpenMPVersion};
|
unsigned version{context_.langOptions().OpenMPVersion};
|
||||||
if (auto commas{std::get<bool>(x.v.t)}; !commas && version >= 52) {
|
if (auto commas{std::get<bool>(x.v.t)}; !commas && version >= 52) {
|
||||||
@ -3637,7 +3636,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Depend &x) {
|
|||||||
if (taskDep) {
|
if (taskDep) {
|
||||||
if (version == 50) {
|
if (version == 50) {
|
||||||
invalidDep = taskDep->GetTaskDepType() ==
|
invalidDep = taskDep->GetTaskDepType() ==
|
||||||
parser::OmpTaskDependenceType::Type::Depobj;
|
parser::OmpTaskDependenceType::Value::Depobj;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
invalidDep = true;
|
invalidDep = true;
|
||||||
@ -3684,7 +3683,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Depend &x) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (std::get<std::optional<parser::OmpIteratorModifier>>(taskDep->t)) {
|
if (std::get<std::optional<parser::OmpIterator>>(taskDep->t)) {
|
||||||
unsigned allowedInVersion{50};
|
unsigned allowedInVersion{50};
|
||||||
if (version < allowedInVersion) {
|
if (version < allowedInVersion) {
|
||||||
context_.Say(GetContext().clauseSource,
|
context_.Say(GetContext().clauseSource,
|
||||||
@ -3923,7 +3922,8 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Update &x) {
|
|||||||
if (version >= 51) {
|
if (version >= 51) {
|
||||||
bool invalidDep{false};
|
bool invalidDep{false};
|
||||||
if (taskType) {
|
if (taskType) {
|
||||||
invalidDep = taskType->v == parser::OmpTaskDependenceType::Type::Depobj;
|
invalidDep =
|
||||||
|
taskType->v == parser::OmpTaskDependenceType::Value::Depobj;
|
||||||
} else {
|
} else {
|
||||||
invalidDep = true;
|
invalidDep = true;
|
||||||
}
|
}
|
||||||
@ -4058,7 +4058,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::From &x) {
|
|||||||
CheckAllowedClause(llvm::omp::Clause::OMPC_from);
|
CheckAllowedClause(llvm::omp::Clause::OMPC_from);
|
||||||
unsigned version{context_.langOptions().OpenMPVersion};
|
unsigned version{context_.langOptions().OpenMPVersion};
|
||||||
using ExpMod = parser::OmpFromClause::Expectation;
|
using ExpMod = parser::OmpFromClause::Expectation;
|
||||||
using IterMod = parser::OmpIteratorModifier;
|
using IterMod = parser::OmpIterator;
|
||||||
|
|
||||||
if (auto &expMod{std::get<std::optional<std::list<ExpMod>>>(x.v.t)}) {
|
if (auto &expMod{std::get<std::optional<std::list<ExpMod>>>(x.v.t)}) {
|
||||||
unsigned allowedInVersion{51};
|
unsigned allowedInVersion{51};
|
||||||
@ -4122,7 +4122,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::To &x) {
|
|||||||
}
|
}
|
||||||
assert(GetContext().directive == llvm::omp::OMPD_target_update);
|
assert(GetContext().directive == llvm::omp::OMPD_target_update);
|
||||||
using ExpMod = parser::OmpFromClause::Expectation;
|
using ExpMod = parser::OmpFromClause::Expectation;
|
||||||
using IterMod = parser::OmpIteratorModifier;
|
using IterMod = parser::OmpIterator;
|
||||||
|
|
||||||
if (auto &expMod{std::get<std::optional<std::list<ExpMod>>>(x.v.t)}) {
|
if (auto &expMod{std::get<std::optional<std::list<ExpMod>>>(x.v.t)}) {
|
||||||
unsigned allowedInVersion{51};
|
unsigned allowedInVersion{51};
|
||||||
|
@ -202,7 +202,7 @@ private:
|
|||||||
void CheckWorkshareBlockStmts(const parser::Block &, parser::CharBlock);
|
void CheckWorkshareBlockStmts(const parser::Block &, parser::CharBlock);
|
||||||
|
|
||||||
void CheckIteratorRange(const parser::OmpIteratorSpecifier &x);
|
void CheckIteratorRange(const parser::OmpIteratorSpecifier &x);
|
||||||
void CheckIteratorModifier(const parser::OmpIteratorModifier &x);
|
void CheckIteratorModifier(const parser::OmpIterator &x);
|
||||||
void CheckLoopItrVariableIsInt(const parser::OpenMPLoopConstruct &x);
|
void CheckLoopItrVariableIsInt(const parser::OpenMPLoopConstruct &x);
|
||||||
void CheckDoWhile(const parser::OpenMPLoopConstruct &x);
|
void CheckDoWhile(const parser::OpenMPLoopConstruct &x);
|
||||||
void CheckAssociatedLoopConstraints(const parser::OpenMPLoopConstruct &x);
|
void CheckAssociatedLoopConstraints(const parser::OpenMPLoopConstruct &x);
|
||||||
@ -218,8 +218,8 @@ private:
|
|||||||
void CheckSIMDNest(const parser::OpenMPConstruct &x);
|
void CheckSIMDNest(const parser::OpenMPConstruct &x);
|
||||||
void CheckTargetNest(const parser::OpenMPConstruct &x);
|
void CheckTargetNest(const parser::OpenMPConstruct &x);
|
||||||
void CheckTargetUpdate();
|
void CheckTargetUpdate();
|
||||||
void CheckDependenceType(const parser::OmpDependenceType::Type &x);
|
void CheckDependenceType(const parser::OmpDependenceType::Value &x);
|
||||||
void CheckTaskDependenceType(const parser::OmpTaskDependenceType::Type &x);
|
void CheckTaskDependenceType(const parser::OmpTaskDependenceType::Value &x);
|
||||||
void CheckCancellationNest(
|
void CheckCancellationNest(
|
||||||
const parser::CharBlock &source, const parser::OmpCancelType::Type &type);
|
const parser::CharBlock &source, const parser::OmpCancelType::Type &type);
|
||||||
std::int64_t GetOrdCollapseLevel(const parser::OpenMPLoopConstruct &x);
|
std::int64_t GetOrdCollapseLevel(const parser::OpenMPLoopConstruct &x);
|
||||||
|
@ -518,8 +518,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Pre(const parser::OmpClause::Reduction &x) {
|
bool Pre(const parser::OmpClause::Reduction &x) {
|
||||||
const parser::OmpReductionOperator &opr{
|
const parser::OmpReductionIdentifier &opr{
|
||||||
std::get<parser::OmpReductionOperator>(x.v.t)};
|
std::get<parser::OmpReductionIdentifier>(x.v.t)};
|
||||||
auto createDummyProcSymbol = [&](const parser::Name *name) {
|
auto createDummyProcSymbol = [&](const parser::Name *name) {
|
||||||
// If name resolution failed, create a dummy symbol
|
// If name resolution failed, create a dummy symbol
|
||||||
const auto namePair{
|
const auto namePair{
|
||||||
|
@ -63,7 +63,7 @@ end
|
|||||||
!PARSE-TREE: OmpBeginBlockDirective
|
!PARSE-TREE: OmpBeginBlockDirective
|
||||||
!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = task
|
!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = task
|
||||||
!PARSE-TREE: | OmpClauseList -> OmpClause -> Affinity -> OmpAffinityClause
|
!PARSE-TREE: | OmpClauseList -> OmpClause -> Affinity -> OmpAffinityClause
|
||||||
!PARSE-TREE: | | OmpIteratorModifier -> OmpIteratorSpecifier
|
!PARSE-TREE: | | OmpIterator -> OmpIteratorSpecifier
|
||||||
!PARSE-TREE: | | | TypeDeclarationStmt
|
!PARSE-TREE: | | | TypeDeclarationStmt
|
||||||
!PARSE-TREE: | | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec ->
|
!PARSE-TREE: | | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec ->
|
||||||
!PARSE-TREE: | | | | EntityDecl
|
!PARSE-TREE: | | | | EntityDecl
|
||||||
|
@ -15,7 +15,7 @@ end
|
|||||||
!PARSE-TREE: | Verbatim
|
!PARSE-TREE: | Verbatim
|
||||||
!PARSE-TREE: | OmpObject -> Designator -> DataRef -> Name = 'x'
|
!PARSE-TREE: | OmpObject -> Designator -> DataRef -> Name = 'x'
|
||||||
!PARSE-TREE: | OmpClause -> Depend -> OmpDependClause -> TaskDep
|
!PARSE-TREE: | OmpClause -> Depend -> OmpDependClause -> TaskDep
|
||||||
!PARSE-TREE: | | OmpTaskDependenceType -> Type = In
|
!PARSE-TREE: | | OmpTaskDependenceType -> Value = In
|
||||||
!PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'y'
|
!PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'y'
|
||||||
|
|
||||||
subroutine f01
|
subroutine f01
|
||||||
@ -31,7 +31,7 @@ end
|
|||||||
!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPDepobjConstruct
|
!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPDepobjConstruct
|
||||||
!PARSE-TREE: | Verbatim
|
!PARSE-TREE: | Verbatim
|
||||||
!PARSE-TREE: | OmpObject -> Designator -> DataRef -> Name = 'x'
|
!PARSE-TREE: | OmpObject -> Designator -> DataRef -> Name = 'x'
|
||||||
!PARSE-TREE: | OmpClause -> Update -> OmpUpdateClause -> OmpTaskDependenceType -> Type = Out
|
!PARSE-TREE: | OmpClause -> Update -> OmpUpdateClause -> OmpTaskDependenceType -> Value = Out
|
||||||
|
|
||||||
subroutine f02
|
subroutine f02
|
||||||
integer :: x
|
integer :: x
|
||||||
|
@ -45,7 +45,7 @@ end
|
|||||||
!PARSE-TREE: OmpSimpleStandaloneDirective -> llvm::omp::Directive = target update
|
!PARSE-TREE: OmpSimpleStandaloneDirective -> llvm::omp::Directive = target update
|
||||||
!PARSE-TREE: OmpClauseList -> OmpClause -> From -> OmpFromClause
|
!PARSE-TREE: OmpClauseList -> OmpClause -> From -> OmpFromClause
|
||||||
!PARSE-TREE: | Expectation = Present
|
!PARSE-TREE: | Expectation = Present
|
||||||
!PARSE-TREE: | OmpIteratorModifier -> OmpIteratorSpecifier
|
!PARSE-TREE: | OmpIterator -> OmpIteratorSpecifier
|
||||||
!PARSE-TREE: | | TypeDeclarationStmt
|
!PARSE-TREE: | | TypeDeclarationStmt
|
||||||
!PARSE-TREE: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec ->
|
!PARSE-TREE: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec ->
|
||||||
!PARSE-TREE: | | | EntityDecl
|
!PARSE-TREE: | | | EntityDecl
|
||||||
@ -74,7 +74,7 @@ end
|
|||||||
!PARSE-TREE: OmpSimpleStandaloneDirective -> llvm::omp::Directive = target update
|
!PARSE-TREE: OmpSimpleStandaloneDirective -> llvm::omp::Directive = target update
|
||||||
!PARSE-TREE: OmpClauseList -> OmpClause -> From -> OmpFromClause
|
!PARSE-TREE: OmpClauseList -> OmpClause -> From -> OmpFromClause
|
||||||
!PARSE-TREE: | Expectation = Present
|
!PARSE-TREE: | Expectation = Present
|
||||||
!PARSE-TREE: | OmpIteratorModifier -> OmpIteratorSpecifier
|
!PARSE-TREE: | OmpIterator -> OmpIteratorSpecifier
|
||||||
!PARSE-TREE: | | TypeDeclarationStmt
|
!PARSE-TREE: | | TypeDeclarationStmt
|
||||||
!PARSE-TREE: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec ->
|
!PARSE-TREE: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec ->
|
||||||
!PARSE-TREE: | | | EntityDecl
|
!PARSE-TREE: | | | EntityDecl
|
||||||
|
@ -37,14 +37,14 @@ end subroutine omp_in_reduction_taskgroup
|
|||||||
!PARSE-TREE-NEXT: OmpBeginBlockDirective
|
!PARSE-TREE-NEXT: OmpBeginBlockDirective
|
||||||
!PARSE-TREE-NEXT: OmpBlockDirective -> llvm::omp::Directive = task
|
!PARSE-TREE-NEXT: OmpBlockDirective -> llvm::omp::Directive = task
|
||||||
!PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> InReduction -> OmpInReductionClause
|
!PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> InReduction -> OmpInReductionClause
|
||||||
!PARSE-TREE-NEXT: OmpReductionOperator -> DefinedOperator -> IntrinsicOperator = Add
|
!PARSE-TREE-NEXT: OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Add
|
||||||
!PARSE-TREE-NEXT: OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'z'
|
!PARSE-TREE-NEXT: OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'z'
|
||||||
|
|
||||||
!PARSE-TREE: OpenMPConstruct -> OpenMPLoopConstruct
|
!PARSE-TREE: OpenMPConstruct -> OpenMPLoopConstruct
|
||||||
!PARSE-TREE-NEXT: OmpBeginLoopDirective
|
!PARSE-TREE-NEXT: OmpBeginLoopDirective
|
||||||
!PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = taskloop
|
!PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = taskloop
|
||||||
!PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> InReduction -> OmpInReductionClause
|
!PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> InReduction -> OmpInReductionClause
|
||||||
!PARSE-TREE-NEXT: OmpReductionOperator -> DefinedOperator -> IntrinsicOperator = Add
|
!PARSE-TREE-NEXT: OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Add
|
||||||
!PARSE-TREE-NEXT: OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'z'
|
!PARSE-TREE-NEXT: OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'z'
|
||||||
|
|
||||||
subroutine omp_in_reduction_parallel()
|
subroutine omp_in_reduction_parallel()
|
||||||
@ -74,6 +74,6 @@ end subroutine omp_in_reduction_parallel
|
|||||||
!PARSE-TREE-NEXT: OmpBeginLoopDirective
|
!PARSE-TREE-NEXT: OmpBeginLoopDirective
|
||||||
!PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = taskloop simd
|
!PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = taskloop simd
|
||||||
!PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> InReduction -> OmpInReductionClause
|
!PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> InReduction -> OmpInReductionClause
|
||||||
!PARSE-TREE-NEXT: OmpReductionOperator -> DefinedOperator -> IntrinsicOperator = Add
|
!PARSE-TREE-NEXT: OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Add
|
||||||
!PASRE-TREE-NEXT: OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'z'
|
!PASRE-TREE-NEXT: OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'z'
|
||||||
|
|
||||||
|
@ -159,7 +159,7 @@ end
|
|||||||
!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target
|
!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target
|
||||||
!PARSE-TREE: | OmpClauseList -> OmpClause -> Map -> OmpMapClause
|
!PARSE-TREE: | OmpClauseList -> OmpClause -> Map -> OmpMapClause
|
||||||
!PARSE-TREE: | | TypeModifier = Present
|
!PARSE-TREE: | | TypeModifier = Present
|
||||||
!PARSE-TREE: | | OmpIteratorModifier -> OmpIteratorSpecifier
|
!PARSE-TREE: | | OmpIterator -> OmpIteratorSpecifier
|
||||||
!PARSE-TREE: | | | TypeDeclarationStmt
|
!PARSE-TREE: | | | TypeDeclarationStmt
|
||||||
!PARSE-TREE: | | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec ->
|
!PARSE-TREE: | | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec ->
|
||||||
!PARSE-TREE: | | | | EntityDecl
|
!PARSE-TREE: | | | | EntityDecl
|
||||||
@ -194,7 +194,7 @@ end
|
|||||||
!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target
|
!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target
|
||||||
!PARSE-TREE: | OmpClauseList -> OmpClause -> Map -> OmpMapClause
|
!PARSE-TREE: | OmpClauseList -> OmpClause -> Map -> OmpMapClause
|
||||||
!PARSE-TREE: | | TypeModifier = Present
|
!PARSE-TREE: | | TypeModifier = Present
|
||||||
!PARSE-TREE: | | OmpIteratorModifier -> OmpIteratorSpecifier
|
!PARSE-TREE: | | OmpIterator -> OmpIteratorSpecifier
|
||||||
!PARSE-TREE: | | | TypeDeclarationStmt
|
!PARSE-TREE: | | | TypeDeclarationStmt
|
||||||
!PARSE-TREE: | | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec ->
|
!PARSE-TREE: | | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec ->
|
||||||
!PARSE-TREE: | | | | EntityDecl
|
!PARSE-TREE: | | | | EntityDecl
|
||||||
@ -229,7 +229,7 @@ end
|
|||||||
!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target
|
!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target
|
||||||
!PARSE-TREE: | OmpClauseList -> OmpClause -> Map -> OmpMapClause
|
!PARSE-TREE: | OmpClauseList -> OmpClause -> Map -> OmpMapClause
|
||||||
!PARSE-TREE: | | TypeModifier = Present
|
!PARSE-TREE: | | TypeModifier = Present
|
||||||
!PARSE-TREE: | | OmpIteratorModifier -> OmpIteratorSpecifier
|
!PARSE-TREE: | | OmpIterator -> OmpIteratorSpecifier
|
||||||
!PARSE-TREE: | | | TypeDeclarationStmt
|
!PARSE-TREE: | | | TypeDeclarationStmt
|
||||||
!PARSE-TREE: | | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec ->
|
!PARSE-TREE: | | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec ->
|
||||||
!PARSE-TREE: | | | | EntityDecl
|
!PARSE-TREE: | | | | EntityDecl
|
||||||
@ -287,7 +287,7 @@ end
|
|||||||
!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target
|
!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target
|
||||||
!PARSE-TREE: | OmpClauseList -> OmpClause -> Map -> OmpMapClause
|
!PARSE-TREE: | OmpClauseList -> OmpClause -> Map -> OmpMapClause
|
||||||
!PARSE-TREE: | | TypeModifier = Present
|
!PARSE-TREE: | | TypeModifier = Present
|
||||||
!PARSE-TREE: | | OmpIteratorModifier -> OmpIteratorSpecifier
|
!PARSE-TREE: | | OmpIterator -> OmpIteratorSpecifier
|
||||||
!PARSE-TREE: | | | TypeDeclarationStmt
|
!PARSE-TREE: | | | TypeDeclarationStmt
|
||||||
!PARSE-TREE: | | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec ->
|
!PARSE-TREE: | | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec ->
|
||||||
!PARSE-TREE: | | | | EntityDecl
|
!PARSE-TREE: | | | | EntityDecl
|
||||||
|
@ -10,7 +10,7 @@ subroutine foo()
|
|||||||
! PARSE-TREE: | | | | OmpLoopDirective -> llvm::omp::Directive = do
|
! PARSE-TREE: | | | | OmpLoopDirective -> llvm::omp::Directive = do
|
||||||
! PARSE-TREE: | | | | OmpClauseList -> OmpClause -> Reduction -> OmpReductionClause
|
! PARSE-TREE: | | | | OmpClauseList -> OmpClause -> Reduction -> OmpReductionClause
|
||||||
! PARSE-TREE: | | | | | ReductionModifier = Task
|
! PARSE-TREE: | | | | | ReductionModifier = Task
|
||||||
! PARSE-TREE: | | | | | OmpReductionOperator -> DefinedOperator -> IntrinsicOperator = Multiply
|
! PARSE-TREE: | | | | | OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Multiply
|
||||||
! PARSE-TREE: | | | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'j
|
! PARSE-TREE: | | | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'j
|
||||||
!$omp do reduction (task, *: j)
|
!$omp do reduction (task, *: j)
|
||||||
do i = 1, 10
|
do i = 1, 10
|
||||||
|
@ -45,7 +45,7 @@ end
|
|||||||
!PARSE-TREE: OmpSimpleStandaloneDirective -> llvm::omp::Directive = target update
|
!PARSE-TREE: OmpSimpleStandaloneDirective -> llvm::omp::Directive = target update
|
||||||
!PARSE-TREE: OmpClauseList -> OmpClause -> To -> OmpToClause
|
!PARSE-TREE: OmpClauseList -> OmpClause -> To -> OmpToClause
|
||||||
!PARSE-TREE: | Expectation = Present
|
!PARSE-TREE: | Expectation = Present
|
||||||
!PARSE-TREE: | OmpIteratorModifier -> OmpIteratorSpecifier
|
!PARSE-TREE: | OmpIterator -> OmpIteratorSpecifier
|
||||||
!PARSE-TREE: | | TypeDeclarationStmt
|
!PARSE-TREE: | | TypeDeclarationStmt
|
||||||
!PARSE-TREE: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec ->
|
!PARSE-TREE: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec ->
|
||||||
!PARSE-TREE: | | | EntityDecl
|
!PARSE-TREE: | | | EntityDecl
|
||||||
@ -74,7 +74,7 @@ end
|
|||||||
!PARSE-TREE: OmpSimpleStandaloneDirective -> llvm::omp::Directive = target update
|
!PARSE-TREE: OmpSimpleStandaloneDirective -> llvm::omp::Directive = target update
|
||||||
!PARSE-TREE: OmpClauseList -> OmpClause -> To -> OmpToClause
|
!PARSE-TREE: OmpClauseList -> OmpClause -> To -> OmpToClause
|
||||||
!PARSE-TREE: | Expectation = Present
|
!PARSE-TREE: | Expectation = Present
|
||||||
!PARSE-TREE: | OmpIteratorModifier -> OmpIteratorSpecifier
|
!PARSE-TREE: | OmpIterator -> OmpIteratorSpecifier
|
||||||
!PARSE-TREE: | | TypeDeclarationStmt
|
!PARSE-TREE: | | TypeDeclarationStmt
|
||||||
!PARSE-TREE: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec ->
|
!PARSE-TREE: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec ->
|
||||||
!PARSE-TREE: | | | EntityDecl
|
!PARSE-TREE: | | | EntityDecl
|
||||||
|
Loading…
x
Reference in New Issue
Block a user