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