//===-- include/flang/Parser/parse-tree.h -----------------------*- C++ -*-===// // // 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 // //===----------------------------------------------------------------------===// #ifndef FORTRAN_PARSER_PARSE_TREE_H_ #define FORTRAN_PARSER_PARSE_TREE_H_ // Defines the classes used to represent successful reductions of productions // in the Fortran grammar. The names and content of these definitions // adhere closely to the syntax specifications in the language standard (q.v.) // that are transcribed here and referenced via their requirement numbers. // The representations of some productions that may also be of use in the // run-time I/O support library have been isolated into a distinct header file // (viz., format-specification.h). #include "char-block.h" #include "characters.h" #include "format-specification.h" #include "message.h" #include "provenance.h" #include "flang/Common/Fortran.h" #include "flang/Common/idioms.h" #include "flang/Common/indirection.h" #include "llvm/Frontend/OpenACC/ACC.h.inc" #include "llvm/Frontend/OpenMP/OMPConstants.h" #include #include #include #include #include #include #include #include #include // Parse tree node class types do not have default constructors. They // explicitly declare "T() {} = delete;" to make this clear. This restriction // prevents the introduction of what would be a viral requirement to include // std::monostate among most std::variant<> discriminated union members. // Parse tree node class types do not have copy constructors or copy assignment // operators. They are explicitly declared "= delete;" to make this clear, // although a C++ compiler wouldn't default them anyway due to the presence // of explicitly defaulted move constructors and move assignments. CLASS_TRAIT(EmptyTrait) CLASS_TRAIT(WrapperTrait) CLASS_TRAIT(UnionTrait) CLASS_TRAIT(TupleTrait) CLASS_TRAIT(ConstraintTrait) // Some parse tree nodes have fields in them to cache the results of a // successful semantic analysis later. Their types are forward declared // here. namespace Fortran::semantics { class Symbol; class DeclTypeSpec; class DerivedTypeSpec; } // namespace Fortran::semantics // Expressions in the parse tree have owning pointers that can be set to // type-checked generic expression representations by semantic analysis. namespace Fortran::evaluate { struct GenericExprWrapper; // forward definition, wraps Expr struct GenericAssignmentWrapper; // forward definition, represent assignment class ProcedureRef; // forward definition, represents a CALL or function ref } // namespace Fortran::evaluate // Most non-template classes in this file use these default definitions // for their move constructor and move assignment operator=, and disable // their copy constructor and copy assignment operator=. #define COPY_AND_ASSIGN_BOILERPLATE(classname) \ classname(classname &&) = default; \ classname &operator=(classname &&) = default; \ classname(const classname &) = delete; \ classname &operator=(const classname &) = delete // Almost all classes in this file have no default constructor. #define BOILERPLATE(classname) \ COPY_AND_ASSIGN_BOILERPLATE(classname); \ classname() = delete // Empty classes are often used below as alternatives in std::variant<> // discriminated unions. #define EMPTY_CLASS(classname) \ struct classname { \ classname() {} \ classname(const classname &) {} \ classname(classname &&) {} \ classname &operator=(const classname &) { return *this; }; \ classname &operator=(classname &&) { return *this; }; \ using EmptyTrait = std::true_type; \ } // Many classes below simply wrap a std::variant<> discriminated union, // which is conventionally named "u". #define UNION_CLASS_BOILERPLATE(classname) \ template > \ classname(A &&x) : u(std::move(x)) {} \ using UnionTrait = std::true_type; \ BOILERPLATE(classname) // Many other classes below simply wrap a std::tuple<> structure, which // is conventionally named "t". #define TUPLE_CLASS_BOILERPLATE(classname) \ template > \ classname(Ts &&...args) : t(std::move(args)...) {} \ using TupleTrait = std::true_type; \ BOILERPLATE(classname) // Many other classes below simply wrap a single data member, which is // conventionally named "v". #define WRAPPER_CLASS_BOILERPLATE(classname, type) \ BOILERPLATE(classname); \ classname(type &&x) : v(std::move(x)) {} \ using WrapperTrait = std::true_type; \ type v #define WRAPPER_CLASS(classname, type) \ struct classname { \ WRAPPER_CLASS_BOILERPLATE(classname, type); \ } namespace Fortran::parser { // These are the unavoidable recursively-defined productions of Fortran. // Some references to the representations of their parses require // indirection. The Indirect<> pointer wrapper class is used to // enforce ownership semantics and non-nullability. struct SpecificationPart; // R504 struct ExecutableConstruct; // R514 struct ActionStmt; // R515 struct AcImpliedDo; // R774 struct DataImpliedDo; // R840 struct Designator; // R901 struct Variable; // R902 struct Expr; // R1001 struct WhereConstruct; // R1042 struct ForallConstruct; // R1050 struct InputImpliedDo; // R1218 struct OutputImpliedDo; // R1218 struct FunctionReference; // R1520 struct FunctionSubprogram; // R1529 struct SubroutineSubprogram; // R1534 // These additional forward references are declared so that the order of // class definitions in this header file can remain reasonably consistent // with order of the the requirement productions in the grammar. struct DerivedTypeDef; // R726 struct EnumDef; // R759 struct TypeDeclarationStmt; // R801 struct AccessStmt; // R827 struct AllocatableStmt; // R829 struct AsynchronousStmt; // R831 struct BindStmt; // R832 struct CodimensionStmt; // R834 struct ContiguousStmt; // R836 struct DataStmt; // R837 struct DataStmtValue; // R843 struct DimensionStmt; // R848 struct IntentStmt; // R849 struct OptionalStmt; // R850 struct ParameterStmt; // R851 struct OldParameterStmt; struct PointerStmt; // R853 struct ProtectedStmt; // R855 struct SaveStmt; // R856 struct TargetStmt; // R859 struct ValueStmt; // R861 struct VolatileStmt; // R862 struct ImplicitStmt; // R863 struct ImportStmt; // R867 struct NamelistStmt; // R868 struct EquivalenceStmt; // R870 struct CommonStmt; // R873 struct Substring; // R908 struct CharLiteralConstantSubstring; struct SubstringInquiry; struct DataRef; // R911 struct StructureComponent; // R913 struct CoindexedNamedObject; // R914 struct ArrayElement; // R917 struct AllocateStmt; // R927 struct NullifyStmt; // R939 struct DeallocateStmt; // R941 struct AssignmentStmt; // R1032 struct PointerAssignmentStmt; // R1033 struct WhereStmt; // R1041, R1045, R1046 struct ForallStmt; // R1055 struct AssociateConstruct; // R1102 struct BlockConstruct; // R1107 struct ChangeTeamConstruct; // R1111 struct CriticalConstruct; // R1116 struct DoConstruct; // R1119 struct LabelDoStmt; // R1121 struct ConcurrentHeader; // R1125 struct EndDoStmt; // R1132 struct CycleStmt; // R1133 struct IfConstruct; // R1134 struct IfStmt; // R1139 struct CaseConstruct; // R1140 struct SelectRankConstruct; // R1148 struct SelectTypeConstruct; // R1152 struct ExitStmt; // R1156 struct GotoStmt; // R1157 struct ComputedGotoStmt; // R1158 struct StopStmt; // R1160, R1161 struct NotifyWaitStmt; // F2023: R1166 struct SyncAllStmt; // R1164 struct SyncImagesStmt; // R1166 struct SyncMemoryStmt; // R1168 struct SyncTeamStmt; // R1169 struct EventPostStmt; // R1170, R1171 struct EventWaitSpec; // F2023: R1177 struct EventWaitStmt; // R1172, R1173, R1174 struct FormTeamStmt; // R1175, R1176, R1177 struct LockStmt; // R1178 struct UnlockStmt; // R1180 struct OpenStmt; // R1204 struct CloseStmt; // R1208 struct ReadStmt; // R1210 struct WriteStmt; // R1211 struct PrintStmt; // R1212 struct WaitStmt; // R1222 struct BackspaceStmt; // R1224 struct EndfileStmt; // R1225 struct RewindStmt; // R1226 struct FlushStmt; // R1228 struct InquireStmt; // R1230 struct FormatStmt; // R1301 struct MainProgram; // R1401 struct Module; // R1404 struct UseStmt; // R1409 struct Submodule; // R1416 struct BlockData; // R1420 struct InterfaceBlock; // R1501 struct GenericSpec; // R1508 struct GenericStmt; // R1510 struct ExternalStmt; // R1511 struct ProcedureDeclarationStmt; // R1512 struct IntrinsicStmt; // R1519 struct Call; // R1520 & R1521 struct CallStmt; // R1521 struct ProcedureDesignator; // R1522 struct ActualArg; // R1524 struct SeparateModuleSubprogram; // R1538 struct EntryStmt; // R1541 struct ReturnStmt; // R1542 struct StmtFunctionStmt; // R1544 // Directives, extensions, and deprecated statements struct CompilerDirective; struct BasedPointerStmt; struct CUDAAttributesStmt; struct StructureDef; struct ArithmeticIfStmt; struct AssignStmt; struct AssignedGotoStmt; struct PauseStmt; struct OpenACCConstruct; struct AccEndCombinedDirective; struct OpenACCDeclarativeConstruct; struct OpenACCRoutineConstruct; struct OpenMPConstruct; struct OpenMPDeclarativeConstruct; struct OmpEndLoopDirective; struct CUFKernelDoConstruct; // Cooked character stream locations using Location = const char *; // A parse tree node with provenance only struct Verbatim { // Allow a no-arg constructor for Verbatim so parsers can return `RESULT{}`. constexpr Verbatim() {} COPY_AND_ASSIGN_BOILERPLATE(Verbatim); using EmptyTrait = std::true_type; CharBlock source; }; // Implicit definitions of the Standard // R403 scalar-xyz -> xyz // These template class wrappers correspond to the Standard's modifiers // scalar-xyz, constant-xzy, int-xzy, default-char-xyz, & logical-xyz. template struct Scalar { using ConstraintTrait = std::true_type; Scalar(Scalar &&that) = default; Scalar(A &&that) : thing(std::move(that)) {} Scalar &operator=(Scalar &&) = default; A thing; }; template struct Constant { using ConstraintTrait = std::true_type; Constant(Constant &&that) = default; Constant(A &&that) : thing(std::move(that)) {} Constant &operator=(Constant &&) = default; A thing; }; template struct Integer { using ConstraintTrait = std::true_type; Integer(Integer &&that) = default; Integer(A &&that) : thing(std::move(that)) {} Integer &operator=(Integer &&) = default; A thing; }; template struct Logical { using ConstraintTrait = std::true_type; Logical(Logical &&that) = default; Logical(A &&that) : thing(std::move(that)) {} Logical &operator=(Logical &&) = default; A thing; }; template struct DefaultChar { using ConstraintTrait = std::true_type; DefaultChar(DefaultChar &&that) = default; DefaultChar(A &&that) : thing(std::move(that)) {} DefaultChar &operator=(DefaultChar &&) = default; A thing; }; using LogicalExpr = Logical>; // R1024 using DefaultCharExpr = DefaultChar>; // R1025 using IntExpr = Integer>; // R1026 using ConstantExpr = Constant>; // R1029 using IntConstantExpr = Integer; // R1031 using ScalarLogicalExpr = Scalar; using ScalarIntExpr = Scalar; using ScalarIntConstantExpr = Scalar; using ScalarDefaultCharExpr = Scalar; // R1030 default-char-constant-expr is used in the Standard only as part of // scalar-default-char-constant-expr. using ScalarDefaultCharConstantExpr = Scalar>; // R611 label -> digit [digit]... using Label = common::Label; // validated later, must be in [1..99999] // A wrapper for xzy-stmt productions that are statements, so that // source provenances and labels have a uniform representation. template struct UnlabeledStatement { explicit UnlabeledStatement(A &&s) : statement(std::move(s)) {} CharBlock source; A statement; }; template struct Statement : public UnlabeledStatement { Statement(std::optional &&lab, A &&s) : UnlabeledStatement{std::move(s)}, label(std::move(lab)) {} std::optional &&x) : nature(std::move(nat)), moduleName(std::move(n)), u(std::move(x)) {} std::optional nature; Name moduleName; std::variant, std::list> u; }; // R1514 proc-attr-spec -> // access-spec | proc-language-binding-spec | INTENT ( intent-spec ) | // OPTIONAL | POINTER | PROTECTED | SAVE struct ProcAttrSpec { UNION_CLASS_BOILERPLATE(ProcAttrSpec); std::variant u; }; // R1512 procedure-declaration-stmt -> // PROCEDURE ( [proc-interface] ) [[, proc-attr-spec]... ::] // proc-decl-list struct ProcedureDeclarationStmt { TUPLE_CLASS_BOILERPLATE(ProcedureDeclarationStmt); std::tuple, std::list, std::list> t; }; // R1527 prefix-spec -> // declaration-type-spec | ELEMENTAL | IMPURE | MODULE | // NON_RECURSIVE | PURE | RECURSIVE | // (CUDA) ATTRIBUTES ( (DEVICE | GLOBAL | GRID_GLOBAL | HOST)... ) // LAUNCH_BOUNDS(expr-list) | CLUSTER_DIMS(expr-list) struct PrefixSpec { UNION_CLASS_BOILERPLATE(PrefixSpec); EMPTY_CLASS(Elemental); EMPTY_CLASS(Impure); EMPTY_CLASS(Module); EMPTY_CLASS(Non_Recursive); EMPTY_CLASS(Pure); EMPTY_CLASS(Recursive); WRAPPER_CLASS(Attributes, std::list); WRAPPER_CLASS(Launch_Bounds, std::list); WRAPPER_CLASS(Cluster_Dims, std::list); std::variant u; }; // R1532 suffix -> // proc-language-binding-spec [RESULT ( result-name )] | // RESULT ( result-name ) [proc-language-binding-spec] struct Suffix { BOILERPLATE(Suffix); Suffix(LanguageBindingSpec &&lbs, std::optional &&rn) : binding(std::move(lbs)), resultName(std::move(rn)) {} Suffix(Name &&rn, std::optional &&lbs) : binding(std::move(lbs)), resultName(std::move(rn)) {} std::optional binding; std::optional resultName; }; // R1530 function-stmt -> // [prefix] FUNCTION function-name ( [dummy-arg-name-list] ) [suffix] // R1526 prefix -> prefix-spec [prefix-spec]... // R1531 dummy-arg-name -> name struct FunctionStmt { TUPLE_CLASS_BOILERPLATE(FunctionStmt); std::tuple, Name, std::list, std::optional> t; }; // R1533 end-function-stmt -> END [FUNCTION [function-name]] WRAPPER_CLASS(EndFunctionStmt, std::optional); // R1536 dummy-arg -> dummy-arg-name | * struct DummyArg { UNION_CLASS_BOILERPLATE(DummyArg); std::variant u; }; // R1535 subroutine-stmt -> // [prefix] SUBROUTINE subroutine-name [( [dummy-arg-list] ) // [proc-language-binding-spec]] struct SubroutineStmt { TUPLE_CLASS_BOILERPLATE(SubroutineStmt); std::tuple, Name, std::list, std::optional> t; }; // R1537 end-subroutine-stmt -> END [SUBROUTINE [subroutine-name]] WRAPPER_CLASS(EndSubroutineStmt, std::optional); // R1505 interface-body -> // function-stmt [specification-part] end-function-stmt | // subroutine-stmt [specification-part] end-subroutine-stmt struct InterfaceBody { UNION_CLASS_BOILERPLATE(InterfaceBody); struct Function { TUPLE_CLASS_BOILERPLATE(Function); std::tuple, common::Indirection, Statement> t; }; struct Subroutine { TUPLE_CLASS_BOILERPLATE(Subroutine); std::tuple, common::Indirection, Statement> t; }; std::variant u; }; // R1506 procedure-stmt -> [MODULE] PROCEDURE [::] specific-procedure-list struct ProcedureStmt { ENUM_CLASS(Kind, ModuleProcedure, Procedure) TUPLE_CLASS_BOILERPLATE(ProcedureStmt); std::tuple> t; }; // R1502 interface-specification -> interface-body | procedure-stmt struct InterfaceSpecification { UNION_CLASS_BOILERPLATE(InterfaceSpecification); std::variant> u; }; // R1504 end-interface-stmt -> END INTERFACE [generic-spec] WRAPPER_CLASS(EndInterfaceStmt, std::optional); // R1501 interface-block -> // interface-stmt [interface-specification]... end-interface-stmt struct InterfaceBlock { TUPLE_CLASS_BOILERPLATE(InterfaceBlock); std::tuple, std::list, Statement> t; }; // R1511 external-stmt -> EXTERNAL [::] external-name-list WRAPPER_CLASS(ExternalStmt, std::list); // R1519 intrinsic-stmt -> INTRINSIC [::] intrinsic-procedure-name-list WRAPPER_CLASS(IntrinsicStmt, std::list); // R1522 procedure-designator -> // procedure-name | proc-component-ref | data-ref % binding-name struct ProcedureDesignator { UNION_CLASS_BOILERPLATE(ProcedureDesignator); std::variant u; }; // R1525 alt-return-spec -> * label WRAPPER_CLASS(AltReturnSpec, Label); // R1524 actual-arg -> // expr | variable | procedure-name | proc-component-ref | // alt-return-spec struct ActualArg { WRAPPER_CLASS(PercentRef, Variable); // %REF(v) extension WRAPPER_CLASS(PercentVal, Expr); // %VAL(x) extension UNION_CLASS_BOILERPLATE(ActualArg); ActualArg(Expr &&x) : u{common::Indirection(std::move(x))} {} std::variant, AltReturnSpec, PercentRef, PercentVal> u; }; // R1523 actual-arg-spec -> [keyword =] actual-arg struct ActualArgSpec { TUPLE_CLASS_BOILERPLATE(ActualArgSpec); std::tuple, ActualArg> t; }; // R1520 function-reference -> procedure-designator // ( [actual-arg-spec-list] ) struct Call { TUPLE_CLASS_BOILERPLATE(Call); std::tuple> t; }; struct FunctionReference { WRAPPER_CLASS_BOILERPLATE(FunctionReference, Call); CharBlock source; Designator ConvertToArrayElementRef(); StructureConstructor ConvertToStructureConstructor( const semantics::DerivedTypeSpec &); }; // R1521 call-stmt -> CALL procedure-designator [ chevrons ] // [( [actual-arg-spec-list] )] // (CUDA) chevrons -> <<< scalar-expr, scalar-expr [, // scalar-int-expr [, scalar-int-expr ] ] >>> struct CallStmt { BOILERPLATE(CallStmt); struct Chevrons { TUPLE_CLASS_BOILERPLATE(Chevrons); std::tuple, std::optional> t; }; explicit CallStmt(ProcedureDesignator &&pd, std::optional &&ch, std::list &&args) : call{std::move(pd), std::move(args)}, chevrons{std::move(ch)} {} Call call; std::optional chevrons; CharBlock source; mutable common::ForwardOwningPointer typedCall; // filled by semantics }; // R1529 function-subprogram -> // function-stmt [specification-part] [execution-part] // [internal-subprogram-part] end-function-stmt struct FunctionSubprogram { TUPLE_CLASS_BOILERPLATE(FunctionSubprogram); std::tuple, SpecificationPart, ExecutionPart, std::optional, Statement> t; }; // R1534 subroutine-subprogram -> // subroutine-stmt [specification-part] [execution-part] // [internal-subprogram-part] end-subroutine-stmt struct SubroutineSubprogram { TUPLE_CLASS_BOILERPLATE(SubroutineSubprogram); std::tuple, SpecificationPart, ExecutionPart, std::optional, Statement> t; }; // R1539 mp-subprogram-stmt -> MODULE PROCEDURE procedure-name WRAPPER_CLASS(MpSubprogramStmt, Name); // R1540 end-mp-subprogram-stmt -> END [PROCEDURE [procedure-name]] WRAPPER_CLASS(EndMpSubprogramStmt, std::optional); // R1538 separate-module-subprogram -> // mp-subprogram-stmt [specification-part] [execution-part] // [internal-subprogram-part] end-mp-subprogram-stmt struct SeparateModuleSubprogram { TUPLE_CLASS_BOILERPLATE(SeparateModuleSubprogram); std::tuple, SpecificationPart, ExecutionPart, std::optional, Statement> t; }; // R1541 entry-stmt -> ENTRY entry-name [( [dummy-arg-list] ) [suffix]] struct EntryStmt { TUPLE_CLASS_BOILERPLATE(EntryStmt); std::tuple, std::optional> t; }; // R1542 return-stmt -> RETURN [scalar-int-expr] WRAPPER_CLASS(ReturnStmt, std::optional); // R1544 stmt-function-stmt -> // function-name ( [dummy-arg-name-list] ) = scalar-expr struct StmtFunctionStmt { TUPLE_CLASS_BOILERPLATE(StmtFunctionStmt); std::tuple, Scalar> t; Statement ConvertToAssignment(); }; // Compiler directives // !DIR$ IGNORE_TKR [ [(tkrdmac...)] name ]... // !DIR$ LOOP COUNT (n1[, n2]...) // !DIR$ name... struct CompilerDirective { UNION_CLASS_BOILERPLATE(CompilerDirective); struct IgnoreTKR { TUPLE_CLASS_BOILERPLATE(IgnoreTKR); std::tuple>, Name> t; }; struct LoopCount { WRAPPER_CLASS_BOILERPLATE(LoopCount, std::list); }; struct NameValue { TUPLE_CLASS_BOILERPLATE(NameValue); std::tuple> t; }; CharBlock source; std::variant, LoopCount, std::list> u; }; // (CUDA) ATTRIBUTE(attribute) [::] name-list struct CUDAAttributesStmt { TUPLE_CLASS_BOILERPLATE(CUDAAttributesStmt); std::tuple> t; }; // Legacy extensions struct BasedPointer { TUPLE_CLASS_BOILERPLATE(BasedPointer); std::tuple> t; }; WRAPPER_CLASS(BasedPointerStmt, std::list); struct Union; struct StructureDef; struct StructureField { UNION_CLASS_BOILERPLATE(StructureField); std::variant, common::Indirection, common::Indirection> u; }; struct Map { EMPTY_CLASS(MapStmt); EMPTY_CLASS(EndMapStmt); TUPLE_CLASS_BOILERPLATE(Map); std::tuple, std::list, Statement> t; }; struct Union { EMPTY_CLASS(UnionStmt); EMPTY_CLASS(EndUnionStmt); TUPLE_CLASS_BOILERPLATE(Union); std::tuple, std::list, Statement> t; }; struct StructureStmt { TUPLE_CLASS_BOILERPLATE(StructureStmt); std::tuple, std::list> t; }; struct StructureDef { EMPTY_CLASS(EndStructureStmt); TUPLE_CLASS_BOILERPLATE(StructureDef); std::tuple, std::list, Statement> t; }; // Old style PARAMETER statement without parentheses. // Types are determined entirely from the right-hand sides, not the names. WRAPPER_CLASS(OldParameterStmt, std::list); // Deprecations struct ArithmeticIfStmt { TUPLE_CLASS_BOILERPLATE(ArithmeticIfStmt); std::tuple t; }; struct AssignStmt { TUPLE_CLASS_BOILERPLATE(AssignStmt); std::tuple t; }; struct AssignedGotoStmt { TUPLE_CLASS_BOILERPLATE(AssignedGotoStmt); std::tuple> t; }; WRAPPER_CLASS(PauseStmt, std::optional); // Parse tree nodes for OpenMP 4.5 directives and clauses // 2.5 proc-bind-clause -> PROC_BIND (MASTER | CLOSE | SPREAD) struct OmpProcBindClause { ENUM_CLASS(Type, Close, Master, Spread, Primary) WRAPPER_CLASS_BOILERPLATE(OmpProcBindClause, Type); }; // 2.15.3.1 default-clause -> DEFAULT (PRIVATE | FIRSTPRIVATE | SHARED | NONE) struct OmpDefaultClause { ENUM_CLASS(Type, Private, Firstprivate, Shared, None) WRAPPER_CLASS_BOILERPLATE(OmpDefaultClause, Type); }; // 2.1 Directives or clauses may accept a list or extended-list. // A list item is a variable, array section or common block name (enclosed // in slashes). An extended list item is a list item or a procedure Name. // variable-name | / common-block / | array-sections struct OmpObject { UNION_CLASS_BOILERPLATE(OmpObject); std::variant u; }; WRAPPER_CLASS(OmpObjectList, std::list); // 2.15.5.1 map-type -> TO | FROM | TOFROM | ALLOC | RELEASE | DELETE struct OmpMapType { TUPLE_CLASS_BOILERPLATE(OmpMapType); EMPTY_CLASS(Always); ENUM_CLASS(Type, To, From, Tofrom, Alloc, Release, Delete) std::tuple, Type> t; }; // 2.15.5.1 map -> MAP ([ [ALWAYS[,]] map-type : ] variable-name-list) struct OmpMapClause { TUPLE_CLASS_BOILERPLATE(OmpMapClause); std::tuple, OmpObjectList> t; }; // 2.15.5.2 defaultmap -> DEFAULTMAP (implicit-behavior[:variable-category]) struct OmpDefaultmapClause { TUPLE_CLASS_BOILERPLATE(OmpDefaultmapClause); ENUM_CLASS( ImplicitBehavior, Alloc, To, From, Tofrom, Firstprivate, None, Default) ENUM_CLASS(VariableCategory, Scalar, Aggregate, Allocatable, Pointer) std::tuple> t; }; // 2.7.1 sched-modifier -> MONOTONIC | NONMONOTONIC | SIMD struct OmpScheduleModifierType { ENUM_CLASS(ModType, Monotonic, Nonmonotonic, Simd) WRAPPER_CLASS_BOILERPLATE(OmpScheduleModifierType, ModType); }; struct OmpScheduleModifier { TUPLE_CLASS_BOILERPLATE(OmpScheduleModifier); WRAPPER_CLASS(Modifier1, OmpScheduleModifierType); WRAPPER_CLASS(Modifier2, OmpScheduleModifierType); std::tuple> t; }; // 2.7.1 schedule-clause -> SCHEDULE ([sched-modifier1] [, sched-modifier2]:] // kind[, chunk_size]) struct OmpScheduleClause { TUPLE_CLASS_BOILERPLATE(OmpScheduleClause); ENUM_CLASS(ScheduleType, Static, Dynamic, Guided, Auto, Runtime) std::tuple, ScheduleType, std::optional> t; }; // device([ device-modifier :] scalar-integer-expression) struct OmpDeviceClause { TUPLE_CLASS_BOILERPLATE(OmpDeviceClause); ENUM_CLASS(DeviceModifier, Ancestor, Device_Num) std::tuple, ScalarIntExpr> t; }; // device_type(any | host | nohost) struct OmpDeviceTypeClause { ENUM_CLASS(Type, Any, Host, Nohost) WRAPPER_CLASS_BOILERPLATE(OmpDeviceTypeClause, Type); }; // 2.12 if-clause -> IF ([ directive-name-modifier :] scalar-logical-expr) struct OmpIfClause { TUPLE_CLASS_BOILERPLATE(OmpIfClause); ENUM_CLASS(DirectiveNameModifier, Parallel, Simd, Target, TargetData, TargetEnterData, TargetExitData, TargetUpdate, Task, Taskloop, Teams) std::tuple, ScalarLogicalExpr> t; }; // 2.8.1 aligned-clause -> ALIGNED (variable-name-list[ : scalar-constant]) struct OmpAlignedClause { TUPLE_CLASS_BOILERPLATE(OmpAlignedClause); CharBlock source; std::tuple> t; }; // 2.9.5 order-clause -> ORDER ([order-modifier :]concurrent) struct OmpOrderModifier { UNION_CLASS_BOILERPLATE(OmpOrderModifier); ENUM_CLASS(Kind, Reproducible, Unconstrained) std::variant u; }; struct OmpOrderClause { TUPLE_CLASS_BOILERPLATE(OmpOrderClause); ENUM_CLASS(Type, Concurrent) std::tuple, Type> 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]) // linear-list -> list | linear-modifier(list) struct OmpLinearClause { UNION_CLASS_BOILERPLATE(OmpLinearClause); struct WithModifier { BOILERPLATE(WithModifier); WithModifier(OmpLinearModifier &&m, std::list &&n, std::optional &&s) : modifier(std::move(m)), names(std::move(n)), step(std::move(s)) {} OmpLinearModifier modifier; std::list names; std::optional step; }; struct WithoutModifier { BOILERPLATE(WithoutModifier); WithoutModifier( std::list &&n, std::optional &&s) : names(std::move(n)), step(std::move(s)) {} std::list names; std::optional step; }; std::variant u; }; // 2.15.3.6 reduction-identifier -> + | - | * | .AND. | .OR. | .EQV. | .NEQV. | // MAX | MIN | IAND | IOR | IEOR struct OmpReductionOperator { UNION_CLASS_BOILERPLATE(OmpReductionOperator); std::variant u; }; // 2.15.3.6 reduction-clause -> REDUCTION (reduction-identifier: // variable-name-list) struct OmpReductionClause { TUPLE_CLASS_BOILERPLATE(OmpReductionClause); std::tuple t; }; // OMP 5.0 2.19.5.6 in_reduction-clause -> IN_REDUCTION (reduction-identifier: // variable-name-list) struct OmpInReductionClause { TUPLE_CLASS_BOILERPLATE(OmpInReductionClause); std::tuple t; }; // OMP 5.0 2.11.4 allocate-clause -> ALLOCATE ([allocator:] variable-name-list) // OMP 5.2 2.13.4 allocate-clause -> ALLOCATE ([allocate-modifier [, // allocate-modifier] :] // variable-name-list) // allocate-modifier -> allocator | align struct OmpAllocateClause { struct AllocateModifier { WRAPPER_CLASS(Allocator, ScalarIntExpr); WRAPPER_CLASS(Align, ScalarIntExpr); struct ComplexModifier { TUPLE_CLASS_BOILERPLATE(ComplexModifier); std::tuple t; }; UNION_CLASS_BOILERPLATE(AllocateModifier); std::variant u; }; TUPLE_CLASS_BOILERPLATE(OmpAllocateClause); std::tuple, OmpObjectList> t; }; // 2.13.9 depend-vec-length -> +/- non-negative-constant struct OmpDependSinkVecLength { TUPLE_CLASS_BOILERPLATE(OmpDependSinkVecLength); std::tuple t; }; // 2.13.9 depend-vec -> iterator [+/- depend-vec-length],...,iterator[...] struct OmpDependSinkVec { TUPLE_CLASS_BOILERPLATE(OmpDependSinkVec); std::tuple> t; }; // 2.13.9 depend-type -> IN | OUT | INOUT | SOURCE | SINK struct OmpDependenceType { ENUM_CLASS(Type, In, Out, Inout, Source, Sink) WRAPPER_CLASS_BOILERPLATE(OmpDependenceType, Type); }; // 2.13.9 depend-clause -> DEPEND (((IN | OUT | INOUT) : variable-name-list) | // SOURCE | SINK : depend-vec) struct OmpDependClause { UNION_CLASS_BOILERPLATE(OmpDependClause); EMPTY_CLASS(Source); WRAPPER_CLASS(Sink, std::list); struct InOut { TUPLE_CLASS_BOILERPLATE(InOut); std::tuple> t; }; std::variant u; }; // OMP 5.0 2.4 atomic-default-mem-order-clause -> // ATOMIC_DEFAULT_MEM_ORDER (SEQ_CST | ACQ_REL | // RELAXED) struct OmpAtomicDefaultMemOrderClause { WRAPPER_CLASS_BOILERPLATE( OmpAtomicDefaultMemOrderClause, common::OmpAtomicDefaultMemOrderType); }; // OpenMP Clauses struct OmpClause { UNION_CLASS_BOILERPLATE(OmpClause); #define GEN_FLANG_CLAUSE_PARSER_CLASSES #include "llvm/Frontend/OpenMP/OMP.inc" CharBlock source; std::variant< #define GEN_FLANG_CLAUSE_PARSER_CLASSES_LIST #include "llvm/Frontend/OpenMP/OMP.inc" > u; }; struct OmpClauseList { WRAPPER_CLASS_BOILERPLATE(OmpClauseList, std::list); CharBlock source; }; // 2.7.2 SECTIONS // 2.11.2 PARALLEL SECTIONS struct OmpSectionsDirective { WRAPPER_CLASS_BOILERPLATE(OmpSectionsDirective, llvm::omp::Directive); CharBlock source; }; struct OmpBeginSectionsDirective { TUPLE_CLASS_BOILERPLATE(OmpBeginSectionsDirective); std::tuple t; CharBlock source; }; struct OmpEndSectionsDirective { TUPLE_CLASS_BOILERPLATE(OmpEndSectionsDirective); std::tuple t; CharBlock source; }; // [!$omp section] // structured-block // [!$omp section // structured-block] // ... struct OpenMPSectionConstruct { WRAPPER_CLASS_BOILERPLATE(OpenMPSectionConstruct, Block); CharBlock source; }; // `OmpSectionBlocks` is a list of section constructs. The parser guarentees // that the `OpenMPConstruct` here always encapsulates an // `OpenMPSectionConstruct` and not any other OpenMP construct. WRAPPER_CLASS(OmpSectionBlocks, std::list); struct OpenMPSectionsConstruct { TUPLE_CLASS_BOILERPLATE(OpenMPSectionsConstruct); std::tuple t; }; // OpenMP directive beginning or ending a block struct OmpBlockDirective { WRAPPER_CLASS_BOILERPLATE(OmpBlockDirective, llvm::omp::Directive); CharBlock source; }; // 2.10.6 declare-target -> DECLARE TARGET (extended-list) | // DECLARE TARGET [declare-target-clause[ [,] // declare-target-clause]...] struct OmpDeclareTargetWithList { WRAPPER_CLASS_BOILERPLATE(OmpDeclareTargetWithList, OmpObjectList); CharBlock source; }; struct OmpDeclareTargetWithClause { WRAPPER_CLASS_BOILERPLATE(OmpDeclareTargetWithClause, OmpClauseList); CharBlock source; }; struct OmpDeclareTargetSpecifier { UNION_CLASS_BOILERPLATE(OmpDeclareTargetSpecifier); std::variant u; }; struct OpenMPDeclareTargetConstruct { TUPLE_CLASS_BOILERPLATE(OpenMPDeclareTargetConstruct); CharBlock source; std::tuple t; }; // 2.16 declare-reduction -> DECLARE REDUCTION (reduction-identifier : type-list // : combiner) [initializer-clause] struct OmpReductionCombiner { UNION_CLASS_BOILERPLATE(OmpReductionCombiner); WRAPPER_CLASS(FunctionCombiner, Call); std::variant u; }; WRAPPER_CLASS(OmpReductionInitializerClause, Expr); struct OpenMPDeclareReductionConstruct { TUPLE_CLASS_BOILERPLATE(OpenMPDeclareReductionConstruct); CharBlock source; std::tuple, OmpReductionCombiner, std::optional> t; }; // 2.8.2 declare-simd -> DECLARE SIMD [(proc-name)] [declare-simd-clause[ [,] // declare-simd-clause]...] struct OpenMPDeclareSimdConstruct { TUPLE_CLASS_BOILERPLATE(OpenMPDeclareSimdConstruct); CharBlock source; std::tuple, OmpClauseList> t; }; // 2.4 requires -> REQUIRES requires-clause[ [ [,] requires-clause]...] struct OpenMPRequiresConstruct { TUPLE_CLASS_BOILERPLATE(OpenMPRequiresConstruct); CharBlock source; std::tuple t; }; // 2.15.2 threadprivate -> THREADPRIVATE (variable-name-list) struct OpenMPThreadprivate { TUPLE_CLASS_BOILERPLATE(OpenMPThreadprivate); CharBlock source; std::tuple t; }; // 2.11.3 allocate -> ALLOCATE (variable-name-list) [clause] struct OpenMPDeclarativeAllocate { TUPLE_CLASS_BOILERPLATE(OpenMPDeclarativeAllocate); CharBlock source; std::tuple t; }; struct OpenMPDeclarativeConstruct { UNION_CLASS_BOILERPLATE(OpenMPDeclarativeConstruct); CharBlock source; std::variant u; }; // 2.13.2 CRITICAL [Name] END CRITICAL [Name] struct OmpCriticalDirective { TUPLE_CLASS_BOILERPLATE(OmpCriticalDirective); CharBlock source; std::tuple, OmpClauseList> t; }; struct OmpEndCriticalDirective { TUPLE_CLASS_BOILERPLATE(OmpEndCriticalDirective); CharBlock source; std::tuple> t; }; struct OpenMPCriticalConstruct { TUPLE_CLASS_BOILERPLATE(OpenMPCriticalConstruct); std::tuple t; }; // 2.11.3 allocate -> ALLOCATE [(variable-name-list)] [clause] // [ALLOCATE (variable-name-list) [clause] [...]] // allocate-statement // clause -> allocator-clause struct OpenMPExecutableAllocate { TUPLE_CLASS_BOILERPLATE(OpenMPExecutableAllocate); CharBlock source; std::tuple, OmpClauseList, std::optional>, Statement> t; }; EMPTY_CLASS(OmpEndAllocators); // 6.7 Allocators construct [OpenMP 5.2] // allocators-construct -> ALLOCATORS [allocate-clause [,]] // allocate-stmt // [omp-end-allocators-construct] struct OpenMPAllocatorsConstruct { TUPLE_CLASS_BOILERPLATE(OpenMPAllocatorsConstruct); CharBlock source; std::tuple, std::optional> t; }; // 2.17.7 Atomic construct/2.17.8 Flush construct [OpenMP 5.0] // memory-order-clause -> acq_rel // release // acquire // seq_cst // relaxed struct OmpMemoryOrderClause { WRAPPER_CLASS_BOILERPLATE(OmpMemoryOrderClause, OmpClause); CharBlock source; }; // 2.17.7 Atomic construct // atomic-clause -> memory-order-clause | HINT(hint-expression) struct OmpAtomicClause { UNION_CLASS_BOILERPLATE(OmpAtomicClause); CharBlock source; std::variant u; }; // atomic-clause-list -> [atomic-clause, [atomic-clause], ...] struct OmpAtomicClauseList { WRAPPER_CLASS_BOILERPLATE(OmpAtomicClauseList, std::list); CharBlock source; }; // END ATOMIC EMPTY_CLASS(OmpEndAtomic); // ATOMIC READ struct OmpAtomicRead { TUPLE_CLASS_BOILERPLATE(OmpAtomicRead); CharBlock source; std::tuple, std::optional> t; }; // ATOMIC WRITE struct OmpAtomicWrite { TUPLE_CLASS_BOILERPLATE(OmpAtomicWrite); CharBlock source; std::tuple, std::optional> t; }; // ATOMIC UPDATE struct OmpAtomicUpdate { TUPLE_CLASS_BOILERPLATE(OmpAtomicUpdate); CharBlock source; std::tuple, std::optional> t; }; // ATOMIC CAPTURE struct OmpAtomicCapture { TUPLE_CLASS_BOILERPLATE(OmpAtomicCapture); CharBlock source; WRAPPER_CLASS(Stmt1, Statement); WRAPPER_CLASS(Stmt2, Statement); std::tuple t; }; // ATOMIC struct OmpAtomic { TUPLE_CLASS_BOILERPLATE(OmpAtomic); CharBlock source; std::tuple, std::optional> t; }; // 2.17.7 atomic -> // ATOMIC [atomic-clause-list] atomic-construct [atomic-clause-list] | // ATOMIC [atomic-clause-list] // atomic-construct -> READ | WRITE | UPDATE | CAPTURE struct OpenMPAtomicConstruct { UNION_CLASS_BOILERPLATE(OpenMPAtomicConstruct); std::variant u; }; // OpenMP directives that associate with loop(s) struct OmpLoopDirective { WRAPPER_CLASS_BOILERPLATE(OmpLoopDirective, llvm::omp::Directive); CharBlock source; }; // 2.14.1 construct-type-clause -> PARALLEL | SECTIONS | DO | TASKGROUP struct OmpCancelType { ENUM_CLASS(Type, Parallel, Sections, Do, Taskgroup) WRAPPER_CLASS_BOILERPLATE(OmpCancelType, Type); CharBlock source; }; // 2.14.2 cancellation-point -> CANCELLATION POINT construct-type-clause struct OpenMPCancellationPointConstruct { TUPLE_CLASS_BOILERPLATE(OpenMPCancellationPointConstruct); CharBlock source; std::tuple t; }; // 2.14.1 cancel -> CANCEL construct-type-clause [ [,] if-clause] struct OpenMPCancelConstruct { TUPLE_CLASS_BOILERPLATE(OpenMPCancelConstruct); WRAPPER_CLASS(If, ScalarLogicalExpr); CharBlock source; std::tuple> t; }; // 2.17.8 flush -> FLUSH [memory-order-clause] [(variable-name-list)] struct OpenMPFlushConstruct { TUPLE_CLASS_BOILERPLATE(OpenMPFlushConstruct); CharBlock source; std::tuple>, std::optional> t; }; struct OmpSimpleStandaloneDirective { WRAPPER_CLASS_BOILERPLATE(OmpSimpleStandaloneDirective, llvm::omp::Directive); CharBlock source; }; struct OpenMPSimpleStandaloneConstruct { TUPLE_CLASS_BOILERPLATE(OpenMPSimpleStandaloneConstruct); CharBlock source; std::tuple t; }; struct OpenMPStandaloneConstruct { UNION_CLASS_BOILERPLATE(OpenMPStandaloneConstruct); CharBlock source; std::variant u; }; struct OmpBeginLoopDirective { TUPLE_CLASS_BOILERPLATE(OmpBeginLoopDirective); std::tuple t; CharBlock source; }; struct OmpEndLoopDirective { TUPLE_CLASS_BOILERPLATE(OmpEndLoopDirective); std::tuple t; CharBlock source; }; struct OmpBeginBlockDirective { TUPLE_CLASS_BOILERPLATE(OmpBeginBlockDirective); std::tuple t; CharBlock source; }; struct OmpEndBlockDirective { TUPLE_CLASS_BOILERPLATE(OmpEndBlockDirective); std::tuple t; CharBlock source; }; struct OpenMPBlockConstruct { TUPLE_CLASS_BOILERPLATE(OpenMPBlockConstruct); std::tuple t; }; // OpenMP directives enclosing do loop struct OpenMPLoopConstruct { TUPLE_CLASS_BOILERPLATE(OpenMPLoopConstruct); OpenMPLoopConstruct(OmpBeginLoopDirective &&a) : t({std::move(a), std::nullopt, std::nullopt}) {} std::tuple, std::optional> t; }; struct OpenMPConstruct { UNION_CLASS_BOILERPLATE(OpenMPConstruct); std::variant u; }; // Parse tree nodes for OpenACC 3.3 directives and clauses struct AccObject { UNION_CLASS_BOILERPLATE(AccObject); std::variant u; }; WRAPPER_CLASS(AccObjectList, std::list); // OpenACC directive beginning or ending a block struct AccBlockDirective { WRAPPER_CLASS_BOILERPLATE(AccBlockDirective, llvm::acc::Directive); CharBlock source; }; struct AccLoopDirective { WRAPPER_CLASS_BOILERPLATE(AccLoopDirective, llvm::acc::Directive); CharBlock source; }; struct AccStandaloneDirective { WRAPPER_CLASS_BOILERPLATE(AccStandaloneDirective, llvm::acc::Directive); CharBlock source; }; // 2.11 Combined constructs struct AccCombinedDirective { WRAPPER_CLASS_BOILERPLATE(AccCombinedDirective, llvm::acc::Directive); CharBlock source; }; struct AccDeclarativeDirective { WRAPPER_CLASS_BOILERPLATE(AccDeclarativeDirective, llvm::acc::Directive); CharBlock source; }; // OpenACC Clauses struct AccBindClause { UNION_CLASS_BOILERPLATE(AccBindClause); std::variant u; CharBlock source; }; struct AccDefaultClause { WRAPPER_CLASS_BOILERPLATE(AccDefaultClause, llvm::acc::DefaultValue); CharBlock source; }; struct AccDataModifier { ENUM_CLASS(Modifier, ReadOnly, Zero) WRAPPER_CLASS_BOILERPLATE(AccDataModifier, Modifier); CharBlock source; }; struct AccObjectListWithModifier { TUPLE_CLASS_BOILERPLATE(AccObjectListWithModifier); std::tuple, AccObjectList> t; }; // 2.5.15: + | * | max | min | iand | ior | ieor | .and. | .or. | .eqv. | .neqv. struct AccReductionOperator { ENUM_CLASS( Operator, Plus, Multiply, Max, Min, Iand, Ior, Ieor, And, Or, Eqv, Neqv) WRAPPER_CLASS_BOILERPLATE(AccReductionOperator, Operator); CharBlock source; }; struct AccObjectListWithReduction { TUPLE_CLASS_BOILERPLATE(AccObjectListWithReduction); std::tuple t; }; struct AccWaitArgument { TUPLE_CLASS_BOILERPLATE(AccWaitArgument); std::tuple, std::list> t; }; struct AccDeviceTypeExpr { WRAPPER_CLASS_BOILERPLATE( AccDeviceTypeExpr, Fortran::common::OpenACCDeviceType); CharBlock source; }; struct AccDeviceTypeExprList { WRAPPER_CLASS_BOILERPLATE( AccDeviceTypeExprList, std::list); }; struct AccTileExpr { TUPLE_CLASS_BOILERPLATE(AccTileExpr); CharBlock source; std::tuple> t; // if null then * }; struct AccTileExprList { WRAPPER_CLASS_BOILERPLATE(AccTileExprList, std::list); }; struct AccSizeExpr { WRAPPER_CLASS_BOILERPLATE(AccSizeExpr, std::optional); }; struct AccSizeExprList { WRAPPER_CLASS_BOILERPLATE(AccSizeExprList, std::list); }; struct AccSelfClause { UNION_CLASS_BOILERPLATE(AccSelfClause); std::variant, AccObjectList> u; CharBlock source; }; // num, dim, static struct AccGangArg { UNION_CLASS_BOILERPLATE(AccGangArg); WRAPPER_CLASS(Num, ScalarIntExpr); WRAPPER_CLASS(Dim, ScalarIntExpr); WRAPPER_CLASS(Static, AccSizeExpr); std::variant u; CharBlock source; }; struct AccGangArgList { WRAPPER_CLASS_BOILERPLATE(AccGangArgList, std::list); }; struct AccCollapseArg { TUPLE_CLASS_BOILERPLATE(AccCollapseArg); std::tuple t; }; struct AccClause { UNION_CLASS_BOILERPLATE(AccClause); #define GEN_FLANG_CLAUSE_PARSER_CLASSES #include "llvm/Frontend/OpenACC/ACC.inc" CharBlock source; std::variant< #define GEN_FLANG_CLAUSE_PARSER_CLASSES_LIST #include "llvm/Frontend/OpenACC/ACC.inc" > u; }; struct AccClauseList { WRAPPER_CLASS_BOILERPLATE(AccClauseList, std::list); CharBlock source; }; struct OpenACCRoutineConstruct { TUPLE_CLASS_BOILERPLATE(OpenACCRoutineConstruct); CharBlock source; std::tuple, AccClauseList> t; }; struct OpenACCCacheConstruct { TUPLE_CLASS_BOILERPLATE(OpenACCCacheConstruct); CharBlock source; std::tuple t; }; struct OpenACCWaitConstruct { TUPLE_CLASS_BOILERPLATE(OpenACCWaitConstruct); CharBlock source; std::tuple, AccClauseList> t; }; struct AccBeginLoopDirective { TUPLE_CLASS_BOILERPLATE(AccBeginLoopDirective); std::tuple t; CharBlock source; }; struct AccBeginBlockDirective { TUPLE_CLASS_BOILERPLATE(AccBeginBlockDirective); CharBlock source; std::tuple t; }; struct AccEndBlockDirective { CharBlock source; WRAPPER_CLASS_BOILERPLATE(AccEndBlockDirective, AccBlockDirective); }; // ACC END ATOMIC EMPTY_CLASS(AccEndAtomic); // ACC ATOMIC READ struct AccAtomicRead { TUPLE_CLASS_BOILERPLATE(AccAtomicRead); std::tuple, std::optional> t; }; // ACC ATOMIC WRITE struct AccAtomicWrite { TUPLE_CLASS_BOILERPLATE(AccAtomicWrite); std::tuple, std::optional> t; }; // ACC ATOMIC UPDATE struct AccAtomicUpdate { TUPLE_CLASS_BOILERPLATE(AccAtomicUpdate); std::tuple, Statement, std::optional> t; }; // ACC ATOMIC CAPTURE struct AccAtomicCapture { TUPLE_CLASS_BOILERPLATE(AccAtomicCapture); WRAPPER_CLASS(Stmt1, Statement); WRAPPER_CLASS(Stmt2, Statement); std::tuple t; }; struct OpenACCAtomicConstruct { UNION_CLASS_BOILERPLATE(OpenACCAtomicConstruct); std::variant u; CharBlock source; }; struct OpenACCBlockConstruct { TUPLE_CLASS_BOILERPLATE(OpenACCBlockConstruct); std::tuple t; }; struct OpenACCStandaloneDeclarativeConstruct { TUPLE_CLASS_BOILERPLATE(OpenACCStandaloneDeclarativeConstruct); CharBlock source; std::tuple t; }; struct AccBeginCombinedDirective { TUPLE_CLASS_BOILERPLATE(AccBeginCombinedDirective); CharBlock source; std::tuple t; }; struct AccEndCombinedDirective { WRAPPER_CLASS_BOILERPLATE(AccEndCombinedDirective, AccCombinedDirective); CharBlock source; }; struct OpenACCCombinedConstruct { TUPLE_CLASS_BOILERPLATE(OpenACCCombinedConstruct); CharBlock source; OpenACCCombinedConstruct(AccBeginCombinedDirective &&a) : t({std::move(a), std::nullopt, std::nullopt}) {} std::tuple, std::optional> t; }; struct OpenACCDeclarativeConstruct { UNION_CLASS_BOILERPLATE(OpenACCDeclarativeConstruct); CharBlock source; std::variant u; }; // OpenACC directives enclosing do loop EMPTY_CLASS(AccEndLoop); struct OpenACCLoopConstruct { TUPLE_CLASS_BOILERPLATE(OpenACCLoopConstruct); OpenACCLoopConstruct(AccBeginLoopDirective &&a) : t({std::move(a), std::nullopt, std::nullopt}) {} std::tuple, std::optional> t; }; struct OpenACCEndConstruct { WRAPPER_CLASS_BOILERPLATE(OpenACCEndConstruct, llvm::acc::Directive); CharBlock source; }; struct OpenACCStandaloneConstruct { TUPLE_CLASS_BOILERPLATE(OpenACCStandaloneConstruct); CharBlock source; std::tuple t; }; struct OpenACCConstruct { UNION_CLASS_BOILERPLATE(OpenACCConstruct); std::variant u; }; // CUF-kernel-do-construct -> // !$CUF KERNEL DO [ (scalar-int-constant-expr) ] <<< grid, block [, stream] // >>> do-construct // grid -> * | scalar-int-expr | ( scalar-int-expr-list ) // block -> * | scalar-int-expr | ( scalar-int-expr-list ) // stream -> 0, scalar-int-expr | STREAM = scalar-int-expr struct CUFKernelDoConstruct { TUPLE_CLASS_BOILERPLATE(CUFKernelDoConstruct); struct Directive { TUPLE_CLASS_BOILERPLATE(Directive); CharBlock source; std::tuple, std::list, std::list, std::optional> t; }; std::tuple> t; }; } // namespace Fortran::parser #endif // FORTRAN_PARSER_PARSE_TREE_H_