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