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