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