FLANG
parse-tree.h
1//===-- include/flang/Parser/parse-tree.h -----------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef FORTRAN_PARSER_PARSE_TREE_H_
10#define FORTRAN_PARSER_PARSE_TREE_H_
11
12// Defines the classes used to represent successful reductions of productions
13// in the Fortran grammar. The names and content of these definitions
14// adhere closely to the syntax specifications in the language standard (q.v.)
15// that are transcribed here and referenced via their requirement numbers.
16// The representations of some productions that may also be of use in the
17// run-time I/O support library have been isolated into a distinct header file
18// (viz., format-specification.h).
19
20#include "char-block.h"
21#include "characters.h"
22#include "format-specification.h"
23#include "message.h"
24#include "provenance.h"
25#include "flang/Common/idioms.h"
26#include "flang/Common/indirection.h"
27#include "flang/Support/Fortran.h"
28#include "llvm/Frontend/OpenACC/ACC.h.inc"
29#include "llvm/Frontend/OpenMP/OMP.h"
30#include "llvm/Frontend/OpenMP/OMPConstants.h"
31#include <cinttypes>
32#include <list>
33#include <memory>
34#include <optional>
35#include <string>
36#include <tuple>
37#include <type_traits>
38#include <utility>
39#include <variant>
40
41// Parse tree node class types do not have default constructors. They
42// explicitly declare "T() {} = delete;" to make this clear. This restriction
43// prevents the introduction of what would be a viral requirement to include
44// std::monostate among most std::variant<> discriminated union members.
45
46// Parse tree node class types do not have copy constructors or copy assignment
47// operators. They are explicitly declared "= delete;" to make this clear,
48// although a C++ compiler wouldn't default them anyway due to the presence
49// of explicitly defaulted move constructors and move assignments.
50
51CLASS_TRAIT(EmptyTrait)
52CLASS_TRAIT(WrapperTrait)
53CLASS_TRAIT(UnionTrait)
54CLASS_TRAIT(TupleTrait)
55CLASS_TRAIT(ConstraintTrait)
56
57// Some parse tree nodes have fields in them to cache the results of a
58// successful semantic analysis later. Their types are forward declared
59// here.
60namespace Fortran::semantics {
61class Symbol;
62class DeclTypeSpec;
63class DerivedTypeSpec;
64} // namespace Fortran::semantics
65
66// Expressions in the parse tree have owning pointers that can be set to
67// type-checked generic expression representations by semantic analysis.
68namespace Fortran::evaluate {
69struct GenericExprWrapper; // forward definition, wraps Expr<SomeType>
70struct GenericAssignmentWrapper; // forward definition, represent assignment
71class ProcedureRef; // forward definition, represents a CALL or function ref
72} // namespace Fortran::evaluate
73
74// Most non-template classes in this file use these default definitions
75// for their move constructor and move assignment operator=, and disable
76// their copy constructor and copy assignment operator=.
77#define COPY_AND_ASSIGN_BOILERPLATE(classname) \
78 classname(classname &&) = default; \
79 classname &operator=(classname &&) = default; \
80 classname(const classname &) = delete; \
81 classname &operator=(const classname &) = delete
82
83// Almost all classes in this file have no default constructor.
84#define BOILERPLATE(classname) \
85 COPY_AND_ASSIGN_BOILERPLATE(classname); \
86 classname() = delete
87
88// Empty classes are often used below as alternatives in std::variant<>
89// discriminated unions.
90#define EMPTY_CLASS(classname) \
91 struct classname { \
92 classname() {} \
93 classname(const classname &) {} \
94 classname(classname &&) {} \
95 classname &operator=(const classname &) { return *this; }; \
96 classname &operator=(classname &&) { return *this; }; \
97 using EmptyTrait = std::true_type; \
98 }
99
100// Many classes below simply wrap a std::variant<> discriminated union,
101// which is conventionally named "u".
102#define UNION_CLASS_BOILERPLATE(classname) \
103 template <typename A, typename = common::NoLvalue<A>> \
104 classname(A &&x) : u(std::move(x)) {} \
105 using UnionTrait = std::true_type; \
106 BOILERPLATE(classname)
107
108// Many other classes below simply wrap a std::tuple<> structure, which
109// is conventionally named "t".
110#define TUPLE_CLASS_BOILERPLATE(classname) \
111 template <typename... Ts, typename = common::NoLvalue<Ts...>> \
112 classname(Ts &&...args) : t(std::move(args)...) {} \
113 using TupleTrait = std::true_type; \
114 BOILERPLATE(classname)
115
116// Many other classes below simply wrap a single data member, which is
117// conventionally named "v".
118#define WRAPPER_CLASS_BOILERPLATE(classname, type) \
119 BOILERPLATE(classname); \
120 classname(type &&x) : v(std::move(x)) {} \
121 using WrapperTrait = std::true_type; \
122 type v
123
124#define WRAPPER_CLASS(classname, type) \
125 struct classname { \
126 WRAPPER_CLASS_BOILERPLATE(classname, type); \
127 }
128
129namespace Fortran::parser {
130
131// These are the unavoidable recursively-defined productions of Fortran.
132// Some references to the representations of their parses require
133// indirection. The Indirect<> pointer wrapper class is used to
134// enforce ownership semantics and non-nullability.
135struct SpecificationPart; // R504
136struct ExecutableConstruct; // R514
137struct ActionStmt; // R515
138struct AcImpliedDo; // R774
139struct DataImpliedDo; // R840
140struct Designator; // R901
141struct Variable; // R902
142struct Expr; // R1001
143struct WhereConstruct; // R1042
144struct ForallConstruct; // R1050
145struct InputImpliedDo; // R1218
146struct OutputImpliedDo; // R1218
147struct FunctionReference; // R1520
148struct FunctionSubprogram; // R1529
149struct SubroutineSubprogram; // R1534
150
151// These additional forward references are declared so that the order of
152// class definitions in this header file can remain reasonably consistent
153// with order of the the requirement productions in the grammar.
154struct DerivedTypeDef; // R726
155struct EnumDef; // R759
156struct TypeDeclarationStmt; // R801
157struct AccessStmt; // R827
158struct AllocatableStmt; // R829
159struct AsynchronousStmt; // R831
160struct BindStmt; // R832
161struct CodimensionStmt; // R834
162struct ContiguousStmt; // R836
163struct DataStmt; // R837
164struct DataStmtValue; // R843
165struct DimensionStmt; // R848
166struct IntentStmt; // R849
167struct OptionalStmt; // R850
168struct ParameterStmt; // R851
169struct OldParameterStmt;
170struct PointerStmt; // R853
171struct ProtectedStmt; // R855
172struct SaveStmt; // R856
173struct TargetStmt; // R859
174struct ValueStmt; // R861
175struct VolatileStmt; // R862
176struct ImplicitStmt; // R863
177struct ImportStmt; // R867
178struct NamelistStmt; // R868
179struct EquivalenceStmt; // R870
180struct CommonStmt; // R873
181struct Substring; // R908
183struct SubstringInquiry;
184struct DataRef; // R911
185struct StructureComponent; // R913
186struct CoindexedNamedObject; // R914
187struct ArrayElement; // R917
188struct AllocateStmt; // R927
189struct NullifyStmt; // R939
190struct DeallocateStmt; // R941
191struct AssignmentStmt; // R1032
192struct PointerAssignmentStmt; // R1033
193struct WhereStmt; // R1041, R1045, R1046
194struct ForallStmt; // R1055
195struct AssociateConstruct; // R1102
196struct BlockConstruct; // R1107
197struct ChangeTeamConstruct; // R1111
198struct CriticalConstruct; // R1116
199struct DoConstruct; // R1119
200struct LabelDoStmt; // R1121
201struct ConcurrentHeader; // R1125
202struct EndDoStmt; // R1132
203struct CycleStmt; // R1133
204struct IfConstruct; // R1134
205struct IfStmt; // R1139
206struct CaseConstruct; // R1140
207struct SelectRankConstruct; // R1148
208struct SelectTypeConstruct; // R1152
209struct ExitStmt; // R1156
210struct GotoStmt; // R1157
211struct ComputedGotoStmt; // R1158
212struct StopStmt; // R1160, R1161
213struct NotifyWaitStmt; // F2023: R1166
214struct SyncAllStmt; // R1164
215struct SyncImagesStmt; // R1166
216struct SyncMemoryStmt; // R1168
217struct SyncTeamStmt; // R1169
218struct EventPostStmt; // R1170, R1171
219struct EventWaitSpec; // F2023: R1177
220struct EventWaitStmt; // R1172, R1173, R1174
221struct FormTeamStmt; // R1175, R1176, R1177
222struct LockStmt; // R1178
223struct UnlockStmt; // R1180
224struct OpenStmt; // R1204
225struct CloseStmt; // R1208
226struct ReadStmt; // R1210
227struct WriteStmt; // R1211
228struct PrintStmt; // R1212
229struct WaitStmt; // R1222
230struct BackspaceStmt; // R1224
231struct EndfileStmt; // R1225
232struct RewindStmt; // R1226
233struct FlushStmt; // R1228
234struct InquireStmt; // R1230
235struct FormatStmt; // R1301
236struct MainProgram; // R1401
237struct Module; // R1404
238struct UseStmt; // R1409
239struct Submodule; // R1416
240struct BlockData; // R1420
241struct InterfaceBlock; // R1501
242struct GenericSpec; // R1508
243struct GenericStmt; // R1510
244struct ExternalStmt; // R1511
245struct ProcedureDeclarationStmt; // R1512
246struct IntrinsicStmt; // R1519
247struct Call; // R1520 & R1521
248struct CallStmt; // R1521
249struct ProcedureDesignator; // R1522
250struct ActualArg; // R1524
251struct SeparateModuleSubprogram; // R1538
252struct EntryStmt; // R1541
253struct ReturnStmt; // R1542
254struct StmtFunctionStmt; // R1544
255
256// Directives, extensions, and deprecated statements
257struct CompilerDirective;
258struct BasedPointerStmt;
259struct CUDAAttributesStmt;
260struct StructureDef;
261struct ArithmeticIfStmt;
262struct AssignStmt;
263struct AssignedGotoStmt;
264struct PauseStmt;
265struct OpenACCConstruct;
269struct OpenMPConstruct;
274
275// Cooked character stream locations
276using Location = const char *;
277
278// A parse tree node with provenance only
279struct Verbatim {
280 // Allow a no-arg constructor for Verbatim so parsers can return `RESULT{}`.
281 constexpr Verbatim() {}
282 COPY_AND_ASSIGN_BOILERPLATE(Verbatim);
283 using EmptyTrait = std::true_type;
284 CharBlock source;
285};
286
287// Implicit definitions of the Standard
288
289// R403 scalar-xyz -> xyz
290// These template class wrappers correspond to the Standard's modifiers
291// scalar-xyz, constant-xzy, int-xzy, default-char-xyz, & logical-xyz.
292template <typename A> struct Scalar {
293 using ConstraintTrait = std::true_type;
294 Scalar(Scalar &&that) = default;
295 Scalar(A &&that) : thing(std::move(that)) {}
296 Scalar &operator=(Scalar &&) = default;
297 A thing;
298};
299
300template <typename A> struct Constant {
301 using ConstraintTrait = std::true_type;
302 Constant(Constant &&that) = default;
303 Constant(A &&that) : thing(std::move(that)) {}
304 Constant &operator=(Constant &&) = default;
305 A thing;
306};
307
308template <typename A> struct Integer {
309 using ConstraintTrait = std::true_type;
310 Integer(Integer &&that) = default;
311 Integer(A &&that) : thing(std::move(that)) {}
312 Integer &operator=(Integer &&) = default;
313 A thing;
314};
315
316template <typename A> struct Logical {
317 using ConstraintTrait = std::true_type;
318 Logical(Logical &&that) = default;
319 Logical(A &&that) : thing(std::move(that)) {}
320 Logical &operator=(Logical &&) = default;
321 A thing;
322};
323
324template <typename A> struct DefaultChar {
325 using ConstraintTrait = std::true_type;
326 DefaultChar(DefaultChar &&that) = default;
327 DefaultChar(A &&that) : thing(std::move(that)) {}
328 DefaultChar &operator=(DefaultChar &&) = default;
329 A thing;
330};
331
332using LogicalExpr = Logical<common::Indirection<Expr>>; // R1024
333using DefaultCharExpr = DefaultChar<common::Indirection<Expr>>; // R1025
334using IntExpr = Integer<common::Indirection<Expr>>; // R1026
335using ConstantExpr = Constant<common::Indirection<Expr>>; // R1029
336using IntConstantExpr = Integer<ConstantExpr>; // R1031
337using ScalarLogicalExpr = Scalar<LogicalExpr>;
338using ScalarIntExpr = Scalar<IntExpr>;
339using ScalarIntConstantExpr = Scalar<IntConstantExpr>;
340using ScalarDefaultCharExpr = Scalar<DefaultCharExpr>;
341// R1030 default-char-constant-expr is used in the Standard only as part of
342// scalar-default-char-constant-expr.
343using ScalarDefaultCharConstantExpr = Scalar<DefaultChar<ConstantExpr>>;
344
345// R611 label -> digit [digit]...
346using Label = common::Label; // validated later, must be in [1..99999]
347
348// A wrapper for xzy-stmt productions that are statements, so that
349// source provenances and labels have a uniform representation.
350template <typename A> struct UnlabeledStatement {
351 explicit UnlabeledStatement(A &&s) : statement(std::move(s)) {}
352 CharBlock source;
353 A statement;
354};
355template <typename A> struct Statement : public UnlabeledStatement<A> {
356 Statement(std::optional<long> &&lab, A &&s)
357 : UnlabeledStatement<A>{std::move(s)}, label(std::move(lab)) {}
358 std::optional<Label> label;
359};
360
361// Error recovery marker
362EMPTY_CLASS(ErrorRecovery);
363
364// R513 other-specification-stmt ->
365// access-stmt | allocatable-stmt | asynchronous-stmt | bind-stmt |
366// codimension-stmt | contiguous-stmt | dimension-stmt | external-stmt |
367// intent-stmt | intrinsic-stmt | namelist-stmt | optional-stmt |
368// pointer-stmt | protected-stmt | save-stmt | target-stmt |
369// volatile-stmt | value-stmt | common-stmt | equivalence-stmt
370// Extension: (Cray) based POINTER statement
371// Extension: CUDA data attribute statement
389
390// R508 specification-construct ->
391// derived-type-def | enum-def | generic-stmt | interface-block |
392// parameter-stmt | procedure-declaration-stmt |
393// other-specification-stmt | type-declaration-stmt
410
411// R506 implicit-part-stmt ->
412// implicit-stmt | parameter-stmt | format-stmt | entry-stmt
424
425// R505 implicit-part -> [implicit-part-stmt]... implicit-stmt
426WRAPPER_CLASS(ImplicitPart, std::list<ImplicitPartStmt>);
427
428// R507 declaration-construct ->
429// specification-construct | data-stmt | format-stmt |
430// entry-stmt | stmt-function-stmt
432 UNION_CLASS_BOILERPLATE(DeclarationConstruct);
433 std::variant<SpecificationConstruct, Statement<common::Indirection<DataStmt>>,
437 u;
438};
439
440// R504 specification-part -> [use-stmt]... [import-stmt]... [implicit-part]
441// [declaration-construct]...
442// PARAMETER, FORMAT, and ENTRY statements that appear before any other
443// kind of declaration-construct will be parsed into the implicit-part,
444// even if there are no IMPLICIT statements.
446 TUPLE_CLASS_BOILERPLATE(SpecificationPart);
447 std::tuple<std::list<OpenACCDeclarativeConstruct>,
448 std::list<OpenMPDeclarativeConstruct>,
449 std::list<common::Indirection<CompilerDirective>>,
450 std::list<Statement<common::Indirection<UseStmt>>>,
451 std::list<Statement<common::Indirection<ImportStmt>>>, ImplicitPart,
452 std::list<DeclarationConstruct>>
453 t;
454};
455
456// R512 internal-subprogram -> function-subprogram | subroutine-subprogram
458 UNION_CLASS_BOILERPLATE(InternalSubprogram);
459 std::variant<common::Indirection<FunctionSubprogram>,
462 u;
463};
464
465// R1543 contains-stmt -> CONTAINS
466EMPTY_CLASS(ContainsStmt);
467
468// R511 internal-subprogram-part -> contains-stmt [internal-subprogram]...
470 TUPLE_CLASS_BOILERPLATE(InternalSubprogramPart);
471 std::tuple<Statement<ContainsStmt>, std::list<InternalSubprogram>> t;
472};
473
474// R1159 continue-stmt -> CONTINUE
475EMPTY_CLASS(ContinueStmt);
476
477// R1163 fail-image-stmt -> FAIL IMAGE
478EMPTY_CLASS(FailImageStmt);
479
480// R515 action-stmt ->
481// allocate-stmt | assignment-stmt | backspace-stmt | call-stmt |
482// close-stmt | continue-stmt | cycle-stmt | deallocate-stmt |
483// endfile-stmt | error-stop-stmt | event-post-stmt | event-wait-stmt |
484// exit-stmt | fail-image-stmt | flush-stmt | form-team-stmt |
485// goto-stmt | if-stmt | inquire-stmt | lock-stmt | notify-wait-stmt |
486// nullify-stmt | open-stmt | pointer-assignment-stmt | print-stmt |
487// read-stmt | return-stmt | rewind-stmt | stop-stmt | sync-all-stmt |
488// sync-images-stmt | sync-memory-stmt | sync-team-stmt | unlock-stmt |
489// wait-stmt | where-stmt | write-stmt | computed-goto-stmt | forall-stmt
491 UNION_CLASS_BOILERPLATE(ActionStmt);
492 std::variant<common::Indirection<AllocateStmt>,
495 ContinueStmt, common::Indirection<CycleStmt>,
498 common::Indirection<ExitStmt>, FailImageStmt,
514 u;
515};
516
517// R514 executable-construct ->
518// action-stmt | associate-construct | block-construct |
519// case-construct | change-team-construct | critical-construct |
520// do-construct | if-construct | select-rank-construct |
521// select-type-construct | where-construct | forall-construct |
522// (CUDA) CUF-kernel-do-construct
543
544// R510 execution-part-construct ->
545// executable-construct | format-stmt | entry-stmt | data-stmt
546// Extension (PGI/Intel): also accept NAMELIST in execution part
548 UNION_CLASS_BOILERPLATE(ExecutionPartConstruct);
549 std::variant<ExecutableConstruct, Statement<common::Indirection<FormatStmt>>,
553 u;
554};
555
556// R509 execution-part -> executable-construct [execution-part-construct]...
557// R1101 block -> [execution-part-construct]...
558using Block = std::list<ExecutionPartConstruct>;
559WRAPPER_CLASS(ExecutionPart, Block);
560
561// R502 program-unit ->
562// main-program | external-subprogram | module | submodule | block-data
563// R503 external-subprogram -> function-subprogram | subroutine-subprogram
574
575// R501 program -> program-unit [program-unit]...
576// This is the top-level production.
577WRAPPER_CLASS(Program, std::list<ProgramUnit>);
578
579// R603 name -> letter [alphanumeric-character]...
580struct Name {
581 std::string ToString() const { return source.ToString(); }
582 CharBlock source;
583 mutable semantics::Symbol *symbol{nullptr}; // filled in during semantics
584};
585
586// R516 keyword -> name
587WRAPPER_CLASS(Keyword, Name);
588
589// R606 named-constant -> name
590WRAPPER_CLASS(NamedConstant, Name);
591
592// R1003 defined-unary-op -> . letter [letter]... .
593// R1023 defined-binary-op -> . letter [letter]... .
594// R1414 local-defined-operator -> defined-unary-op | defined-binary-op
595// R1415 use-defined-operator -> defined-unary-op | defined-binary-op
596// The Name here is stored with the dots; e.g., .FOO.
597WRAPPER_CLASS(DefinedOpName, Name);
598
599// R608 intrinsic-operator ->
600// ** | * | / | + | - | // | .LT. | .LE. | .EQ. | .NE. | .GE. | .GT. |
601// .NOT. | .AND. | .OR. | .EQV. | .NEQV.
602// R609 defined-operator ->
603// defined-unary-op | defined-binary-op | extended-intrinsic-op
604// R610 extended-intrinsic-op -> intrinsic-operator
606 UNION_CLASS_BOILERPLATE(DefinedOperator);
607 ENUM_CLASS(IntrinsicOperator, Power, Multiply, Divide, Add, Subtract, Concat,
608 LT, LE, EQ, NE, GE, GT, NOT, AND, OR, EQV, NEQV)
609 std::variant<DefinedOpName, IntrinsicOperator> u;
610};
611
612// R804 object-name -> name
613using ObjectName = Name;
614
615// R867 import-stmt ->
616// IMPORT [[::] import-name-list] |
617// IMPORT , ONLY : import-name-list | IMPORT , NONE | IMPORT , ALL
618struct ImportStmt {
619 BOILERPLATE(ImportStmt);
620 ImportStmt(common::ImportKind &&k) : kind{k} {}
621 ImportStmt(std::list<Name> &&n) : names(std::move(n)) {}
622 ImportStmt(common::ImportKind &&, std::list<Name> &&);
623 common::ImportKind kind{common::ImportKind::Default};
624 std::list<Name> names;
625};
626
627// R868 namelist-stmt ->
628// NAMELIST / namelist-group-name / namelist-group-object-list
629// [[,] / namelist-group-name / namelist-group-object-list]...
630// R869 namelist-group-object -> variable-name
632 struct Group {
633 TUPLE_CLASS_BOILERPLATE(Group);
634 std::tuple<Name, std::list<Name>> t;
635 };
636 WRAPPER_CLASS_BOILERPLATE(NamelistStmt, std::list<Group>);
637};
638
639// R701 type-param-value -> scalar-int-expr | * | :
640EMPTY_CLASS(Star);
641
643 UNION_CLASS_BOILERPLATE(TypeParamValue);
644 EMPTY_CLASS(Deferred); // :
645 std::variant<ScalarIntExpr, Star, Deferred> u;
646};
647
648// R706 kind-selector -> ( [KIND =] scalar-int-constant-expr )
649// Legacy extension: kind-selector -> * digit-string
650// N.B. These are not semantically identical in the case of COMPLEX.
652 UNION_CLASS_BOILERPLATE(KindSelector);
653 WRAPPER_CLASS(StarSize, std::uint64_t);
654 std::variant<ScalarIntConstantExpr, StarSize> u;
655};
656
657// R705 integer-type-spec -> INTEGER [kind-selector]
658WRAPPER_CLASS(IntegerTypeSpec, std::optional<KindSelector>);
659
660WRAPPER_CLASS(UnsignedTypeSpec, std::optional<KindSelector>);
661
662// R723 char-length -> ( type-param-value ) | digit-string
664 UNION_CLASS_BOILERPLATE(CharLength);
665 std::variant<TypeParamValue, std::uint64_t> u;
666};
667
668// R722 length-selector -> ( [LEN =] type-param-value ) | * char-length [,]
670 UNION_CLASS_BOILERPLATE(LengthSelector);
671 std::variant<TypeParamValue, CharLength> u;
672};
673
674// R721 char-selector ->
675// length-selector |
676// ( LEN = type-param-value , KIND = scalar-int-constant-expr ) |
677// ( type-param-value , [KIND =] scalar-int-constant-expr ) |
678// ( KIND = scalar-int-constant-expr [, LEN = type-param-value] )
679struct CharSelector {
680 UNION_CLASS_BOILERPLATE(CharSelector);
681 struct LengthAndKind {
682 BOILERPLATE(LengthAndKind);
683 LengthAndKind(std::optional<TypeParamValue> &&l, ScalarIntConstantExpr &&k)
684 : length(std::move(l)), kind(std::move(k)) {}
685 std::optional<TypeParamValue> length;
686 ScalarIntConstantExpr kind;
687 };
688 CharSelector(TypeParamValue &&l, ScalarIntConstantExpr &&k)
689 : u{LengthAndKind{std::make_optional(std::move(l)), std::move(k)}} {}
690 CharSelector(ScalarIntConstantExpr &&k, std::optional<TypeParamValue> &&l)
691 : u{LengthAndKind{std::move(l), std::move(k)}} {}
692 std::variant<LengthSelector, LengthAndKind> u;
693};
694
695// R704 intrinsic-type-spec ->
696// integer-type-spec | REAL [kind-selector] | DOUBLE PRECISION |
697// COMPLEX [kind-selector] | CHARACTER [char-selector] |
698// LOGICAL [kind-selector]
699// Extensions: DOUBLE COMPLEX & UNSIGNED [kind-selector]
701 UNION_CLASS_BOILERPLATE(IntrinsicTypeSpec);
702 struct Real {
703 BOILERPLATE(Real);
704 Real(std::optional<KindSelector> &&k) : kind{std::move(k)} {}
705 std::optional<KindSelector> kind;
706 };
707 EMPTY_CLASS(DoublePrecision);
708 struct Complex {
709 BOILERPLATE(Complex);
710 Complex(std::optional<KindSelector> &&k) : kind{std::move(k)} {}
711 std::optional<KindSelector> kind;
712 };
713 struct Character {
714 BOILERPLATE(Character);
715 Character(std::optional<CharSelector> &&s) : selector{std::move(s)} {}
716 std::optional<CharSelector> selector;
717 };
718 struct Logical {
719 BOILERPLATE(Logical);
720 Logical(std::optional<KindSelector> &&k) : kind{std::move(k)} {}
721 std::optional<KindSelector> kind;
722 };
723 EMPTY_CLASS(DoubleComplex);
724 std::variant<IntegerTypeSpec, UnsignedTypeSpec, Real, DoublePrecision,
725 Complex, Character, Logical, DoubleComplex>
726 u;
727};
728
729// Extension: Vector type
731 UNION_CLASS_BOILERPLATE(VectorElementType);
732 std::variant<IntegerTypeSpec, IntrinsicTypeSpec::Real, UnsignedTypeSpec> u;
733};
734WRAPPER_CLASS(IntrinsicVectorTypeSpec, VectorElementType);
736 UNION_CLASS_BOILERPLATE(VectorTypeSpec);
737 EMPTY_CLASS(PairVectorTypeSpec);
738 EMPTY_CLASS(QuadVectorTypeSpec);
739 std::variant<IntrinsicVectorTypeSpec, PairVectorTypeSpec, QuadVectorTypeSpec>
740 u;
741};
742
743// R755 type-param-spec -> [keyword =] type-param-value
745 TUPLE_CLASS_BOILERPLATE(TypeParamSpec);
746 std::tuple<std::optional<Keyword>, TypeParamValue> t;
747};
748
749// R754 derived-type-spec -> type-name [(type-param-spec-list)]
751 TUPLE_CLASS_BOILERPLATE(DerivedTypeSpec);
752 mutable const semantics::DerivedTypeSpec *derivedTypeSpec{nullptr};
753 std::tuple<Name, std::list<TypeParamSpec>> t;
754};
755
756// R702 type-spec -> intrinsic-type-spec | derived-type-spec
757struct TypeSpec {
758 UNION_CLASS_BOILERPLATE(TypeSpec);
759 mutable const semantics::DeclTypeSpec *declTypeSpec{nullptr};
760 std::variant<IntrinsicTypeSpec, DerivedTypeSpec> u;
761};
762
763// R703 declaration-type-spec ->
764// intrinsic-type-spec | TYPE ( intrinsic-type-spec ) |
765// TYPE ( derived-type-spec ) | CLASS ( derived-type-spec ) |
766// CLASS ( * ) | TYPE ( * )
767// Legacy extension: RECORD /struct/
769 UNION_CLASS_BOILERPLATE(DeclarationTypeSpec);
770 struct Type {
771 BOILERPLATE(Type);
772 Type(DerivedTypeSpec &&dt) : derived(std::move(dt)) {}
773 DerivedTypeSpec derived;
774 };
775 struct Class {
776 BOILERPLATE(Class);
777 Class(DerivedTypeSpec &&dt) : derived(std::move(dt)) {}
778 DerivedTypeSpec derived;
779 };
780 EMPTY_CLASS(ClassStar);
781 EMPTY_CLASS(TypeStar);
782 WRAPPER_CLASS(Record, Name);
783 std::variant<IntrinsicTypeSpec, Type, Class, ClassStar, TypeStar, Record,
785 u;
786};
787
788// R709 kind-param -> digit-string | scalar-int-constant-name
789struct KindParam {
790 UNION_CLASS_BOILERPLATE(KindParam);
791 std::variant<std::uint64_t, Scalar<Integer<Constant<Name>>>> u;
792};
793
794// R707 signed-int-literal-constant -> [sign] int-literal-constant
796 TUPLE_CLASS_BOILERPLATE(SignedIntLiteralConstant);
797 CharBlock source;
798 std::tuple<CharBlock, std::optional<KindParam>> t;
799};
800
801// R708 int-literal-constant -> digit-string [_ kind-param]
803 TUPLE_CLASS_BOILERPLATE(IntLiteralConstant);
804 std::tuple<CharBlock, std::optional<KindParam>> t;
805};
806
807// extension: unsigned-literal-constant -> digit-string U [_ kind-param]
809 TUPLE_CLASS_BOILERPLATE(UnsignedLiteralConstant);
810 std::tuple<CharBlock, std::optional<KindParam>> t;
811};
812
813// R712 sign -> + | -
814enum class Sign { Positive, Negative };
815
816// R714 real-literal-constant ->
817// significand [exponent-letter exponent] [_ kind-param] |
818// digit-string exponent-letter exponent [_ kind-param]
819// R715 significand -> digit-string . [digit-string] | . digit-string
820// R717 exponent -> signed-digit-string
821struct RealLiteralConstant {
822 BOILERPLATE(RealLiteralConstant);
823 struct Real {
824 COPY_AND_ASSIGN_BOILERPLATE(Real);
825 Real() {}
826 CharBlock source;
827 };
828 RealLiteralConstant(Real &&r, std::optional<KindParam> &&k)
829 : real{std::move(r)}, kind{std::move(k)} {}
830 Real real;
831 std::optional<KindParam> kind;
832};
833
834// R713 signed-real-literal-constant -> [sign] real-literal-constant
836 TUPLE_CLASS_BOILERPLATE(SignedRealLiteralConstant);
837 std::tuple<std::optional<Sign>, RealLiteralConstant> t;
838};
839
840// R719 real-part ->
841// signed-int-literal-constant | signed-real-literal-constant |
842// named-constant
843// R720 imag-part ->
844// signed-int-literal-constant | signed-real-literal-constant |
845// named-constant
847 UNION_CLASS_BOILERPLATE(ComplexPart);
849 NamedConstant>
850 u;
851};
852
853// R718 complex-literal-constant -> ( real-part , imag-part )
855 TUPLE_CLASS_BOILERPLATE(ComplexLiteralConstant);
856 std::tuple<ComplexPart, ComplexPart> t; // real, imaginary
857};
858
859// Extension: signed COMPLEX constant
861 TUPLE_CLASS_BOILERPLATE(SignedComplexLiteralConstant);
862 std::tuple<Sign, ComplexLiteralConstant> t;
863};
864
865// R724 char-literal-constant ->
866// [kind-param _] ' [rep-char]... ' |
867// [kind-param _] " [rep-char]... "
869 TUPLE_CLASS_BOILERPLATE(CharLiteralConstant);
870 std::tuple<std::optional<KindParam>, std::string> t;
871 std::string GetString() const { return std::get<std::string>(t); }
872};
873
874// legacy extension
876 WRAPPER_CLASS_BOILERPLATE(HollerithLiteralConstant, std::string);
877 std::string GetString() const { return v; }
878};
879
880// R725 logical-literal-constant ->
881// .TRUE. [_ kind-param] | .FALSE. [_ kind-param]
883 TUPLE_CLASS_BOILERPLATE(LogicalLiteralConstant);
884 std::tuple<bool, std::optional<KindParam>> t;
885};
886
887// R764 boz-literal-constant -> binary-constant | octal-constant | hex-constant
888// R765 binary-constant -> B ' digit [digit]... ' | B " digit [digit]... "
889// R766 octal-constant -> O ' digit [digit]... ' | O " digit [digit]... "
890// R767 hex-constant ->
891// Z ' hex-digit [hex-digit]... ' | Z " hex-digit [hex-digit]... "
892// The constant must be large enough to hold any real or integer scalar
893// of any supported kind (F'2018 7.7).
894WRAPPER_CLASS(BOZLiteralConstant, std::string);
895
896// R605 literal-constant ->
897// int-literal-constant | real-literal-constant |
898// complex-literal-constant | logical-literal-constant |
899// char-literal-constant | boz-literal-constant
907
908// R807 access-spec -> PUBLIC | PRIVATE
910 ENUM_CLASS(Kind, Public, Private)
911 WRAPPER_CLASS_BOILERPLATE(AccessSpec, Kind);
912};
913
914// R728 type-attr-spec ->
915// ABSTRACT | access-spec | BIND(C) | EXTENDS ( parent-type-name )
916EMPTY_CLASS(Abstract);
918 UNION_CLASS_BOILERPLATE(TypeAttrSpec);
919 EMPTY_CLASS(BindC);
920 WRAPPER_CLASS(Extends, Name);
921 std::variant<Abstract, AccessSpec, BindC, Extends> u;
922};
923
924// R727 derived-type-stmt ->
925// TYPE [[, type-attr-spec-list] ::] type-name [( type-param-name-list )]
927 TUPLE_CLASS_BOILERPLATE(DerivedTypeStmt);
928 std::tuple<std::list<TypeAttrSpec>, Name, std::list<Name>> t;
929};
930
931// R731 sequence-stmt -> SEQUENCE
932EMPTY_CLASS(SequenceStmt);
933
934// R745 private-components-stmt -> PRIVATE
935// R747 binding-private-stmt -> PRIVATE
936EMPTY_CLASS(PrivateStmt);
937
938// R729 private-or-sequence -> private-components-stmt | sequence-stmt
940 UNION_CLASS_BOILERPLATE(PrivateOrSequence);
941 std::variant<PrivateStmt, SequenceStmt> u;
942};
943
944// R733 type-param-decl -> type-param-name [= scalar-int-constant-expr]
946 TUPLE_CLASS_BOILERPLATE(TypeParamDecl);
947 std::tuple<Name, std::optional<ScalarIntConstantExpr>> t;
948};
949
950// R732 type-param-def-stmt ->
951// integer-type-spec , type-param-attr-spec :: type-param-decl-list
952// R734 type-param-attr-spec -> KIND | LEN
954 TUPLE_CLASS_BOILERPLATE(TypeParamDefStmt);
955 std::tuple<IntegerTypeSpec, common::TypeParamAttr, std::list<TypeParamDecl>>
956 t;
957};
958
959// R1028 specification-expr -> scalar-int-expr
960WRAPPER_CLASS(SpecificationExpr, ScalarIntExpr);
961
962// R816 explicit-shape-spec -> [lower-bound :] upper-bound
963// R817 lower-bound -> specification-expr
964// R818 upper-bound -> specification-expr
966 TUPLE_CLASS_BOILERPLATE(ExplicitShapeSpec);
967 std::tuple<std::optional<SpecificationExpr>, SpecificationExpr> t;
968};
969
970// R810 deferred-coshape-spec -> :
971// deferred-coshape-spec-list is just a count of the colons (i.e., the rank).
972WRAPPER_CLASS(DeferredCoshapeSpecList, int);
973
974// R811 explicit-coshape-spec ->
975// [[lower-cobound :] upper-cobound ,]... [lower-cobound :] *
976// R812 lower-cobound -> specification-expr
977// R813 upper-cobound -> specification-expr
979 TUPLE_CLASS_BOILERPLATE(ExplicitCoshapeSpec);
980 std::tuple<std::list<ExplicitShapeSpec>, std::optional<SpecificationExpr>> t;
981};
982
983// R809 coarray-spec -> deferred-coshape-spec-list | explicit-coshape-spec
985 UNION_CLASS_BOILERPLATE(CoarraySpec);
986 std::variant<DeferredCoshapeSpecList, ExplicitCoshapeSpec> u;
987};
988
989// R820 deferred-shape-spec -> :
990// deferred-shape-spec-list is just a count of the colons (i.e., the rank).
991WRAPPER_CLASS(DeferredShapeSpecList, int);
992
993// R740 component-array-spec ->
994// explicit-shape-spec-list | deferred-shape-spec-list
996 UNION_CLASS_BOILERPLATE(ComponentArraySpec);
997 std::variant<std::list<ExplicitShapeSpec>, DeferredShapeSpecList> u;
998};
999
1000// R738 component-attr-spec ->
1001// access-spec | ALLOCATABLE |
1002// CODIMENSION lbracket coarray-spec rbracket |
1003// CONTIGUOUS | DIMENSION ( component-array-spec ) | POINTER |
1004// (CUDA) CONSTANT | DEVICE | MANAGED | PINNED | SHARED | TEXTURE | UNIFIED
1005EMPTY_CLASS(Allocatable);
1006EMPTY_CLASS(Pointer);
1007EMPTY_CLASS(Contiguous);
1009 UNION_CLASS_BOILERPLATE(ComponentAttrSpec);
1010 std::variant<AccessSpec, Allocatable, CoarraySpec, Contiguous,
1011 ComponentArraySpec, Pointer, common::CUDADataAttr, ErrorRecovery>
1012 u;
1013};
1014
1015// R806 null-init -> function-reference ... which must be NULL()
1016WRAPPER_CLASS(NullInit, common::Indirection<Expr>);
1017
1018// R744 initial-data-target -> designator
1019using InitialDataTarget = common::Indirection<Designator>;
1020
1021// R743 component-initialization ->
1022// = constant-expr | => null-init | => initial-data-target
1023// R805 initialization ->
1024// = constant-expr | => null-init | => initial-data-target
1025// Universal extension: initialization -> / data-stmt-value-list /
1027 UNION_CLASS_BOILERPLATE(Initialization);
1028 std::variant<ConstantExpr, NullInit, InitialDataTarget,
1029 std::list<common::Indirection<DataStmtValue>>>
1030 u;
1031};
1032
1033// R739 component-decl ->
1034// component-name [( component-array-spec )]
1035// [lbracket coarray-spec rbracket] [* char-length]
1036// [component-initialization] |
1037// component-name *char-length [( component-array-spec )]
1038// [lbracket coarray-spec rbracket] [component-initialization]
1039struct ComponentDecl {
1040 TUPLE_CLASS_BOILERPLATE(ComponentDecl);
1041 ComponentDecl(Name &&name, CharLength &&length,
1042 std::optional<ComponentArraySpec> &&aSpec,
1043 std::optional<CoarraySpec> &&coaSpec,
1044 std::optional<Initialization> &&init)
1045 : t{std::move(name), std::move(aSpec), std::move(coaSpec),
1046 std::move(length), std::move(init)} {}
1047 std::tuple<Name, std::optional<ComponentArraySpec>,
1048 std::optional<CoarraySpec>, std::optional<CharLength>,
1049 std::optional<Initialization>>
1050 t;
1051};
1052
1053// A %FILL component for a DEC STRUCTURE. The name will be replaced
1054// with a distinct compiler-generated name.
1055struct FillDecl {
1056 TUPLE_CLASS_BOILERPLATE(FillDecl);
1057 std::tuple<Name, std::optional<ComponentArraySpec>, std::optional<CharLength>>
1058 t;
1059};
1060
1062 UNION_CLASS_BOILERPLATE(ComponentOrFill);
1063 std::variant<ComponentDecl, FillDecl> u;
1064};
1065
1066// R737 data-component-def-stmt ->
1067// declaration-type-spec [[, component-attr-spec-list] ::]
1068// component-decl-list
1070 TUPLE_CLASS_BOILERPLATE(DataComponentDefStmt);
1071 std::tuple<DeclarationTypeSpec, std::list<ComponentAttrSpec>,
1072 std::list<ComponentOrFill>>
1073 t;
1074};
1075
1076// R742 proc-component-attr-spec ->
1077// access-spec | NOPASS | PASS [(arg-name)] | POINTER
1078EMPTY_CLASS(NoPass);
1079WRAPPER_CLASS(Pass, std::optional<Name>);
1081 UNION_CLASS_BOILERPLATE(ProcComponentAttrSpec);
1082 std::variant<AccessSpec, NoPass, Pass, Pointer> u;
1083};
1084
1085// R1517 proc-pointer-init -> null-init | initial-proc-target
1086// R1518 initial-proc-target -> procedure-name
1088 UNION_CLASS_BOILERPLATE(ProcPointerInit);
1089 std::variant<NullInit, Name> u;
1090};
1091
1092// R1513 proc-interface -> interface-name | declaration-type-spec
1093// R1516 interface-name -> name
1095 UNION_CLASS_BOILERPLATE(ProcInterface);
1096 std::variant<Name, DeclarationTypeSpec> u;
1097};
1098
1099// R1515 proc-decl -> procedure-entity-name [=> proc-pointer-init]
1100struct ProcDecl {
1101 TUPLE_CLASS_BOILERPLATE(ProcDecl);
1102 std::tuple<Name, std::optional<ProcPointerInit>> t;
1103};
1104
1105// R741 proc-component-def-stmt ->
1106// PROCEDURE ( [proc-interface] ) , proc-component-attr-spec-list
1107// :: proc-decl-list
1109 TUPLE_CLASS_BOILERPLATE(ProcComponentDefStmt);
1110 std::tuple<std::optional<ProcInterface>, std::list<ProcComponentAttrSpec>,
1111 std::list<ProcDecl>>
1112 t;
1113};
1114
1115// R736 component-def-stmt -> data-component-def-stmt | proc-component-def-stmt
1117 UNION_CLASS_BOILERPLATE(ComponentDefStmt);
1120 // , TypeParamDefStmt -- PGI accidental extension, not enabled
1121 >
1122 u;
1123};
1124
1125// R752 bind-attr ->
1126// access-spec | DEFERRED | NON_OVERRIDABLE | NOPASS | PASS [(arg-name)]
1127struct BindAttr {
1128 UNION_CLASS_BOILERPLATE(BindAttr);
1129 EMPTY_CLASS(Deferred);
1130 EMPTY_CLASS(Non_Overridable);
1131 std::variant<AccessSpec, Deferred, Non_Overridable, NoPass, Pass> u;
1132};
1133
1134// R750 type-bound-proc-decl -> binding-name [=> procedure-name]
1136 TUPLE_CLASS_BOILERPLATE(TypeBoundProcDecl);
1137 std::tuple<Name, std::optional<Name>> t;
1138};
1139
1140// R749 type-bound-procedure-stmt ->
1141// PROCEDURE [[, bind-attr-list] ::] type-bound-proc-decl-list |
1142// PROCEDURE ( interface-name ) , bind-attr-list :: binding-name-list
1143// The second form, with interface-name, requires DEFERRED in bind-attr-list,
1144// and thus can appear only in an abstract type.
1146 UNION_CLASS_BOILERPLATE(TypeBoundProcedureStmt);
1147 struct WithoutInterface {
1148 BOILERPLATE(WithoutInterface);
1149 WithoutInterface(
1150 std::list<BindAttr> &&as, std::list<TypeBoundProcDecl> &&ds)
1151 : attributes(std::move(as)), declarations(std::move(ds)) {}
1152 std::list<BindAttr> attributes;
1153 std::list<TypeBoundProcDecl> declarations;
1154 };
1155 struct WithInterface {
1156 BOILERPLATE(WithInterface);
1157 WithInterface(Name &&n, std::list<BindAttr> &&as, std::list<Name> &&bs)
1158 : interfaceName(std::move(n)), attributes(std::move(as)),
1159 bindingNames(std::move(bs)) {}
1160 Name interfaceName;
1161 std::list<BindAttr> attributes;
1162 std::list<Name> bindingNames;
1163 };
1164 std::variant<WithoutInterface, WithInterface> u;
1165};
1166
1167// R751 type-bound-generic-stmt ->
1168// GENERIC [, access-spec] :: generic-spec => binding-name-list
1170 TUPLE_CLASS_BOILERPLATE(TypeBoundGenericStmt);
1171 std::tuple<std::optional<AccessSpec>, common::Indirection<GenericSpec>,
1172 std::list<Name>>
1173 t;
1174};
1175
1176// R753 final-procedure-stmt -> FINAL [::] final-subroutine-name-list
1177WRAPPER_CLASS(FinalProcedureStmt, std::list<Name>);
1178
1179// R748 type-bound-proc-binding ->
1180// type-bound-procedure-stmt | type-bound-generic-stmt |
1181// final-procedure-stmt
1183 UNION_CLASS_BOILERPLATE(TypeBoundProcBinding);
1184 std::variant<TypeBoundProcedureStmt, TypeBoundGenericStmt, FinalProcedureStmt,
1185 ErrorRecovery>
1186 u;
1187};
1188
1189// R746 type-bound-procedure-part ->
1190// contains-stmt [binding-private-stmt] [type-bound-proc-binding]...
1192 TUPLE_CLASS_BOILERPLATE(TypeBoundProcedurePart);
1193 std::tuple<Statement<ContainsStmt>, std::optional<Statement<PrivateStmt>>,
1194 std::list<Statement<TypeBoundProcBinding>>>
1195 t;
1196};
1197
1198// R730 end-type-stmt -> END TYPE [type-name]
1199WRAPPER_CLASS(EndTypeStmt, std::optional<Name>);
1200
1201// R726 derived-type-def ->
1202// derived-type-stmt [type-param-def-stmt]... [private-or-sequence]...
1203// [component-part] [type-bound-procedure-part] end-type-stmt
1204// R735 component-part -> [component-def-stmt]...
1206 TUPLE_CLASS_BOILERPLATE(DerivedTypeDef);
1207 std::tuple<Statement<DerivedTypeStmt>, std::list<Statement<TypeParamDefStmt>>,
1208 std::list<Statement<PrivateOrSequence>>,
1209 std::list<Statement<ComponentDefStmt>>,
1210 std::optional<TypeBoundProcedurePart>, Statement<EndTypeStmt>>
1211 t;
1212};
1213
1214// R758 component-data-source -> expr | data-target | proc-target
1215// R1037 data-target -> expr
1216// R1040 proc-target -> expr | procedure-name | proc-component-ref
1217WRAPPER_CLASS(ComponentDataSource, common::Indirection<Expr>);
1218
1219// R757 component-spec -> [keyword =] component-data-source
1221 TUPLE_CLASS_BOILERPLATE(ComponentSpec);
1222 std::tuple<std::optional<Keyword>, ComponentDataSource> t;
1223};
1224
1225// R756 structure-constructor -> derived-type-spec ( [component-spec-list] )
1227 TUPLE_CLASS_BOILERPLATE(StructureConstructor);
1228 std::tuple<DerivedTypeSpec, std::list<ComponentSpec>> t;
1229};
1230
1231// R760 enum-def-stmt -> ENUM, BIND(C)
1232EMPTY_CLASS(EnumDefStmt);
1233
1234// R762 enumerator -> named-constant [= scalar-int-constant-expr]
1236 TUPLE_CLASS_BOILERPLATE(Enumerator);
1237 std::tuple<NamedConstant, std::optional<ScalarIntConstantExpr>> t;
1238};
1239
1240// R761 enumerator-def-stmt -> ENUMERATOR [::] enumerator-list
1241WRAPPER_CLASS(EnumeratorDefStmt, std::list<Enumerator>);
1242
1243// R763 end-enum-stmt -> END ENUM
1244EMPTY_CLASS(EndEnumStmt);
1245
1246// R759 enum-def ->
1247// enum-def-stmt enumerator-def-stmt [enumerator-def-stmt]...
1248// end-enum-stmt
1249struct EnumDef {
1250 TUPLE_CLASS_BOILERPLATE(EnumDef);
1251 std::tuple<Statement<EnumDefStmt>, std::list<Statement<EnumeratorDefStmt>>,
1253 t;
1254};
1255
1256// R773 ac-value -> expr | ac-implied-do
1257struct AcValue {
1258 struct Triplet { // PGI/Intel extension
1259 TUPLE_CLASS_BOILERPLATE(Triplet);
1260 std::tuple<ScalarIntExpr, ScalarIntExpr, std::optional<ScalarIntExpr>> t;
1261 };
1262 UNION_CLASS_BOILERPLATE(AcValue);
1263 std::variant<Triplet, common::Indirection<Expr>,
1265 u;
1266};
1267
1268// R770 ac-spec -> type-spec :: | [type-spec ::] ac-value-list
1269struct AcSpec {
1270 BOILERPLATE(AcSpec);
1271 AcSpec(std::optional<TypeSpec> &&ts, std::list<AcValue> &&xs)
1272 : type(std::move(ts)), values(std::move(xs)) {}
1273 explicit AcSpec(TypeSpec &&ts) : type{std::move(ts)} {}
1274 std::optional<TypeSpec> type;
1275 std::list<AcValue> values;
1276};
1277
1278// R769 array-constructor -> (/ ac-spec /) | lbracket ac-spec rbracket
1279WRAPPER_CLASS(ArrayConstructor, AcSpec);
1280
1281// R1124 do-variable -> scalar-int-variable-name
1282using DoVariable = Scalar<Integer<Name>>;
1283
1284template <typename VAR, typename BOUND> struct LoopBounds {
1285 LoopBounds(LoopBounds &&that) = default;
1286 LoopBounds(
1287 VAR &&name, BOUND &&lower, BOUND &&upper, std::optional<BOUND> &&step)
1288 : name{std::move(name)}, lower{std::move(lower)}, upper{std::move(upper)},
1289 step{std::move(step)} {}
1290 LoopBounds &operator=(LoopBounds &&) = default;
1291 VAR name;
1292 BOUND lower, upper;
1293 std::optional<BOUND> step;
1294};
1295
1296using ScalarName = Scalar<Name>;
1297using ScalarExpr = Scalar<common::Indirection<Expr>>;
1298
1299// R775 ac-implied-do-control ->
1300// [integer-type-spec ::] ac-do-variable = scalar-int-expr ,
1301// scalar-int-expr [, scalar-int-expr]
1302// R776 ac-do-variable -> do-variable
1304 TUPLE_CLASS_BOILERPLATE(AcImpliedDoControl);
1306 std::tuple<std::optional<IntegerTypeSpec>, Bounds> t;
1307};
1308
1309// R774 ac-implied-do -> ( ac-value-list , ac-implied-do-control )
1311 TUPLE_CLASS_BOILERPLATE(AcImpliedDo);
1312 std::tuple<std::list<AcValue>, AcImpliedDoControl> t;
1313};
1314
1315// R808 language-binding-spec ->
1316// BIND ( C [, NAME = scalar-default-char-constant-expr ]
1317// [, CDEFINED ] )
1318// R1528 proc-language-binding-spec -> language-binding-spec
1320 TUPLE_CLASS_BOILERPLATE(LanguageBindingSpec);
1321 std::tuple<std::optional<ScalarDefaultCharConstantExpr>, bool> t;
1322};
1323
1324// R852 named-constant-def -> named-constant = constant-expr
1326 TUPLE_CLASS_BOILERPLATE(NamedConstantDef);
1327 std::tuple<NamedConstant, ConstantExpr> t;
1328};
1329
1330// R851 parameter-stmt -> PARAMETER ( named-constant-def-list )
1331WRAPPER_CLASS(ParameterStmt, std::list<NamedConstantDef>);
1332
1333// R819 assumed-shape-spec -> [lower-bound] :
1334WRAPPER_CLASS(AssumedShapeSpec, std::optional<SpecificationExpr>);
1335
1336// R821 assumed-implied-spec -> [lower-bound :] *
1337WRAPPER_CLASS(AssumedImpliedSpec, std::optional<SpecificationExpr>);
1338
1339// R822 assumed-size-spec -> explicit-shape-spec-list , assumed-implied-spec
1341 TUPLE_CLASS_BOILERPLATE(AssumedSizeSpec);
1342 std::tuple<std::list<ExplicitShapeSpec>, AssumedImpliedSpec> t;
1343};
1344
1345// R823 implied-shape-or-assumed-size-spec -> assumed-implied-spec
1346// R824 implied-shape-spec -> assumed-implied-spec , assumed-implied-spec-list
1347// I.e., when the assumed-implied-spec-list has a single item, it constitutes an
1348// implied-shape-or-assumed-size-spec; otherwise, an implied-shape-spec.
1349WRAPPER_CLASS(ImpliedShapeSpec, std::list<AssumedImpliedSpec>);
1350
1351// R825 assumed-rank-spec -> ..
1352EMPTY_CLASS(AssumedRankSpec);
1353
1354// R815 array-spec ->
1355// explicit-shape-spec-list | assumed-shape-spec-list |
1356// deferred-shape-spec-list | assumed-size-spec | implied-shape-spec |
1357// implied-shape-or-assumed-size-spec | assumed-rank-spec
1359 UNION_CLASS_BOILERPLATE(ArraySpec);
1360 std::variant<std::list<ExplicitShapeSpec>, std::list<AssumedShapeSpec>,
1361 DeferredShapeSpecList, AssumedSizeSpec, ImpliedShapeSpec, AssumedRankSpec>
1362 u;
1363};
1364
1365// R826 intent-spec -> IN | OUT | INOUT
1367 ENUM_CLASS(Intent, In, Out, InOut)
1368 WRAPPER_CLASS_BOILERPLATE(IntentSpec, Intent);
1369};
1370
1371// R802 attr-spec ->
1372// access-spec | ALLOCATABLE | ASYNCHRONOUS |
1373// CODIMENSION lbracket coarray-spec rbracket | CONTIGUOUS |
1374// DIMENSION ( array-spec ) | EXTERNAL | INTENT ( intent-spec ) |
1375// INTRINSIC | language-binding-spec | OPTIONAL | PARAMETER | POINTER |
1376// PROTECTED | SAVE | TARGET | VALUE | VOLATILE |
1377// (CUDA) CONSTANT | DEVICE | MANAGED | PINNED | SHARED | TEXTURE
1378EMPTY_CLASS(Asynchronous);
1379EMPTY_CLASS(External);
1380EMPTY_CLASS(Intrinsic);
1381EMPTY_CLASS(Optional);
1382EMPTY_CLASS(Parameter);
1383EMPTY_CLASS(Protected);
1384EMPTY_CLASS(Save);
1385EMPTY_CLASS(Target);
1386EMPTY_CLASS(Value);
1387EMPTY_CLASS(Volatile);
1388struct AttrSpec {
1389 UNION_CLASS_BOILERPLATE(AttrSpec);
1390 std::variant<AccessSpec, Allocatable, Asynchronous, CoarraySpec, Contiguous,
1391 ArraySpec, External, IntentSpec, Intrinsic, LanguageBindingSpec, Optional,
1392 Parameter, Pointer, Protected, Save, Target, Value, Volatile,
1393 common::CUDADataAttr>
1394 u;
1395};
1396
1397// R803 entity-decl ->
1398// object-name [( array-spec )] [lbracket coarray-spec rbracket]
1399// [* char-length] [initialization] |
1400// function-name [* char-length] |
1401// (ext.) object-name *char-length [( array-spec )]
1402// [lbracket coarray-spec rbracket] [initialization]
1403struct EntityDecl {
1404 TUPLE_CLASS_BOILERPLATE(EntityDecl);
1405 EntityDecl(ObjectName &&name, CharLength &&length,
1406 std::optional<ArraySpec> &&aSpec, std::optional<CoarraySpec> &&coaSpec,
1407 std::optional<Initialization> &&init)
1408 : t{std::move(name), std::move(aSpec), std::move(coaSpec),
1409 std::move(length), std::move(init)} {}
1410 std::tuple<ObjectName, std::optional<ArraySpec>, std::optional<CoarraySpec>,
1411 std::optional<CharLength>, std::optional<Initialization>>
1412 t;
1413};
1414
1415// R801 type-declaration-stmt ->
1416// declaration-type-spec [[, attr-spec]... ::] entity-decl-list
1418 TUPLE_CLASS_BOILERPLATE(TypeDeclarationStmt);
1419 std::tuple<DeclarationTypeSpec, std::list<AttrSpec>, std::list<EntityDecl>> t;
1420};
1421
1422// R828 access-id -> access-name | generic-spec
1423// "access-name" is ambiguous with "generic-spec", so that's what's parsed
1424WRAPPER_CLASS(AccessId, common::Indirection<GenericSpec>);
1425
1426// R827 access-stmt -> access-spec [[::] access-id-list]
1428 TUPLE_CLASS_BOILERPLATE(AccessStmt);
1429 std::tuple<AccessSpec, std::list<AccessId>> t;
1430};
1431
1432// R830 allocatable-decl ->
1433// object-name [( array-spec )] [lbracket coarray-spec rbracket]
1434// R860 target-decl ->
1435// object-name [( array-spec )] [lbracket coarray-spec rbracket]
1437 TUPLE_CLASS_BOILERPLATE(ObjectDecl);
1438 std::tuple<ObjectName, std::optional<ArraySpec>, std::optional<CoarraySpec>>
1439 t;
1440};
1441
1442// R829 allocatable-stmt -> ALLOCATABLE [::] allocatable-decl-list
1443WRAPPER_CLASS(AllocatableStmt, std::list<ObjectDecl>);
1444
1445// R831 asynchronous-stmt -> ASYNCHRONOUS [::] object-name-list
1446WRAPPER_CLASS(AsynchronousStmt, std::list<ObjectName>);
1447
1448// R833 bind-entity -> entity-name | / common-block-name /
1450 TUPLE_CLASS_BOILERPLATE(BindEntity);
1451 ENUM_CLASS(Kind, Object, Common)
1452 std::tuple<Kind, Name> t;
1453};
1454
1455// R832 bind-stmt -> language-binding-spec [::] bind-entity-list
1456struct BindStmt {
1457 TUPLE_CLASS_BOILERPLATE(BindStmt);
1458 std::tuple<LanguageBindingSpec, std::list<BindEntity>> t;
1459};
1460
1461// R835 codimension-decl -> coarray-name lbracket coarray-spec rbracket
1463 TUPLE_CLASS_BOILERPLATE(CodimensionDecl);
1464 std::tuple<Name, CoarraySpec> t;
1465};
1466
1467// R834 codimension-stmt -> CODIMENSION [::] codimension-decl-list
1468WRAPPER_CLASS(CodimensionStmt, std::list<CodimensionDecl>);
1469
1470// R836 contiguous-stmt -> CONTIGUOUS [::] object-name-list
1471WRAPPER_CLASS(ContiguousStmt, std::list<ObjectName>);
1472
1473// R847 constant-subobject -> designator
1474// R846 int-constant-subobject -> constant-subobject
1475using ConstantSubobject = Constant<common::Indirection<Designator>>;
1476
1477// Represents an analyzed expression
1479
1480// R845 data-stmt-constant ->
1481// scalar-constant | scalar-constant-subobject |
1482// signed-int-literal-constant | signed-real-literal-constant |
1483// null-init | initial-data-target |
1484// structure-constructor
1485// N.B. Parsing ambiguities abound here without recourse to symbols
1486// (see comments on R845's parser).
1488 UNION_CLASS_BOILERPLATE(DataStmtConstant);
1489 CharBlock source;
1490 mutable TypedExpr typedExpr;
1491 std::variant<common::Indirection<CharLiteralConstantSubstring>,
1495 u;
1496};
1497
1498// R844 data-stmt-repeat -> scalar-int-constant | scalar-int-constant-subobject
1499// R607 int-constant -> constant
1500// R604 constant -> literal-constant | named-constant
1501// (only literal-constant -> int-literal-constant applies)
1503 UNION_CLASS_BOILERPLATE(DataStmtRepeat);
1504 std::variant<IntLiteralConstant, Scalar<Integer<ConstantSubobject>>> u;
1505};
1506
1507// R843 data-stmt-value -> [data-stmt-repeat *] data-stmt-constant
1509 TUPLE_CLASS_BOILERPLATE(DataStmtValue);
1510 mutable std::int64_t repetitions{1}; // replaced during semantics
1511 std::tuple<std::optional<DataStmtRepeat>, DataStmtConstant> t;
1512};
1513
1514// R841 data-i-do-object ->
1515// array-element | scalar-structure-component | data-implied-do
1517 UNION_CLASS_BOILERPLATE(DataIDoObject);
1518 std::variant<Scalar<common::Indirection<Designator>>,
1520 u;
1521};
1522
1523// R840 data-implied-do ->
1524// ( data-i-do-object-list , [integer-type-spec ::] data-i-do-variable
1525// = scalar-int-constant-expr , scalar-int-constant-expr
1526// [, scalar-int-constant-expr] )
1527// R842 data-i-do-variable -> do-variable
1529 TUPLE_CLASS_BOILERPLATE(DataImpliedDo);
1531 std::tuple<std::list<DataIDoObject>, std::optional<IntegerTypeSpec>, Bounds>
1532 t;
1533};
1534
1535// R839 data-stmt-object -> variable | data-implied-do
1537 UNION_CLASS_BOILERPLATE(DataStmtObject);
1538 std::variant<common::Indirection<Variable>, DataImpliedDo> u;
1539};
1540
1541// R838 data-stmt-set -> data-stmt-object-list / data-stmt-value-list /
1543 TUPLE_CLASS_BOILERPLATE(DataStmtSet);
1544 std::tuple<std::list<DataStmtObject>, std::list<DataStmtValue>> t;
1545};
1546
1547// R837 data-stmt -> DATA data-stmt-set [[,] data-stmt-set]...
1548WRAPPER_CLASS(DataStmt, std::list<DataStmtSet>);
1549
1550// R848 dimension-stmt ->
1551// DIMENSION [::] array-name ( array-spec )
1552// [, array-name ( array-spec )]...
1555 TUPLE_CLASS_BOILERPLATE(Declaration);
1556 std::tuple<Name, ArraySpec> t;
1557 };
1558 WRAPPER_CLASS_BOILERPLATE(DimensionStmt, std::list<Declaration>);
1559};
1560
1561// R849 intent-stmt -> INTENT ( intent-spec ) [::] dummy-arg-name-list
1563 TUPLE_CLASS_BOILERPLATE(IntentStmt);
1564 std::tuple<IntentSpec, std::list<Name>> t;
1565};
1566
1567// R850 optional-stmt -> OPTIONAL [::] dummy-arg-name-list
1568WRAPPER_CLASS(OptionalStmt, std::list<Name>);
1569
1570// R854 pointer-decl ->
1571// object-name [( deferred-shape-spec-list )] | proc-entity-name
1573 TUPLE_CLASS_BOILERPLATE(PointerDecl);
1574 std::tuple<Name, std::optional<DeferredShapeSpecList>> t;
1575};
1576
1577// R853 pointer-stmt -> POINTER [::] pointer-decl-list
1578WRAPPER_CLASS(PointerStmt, std::list<PointerDecl>);
1579
1580// R855 protected-stmt -> PROTECTED [::] entity-name-list
1581WRAPPER_CLASS(ProtectedStmt, std::list<Name>);
1582
1583// R857 saved-entity -> object-name | proc-pointer-name | / common-block-name /
1584// R858 proc-pointer-name -> name
1586 TUPLE_CLASS_BOILERPLATE(SavedEntity);
1587 ENUM_CLASS(Kind, Entity, Common)
1588 std::tuple<Kind, Name> t;
1589};
1590
1591// R856 save-stmt -> SAVE [[::] saved-entity-list]
1592WRAPPER_CLASS(SaveStmt, std::list<SavedEntity>);
1593
1594// R859 target-stmt -> TARGET [::] target-decl-list
1595WRAPPER_CLASS(TargetStmt, std::list<ObjectDecl>);
1596
1597// R861 value-stmt -> VALUE [::] dummy-arg-name-list
1598WRAPPER_CLASS(ValueStmt, std::list<Name>);
1599
1600// R862 volatile-stmt -> VOLATILE [::] object-name-list
1601WRAPPER_CLASS(VolatileStmt, std::list<ObjectName>);
1602
1603// R865 letter-spec -> letter [- letter]
1605 TUPLE_CLASS_BOILERPLATE(LetterSpec);
1606 std::tuple<Location, std::optional<Location>> t;
1607};
1608
1609// R864 implicit-spec -> declaration-type-spec ( letter-spec-list )
1611 TUPLE_CLASS_BOILERPLATE(ImplicitSpec);
1612 std::tuple<DeclarationTypeSpec, std::list<LetterSpec>> t;
1613};
1614
1615// R863 implicit-stmt ->
1616// IMPLICIT implicit-spec-list |
1617// IMPLICIT NONE [( [implicit-name-spec-list] )]
1618// R866 implicit-name-spec -> EXTERNAL | TYPE
1620 UNION_CLASS_BOILERPLATE(ImplicitStmt);
1621 ENUM_CLASS(ImplicitNoneNameSpec, External, Type) // R866
1622 std::variant<std::list<ImplicitSpec>, std::list<ImplicitNoneNameSpec>> u;
1623};
1624
1625// R874 common-block-object -> variable-name [( array-spec )]
1627 TUPLE_CLASS_BOILERPLATE(CommonBlockObject);
1628 std::tuple<Name, std::optional<ArraySpec>> t;
1629};
1630
1631// R873 common-stmt ->
1632// COMMON [/ [common-block-name] /] common-block-object-list
1633// [[,] / [common-block-name] / common-block-object-list]...
1634struct CommonStmt {
1635 struct Block {
1636 TUPLE_CLASS_BOILERPLATE(Block);
1637 std::tuple<std::optional<Name>, std::list<CommonBlockObject>> t;
1638 };
1639 BOILERPLATE(CommonStmt);
1640 CommonStmt(std::optional<Name> &&, std::list<CommonBlockObject> &&,
1641 std::list<Block> &&);
1642 CharBlock source;
1643 std::list<Block> blocks;
1644};
1645
1646// R872 equivalence-object -> variable-name | array-element | substring
1647WRAPPER_CLASS(EquivalenceObject, common::Indirection<Designator>);
1648
1649// R870 equivalence-stmt -> EQUIVALENCE equivalence-set-list
1650// R871 equivalence-set -> ( equivalence-object , equivalence-object-list )
1651WRAPPER_CLASS(EquivalenceStmt, std::list<std::list<EquivalenceObject>>);
1652
1653// R910 substring-range -> [scalar-int-expr] : [scalar-int-expr]
1655 TUPLE_CLASS_BOILERPLATE(SubstringRange);
1656 std::tuple<std::optional<ScalarIntExpr>, std::optional<ScalarIntExpr>> t;
1657};
1658
1659// R919 subscript -> scalar-int-expr
1660using Subscript = ScalarIntExpr;
1661
1662// R921 subscript-triplet -> [subscript] : [subscript] [: stride]
1664 TUPLE_CLASS_BOILERPLATE(SubscriptTriplet);
1665 std::tuple<std::optional<Subscript>, std::optional<Subscript>,
1666 std::optional<Subscript>>
1667 t;
1668};
1669
1670// R920 section-subscript -> subscript | subscript-triplet | vector-subscript
1671// R923 vector-subscript -> int-expr
1673 UNION_CLASS_BOILERPLATE(SectionSubscript);
1674 std::variant<IntExpr, SubscriptTriplet> u;
1675};
1676
1677// R925 cosubscript -> scalar-int-expr
1678using Cosubscript = ScalarIntExpr;
1679
1680// R1115 team-value -> scalar-expr
1681WRAPPER_CLASS(TeamValue, Scalar<common::Indirection<Expr>>);
1682
1683// R926 image-selector-spec ->
1684// STAT = stat-variable | TEAM = team-value |
1685// TEAM_NUMBER = scalar-int-expr
1687 WRAPPER_CLASS(Stat, Scalar<Integer<common::Indirection<Variable>>>);
1688 WRAPPER_CLASS(Team_Number, ScalarIntExpr);
1689 UNION_CLASS_BOILERPLATE(ImageSelectorSpec);
1690 std::variant<Stat, TeamValue, Team_Number> u;
1691};
1692
1693// R924 image-selector ->
1694// lbracket cosubscript-list [, image-selector-spec-list] rbracket
1696 TUPLE_CLASS_BOILERPLATE(ImageSelector);
1697 std::tuple<std::list<Cosubscript>, std::list<ImageSelectorSpec>> t;
1698};
1699
1700// R1001 - R1022 expressions
1701struct Expr {
1702 UNION_CLASS_BOILERPLATE(Expr);
1703
1704 WRAPPER_CLASS(IntrinsicUnary, common::Indirection<Expr>);
1705 struct Parentheses : public IntrinsicUnary {
1706 using IntrinsicUnary::IntrinsicUnary;
1707 };
1708 struct UnaryPlus : public IntrinsicUnary {
1709 using IntrinsicUnary::IntrinsicUnary;
1710 };
1711 struct Negate : public IntrinsicUnary {
1712 using IntrinsicUnary::IntrinsicUnary;
1713 };
1714 struct NOT : public IntrinsicUnary {
1715 using IntrinsicUnary::IntrinsicUnary;
1716 };
1717
1718 WRAPPER_CLASS(PercentLoc, common::Indirection<Variable>); // %LOC(v) extension
1719
1721 TUPLE_CLASS_BOILERPLATE(DefinedUnary);
1722 std::tuple<DefinedOpName, common::Indirection<Expr>> t;
1723 };
1724
1726 TUPLE_CLASS_BOILERPLATE(IntrinsicBinary);
1727 std::tuple<common::Indirection<Expr>, common::Indirection<Expr>> t;
1728 };
1729 struct Power : public IntrinsicBinary {
1730 using IntrinsicBinary::IntrinsicBinary;
1731 };
1732 struct Multiply : public IntrinsicBinary {
1733 using IntrinsicBinary::IntrinsicBinary;
1734 };
1735 struct Divide : public IntrinsicBinary {
1736 using IntrinsicBinary::IntrinsicBinary;
1737 };
1738 struct Add : public IntrinsicBinary {
1739 using IntrinsicBinary::IntrinsicBinary;
1740 };
1741 struct Subtract : public IntrinsicBinary {
1742 using IntrinsicBinary::IntrinsicBinary;
1743 };
1744 struct Concat : public IntrinsicBinary {
1745 using IntrinsicBinary::IntrinsicBinary;
1746 };
1747 struct LT : public IntrinsicBinary {
1748 using IntrinsicBinary::IntrinsicBinary;
1749 };
1750 struct LE : public IntrinsicBinary {
1751 using IntrinsicBinary::IntrinsicBinary;
1752 };
1753 struct EQ : public IntrinsicBinary {
1754 using IntrinsicBinary::IntrinsicBinary;
1755 };
1756 struct NE : public IntrinsicBinary {
1757 using IntrinsicBinary::IntrinsicBinary;
1758 };
1759 struct GE : public IntrinsicBinary {
1760 using IntrinsicBinary::IntrinsicBinary;
1761 };
1762 struct GT : public IntrinsicBinary {
1763 using IntrinsicBinary::IntrinsicBinary;
1764 };
1765 struct AND : public IntrinsicBinary {
1766 using IntrinsicBinary::IntrinsicBinary;
1767 };
1768 struct OR : public IntrinsicBinary {
1769 using IntrinsicBinary::IntrinsicBinary;
1770 };
1771 struct EQV : public IntrinsicBinary {
1772 using IntrinsicBinary::IntrinsicBinary;
1773 };
1774 struct NEQV : public IntrinsicBinary {
1775 using IntrinsicBinary::IntrinsicBinary;
1776 };
1777
1778 // PGI/XLF extension: (x,y), not both constant
1780 using IntrinsicBinary::IntrinsicBinary;
1781 };
1782
1784 TUPLE_CLASS_BOILERPLATE(DefinedBinary);
1785 std::tuple<DefinedOpName, common::Indirection<Expr>,
1787 t;
1788 };
1789
1790 explicit Expr(Designator &&);
1791 explicit Expr(FunctionReference &&);
1792
1793 mutable TypedExpr typedExpr;
1794
1795 CharBlock source;
1796
1797 std::variant<common::Indirection<CharLiteralConstantSubstring>,
1801 Add, Subtract, Concat, LT, LE, EQ, NE, GE, GT, AND, OR, EQV, NEQV,
1803 u;
1804};
1805
1806// R912 part-ref -> part-name [( section-subscript-list )] [image-selector]
1807struct PartRef {
1808 BOILERPLATE(PartRef);
1809 PartRef(Name &&n, std::list<SectionSubscript> &&ss,
1810 std::optional<ImageSelector> &&is)
1811 : name{std::move(n)}, subscripts(std::move(ss)),
1812 imageSelector{std::move(is)} {}
1813 Name name;
1814 std::list<SectionSubscript> subscripts;
1815 std::optional<ImageSelector> imageSelector;
1816};
1817
1818// R911 data-ref -> part-ref [% part-ref]...
1819struct DataRef {
1820 UNION_CLASS_BOILERPLATE(DataRef);
1821 explicit DataRef(std::list<PartRef> &&);
1822 std::variant<Name, common::Indirection<StructureComponent>,
1825 u;
1826};
1827
1828// R908 substring -> parent-string ( substring-range )
1829// R909 parent-string ->
1830// scalar-variable-name | array-element | coindexed-named-object |
1831// scalar-structure-component | scalar-char-literal-constant |
1832// scalar-named-constant
1833// Substrings of character literals have been factored out into their
1834// own productions so that they can't appear as designators in any context
1835// other than a primary expression.
1837 TUPLE_CLASS_BOILERPLATE(Substring);
1838 std::tuple<DataRef, SubstringRange> t;
1839};
1840
1842 TUPLE_CLASS_BOILERPLATE(CharLiteralConstantSubstring);
1843 std::tuple<CharLiteralConstant, SubstringRange> t;
1844};
1845
1846// substring%KIND/LEN type parameter inquiry for cases that could not be
1847// parsed as part-refs and fixed up afterwards. N.B. we only have to
1848// handle inquiries into designator-based substrings, not those based on
1849// char-literal-constants.
1851 CharBlock source;
1852 WRAPPER_CLASS_BOILERPLATE(SubstringInquiry, Substring);
1853};
1854
1855// R901 designator -> object-name | array-element | array-section |
1856// coindexed-named-object | complex-part-designator |
1857// structure-component | substring
1859 UNION_CLASS_BOILERPLATE(Designator);
1860 bool EndsInBareName() const;
1861 CharBlock source;
1862 std::variant<DataRef, Substring> u;
1863};
1864
1865// R902 variable -> designator | function-reference
1866struct Variable {
1867 UNION_CLASS_BOILERPLATE(Variable);
1868 mutable TypedExpr typedExpr;
1869 CharBlock GetSource() const;
1870 std::variant<common::Indirection<Designator>,
1872 u;
1873};
1874
1875// R904 logical-variable -> variable
1876// Appears only as part of scalar-logical-variable.
1877using ScalarLogicalVariable = Scalar<Logical<Variable>>;
1878
1879// R906 default-char-variable -> variable
1880// Appears only as part of scalar-default-char-variable.
1881using ScalarDefaultCharVariable = Scalar<DefaultChar<Variable>>;
1882
1883// R907 int-variable -> variable
1884// Appears only as part of scalar-int-variable.
1885using ScalarIntVariable = Scalar<Integer<Variable>>;
1886
1887// R913 structure-component -> data-ref
1888struct StructureComponent {
1889 BOILERPLATE(StructureComponent);
1890 StructureComponent(DataRef &&dr, Name &&n)
1891 : base{std::move(dr)}, component(std::move(n)) {}
1892 DataRef base;
1893 Name component;
1894};
1895
1896// R1039 proc-component-ref -> scalar-variable % procedure-component-name
1897// C1027 constrains the scalar-variable to be a data-ref without coindices.
1899 WRAPPER_CLASS_BOILERPLATE(ProcComponentRef, Scalar<StructureComponent>);
1900};
1901
1902// R914 coindexed-named-object -> data-ref
1903struct CoindexedNamedObject {
1904 BOILERPLATE(CoindexedNamedObject);
1905 CoindexedNamedObject(DataRef &&dr, ImageSelector &&is)
1906 : base{std::move(dr)}, imageSelector{std::move(is)} {}
1907 DataRef base;
1908 ImageSelector imageSelector;
1909};
1910
1911// R917 array-element -> data-ref
1912struct ArrayElement {
1913 BOILERPLATE(ArrayElement);
1914 ArrayElement(DataRef &&dr, std::list<SectionSubscript> &&ss)
1915 : base{std::move(dr)}, subscripts(std::move(ss)) {}
1916 Substring ConvertToSubstring();
1917 StructureConstructor ConvertToStructureConstructor(
1919 DataRef base;
1920 std::list<SectionSubscript> subscripts;
1921};
1922
1923// R933 allocate-object -> variable-name | structure-component
1925 UNION_CLASS_BOILERPLATE(AllocateObject);
1926 mutable TypedExpr typedExpr;
1927 std::variant<Name, StructureComponent> u;
1928};
1929
1930// R935 lower-bound-expr -> scalar-int-expr
1931// R936 upper-bound-expr -> scalar-int-expr
1932using BoundExpr = ScalarIntExpr;
1933
1934// R934 allocate-shape-spec -> [lower-bound-expr :] upper-bound-expr
1935// R938 allocate-coshape-spec -> [lower-bound-expr :] upper-bound-expr
1937 TUPLE_CLASS_BOILERPLATE(AllocateShapeSpec);
1938 std::tuple<std::optional<BoundExpr>, BoundExpr> t;
1939};
1940
1941using AllocateCoshapeSpec = AllocateShapeSpec;
1942
1943// R937 allocate-coarray-spec ->
1944// [allocate-coshape-spec-list ,] [lower-bound-expr :] *
1946 TUPLE_CLASS_BOILERPLATE(AllocateCoarraySpec);
1947 std::tuple<std::list<AllocateCoshapeSpec>, std::optional<BoundExpr>> t;
1948};
1949
1950// R932 allocation ->
1951// allocate-object [( allocate-shape-spec-list )]
1952// [lbracket allocate-coarray-spec rbracket]
1954 TUPLE_CLASS_BOILERPLATE(Allocation);
1955 std::tuple<AllocateObject, std::list<AllocateShapeSpec>,
1956 std::optional<AllocateCoarraySpec>>
1957 t;
1958};
1959
1960// R929 stat-variable -> scalar-int-variable
1961WRAPPER_CLASS(StatVariable, ScalarIntVariable);
1962
1963// R930 errmsg-variable -> scalar-default-char-variable
1964// R1207 iomsg-variable -> scalar-default-char-variable
1965WRAPPER_CLASS(MsgVariable, ScalarDefaultCharVariable);
1966
1967// R942 dealloc-opt -> STAT = stat-variable | ERRMSG = errmsg-variable
1968// R1165 sync-stat -> STAT = stat-variable | ERRMSG = errmsg-variable
1970 UNION_CLASS_BOILERPLATE(StatOrErrmsg);
1971 std::variant<StatVariable, MsgVariable> u;
1972};
1973
1974// R928 alloc-opt ->
1975// ERRMSG = errmsg-variable | MOLD = source-expr |
1976// SOURCE = source-expr | STAT = stat-variable |
1977// (CUDA) STREAM = scalar-int-expr
1978// PINNED = scalar-logical-variable
1979// R931 source-expr -> expr
1980struct AllocOpt {
1981 UNION_CLASS_BOILERPLATE(AllocOpt);
1982 WRAPPER_CLASS(Mold, common::Indirection<Expr>);
1983 WRAPPER_CLASS(Source, common::Indirection<Expr>);
1984 WRAPPER_CLASS(Stream, common::Indirection<ScalarIntExpr>);
1985 WRAPPER_CLASS(Pinned, common::Indirection<ScalarLogicalVariable>);
1986 std::variant<Mold, Source, StatOrErrmsg, Stream, Pinned> u;
1987};
1988
1989// R927 allocate-stmt ->
1990// ALLOCATE ( [type-spec ::] allocation-list [, alloc-opt-list] )
1992 TUPLE_CLASS_BOILERPLATE(AllocateStmt);
1993 std::tuple<std::optional<TypeSpec>, std::list<Allocation>,
1994 std::list<AllocOpt>>
1995 t;
1996};
1997
1998// R940 pointer-object ->
1999// variable-name | structure-component | proc-pointer-name
2001 UNION_CLASS_BOILERPLATE(PointerObject);
2002 mutable TypedExpr typedExpr;
2003 std::variant<Name, StructureComponent> u;
2004};
2005
2006// R939 nullify-stmt -> NULLIFY ( pointer-object-list )
2007WRAPPER_CLASS(NullifyStmt, std::list<PointerObject>);
2008
2009// R941 deallocate-stmt ->
2010// DEALLOCATE ( allocate-object-list [, dealloc-opt-list] )
2012 TUPLE_CLASS_BOILERPLATE(DeallocateStmt);
2013 std::tuple<std::list<AllocateObject>, std::list<StatOrErrmsg>> t;
2014};
2015
2016// R1032 assignment-stmt -> variable = expr
2018 TUPLE_CLASS_BOILERPLATE(AssignmentStmt);
2019 using TypedAssignment =
2021 mutable TypedAssignment typedAssignment;
2022 std::tuple<Variable, Expr> t;
2023};
2024
2025// R1035 bounds-spec -> lower-bound-expr :
2026WRAPPER_CLASS(BoundsSpec, BoundExpr);
2027
2028// R1036 bounds-remapping -> lower-bound-expr : upper-bound-expr
2030 TUPLE_CLASS_BOILERPLATE(BoundsRemapping);
2031 std::tuple<BoundExpr, BoundExpr> t;
2032};
2033
2034// R1033 pointer-assignment-stmt ->
2035// data-pointer-object [( bounds-spec-list )] => data-target |
2036// data-pointer-object ( bounds-remapping-list ) => data-target |
2037// proc-pointer-object => proc-target
2038// R1034 data-pointer-object ->
2039// variable-name | scalar-variable % data-pointer-component-name
2040// R1038 proc-pointer-object -> proc-pointer-name | proc-component-ref
2042 struct Bounds {
2043 UNION_CLASS_BOILERPLATE(Bounds);
2044 std::variant<std::list<BoundsRemapping>, std::list<BoundsSpec>> u;
2045 };
2046 TUPLE_CLASS_BOILERPLATE(PointerAssignmentStmt);
2047 mutable AssignmentStmt::TypedAssignment typedAssignment;
2048 std::tuple<DataRef, Bounds, Expr> t;
2049};
2050
2051// R1041 where-stmt -> WHERE ( mask-expr ) where-assignment-stmt
2052// R1045 where-assignment-stmt -> assignment-stmt
2053// R1046 mask-expr -> logical-expr
2055 TUPLE_CLASS_BOILERPLATE(WhereStmt);
2056 std::tuple<LogicalExpr, AssignmentStmt> t;
2057};
2058
2059// R1043 where-construct-stmt -> [where-construct-name :] WHERE ( mask-expr )
2061 TUPLE_CLASS_BOILERPLATE(WhereConstructStmt);
2062 std::tuple<std::optional<Name>, LogicalExpr> t;
2063};
2064
2065// R1044 where-body-construct ->
2066// where-assignment-stmt | where-stmt | where-construct
2068 UNION_CLASS_BOILERPLATE(WhereBodyConstruct);
2069 std::variant<Statement<AssignmentStmt>, Statement<WhereStmt>,
2071 u;
2072};
2073
2074// R1047 masked-elsewhere-stmt ->
2075// ELSEWHERE ( mask-expr ) [where-construct-name]
2077 TUPLE_CLASS_BOILERPLATE(MaskedElsewhereStmt);
2078 std::tuple<LogicalExpr, std::optional<Name>> t;
2079};
2080
2081// R1048 elsewhere-stmt -> ELSEWHERE [where-construct-name]
2082WRAPPER_CLASS(ElsewhereStmt, std::optional<Name>);
2083
2084// R1049 end-where-stmt -> END WHERE [where-construct-name]
2085WRAPPER_CLASS(EndWhereStmt, std::optional<Name>);
2086
2087// R1042 where-construct ->
2088// where-construct-stmt [where-body-construct]...
2089// [masked-elsewhere-stmt [where-body-construct]...]...
2090// [elsewhere-stmt [where-body-construct]...] end-where-stmt
2093 TUPLE_CLASS_BOILERPLATE(MaskedElsewhere);
2094 std::tuple<Statement<MaskedElsewhereStmt>, std::list<WhereBodyConstruct>> t;
2095 };
2096 struct Elsewhere {
2097 TUPLE_CLASS_BOILERPLATE(Elsewhere);
2098 std::tuple<Statement<ElsewhereStmt>, std::list<WhereBodyConstruct>> t;
2099 };
2100 TUPLE_CLASS_BOILERPLATE(WhereConstruct);
2101 std::tuple<Statement<WhereConstructStmt>, std::list<WhereBodyConstruct>,
2102 std::list<MaskedElsewhere>, std::optional<Elsewhere>,
2104 t;
2105};
2106
2107// R1051 forall-construct-stmt ->
2108// [forall-construct-name :] FORALL concurrent-header
2110 TUPLE_CLASS_BOILERPLATE(ForallConstructStmt);
2111 std::tuple<std::optional<Name>, common::Indirection<ConcurrentHeader>> t;
2112};
2113
2114// R1053 forall-assignment-stmt -> assignment-stmt | pointer-assignment-stmt
2116 UNION_CLASS_BOILERPLATE(ForallAssignmentStmt);
2117 std::variant<AssignmentStmt, PointerAssignmentStmt> u;
2118};
2119
2120// R1055 forall-stmt -> FORALL concurrent-header forall-assignment-stmt
2122 TUPLE_CLASS_BOILERPLATE(ForallStmt);
2123 std::tuple<common::Indirection<ConcurrentHeader>,
2125 t;
2126};
2127
2128// R1052 forall-body-construct ->
2129// forall-assignment-stmt | where-stmt | where-construct |
2130// forall-construct | forall-stmt
2132 UNION_CLASS_BOILERPLATE(ForallBodyConstruct);
2133 std::variant<Statement<ForallAssignmentStmt>, Statement<WhereStmt>,
2136 u;
2137};
2138
2139// R1054 end-forall-stmt -> END FORALL [forall-construct-name]
2140WRAPPER_CLASS(EndForallStmt, std::optional<Name>);
2141
2142// R1050 forall-construct ->
2143// forall-construct-stmt [forall-body-construct]... end-forall-stmt
2145 TUPLE_CLASS_BOILERPLATE(ForallConstruct);
2146 std::tuple<Statement<ForallConstructStmt>, std::list<ForallBodyConstruct>,
2148 t;
2149};
2150
2151// R1105 selector -> expr | variable
2152struct Selector {
2153 UNION_CLASS_BOILERPLATE(Selector);
2154 std::variant<Expr, Variable> u;
2155};
2156
2157// R1104 association -> associate-name => selector
2159 TUPLE_CLASS_BOILERPLATE(Association);
2160 std::tuple<Name, Selector> t;
2161};
2162
2163// R1103 associate-stmt ->
2164// [associate-construct-name :] ASSOCIATE ( association-list )
2166 TUPLE_CLASS_BOILERPLATE(AssociateStmt);
2167 std::tuple<std::optional<Name>, std::list<Association>> t;
2168};
2169
2170// R1106 end-associate-stmt -> END ASSOCIATE [associate-construct-name]
2171WRAPPER_CLASS(EndAssociateStmt, std::optional<Name>);
2172
2173// R1102 associate-construct -> associate-stmt block end-associate-stmt
2175 TUPLE_CLASS_BOILERPLATE(AssociateConstruct);
2176 std::tuple<Statement<AssociateStmt>, Block, Statement<EndAssociateStmt>> t;
2177};
2178
2179// R1108 block-stmt -> [block-construct-name :] BLOCK
2180WRAPPER_CLASS(BlockStmt, std::optional<Name>);
2181
2182// R1110 end-block-stmt -> END BLOCK [block-construct-name]
2183WRAPPER_CLASS(EndBlockStmt, std::optional<Name>);
2184
2185// R1109 block-specification-part ->
2186// [use-stmt]... [import-stmt]...
2187// [[declaration-construct]... specification-construct]
2188// N.B. Because BlockSpecificationPart just wraps the more general
2189// SpecificationPart, it can misrecognize an ImplicitPart as part of
2190// the BlockSpecificationPart during parsing, and we have to detect and
2191// flag such usage in semantics.
2192WRAPPER_CLASS(BlockSpecificationPart, SpecificationPart);
2193
2194// R1107 block-construct ->
2195// block-stmt [block-specification-part] block end-block-stmt
2197 TUPLE_CLASS_BOILERPLATE(BlockConstruct);
2198 std::tuple<Statement<BlockStmt>, BlockSpecificationPart, Block,
2200 t;
2201};
2202
2203// R1113 coarray-association -> codimension-decl => selector
2205 TUPLE_CLASS_BOILERPLATE(CoarrayAssociation);
2206 std::tuple<CodimensionDecl, Selector> t;
2207};
2208
2209// R1112 change-team-stmt ->
2210// [team-construct-name :] CHANGE TEAM
2211// ( team-value [, coarray-association-list] [, sync-stat-list] )
2213 TUPLE_CLASS_BOILERPLATE(ChangeTeamStmt);
2214 std::tuple<std::optional<Name>, TeamValue, std::list<CoarrayAssociation>,
2215 std::list<StatOrErrmsg>>
2216 t;
2217};
2218
2219// R1114 end-change-team-stmt ->
2220// END TEAM [( [sync-stat-list] )] [team-construct-name]
2222 TUPLE_CLASS_BOILERPLATE(EndChangeTeamStmt);
2223 std::tuple<std::list<StatOrErrmsg>, std::optional<Name>> t;
2224};
2225
2226// R1111 change-team-construct -> change-team-stmt block end-change-team-stmt
2228 TUPLE_CLASS_BOILERPLATE(ChangeTeamConstruct);
2229 std::tuple<Statement<ChangeTeamStmt>, Block, Statement<EndChangeTeamStmt>> t;
2230};
2231
2232// R1117 critical-stmt ->
2233// [critical-construct-name :] CRITICAL [( [sync-stat-list] )]
2235 TUPLE_CLASS_BOILERPLATE(CriticalStmt);
2236 std::tuple<std::optional<Name>, std::list<StatOrErrmsg>> t;
2237};
2238
2239// R1118 end-critical-stmt -> END CRITICAL [critical-construct-name]
2240WRAPPER_CLASS(EndCriticalStmt, std::optional<Name>);
2241
2242// R1116 critical-construct -> critical-stmt block end-critical-stmt
2244 TUPLE_CLASS_BOILERPLATE(CriticalConstruct);
2245 std::tuple<Statement<CriticalStmt>, Block, Statement<EndCriticalStmt>> t;
2246};
2247
2248// R1126 concurrent-control ->
2249// index-name = concurrent-limit : concurrent-limit [: concurrent-step]
2250// R1127 concurrent-limit -> scalar-int-expr
2251// R1128 concurrent-step -> scalar-int-expr
2253 TUPLE_CLASS_BOILERPLATE(ConcurrentControl);
2254 std::tuple<Name, ScalarIntExpr, ScalarIntExpr, std::optional<ScalarIntExpr>>
2255 t;
2256};
2257
2258// R1125 concurrent-header ->
2259// ( [integer-type-spec ::] concurrent-control-list
2260// [, scalar-mask-expr] )
2262 TUPLE_CLASS_BOILERPLATE(ConcurrentHeader);
2263 std::tuple<std::optional<IntegerTypeSpec>, std::list<ConcurrentControl>,
2264 std::optional<ScalarLogicalExpr>>
2265 t;
2266};
2267
2268// F'2023 R1131 reduce-operation -> reduction-operator
2269// CUF reduction-op -> reduction-operator
2270// OpenACC 3.3 2.5.15 reduction-operator ->
2271// + | * | .AND. | .OR. | .EQV. | .NEQV. |
2272// MAX | MIN | IAND | IOR | IEOR
2274 ENUM_CLASS(
2275 Operator, Plus, Multiply, Max, Min, Iand, Ior, Ieor, And, Or, Eqv, Neqv)
2276 WRAPPER_CLASS_BOILERPLATE(ReductionOperator, Operator);
2277 CharBlock source;
2278};
2279
2280// R1130 locality-spec ->
2281// LOCAL ( variable-name-list ) | LOCAL_INIT ( variable-name-list ) |
2282// REDUCE ( reduce-operation : variable-name-list ) |
2283// SHARED ( variable-name-list ) | DEFAULT ( NONE )
2285 UNION_CLASS_BOILERPLATE(LocalitySpec);
2286 WRAPPER_CLASS(Local, std::list<Name>);
2287 WRAPPER_CLASS(LocalInit, std::list<Name>);
2288 struct Reduce {
2289 TUPLE_CLASS_BOILERPLATE(Reduce);
2290 using Operator = ReductionOperator;
2291 std::tuple<Operator, std::list<Name>> t;
2292 };
2293 WRAPPER_CLASS(Shared, std::list<Name>);
2294 EMPTY_CLASS(DefaultNone);
2295 std::variant<Local, LocalInit, Reduce, Shared, DefaultNone> u;
2296};
2297
2298// R1123 loop-control ->
2299// [,] do-variable = scalar-int-expr , scalar-int-expr
2300// [, scalar-int-expr] |
2301// [,] WHILE ( scalar-logical-expr ) |
2302// [,] CONCURRENT concurrent-header concurrent-locality
2303// R1129 concurrent-locality -> [locality-spec]...
2305 UNION_CLASS_BOILERPLATE(LoopControl);
2306 struct Concurrent {
2307 TUPLE_CLASS_BOILERPLATE(Concurrent);
2308 std::tuple<ConcurrentHeader, std::list<LocalitySpec>> t;
2309 };
2311 std::variant<Bounds, ScalarLogicalExpr, Concurrent> u;
2312};
2313
2314// R1121 label-do-stmt -> [do-construct-name :] DO label [loop-control]
2315// A label-do-stmt with a do-construct-name is parsed as a non-label-do-stmt.
2317 TUPLE_CLASS_BOILERPLATE(LabelDoStmt);
2318 std::tuple<Label, std::optional<LoopControl>> t;
2319};
2320
2321// R1122 nonlabel-do-stmt -> [do-construct-name :] DO [loop-control]
2323 TUPLE_CLASS_BOILERPLATE(NonLabelDoStmt);
2324 std::tuple<std::optional<Name>, std::optional<Label>,
2325 std::optional<LoopControl>>
2326 t;
2327};
2328
2329// R1132 end-do-stmt -> END DO [do-construct-name]
2330WRAPPER_CLASS(EndDoStmt, std::optional<Name>);
2331
2332// R1131 end-do -> end-do-stmt | continue-stmt
2333
2334// R1119 do-construct -> do-stmt block end-do
2335// R1120 do-stmt -> nonlabel-do-stmt | label-do-stmt
2336// Deprecated, but supported: "label DO" loops ending on statements other
2337// than END DO and CONTINUE, and multiple "label DO" loops ending on the
2338// same label.
2340 TUPLE_CLASS_BOILERPLATE(DoConstruct);
2341 const std::optional<LoopControl> &GetLoopControl() const;
2342 bool IsDoNormal() const;
2343 bool IsDoWhile() const;
2344 bool IsDoConcurrent() const;
2345 std::tuple<Statement<NonLabelDoStmt>, Block, Statement<EndDoStmt>> t;
2346};
2347
2348// R1133 cycle-stmt -> CYCLE [do-construct-name]
2349WRAPPER_CLASS(CycleStmt, std::optional<Name>);
2350
2351// R1135 if-then-stmt -> [if-construct-name :] IF ( scalar-logical-expr ) THEN
2353 TUPLE_CLASS_BOILERPLATE(IfThenStmt);
2354 std::tuple<std::optional<Name>, ScalarLogicalExpr> t;
2355};
2356
2357// R1136 else-if-stmt ->
2358// ELSE IF ( scalar-logical-expr ) THEN [if-construct-name]
2360 TUPLE_CLASS_BOILERPLATE(ElseIfStmt);
2361 std::tuple<ScalarLogicalExpr, std::optional<Name>> t;
2362};
2363
2364// R1137 else-stmt -> ELSE [if-construct-name]
2365WRAPPER_CLASS(ElseStmt, std::optional<Name>);
2366
2367// R1138 end-if-stmt -> END IF [if-construct-name]
2368WRAPPER_CLASS(EndIfStmt, std::optional<Name>);
2369
2370// R1134 if-construct ->
2371// if-then-stmt block [else-if-stmt block]...
2372// [else-stmt block] end-if-stmt
2375 TUPLE_CLASS_BOILERPLATE(ElseIfBlock);
2376 std::tuple<Statement<ElseIfStmt>, Block> t;
2377 };
2378 struct ElseBlock {
2379 TUPLE_CLASS_BOILERPLATE(ElseBlock);
2380 std::tuple<Statement<ElseStmt>, Block> t;
2381 };
2382 TUPLE_CLASS_BOILERPLATE(IfConstruct);
2383 std::tuple<Statement<IfThenStmt>, Block, std::list<ElseIfBlock>,
2384 std::optional<ElseBlock>, Statement<EndIfStmt>>
2385 t;
2386};
2387
2388// R1139 if-stmt -> IF ( scalar-logical-expr ) action-stmt
2389struct IfStmt {
2390 TUPLE_CLASS_BOILERPLATE(IfStmt);
2391 std::tuple<ScalarLogicalExpr, UnlabeledStatement<ActionStmt>> t;
2392};
2393
2394// R1141 select-case-stmt -> [case-construct-name :] SELECT CASE ( case-expr )
2395// R1144 case-expr -> scalar-expr
2397 TUPLE_CLASS_BOILERPLATE(SelectCaseStmt);
2398 std::tuple<std::optional<Name>, Scalar<Expr>> t;
2399};
2400
2401// R1147 case-value -> scalar-constant-expr
2402using CaseValue = Scalar<ConstantExpr>;
2403
2404// R1146 case-value-range ->
2405// case-value | case-value : | : case-value | case-value : case-value
2407 UNION_CLASS_BOILERPLATE(CaseValueRange);
2408 struct Range {
2409 BOILERPLATE(Range);
2410 Range(std::optional<CaseValue> &&l, std::optional<CaseValue> &&u)
2411 : lower{std::move(l)}, upper{std::move(u)} {}
2412 std::optional<CaseValue> lower, upper; // not both missing
2413 };
2414 std::variant<CaseValue, Range> u;
2415};
2416
2417// R1145 case-selector -> ( case-value-range-list ) | DEFAULT
2418EMPTY_CLASS(Default);
2419
2421 UNION_CLASS_BOILERPLATE(CaseSelector);
2422 std::variant<std::list<CaseValueRange>, Default> u;
2423};
2424
2425// R1142 case-stmt -> CASE case-selector [case-construct-name]
2426struct CaseStmt {
2427 TUPLE_CLASS_BOILERPLATE(CaseStmt);
2428 std::tuple<CaseSelector, std::optional<Name>> t;
2429};
2430
2431// R1143 end-select-stmt -> END SELECT [case-construct-name]
2432// R1151 end-select-rank-stmt -> END SELECT [select-construct-name]
2433// R1155 end-select-type-stmt -> END SELECT [select-construct-name]
2434WRAPPER_CLASS(EndSelectStmt, std::optional<Name>);
2435
2436// R1140 case-construct ->
2437// select-case-stmt [case-stmt block]... end-select-stmt
2439 struct Case {
2440 TUPLE_CLASS_BOILERPLATE(Case);
2441 std::tuple<Statement<CaseStmt>, Block> t;
2442 };
2443 TUPLE_CLASS_BOILERPLATE(CaseConstruct);
2444 std::tuple<Statement<SelectCaseStmt>, std::list<Case>,
2446 t;
2447};
2448
2449// R1149 select-rank-stmt ->
2450// [select-construct-name :] SELECT RANK
2451// ( [associate-name =>] selector )
2453 TUPLE_CLASS_BOILERPLATE(SelectRankStmt);
2454 std::tuple<std::optional<Name>, std::optional<Name>, Selector> t;
2455};
2456
2457// R1150 select-rank-case-stmt ->
2458// RANK ( scalar-int-constant-expr ) [select-construct-name] |
2459// RANK ( * ) [select-construct-name] |
2460// RANK DEFAULT [select-construct-name]
2462 struct Rank {
2463 UNION_CLASS_BOILERPLATE(Rank);
2464 std::variant<ScalarIntConstantExpr, Star, Default> u;
2465 };
2466 TUPLE_CLASS_BOILERPLATE(SelectRankCaseStmt);
2467 std::tuple<Rank, std::optional<Name>> t;
2468};
2469
2470// R1148 select-rank-construct ->
2471// select-rank-stmt [select-rank-case-stmt block]...
2472// end-select-rank-stmt
2474 TUPLE_CLASS_BOILERPLATE(SelectRankConstruct);
2475 struct RankCase {
2476 TUPLE_CLASS_BOILERPLATE(RankCase);
2477 std::tuple<Statement<SelectRankCaseStmt>, Block> t;
2478 };
2479 std::tuple<Statement<SelectRankStmt>, std::list<RankCase>,
2481 t;
2482};
2483
2484// R1153 select-type-stmt ->
2485// [select-construct-name :] SELECT TYPE
2486// ( [associate-name =>] selector )
2488 TUPLE_CLASS_BOILERPLATE(SelectTypeStmt);
2489 std::tuple<std::optional<Name>, std::optional<Name>, Selector> t;
2490};
2491
2492// R1154 type-guard-stmt ->
2493// TYPE IS ( type-spec ) [select-construct-name] |
2494// CLASS IS ( derived-type-spec ) [select-construct-name] |
2495// CLASS DEFAULT [select-construct-name]
2497 struct Guard {
2498 UNION_CLASS_BOILERPLATE(Guard);
2499 std::variant<TypeSpec, DerivedTypeSpec, Default> u;
2500 };
2501 TUPLE_CLASS_BOILERPLATE(TypeGuardStmt);
2502 std::tuple<Guard, std::optional<Name>> t;
2503};
2504
2505// R1152 select-type-construct ->
2506// select-type-stmt [type-guard-stmt block]... end-select-type-stmt
2508 TUPLE_CLASS_BOILERPLATE(SelectTypeConstruct);
2509 struct TypeCase {
2510 TUPLE_CLASS_BOILERPLATE(TypeCase);
2511 std::tuple<Statement<TypeGuardStmt>, Block> t;
2512 };
2513 std::tuple<Statement<SelectTypeStmt>, std::list<TypeCase>,
2515 t;
2516};
2517
2518// R1156 exit-stmt -> EXIT [construct-name]
2519WRAPPER_CLASS(ExitStmt, std::optional<Name>);
2520
2521// R1157 goto-stmt -> GO TO label
2522WRAPPER_CLASS(GotoStmt, Label);
2523
2524// R1158 computed-goto-stmt -> GO TO ( label-list ) [,] scalar-int-expr
2526 TUPLE_CLASS_BOILERPLATE(ComputedGotoStmt);
2527 std::tuple<std::list<Label>, ScalarIntExpr> t;
2528};
2529
2530// R1162 stop-code -> scalar-default-char-expr | scalar-int-expr
2531// We can't distinguish character expressions from integer
2532// expressions during parsing, so we just parse an expr and
2533// check its type later.
2534WRAPPER_CLASS(StopCode, Scalar<Expr>);
2535
2536// R1160 stop-stmt -> STOP [stop-code] [, QUIET = scalar-logical-expr]
2537// R1161 error-stop-stmt ->
2538// ERROR STOP [stop-code] [, QUIET = scalar-logical-expr]
2539struct StopStmt {
2540 ENUM_CLASS(Kind, Stop, ErrorStop)
2541 TUPLE_CLASS_BOILERPLATE(StopStmt);
2542 std::tuple<Kind, std::optional<StopCode>, std::optional<ScalarLogicalExpr>> t;
2543};
2544
2545// F2023: R1166 notify-wait-stmt -> NOTIFY WAIT ( notify-variable [,
2546// event-wait-spec-list] )
2548 TUPLE_CLASS_BOILERPLATE(NotifyWaitStmt);
2549 std::tuple<Scalar<Variable>, std::list<EventWaitSpec>> t;
2550};
2551
2552// R1164 sync-all-stmt -> SYNC ALL [( [sync-stat-list] )]
2553WRAPPER_CLASS(SyncAllStmt, std::list<StatOrErrmsg>);
2554
2555// R1166 sync-images-stmt -> SYNC IMAGES ( image-set [, sync-stat-list] )
2556// R1167 image-set -> int-expr | *
2558 struct ImageSet {
2559 UNION_CLASS_BOILERPLATE(ImageSet);
2560 std::variant<IntExpr, Star> u;
2561 };
2562 TUPLE_CLASS_BOILERPLATE(SyncImagesStmt);
2563 std::tuple<ImageSet, std::list<StatOrErrmsg>> t;
2564};
2565
2566// R1168 sync-memory-stmt -> SYNC MEMORY [( [sync-stat-list] )]
2567WRAPPER_CLASS(SyncMemoryStmt, std::list<StatOrErrmsg>);
2568
2569// R1169 sync-team-stmt -> SYNC TEAM ( team-value [, sync-stat-list] )
2571 TUPLE_CLASS_BOILERPLATE(SyncTeamStmt);
2572 std::tuple<TeamValue, std::list<StatOrErrmsg>> t;
2573};
2574
2575// R1171 event-variable -> scalar-variable
2576using EventVariable = Scalar<Variable>;
2577
2578// R1170 event-post-stmt -> EVENT POST ( event-variable [, sync-stat-list] )
2580 TUPLE_CLASS_BOILERPLATE(EventPostStmt);
2581 std::tuple<EventVariable, std::list<StatOrErrmsg>> t;
2582};
2583
2584// R1173 event-wait-spec -> until-spec | sync-stat
2586 UNION_CLASS_BOILERPLATE(EventWaitSpec);
2587 std::variant<ScalarIntExpr, StatOrErrmsg> u;
2588};
2589
2590// R1172 event-wait-stmt ->
2591// EVENT WAIT ( event-variable [, event-wait-spec-list] )
2592// R1174 until-spec -> UNTIL_COUNT = scalar-int-expr
2594 TUPLE_CLASS_BOILERPLATE(EventWaitStmt);
2595 std::tuple<EventVariable, std::list<EventWaitSpec>> t;
2596};
2597
2598// R1177 team-variable -> scalar-variable
2599using TeamVariable = Scalar<Variable>;
2600
2601// R1175 form-team-stmt ->
2602// FORM TEAM ( team-number , team-variable [, form-team-spec-list] )
2603// R1176 team-number -> scalar-int-expr
2604// R1178 form-team-spec -> NEW_INDEX = scalar-int-expr | sync-stat
2607 UNION_CLASS_BOILERPLATE(FormTeamSpec);
2608 std::variant<ScalarIntExpr, StatOrErrmsg> u;
2609 };
2610 TUPLE_CLASS_BOILERPLATE(FormTeamStmt);
2611 std::tuple<ScalarIntExpr, TeamVariable, std::list<FormTeamSpec>> t;
2612};
2613
2614// R1182 lock-variable -> scalar-variable
2615using LockVariable = Scalar<Variable>;
2616
2617// R1179 lock-stmt -> LOCK ( lock-variable [, lock-stat-list] )
2618// R1180 lock-stat -> ACQUIRED_LOCK = scalar-logical-variable | sync-stat
2619struct LockStmt {
2620 struct LockStat {
2621 UNION_CLASS_BOILERPLATE(LockStat);
2622 std::variant<Scalar<Logical<Variable>>, StatOrErrmsg> u;
2623 };
2624 TUPLE_CLASS_BOILERPLATE(LockStmt);
2625 std::tuple<LockVariable, std::list<LockStat>> t;
2626};
2627
2628// R1181 unlock-stmt -> UNLOCK ( lock-variable [, sync-stat-list] )
2630 TUPLE_CLASS_BOILERPLATE(UnlockStmt);
2631 std::tuple<LockVariable, std::list<StatOrErrmsg>> t;
2632};
2633
2634// R1202 file-unit-number -> scalar-int-expr
2635WRAPPER_CLASS(FileUnitNumber, ScalarIntExpr);
2636
2637// R1201 io-unit -> file-unit-number | * | internal-file-variable
2638// R1203 internal-file-variable -> char-variable
2639// R905 char-variable -> variable
2640// When Variable appears as an IoUnit, it must be character of a default,
2641// ASCII, or Unicode kind; this constraint is not automatically checked.
2642// The parse is ambiguous and is repaired if necessary once the types of
2643// symbols are known.
2644struct IoUnit {
2645 UNION_CLASS_BOILERPLATE(IoUnit);
2646 std::variant<Variable, common::Indirection<Expr>, Star> u;
2647};
2648
2649// R1206 file-name-expr -> scalar-default-char-expr
2650using FileNameExpr = ScalarDefaultCharExpr;
2651
2652// R1205 connect-spec ->
2653// [UNIT =] file-unit-number | ACCESS = scalar-default-char-expr |
2654// ACTION = scalar-default-char-expr |
2655// ASYNCHRONOUS = scalar-default-char-expr |
2656// BLANK = scalar-default-char-expr |
2657// DECIMAL = scalar-default-char-expr |
2658// DELIM = scalar-default-char-expr |
2659// ENCODING = scalar-default-char-expr | ERR = label |
2660// FILE = file-name-expr | FORM = scalar-default-char-expr |
2661// IOMSG = iomsg-variable | IOSTAT = scalar-int-variable |
2662// NEWUNIT = scalar-int-variable | PAD = scalar-default-char-expr |
2663// POSITION = scalar-default-char-expr | RECL = scalar-int-expr |
2664// ROUND = scalar-default-char-expr | SIGN = scalar-default-char-expr |
2665// STATUS = scalar-default-char-expr
2666// @ | CARRIAGECONTROL = scalar-default-char-variable
2667// | CONVERT = scalar-default-char-variable
2668// | DISPOSE = scalar-default-char-variable
2669WRAPPER_CLASS(StatusExpr, ScalarDefaultCharExpr);
2670WRAPPER_CLASS(ErrLabel, Label);
2671
2673 UNION_CLASS_BOILERPLATE(ConnectSpec);
2674 struct CharExpr {
2675 ENUM_CLASS(Kind, Access, Action, Asynchronous, Blank, Decimal, Delim,
2676 Encoding, Form, Pad, Position, Round, Sign,
2677 /* extensions: */ Carriagecontrol, Convert, Dispose)
2678 TUPLE_CLASS_BOILERPLATE(CharExpr);
2679 std::tuple<Kind, ScalarDefaultCharExpr> t;
2680 };
2681 WRAPPER_CLASS(Recl, ScalarIntExpr);
2682 WRAPPER_CLASS(Newunit, ScalarIntVariable);
2683 std::variant<FileUnitNumber, FileNameExpr, CharExpr, MsgVariable,
2684 StatVariable, Recl, Newunit, ErrLabel, StatusExpr>
2685 u;
2686};
2687
2688// R1204 open-stmt -> OPEN ( connect-spec-list )
2689WRAPPER_CLASS(OpenStmt, std::list<ConnectSpec>);
2690
2691// R1208 close-stmt -> CLOSE ( close-spec-list )
2692// R1209 close-spec ->
2693// [UNIT =] file-unit-number | IOSTAT = scalar-int-variable |
2694// IOMSG = iomsg-variable | ERR = label |
2695// STATUS = scalar-default-char-expr
2697 struct CloseSpec {
2698 UNION_CLASS_BOILERPLATE(CloseSpec);
2699 std::variant<FileUnitNumber, StatVariable, MsgVariable, ErrLabel,
2700 StatusExpr>
2701 u;
2702 };
2703 WRAPPER_CLASS_BOILERPLATE(CloseStmt, std::list<CloseSpec>);
2704};
2705
2706// R1215 format -> default-char-expr | label | *
2707// deprecated(ASSIGN): | scalar-int-name
2708struct Format {
2709 UNION_CLASS_BOILERPLATE(Format);
2710 std::variant<Expr, Label, Star> u;
2711};
2712
2713// R1214 id-variable -> scalar-int-variable
2714WRAPPER_CLASS(IdVariable, ScalarIntVariable);
2715
2716// R1213 io-control-spec ->
2717// [UNIT =] io-unit | [FMT =] format | [NML =] namelist-group-name |
2718// ADVANCE = scalar-default-char-expr |
2719// ASYNCHRONOUS = scalar-default-char-constant-expr |
2720// BLANK = scalar-default-char-expr |
2721// DECIMAL = scalar-default-char-expr |
2722// DELIM = scalar-default-char-expr | END = label | EOR = label |
2723// ERR = label | ID = id-variable | IOMSG = iomsg-variable |
2724// IOSTAT = scalar-int-variable | PAD = scalar-default-char-expr |
2725// POS = scalar-int-expr | REC = scalar-int-expr |
2726// ROUND = scalar-default-char-expr | SIGN = scalar-default-char-expr |
2727// SIZE = scalar-int-variable
2728WRAPPER_CLASS(EndLabel, Label);
2729WRAPPER_CLASS(EorLabel, Label);
2731 UNION_CLASS_BOILERPLATE(IoControlSpec);
2732 struct CharExpr {
2733 ENUM_CLASS(Kind, Advance, Blank, Decimal, Delim, Pad, Round, Sign)
2734 TUPLE_CLASS_BOILERPLATE(CharExpr);
2735 std::tuple<Kind, ScalarDefaultCharExpr> t;
2736 };
2737 WRAPPER_CLASS(Asynchronous, ScalarDefaultCharConstantExpr);
2738 WRAPPER_CLASS(Pos, ScalarIntExpr);
2739 WRAPPER_CLASS(Rec, ScalarIntExpr);
2740 WRAPPER_CLASS(Size, ScalarIntVariable);
2741 std::variant<IoUnit, Format, Name, CharExpr, Asynchronous, EndLabel, EorLabel,
2742 ErrLabel, IdVariable, MsgVariable, StatVariable, Pos, Rec, Size>
2743 u;
2744};
2745
2746// R1216 input-item -> variable | io-implied-do
2748 UNION_CLASS_BOILERPLATE(InputItem);
2749 std::variant<Variable, common::Indirection<InputImpliedDo>> u;
2750};
2751
2752// R1210 read-stmt ->
2753// READ ( io-control-spec-list ) [input-item-list] |
2754// READ format [, input-item-list]
2755struct ReadStmt {
2756 BOILERPLATE(ReadStmt);
2757 ReadStmt(std::optional<IoUnit> &&i, std::optional<Format> &&f,
2758 std::list<IoControlSpec> &&cs, std::list<InputItem> &&its)
2759 : iounit{std::move(i)}, format{std::move(f)}, controls(std::move(cs)),
2760 items(std::move(its)) {}
2761 std::optional<IoUnit> iounit; // if first in controls without UNIT= &/or
2762 // followed by untagged format/namelist
2763 std::optional<Format> format; // if second in controls without FMT=/NML=, or
2764 // no (io-control-spec-list); might be
2765 // an untagged namelist group name
2766 std::list<IoControlSpec> controls;
2767 std::list<InputItem> items;
2768};
2769
2770// R1217 output-item -> expr | io-implied-do
2772 UNION_CLASS_BOILERPLATE(OutputItem);
2773 std::variant<Expr, common::Indirection<OutputImpliedDo>> u;
2774};
2775
2776// R1211 write-stmt -> WRITE ( io-control-spec-list ) [output-item-list]
2777struct WriteStmt {
2778 BOILERPLATE(WriteStmt);
2779 WriteStmt(std::optional<IoUnit> &&i, std::optional<Format> &&f,
2780 std::list<IoControlSpec> &&cs, std::list<OutputItem> &&its)
2781 : iounit{std::move(i)}, format{std::move(f)}, controls(std::move(cs)),
2782 items(std::move(its)) {}
2783 std::optional<IoUnit> iounit; // if first in controls without UNIT= &/or
2784 // followed by untagged format/namelist
2785 std::optional<Format> format; // if second in controls without FMT=/NML=;
2786 // might be an untagged namelist group, too
2787 std::list<IoControlSpec> controls;
2788 std::list<OutputItem> items;
2789};
2790
2791// R1212 print-stmt PRINT format [, output-item-list]
2793 TUPLE_CLASS_BOILERPLATE(PrintStmt);
2794 std::tuple<Format, std::list<OutputItem>> t;
2795};
2796
2797// R1220 io-implied-do-control ->
2798// do-variable = scalar-int-expr , scalar-int-expr [, scalar-int-expr]
2799using IoImpliedDoControl = LoopBounds<DoVariable, ScalarIntExpr>;
2800
2801// R1218 io-implied-do -> ( io-implied-do-object-list , io-implied-do-control )
2802// R1219 io-implied-do-object -> input-item | output-item
2804 TUPLE_CLASS_BOILERPLATE(InputImpliedDo);
2805 std::tuple<std::list<InputItem>, IoImpliedDoControl> t;
2806};
2807
2809 TUPLE_CLASS_BOILERPLATE(OutputImpliedDo);
2810 std::tuple<std::list<OutputItem>, IoImpliedDoControl> t;
2811};
2812
2813// R1223 wait-spec ->
2814// [UNIT =] file-unit-number | END = label | EOR = label | ERR = label |
2815// ID = scalar-int-expr | IOMSG = iomsg-variable |
2816// IOSTAT = scalar-int-variable
2817WRAPPER_CLASS(IdExpr, ScalarIntExpr);
2818struct WaitSpec {
2819 UNION_CLASS_BOILERPLATE(WaitSpec);
2820 std::variant<FileUnitNumber, EndLabel, EorLabel, ErrLabel, IdExpr,
2821 MsgVariable, StatVariable>
2822 u;
2823};
2824
2825// R1222 wait-stmt -> WAIT ( wait-spec-list )
2826WRAPPER_CLASS(WaitStmt, std::list<WaitSpec>);
2827
2828// R1227 position-spec ->
2829// [UNIT =] file-unit-number | IOMSG = iomsg-variable |
2830// IOSTAT = scalar-int-variable | ERR = label
2831// R1229 flush-spec ->
2832// [UNIT =] file-unit-number | IOSTAT = scalar-int-variable |
2833// IOMSG = iomsg-variable | ERR = label
2835 UNION_CLASS_BOILERPLATE(PositionOrFlushSpec);
2836 std::variant<FileUnitNumber, MsgVariable, StatVariable, ErrLabel> u;
2837};
2838
2839// R1224 backspace-stmt ->
2840// BACKSPACE file-unit-number | BACKSPACE ( position-spec-list )
2841WRAPPER_CLASS(BackspaceStmt, std::list<PositionOrFlushSpec>);
2842
2843// R1225 endfile-stmt ->
2844// ENDFILE file-unit-number | ENDFILE ( position-spec-list )
2845WRAPPER_CLASS(EndfileStmt, std::list<PositionOrFlushSpec>);
2846
2847// R1226 rewind-stmt -> REWIND file-unit-number | REWIND ( position-spec-list )
2848WRAPPER_CLASS(RewindStmt, std::list<PositionOrFlushSpec>);
2849
2850// R1228 flush-stmt -> FLUSH file-unit-number | FLUSH ( flush-spec-list )
2851WRAPPER_CLASS(FlushStmt, std::list<PositionOrFlushSpec>);
2852
2853// R1231 inquire-spec ->
2854// [UNIT =] file-unit-number | FILE = file-name-expr |
2855// ACCESS = scalar-default-char-variable |
2856// ACTION = scalar-default-char-variable |
2857// ASYNCHRONOUS = scalar-default-char-variable |
2858// BLANK = scalar-default-char-variable |
2859// DECIMAL = scalar-default-char-variable |
2860// DELIM = scalar-default-char-variable |
2861// DIRECT = scalar-default-char-variable |
2862// ENCODING = scalar-default-char-variable |
2863// ERR = label | EXIST = scalar-logical-variable |
2864// FORM = scalar-default-char-variable |
2865// FORMATTED = scalar-default-char-variable |
2866// ID = scalar-int-expr | IOMSG = iomsg-variable |
2867// IOSTAT = scalar-int-variable |
2868// NAME = scalar-default-char-variable |
2869// NAMED = scalar-logical-variable |
2870// NEXTREC = scalar-int-variable | NUMBER = scalar-int-variable |
2871// OPENED = scalar-logical-variable |
2872// PAD = scalar-default-char-variable |
2873// PENDING = scalar-logical-variable | POS = scalar-int-variable |
2874// POSITION = scalar-default-char-variable |
2875// READ = scalar-default-char-variable |
2876// READWRITE = scalar-default-char-variable |
2877// RECL = scalar-int-variable | ROUND = scalar-default-char-variable |
2878// SEQUENTIAL = scalar-default-char-variable |
2879// SIGN = scalar-default-char-variable |
2880// SIZE = scalar-int-variable |
2881// STREAM = scalar-default-char-variable |
2882// STATUS = scalar-default-char-variable |
2883// UNFORMATTED = scalar-default-char-variable |
2884// WRITE = scalar-default-char-variable
2885// @ | CARRIAGECONTROL = scalar-default-char-variable
2886// | CONVERT = scalar-default-char-variable
2887// | DISPOSE = scalar-default-char-variable
2889 UNION_CLASS_BOILERPLATE(InquireSpec);
2890 struct CharVar {
2891 ENUM_CLASS(Kind, Access, Action, Asynchronous, Blank, Decimal, Delim,
2892 Direct, Encoding, Form, Formatted, Iomsg, Name, Pad, Position, Read,
2893 Readwrite, Round, Sequential, Sign, Stream, Status, Unformatted, Write,
2894 /* extensions: */ Carriagecontrol, Convert, Dispose)
2895 TUPLE_CLASS_BOILERPLATE(CharVar);
2896 std::tuple<Kind, ScalarDefaultCharVariable> t;
2897 };
2898 struct IntVar {
2899 ENUM_CLASS(Kind, Iostat, Nextrec, Number, Pos, Recl, Size)
2900 TUPLE_CLASS_BOILERPLATE(IntVar);
2901 std::tuple<Kind, ScalarIntVariable> t;
2902 };
2903 struct LogVar {
2904 ENUM_CLASS(Kind, Exist, Named, Opened, Pending)
2905 TUPLE_CLASS_BOILERPLATE(LogVar);
2906 std::tuple<Kind, Scalar<Logical<Variable>>> t;
2907 };
2908 std::variant<FileUnitNumber, FileNameExpr, CharVar, IntVar, LogVar, IdExpr,
2909 ErrLabel>
2910 u;
2911};
2912
2913// R1230 inquire-stmt ->
2914// INQUIRE ( inquire-spec-list ) |
2915// INQUIRE ( IOLENGTH = scalar-int-variable ) output-item-list
2917 UNION_CLASS_BOILERPLATE(InquireStmt);
2918 struct Iolength {
2919 TUPLE_CLASS_BOILERPLATE(Iolength);
2920 std::tuple<ScalarIntVariable, std::list<OutputItem>> t;
2921 };
2922 std::variant<std::list<InquireSpec>, Iolength> u;
2923};
2924
2925// R1301 format-stmt -> FORMAT format-specification
2926WRAPPER_CLASS(FormatStmt, format::FormatSpecification);
2927
2928// R1402 program-stmt -> PROGRAM program-name
2929WRAPPER_CLASS(ProgramStmt, Name);
2930
2931// R1403 end-program-stmt -> END [PROGRAM [program-name]]
2932WRAPPER_CLASS(EndProgramStmt, std::optional<Name>);
2933
2934// R1401 main-program ->
2935// [program-stmt] [specification-part] [execution-part]
2936// [internal-subprogram-part] end-program-stmt
2938 TUPLE_CLASS_BOILERPLATE(MainProgram);
2939 std::tuple<std::optional<Statement<ProgramStmt>>, SpecificationPart,
2940 ExecutionPart, std::optional<InternalSubprogramPart>,
2942 t;
2943};
2944
2945// R1405 module-stmt -> MODULE module-name
2946WRAPPER_CLASS(ModuleStmt, Name);
2947
2948// R1408 module-subprogram ->
2949// function-subprogram | subroutine-subprogram |
2950// separate-module-subprogram
2952 UNION_CLASS_BOILERPLATE(ModuleSubprogram);
2953 std::variant<common::Indirection<FunctionSubprogram>,
2957 u;
2958};
2959
2960// R1407 module-subprogram-part -> contains-stmt [module-subprogram]...
2962 TUPLE_CLASS_BOILERPLATE(ModuleSubprogramPart);
2963 std::tuple<Statement<ContainsStmt>, std::list<ModuleSubprogram>> t;
2964};
2965
2966// R1406 end-module-stmt -> END [MODULE [module-name]]
2967WRAPPER_CLASS(EndModuleStmt, std::optional<Name>);
2968
2969// R1404 module ->
2970// module-stmt [specification-part] [module-subprogram-part]
2971// end-module-stmt
2972struct Module {
2973 TUPLE_CLASS_BOILERPLATE(Module);
2974 std::tuple<Statement<ModuleStmt>, SpecificationPart,
2975 std::optional<ModuleSubprogramPart>, Statement<EndModuleStmt>>
2976 t;
2977};
2978
2979// R1411 rename ->
2980// local-name => use-name |
2981// OPERATOR ( local-defined-operator ) =>
2982// OPERATOR ( use-defined-operator )
2983struct Rename {
2984 UNION_CLASS_BOILERPLATE(Rename);
2985 struct Names {
2986 TUPLE_CLASS_BOILERPLATE(Names);
2987 std::tuple<Name, Name> t;
2988 };
2989 struct Operators {
2990 TUPLE_CLASS_BOILERPLATE(Operators);
2991 std::tuple<DefinedOpName, DefinedOpName> t;
2992 };
2993 std::variant<Names, Operators> u;
2994};
2995
2996// R1418 parent-identifier -> ancestor-module-name [: parent-submodule-name]
2998 TUPLE_CLASS_BOILERPLATE(ParentIdentifier);
2999 std::tuple<Name, std::optional<Name>> t;
3000};
3001
3002// R1417 submodule-stmt -> SUBMODULE ( parent-identifier ) submodule-name
3004 TUPLE_CLASS_BOILERPLATE(SubmoduleStmt);
3005 std::tuple<ParentIdentifier, Name> t;
3006};
3007
3008// R1419 end-submodule-stmt -> END [SUBMODULE [submodule-name]]
3009WRAPPER_CLASS(EndSubmoduleStmt, std::optional<Name>);
3010
3011// R1416 submodule ->
3012// submodule-stmt [specification-part] [module-subprogram-part]
3013// end-submodule-stmt
3015 TUPLE_CLASS_BOILERPLATE(Submodule);
3016 std::tuple<Statement<SubmoduleStmt>, SpecificationPart,
3017 std::optional<ModuleSubprogramPart>, Statement<EndSubmoduleStmt>>
3018 t;
3019};
3020
3021// R1421 block-data-stmt -> BLOCK DATA [block-data-name]
3022WRAPPER_CLASS(BlockDataStmt, std::optional<Name>);
3023
3024// R1422 end-block-data-stmt -> END [BLOCK DATA [block-data-name]]
3025WRAPPER_CLASS(EndBlockDataStmt, std::optional<Name>);
3026
3027// R1420 block-data -> block-data-stmt [specification-part] end-block-data-stmt
3029 TUPLE_CLASS_BOILERPLATE(BlockData);
3030 std::tuple<Statement<BlockDataStmt>, SpecificationPart,
3032 t;
3033};
3034
3035// R1508 generic-spec ->
3036// generic-name | OPERATOR ( defined-operator ) |
3037// ASSIGNMENT ( = ) | defined-io-generic-spec
3038// R1509 defined-io-generic-spec ->
3039// READ ( FORMATTED ) | READ ( UNFORMATTED ) |
3040// WRITE ( FORMATTED ) | WRITE ( UNFORMATTED )
3042 UNION_CLASS_BOILERPLATE(GenericSpec);
3043 EMPTY_CLASS(Assignment);
3044 EMPTY_CLASS(ReadFormatted);
3045 EMPTY_CLASS(ReadUnformatted);
3046 EMPTY_CLASS(WriteFormatted);
3047 EMPTY_CLASS(WriteUnformatted);
3048 CharBlock source;
3049 std::variant<Name, DefinedOperator, Assignment, ReadFormatted,
3050 ReadUnformatted, WriteFormatted, WriteUnformatted>
3051 u;
3052};
3053
3054// R1510 generic-stmt ->
3055// GENERIC [, access-spec] :: generic-spec => specific-procedure-list
3057 TUPLE_CLASS_BOILERPLATE(GenericStmt);
3058 std::tuple<std::optional<AccessSpec>, GenericSpec, std::list<Name>> t;
3059};
3060
3061// R1503 interface-stmt -> INTERFACE [generic-spec] | ABSTRACT INTERFACE
3062struct InterfaceStmt {
3063 UNION_CLASS_BOILERPLATE(InterfaceStmt);
3064 // Workaround for clang with libstc++10 bug
3065 InterfaceStmt(Abstract x) : u{x} {}
3066
3067 std::variant<std::optional<GenericSpec>, Abstract> u;
3068};
3069
3070// R1412 only -> generic-spec | only-use-name | rename
3071// R1413 only-use-name -> use-name
3072struct Only {
3073 UNION_CLASS_BOILERPLATE(Only);
3074 std::variant<common::Indirection<GenericSpec>, Name, Rename> u;
3075};
3076
3077// R1409 use-stmt ->
3078// USE [[, module-nature] ::] module-name [, rename-list] |
3079// USE [[, module-nature] ::] module-name , ONLY : [only-list]
3080// R1410 module-nature -> INTRINSIC | NON_INTRINSIC
3081struct UseStmt {
3082 BOILERPLATE(UseStmt);
3083 ENUM_CLASS(ModuleNature, Intrinsic, Non_Intrinsic) // R1410
3084 template <typename A>
3085 UseStmt(std::optional<ModuleNature> &&nat, Name &&n, std::list<A> &&x)
3086 : nature(std::move(nat)), moduleName(std::move(n)), u(std::move(x)) {}
3087 std::optional<ModuleNature> nature;
3088 Name moduleName;
3089 std::variant<std::list<Rename>, std::list<Only>> u;
3090};
3091
3092// R1514 proc-attr-spec ->
3093// access-spec | proc-language-binding-spec | INTENT ( intent-spec ) |
3094// OPTIONAL | POINTER | PROTECTED | SAVE
3096 UNION_CLASS_BOILERPLATE(ProcAttrSpec);
3097 std::variant<AccessSpec, LanguageBindingSpec, IntentSpec, Optional, Pointer,
3098 Protected, Save>
3099 u;
3100};
3101
3102// R1512 procedure-declaration-stmt ->
3103// PROCEDURE ( [proc-interface] ) [[, proc-attr-spec]... ::]
3104// proc-decl-list
3106 TUPLE_CLASS_BOILERPLATE(ProcedureDeclarationStmt);
3107 std::tuple<std::optional<ProcInterface>, std::list<ProcAttrSpec>,
3108 std::list<ProcDecl>>
3109 t;
3110};
3111
3112// R1527 prefix-spec ->
3113// declaration-type-spec | ELEMENTAL | IMPURE | MODULE |
3114// NON_RECURSIVE | PURE | RECURSIVE |
3115// (CUDA) ATTRIBUTES ( (DEVICE | GLOBAL | GRID_GLOBAL | HOST)... )
3116// LAUNCH_BOUNDS(expr-list) | CLUSTER_DIMS(expr-list)
3118 UNION_CLASS_BOILERPLATE(PrefixSpec);
3119 EMPTY_CLASS(Elemental);
3120 EMPTY_CLASS(Impure);
3121 EMPTY_CLASS(Module);
3122 EMPTY_CLASS(Non_Recursive);
3123 EMPTY_CLASS(Pure);
3124 EMPTY_CLASS(Recursive);
3125 WRAPPER_CLASS(Attributes, std::list<common::CUDASubprogramAttrs>);
3126 WRAPPER_CLASS(Launch_Bounds, std::list<ScalarIntConstantExpr>);
3127 WRAPPER_CLASS(Cluster_Dims, std::list<ScalarIntConstantExpr>);
3128 std::variant<DeclarationTypeSpec, Elemental, Impure, Module, Non_Recursive,
3129 Pure, Recursive, Attributes, Launch_Bounds, Cluster_Dims>
3130 u;
3131};
3132
3133// R1532 suffix ->
3134// proc-language-binding-spec [RESULT ( result-name )] |
3135// RESULT ( result-name ) [proc-language-binding-spec]
3136struct Suffix {
3137 BOILERPLATE(Suffix);
3138 Suffix(LanguageBindingSpec &&lbs, std::optional<Name> &&rn)
3139 : binding(std::move(lbs)), resultName(std::move(rn)) {}
3140 Suffix(Name &&rn, std::optional<LanguageBindingSpec> &&lbs)
3141 : binding(std::move(lbs)), resultName(std::move(rn)) {}
3142 std::optional<LanguageBindingSpec> binding;
3143 std::optional<Name> resultName;
3144};
3145
3146// R1530 function-stmt ->
3147// [prefix] FUNCTION function-name ( [dummy-arg-name-list] ) [suffix]
3148// R1526 prefix -> prefix-spec [prefix-spec]...
3149// R1531 dummy-arg-name -> name
3151 TUPLE_CLASS_BOILERPLATE(FunctionStmt);
3152 std::tuple<std::list<PrefixSpec>, Name, std::list<Name>,
3153 std::optional<Suffix>>
3154 t;
3155};
3156
3157// R1533 end-function-stmt -> END [FUNCTION [function-name]]
3158WRAPPER_CLASS(EndFunctionStmt, std::optional<Name>);
3159
3160// R1536 dummy-arg -> dummy-arg-name | *
3161struct DummyArg {
3162 UNION_CLASS_BOILERPLATE(DummyArg);
3163 std::variant<Name, Star> u;
3164};
3165
3166// R1535 subroutine-stmt ->
3167// [prefix] SUBROUTINE subroutine-name [( [dummy-arg-list] )
3168// [proc-language-binding-spec]]
3170 TUPLE_CLASS_BOILERPLATE(SubroutineStmt);
3171 std::tuple<std::list<PrefixSpec>, Name, std::list<DummyArg>,
3172 std::optional<LanguageBindingSpec>>
3173 t;
3174};
3175
3176// R1537 end-subroutine-stmt -> END [SUBROUTINE [subroutine-name]]
3177WRAPPER_CLASS(EndSubroutineStmt, std::optional<Name>);
3178
3179// R1505 interface-body ->
3180// function-stmt [specification-part] end-function-stmt |
3181// subroutine-stmt [specification-part] end-subroutine-stmt
3183 UNION_CLASS_BOILERPLATE(InterfaceBody);
3184 struct Function {
3185 TUPLE_CLASS_BOILERPLATE(Function);
3186 std::tuple<Statement<FunctionStmt>, common::Indirection<SpecificationPart>,
3188 t;
3189 };
3190 struct Subroutine {
3191 TUPLE_CLASS_BOILERPLATE(Subroutine);
3192 std::tuple<Statement<SubroutineStmt>,
3194 t;
3195 };
3196 std::variant<Function, Subroutine> u;
3197};
3198
3199// R1506 procedure-stmt -> [MODULE] PROCEDURE [::] specific-procedure-list
3201 ENUM_CLASS(Kind, ModuleProcedure, Procedure)
3202 TUPLE_CLASS_BOILERPLATE(ProcedureStmt);
3203 std::tuple<Kind, std::list<Name>> t;
3204};
3205
3206// R1502 interface-specification -> interface-body | procedure-stmt
3208 UNION_CLASS_BOILERPLATE(InterfaceSpecification);
3209 std::variant<InterfaceBody, Statement<ProcedureStmt>> u;
3210};
3211
3212// R1504 end-interface-stmt -> END INTERFACE [generic-spec]
3213WRAPPER_CLASS(EndInterfaceStmt, std::optional<GenericSpec>);
3214
3215// R1501 interface-block ->
3216// interface-stmt [interface-specification]... end-interface-stmt
3218 TUPLE_CLASS_BOILERPLATE(InterfaceBlock);
3219 std::tuple<Statement<InterfaceStmt>, std::list<InterfaceSpecification>,
3221 t;
3222};
3223
3224// R1511 external-stmt -> EXTERNAL [::] external-name-list
3225WRAPPER_CLASS(ExternalStmt, std::list<Name>);
3226
3227// R1519 intrinsic-stmt -> INTRINSIC [::] intrinsic-procedure-name-list
3228WRAPPER_CLASS(IntrinsicStmt, std::list<Name>);
3229
3230// R1522 procedure-designator ->
3231// procedure-name | proc-component-ref | data-ref % binding-name
3233 UNION_CLASS_BOILERPLATE(ProcedureDesignator);
3234 std::variant<Name, ProcComponentRef> u;
3235};
3236
3237// R1525 alt-return-spec -> * label
3238WRAPPER_CLASS(AltReturnSpec, Label);
3239
3240// R1524 actual-arg ->
3241// expr | variable | procedure-name | proc-component-ref |
3242// alt-return-spec
3243struct ActualArg {
3244 WRAPPER_CLASS(PercentRef, Expr); // %REF(x) extension
3245 WRAPPER_CLASS(PercentVal, Expr); // %VAL(x) extension
3246 UNION_CLASS_BOILERPLATE(ActualArg);
3247 ActualArg(Expr &&x) : u{common::Indirection<Expr>(std::move(x))} {}
3248 std::variant<common::Indirection<Expr>, AltReturnSpec, PercentRef, PercentVal>
3249 u;
3250};
3251
3252// R1523 actual-arg-spec -> [keyword =] actual-arg
3254 TUPLE_CLASS_BOILERPLATE(ActualArgSpec);
3255 std::tuple<std::optional<Keyword>, ActualArg> t;
3256};
3257
3258// R1520 function-reference -> procedure-designator
3259// ( [actual-arg-spec-list] )
3260struct Call {
3261 TUPLE_CLASS_BOILERPLATE(Call);
3262 std::tuple<ProcedureDesignator, std::list<ActualArgSpec>> t;
3263};
3264
3266 WRAPPER_CLASS_BOILERPLATE(FunctionReference, Call);
3267 CharBlock source;
3268 Designator ConvertToArrayElementRef();
3269 StructureConstructor ConvertToStructureConstructor(
3271};
3272
3273// R1521 call-stmt -> CALL procedure-designator [ chevrons ]
3274// [( [actual-arg-spec-list] )]
3275// (CUDA) chevrons -> <<< * | scalar-expr, scalar-expr [,
3276// scalar-int-expr [, scalar-int-expr ] ] >>>
3277struct CallStmt {
3278 BOILERPLATE(CallStmt);
3279 WRAPPER_CLASS(StarOrExpr, std::optional<ScalarExpr>);
3280 struct Chevrons {
3281 TUPLE_CLASS_BOILERPLATE(Chevrons);
3282 std::tuple<StarOrExpr, ScalarExpr, std::optional<ScalarIntExpr>,
3283 std::optional<ScalarIntExpr>>
3284 t;
3285 };
3286 explicit CallStmt(ProcedureDesignator &&pd, std::optional<Chevrons> &&ch,
3287 std::list<ActualArgSpec> &&args)
3288 : call{std::move(pd), std::move(args)}, chevrons{std::move(ch)} {}
3289 Call call;
3290 std::optional<Chevrons> chevrons;
3291 CharBlock source;
3293 typedCall; // filled by semantics
3294};
3295
3296// R1529 function-subprogram ->
3297// function-stmt [specification-part] [execution-part]
3298// [internal-subprogram-part] end-function-stmt
3300 TUPLE_CLASS_BOILERPLATE(FunctionSubprogram);
3301 std::tuple<Statement<FunctionStmt>, SpecificationPart, ExecutionPart,
3302 std::optional<InternalSubprogramPart>, Statement<EndFunctionStmt>>
3303 t;
3304};
3305
3306// R1534 subroutine-subprogram ->
3307// subroutine-stmt [specification-part] [execution-part]
3308// [internal-subprogram-part] end-subroutine-stmt
3310 TUPLE_CLASS_BOILERPLATE(SubroutineSubprogram);
3311 std::tuple<Statement<SubroutineStmt>, SpecificationPart, ExecutionPart,
3312 std::optional<InternalSubprogramPart>, Statement<EndSubroutineStmt>>
3313 t;
3314};
3315
3316// R1539 mp-subprogram-stmt -> MODULE PROCEDURE procedure-name
3317WRAPPER_CLASS(MpSubprogramStmt, Name);
3318
3319// R1540 end-mp-subprogram-stmt -> END [PROCEDURE [procedure-name]]
3320WRAPPER_CLASS(EndMpSubprogramStmt, std::optional<Name>);
3321
3322// R1538 separate-module-subprogram ->
3323// mp-subprogram-stmt [specification-part] [execution-part]
3324// [internal-subprogram-part] end-mp-subprogram-stmt
3326 TUPLE_CLASS_BOILERPLATE(SeparateModuleSubprogram);
3327 std::tuple<Statement<MpSubprogramStmt>, SpecificationPart, ExecutionPart,
3328 std::optional<InternalSubprogramPart>, Statement<EndMpSubprogramStmt>>
3329 t;
3330};
3331
3332// R1541 entry-stmt -> ENTRY entry-name [( [dummy-arg-list] ) [suffix]]
3334 TUPLE_CLASS_BOILERPLATE(EntryStmt);
3335 std::tuple<Name, std::list<DummyArg>, std::optional<Suffix>> t;
3336};
3337
3338// R1542 return-stmt -> RETURN [scalar-int-expr]
3339WRAPPER_CLASS(ReturnStmt, std::optional<ScalarIntExpr>);
3340
3341// R1544 stmt-function-stmt ->
3342// function-name ( [dummy-arg-name-list] ) = scalar-expr
3344 TUPLE_CLASS_BOILERPLATE(StmtFunctionStmt);
3345 std::tuple<Name, std::list<Name>, Scalar<Expr>> t;
3346 Statement<ActionStmt> ConvertToAssignment();
3347};
3348
3349// Compiler directives
3350// !DIR$ IGNORE_TKR [ [(tkrdmac...)] name ]...
3351// !DIR$ LOOP COUNT (n1[, n2]...)
3352// !DIR$ name[=value] [, name[=value]]... = can be :
3353// !DIR$ UNROLL [N]
3354// !DIR$ UNROLL_AND_JAM [N]
3355// !DIR$ NOVECTOR
3356// !DIR$ NOUNROLL
3357// !DIR$ NOUNROLL_AND_JAM
3358// !DIR$ <anything else>
3360 UNION_CLASS_BOILERPLATE(CompilerDirective);
3361 struct IgnoreTKR {
3362 TUPLE_CLASS_BOILERPLATE(IgnoreTKR);
3363 std::tuple<std::optional<std::list<const char *>>, Name> t;
3364 };
3365 struct LoopCount {
3366 WRAPPER_CLASS_BOILERPLATE(LoopCount, std::list<std::uint64_t>);
3367 };
3369 TUPLE_CLASS_BOILERPLATE(AssumeAligned);
3370 std::tuple<common::Indirection<Designator>, uint64_t> t;
3371 };
3372 EMPTY_CLASS(VectorAlways);
3373 struct NameValue {
3374 TUPLE_CLASS_BOILERPLATE(NameValue);
3375 std::tuple<Name, std::optional<std::uint64_t>> t;
3376 };
3377 struct Unroll {
3378 WRAPPER_CLASS_BOILERPLATE(Unroll, std::optional<std::uint64_t>);
3379 };
3381 WRAPPER_CLASS_BOILERPLATE(UnrollAndJam, std::optional<std::uint64_t>);
3382 };
3383 EMPTY_CLASS(NoVector);
3384 EMPTY_CLASS(NoUnroll);
3385 EMPTY_CLASS(NoUnrollAndJam);
3386 EMPTY_CLASS(Unrecognized);
3387 CharBlock source;
3388 std::variant<std::list<IgnoreTKR>, LoopCount, std::list<AssumeAligned>,
3389 VectorAlways, std::list<NameValue>, Unroll, UnrollAndJam, Unrecognized,
3390 NoVector, NoUnroll, NoUnrollAndJam>
3391 u;
3392};
3393
3394// (CUDA) ATTRIBUTE(attribute) [::] name-list
3396 TUPLE_CLASS_BOILERPLATE(CUDAAttributesStmt);
3397 std::tuple<common::CUDADataAttr, std::list<Name>> t;
3398};
3399
3400// Legacy extensions
3402 TUPLE_CLASS_BOILERPLATE(BasedPointer);
3403 std::tuple<ObjectName, ObjectName, std::optional<ArraySpec>> t;
3404};
3405WRAPPER_CLASS(BasedPointerStmt, std::list<BasedPointer>);
3406
3407struct Union;
3408struct StructureDef;
3409
3411 UNION_CLASS_BOILERPLATE(StructureField);
3412 std::variant<Statement<DataComponentDefStmt>,
3414 u;
3415};
3416
3417struct Map {
3418 EMPTY_CLASS(MapStmt);
3419 EMPTY_CLASS(EndMapStmt);
3420 TUPLE_CLASS_BOILERPLATE(Map);
3421 std::tuple<Statement<MapStmt>, std::list<StructureField>,
3423 t;
3424};
3425
3426struct Union {
3427 EMPTY_CLASS(UnionStmt);
3428 EMPTY_CLASS(EndUnionStmt);
3429 TUPLE_CLASS_BOILERPLATE(Union);
3430 std::tuple<Statement<UnionStmt>, std::list<Map>, Statement<EndUnionStmt>> t;
3431};
3432
3434 TUPLE_CLASS_BOILERPLATE(StructureStmt);
3435 std::tuple<std::optional<Name>, std::list<EntityDecl>> t;
3436};
3437
3439 EMPTY_CLASS(EndStructureStmt);
3440 TUPLE_CLASS_BOILERPLATE(StructureDef);
3441 std::tuple<Statement<StructureStmt>, std::list<StructureField>,
3443 t;
3444};
3445
3446// Old style PARAMETER statement without parentheses.
3447// Types are determined entirely from the right-hand sides, not the names.
3448WRAPPER_CLASS(OldParameterStmt, std::list<NamedConstantDef>);
3449
3450// Deprecations
3452 TUPLE_CLASS_BOILERPLATE(ArithmeticIfStmt);
3453 std::tuple<Expr, Label, Label, Label> t;
3454};
3455
3457 TUPLE_CLASS_BOILERPLATE(AssignStmt);
3458 std::tuple<Label, Name> t;
3459};
3460
3462 TUPLE_CLASS_BOILERPLATE(AssignedGotoStmt);
3463 std::tuple<Name, std::list<Label>> t;
3464};
3465
3466WRAPPER_CLASS(PauseStmt, std::optional<StopCode>);
3467
3468// Parse tree nodes for OpenMP directives and clauses
3469
3470// --- Common definitions
3471
3472#define INHERITED_TUPLE_CLASS_BOILERPLATE(classname, basename) \
3473 using basename::basename; \
3474 classname(basename &&b) : basename(std::move(b)) {} \
3475 using TupleTrait = std::true_type; \
3476 BOILERPLATE(classname)
3477
3478#define INHERITED_WRAPPER_CLASS_BOILERPLATE(classname, basename) \
3479 BOILERPLATE(classname); \
3480 using basename::basename; \
3481 classname(basename &&base) : basename(std::move(base)) {} \
3482 using WrapperTrait = std::true_type
3483
3484struct OmpClause;
3486
3487struct OmpDirectiveName {
3488 // No boilerplates: this class should be copyable, movable, etc.
3489 constexpr OmpDirectiveName() = default;
3490 constexpr OmpDirectiveName(const OmpDirectiveName &) = default;
3491 constexpr OmpDirectiveName(llvm::omp::Directive x) : v(x) {}
3492 // Construct from an already parsed text. Use Verbatim for this because
3493 // Verbatim's source corresponds to an actual source location.
3494 // This allows "construct<OmpDirectiveName>(Verbatim("<name>"))".
3495 OmpDirectiveName(const Verbatim &name);
3496 using WrapperTrait = std::true_type;
3497
3498 bool IsExecutionPart() const; // Is allowed in the execution part
3499
3500 CharBlock source;
3501 llvm::omp::Directive v{llvm::omp::Directive::OMPD_unknown};
3502};
3503
3504// 2.1 Directives or clauses may accept a list or extended-list.
3505// A list item is a variable, array section or common block name (enclosed
3506// in slashes). An extended list item is a list item or a procedure Name.
3507// variable-name | / common-block / | array-sections
3509 // Blank common blocks are not valid objects. Parse them to emit meaningful
3510 // diagnostics.
3511 struct Invalid {
3512 ENUM_CLASS(Kind, BlankCommonBlock);
3513 WRAPPER_CLASS_BOILERPLATE(Invalid, Kind);
3514 CharBlock source;
3515 };
3516 UNION_CLASS_BOILERPLATE(OmpObject);
3517 std::variant<Designator, /*common block*/ Name, Invalid> u;
3518};
3519
3520WRAPPER_CLASS(OmpObjectList, std::list<OmpObject>);
3521
3522// Ref: [4.5:201-207], [5.0:293-299], [5.1:325-331], [5.2:124]
3523//
3524// reduction-identifier ->
3525// base-language-identifier | // since 4.5
3526// - | // since 4.5, until 5.2
3527// + | * | .AND. | .OR. | .EQV. | .NEQV. | // since 4.5
3528// MIN | MAX | IAND | IOR | IEOR // since 4.5
3530 UNION_CLASS_BOILERPLATE(OmpReductionIdentifier);
3531 std::variant<DefinedOperator, ProcedureDesignator> u;
3532};
3533
3534// Ref: [4.5:222:6], [5.0:305:27], [5.1:337:19], [5.2:126:3-4], [6.0:240:27-28]
3535//
3536// combiner-expression -> // since 4.5
3537// assignment-statement |
3538// function-reference
3540 UNION_CLASS_BOILERPLATE(OmpReductionCombiner);
3541 std::variant<AssignmentStmt, FunctionReference> u;
3542};
3543
3544inline namespace arguments {
3546 UNION_CLASS_BOILERPLATE(OmpTypeSpecifier);
3547 std::variant<TypeSpec, DeclarationTypeSpec> u;
3548};
3549
3550WRAPPER_CLASS(OmpTypeNameList, std::list<OmpTypeSpecifier>);
3551
3553 UNION_CLASS_BOILERPLATE(OmpLocator);
3554 std::variant<OmpObject, FunctionReference> u;
3555};
3556
3557WRAPPER_CLASS(OmpLocatorList, std::list<OmpLocator>);
3558
3559// Ref: [4.5:58-60], [5.0:58-60], [5.1:63-68], [5.2:197-198], [6.0:334-336]
3560//
3561// Argument to DECLARE VARIANT with the base-name present. (When only
3562// variant-name is present, it is a simple OmpObject).
3563//
3564// base-name-variant-name -> // since 4.5
3565// base-name : variant-name
3567 TUPLE_CLASS_BOILERPLATE(OmpBaseVariantNames);
3568 std::tuple<OmpObject, OmpObject> t;
3569};
3570
3571// Ref: [5.0:326:10-16], [5.1:359:5-11], [5.2:163:2-7], [6.0:293:16-21]
3572//
3573// mapper-specifier ->
3574// [mapper-identifier :] type :: var | // since 5.0
3575// DEFAULT type :: var
3577 // Absent mapper-identifier is equivalent to DEFAULT.
3578 TUPLE_CLASS_BOILERPLATE(OmpMapperSpecifier);
3579 std::tuple<std::string, TypeSpec, Name> t;
3580};
3581
3582// Ref: [4.5:222:1-5], [5.0:305:20-27], [5.1:337:11-19], [5.2:139:18-23],
3583// [6.0:260:16-20]
3584//
3585// reduction-specifier ->
3586// reduction-identifier : typename-list
3587// : combiner-expression // since 4.5, until 5.2
3588// reduction-identifier : typename-list // since 6.0
3590 TUPLE_CLASS_BOILERPLATE(OmpReductionSpecifier);
3591 std::tuple<OmpReductionIdentifier, OmpTypeNameList,
3592 std::optional<OmpReductionCombiner>>
3593 t;
3594};
3595
3597 CharBlock source;
3598 UNION_CLASS_BOILERPLATE(OmpArgument);
3599 std::variant<OmpLocator, // {variable, extended, locator}-list-item
3600 OmpBaseVariantNames, // base-name:variant-name
3602 u;
3603};
3604
3606 WRAPPER_CLASS_BOILERPLATE(OmpArgumentList, std::list<OmpArgument>);
3607 CharBlock source;
3608};
3609} // namespace arguments
3610
3611inline namespace traits {
3612// trait-property-name ->
3613// identifier | string-literal
3614//
3615// This is a bit of a problematic case. The spec says that a word in quotes,
3616// and the same word without quotes are equivalent. We currently parse both
3617// as a string, but it's likely just a temporary solution.
3618//
3619// The problem is that trait-property can be (among other things) a
3620// trait-property-name or a trait-property-expression. A simple identifier
3621// can be either, there is no reasonably simple way of telling them apart
3622// in the parser. There is a similar issue with extensions. Some of that
3623// disambiguation may need to be done in the "canonicalization" pass and
3624// then some of those AST nodes would be rewritten into different ones.
3625//
3627 CharBlock source;
3628 WRAPPER_CLASS_BOILERPLATE(OmpTraitPropertyName, std::string);
3629};
3630
3631// trait-score ->
3632// SCORE(non-negative-const-integer-expression)
3634 CharBlock source;
3635 WRAPPER_CLASS_BOILERPLATE(OmpTraitScore, ScalarIntExpr);
3636};
3637
3638// trait-property-extension ->
3639// trait-property-name |
3640// scalar-expr |
3641// trait-property-name (trait-property-extension, ...)
3642//
3644 CharBlock source;
3645 UNION_CLASS_BOILERPLATE(OmpTraitPropertyExtension);
3646 struct Complex { // name (prop-ext, prop-ext, ...)
3647 CharBlock source;
3648 TUPLE_CLASS_BOILERPLATE(Complex);
3649 std::tuple<OmpTraitPropertyName,
3650 std::list<common::Indirection<OmpTraitPropertyExtension>>>
3651 t;
3652 };
3653
3654 std::variant<OmpTraitPropertyName, ScalarExpr, Complex> u;
3655};
3656
3657// trait-property ->
3658// trait-property-name | OmpClause |
3659// trait-property-expression | trait-property-extension
3660// trait-property-expression ->
3661// scalar-logical-expression | scalar-integer-expression
3662//
3663// The parser for a logical expression will accept an integer expression,
3664// and if it's not logical, it will flag an error later. The same thing
3665// will happen if the scalar integer expression sees a logical expresion.
3666// To avoid this, parse all expressions as scalar expressions.
3668 CharBlock source;
3669 UNION_CLASS_BOILERPLATE(OmpTraitProperty);
3670 std::variant<OmpTraitPropertyName, common::Indirection<OmpClause>,
3671 ScalarExpr, // trait-property-expresion
3673 u;
3674};
3675
3676// trait-selector-name ->
3677// KIND | DT // name-list (host, nohost, +/add-def-doc)
3678// ISA | DT // name-list (isa_name, ... /impl-defined)
3679// ARCH | DT // name-list (arch_name, ... /impl-defined)
3680// directive-name | C // no properties
3681// SIMD | C // clause-list (from declare_simd)
3682// // (at least simdlen, inbranch/notinbranch)
3683// DEVICE_NUM | T // device-number
3684// UID | T // unique-string-id /impl-defined
3685// VENDOR | I // name-list (vendor-id /add-def-doc)
3686// EXTENSION | I // name-list (ext_name /impl-defined)
3687// ATOMIC_DEFAULT_MEM_ORDER I | // clause-list (value of admo)
3688// REQUIRES | I // clause-list (from requires)
3689// CONDITION U // logical-expr
3690// <other name> I // treated as extension
3691//
3692// Trait-set-selectors:
3693// [D]evice, [T]arget_device, [C]onstruct, [I]mplementation, [U]ser.
3695 std::string ToString() const;
3696 CharBlock source;
3697 UNION_CLASS_BOILERPLATE(OmpTraitSelectorName);
3698 ENUM_CLASS(Value, Arch, Atomic_Default_Mem_Order, Condition, Device_Num,
3699 Extension, Isa, Kind, Requires, Simd, Uid, Vendor)
3700 std::variant<Value, llvm::omp::Directive, std::string> u;
3701};
3702
3703// trait-selector ->
3704// trait-selector-name |
3705// trait-selector-name ([trait-score:] trait-property, ...)
3707 CharBlock source;
3708 TUPLE_CLASS_BOILERPLATE(OmpTraitSelector);
3709 struct Properties {
3710 TUPLE_CLASS_BOILERPLATE(Properties);
3711 std::tuple<std::optional<OmpTraitScore>, std::list<OmpTraitProperty>> t;
3712 };
3713 std::tuple<OmpTraitSelectorName, std::optional<Properties>> t;
3714};
3715
3716// trait-set-selector-name ->
3717// CONSTRUCT | DEVICE | IMPLEMENTATION | USER | // since 5.0
3718// TARGET_DEVICE // since 5.1
3720 std::string ToString() const;
3721 CharBlock source;
3722 ENUM_CLASS(Value, Construct, Device, Implementation, Target_Device, User)
3723 WRAPPER_CLASS_BOILERPLATE(OmpTraitSetSelectorName, Value);
3724};
3725
3726// trait-set-selector ->
3727// trait-set-selector-name = {trait-selector, ...}
3729 CharBlock source;
3730 TUPLE_CLASS_BOILERPLATE(OmpTraitSetSelector);
3731 std::tuple<OmpTraitSetSelectorName, std::list<OmpTraitSelector>> t;
3732};
3733
3734// context-selector-specification ->
3735// trait-set-selector, ...
3737 CharBlock source;
3738 WRAPPER_CLASS_BOILERPLATE(
3739 OmpContextSelectorSpecification, std::list<OmpTraitSetSelector>);
3740};
3741} // namespace traits
3742
3743#define MODIFIER_BOILERPLATE(...) \
3744 struct Modifier { \
3745 using Variant = std::variant<__VA_ARGS__>; \
3746 UNION_CLASS_BOILERPLATE(Modifier); \
3747 CharBlock source; \
3748 Variant u; \
3749 }
3750
3751#define MODIFIERS() std::optional<std::list<Modifier>>
3752
3753inline namespace modifier {
3754// For uniformity, in all keyword modifiers the name of the type defined
3755// by ENUM_CLASS is "Value", e.g.
3756// struct Foo {
3757// ENUM_CLASS(Value, Keyword1, Keyword2);
3758// };
3759
3761 ENUM_CLASS(Value, Cgroup);
3762 WRAPPER_CLASS_BOILERPLATE(OmpAccessGroup, Value);
3763};
3764
3765// Ref: [4.5:72-81], [5.0:110-119], [5.1:134-143], [5.2:169-170]
3766//
3767// alignment ->
3768// scalar-integer-expression // since 4.5
3770 WRAPPER_CLASS_BOILERPLATE(OmpAlignment, ScalarIntExpr);
3771};
3772
3773// Ref: [5.1:184-185], [5.2:178-179]
3774//
3775// align-modifier ->
3776// ALIGN(alignment) // since 5.1
3778 WRAPPER_CLASS_BOILERPLATE(OmpAlignModifier, ScalarIntExpr);
3779};
3780
3781// Ref: [5.0:158-159], [5.1:184-185], [5.2:178-179]
3782//
3783// allocator-simple-modifier ->
3784// allocator // since 5.0
3786 WRAPPER_CLASS_BOILERPLATE(OmpAllocatorSimpleModifier, ScalarIntExpr);
3787};
3788
3789// Ref: [5.1:184-185], [5.2:178-179]
3790//
3791// allocator-complex-modifier ->
3792// ALLOCATOR(allocator) // since 5.1
3794 WRAPPER_CLASS_BOILERPLATE(OmpAllocatorComplexModifier, ScalarIntExpr);
3795};
3796
3797// Ref: [4.5:216-219], [5.0:315-324], [5.1:347-355], [5.2:150-158],
3798// [6.0:279-288]
3799//
3800// always-modifier ->
3801// ALWAYS // since 4.5
3802//
3803// Until 5.2, it was a part of map-type-modifier. Since 6.0 the
3804// map-type-modifier has been split into individual modifiers.
3806 ENUM_CLASS(Value, Always)
3807 WRAPPER_CLASS_BOILERPLATE(OmpAlwaysModifier, Value);
3808};
3809
3810// Ref: [6.0:289-290]
3811//
3812// automap-modifier ->
3813// automap // since 6.0
3814//
3816 ENUM_CLASS(Value, Automap);
3817 WRAPPER_CLASS_BOILERPLATE(OmpAutomapModifier, Value);
3818};
3819
3820// Ref: [5.2:252-254]
3821//
3822// chunk-modifier ->
3823// SIMD // since 5.2
3824//
3825// Prior to 5.2 "chunk-modifier" was a part of "modifier" on SCHEDULE clause.
3827 ENUM_CLASS(Value, Simd)
3828 WRAPPER_CLASS_BOILERPLATE(OmpChunkModifier, Value);
3829};
3830
3831// Ref: [4.5:216-219], [5.0:315-324], [5.1:347-355], [5.2:150-158],
3832// [6.0:279-288]
3833//
3834// close-modifier ->
3835// CLOSE // since 5.0
3836//
3837// Until 5.2, it was a part of map-type-modifier. Since 6.0 the
3838// map-type-modifier has been split into individual modifiers.
3840 ENUM_CLASS(Value, Close)
3841 WRAPPER_CLASS_BOILERPLATE(OmpCloseModifier, Value);
3842};
3843
3844// Ref: [4.5:216-219], [5.0:315-324], [5.1:347-355], [5.2:150-158],
3845// [6.0:279-288]
3846//
3847// delete-modifier ->
3848// DELETE // since 6.0
3849//
3850// Until 5.2, it was a part of map-type.
3852 ENUM_CLASS(Value, Delete)
3853 WRAPPER_CLASS_BOILERPLATE(OmpDeleteModifier, Value);
3854};
3855
3856// Ref: [4.5:169-170], [5.0:255-256], [5.1:288-289]
3857//
3858// dependence-type ->
3859// SINK | SOURCE | // since 4.5
3860// IN | OUT | INOUT | // since 4.5, until 5.1
3861// MUTEXINOUTSET | DEPOBJ | // since 5.0, until 5.1
3862// INOUTSET // since 5.1, until 5.1
3863//
3864// All of these, except SINK and SOURCE became task-dependence-type in 5.2.
3865//
3866// Keeping these two as separate types, since having them all together
3867// creates conflicts when parsing the DEPEND clause. For DEPEND(SINK: ...),
3868// the SINK may be parsed as 'task-dependence-type', and the list after
3869// the ':' would then be parsed as OmpObjectList (instead of the iteration
3870// vector). This would accept the vector "i, j, k" (although interpreted
3871// incorrectly), while flagging a syntax error for "i+1, j, k".
3873 ENUM_CLASS(Value, Sink, Source);
3874 WRAPPER_CLASS_BOILERPLATE(OmpDependenceType, Value);
3875};
3876
3877// Ref: [5.0:170-176], [5.1:197-205], [5.2:276-277]
3878//
3879// device-modifier ->
3880// ANCESTOR | DEVICE_NUM // since 5.0
3882 ENUM_CLASS(Value, Ancestor, Device_Num)
3883 WRAPPER_CLASS_BOILERPLATE(OmpDeviceModifier, Value);
3884};
3885
3886// Ref: [5.2:72-73,230-323], in 4.5-5.1 it's scattered over individual
3887// directives that allow the IF clause.
3888//
3889// directive-name-modifier ->
3890// PARALLEL | TARGET | TARGET DATA |
3891// TARGET ENTER DATA | TARGET EXIT DATA |
3892// TARGET UPDATE | TASK | TASKLOOP | // since 4.5
3893// CANCEL[*] | SIMD | // since 5.0
3894// TEAMS // since 5.2
3895//
3896// [*] The IF clause is allowed on CANCEL in OpenMP 4.5, but only without
3897// the directive-name-modifier. For the sake of uniformity CANCEL can be
3898// considered a valid value in 4.5 as well.
3899struct OmpDirectiveNameModifier : public OmpDirectiveName {
3900 INHERITED_WRAPPER_CLASS_BOILERPLATE(
3901 OmpDirectiveNameModifier, OmpDirectiveName);
3902};
3903
3904// Ref: [5.1:205-209], [5.2:166-168]
3905//
3906// motion-modifier ->
3907// PRESENT | // since 5.0, until 5.0
3908// mapper | iterator
3909// expectation ->
3910// PRESENT // since 5.1
3911//
3912// The PRESENT value was a part of motion-modifier in 5.1, and became a
3913// value of expectation in 5.2.
3915 ENUM_CLASS(Value, Present);
3916 WRAPPER_CLASS_BOILERPLATE(OmpExpectation, Value);
3917};
3918
3919// REF: [5.1:217-220], [5.2:293-294]
3920//
3921// OmpInteropRuntimeIdentifier -> // since 5.2
3922// CharLiteralConstant || ScalarIntConstantExpr
3924 UNION_CLASS_BOILERPLATE(OmpInteropRuntimeIdentifier);
3925 std::variant<CharLiteralConstant, ScalarIntConstantExpr> u;
3926};
3927
3928// REF: [5.1:217-220], [5.2:293-294]
3929//
3930// OmpInteropPreference -> // since 5.2
3931// ([OmpRuntimeIdentifier, ...])
3933 WRAPPER_CLASS_BOILERPLATE(
3934 OmpInteropPreference, std::list<OmpInteropRuntimeIdentifier>);
3935};
3936
3937// REF: [5.1:217-220], [5.2:293-294]
3938//
3939// InteropType -> target || targetsync // since 5.2
3940// There can be at most only two interop-type.
3942 ENUM_CLASS(Value, Target, TargetSync)
3943 WRAPPER_CLASS_BOILERPLATE(OmpInteropType, Value);
3944};
3945
3946// Ref: [5.0:47-49], [5.1:49-51], [5.2:67-69]
3947//
3948// iterator-specifier ->
3949// [iterator-type] iterator-identifier
3950// = range-specification | // since 5.0
3951// [iterator-type ::] iterator-identifier
3952// = range-specification // since 5.2
3954 TUPLE_CLASS_BOILERPLATE(OmpIteratorSpecifier);
3955 CharBlock source;
3956 std::tuple<TypeDeclarationStmt, SubscriptTriplet> t;
3957};
3958
3959// Ref: [5.0:47-49], [5.1:49-51], [5.2:67-69]
3960//
3961// iterator-modifier ->
3962// ITERATOR(iterator-specifier [, ...]) // since 5.0
3964 WRAPPER_CLASS_BOILERPLATE(OmpIterator, std::list<OmpIteratorSpecifier>);
3965};
3966
3967// Ref: [5.0:288-290], [5.1:321-322], [5.2:115-117]
3968//
3969// lastprivate-modifier ->
3970// CONDITIONAL // since 5.0
3972 ENUM_CLASS(Value, Conditional)
3973 WRAPPER_CLASS_BOILERPLATE(OmpLastprivateModifier, Value);
3974};
3975
3976// Ref: [4.5:207-210], [5.0:290-293], [5.1:323-325], [5.2:117-120]
3977//
3978// linear-modifier ->
3979// REF | UVAL | VAL // since 4.5
3981 ENUM_CLASS(Value, Ref, Uval, Val);
3982 WRAPPER_CLASS_BOILERPLATE(OmpLinearModifier, Value);
3983};
3984
3985// Ref: [5.0:176-180], [5.1:205-210], [5.2:149-150]
3986//
3987// mapper ->
3988// identifier // since 4.5
3990 WRAPPER_CLASS_BOILERPLATE(OmpMapper, Name);
3991};
3992
3993// Ref: [4.5:216-219], [5.0:315-324], [5.1:347-355], [5.2:150-158],
3994// [6.0:279-288]
3995//
3996// map-type ->
3997// ALLOC | DELETE | RELEASE | // since 4.5, until 5.2
3998// FROM | TO | TOFROM | // since 4.5
3999// STORAGE // since 6.0
4000//
4001// Since 6.0 DELETE is a separate delete-modifier.
4003 ENUM_CLASS(Value, Alloc, Delete, From, Release, Storage, To, Tofrom);
4004 WRAPPER_CLASS_BOILERPLATE(OmpMapType, Value);
4005};
4006
4007// Ref: [4.5:216-219], [5.0:315-324], [5.1:347-355], [5.2:150-158]
4008//
4009// map-type-modifier ->
4010// ALWAYS | // since 4.5, until 5.2
4011// CLOSE | // since 5.0, until 5.2
4012// PRESENT // since 5.1, until 5.2
4013// Since 6.0 the map-type-modifier has been split into individual modifiers.
4014//
4016 ENUM_CLASS(Value, Always, Close, Present, Ompx_Hold)
4017 WRAPPER_CLASS_BOILERPLATE(OmpMapTypeModifier, Value);
4018};
4019
4020// Ref: [4.5:56-63], [5.0:101-109], [5.1:126-133], [5.2:252-254]
4021//
4022// modifier ->
4023// MONOTONIC | NONMONOTONIC | SIMD // since 4.5, until 5.1
4024// ordering-modifier ->
4025// MONOTONIC | NONMONOTONIC // since 5.2
4026//
4027// Until 5.1, the SCHEDULE clause accepted up to two instances of "modifier".
4028// Since 5.2 "modifier" was replaced with "ordering-modifier" and "chunk-
4029// modifier".
4031 ENUM_CLASS(Value, Monotonic, Nonmonotonic, Simd)
4032 WRAPPER_CLASS_BOILERPLATE(OmpOrderingModifier, Value);
4033};
4034
4035// Ref: [5.1:125-126], [5.2:233-234]
4036//
4037// order-modifier ->
4038// REPRODUCIBLE | UNCONSTRAINED // since 5.1
4040 ENUM_CLASS(Value, Reproducible, Unconstrained)
4041 WRAPPER_CLASS_BOILERPLATE(OmpOrderModifier, Value);
4042};
4043
4044// Ref: [5.1:166-171], [5.2:269-270]
4045//
4046// prescriptiveness ->
4047// STRICT // since 5.1
4048// FALLBACK // since 6.1
4050 ENUM_CLASS(Value, Strict, Fallback)
4051 WRAPPER_CLASS_BOILERPLATE(OmpPrescriptiveness, Value);
4052};
4053
4054// Ref: [4.5:216-219], [5.0:315-324], [5.1:347-355], [5.2:150-158],
4055// [6.0:279-288]
4056//
4057// present-modifier ->
4058// PRESENT // since 5.1
4059//
4060// Until 5.2, it was a part of map-type-modifier. Since 6.0 the
4061// map-type-modifier has been split into individual modifiers.
4063 ENUM_CLASS(Value, Present)
4064 WRAPPER_CLASS_BOILERPLATE(OmpPresentModifier, Value);
4065};
4066
4067// Ref: [5.0:300-302], [5.1:332-334], [5.2:134-137]
4068//
4069// reduction-modifier ->
4070// DEFAULT | INSCAN | TASK // since 5.0
4072 ENUM_CLASS(Value, Default, Inscan, Task);
4073 WRAPPER_CLASS_BOILERPLATE(OmpReductionModifier, Value);
4074};
4075
4076// Ref: [6.0:279-288]
4077//
4078// ref-modifier ->
4079// REF_PTEE | REF_PTR | REF_PTR_PTEE // since 6.0
4080//
4082 ENUM_CLASS(Value, Ref_Ptee, Ref_Ptr, Ref_Ptr_Ptee)
4083 WRAPPER_CLASS_BOILERPLATE(OmpRefModifier, Value);
4084};
4085
4086// Ref: [6.0:279-288]
4087//
4088// self-modifier ->
4089// SELF // since 6.0
4090//
4092 ENUM_CLASS(Value, Self)
4093 WRAPPER_CLASS_BOILERPLATE(OmpSelfModifier, Value);
4094};
4095
4096// Ref: [5.2:117-120]
4097//
4098// step-complex-modifier ->
4099// STEP(integer-expression) // since 5.2
4101 WRAPPER_CLASS_BOILERPLATE(OmpStepComplexModifier, ScalarIntExpr);
4102};
4103
4104// Ref: [4.5:207-210], [5.0:290-293], [5.1:323-325], [5.2:117-120]
4105//
4106// step-simple-modifier ->
4107// integer-expresion // since 4.5
4109 WRAPPER_CLASS_BOILERPLATE(OmpStepSimpleModifier, ScalarIntExpr);
4110};
4111
4112// Ref: [4.5:169-170], [5.0:254-256], [5.1:287-289], [5.2:321]
4113//
4114// task-dependence-type -> // "dependence-type" in 5.1 and before
4115// IN | OUT | INOUT | // since 4.5
4116// MUTEXINOUTSET | DEPOBJ | // since 5.0
4117// INOUTSET // since 5.2
4119 ENUM_CLASS(Value, In, Out, Inout, Inoutset, Mutexinoutset, Depobj)
4120 WRAPPER_CLASS_BOILERPLATE(OmpTaskDependenceType, Value);
4121};
4122
4123// Ref: [4.5:229-230], [5.0:324-325], [5.1:357-358], [5.2:161-162]
4124//
4125// variable-category ->
4126// SCALAR | // since 4.5
4127// AGGREGATE | ALLOCATABLE | POINTER | // since 5.0
4128// ALL // since 5.2
4130 ENUM_CLASS(Value, Aggregate, All, Allocatable, Pointer, Scalar)
4131 WRAPPER_CLASS_BOILERPLATE(OmpVariableCategory, Value);
4132};
4133
4134// Extension:
4135// https://openmp.llvm.org//openacc/OpenMPExtensions.html#ompx-hold
4136//
4137// ompx-hold-modifier ->
4138// OMPX_HOLD // since 4.5
4139//
4140// Until 5.2, it was a part of map-type-modifier. Since 6.0 the
4141// map-type-modifier has been split into individual modifiers.
4143 ENUM_CLASS(Value, Ompx_Hold)
4144 WRAPPER_CLASS_BOILERPLATE(OmpxHoldModifier, Value);
4145};
4146
4147// context-selector
4148using OmpContextSelector = traits::OmpContextSelectorSpecification;
4149} // namespace modifier
4150
4151// --- Clauses
4152
4153using OmpDirectiveList = std::list<llvm::omp::Directive>;
4154
4155// Ref: [5.2:214]
4156//
4157// absent-clause ->
4158// ABSENT(directive-name[, directive-name])
4160 WRAPPER_CLASS_BOILERPLATE(OmpAbsentClause, OmpDirectiveList);
4161};
4162
4164 TUPLE_CLASS_BOILERPLATE(OmpAdjustArgsClause);
4166 ENUM_CLASS(Value, Nothing, Need_Device_Ptr)
4167 WRAPPER_CLASS_BOILERPLATE(OmpAdjustOp, Value);
4168 };
4169 std::tuple<OmpAdjustOp, OmpObjectList> t;
4170};
4171
4172// Ref: [5.0:135-140], [5.1:161-166], [5.2:264-265]
4173//
4174// affinity-clause ->
4175// AFFINITY([aff-modifier:] locator-list) // since 5.0
4176// aff-modifier ->
4177// interator-modifier // since 5.0
4179 TUPLE_CLASS_BOILERPLATE(OmpAffinityClause);
4180 MODIFIER_BOILERPLATE(OmpIterator);
4181 std::tuple<MODIFIERS(), OmpObjectList> t;
4182};
4183
4184// Ref: 5.2: [174]
4186 WRAPPER_CLASS_BOILERPLATE(OmpAlignClause, ScalarIntExpr);
4187};
4188
4189// Ref: [4.5:72-81], [5.0:110-119], [5.1:134-143], [5.2:169-170]
4190//
4191// aligned-clause ->
4192// ALIGNED(list [: alignment]) // since 4.5
4194 TUPLE_CLASS_BOILERPLATE(OmpAlignedClause);
4195 MODIFIER_BOILERPLATE(OmpAlignment);
4196 std::tuple<OmpObjectList, MODIFIERS()> t;
4197};
4198
4199// Ref: [5.0:158-159], [5.1:184-185], [5.2:178-179]
4200//
4201// allocate-clause ->
4202// ALLOCATE(
4203// [allocator-simple-modifier:] list) | // since 5.0
4204// ALLOCATE([modifier...:] list) // since 5.1
4205// modifier ->
4206// allocator-simple-modifier |
4207// allocator-complex-modifier | align-modifier // since 5.1
4209 MODIFIER_BOILERPLATE(OmpAlignModifier, OmpAllocatorSimpleModifier,
4211 TUPLE_CLASS_BOILERPLATE(OmpAllocateClause);
4212 std::tuple<MODIFIERS(), OmpObjectList> t;
4213};
4214
4217 WRAPPER_CLASS_BOILERPLATE(OmpAppendOp, std::list<OmpInteropType>);
4218 };
4219 WRAPPER_CLASS_BOILERPLATE(OmpAppendArgsClause, std::list<OmpAppendOp>);
4220};
4221
4222// Ref: [5.2:216-217 (sort of, as it's only mentioned in passing)
4223// AT(compilation|execution)
4225 ENUM_CLASS(ActionTime, Compilation, Execution);
4226 WRAPPER_CLASS_BOILERPLATE(OmpAtClause, ActionTime);
4227};
4228
4229// Ref: [5.0:60-63], [5.1:83-86], [5.2:210-213]
4230//
4231// atomic-default-mem-order-clause ->
4232// ATOMIC_DEFAULT_MEM_ORDER(memory-order) // since 5.0
4233// memory-order ->
4234// SEQ_CST | ACQ_REL | RELAXED | // since 5.0
4235// ACQUIRE | RELEASE // since 5.2
4237 using MemoryOrder = common::OmpMemoryOrderType;
4238 WRAPPER_CLASS_BOILERPLATE(OmpAtomicDefaultMemOrderClause, MemoryOrder);
4239};
4240
4241// Ref: [5.0:128-131], [5.1:151-154], [5.2:258-259]
4242//
4243// bind-clause ->
4244// BIND(binding) // since 5.0
4245// binding ->
4246// TEAMS | PARALLEL | THREAD // since 5.0
4248 ENUM_CLASS(Binding, Parallel, Teams, Thread)
4249 WRAPPER_CLASS_BOILERPLATE(OmpBindClause, Binding);
4250};
4251
4252// Artificial clause to represent a cancellable construct.
4254 TUPLE_CLASS_BOILERPLATE(OmpCancellationConstructTypeClause);
4255 std::tuple<OmpDirectiveName, std::optional<ScalarLogicalExpr>> t;
4256};
4257
4258// Ref: [5.2:214]
4259//
4260// contains-clause ->
4261// CONTAINS(directive-name[, directive-name])
4263 WRAPPER_CLASS_BOILERPLATE(OmpContainsClause, OmpDirectiveList);
4264};
4265
4266// Ref: [4.5:46-50], [5.0:74-78], [5.1:92-96], [5.2:109]
4267//
4268// When used as a data-sharing clause:
4269// default-clause ->
4270// DEFAULT(data-sharing-attribute) // since 4.5
4271// data-sharing-attribute ->
4272// SHARED | NONE | // since 4.5
4273// PRIVATE | FIRSTPRIVATE // since 5.0
4274//
4275// When used in METADIRECTIVE:
4276// default-clause ->
4277// DEFAULT(directive-specification) // since 5.0, until 5.1
4278// See also otherwise-clause.
4280 ENUM_CLASS(DataSharingAttribute, Private, Firstprivate, Shared, None)
4281 UNION_CLASS_BOILERPLATE(OmpDefaultClause);
4282 std::variant<DataSharingAttribute,
4284 u;
4285};
4286
4287// Ref: [4.5:103-107], [5.0:324-325], [5.1:357-358], [5.2:161-162]
4288//
4289// defaultmap-clause ->
4290// DEFAULTMAP(implicit-behavior
4291// [: variable-category]) // since 5.0
4292// implicit-behavior ->
4293// TOFROM | // since 4.5
4294// ALLOC | TO | FROM | FIRSTPRIVATE | NONE |
4295// DEFAULT | // since 5.0
4296// PRESENT // since 5.1
4298 TUPLE_CLASS_BOILERPLATE(OmpDefaultmapClause);
4299 ENUM_CLASS(ImplicitBehavior, Alloc, To, From, Tofrom, Firstprivate, None,
4300 Default, Present)
4301 MODIFIER_BOILERPLATE(OmpVariableCategory);
4302 std::tuple<ImplicitBehavior, MODIFIERS()> t;
4303};
4304
4305// Ref: [4.5:169-172], [5.0:255-259], [5.1:288-292], [5.2:91-93]
4306//
4307// iteration-offset ->
4308// +|- non-negative-constant // since 4.5
4310 TUPLE_CLASS_BOILERPLATE(OmpIterationOffset);
4311 std::tuple<DefinedOperator, ScalarIntConstantExpr> t;
4312};
4313
4314// Ref: [4.5:169-172], [5.0:255-259], [5.1:288-292], [5.2:91-93]
4315//
4316// iteration ->
4317// induction-variable [iteration-offset] // since 4.5
4319 TUPLE_CLASS_BOILERPLATE(OmpIteration);
4320 std::tuple<Name, std::optional<OmpIterationOffset>> t;
4321};
4322
4323// Ref: [4.5:169-172], [5.0:255-259], [5.1:288-292], [5.2:91-93]
4324//
4325// iteration-vector ->
4326// [iteration...] // since 4.5
4327WRAPPER_CLASS(OmpIterationVector, std::list<OmpIteration>);
4328
4329// Extract this into a separate structure (instead of having it directly in
4330// OmpDoacrossClause), so that the context in TYPE_CONTEXT_PARSER can be set
4331// separately for OmpDependClause and OmpDoacrossClause.
4332//
4333// See: depend-clause, doacross-clause
4335 OmpDependenceType::Value GetDepType() const;
4336
4337 WRAPPER_CLASS(Sink, OmpIterationVector);
4338 EMPTY_CLASS(Source);
4339 UNION_CLASS_BOILERPLATE(OmpDoacross);
4340 std::variant<Sink, Source> u;
4341};
4342
4343// Ref: [4.5:169-172], [5.0:255-259], [5.1:288-292], [5.2:323-326]
4344//
4345// depend-clause ->
4346// DEPEND(SOURCE) | // since 4.5, until 5.1
4347// DEPEND(SINK: iteration-vector) | // since 4.5, until 5.1
4348// DEPEND([depend-modifier,]
4349// task-dependence-type: locator-list) // since 4.5
4350//
4351// depend-modifier -> iterator-modifier // since 5.0
4353 UNION_CLASS_BOILERPLATE(OmpDependClause);
4354 struct TaskDep {
4355 OmpTaskDependenceType::Value GetTaskDepType() const;
4356 TUPLE_CLASS_BOILERPLATE(TaskDep);
4357 MODIFIER_BOILERPLATE(OmpIterator, OmpTaskDependenceType);
4358 std::tuple<MODIFIERS(), OmpObjectList> t;
4359 };
4360 std::variant<TaskDep, OmpDoacross> u;
4361};
4362
4363// Ref: [5.2:326-328]
4364//
4365// doacross-clause ->
4366// DOACROSS(dependence-type: iteration-vector) // since 5.2
4367WRAPPER_CLASS(OmpDoacrossClause, OmpDoacross);
4368
4369// Ref: [5.0:254-255], [5.1:287-288], [5.2:73]
4370//
4371// destroy-clause ->
4372// DESTROY | // since 5.0, until 5.1
4373// DESTROY(variable) // since 5.2
4374WRAPPER_CLASS(OmpDestroyClause, OmpObject);
4375
4376// Ref: [5.0:135-140], [5.1:161-166], [5.2:265-266]
4377//
4378// detach-clause ->
4379// DETACH(event-handle) // since 5.0
4381 WRAPPER_CLASS_BOILERPLATE(OmpDetachClause, OmpObject);
4382};
4383
4384// Ref: [4.5:103-107], [5.0:170-176], [5.1:197-205], [5.2:276-277]
4385//
4386// device-clause ->
4387// DEVICE(scalar-integer-expression) | // since 4.5
4388// DEVICE([device-modifier:]
4389// scalar-integer-expression) // since 5.0
4391 TUPLE_CLASS_BOILERPLATE(OmpDeviceClause);
4392 MODIFIER_BOILERPLATE(OmpDeviceModifier);
4393 std::tuple<MODIFIERS(), ScalarIntExpr> t;
4394};
4395
4396// Ref: [5.0:180-185], [5.1:210-216], [5.2:275]
4397//
4398// device-type-clause ->
4399// DEVICE_TYPE(ANY | HOST | NOHOST) // since 5.0
4401 ENUM_CLASS(DeviceTypeDescription, Any, Host, Nohost)
4402 WRAPPER_CLASS_BOILERPLATE(OmpDeviceTypeClause, DeviceTypeDescription);
4403};
4404
4406 TUPLE_CLASS_BOILERPLATE(OmpDynGroupprivateClause);
4407 MODIFIER_BOILERPLATE(OmpAccessGroup, OmpPrescriptiveness);
4408 std::tuple<MODIFIERS(), ScalarIntExpr> t;
4409};
4410
4411// Ref: [5.2:158-159], [6.0:289-290]
4412//
4413// enter-clause ->
4414// ENTER(locator-list) |
4415// ENTER(automap-modifier: locator-list) | // since 6.0
4417 TUPLE_CLASS_BOILERPLATE(OmpEnterClause);
4418 MODIFIER_BOILERPLATE(OmpAutomapModifier);
4419 std::tuple<MODIFIERS(), OmpObjectList> t;
4420};
4421
4422// OMP 5.2 15.8.3 extended-atomic, fail-clause ->
4423// FAIL(memory-order)
4425 using MemoryOrder = common::OmpMemoryOrderType;
4426 WRAPPER_CLASS_BOILERPLATE(OmpFailClause, MemoryOrder);
4427};
4428
4429// Ref: [4.5:107-109], [5.0:176-180], [5.1:205-210], [5.2:167-168]
4430//
4431// from-clause ->
4432// FROM(locator-list) |
4433// FROM(mapper-modifier: locator-list) | // since 5.0
4434// FROM(motion-modifier[,] ...: locator-list) // since 5.1
4435// motion-modifier ->
4436// PRESENT | mapper-modifier | iterator-modifier
4438 TUPLE_CLASS_BOILERPLATE(OmpFromClause);
4439 MODIFIER_BOILERPLATE(OmpExpectation, OmpIterator, OmpMapper);
4440 std::tuple<MODIFIERS(), OmpObjectList, /*CommaSeparated=*/bool> t;
4441};
4442
4443// Ref: [4.5:87-91], [5.0:140-146], [5.1:166-171], [5.2:269]
4444//
4445// grainsize-clause ->
4446// GRAINSIZE(grain-size) | // since 4.5
4447// GRAINSIZE([prescriptiveness:] grain-size) // since 5.1
4449 TUPLE_CLASS_BOILERPLATE(OmpGrainsizeClause);
4450 MODIFIER_BOILERPLATE(OmpPrescriptiveness);
4451 std::tuple<MODIFIERS(), ScalarIntExpr> t;
4452};
4453
4454// Ref: [6.0:438]
4455//
4456// graph_id-clause ->
4457// GRAPH_ID(graph-id-value) // since 6.0
4459 WRAPPER_CLASS_BOILERPLATE(OmpGraphIdClause, ScalarIntExpr);
4460};
4461
4462// Ref: [6.0:438-439]
4463//
4464// graph_reset-clause ->
4465// GRAPH_RESET[(graph-reset-expression)] // since 6.0
4467 WRAPPER_CLASS_BOILERPLATE(OmpGraphResetClause, ScalarLogicalExpr);
4468};
4469
4470// Ref: [5.0:234-242], [5.1:266-275], [5.2:299], [6.0:472-473]
4472 WRAPPER_CLASS_BOILERPLATE(OmpHintClause, ScalarIntConstantExpr);
4473};
4474
4475// Ref: [5.2: 214]
4476//
4477// holds-clause ->
4478// HOLDS(expr)
4480 WRAPPER_CLASS_BOILERPLATE(OmpHoldsClause, common::Indirection<Expr>);
4481};
4482
4483// Ref: [5.2: 209]
4485 WRAPPER_CLASS_BOILERPLATE(
4486 OmpIndirectClause, std::optional<ScalarLogicalExpr>);
4487};
4488
4489// Ref: [5.2:72-73], in 4.5-5.1 it's scattered over individual directives
4490// that allow the IF clause.
4491//
4492// if-clause ->
4493// IF([directive-name-modifier:]
4494// scalar-logical-expression) // since 4.5
4496 TUPLE_CLASS_BOILERPLATE(OmpIfClause);
4497 MODIFIER_BOILERPLATE(OmpDirectiveNameModifier);
4498 std::tuple<MODIFIERS(), ScalarLogicalExpr> t;
4499};
4500
4501// Ref: [5.0:170-176], [5.1:197-205], [5.2:138-139]
4502//
4503// in-reduction-clause ->
4504// IN_REDUCTION(reduction-identifier: list) // since 5.0
4506 TUPLE_CLASS_BOILERPLATE(OmpInReductionClause);
4507 MODIFIER_BOILERPLATE(OmpReductionIdentifier);
4508 std::tuple<MODIFIERS(), OmpObjectList> t;
4509};
4510
4511// declare-reduction -> DECLARE REDUCTION (reduction-identifier : type-list
4512// : combiner) [initializer-clause]
4514 TUPLE_CLASS_BOILERPLATE(OmpInitializerProc);
4515 std::tuple<ProcedureDesignator, std::list<ActualArgSpec>> t;
4516};
4517// Initialization for declare reduction construct
4519 UNION_CLASS_BOILERPLATE(OmpInitializerClause);
4520 std::variant<OmpInitializerProc, AssignmentStmt> u;
4521};
4522
4523// Ref: [4.5:199-201], [5.0:288-290], [5.1:321-322], [5.2:115-117]
4524//
4525// lastprivate-clause ->
4526// LASTPRIVATE(list) | // since 4.5
4527// LASTPRIVATE([lastprivate-modifier:] list) // since 5.0
4529 TUPLE_CLASS_BOILERPLATE(OmpLastprivateClause);
4530 MODIFIER_BOILERPLATE(OmpLastprivateModifier);
4531 std::tuple<MODIFIERS(), OmpObjectList> t;
4532};
4533
4534// Ref: [4.5:207-210], [5.0:290-293], [5.1:323-325], [5.2:117-120]
4535//
4536// linear-clause ->
4537// LINEAR(list [: step-simple-modifier]) | // since 4.5
4538// LINEAR(linear-modifier(list)
4539// [: step-simple-modifier]) | // since 4.5, until 5.2[*]
4540// LINEAR(list [: linear-modifier,
4541// step-complex-modifier]) // since 5.2
4542// [*] Still allowed in 5.2 when on DECLARE SIMD, but deprecated.
4544 TUPLE_CLASS_BOILERPLATE(OmpLinearClause);
4545 MODIFIER_BOILERPLATE(
4547 std::tuple<OmpObjectList, MODIFIERS(), /*PostModified=*/bool> t;
4548};
4549
4550// Ref: [6.0:207-208]
4551//
4552// loop-range-clause ->
4553// LOOPRANGE(first, count) // since 6.0
4555 TUPLE_CLASS_BOILERPLATE(OmpLoopRangeClause);
4556 std::tuple<ScalarIntConstantExpr, ScalarIntConstantExpr> t;
4557};
4558
4559// Ref: [4.5:216-219], [5.0:315-324], [5.1:347-355], [5.2:150-158]
4560//
4561// map-clause ->
4562// MAP([modifier...:] locator-list) // since 4.5
4563// modifier ->
4564// map-type-modifier [replaced] | // since 4.5, until 5.2
4565// always-modifier | // since 6.0
4566// close-modifier | // since 6.0
4567// delete-modifier | // since 6.0
4568// present-modifier | // since 6.0
4569// ref-modifier | // since 6.0
4570// self-modifier | // since 6.0
4571// mapper | // since 5.0
4572// iterator | // since 5.1
4573// map-type // since 4.5
4574// ompx-hold-modifier | // since 6.0
4575//
4576// Since 6.0 the map-type-modifier has been split into individual modifiers,
4577// and delete-modifier has been split from map-type.
4579 TUPLE_CLASS_BOILERPLATE(OmpMapClause);
4583 std::tuple<MODIFIERS(), OmpObjectList, /*CommaSeparated=*/bool> t;
4584};
4585
4586// Ref: [5.0:58-60], [5.1:63-68], [5.2:194-195]
4587//
4588// match-clause ->
4589// MATCH (context-selector-specification) // since 5.0
4591 // The context-selector is an argument.
4592 WRAPPER_CLASS_BOILERPLATE(
4594};
4595
4596// Ref: [5.2:217-218]
4597// message-clause ->
4598// MESSAGE("message-text")
4600 WRAPPER_CLASS_BOILERPLATE(OmpMessageClause, Expr);
4601};
4602
4603// Ref: [5.2: 214]
4604//
4605// no_openmp_clause -> NO_OPENMP
4606EMPTY_CLASS(OmpNoOpenMPClause);
4607
4608// Ref: [5.2: 214]
4609//
4610// no_openmp_routines_clause -> NO_OPENMP_ROUTINES
4611EMPTY_CLASS(OmpNoOpenMPRoutinesClause);
4612
4613// Ref: [5.2: 214]
4614//
4615// no_parallelism_clause -> NO_PARALELISM
4616EMPTY_CLASS(OmpNoParallelismClause);
4617
4618// Ref: [4.5:87-91], [5.0:140-146], [5.1:166-171], [5.2:270]
4619//
4620// num-tasks-clause ->
4621// NUM_TASKS(num-tasks) | // since 4.5
4622// NUM_TASKS([prescriptiveness:] num-tasks) // since 5.1
4624 TUPLE_CLASS_BOILERPLATE(OmpNumTasksClause);
4625 MODIFIER_BOILERPLATE(OmpPrescriptiveness);
4626 std::tuple<MODIFIERS(), ScalarIntExpr> t;
4627};
4628
4629// Ref: [5.0:101-109], [5.1:126-134], [5.2:233-234]
4630//
4631// order-clause ->
4632// ORDER(CONCURRENT) | // since 5.0
4633// ORDER([order-modifier:] CONCURRENT) // since 5.1
4635 TUPLE_CLASS_BOILERPLATE(OmpOrderClause);
4636 ENUM_CLASS(Ordering, Concurrent)
4637 MODIFIER_BOILERPLATE(OmpOrderModifier);
4638 std::tuple<MODIFIERS(), Ordering> t;
4639};
4640
4641// Ref: [5.0:56-57], [5.1:60-62], [5.2:191]
4642//
4643// otherwise-clause ->
4644// DEFAULT ([directive-specification]) // since 5.0, until 5.1
4645// otherwise-clause ->
4646// OTHERWISE ([directive-specification])] // since 5.2
4648 WRAPPER_CLASS_BOILERPLATE(OmpOtherwiseClause,
4650};
4651
4652// Ref: [4.5:46-50], [5.0:74-78], [5.1:92-96], [5.2:229-230]
4653//
4654// proc-bind-clause ->
4655// PROC_BIND(affinity-policy) // since 4.5
4656// affinity-policy ->
4657// CLOSE | PRIMARY | SPREAD | // since 4.5
4658// MASTER // since 4.5, until 5.2
4660 ENUM_CLASS(AffinityPolicy, Close, Master, Spread, Primary)
4661 WRAPPER_CLASS_BOILERPLATE(OmpProcBindClause, AffinityPolicy);
4662};
4663
4664// Ref: [4.5:201-207], [5.0:300-302], [5.1:332-334], [5.2:134-137]
4665//
4666// reduction-clause ->
4667// REDUCTION(reduction-identifier: list) | // since 4.5
4668// REDUCTION([reduction-modifier,]
4669// reduction-identifier: list) // since 5.0
4671 TUPLE_CLASS_BOILERPLATE(OmpReductionClause);
4672 MODIFIER_BOILERPLATE(OmpReductionModifier, OmpReductionIdentifier);
4673 std::tuple<MODIFIERS(), OmpObjectList> t;
4674};
4675
4676// Ref: [6.0:440:441]
4677//
4678// replayable-clause ->
4679// REPLAYABLE[(replayable-expression)] // since 6.0
4681 WRAPPER_CLASS_BOILERPLATE(OmpReplayableClause, Scalar<Logical<ConstantExpr>>);
4682};
4683
4684// Ref: [4.5:56-63], [5.0:101-109], [5.1:126-133], [5.2:252-254]
4685//
4686// schedule-clause ->
4687// SCHEDULE([modifier[, modifier]:]
4688// kind[, chunk-size]) // since 4.5, until 5.1
4689// schedule-clause ->
4690// SCHEDULE([ordering-modifier], chunk-modifier],
4691// kind[, chunk_size]) // since 5.2
4693 TUPLE_CLASS_BOILERPLATE(OmpScheduleClause);
4694 ENUM_CLASS(Kind, Static, Dynamic, Guided, Auto, Runtime)
4695 MODIFIER_BOILERPLATE(OmpOrderingModifier, OmpChunkModifier);
4696 std::tuple<MODIFIERS(), Kind, std::optional<ScalarIntExpr>> t;
4697};
4698
4699// REF: [5.2:217]
4700// severity-clause ->
4701// SEVERITY(warning|fatal)
4703 ENUM_CLASS(Severity, Fatal, Warning);
4704 WRAPPER_CLASS_BOILERPLATE(OmpSeverityClause, Severity);
4705};
4706
4707// Ref: [5.0:232-234], [5.1:264-266], [5.2:137]
4708//
4709// task-reduction-clause ->
4710// TASK_REDUCTION(reduction-identifier: list) // since 5.0
4712 TUPLE_CLASS_BOILERPLATE(OmpTaskReductionClause);
4713 MODIFIER_BOILERPLATE(OmpReductionIdentifier);
4714 std::tuple<MODIFIERS(), OmpObjectList> t;
4715};
4716
4717// Ref: [4.5:107-109], [5.0:176-180], [5.1:205-210], [5.2:167-168]
4718//
4719// to-clause (in DECLARE TARGET) ->
4720// TO(extended-list) | // until 5.1
4721// to-clause (in TARGET UPDATE) ->
4722// TO(locator-list) |
4723// TO(mapper-modifier: locator-list) | // since 5.0
4724// TO(motion-modifier[,] ...: locator-list) // since 5.1
4725// motion-modifier ->
4726// PRESENT | mapper-modifier | iterator-modifier
4728 TUPLE_CLASS_BOILERPLATE(OmpToClause);
4729 MODIFIER_BOILERPLATE(OmpExpectation, OmpIterator, OmpMapper);
4730 std::tuple<MODIFIERS(), OmpObjectList, /*CommaSeparated=*/bool> t;
4731};
4732
4733// Ref: [6.0:510-511]
4734//
4735// transparent-clause ->
4736// TRANSPARENT[(impex-type)] // since 6.0
4738 WRAPPER_CLASS_BOILERPLATE(OmpTransparentClause, ScalarIntExpr);
4739};
4740
4741// Ref: [5.0:254-255], [5.1:287-288], [5.2:321-322]
4742//
4743// In ATOMIC construct
4744// update-clause ->
4745// UPDATE // Since 4.5
4746//
4747// In DEPOBJ construct
4748// update-clause ->
4749// UPDATE(dependence-type) // since 5.0, until 5.1
4750// update-clause ->
4751// UPDATE(task-dependence-type) // since 5.2
4753 UNION_CLASS_BOILERPLATE(OmpUpdateClause);
4754 // The dependence type is an argument here, not a modifier.
4755 std::variant<OmpDependenceType, OmpTaskDependenceType> u;
4756};
4757
4758// Ref: [5.0:56-57], [5.1:60-62], [5.2:190-191]
4759//
4760// when-clause ->
4761// WHEN (context-selector :
4762// [directive-specification]) // since 5.0
4764 TUPLE_CLASS_BOILERPLATE(OmpWhenClause);
4765 MODIFIER_BOILERPLATE(OmpContextSelector);
4766 std::tuple<MODIFIERS(),
4767 std::optional<common::Indirection<OmpDirectiveSpecification>>>
4768 t;
4769};
4770
4771// REF: [5.1:217-220], [5.2:293-294]
4772//
4773// init-clause -> INIT ([interop-modifier,] [interop-type,]
4774// interop-type: interop-var)
4775// interop-modifier: prefer_type(preference-list)
4776// interop-type: target, targetsync
4777// interop-var: Ompobject
4778// There can be at most only two interop-type.
4780 TUPLE_CLASS_BOILERPLATE(OmpInitClause);
4781 MODIFIER_BOILERPLATE(OmpInteropPreference, OmpInteropType);
4782 std::tuple<MODIFIERS(), OmpObject> t;
4783};
4784
4785// REF: [5.1:217-220], [5.2:294]
4786//
4787// 14.1.3 use-clause -> USE (interop-var)
4788WRAPPER_CLASS(OmpUseClause, OmpObject);
4789
4790// OpenMP Clauses
4792 UNION_CLASS_BOILERPLATE(OmpClause);
4793 llvm::omp::Clause Id() const;
4794
4795#define GEN_FLANG_CLAUSE_PARSER_CLASSES
4796#include "llvm/Frontend/OpenMP/OMP.inc"
4797
4798 CharBlock source;
4799
4800 std::variant<
4801#define GEN_FLANG_CLAUSE_PARSER_CLASSES_LIST
4802#include "llvm/Frontend/OpenMP/OMP.inc"
4803 >
4804 u;
4805};
4806
4808 WRAPPER_CLASS_BOILERPLATE(OmpClauseList, std::list<OmpClause>);
4809 CharBlock source;
4810};
4811
4812// --- Directives and constructs
4813
4815 ENUM_CLASS(Flags, None, DeprecatedSyntax);
4816 TUPLE_CLASS_BOILERPLATE(OmpDirectiveSpecification);
4817 const OmpDirectiveName &DirName() const {
4818 return std::get<OmpDirectiveName>(t);
4819 }
4820 llvm::omp::Directive DirId() const { //
4821 return DirName().v;
4822 }
4823 const OmpArgumentList &Arguments() const;
4824 const OmpClauseList &Clauses() const;
4825
4826 CharBlock source;
4827 std::tuple<OmpDirectiveName, std::optional<OmpArgumentList>,
4828 std::optional<OmpClauseList>, Flags>
4829 t;
4830};
4831
4832// OmpBeginDirective and OmpEndDirective are needed for semantic analysis,
4833// where some checks are done specifically for either the begin or the end
4834// directive. The structure of both is identical, but the diffent types
4835// allow to distinguish them in the type-based parse-tree visitor.
4837 INHERITED_TUPLE_CLASS_BOILERPLATE(
4839};
4840
4842 INHERITED_TUPLE_CLASS_BOILERPLATE(OmpEndDirective, OmpDirectiveSpecification);
4843};
4844
4845// Common base class for block-associated constructs.
4847 TUPLE_CLASS_BOILERPLATE(OmpBlockConstruct);
4848 const OmpBeginDirective &BeginDir() const {
4849 return std::get<OmpBeginDirective>(t);
4850 }
4851 const std::optional<OmpEndDirective> &EndDir() const {
4852 return std::get<std::optional<OmpEndDirective>>(t);
4853 }
4854
4855 CharBlock source;
4856 std::tuple<OmpBeginDirective, Block, std::optional<OmpEndDirective>> t;
4857};
4858
4860 WRAPPER_CLASS_BOILERPLATE(
4862};
4863
4864// Ref: [5.1:89-90], [5.2:216]
4865//
4866// nothing-directive ->
4867// NOTHING // since 5.1
4869 WRAPPER_CLASS_BOILERPLATE(OmpNothingDirective, OmpDirectiveSpecification);
4870};
4871
4872// Ref: OpenMP [5.2:216-218]
4873// ERROR AT(compilation|execution) SEVERITY(fatal|warning) MESSAGE("msg-str)
4875 WRAPPER_CLASS_BOILERPLATE(OmpErrorDirective, OmpDirectiveSpecification);
4876};
4877
4879 UNION_CLASS_BOILERPLATE(OpenMPUtilityConstruct);
4880 CharBlock source;
4881 std::variant<OmpErrorDirective, OmpNothingDirective> u;
4882};
4883
4884// Ref: [5.2: 213-216]
4885//
4886// assumes-construct ->
4887// ASSUMES absent-clause | contains-clause | holds-clause | no-openmp-clause |
4888// no-openmp-routines-clause | no-parallelism-clause
4890 WRAPPER_CLASS_BOILERPLATE(
4892 CharBlock source;
4893};
4894
4895// Ref: [5.1:86-89], [5.2:215], [6.0:369]
4896//
4897// assume-directive -> // since 5.1
4898// ASSUME assumption-clause...
4899// block
4900// [END ASSUME]
4902 INHERITED_TUPLE_CLASS_BOILERPLATE(OpenMPAssumeConstruct, OmpBlockConstruct);
4903};
4904
4905// 2.7.2 SECTIONS
4906// 2.11.2 PARALLEL SECTIONS
4908 INHERITED_TUPLE_CLASS_BOILERPLATE(
4910};
4911
4913 INHERITED_TUPLE_CLASS_BOILERPLATE(OmpEndSectionsDirective, OmpEndDirective);
4914};
4915
4916// [!$omp section]
4917// structured-block
4918// [!$omp section
4919// structured-block]
4920// ...
4922 TUPLE_CLASS_BOILERPLATE(OpenMPSectionConstruct);
4923 std::tuple<std::optional<OmpDirectiveSpecification>, Block> t;
4924 CharBlock source;
4925};
4926
4928 TUPLE_CLASS_BOILERPLATE(OpenMPSectionsConstruct);
4929 CharBlock source;
4930 const OmpBeginSectionsDirective &BeginDir() const {
4931 return std::get<OmpBeginSectionsDirective>(t);
4932 }
4933 const std::optional<OmpEndSectionsDirective> &EndDir() const {
4934 return std::get<std::optional<OmpEndSectionsDirective>>(t);
4935 }
4936 // Each of the OpenMPConstructs in the list below contains an
4937 // OpenMPSectionConstruct. This is guaranteed by the parser.
4938 // The end sections directive is optional here because it is difficult to
4939 // generate helpful error messages for a missing end directive within the
4940 // parser. Semantics will generate an error if this is absent.
4941 std::tuple<OmpBeginSectionsDirective, std::list<OpenMPConstruct>,
4942 std::optional<OmpEndSectionsDirective>>
4943 t;
4944};
4945
4946// Ref: [4.5:58-60], [5.0:58-60], [5.1:63-68], [5.2:197-198], [6.0:334-336]
4947//
4948// declare-variant-directive ->
4949// DECLARE_VARIANT([base-name:]variant-name) // since 4.5
4951 WRAPPER_CLASS_BOILERPLATE(
4953 CharBlock source;
4954};
4955
4956// Ref: [4.5:110-113], [5.0:180-185], [5.1:210-216], [5.2:206-207],
4957// [6.0:346-348]
4958//
4959// declare-target-directive -> // since 4.5
4960// DECLARE_TARGET[(extended-list)] |
4961// DECLARE_TARGET clause-list
4963 WRAPPER_CLASS_BOILERPLATE(
4965 CharBlock source;
4966};
4967
4968// OMP v5.2: 5.8.8
4969// declare-mapper -> DECLARE MAPPER ([mapper-name :] type :: var) map-clauses
4971 WRAPPER_CLASS_BOILERPLATE(
4973 CharBlock source;
4974};
4975
4976// ref: 5.2: Section 5.5.11 139-141
4977// 2.16 declare-reduction -> DECLARE REDUCTION (reduction-identifier : type-list
4978// : combiner) [initializer-clause]
4980 WRAPPER_CLASS_BOILERPLATE(
4982 CharBlock source;
4983};
4984
4985// 2.8.2 declare-simd -> DECLARE SIMD [(proc-name)] [declare-simd-clause[ [,]
4986// declare-simd-clause]...]
4988 WRAPPER_CLASS_BOILERPLATE(
4990 CharBlock source;
4991};
4992
4993// ref: [6.0:301-303]
4994//
4995// groupprivate-directive ->
4996// GROUPPRIVATE (variable-list-item...) // since 6.0
4998 WRAPPER_CLASS_BOILERPLATE(OpenMPGroupprivate, OmpDirectiveSpecification);
4999 CharBlock source;
5000};
5001
5002// 2.4 requires -> REQUIRES requires-clause[ [ [,] requires-clause]...]
5004 WRAPPER_CLASS_BOILERPLATE(OpenMPRequiresConstruct, OmpDirectiveSpecification);
5005 CharBlock source;
5006};
5007
5008// 2.15.2 threadprivate -> THREADPRIVATE (variable-name-list)
5010 WRAPPER_CLASS_BOILERPLATE(OpenMPThreadprivate, OmpDirectiveSpecification);
5011 CharBlock source;
5012};
5013
5014// 2.11.3 allocate -> ALLOCATE (variable-name-list) [clause]
5016 TUPLE_CLASS_BOILERPLATE(OpenMPDeclarativeAllocate);
5017 CharBlock source;
5018 std::tuple<Verbatim, OmpObjectList, OmpClauseList> t;
5019};
5020
5032
5034 INHERITED_TUPLE_CLASS_BOILERPLATE(OpenMPCriticalConstruct, OmpBlockConstruct);
5035};
5036
5037// 2.11.3 allocate -> ALLOCATE [(variable-name-list)] [clause]
5038// [ALLOCATE (variable-name-list) [clause] [...]]
5039// allocate-statement
5040// clause -> allocator-clause
5042 TUPLE_CLASS_BOILERPLATE(OpenMPExecutableAllocate);
5043 CharBlock source;
5044 std::tuple<Verbatim, std::optional<OmpObjectList>, OmpClauseList,
5045 std::optional<std::list<OpenMPDeclarativeAllocate>>,
5047 t;
5048};
5049
5050// Ref: [5.2:180-181], [6.0:315]
5051//
5052// allocators-construct ->
5053// ALLOCATORS [allocate-clause...]
5054// block
5055// [END ALLOCATORS]
5057 INHERITED_TUPLE_CLASS_BOILERPLATE(
5059};
5060
5062 llvm::omp::Clause GetKind() const;
5063 bool IsCapture() const;
5064 bool IsCompare() const;
5065 INHERITED_TUPLE_CLASS_BOILERPLATE(OpenMPAtomicConstruct, OmpBlockConstruct);
5066
5067 // Information filled out during semantic checks to avoid duplication
5068 // of analyses.
5069 struct Analysis {
5070 static constexpr int None = 0;
5071 static constexpr int Read = 1;
5072 static constexpr int Write = 2;
5073 static constexpr int Update = Read | Write;
5074 static constexpr int Action = 3; // Bitmask for None, Read, Write, Update
5075 static constexpr int IfTrue = 4;
5076 static constexpr int IfFalse = 8;
5077 static constexpr int Condition = 12; // Bitmask for IfTrue, IfFalse
5078
5079 struct Op {
5080 int what;
5081 AssignmentStmt::TypedAssignment assign;
5082 };
5083 TypedExpr atom, cond;
5084 Op op0, op1;
5085 };
5086
5087 mutable Analysis analysis;
5088};
5089
5090// 2.14.2 cancellation-point -> CANCELLATION POINT construct-type-clause
5092 WRAPPER_CLASS_BOILERPLATE(
5094 CharBlock source;
5095};
5096
5097// 2.14.1 cancel -> CANCEL construct-type-clause [ [,] if-clause]
5099 WRAPPER_CLASS_BOILERPLATE(OpenMPCancelConstruct, OmpDirectiveSpecification);
5100 CharBlock source;
5101};
5102
5103// Ref: [5.0:254-255], [5.1:287-288], [5.2:322-323]
5104//
5105// depobj-construct -> DEPOBJ(depend-object) depobj-clause // since 5.0
5106// depobj-clause -> depend-clause | // until 5.2
5107// destroy-clause |
5108// update-clause
5110 WRAPPER_CLASS_BOILERPLATE(OpenMPDepobjConstruct, OmpDirectiveSpecification);
5111 CharBlock source;
5112};
5113
5114// Ref: [5.2: 200-201]
5115//
5116// dispatch-construct -> DISPATCH dispatch-clause
5117// dispatch-clause -> depend-clause |
5118// device-clause |
5119// is_device_ptr-clause |
5120// nocontext-clause |
5121// novariants-clause |
5122// nowait-clause
5124 INHERITED_TUPLE_CLASS_BOILERPLATE(OpenMPDispatchConstruct, OmpBlockConstruct);
5125};
5126
5127// [4.5:162-165], [5.0:242-246], [5.1:275-279], [5.2:315-316], [6.0:498-500]
5128//
5129// flush-construct ->
5130// FLUSH [(list)] // since 4.5, until 4.5
5131// flush-construct ->
5132// FLUSH [memory-order-clause] [(list)] // since 5.0, until 5.1
5133// flush-construct ->
5134// FLUSH [(list)] [clause-list] // since 5.2
5135//
5136// memory-order-clause -> // since 5.0, until 5.1
5137// ACQ_REL | RELEASE | ACQUIRE | // since 5.0
5138// SEQ_CST // since 5.1
5140 WRAPPER_CLASS_BOILERPLATE(OpenMPFlushConstruct, OmpDirectiveSpecification);
5141 CharBlock source;
5142};
5143
5144// Ref: [5.1:217-220], [5.2:291-292]
5145//
5146// interop -> INTEROP clause[ [ [,] clause]...]
5148 WRAPPER_CLASS_BOILERPLATE(OpenMPInteropConstruct, OmpDirectiveSpecification);
5149 CharBlock source;
5150};
5151
5153 WRAPPER_CLASS_BOILERPLATE(
5155 CharBlock source;
5156};
5157
5166
5168 INHERITED_TUPLE_CLASS_BOILERPLATE(OmpBeginLoopDirective, OmpBeginDirective);
5169};
5170
5172 INHERITED_TUPLE_CLASS_BOILERPLATE(OmpEndLoopDirective, OmpEndDirective);
5173};
5174
5175// OpenMP directives enclosing do loop
5176using NestedConstruct =
5177 std::variant<DoConstruct, common::Indirection<OpenMPLoopConstruct>>;
5178struct OpenMPLoopConstruct {
5179 TUPLE_CLASS_BOILERPLATE(OpenMPLoopConstruct);
5180 OpenMPLoopConstruct(OmpBeginLoopDirective &&a)
5181 : t({std::move(a), std::nullopt, std::nullopt}) {}
5182
5183 const OmpBeginLoopDirective &BeginDir() const {
5184 return std::get<OmpBeginLoopDirective>(t);
5185 }
5186 const std::optional<OmpEndLoopDirective> &EndDir() const {
5187 return std::get<std::optional<OmpEndLoopDirective>>(t);
5188 }
5189 std::tuple<OmpBeginLoopDirective, std::optional<NestedConstruct>,
5190 std::optional<OmpEndLoopDirective>>
5191 t;
5192};
5193
5194// Lookahead class to identify execution-part OpenMP constructs without
5195// parsing the entire OpenMP construct.
5197 WRAPPER_CLASS_BOILERPLATE(OpenMPExecDirective, OmpDirectiveName);
5198 CharBlock source;
5199};
5200
5210
5211// Parse tree nodes for OpenACC 3.3 directives and clauses
5212
5214 UNION_CLASS_BOILERPLATE(AccObject);
5215 std::variant<Designator, /*common block*/ Name> u;
5216};
5217
5218WRAPPER_CLASS(AccObjectList, std::list<AccObject>);
5219
5220// OpenACC directive beginning or ending a block
5222 WRAPPER_CLASS_BOILERPLATE(AccBlockDirective, llvm::acc::Directive);
5223 CharBlock source;
5224};
5225
5227 WRAPPER_CLASS_BOILERPLATE(AccLoopDirective, llvm::acc::Directive);
5228 CharBlock source;
5229};
5230
5232 WRAPPER_CLASS_BOILERPLATE(AccStandaloneDirective, llvm::acc::Directive);
5233 CharBlock source;
5234};
5235
5236// 2.11 Combined constructs
5238 WRAPPER_CLASS_BOILERPLATE(AccCombinedDirective, llvm::acc::Directive);
5239 CharBlock source;
5240};
5241
5243 WRAPPER_CLASS_BOILERPLATE(AccDeclarativeDirective, llvm::acc::Directive);
5244 CharBlock source;
5245};
5246
5247// OpenACC Clauses
5249 UNION_CLASS_BOILERPLATE(AccBindClause);
5250 std::variant<Name, ScalarDefaultCharExpr> u;
5251 CharBlock source;
5252};
5253
5255 WRAPPER_CLASS_BOILERPLATE(AccDefaultClause, llvm::acc::DefaultValue);
5256 CharBlock source;
5257};
5258
5260 ENUM_CLASS(Modifier, ReadOnly, Zero)
5261 WRAPPER_CLASS_BOILERPLATE(AccDataModifier, Modifier);
5262 CharBlock source;
5263};
5264
5266 TUPLE_CLASS_BOILERPLATE(AccObjectListWithModifier);
5267 std::tuple<std::optional<AccDataModifier>, AccObjectList> t;
5268};
5269
5271 TUPLE_CLASS_BOILERPLATE(AccObjectListWithReduction);
5272 std::tuple<ReductionOperator, AccObjectList> t;
5273};
5274
5276 TUPLE_CLASS_BOILERPLATE(AccWaitArgument);
5277 std::tuple<std::optional<ScalarIntExpr>, std::list<ScalarIntExpr>> t;
5278};
5279
5281 WRAPPER_CLASS_BOILERPLATE(
5282 AccDeviceTypeExpr, Fortran::common::OpenACCDeviceType);
5283 CharBlock source;
5284};
5285
5287 WRAPPER_CLASS_BOILERPLATE(
5288 AccDeviceTypeExprList, std::list<AccDeviceTypeExpr>);
5289};
5290
5292 TUPLE_CLASS_BOILERPLATE(AccTileExpr);
5293 CharBlock source;
5294 std::tuple<std::optional<ScalarIntConstantExpr>> t; // if null then *
5295};
5296
5298 WRAPPER_CLASS_BOILERPLATE(AccTileExprList, std::list<AccTileExpr>);
5299};
5300
5302 WRAPPER_CLASS_BOILERPLATE(AccSizeExpr, std::optional<ScalarIntExpr>);
5303};
5304
5306 WRAPPER_CLASS_BOILERPLATE(AccSizeExprList, std::list<AccSizeExpr>);
5307};
5308
5310 UNION_CLASS_BOILERPLATE(AccSelfClause);
5311 std::variant<std::optional<ScalarLogicalExpr>, AccObjectList> u;
5312 CharBlock source;
5313};
5314
5315// num, dim, static
5317 UNION_CLASS_BOILERPLATE(AccGangArg);
5318 WRAPPER_CLASS(Num, ScalarIntExpr);
5319 WRAPPER_CLASS(Dim, ScalarIntExpr);
5320 WRAPPER_CLASS(Static, AccSizeExpr);
5321 std::variant<Num, Dim, Static> u;
5322 CharBlock source;
5323};
5324
5326 WRAPPER_CLASS_BOILERPLATE(AccGangArgList, std::list<AccGangArg>);
5327};
5328
5330 TUPLE_CLASS_BOILERPLATE(AccCollapseArg);
5331 std::tuple<bool, ScalarIntConstantExpr> t;
5332};
5333
5335 UNION_CLASS_BOILERPLATE(AccClause);
5336
5337#define GEN_FLANG_CLAUSE_PARSER_CLASSES
5338#include "llvm/Frontend/OpenACC/ACC.inc"
5339
5340 CharBlock source;
5341
5342 std::variant<
5343#define GEN_FLANG_CLAUSE_PARSER_CLASSES_LIST
5344#include "llvm/Frontend/OpenACC/ACC.inc"
5345 >
5346 u;
5347};
5348
5350 WRAPPER_CLASS_BOILERPLATE(AccClauseList, std::list<AccClause>);
5351 CharBlock source;
5352};
5353
5355 TUPLE_CLASS_BOILERPLATE(OpenACCRoutineConstruct);
5356 CharBlock source;
5357 std::tuple<Verbatim, std::optional<Name>, AccClauseList> t;
5358};
5359
5361 TUPLE_CLASS_BOILERPLATE(OpenACCCacheConstruct);
5362 CharBlock source;
5363 std::tuple<Verbatim, AccObjectListWithModifier> t;
5364};
5365
5367 TUPLE_CLASS_BOILERPLATE(OpenACCWaitConstruct);
5368 CharBlock source;
5369 std::tuple<Verbatim, std::optional<AccWaitArgument>, AccClauseList> t;
5370};
5371
5373 TUPLE_CLASS_BOILERPLATE(AccBeginLoopDirective);
5374 std::tuple<AccLoopDirective, AccClauseList> t;
5375 CharBlock source;
5376};
5377
5379 TUPLE_CLASS_BOILERPLATE(AccBeginBlockDirective);
5380 CharBlock source;
5381 std::tuple<AccBlockDirective, AccClauseList> t;
5382};
5383
5385 CharBlock source;
5386 WRAPPER_CLASS_BOILERPLATE(AccEndBlockDirective, AccBlockDirective);
5387};
5388
5389// ACC END ATOMIC
5390EMPTY_CLASS(AccEndAtomic);
5391
5392// ACC ATOMIC READ
5394 TUPLE_CLASS_BOILERPLATE(AccAtomicRead);
5395 std::tuple<Verbatim, AccClauseList, Statement<AssignmentStmt>,
5396 std::optional<AccEndAtomic>>
5397 t;
5398};
5399
5400// ACC ATOMIC WRITE
5402 TUPLE_CLASS_BOILERPLATE(AccAtomicWrite);
5403 std::tuple<Verbatim, AccClauseList, Statement<AssignmentStmt>,
5404 std::optional<AccEndAtomic>>
5405 t;
5406};
5407
5408// ACC ATOMIC UPDATE
5410 TUPLE_CLASS_BOILERPLATE(AccAtomicUpdate);
5411 std::tuple<std::optional<Verbatim>, AccClauseList, Statement<AssignmentStmt>,
5412 std::optional<AccEndAtomic>>
5413 t;
5414};
5415
5416// ACC ATOMIC CAPTURE
5418 TUPLE_CLASS_BOILERPLATE(AccAtomicCapture);
5419 WRAPPER_CLASS(Stmt1, Statement<AssignmentStmt>);
5420 WRAPPER_CLASS(Stmt2, Statement<AssignmentStmt>);
5421 std::tuple<Verbatim, AccClauseList, Stmt1, Stmt2, AccEndAtomic> t;
5422};
5423
5425 UNION_CLASS_BOILERPLATE(OpenACCAtomicConstruct);
5426 std::variant<AccAtomicRead, AccAtomicWrite, AccAtomicCapture, AccAtomicUpdate>
5427 u;
5428 CharBlock source;
5429};
5430
5432 TUPLE_CLASS_BOILERPLATE(OpenACCBlockConstruct);
5433 std::tuple<AccBeginBlockDirective, Block, AccEndBlockDirective> t;
5434};
5435
5437 TUPLE_CLASS_BOILERPLATE(OpenACCStandaloneDeclarativeConstruct);
5438 CharBlock source;
5439 std::tuple<AccDeclarativeDirective, AccClauseList> t;
5440};
5441
5443 TUPLE_CLASS_BOILERPLATE(AccBeginCombinedDirective);
5444 CharBlock source;
5445 std::tuple<AccCombinedDirective, AccClauseList> t;
5446};
5447
5449 WRAPPER_CLASS_BOILERPLATE(AccEndCombinedDirective, AccCombinedDirective);
5450 CharBlock source;
5451};
5452
5453struct OpenACCCombinedConstruct {
5454 TUPLE_CLASS_BOILERPLATE(OpenACCCombinedConstruct);
5455 CharBlock source;
5456 OpenACCCombinedConstruct(AccBeginCombinedDirective &&a)
5457 : t({std::move(a), std::nullopt, std::nullopt}) {}
5458 std::tuple<AccBeginCombinedDirective, std::optional<DoConstruct>,
5459 std::optional<AccEndCombinedDirective>>
5460 t;
5461};
5462
5464 UNION_CLASS_BOILERPLATE(OpenACCDeclarativeConstruct);
5465 CharBlock source;
5466 std::variant<OpenACCStandaloneDeclarativeConstruct, OpenACCRoutineConstruct>
5467 u;
5468};
5469
5470// OpenACC directives enclosing do loop
5471EMPTY_CLASS(AccEndLoop);
5472struct OpenACCLoopConstruct {
5473 TUPLE_CLASS_BOILERPLATE(OpenACCLoopConstruct);
5474 OpenACCLoopConstruct(AccBeginLoopDirective &&a)
5475 : t({std::move(a), std::nullopt, std::nullopt}) {}
5476 std::tuple<AccBeginLoopDirective, std::optional<DoConstruct>,
5477 std::optional<AccEndLoop>>
5478 t;
5479};
5480
5482 WRAPPER_CLASS_BOILERPLATE(OpenACCEndConstruct, llvm::acc::Directive);
5483 CharBlock source;
5484};
5485
5487 TUPLE_CLASS_BOILERPLATE(OpenACCStandaloneConstruct);
5488 CharBlock source;
5489 std::tuple<AccStandaloneDirective, AccClauseList> t;
5490};
5491
5499
5500// CUF-kernel-do-construct ->
5501// !$CUF KERNEL DO [ (scalar-int-constant-expr) ]
5502// <<< grid, block [, stream] >>>
5503// [ cuf-reduction... ]
5504// do-construct
5505// star-or-expr -> * | scalar-int-expr
5506// grid -> * | scalar-int-expr | ( star-or-expr-list )
5507// block -> * | scalar-int-expr | ( star-or-expr-list )
5508// stream -> 0, scalar-int-expr | STREAM = scalar-int-expr
5509// cuf-reduction -> [ REDUCE | REDUCTION ] (
5510// reduction-op : scalar-variable-list )
5511
5513 TUPLE_CLASS_BOILERPLATE(CUFReduction);
5514 using Operator = ReductionOperator;
5515 std::tuple<Operator, std::list<Scalar<Variable>>> t;
5516};
5517
5519 TUPLE_CLASS_BOILERPLATE(CUFKernelDoConstruct);
5520 WRAPPER_CLASS(StarOrExpr, std::optional<ScalarIntExpr>);
5522 TUPLE_CLASS_BOILERPLATE(LaunchConfiguration);
5523 std::tuple<std::list<StarOrExpr>, std::list<StarOrExpr>,
5524 std::optional<ScalarIntExpr>>
5525 t;
5526 };
5527 struct Directive {
5528 TUPLE_CLASS_BOILERPLATE(Directive);
5529 CharBlock source;
5530 std::tuple<std::optional<ScalarIntConstantExpr>,
5531 std::optional<LaunchConfiguration>, std::list<CUFReduction>>
5532 t;
5533 };
5534 std::tuple<Directive, std::optional<DoConstruct>> t;
5535};
5536
5537} // namespace Fortran::parser
5538#endif // FORTRAN_PARSER_PARSE_TREE_H_
Definition indirection.h:127
Definition indirection.h:31
Definition call.h:232
Definition char-block.h:28
Definition symbol.h:781
Definition call.h:34
Definition check-expression.h:19
Definition expression.h:896
Definition format-specification.h:135
Definition parse-tree.h:1303
Definition parse-tree.h:1310
Definition parse-tree.h:1269
Definition parse-tree.h:1258
Definition parse-tree.h:1257
Definition parse-tree.h:5417
Definition parse-tree.h:5393
Definition parse-tree.h:5409
Definition parse-tree.h:5401
Definition parse-tree.h:5378
Definition parse-tree.h:5442
Definition parse-tree.h:5372
Definition parse-tree.h:5248
Definition parse-tree.h:5221
Definition parse-tree.h:5349
Definition parse-tree.h:5334
Definition parse-tree.h:5329
Definition parse-tree.h:5237
Definition parse-tree.h:5259
Definition parse-tree.h:5242
Definition parse-tree.h:5254
Definition parse-tree.h:5286
Definition parse-tree.h:5280
Definition parse-tree.h:5384
Definition parse-tree.h:5448
Definition parse-tree.h:5325
Definition parse-tree.h:5316
Definition parse-tree.h:5226
Definition parse-tree.h:5265
Definition parse-tree.h:5213
Definition parse-tree.h:5309
Definition parse-tree.h:5305
Definition parse-tree.h:5301
Definition parse-tree.h:5231
Definition parse-tree.h:5297
Definition parse-tree.h:5291
Definition parse-tree.h:5275
Definition parse-tree.h:909
Definition parse-tree.h:1427
Definition parse-tree.h:490
Definition parse-tree.h:3253
Definition parse-tree.h:3243
Definition parse-tree.h:1980
Definition parse-tree.h:1945
Definition parse-tree.h:1924
Definition parse-tree.h:1936
Definition parse-tree.h:1991
Definition parse-tree.h:1953
Definition parse-tree.h:3451
Definition parse-tree.h:1912
Definition parse-tree.h:1358
Definition parse-tree.h:3456
Definition parse-tree.h:3461
Definition parse-tree.h:2017
Definition parse-tree.h:2174
Definition parse-tree.h:2165
Definition parse-tree.h:2158
Definition parse-tree.h:1340
Definition parse-tree.h:1388
Definition parse-tree.h:3401
Definition parse-tree.h:1127
Definition parse-tree.h:1449
Definition parse-tree.h:1456
Definition parse-tree.h:2196
Definition parse-tree.h:3028
Definition parse-tree.h:2029
Definition parse-tree.h:3395
Definition parse-tree.h:5518
Definition parse-tree.h:5512
Definition parse-tree.h:3280
Definition parse-tree.h:3277
Definition parse-tree.h:3260
Definition parse-tree.h:2439
Definition parse-tree.h:2438
Definition parse-tree.h:2420
Definition parse-tree.h:2426
Definition parse-tree.h:2406
Definition parse-tree.h:2227
Definition parse-tree.h:2212
Definition parse-tree.h:663
Definition parse-tree.h:868
Definition parse-tree.h:679
Definition parse-tree.h:2697
Definition parse-tree.h:2696
Definition parse-tree.h:2204
Definition parse-tree.h:984
Definition parse-tree.h:1462
Definition parse-tree.h:1903
Definition parse-tree.h:1626
Definition parse-tree.h:1635
Definition parse-tree.h:1634
Definition parse-tree.h:3377
Definition parse-tree.h:3359
Definition parse-tree.h:854
Definition parse-tree.h:846
Definition parse-tree.h:995
Definition parse-tree.h:1008
Definition parse-tree.h:1116
Definition parse-tree.h:1061
Definition parse-tree.h:1220
Definition parse-tree.h:2525
Definition parse-tree.h:2252
Definition parse-tree.h:2261
Definition parse-tree.h:2674
Definition parse-tree.h:2672
Definition parse-tree.h:300
Definition parse-tree.h:2243
Definition parse-tree.h:2234
Definition parse-tree.h:1069
Definition parse-tree.h:1516
Definition parse-tree.h:1528
Definition parse-tree.h:1819
Definition parse-tree.h:1487
Definition parse-tree.h:1536
Definition parse-tree.h:1502
Definition parse-tree.h:1542
Definition parse-tree.h:1508
Definition parse-tree.h:2011
Definition parse-tree.h:431
Definition parse-tree.h:768
Definition parse-tree.h:324
Definition parse-tree.h:605
Definition parse-tree.h:1205
Definition parse-tree.h:750
Definition parse-tree.h:926
Definition parse-tree.h:1858
Definition parse-tree.h:1553
Definition parse-tree.h:2339
Definition parse-tree.h:3161
Definition parse-tree.h:2359
Definition parse-tree.h:2221
Definition parse-tree.h:3333
Definition parse-tree.h:1249
Definition parse-tree.h:1235
Definition parse-tree.h:2579
Definition parse-tree.h:2585
Definition parse-tree.h:2593
Definition parse-tree.h:523
Definition parse-tree.h:547
Definition parse-tree.h:978
Definition parse-tree.h:965
Definition parse-tree.h:1765
Definition parse-tree.h:1738
Definition parse-tree.h:1779
Definition parse-tree.h:1744
Definition parse-tree.h:1783
Definition parse-tree.h:1720
Definition parse-tree.h:1735
Definition parse-tree.h:1771
Definition parse-tree.h:1753
Definition parse-tree.h:1759
Definition parse-tree.h:1762
Definition parse-tree.h:1725
Definition parse-tree.h:1750
Definition parse-tree.h:1747
Definition parse-tree.h:1732
Definition parse-tree.h:1774
Definition parse-tree.h:1756
Definition parse-tree.h:1714
Definition parse-tree.h:1711
Definition parse-tree.h:1768
Definition parse-tree.h:1705
Definition parse-tree.h:1729
Definition parse-tree.h:1741
Definition parse-tree.h:1708
Definition parse-tree.h:1701
Definition parse-tree.h:1055
Definition parse-tree.h:2115
Definition parse-tree.h:2131
Definition parse-tree.h:2109
Definition parse-tree.h:2144
Definition parse-tree.h:2121
Definition parse-tree.h:2605
Definition parse-tree.h:2708
Definition parse-tree.h:3265
Definition parse-tree.h:3150
Definition parse-tree.h:3299
Definition parse-tree.h:3041
Definition parse-tree.h:3056
Definition parse-tree.h:2378
Definition parse-tree.h:2374
Definition parse-tree.h:2373
Definition parse-tree.h:2389
Definition parse-tree.h:2352
Definition parse-tree.h:1686
Definition parse-tree.h:1695
Definition parse-tree.h:413
Definition parse-tree.h:1610
Definition parse-tree.h:1619
Definition parse-tree.h:618
Definition parse-tree.h:1026
Definition parse-tree.h:2803
Definition parse-tree.h:2747
Definition parse-tree.h:2890
Definition parse-tree.h:2898
Definition parse-tree.h:2903
Definition parse-tree.h:2888
Definition parse-tree.h:2918
Definition parse-tree.h:2916
Definition parse-tree.h:802
Definition parse-tree.h:308
Definition parse-tree.h:1366
Definition parse-tree.h:1562
Definition parse-tree.h:3217
Definition parse-tree.h:3184
Definition parse-tree.h:3190
Definition parse-tree.h:3182
Definition parse-tree.h:3207
Definition parse-tree.h:469
Definition parse-tree.h:457
Definition parse-tree.h:702
Definition parse-tree.h:700
Definition parse-tree.h:2732
Definition parse-tree.h:2730
Definition parse-tree.h:2644
Definition parse-tree.h:789
Definition parse-tree.h:651
Definition parse-tree.h:2316
Definition parse-tree.h:1319
Definition parse-tree.h:669
Definition parse-tree.h:1604
Definition parse-tree.h:900
Definition parse-tree.h:2288
Definition parse-tree.h:2284
Definition parse-tree.h:2620
Definition parse-tree.h:2619
Definition parse-tree.h:882
Definition parse-tree.h:316
Definition parse-tree.h:1284
Definition parse-tree.h:2306
Definition parse-tree.h:2304
Definition parse-tree.h:2937
Definition parse-tree.h:3417
Definition parse-tree.h:2076
Definition parse-tree.h:2961
Definition parse-tree.h:2951
Definition parse-tree.h:2972
Definition parse-tree.h:580
Definition parse-tree.h:1325
Definition parse-tree.h:632
Definition parse-tree.h:631
Definition parse-tree.h:2322
Definition parse-tree.h:2547
Definition parse-tree.h:1436
Definition parse-tree.h:4159
Definition parse-tree.h:4163
Definition parse-tree.h:4178
Definition parse-tree.h:4185
Definition parse-tree.h:4193
Definition parse-tree.h:4208
Definition parse-tree.h:4215
Definition parse-tree.h:4224
Definition parse-tree.h:4836
Definition parse-tree.h:5167
Definition parse-tree.h:4907
Definition parse-tree.h:4247
Definition parse-tree.h:4846
Definition parse-tree.h:4807
Definition parse-tree.h:4791
Definition parse-tree.h:4262
Definition parse-tree.h:4279
Definition parse-tree.h:4297
Definition parse-tree.h:4354
Definition parse-tree.h:4352
Definition parse-tree.h:4380
Definition parse-tree.h:4390
Definition parse-tree.h:4400
Definition parse-tree.h:3487
Definition parse-tree.h:4814
Definition parse-tree.h:4334
Definition parse-tree.h:4405
Definition parse-tree.h:4841
Definition parse-tree.h:5171
Definition parse-tree.h:4912
Definition parse-tree.h:4416
Definition parse-tree.h:4874
Definition parse-tree.h:4424
Definition parse-tree.h:4437
Definition parse-tree.h:4448
Definition parse-tree.h:4458
Definition parse-tree.h:4466
Definition parse-tree.h:4471
Definition parse-tree.h:4479
Definition parse-tree.h:4495
Definition parse-tree.h:4505
Definition parse-tree.h:4484
Definition parse-tree.h:4779
Definition parse-tree.h:4518
Definition parse-tree.h:4513
Definition parse-tree.h:4309
Definition parse-tree.h:4318
Definition parse-tree.h:4528
Definition parse-tree.h:4543
Definition parse-tree.h:4554
Definition parse-tree.h:4578
Definition parse-tree.h:4590
Definition parse-tree.h:4599
Definition parse-tree.h:4859
Definition parse-tree.h:4868
Definition parse-tree.h:4623
Definition parse-tree.h:3511
Definition parse-tree.h:3508
Definition parse-tree.h:4634
Definition parse-tree.h:4647
Definition parse-tree.h:4659
Definition parse-tree.h:4670
Definition parse-tree.h:3539
Definition parse-tree.h:3529
Definition parse-tree.h:4680
Definition parse-tree.h:4692
Definition parse-tree.h:4702
Definition parse-tree.h:4711
Definition parse-tree.h:4727
Definition parse-tree.h:4737
Definition parse-tree.h:4752
Definition parse-tree.h:4763
Definition parse-tree.h:3072
Definition parse-tree.h:5424
Definition parse-tree.h:5431
Definition parse-tree.h:5360
Definition parse-tree.h:5453
Definition parse-tree.h:5492
Definition parse-tree.h:5481
Definition parse-tree.h:5472
Definition parse-tree.h:5354
Definition parse-tree.h:5366
Definition parse-tree.h:5056
Definition parse-tree.h:4901
Definition parse-tree.h:5061
Definition parse-tree.h:5098
Definition parse-tree.h:5201
Definition parse-tree.h:5033
Definition parse-tree.h:5015
Definition parse-tree.h:4889
Definition parse-tree.h:5109
Definition parse-tree.h:5123
Definition parse-tree.h:5196
Definition parse-tree.h:5041
Definition parse-tree.h:5139
Definition parse-tree.h:4997
Definition parse-tree.h:5147
Definition parse-tree.h:5178
Definition parse-tree.h:5003
Definition parse-tree.h:4921
Definition parse-tree.h:4927
Definition parse-tree.h:5158
Definition parse-tree.h:5009
Definition parse-tree.h:4878
Definition parse-tree.h:372
Definition parse-tree.h:2808
Definition parse-tree.h:2771
Definition parse-tree.h:2997
Definition parse-tree.h:2041
Definition parse-tree.h:1572
Definition parse-tree.h:2000
Definition parse-tree.h:2834
Definition parse-tree.h:3117
Definition parse-tree.h:2792
Definition parse-tree.h:939
Definition parse-tree.h:3095
Definition parse-tree.h:1080
Definition parse-tree.h:1108
Definition parse-tree.h:1898
Definition parse-tree.h:1100
Definition parse-tree.h:1094
Definition parse-tree.h:1087
Definition parse-tree.h:3105
Definition parse-tree.h:3232
Definition parse-tree.h:3200
Definition parse-tree.h:564
Definition parse-tree.h:2755
Definition parse-tree.h:821
Definition parse-tree.h:2273
Definition parse-tree.h:2985
Definition parse-tree.h:2989
Definition parse-tree.h:2983
Definition parse-tree.h:1585
Definition parse-tree.h:292
Definition parse-tree.h:1672
Definition parse-tree.h:2396
Definition parse-tree.h:2462
Definition parse-tree.h:2461
Definition parse-tree.h:2473
Definition parse-tree.h:2452
Definition parse-tree.h:2507
Definition parse-tree.h:2487
Definition parse-tree.h:2152
Definition parse-tree.h:3325
Definition parse-tree.h:394
Definition parse-tree.h:445
Definition parse-tree.h:1969
Definition parse-tree.h:355
Definition parse-tree.h:3343
Definition parse-tree.h:2539
Definition parse-tree.h:1888
Definition parse-tree.h:1226
Definition parse-tree.h:3438
Definition parse-tree.h:3410
Definition parse-tree.h:3433
Definition parse-tree.h:3003
Definition parse-tree.h:3014
Definition parse-tree.h:3169
Definition parse-tree.h:3309
Definition parse-tree.h:1663
Definition parse-tree.h:1850
Definition parse-tree.h:1654
Definition parse-tree.h:1836
Definition parse-tree.h:2558
Definition parse-tree.h:2557
Definition parse-tree.h:2570
Definition parse-tree.h:917
Definition parse-tree.h:1169
Definition parse-tree.h:1182
Definition parse-tree.h:1135
Definition parse-tree.h:1191
Definition parse-tree.h:1145
Definition parse-tree.h:1417
Definition parse-tree.h:2497
Definition parse-tree.h:2496
Definition parse-tree.h:945
Definition parse-tree.h:953
Definition parse-tree.h:744
Definition parse-tree.h:642
Definition parse-tree.h:757
Definition parse-tree.h:3426
Definition parse-tree.h:350
Definition parse-tree.h:2629
Definition parse-tree.h:808
Definition parse-tree.h:3081
Definition parse-tree.h:1866
Definition parse-tree.h:730
Definition parse-tree.h:735
Definition parse-tree.h:279
Definition parse-tree.h:2818
Definition parse-tree.h:2067
Definition parse-tree.h:2060
Definition parse-tree.h:2096
Definition parse-tree.h:2091
Definition parse-tree.h:2054
Definition parse-tree.h:2777
Definition parse-tree.h:3596
Definition parse-tree.h:3552
Definition parse-tree.h:3760
Definition parse-tree.h:3769
Definition parse-tree.h:3914
Definition parse-tree.h:3941
Definition parse-tree.h:3963
Definition parse-tree.h:4002
Definition parse-tree.h:3989
Definition parse-tree.h:4081
Definition parse-tree.h:4091
Definition parse-tree.h:3643
Definition parse-tree.h:3626
Definition parse-tree.h:3667
Definition parse-tree.h:3633
Definition parse-tree.h:3694
Definition parse-tree.h:3706
Definition parse-tree.h:3719
Definition parse-tree.h:3728