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