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