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