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