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