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 | SIMPLE |
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 EMPTY_CLASS(Simple);
3118 WRAPPER_CLASS(Attributes, std::list<common::CUDASubprogramAttrs>);
3119 WRAPPER_CLASS(Launch_Bounds, std::list<ScalarIntConstantExpr>);
3120 WRAPPER_CLASS(Cluster_Dims, std::list<ScalarIntConstantExpr>);
3121 std::variant<DeclarationTypeSpec, Elemental, Impure, Module, Non_Recursive,
3122 Pure, Recursive, Simple, Attributes, Launch_Bounds, Cluster_Dims>
3123 u;
3124};
3125
3126// R1532 suffix ->
3127// proc-language-binding-spec [RESULT ( result-name )] |
3128// RESULT ( result-name ) [proc-language-binding-spec]
3129struct Suffix {
3130 TUPLE_CLASS_BOILERPLATE(Suffix);
3131 Suffix(LanguageBindingSpec &&lbs, std::optional<Name> &&rn)
3132 : t(std::move(rn), std::move(lbs)) {}
3133 std::tuple<std::optional<Name>, std::optional<LanguageBindingSpec>> t;
3134};
3135
3136// R1530 function-stmt ->
3137// [prefix] FUNCTION function-name ( [dummy-arg-name-list] ) [suffix]
3138// R1526 prefix -> prefix-spec [prefix-spec]...
3139// R1531 dummy-arg-name -> name
3141 TUPLE_CLASS_BOILERPLATE(FunctionStmt);
3142 std::tuple<std::list<PrefixSpec>, Name, std::list<Name>,
3143 std::optional<Suffix>>
3144 t;
3145};
3146
3147// R1533 end-function-stmt -> END [FUNCTION [function-name]]
3148WRAPPER_CLASS(EndFunctionStmt, std::optional<Name>);
3149
3150// R1536 dummy-arg -> dummy-arg-name | *
3151struct DummyArg {
3152 UNION_CLASS_BOILERPLATE(DummyArg);
3153 std::variant<Name, Star> u;
3154};
3155
3156// R1535 subroutine-stmt ->
3157// [prefix] SUBROUTINE subroutine-name [( [dummy-arg-list] )
3158// [proc-language-binding-spec]]
3160 TUPLE_CLASS_BOILERPLATE(SubroutineStmt);
3161 std::tuple<std::list<PrefixSpec>, Name, std::list<DummyArg>,
3162 std::optional<LanguageBindingSpec>>
3163 t;
3164};
3165
3166// R1537 end-subroutine-stmt -> END [SUBROUTINE [subroutine-name]]
3167WRAPPER_CLASS(EndSubroutineStmt, std::optional<Name>);
3168
3169// R1505 interface-body ->
3170// function-stmt [specification-part] end-function-stmt |
3171// subroutine-stmt [specification-part] end-subroutine-stmt
3173 UNION_CLASS_BOILERPLATE(InterfaceBody);
3174 struct Function {
3175 TUPLE_CLASS_BOILERPLATE(Function);
3176 std::tuple<Statement<FunctionStmt>, common::Indirection<SpecificationPart>,
3178 t;
3179 };
3180 struct Subroutine {
3181 TUPLE_CLASS_BOILERPLATE(Subroutine);
3182 std::tuple<Statement<SubroutineStmt>,
3184 t;
3185 };
3186 std::variant<Function, Subroutine> u;
3187};
3188
3189// R1506 procedure-stmt -> [MODULE] PROCEDURE [::] specific-procedure-list
3191 ENUM_CLASS(Kind, ModuleProcedure, Procedure)
3192 TUPLE_CLASS_BOILERPLATE(ProcedureStmt);
3193 std::tuple<Kind, std::list<Name>> t;
3194};
3195
3196// R1502 interface-specification -> interface-body | procedure-stmt
3198 UNION_CLASS_BOILERPLATE(InterfaceSpecification);
3199 std::variant<InterfaceBody, Statement<ProcedureStmt>> u;
3200};
3201
3202// R1504 end-interface-stmt -> END INTERFACE [generic-spec]
3203WRAPPER_CLASS(EndInterfaceStmt, std::optional<GenericSpec>);
3204
3205// R1501 interface-block ->
3206// interface-stmt [interface-specification]... end-interface-stmt
3208 TUPLE_CLASS_BOILERPLATE(InterfaceBlock);
3209 std::tuple<Statement<InterfaceStmt>, std::list<InterfaceSpecification>,
3211 t;
3212};
3213
3214// R1511 external-stmt -> EXTERNAL [::] external-name-list
3215WRAPPER_CLASS(ExternalStmt, std::list<Name>);
3216
3217// R1519 intrinsic-stmt -> INTRINSIC [::] intrinsic-procedure-name-list
3218WRAPPER_CLASS(IntrinsicStmt, std::list<Name>);
3219
3220// R1522 procedure-designator ->
3221// procedure-name | proc-component-ref | data-ref % binding-name
3223 UNION_CLASS_BOILERPLATE(ProcedureDesignator);
3224 std::variant<Name, ProcComponentRef> u;
3225};
3226
3227// R1525 alt-return-spec -> * label
3228WRAPPER_CLASS(AltReturnSpec, Label);
3229
3230// .NIL. (part of F2023 R1527)
3231EMPTY_CLASS(ConditionalArgNil);
3232
3233// F2023 R1526 conditional-arg ->
3234// ( scalar-logical-expr ? consequent
3235// [ : scalar-logical-expr ? consequent ]...
3236// : consequent )
3237// F2023 R1527 consequent -> consequent-arg | .NIL.
3238// F2023 R1528 consequent-arg -> expr | variable
3240 TUPLE_CLASS_BOILERPLATE(ConditionalArg);
3241 struct Consequent { // F2023 R1527
3242 UNION_CLASS_BOILERPLATE(Consequent);
3243 // N.B. "variable" is parsed as "expr" and
3244 // the distinction is determined by semantics.
3245 std::variant<common::Indirection<Expr>, ConditionalArgNil> u;
3246 };
3247 std::tuple<ScalarLogicalExpr, Consequent,
3249 t;
3250};
3251
3253 UNION_CLASS_BOILERPLATE(ConditionalArgTail);
3254 std::variant<ConditionalArg, ConditionalArg::Consequent> u;
3255};
3256
3257// R1524 actual-arg ->
3258// expr | variable | procedure-name | proc-component-ref |
3259// alt-return-spec | conditional-arg
3260struct ActualArg {
3261 WRAPPER_CLASS(PercentRef, Expr); // %REF(x) extension
3262 WRAPPER_CLASS(PercentVal, Expr); // %VAL(x) extension
3263 UNION_CLASS_BOILERPLATE(ActualArg);
3264 ActualArg(Expr &&x) : u{common::Indirection<Expr>(std::move(x))} {}
3265 std::variant<common::Indirection<Expr>, AltReturnSpec, PercentRef, PercentVal,
3267 u;
3268};
3269
3270// R1523 actual-arg-spec -> [keyword =] actual-arg
3272 TUPLE_CLASS_BOILERPLATE(ActualArgSpec);
3273 std::tuple<std::optional<Keyword>, ActualArg> t;
3274};
3275
3276// R1520 function-reference -> procedure-designator
3277// ( [actual-arg-spec-list] )
3278struct Call {
3279 TUPLE_CLASS_BOILERPLATE(Call);
3280 std::tuple<ProcedureDesignator, std::list<ActualArgSpec>> t;
3281};
3282
3284 WRAPPER_CLASS_BOILERPLATE(FunctionReference, Call);
3285 CharBlock source;
3286 Designator ConvertToArrayElementRef();
3287 StructureConstructor ConvertToStructureConstructor(
3289};
3290
3291// R1521 call-stmt -> CALL procedure-designator [ chevrons ]
3292// [( [actual-arg-spec-list] )]
3293// (CUDA) chevrons -> <<< * | scalar-expr, scalar-expr [,
3294// scalar-expr [, scalar-int-expr ] ] >>>
3295struct CallStmt {
3296 TUPLE_CLASS_BOILERPLATE(CallStmt);
3297 WRAPPER_CLASS(StarOrExpr, std::optional<ScalarExpr>);
3298 struct Chevrons {
3299 TUPLE_CLASS_BOILERPLATE(Chevrons);
3300 std::tuple<StarOrExpr, ScalarExpr, std::optional<ScalarExpr>,
3301 std::optional<ScalarIntExpr>>
3302 t;
3303 };
3304 explicit CallStmt(ProcedureDesignator &&pd, std::optional<Chevrons> &&ch,
3305 std::list<ActualArgSpec> &&args)
3306 : CallStmt(Call{std::move(pd), std::move(args)}, std::move(ch)) {}
3307 std::tuple<Call, std::optional<Chevrons>> t;
3308 CharBlock source;
3309 mutable TypedCall typedCall; // filled by semantics
3310};
3311
3312// R1529 function-subprogram ->
3313// function-stmt [specification-part] [execution-part]
3314// [internal-subprogram-part] end-function-stmt
3316 TUPLE_CLASS_BOILERPLATE(FunctionSubprogram);
3317 std::tuple<Statement<FunctionStmt>, SpecificationPart, ExecutionPart,
3318 std::optional<InternalSubprogramPart>, Statement<EndFunctionStmt>>
3319 t;
3320};
3321
3322// R1534 subroutine-subprogram ->
3323// subroutine-stmt [specification-part] [execution-part]
3324// [internal-subprogram-part] end-subroutine-stmt
3326 TUPLE_CLASS_BOILERPLATE(SubroutineSubprogram);
3327 std::tuple<Statement<SubroutineStmt>, SpecificationPart, ExecutionPart,
3328 std::optional<InternalSubprogramPart>, Statement<EndSubroutineStmt>>
3329 t;
3330};
3331
3332// R1539 mp-subprogram-stmt -> MODULE PROCEDURE procedure-name
3333WRAPPER_CLASS(MpSubprogramStmt, Name);
3334
3335// R1540 end-mp-subprogram-stmt -> END [PROCEDURE [procedure-name]]
3336WRAPPER_CLASS(EndMpSubprogramStmt, std::optional<Name>);
3337
3338// R1538 separate-module-subprogram ->
3339// mp-subprogram-stmt [specification-part] [execution-part]
3340// [internal-subprogram-part] end-mp-subprogram-stmt
3342 TUPLE_CLASS_BOILERPLATE(SeparateModuleSubprogram);
3343 std::tuple<Statement<MpSubprogramStmt>, SpecificationPart, ExecutionPart,
3344 std::optional<InternalSubprogramPart>, Statement<EndMpSubprogramStmt>>
3345 t;
3346};
3347
3348// R1541 entry-stmt -> ENTRY entry-name [( [dummy-arg-list] ) [suffix]]
3350 TUPLE_CLASS_BOILERPLATE(EntryStmt);
3351 std::tuple<Name, std::list<DummyArg>, std::optional<Suffix>> t;
3352};
3353
3354// R1542 return-stmt -> RETURN [scalar-int-expr]
3355WRAPPER_CLASS(ReturnStmt, std::optional<ScalarIntExpr>);
3356
3357// R1544 stmt-function-stmt ->
3358// function-name ( [dummy-arg-name-list] ) = scalar-expr
3360 TUPLE_CLASS_BOILERPLATE(StmtFunctionStmt);
3361 std::tuple<Name, std::list<Name>, Scalar<Expr>> t;
3362 Statement<ActionStmt> ConvertToAssignment();
3363};
3364
3365// Compiler directives
3366// !DIR$ IGNORE_TKR [ [(tkrdmac...)] name ]...
3367// !DIR$ LOOP COUNT (n1[, n2]...)
3368// !DIR$ name[=value] [, name[=value]]... = can be :
3369// !DIR$ UNROLL [N]
3370// !DIR$ UNROLL_AND_JAM [N]
3371// !DIR$ NOVECTOR
3372// !DIR$ NOUNROLL
3373// !DIR$ NOUNROLL_AND_JAM
3374// !DIR$ PREFETCH designator[, designator]...
3375// !DIR$ FORCEINLINE
3376// !DIR$ INLINE
3377// !DIR$ NOINLINE
3378// !DIR$ INLINEALWAYS
3379// !DIR$ IVDEP
3380// !DIR$ SIMD
3381// !DIR$ <anything else>
3383 UNION_CLASS_BOILERPLATE(CompilerDirective);
3384 struct IgnoreTKR {
3385 TUPLE_CLASS_BOILERPLATE(IgnoreTKR);
3386 std::tuple<std::optional<std::list<const char *>>, Name> t;
3387 };
3388 struct LoopCount {
3389 WRAPPER_CLASS_BOILERPLATE(LoopCount, std::list<std::uint64_t>);
3390 };
3392 TUPLE_CLASS_BOILERPLATE(AssumeAligned);
3393 std::tuple<common::Indirection<Designator>, uint64_t> t;
3394 };
3395 EMPTY_CLASS(VectorAlways);
3397 TUPLE_CLASS_BOILERPLATE(VectorLength);
3398 ENUM_CLASS(Kind, Auto, Fixed, Scalable);
3399
3400 std::tuple<std::uint64_t, Kind> t;
3401 };
3402 struct NameValue {
3403 TUPLE_CLASS_BOILERPLATE(NameValue);
3404 std::tuple<Name, std::optional<std::uint64_t>> t;
3405 };
3406 struct Unroll {
3407 WRAPPER_CLASS_BOILERPLATE(Unroll, std::optional<std::uint64_t>);
3408 };
3410 WRAPPER_CLASS_BOILERPLATE(UnrollAndJam, std::optional<std::uint64_t>);
3411 };
3412 struct Prefetch {
3413 WRAPPER_CLASS_BOILERPLATE(
3415 };
3417 WRAPPER_CLASS_BOILERPLATE(InlineAlways, std::optional<Name>);
3418 };
3419 EMPTY_CLASS(NoVector);
3420 EMPTY_CLASS(NoUnroll);
3421 EMPTY_CLASS(NoUnrollAndJam);
3422 EMPTY_CLASS(ForceInline);
3423 EMPTY_CLASS(Inline);
3424 EMPTY_CLASS(NoInline);
3425 EMPTY_CLASS(IVDep);
3426 EMPTY_CLASS(Simd);
3427 EMPTY_CLASS(Unrecognized);
3428 CharBlock source;
3429 std::variant<std::list<IgnoreTKR>, LoopCount, std::list<AssumeAligned>,
3430 VectorAlways, VectorLength, std::list<NameValue>, Unroll, UnrollAndJam,
3431 Unrecognized, NoVector, NoUnroll, NoUnrollAndJam, ForceInline, Inline,
3432 NoInline, InlineAlways, Prefetch, IVDep, Simd>
3433 u;
3434};
3435
3436// (CUDA) ATTRIBUTE(attribute) [::] name-list
3438 TUPLE_CLASS_BOILERPLATE(CUDAAttributesStmt);
3439 std::tuple<common::CUDADataAttr, std::list<Name>> t;
3440};
3441
3442// Legacy extensions
3444 TUPLE_CLASS_BOILERPLATE(BasedPointer);
3445 std::tuple<ObjectName, ObjectName, std::optional<ArraySpec>> t;
3446};
3447WRAPPER_CLASS(BasedPointerStmt, std::list<BasedPointer>);
3448
3449struct Union;
3450struct StructureDef;
3451
3453 UNION_CLASS_BOILERPLATE(StructureField);
3454 std::variant<Statement<DataComponentDefStmt>,
3456 u;
3457};
3458
3459struct Map {
3460 EMPTY_CLASS(MapStmt);
3461 EMPTY_CLASS(EndMapStmt);
3462 TUPLE_CLASS_BOILERPLATE(Map);
3463 std::tuple<Statement<MapStmt>, std::list<StructureField>,
3465 t;
3466};
3467
3468struct Union {
3469 EMPTY_CLASS(UnionStmt);
3470 EMPTY_CLASS(EndUnionStmt);
3471 TUPLE_CLASS_BOILERPLATE(Union);
3472 std::tuple<Statement<UnionStmt>, std::list<Map>, Statement<EndUnionStmt>> t;
3473};
3474
3476 TUPLE_CLASS_BOILERPLATE(StructureStmt);
3477 std::tuple<std::optional<Name>, std::list<EntityDecl>> t;
3478};
3479
3481 EMPTY_CLASS(EndStructureStmt);
3482 TUPLE_CLASS_BOILERPLATE(StructureDef);
3483 std::tuple<Statement<StructureStmt>, std::list<StructureField>,
3485 t;
3486};
3487
3488// Old style PARAMETER statement without parentheses.
3489// Types are determined entirely from the right-hand sides, not the names.
3490WRAPPER_CLASS(OldParameterStmt, std::list<NamedConstantDef>);
3491
3492// Deprecations
3494 TUPLE_CLASS_BOILERPLATE(ArithmeticIfStmt);
3495 std::tuple<Expr, Label, Label, Label> t;
3496};
3497
3499 TUPLE_CLASS_BOILERPLATE(AssignStmt);
3500 std::tuple<Label, Name> t;
3501};
3502
3504 TUPLE_CLASS_BOILERPLATE(AssignedGotoStmt);
3505 std::tuple<Name, std::list<Label>> t;
3506};
3507
3508WRAPPER_CLASS(PauseStmt, std::optional<StopCode>);
3509
3510// Parse tree nodes for OpenMP directives and clauses
3511
3512// --- Common definitions
3513
3514#define INHERITED_TUPLE_CLASS_BOILERPLATE(classname, basename) \
3515 using basename::basename; \
3516 classname(basename &&b) : basename(std::move(b)) {} \
3517 using TupleTrait = std::true_type; \
3518 BOILERPLATE(classname)
3519
3520#define INHERITED_WRAPPER_CLASS_BOILERPLATE(classname, basename) \
3521 BOILERPLATE(classname); \
3522 using basename::basename; \
3523 classname(basename &&base) : basename(std::move(base)) {} \
3524 using WrapperTrait = std::true_type
3525
3526struct OmpClause;
3528
3529struct OmpDirectiveName {
3530 // No boilerplates: this class should be copyable, movable, etc.
3531 constexpr OmpDirectiveName() = default;
3532 constexpr OmpDirectiveName(const OmpDirectiveName &) = default;
3533 constexpr OmpDirectiveName(llvm::omp::Directive x) : v(x) {}
3534 // Construct from an already parsed text. Use Verbatim for this because
3535 // Verbatim's source corresponds to an actual source location.
3536 // This allows "construct<OmpDirectiveName>(Verbatim("<name>"))".
3537 OmpDirectiveName(const Verbatim &name);
3538 using WrapperTrait = std::true_type;
3539
3540 bool IsExecutionPart() const; // Is allowed in the execution part
3541
3542 CharBlock source;
3543 llvm::omp::Directive v{llvm::omp::Directive::OMPD_unknown};
3544};
3545
3546// type-name list item
3548 CharBlock source;
3549 mutable const semantics::DeclTypeSpec *declTypeSpec{nullptr};
3550 UNION_CLASS_BOILERPLATE(OmpTypeName);
3551 std::variant<TypeSpec, DeclarationTypeSpec> u;
3552};
3553
3555 WRAPPER_CLASS_BOILERPLATE(OmpTypeNameList, std::list<OmpTypeName>);
3556};
3557
3558// 2.1 Directives or clauses may accept a list or extended-list.
3559// A list item is a variable, array section or common block name (enclosed
3560// in slashes). An extended list item is a list item or a procedure Name.
3561// variable-name | / common-block / | array-sections
3563 // Blank common blocks are not valid objects. Parse them to emit meaningful
3564 // diagnostics.
3565 struct Invalid {
3566 ENUM_CLASS(Kind, BlankCommonBlock);
3567 WRAPPER_CLASS_BOILERPLATE(Invalid, Kind);
3568 CharBlock source;
3569 };
3570 UNION_CLASS_BOILERPLATE(OmpObject);
3571 std::variant<Designator, /*common block*/ Name, Invalid> u;
3572};
3573
3575 WRAPPER_CLASS_BOILERPLATE(OmpObjectList, std::list<OmpObject>);
3576};
3577
3579 COPY_AND_ASSIGN_BOILERPLATE(OmpStylizedDeclaration);
3580 // Since "Reference" isn't handled by parse-tree-visitor, add EmptyTrait,
3581 // and visit the members by hand when needed.
3582 using EmptyTrait = std::true_type;
3584 EntityDecl var;
3585};
3586
3588 struct Instance {
3589 UNION_CLASS_BOILERPLATE(Instance);
3590 std::variant<AssignmentStmt, CallStmt, common::Indirection<Expr>> u;
3591 };
3592 TUPLE_CLASS_BOILERPLATE(OmpStylizedInstance);
3593 std::tuple<std::list<OmpStylizedDeclaration>, Instance> t;
3594};
3595
3596class ParseState;
3597
3598// Ref: [5.2:76], [6.0:185]
3599//
3601 CharBlock source;
3602 // Pointer to a temporary copy of the ParseState that is used to create
3603 // additional parse subtrees for the stylized expression. This is only
3604 // used internally during parsing and conveys no information to the
3605 // consumers of the AST.
3606 const ParseState *state{nullptr};
3607 WRAPPER_CLASS_BOILERPLATE(
3608 OmpStylizedExpression, std::list<OmpStylizedInstance>);
3609};
3610
3611// Ref: [4.5:201-207], [5.0:293-299], [5.1:325-331], [5.2:124]
3612//
3613// reduction-identifier ->
3614// base-language-identifier | // since 4.5
3615// - | // since 4.5, until 5.2
3616// + | * | .AND. | .OR. | .EQV. | .NEQV. | // since 4.5
3617// MIN | MAX | IAND | IOR | IEOR // since 4.5
3619 UNION_CLASS_BOILERPLATE(OmpReductionIdentifier);
3620 std::variant<DefinedOperator, ProcedureDesignator> u;
3621};
3622
3623// Ref: [4.5:222:6], [5.0:305:27], [5.1:337:19], [5.2:126:3-4], [6.0:240:27-28]
3624//
3625// combiner-expression -> // since 4.5
3626// assignment-statement |
3627// function-reference
3629 INHERITED_WRAPPER_CLASS_BOILERPLATE(
3631 static llvm::ArrayRef<CharBlock> Variables();
3632};
3633
3634// Ref: [4.5:222:7-8], [5.0:305:28-29], [5.1:337:20-21], [5.2:127:6-8],
3635// [6.0:242:3-5]
3636//
3637// initializer-expression -> // since 4.5
3638// OMP_PRIV = expression |
3639// subroutine-name(argument-list)
3641 INHERITED_WRAPPER_CLASS_BOILERPLATE(
3643 static llvm::ArrayRef<CharBlock> Variables();
3644};
3645
3646inline namespace arguments {
3648 UNION_CLASS_BOILERPLATE(OmpLocator);
3649 std::variant<OmpObject, FunctionReference> u;
3650};
3651
3653 WRAPPER_CLASS_BOILERPLATE(OmpLocatorList, std::list<OmpLocator>);
3654};
3655
3656// Ref: [4.5:58-60], [5.0:58-60], [5.1:63-68], [5.2:197-198], [6.0:334-336]
3657//
3658// Argument to DECLARE VARIANT with the base-name present. (When only
3659// variant-name is present, it is a simple OmpObject).
3660//
3661// base-name-variant-name -> // since 4.5
3662// base-name : variant-name
3664 TUPLE_CLASS_BOILERPLATE(OmpBaseVariantNames);
3665 std::tuple<OmpObject, OmpObject> t;
3666};
3667
3668// Ref: [5.0:326:10-16], [5.1:359:5-11], [5.2:163:2-7], [6.0:293:16-21]
3669//
3670// mapper-specifier ->
3671// [mapper-identifier :] type :: var | // since 5.0
3672// DEFAULT type :: var
3674 // Absent mapper-identifier is equivalent to DEFAULT.
3675 TUPLE_CLASS_BOILERPLATE(OmpMapperSpecifier);
3676 std::tuple<std::string, TypeSpec, Name> t;
3677};
3678
3679// Ref: [4.5:222:1-5], [5.0:305:20-27], [5.1:337:11-19], [5.2:139:18-23],
3680// [6.0:260:16-20]
3681//
3682// reduction-specifier ->
3683// reduction-identifier : typename-list
3684// : combiner-expression // since 4.5, until 5.2
3685// reduction-identifier : typename-list // since 6.0
3687 TUPLE_CLASS_BOILERPLATE(OmpReductionSpecifier);
3689 std::optional<OmpCombinerExpression>>
3690 t;
3691};
3692
3694 CharBlock source;
3695 UNION_CLASS_BOILERPLATE(OmpArgument);
3696 std::variant<OmpLocator, // {variable, extended, locator}-list-item
3697 OmpBaseVariantNames, // base-name:variant-name
3699 u;
3700};
3701
3703 WRAPPER_CLASS_BOILERPLATE(OmpArgumentList, std::list<OmpArgument>);
3704 CharBlock source;
3705};
3706} // namespace arguments
3707
3708inline namespace traits {
3709// trait-property-name ->
3710// identifier | string-literal
3711//
3712// This is a bit of a problematic case. The spec says that a word in quotes,
3713// and the same word without quotes are equivalent. We currently parse both
3714// as a string, but it's likely just a temporary solution.
3715//
3716// The problem is that trait-property can be (among other things) a
3717// trait-property-name or a trait-property-expression. A simple identifier
3718// can be either, there is no reasonably simple way of telling them apart
3719// in the parser. There is a similar issue with extensions. Some of that
3720// disambiguation may need to be done in the "canonicalization" pass and
3721// then some of those AST nodes would be rewritten into different ones.
3722//
3724 CharBlock source;
3725 WRAPPER_CLASS_BOILERPLATE(OmpTraitPropertyName, std::string);
3726};
3727
3728// trait-score ->
3729// SCORE(non-negative-const-integer-expression)
3731 CharBlock source;
3732 WRAPPER_CLASS_BOILERPLATE(OmpTraitScore, ScalarIntExpr);
3733};
3734
3735// trait-property-extension ->
3736// trait-property-name |
3737// scalar-expr |
3738// trait-property-name (trait-property-extension, ...)
3739//
3741 CharBlock source;
3742 UNION_CLASS_BOILERPLATE(OmpTraitPropertyExtension);
3743 struct Complex { // name (prop-ext, prop-ext, ...)
3744 CharBlock source;
3745 TUPLE_CLASS_BOILERPLATE(Complex);
3746 std::tuple<OmpTraitPropertyName,
3747 std::list<common::Indirection<OmpTraitPropertyExtension>>>
3748 t;
3749 };
3750
3751 std::variant<OmpTraitPropertyName, ScalarExpr, Complex> u;
3752};
3753
3754// trait-property ->
3755// trait-property-name | OmpClause |
3756// trait-property-expression | trait-property-extension
3757// trait-property-expression ->
3758// scalar-logical-expression | scalar-integer-expression
3759//
3760// The parser for a logical expression will accept an integer expression,
3761// and if it's not logical, it will flag an error later. The same thing
3762// will happen if the scalar integer expression sees a logical expresion.
3763// To avoid this, parse all expressions as scalar expressions.
3765 CharBlock source;
3766 UNION_CLASS_BOILERPLATE(OmpTraitProperty);
3767 std::variant<OmpTraitPropertyName, common::Indirection<OmpClause>,
3768 ScalarExpr, // trait-property-expresion
3770 u;
3771};
3772
3773// trait-selector-name ->
3774// KIND | DT // name-list (host, nohost, +/add-def-doc)
3775// ISA | DT // name-list (isa_name, ... /impl-defined)
3776// ARCH | DT // name-list (arch_name, ... /impl-defined)
3777// directive-name | C // no properties
3778// SIMD | C // clause-list (from declare_simd)
3779// // (at least simdlen, inbranch/notinbranch)
3780// DEVICE_NUM | T // device-number
3781// UID | T // unique-string-id /impl-defined
3782// VENDOR | I // name-list (vendor-id /add-def-doc)
3783// EXTENSION | I // name-list (ext_name /impl-defined)
3784// ATOMIC_DEFAULT_MEM_ORDER I | // clause-list (value of admo)
3785// REQUIRES | I // clause-list (from requires)
3786// CONDITION U // logical-expr
3787// <other name> I // treated as extension
3788//
3789// Trait-set-selectors:
3790// [D]evice, [T]arget_device, [C]onstruct, [I]mplementation, [U]ser.
3792 std::string ToString() const;
3793 CharBlock source;
3794 UNION_CLASS_BOILERPLATE(OmpTraitSelectorName);
3795 ENUM_CLASS(Value, Arch, Atomic_Default_Mem_Order, Condition, Device_Num,
3796 Extension, Isa, Kind, Requires, Simd, Uid, Vendor)
3797 std::variant<Value, llvm::omp::Directive, std::string> u;
3798};
3799
3800// trait-selector ->
3801// trait-selector-name |
3802// trait-selector-name ([trait-score:] trait-property, ...)
3804 CharBlock source;
3805 TUPLE_CLASS_BOILERPLATE(OmpTraitSelector);
3806 struct Properties {
3807 TUPLE_CLASS_BOILERPLATE(Properties);
3808 std::tuple<std::optional<OmpTraitScore>, std::list<OmpTraitProperty>> t;
3809 };
3810 std::tuple<OmpTraitSelectorName, std::optional<Properties>> t;
3811};
3812
3813// trait-set-selector-name ->
3814// CONSTRUCT | DEVICE | IMPLEMENTATION | USER | // since 5.0
3815// TARGET_DEVICE // since 5.1
3817 std::string ToString() const;
3818 CharBlock source;
3819 ENUM_CLASS(Value, Construct, Device, Implementation, Target_Device, User)
3820 WRAPPER_CLASS_BOILERPLATE(OmpTraitSetSelectorName, Value);
3821};
3822
3823// trait-set-selector ->
3824// trait-set-selector-name = {trait-selector, ...}
3826 CharBlock source;
3827 TUPLE_CLASS_BOILERPLATE(OmpTraitSetSelector);
3828 std::tuple<OmpTraitSetSelectorName, std::list<OmpTraitSelector>> t;
3829};
3830
3831// context-selector-specification ->
3832// trait-set-selector, ...
3834 CharBlock source;
3835 WRAPPER_CLASS_BOILERPLATE(
3836 OmpContextSelectorSpecification, std::list<OmpTraitSetSelector>);
3837};
3838} // namespace traits
3839
3840#define MODIFIER_BOILERPLATE(...) \
3841 struct Modifier { \
3842 using Variant = std::variant<__VA_ARGS__>; \
3843 UNION_CLASS_BOILERPLATE(Modifier); \
3844 CharBlock source; \
3845 Variant u; \
3846 }
3847
3848#define MODIFIERS() std::optional<std::list<Modifier>>
3849
3850inline namespace modifier {
3851// For uniformity, in all keyword modifiers the name of the type defined
3852// by ENUM_CLASS is "Value", e.g.
3853// struct Foo {
3854// ENUM_CLASS(Value, Keyword1, Keyword2);
3855// };
3856
3858 ENUM_CLASS(Value, Cgroup);
3859 WRAPPER_CLASS_BOILERPLATE(OmpAccessGroup, Value);
3860};
3861
3862// Ref: [4.5:72-81], [5.0:110-119], [5.1:134-143], [5.2:169-170]
3863//
3864// alignment ->
3865// scalar-integer-expression // since 4.5
3867 WRAPPER_CLASS_BOILERPLATE(OmpAlignment, ScalarIntExpr);
3868};
3869
3870// Ref: [5.1:184-185], [5.2:178-179]
3871//
3872// align-modifier ->
3873// ALIGN(alignment) // since 5.1
3875 WRAPPER_CLASS_BOILERPLATE(OmpAlignModifier, ScalarIntExpr);
3876};
3877
3878// Ref: [5.0:158-159], [5.1:184-185], [5.2:178-179]
3879//
3880// allocator-simple-modifier ->
3881// allocator // since 5.0
3883 WRAPPER_CLASS_BOILERPLATE(OmpAllocatorSimpleModifier, ScalarIntExpr);
3884};
3885
3886// Ref: [5.1:184-185], [5.2:178-179]
3887//
3888// allocator-complex-modifier ->
3889// ALLOCATOR(allocator) // since 5.1
3891 WRAPPER_CLASS_BOILERPLATE(OmpAllocatorComplexModifier, ScalarIntExpr);
3892};
3893
3894// Ref: [4.5:216-219], [5.0:315-324], [5.1:347-355], [5.2:150-158],
3895// [6.0:279-288]
3896//
3897// always-modifier ->
3898// ALWAYS // since 4.5
3899//
3900// Until 5.2, it was a part of map-type-modifier. Since 6.0 the
3901// map-type-modifier has been split into individual modifiers.
3903 ENUM_CLASS(Value, Always)
3904 WRAPPER_CLASS_BOILERPLATE(OmpAlwaysModifier, Value);
3905};
3906
3907// Ref: [coming in 6.1]
3908//
3909// attach-modifier ->
3910// ATTACH(attachment-mode) // since 6.1
3911//
3912// attachment-mode ->
3913// ALWAYS | AUTO | NEVER
3915 ENUM_CLASS(Value, Always, Never, Auto)
3916 WRAPPER_CLASS_BOILERPLATE(OmpAttachModifier, Value);
3917};
3918
3919// Ref: [6.0:289-290]
3920//
3921// automap-modifier ->
3922// automap // since 6.0
3923//
3925 ENUM_CLASS(Value, Automap);
3926 WRAPPER_CLASS_BOILERPLATE(OmpAutomapModifier, Value);
3927};
3928
3929// Ref: [5.2:252-254]
3930//
3931// chunk-modifier ->
3932// SIMD // since 5.2
3933//
3934// Prior to 5.2 "chunk-modifier" was a part of "modifier" on SCHEDULE clause.
3936 ENUM_CLASS(Value, Simd)
3937 WRAPPER_CLASS_BOILERPLATE(OmpChunkModifier, Value);
3938};
3939
3940// Ref: [4.5:216-219], [5.0:315-324], [5.1:347-355], [5.2:150-158],
3941// [6.0:279-288]
3942//
3943// close-modifier ->
3944// CLOSE // since 5.0
3945//
3946// Until 5.2, it was a part of map-type-modifier. Since 6.0 the
3947// map-type-modifier has been split into individual modifiers.
3949 ENUM_CLASS(Value, Close)
3950 WRAPPER_CLASS_BOILERPLATE(OmpCloseModifier, Value);
3951};
3952
3953// Ref: [4.5:216-219], [5.0:315-324], [5.1:347-355], [5.2:150-158],
3954// [6.0:279-288]
3955//
3956// delete-modifier ->
3957// DELETE // since 6.0
3958//
3959// Until 5.2, it was a part of map-type.
3961 ENUM_CLASS(Value, Delete)
3962 WRAPPER_CLASS_BOILERPLATE(OmpDeleteModifier, Value);
3963};
3964
3965// Ref: [4.5:169-170], [5.0:255-256], [5.1:288-289]
3966//
3967// dependence-type ->
3968// SINK | SOURCE | // since 4.5
3969// IN | OUT | INOUT | // since 4.5, until 5.1
3970// MUTEXINOUTSET | DEPOBJ | // since 5.0, until 5.1
3971// INOUTSET // since 5.1, until 5.1
3972//
3973// All of these, except SINK and SOURCE became task-dependence-type in 5.2.
3974//
3975// Keeping these two as separate types, since having them all together
3976// creates conflicts when parsing the DEPEND clause. For DEPEND(SINK: ...),
3977// the SINK may be parsed as 'task-dependence-type', and the list after
3978// the ':' would then be parsed as OmpObjectList (instead of the iteration
3979// vector). This would accept the vector "i, j, k" (although interpreted
3980// incorrectly), while flagging a syntax error for "i+1, j, k".
3982 ENUM_CLASS(Value, Sink, Source);
3983 WRAPPER_CLASS_BOILERPLATE(OmpDependenceType, Value);
3984};
3985
3986// Ref: [6.0:180-181]
3987//
3988// depinfo-modifier -> // since 6.0
3989// keyword (locator-list-item)
3990// keyword ->
3991// IN | INOUT | INOUTSET | MUTEXINOUTSET | OUT // since 6.0
3993 using Value = common::OmpDependenceKind;
3994 TUPLE_CLASS_BOILERPLATE(OmpDepinfoModifier);
3995 std::tuple<Value, OmpObject> t;
3996};
3997
3998// Ref: [5.0:170-176], [5.1:197-205], [5.2:276-277]
3999//
4000// device-modifier ->
4001// ANCESTOR | DEVICE_NUM // since 5.0
4003 ENUM_CLASS(Value, Ancestor, Device_Num)
4004 WRAPPER_CLASS_BOILERPLATE(OmpDeviceModifier, Value);
4005};
4006
4007// Ref: TODO
4008//
4009// dims-modifier ->
4010// constant integer expression // since 6.1
4012 WRAPPER_CLASS_BOILERPLATE(OmpDimsModifier, ScalarIntConstantExpr);
4013};
4014
4015// Ref: [5.2:72-73,230-323], in 4.5-5.1 it's scattered over individual
4016// directives that allow the IF clause.
4017//
4018// directive-name-modifier ->
4019// PARALLEL | TARGET | TARGET DATA |
4020// TARGET ENTER DATA | TARGET EXIT DATA |
4021// TARGET UPDATE | TASK | TASKLOOP | // since 4.5
4022// CANCEL[*] | SIMD | // since 5.0
4023// TEAMS // since 5.2
4024//
4025// [*] The IF clause is allowed on CANCEL in OpenMP 4.5, but only without
4026// the directive-name-modifier. For the sake of uniformity CANCEL can be
4027// considered a valid value in 4.5 as well.
4028struct OmpDirectiveNameModifier : public OmpDirectiveName {
4029 INHERITED_WRAPPER_CLASS_BOILERPLATE(
4030 OmpDirectiveNameModifier, OmpDirectiveName);
4031};
4032
4033// Ref: [5.1:205-209], [5.2:166-168]
4034//
4035// motion-modifier ->
4036// PRESENT | // since 5.0, until 5.0
4037// mapper | iterator
4038// expectation ->
4039// PRESENT // since 5.1
4040//
4041// The PRESENT value was a part of motion-modifier in 5.1, and became a
4042// value of expectation in 5.2.
4044 ENUM_CLASS(Value, Present);
4045 WRAPPER_CLASS_BOILERPLATE(OmpExpectation, Value);
4046};
4047
4048// Ref: [6.1:tbd]
4049//
4050// fallback-modifier ->
4051// FALLBACK(fallback-mode) // since 6.1
4052// fallback-mode ->
4053// ABORT | DEFAULT_MEM | NULL // since 6.1
4055 ENUM_CLASS(Value, Abort, Default_Mem, Null);
4056 WRAPPER_CLASS_BOILERPLATE(OmpFallbackModifier, Value);
4057};
4058
4059// REF: [5.1:217-220], [5.2:293-294], [6.0:470-471]
4060//
4061// interop-type -> // since 5.1
4062// TARGET |
4063// TARGETSYNC
4064// There can be at most only two interop-type.
4066 ENUM_CLASS(Value, Target, Targetsync)
4067 WRAPPER_CLASS_BOILERPLATE(OmpInteropType, Value);
4068};
4069
4070// Ref: [5.0:47-49], [5.1:49-51], [5.2:67-69]
4071//
4072// iterator-specifier ->
4073// [iterator-type] iterator-identifier
4074// = range-specification | // since 5.0
4075// [iterator-type ::] iterator-identifier
4076// = range-specification // since 5.2
4078 TUPLE_CLASS_BOILERPLATE(OmpIteratorSpecifier);
4079 CharBlock source;
4080 std::tuple<TypeDeclarationStmt, SubscriptTriplet> t;
4081};
4082
4083// Ref: [5.0:47-49], [5.1:49-51], [5.2:67-69]
4084//
4085// iterator-modifier ->
4086// ITERATOR(iterator-specifier [, ...]) // since 5.0
4088 WRAPPER_CLASS_BOILERPLATE(OmpIterator, std::list<OmpIteratorSpecifier>);
4089};
4090
4091// Ref: [5.0:288-290], [5.1:321-322], [5.2:115-117]
4092//
4093// lastprivate-modifier ->
4094// CONDITIONAL // since 5.0
4096 ENUM_CLASS(Value, Conditional)
4097 WRAPPER_CLASS_BOILERPLATE(OmpLastprivateModifier, Value);
4098};
4099
4100// Ref: [4.5:207-210], [5.0:290-293], [5.1:323-325], [5.2:117-120]
4101//
4102// linear-modifier ->
4103// REF | UVAL | VAL // since 4.5
4105 ENUM_CLASS(Value, Ref, Uval, Val);
4106 WRAPPER_CLASS_BOILERPLATE(OmpLinearModifier, Value);
4107};
4108
4109// Ref: [5.1:100-104], [5.2:277], [6.0:452-453]
4110//
4111// lower-bound ->
4112// scalar-integer-expression // since 5.1
4114 WRAPPER_CLASS_BOILERPLATE(OmpLowerBound, ScalarIntExpr);
4115};
4116
4117// Ref: [5.0:176-180], [5.1:205-210], [5.2:149-150]
4118//
4119// mapper ->
4120// identifier // since 4.5
4122 WRAPPER_CLASS_BOILERPLATE(OmpMapper, Name);
4123};
4124
4125// Ref: [4.5:216-219], [5.0:315-324], [5.1:347-355], [5.2:150-158],
4126// [6.0:279-288]
4127//
4128// map-type ->
4129// ALLOC | DELETE | RELEASE | // since 4.5, until 5.2
4130// FROM | TO | TOFROM | // since 4.5
4131// STORAGE // since 6.0
4132//
4133// Since 6.0 DELETE is a separate delete-modifier.
4135 ENUM_CLASS(Value, Alloc, Delete, From, Release, Storage, To, Tofrom);
4136 WRAPPER_CLASS_BOILERPLATE(OmpMapType, Value);
4137};
4138
4139// Ref: [4.5:216-219], [5.0:315-324], [5.1:347-355], [5.2:150-158]
4140//
4141// map-type-modifier ->
4142// ALWAYS | // since 4.5, until 5.2
4143// CLOSE | // since 5.0, until 5.2
4144// PRESENT // since 5.1, until 5.2
4145// Since 6.0 the map-type-modifier has been split into individual modifiers.
4146//
4148 ENUM_CLASS(Value, Always, Close, Present, Ompx_Hold)
4149 WRAPPER_CLASS_BOILERPLATE(OmpMapTypeModifier, Value);
4150};
4151
4152// Ref: [4.5:56-63], [5.0:101-109], [5.1:126-133], [5.2:252-254]
4153//
4154// modifier ->
4155// MONOTONIC | NONMONOTONIC | SIMD // since 4.5, until 5.1
4156// ordering-modifier ->
4157// MONOTONIC | NONMONOTONIC // since 5.2
4158//
4159// Until 5.1, the SCHEDULE clause accepted up to two instances of "modifier".
4160// Since 5.2 "modifier" was replaced with "ordering-modifier" and "chunk-
4161// modifier".
4163 ENUM_CLASS(Value, Monotonic, Nonmonotonic, Simd)
4164 WRAPPER_CLASS_BOILERPLATE(OmpOrderingModifier, Value);
4165};
4166
4167// Ref: [5.1:125-126], [5.2:233-234]
4168//
4169// order-modifier ->
4170// REPRODUCIBLE | UNCONSTRAINED // since 5.1
4172 ENUM_CLASS(Value, Reproducible, Unconstrained)
4173 WRAPPER_CLASS_BOILERPLATE(OmpOrderModifier, Value);
4174};
4175
4176// Ref: [6.0:470-471]
4177//
4178// preference-selector -> // since 6.0
4179// FR(foreign-runtime-identifier) |
4180// ATTR(preference-property-extension, ...)
4182 UNION_CLASS_BOILERPLATE(OmpPreferenceSelector);
4183 using ForeignRuntimeIdentifier = common::Indirection<Expr>;
4184 using PreferencePropertyExtension = common::Indirection<Expr>;
4185 using Extensions = std::list<PreferencePropertyExtension>;
4186 std::variant<ForeignRuntimeIdentifier, Extensions> u;
4187};
4188
4189// Ref: [6.0:470-471]
4190//
4191// preference-specification ->
4192// {preference-selector...} | // since 6.0
4193// foreign-runtime-identifier // since 5.1
4195 UNION_CLASS_BOILERPLATE(OmpPreferenceSpecification);
4196 using ForeignRuntimeIdentifier =
4197 OmpPreferenceSelector::ForeignRuntimeIdentifier;
4198 std::variant<std::list<OmpPreferenceSelector>, ForeignRuntimeIdentifier> u;
4199};
4200
4201// REF: [5.1:217-220], [5.2:293-294], [6.0:470-471]
4202//
4203// prefer-type -> // since 5.1
4204// PREFER_TYPE(preference-specification...)
4206 WRAPPER_CLASS_BOILERPLATE(
4207 OmpPreferType, std::list<OmpPreferenceSpecification>);
4208};
4209
4210// Ref: [5.1:166-171], [5.2:269-270]
4211//
4212// prescriptiveness ->
4213// STRICT // since 5.1
4215 ENUM_CLASS(Value, Strict)
4216 WRAPPER_CLASS_BOILERPLATE(OmpPrescriptiveness, Value);
4217};
4218
4219// Ref: [4.5:216-219], [5.0:315-324], [5.1:347-355], [5.2:150-158],
4220// [6.0:279-288]
4221//
4222// present-modifier ->
4223// PRESENT // since 5.1
4224//
4225// Until 5.2, it was a part of map-type-modifier. Since 6.0 the
4226// map-type-modifier has been split into individual modifiers.
4228 ENUM_CLASS(Value, Present)
4229 WRAPPER_CLASS_BOILERPLATE(OmpPresentModifier, Value);
4230};
4231
4232// Ref: [5.0:300-302], [5.1:332-334], [5.2:134-137]
4233//
4234// reduction-modifier ->
4235// DEFAULT | INSCAN | TASK // since 5.0
4237 ENUM_CLASS(Value, Default, Inscan, Task);
4238 WRAPPER_CLASS_BOILERPLATE(OmpReductionModifier, Value);
4239};
4240
4241// Ref: [6.0:279-288]
4242//
4243// ref-modifier ->
4244// REF_PTEE | REF_PTR | REF_PTR_PTEE // since 6.0
4245//
4247 ENUM_CLASS(Value, Ref_Ptee, Ref_Ptr, Ref_Ptr_Ptee)
4248 WRAPPER_CLASS_BOILERPLATE(OmpRefModifier, Value);
4249};
4250
4251// Ref: [6.0:279-288]
4252//
4253// self-modifier ->
4254// SELF // since 6.0
4255//
4257 ENUM_CLASS(Value, Self)
4258 WRAPPER_CLASS_BOILERPLATE(OmpSelfModifier, Value);
4259};
4260
4261// Ref: [5.2:117-120]
4262//
4263// step-complex-modifier ->
4264// STEP(integer-expression) // since 5.2
4266 WRAPPER_CLASS_BOILERPLATE(OmpStepComplexModifier, ScalarIntExpr);
4267};
4268
4269// Ref: [4.5:207-210], [5.0:290-293], [5.1:323-325], [5.2:117-120]
4270//
4271// step-simple-modifier ->
4272// integer-expresion // since 4.5
4274 WRAPPER_CLASS_BOILERPLATE(OmpStepSimpleModifier, ScalarIntExpr);
4275};
4276
4277// Ref: [4.5:169-170], [5.0:254-256], [5.1:287-289], [5.2:321]
4278//
4279// task-dependence-type -> // "dependence-type" in 5.1 and before
4280// IN | OUT | INOUT | // since 4.5
4281// MUTEXINOUTSET | DEPOBJ | // since 5.0
4282// INOUTSET // since 5.2
4284 using Value = common::OmpDependenceKind;
4285 WRAPPER_CLASS_BOILERPLATE(OmpTaskDependenceType, Value);
4286};
4287
4288// Ref: [4.5:229-230], [5.0:324-325], [5.1:357-358], [5.2:161-162]
4289//
4290// variable-category ->
4291// SCALAR | // since 4.5
4292// AGGREGATE | ALLOCATABLE | POINTER | // since 5.0
4293// ALL // since 5.2
4295 ENUM_CLASS(Value, Aggregate, All, Allocatable, Pointer, Scalar)
4296 WRAPPER_CLASS_BOILERPLATE(OmpVariableCategory, Value);
4297};
4298
4299// Extension:
4300// https://openmp.llvm.org//openacc/OpenMPExtensions.html#ompx-hold
4301//
4302// ompx-hold-modifier ->
4303// OMPX_HOLD // since 4.5
4304//
4305// Until 5.2, it was a part of map-type-modifier. Since 6.0 the
4306// map-type-modifier has been split into individual modifiers.
4308 ENUM_CLASS(Value, Ompx_Hold)
4309 WRAPPER_CLASS_BOILERPLATE(OmpxHoldModifier, Value);
4310};
4311
4312// context-selector
4313using OmpContextSelector = traits::OmpContextSelectorSpecification;
4314} // namespace modifier
4315
4316// --- Clauses
4317
4318using OmpDirectiveList = std::list<llvm::omp::Directive>;
4319
4320// Ref: [5.2:214]
4321//
4322// absent-clause ->
4323// ABSENT(directive-name[, directive-name])
4325 WRAPPER_CLASS_BOILERPLATE(OmpAbsentClause, OmpDirectiveList);
4326};
4327
4329 TUPLE_CLASS_BOILERPLATE(OmpAdjustArgsClause);
4331 ENUM_CLASS(Value, Nothing, Need_Device_Ptr)
4332 WRAPPER_CLASS_BOILERPLATE(OmpAdjustOp, Value);
4333 };
4334 std::tuple<OmpAdjustOp, OmpObjectList> t;
4335};
4336
4337// Ref: [5.0:135-140], [5.1:161-166], [5.2:264-265]
4338//
4339// affinity-clause ->
4340// AFFINITY([aff-modifier:] locator-list) // since 5.0
4341// aff-modifier ->
4342// interator-modifier // since 5.0
4344 TUPLE_CLASS_BOILERPLATE(OmpAffinityClause);
4345 MODIFIER_BOILERPLATE(OmpIterator);
4346 std::tuple<MODIFIERS(), OmpObjectList> t;
4347};
4348
4349// Ref: 5.2: [174]
4351 WRAPPER_CLASS_BOILERPLATE(OmpAlignClause, ScalarIntConstantExpr);
4352};
4353
4354// Ref: [4.5:72-81], [5.0:110-119], [5.1:134-143], [5.2:169-170]
4355//
4356// aligned-clause ->
4357// ALIGNED(list [: alignment]) // since 4.5
4359 TUPLE_CLASS_BOILERPLATE(OmpAlignedClause);
4360 MODIFIER_BOILERPLATE(OmpAlignment);
4361 std::tuple<OmpObjectList, MODIFIERS()> t;
4362};
4363
4364// Ref: [5.0:158-159], [5.1:184-185], [5.2:178-179]
4365//
4366// allocate-clause ->
4367// ALLOCATE(
4368// [allocator-simple-modifier:] list) | // since 5.0
4369// ALLOCATE([modifier...:] list) // since 5.1
4370// modifier ->
4371// allocator-simple-modifier |
4372// allocator-complex-modifier | align-modifier // since 5.1
4374 MODIFIER_BOILERPLATE(OmpAlignModifier, OmpAllocatorSimpleModifier,
4376 TUPLE_CLASS_BOILERPLATE(OmpAllocateClause);
4377 std::tuple<MODIFIERS(), OmpObjectList> t;
4378};
4379
4382 WRAPPER_CLASS_BOILERPLATE(OmpAppendOp, std::list<OmpInteropType>);
4383 };
4384 WRAPPER_CLASS_BOILERPLATE(OmpAppendArgsClause, std::list<OmpAppendOp>);
4385};
4386
4387// Ref: [5.2:216-217 (sort of, as it's only mentioned in passing)
4388// AT(compilation|execution)
4390 ENUM_CLASS(ActionTime, Compilation, Execution);
4391 WRAPPER_CLASS_BOILERPLATE(OmpAtClause, ActionTime);
4392};
4393
4394// Ref: [5.0:60-63], [5.1:83-86], [5.2:210-213]
4395//
4396// atomic-default-mem-order-clause ->
4397// ATOMIC_DEFAULT_MEM_ORDER(memory-order) // since 5.0
4398// memory-order ->
4399// SEQ_CST | ACQ_REL | RELAXED | // since 5.0
4400// ACQUIRE | RELEASE // since 5.2
4402 using MemoryOrder = common::OmpMemoryOrderType;
4403 WRAPPER_CLASS_BOILERPLATE(OmpAtomicDefaultMemOrderClause, MemoryOrder);
4404};
4405
4406// Ref: [5.0:128-131], [5.1:151-154], [5.2:258-259]
4407//
4408// bind-clause ->
4409// BIND(binding) // since 5.0
4410// binding ->
4411// TEAMS | PARALLEL | THREAD // since 5.0
4413 ENUM_CLASS(Binding, Parallel, Teams, Thread)
4414 WRAPPER_CLASS_BOILERPLATE(OmpBindClause, Binding);
4415};
4416
4417// Artificial clause to represent a cancellable construct.
4419 TUPLE_CLASS_BOILERPLATE(OmpCancellationConstructTypeClause);
4420 std::tuple<OmpDirectiveName, std::optional<ScalarLogicalExpr>> t;
4421};
4422
4423// Ref: [6.0:262]
4424//
4425// combiner-clause -> // since 6.0
4426// COMBINER(combiner-expr)
4428 WRAPPER_CLASS_BOILERPLATE(OmpCombinerClause, OmpCombinerExpression);
4429};
4430
4431// Ref: [5.2:214]
4432//
4433// contains-clause ->
4434// CONTAINS(directive-name[, directive-name])
4436 WRAPPER_CLASS_BOILERPLATE(OmpContainsClause, OmpDirectiveList);
4437};
4438
4439// Ref: [4.5:46-50], [5.0:74-78], [5.1:92-96], [5.2:109]
4440//
4441// When used as a data-sharing clause:
4442// default-clause ->
4443// DEFAULT(data-sharing-attribute) // since 4.5
4444// data-sharing-attribute ->
4445// SHARED | NONE | // since 4.5
4446// PRIVATE | FIRSTPRIVATE // since 5.0
4447//
4448// When used in METADIRECTIVE:
4449// default-clause ->
4450// DEFAULT(directive-specification) // since 5.0, until 5.1
4451// See also otherwise-clause.
4453 ENUM_CLASS(DataSharingAttribute, Private, Firstprivate, Shared, None)
4454 UNION_CLASS_BOILERPLATE(OmpDefaultClause);
4455 std::variant<DataSharingAttribute,
4457 u;
4458};
4459
4460// Ref: [4.5:103-107], [5.0:324-325], [5.1:357-358], [5.2:161-162]
4461//
4462// defaultmap-clause ->
4463// DEFAULTMAP(implicit-behavior
4464// [: variable-category]) // since 5.0
4465// implicit-behavior ->
4466// TOFROM | // since 4.5
4467// ALLOC | TO | FROM | FIRSTPRIVATE | NONE |
4468// DEFAULT | // since 5.0
4469// PRESENT // since 5.1
4471 TUPLE_CLASS_BOILERPLATE(OmpDefaultmapClause);
4472 ENUM_CLASS(ImplicitBehavior, Alloc, To, From, Tofrom, Firstprivate, None,
4473 Default, Present)
4474 MODIFIER_BOILERPLATE(OmpVariableCategory);
4475 std::tuple<ImplicitBehavior, MODIFIERS()> t;
4476};
4477
4478// Ref: [4.5:169-172], [5.0:255-259], [5.1:288-292], [5.2:91-93]
4479//
4480// iteration-offset ->
4481// +|- non-negative-constant // since 4.5
4483 TUPLE_CLASS_BOILERPLATE(OmpIterationOffset);
4484 std::tuple<DefinedOperator, ScalarIntConstantExpr> t;
4485};
4486
4487// Ref: [4.5:169-172], [5.0:255-259], [5.1:288-292], [5.2:91-93]
4488//
4489// iteration ->
4490// induction-variable [iteration-offset] // since 4.5
4492 TUPLE_CLASS_BOILERPLATE(OmpIteration);
4493 std::tuple<Name, std::optional<OmpIterationOffset>> t;
4494};
4495
4496// Ref: [4.5:169-172], [5.0:255-259], [5.1:288-292], [5.2:91-93]
4497//
4498// iteration-vector ->
4499// [iteration...] // since 4.5
4501 WRAPPER_CLASS_BOILERPLATE(OmpIterationVector, std::list<OmpIteration>);
4502};
4503
4504// Extract this into a separate structure (instead of having it directly in
4505// OmpDoacrossClause), so that the context in TYPE_CONTEXT_PARSER can be set
4506// separately for OmpDependClause and OmpDoacrossClause.
4507//
4508// See: depend-clause, doacross-clause
4510 OmpDependenceType::Value GetDepType() const;
4511
4512 WRAPPER_CLASS(Sink, OmpIterationVector);
4513 EMPTY_CLASS(Source);
4514 UNION_CLASS_BOILERPLATE(OmpDoacross);
4515 std::variant<Sink, Source> u;
4516};
4517
4518// Ref: [4.5:169-172], [5.0:255-259], [5.1:288-292], [5.2:323-326]
4519//
4520// depend-clause ->
4521// DEPEND(SOURCE) | // since 4.5, until 5.1
4522// DEPEND(SINK: iteration-vector) | // since 4.5, until 5.1
4523// DEPEND([depend-modifier,]
4524// task-dependence-type: locator-list) // since 4.5
4525//
4526// depend-modifier -> iterator-modifier // since 5.0
4528 UNION_CLASS_BOILERPLATE(OmpDependClause);
4529 struct TaskDep {
4530 OmpTaskDependenceType::Value GetTaskDepType() const;
4531 TUPLE_CLASS_BOILERPLATE(TaskDep);
4532 MODIFIER_BOILERPLATE(OmpIterator, OmpTaskDependenceType);
4533 std::tuple<MODIFIERS(), OmpObjectList> t;
4534 };
4535 std::variant<TaskDep, OmpDoacross> u;
4536};
4537
4538// Ref: [5.2:326-328]
4539//
4540// doacross-clause ->
4541// DOACROSS(dependence-type: iteration-vector) // since 5.2
4543 WRAPPER_CLASS_BOILERPLATE(OmpDoacrossClause, OmpDoacross);
4544};
4545
4546// Ref: [5.0:254-255], [5.1:287-288], [5.2:73]
4547//
4548// destroy-clause ->
4549// DESTROY | // since 5.0, until 5.1
4550// DESTROY(variable) // since 5.2
4552 WRAPPER_CLASS_BOILERPLATE(OmpDestroyClause, OmpObject);
4553};
4554
4555// Ref: [5.0:135-140], [5.1:161-166], [5.2:265-266]
4556//
4557// detach-clause ->
4558// DETACH(event-handle) // since 5.0
4560 WRAPPER_CLASS_BOILERPLATE(OmpDetachClause, OmpObject);
4561};
4562
4563// Ref: [4.5:103-107], [5.0:170-176], [5.1:197-205], [5.2:276-277]
4564//
4565// device-clause ->
4566// DEVICE(scalar-integer-expression) | // since 4.5
4567// DEVICE([device-modifier:]
4568// scalar-integer-expression) // since 5.0
4570 TUPLE_CLASS_BOILERPLATE(OmpDeviceClause);
4571 MODIFIER_BOILERPLATE(OmpDeviceModifier);
4572 std::tuple<MODIFIERS(), ScalarIntExpr> t;
4573};
4574
4575// Ref: [6.0:356-362]
4576//
4577// device-safesync-clause ->
4578// DEVICE_SAFESYNC [(scalar-logical-const-expr)] // since 6.0
4580 WRAPPER_CLASS_BOILERPLATE(OmpDeviceSafesyncClause, ScalarLogicalConstantExpr);
4581};
4582
4583// Ref: [5.0:180-185], [5.1:210-216], [5.2:275]
4584//
4585// device-type-clause ->
4586// DEVICE_TYPE(ANY | HOST | NOHOST) // since 5.0
4588 ENUM_CLASS(DeviceTypeDescription, Any, Host, Nohost)
4589 WRAPPER_CLASS_BOILERPLATE(OmpDeviceTypeClause, DeviceTypeDescription);
4590};
4591
4592// Ref: [5.0:60-63], [5.1:83-86], [5.2:212-213], [6.0:356-362]
4593//
4594// dynamic-allocators-clause ->
4595// DYNAMIC_ALLOCATORS // since 5.0
4596// [(scalar-logical-const-expr)] // since 6.0
4598 WRAPPER_CLASS_BOILERPLATE(
4599 OmpDynamicAllocatorsClause, ScalarLogicalConstantExpr);
4600};
4601
4603 TUPLE_CLASS_BOILERPLATE(OmpDynGroupprivateClause);
4604 MODIFIER_BOILERPLATE(OmpAccessGroup, OmpFallbackModifier);
4605 std::tuple<MODIFIERS(), ScalarIntExpr> t;
4606};
4607
4608// Ref: [5.2:158-159], [6.0:289-290]
4609//
4610// enter-clause ->
4611// ENTER(locator-list) |
4612// ENTER(automap-modifier: locator-list) | // since 6.0
4614 TUPLE_CLASS_BOILERPLATE(OmpEnterClause);
4615 MODIFIER_BOILERPLATE(OmpAutomapModifier);
4616 std::tuple<MODIFIERS(), OmpObjectList> t;
4617};
4618
4619// OMP 5.2 15.8.3 extended-atomic, fail-clause ->
4620// FAIL(memory-order)
4622 using MemoryOrder = common::OmpMemoryOrderType;
4623 WRAPPER_CLASS_BOILERPLATE(OmpFailClause, MemoryOrder);
4624};
4625
4626// Ref: [4.5:107-109], [5.0:176-180], [5.1:205-210], [5.2:167-168]
4627//
4628// from-clause ->
4629// FROM(locator-list) |
4630// FROM(mapper-modifier: locator-list) | // since 5.0
4631// FROM(motion-modifier[,] ...: locator-list) // since 5.1
4632// motion-modifier ->
4633// PRESENT | mapper-modifier | iterator-modifier
4635 TUPLE_CLASS_BOILERPLATE(OmpFromClause);
4636 MODIFIER_BOILERPLATE(OmpExpectation, OmpIterator, OmpMapper);
4637 std::tuple<MODIFIERS(), OmpObjectList, /*CommaSeparated=*/bool> t;
4638};
4639
4640// Ref: [4.5:87-91], [5.0:140-146], [5.1:166-171], [5.2:269]
4641//
4642// grainsize-clause ->
4643// GRAINSIZE(grain-size) | // since 4.5
4644// GRAINSIZE([prescriptiveness:] grain-size) // since 5.1
4646 TUPLE_CLASS_BOILERPLATE(OmpGrainsizeClause);
4647 MODIFIER_BOILERPLATE(OmpPrescriptiveness);
4648 std::tuple<MODIFIERS(), ScalarIntExpr> t;
4649};
4650
4651// Ref: [6.0:438]
4652//
4653// graph_id-clause ->
4654// GRAPH_ID(graph-id-value) // since 6.0
4656 WRAPPER_CLASS_BOILERPLATE(OmpGraphIdClause, ScalarIntExpr);
4657};
4658
4659// Ref: [6.0:438-439]
4660//
4661// graph_reset-clause ->
4662// GRAPH_RESET[(graph-reset-expression)] // since 6.0
4664 WRAPPER_CLASS_BOILERPLATE(OmpGraphResetClause, ScalarLogicalExpr);
4665};
4666
4667// Ref: [5.0:234-242], [5.1:266-275], [5.2:299], [6.0:472-473]
4669 WRAPPER_CLASS_BOILERPLATE(OmpHintClause, ScalarIntConstantExpr);
4670};
4671
4672// Ref: [5.2: 214]
4673//
4674// holds-clause ->
4675// HOLDS(expr)
4677 WRAPPER_CLASS_BOILERPLATE(OmpHoldsClause, common::Indirection<Expr>);
4678};
4679
4680// Ref: [5.2: 209]
4682 WRAPPER_CLASS_BOILERPLATE(
4683 OmpIndirectClause, std::optional<ScalarLogicalExpr>);
4684};
4685
4686// Ref: [5.2:72-73], in 4.5-5.1 it's scattered over individual directives
4687// that allow the IF clause.
4688//
4689// if-clause ->
4690// IF([directive-name-modifier:]
4691// scalar-logical-expression) // since 4.5
4693 TUPLE_CLASS_BOILERPLATE(OmpIfClause);
4694 MODIFIER_BOILERPLATE(OmpDirectiveNameModifier);
4695 std::tuple<MODIFIERS(), ScalarLogicalExpr> t;
4696};
4697
4698// Ref: [5.1:217-220], [5.2:293-294], [6.0:180-181]
4699//
4700// init-clause ->
4701// INIT ([modifier... :] interop-var) // since 5.1
4702// modifier ->
4703// prefer-type | interop-type | // since 5.1
4704// depinfo-modifier // since 6.0
4706 TUPLE_CLASS_BOILERPLATE(OmpInitClause);
4707 MODIFIER_BOILERPLATE(OmpPreferType, OmpInteropType, OmpDepinfoModifier);
4708 std::tuple<MODIFIERS(), OmpObject> t;
4709};
4710
4711// Ref: [5.0:170-176], [5.1:197-205], [5.2:138-139]
4712//
4713// in-reduction-clause ->
4714// IN_REDUCTION(reduction-identifier: list) // since 5.0
4716 TUPLE_CLASS_BOILERPLATE(OmpInReductionClause);
4717 MODIFIER_BOILERPLATE(OmpReductionIdentifier);
4718 std::tuple<MODIFIERS(), OmpObjectList> t;
4719};
4720
4721// Initialization for declare reduction construct
4723 WRAPPER_CLASS_BOILERPLATE(OmpInitializerClause, OmpInitializerExpression);
4724};
4725
4726// Ref: [4.5:199-201], [5.0:288-290], [5.1:321-322], [5.2:115-117]
4727//
4728// lastprivate-clause ->
4729// LASTPRIVATE(list) | // since 4.5
4730// LASTPRIVATE([lastprivate-modifier:] list) // since 5.0
4732 TUPLE_CLASS_BOILERPLATE(OmpLastprivateClause);
4733 MODIFIER_BOILERPLATE(OmpLastprivateModifier);
4734 std::tuple<MODIFIERS(), OmpObjectList> t;
4735};
4736
4737// Ref: [4.5:207-210], [5.0:290-293], [5.1:323-325], [5.2:117-120]
4738//
4739// linear-clause ->
4740// LINEAR(list [: step-simple-modifier]) | // since 4.5
4741// LINEAR(linear-modifier(list)
4742// [: step-simple-modifier]) | // since 4.5, until 5.2[*]
4743// LINEAR(list [: linear-modifier,
4744// step-complex-modifier]) // since 5.2
4745// [*] Still allowed in 5.2 when on DECLARE SIMD, but deprecated.
4747 TUPLE_CLASS_BOILERPLATE(OmpLinearClause);
4748 MODIFIER_BOILERPLATE(
4750 std::tuple<OmpObjectList, MODIFIERS(), /*PostModified=*/bool> t;
4751};
4752
4753// Ref: [6.0:207-208]
4754//
4755// looprange-clause ->
4756// LOOPRANGE(first, count) // since 6.0
4758 TUPLE_CLASS_BOILERPLATE(OmpLooprangeClause);
4759 std::tuple<ScalarIntConstantExpr, ScalarIntConstantExpr> t;
4760};
4761
4762// Ref: [4.5:216-219], [5.0:315-324], [5.1:347-355], [5.2:150-158]
4763//
4764// map-clause ->
4765// MAP([modifier...:] locator-list) // since 4.5
4766// modifier ->
4767// map-type-modifier [replaced] | // since 4.5, until 5.2
4768// always-modifier | // since 6.0
4769// attach-modifier | // since 6.1
4770// close-modifier | // since 6.0
4771// delete-modifier | // since 6.0
4772// present-modifier | // since 6.0
4773// ref-modifier | // since 6.0
4774// self-modifier | // since 6.0
4775// mapper | // since 5.0
4776// iterator | // since 5.1
4777// map-type // since 4.5
4778// ompx-hold-modifier | // since 6.0
4779//
4780// Since 6.0 the map-type-modifier has been split into individual modifiers,
4781// and delete-modifier has been split from map-type.
4783 TUPLE_CLASS_BOILERPLATE(OmpMapClause);
4787 std::tuple<MODIFIERS(), OmpObjectList, /*CommaSeparated=*/bool> t;
4788};
4789
4790// Ref: [5.0:58-60], [5.1:63-68], [5.2:194-195]
4791//
4792// match-clause ->
4793// MATCH (context-selector-specification) // since 5.0
4795 // The context-selector is an argument.
4796 WRAPPER_CLASS_BOILERPLATE(
4798};
4799
4800// Ref: [5.2:217-218]
4801// message-clause ->
4802// MESSAGE("message-text")
4804 WRAPPER_CLASS_BOILERPLATE(OmpMessageClause, Expr);
4805};
4806
4807// Ref: [5.2: 214]
4808//
4809// no_openmp_clause -> NO_OPENMP
4810EMPTY_CLASS(OmpNoOpenMPClause);
4811
4812// Ref: [5.2: 214]
4813//
4814// no_openmp_routines_clause -> NO_OPENMP_ROUTINES
4815EMPTY_CLASS(OmpNoOpenMPRoutinesClause);
4816
4817// Ref: [5.2: 214]
4818//
4819// no_parallelism_clause -> NO_PARALELISM
4820EMPTY_CLASS(OmpNoParallelismClause);
4821
4822// Ref: [4.5:87-91], [5.0:140-146], [5.1:166-171], [5.2:270]
4823//
4824// num-tasks-clause ->
4825// NUM_TASKS(num-tasks) | // since 4.5
4826// NUM_TASKS([prescriptiveness:] num-tasks) // since 5.1
4828 TUPLE_CLASS_BOILERPLATE(OmpNumTasksClause);
4829 MODIFIER_BOILERPLATE(OmpPrescriptiveness);
4830 std::tuple<MODIFIERS(), ScalarIntExpr> t;
4831};
4832
4833// Ref: [4.5:114-116], [5.0:82-85], [5.1:100-104], [5.2:277], [6.0:452-453]
4834//
4835// num-teams-clause ->
4836// NUM_TEAMS(expr) | // since 4.5
4837// NUM_TEAMS([lower-bound:] upper-bound) | // since 5.1
4838// NUM_TEAMS([dims: upper-bound...) // since 6.1
4840 TUPLE_CLASS_BOILERPLATE(OmpNumTeamsClause);
4841 MODIFIER_BOILERPLATE(OmpDimsModifier, OmpLowerBound);
4842 std::tuple<MODIFIERS(), std::list<ScalarIntExpr>> t;
4843};
4844
4845// Ref: [4.5:46-50], [5.0:74-78], [5.1:92-96], [5.2:227], [6.0:388-389]
4846//
4847// num-threads-clause
4848// NUM_THREADS(expr) | // since 4.5
4849// NUM_THREADS(expr...) | // since 6.0
4850// NUM_THREADS([dims-modifier:] expr...) // since 6.1
4852 TUPLE_CLASS_BOILERPLATE(OmpNumThreadsClause);
4853 MODIFIER_BOILERPLATE(OmpDimsModifier);
4854 std::tuple<MODIFIERS(), std::list<ScalarIntExpr>> t;
4855};
4856
4857// Ref: [5.0:101-109], [5.1:126-134], [5.2:233-234]
4858//
4859// order-clause ->
4860// ORDER(CONCURRENT) | // since 5.0
4861// ORDER([order-modifier:] CONCURRENT) // since 5.1
4863 TUPLE_CLASS_BOILERPLATE(OmpOrderClause);
4864 ENUM_CLASS(Ordering, Concurrent)
4865 MODIFIER_BOILERPLATE(OmpOrderModifier);
4866 std::tuple<MODIFIERS(), Ordering> t;
4867};
4868
4869// Ref: [5.0:56-57], [5.1:60-62], [5.2:191]
4870//
4871// otherwise-clause ->
4872// DEFAULT ([directive-specification]) // since 5.0, until 5.1
4873// otherwise-clause ->
4874// OTHERWISE ([directive-specification])] // since 5.2
4876 WRAPPER_CLASS_BOILERPLATE(OmpOtherwiseClause,
4878};
4879
4880// Ref: [4.5:46-50], [5.0:74-78], [5.1:92-96], [5.2:229-230]
4881//
4882// proc-bind-clause ->
4883// PROC_BIND(affinity-policy) // since 4.5
4884// affinity-policy ->
4885// CLOSE | PRIMARY | SPREAD | // since 4.5
4886// MASTER // since 4.5, until 5.2
4888 ENUM_CLASS(AffinityPolicy, Close, Master, Spread, Primary)
4889 WRAPPER_CLASS_BOILERPLATE(OmpProcBindClause, AffinityPolicy);
4890};
4891
4892// Ref: [4.5:201-207], [5.0:300-302], [5.1:332-334], [5.2:134-137]
4893//
4894// reduction-clause ->
4895// REDUCTION(reduction-identifier: list) | // since 4.5
4896// REDUCTION([reduction-modifier,]
4897// reduction-identifier: list) // since 5.0
4899 TUPLE_CLASS_BOILERPLATE(OmpReductionClause);
4900 MODIFIER_BOILERPLATE(OmpReductionModifier, OmpReductionIdentifier);
4901 std::tuple<MODIFIERS(), OmpObjectList> t;
4902};
4903
4904// Ref: [6.0:440:441]
4905//
4906// replayable-clause ->
4907// REPLAYABLE[(replayable-expression)] // since 6.0
4909 WRAPPER_CLASS_BOILERPLATE(OmpReplayableClause, ScalarLogicalConstantExpr);
4910};
4911
4912// Ref: [5.0:60-63], [5.1:83-86], [5.2:212-213], [6.0:356-362]
4913//
4914// reverse-offload-clause ->
4915// REVERSE_OFFLOAD // since 5.0
4916// [(scalar-logical-const-expr)] // since 6.0
4918 WRAPPER_CLASS_BOILERPLATE(OmpReverseOffloadClause, ScalarLogicalConstantExpr);
4919};
4920
4921// Ref: [4.5:56-63], [5.0:101-109], [5.1:126-133], [5.2:252-254]
4922//
4923// schedule-clause ->
4924// SCHEDULE([modifier[, modifier]:]
4925// kind[, chunk-size]) // since 4.5, until 5.1
4926// schedule-clause ->
4927// SCHEDULE([ordering-modifier], chunk-modifier],
4928// kind[, chunk_size]) // since 5.2
4930 TUPLE_CLASS_BOILERPLATE(OmpScheduleClause);
4931 ENUM_CLASS(Kind, Static, Dynamic, Guided, Auto, Runtime)
4932 MODIFIER_BOILERPLATE(OmpOrderingModifier, OmpChunkModifier);
4933 std::tuple<MODIFIERS(), Kind, std::optional<ScalarIntExpr>> t;
4934};
4935
4936// ref: [6.0:361-362]
4937//
4938// self-maps-clause ->
4939// SELF_MAPS [(scalar-logical-const-expr)] // since 6.0
4941 WRAPPER_CLASS_BOILERPLATE(OmpSelfMapsClause, ScalarLogicalConstantExpr);
4942};
4943
4944// REF: [5.2:217]
4945// severity-clause ->
4946// SEVERITY(warning|fatal)
4948 ENUM_CLASS(SevLevel, Fatal, Warning);
4949 WRAPPER_CLASS_BOILERPLATE(OmpSeverityClause, SevLevel);
4950};
4951
4952// Ref: [5.0:232-234], [5.1:264-266], [5.2:137]
4953//
4954// task-reduction-clause ->
4955// TASK_REDUCTION(reduction-identifier: list) // since 5.0
4957 TUPLE_CLASS_BOILERPLATE(OmpTaskReductionClause);
4958 MODIFIER_BOILERPLATE(OmpReductionIdentifier);
4959 std::tuple<MODIFIERS(), OmpObjectList> t;
4960};
4961
4962// Ref: [4.5:114-116], [5.0:82-85], [5.1:100-104], [5.2:277], [6.0:452-453]
4963//
4964// thread-limit-clause ->
4965// THREAD_LIMIT(threadlim) // since 4.5
4966// THREAD_LIMIT([dims-modifier:] threadlim...) // since 6.1
4968 TUPLE_CLASS_BOILERPLATE(OmpThreadLimitClause);
4969 MODIFIER_BOILERPLATE(OmpDimsModifier);
4970 std::tuple<MODIFIERS(), std::list<ScalarIntExpr>> t;
4971};
4972
4973// Ref: [6.0:442]
4974// threadset-clause ->
4975// THREADSET(omp_pool|omp_team)
4977 ENUM_CLASS(ThreadsetPolicy, Omp_Pool, Omp_Team)
4978 WRAPPER_CLASS_BOILERPLATE(OmpThreadsetClause, ThreadsetPolicy);
4979};
4980
4981// Ref: [4.5:107-109], [5.0:176-180], [5.1:205-210], [5.2:167-168]
4982//
4983// to-clause (in DECLARE TARGET) ->
4984// TO(extended-list) | // until 5.1
4985// to-clause (in TARGET UPDATE) ->
4986// TO(locator-list) |
4987// TO(mapper-modifier: locator-list) | // since 5.0
4988// TO(motion-modifier[,] ...: locator-list) // since 5.1
4989// motion-modifier ->
4990// PRESENT | mapper-modifier | iterator-modifier
4992 TUPLE_CLASS_BOILERPLATE(OmpToClause);
4993 MODIFIER_BOILERPLATE(OmpExpectation, OmpIterator, OmpMapper);
4994 std::tuple<MODIFIERS(), OmpObjectList, /*CommaSeparated=*/bool> t;
4995};
4996
4997// Ref: [6.0:510-511]
4998//
4999// transparent-clause ->
5000// TRANSPARENT[(impex-type)] // since 6.0
5002 WRAPPER_CLASS_BOILERPLATE(OmpTransparentClause, ScalarIntExpr);
5003};
5004
5005// Ref: [5.0:60-63], [5.1:83-86], [5.2:212-213], [6.0:356-362]
5006//
5007// unified-address-clause ->
5008// UNIFIED_ADDRESS // since 5.0
5009// [(scalar-logical-const-expr)] // since 6.0
5011 WRAPPER_CLASS_BOILERPLATE(OmpUnifiedAddressClause, ScalarLogicalConstantExpr);
5012};
5013
5014// Ref: [5.0:60-63], [5.1:83-86], [5.2:212-213], [6.0:356-362]
5015//
5016// unified-shared-memory-clause ->
5017// UNIFIED_SHARED_MEMORY // since 5.0
5018// [(scalar-logical-const-expr)] // since 6.0
5020 WRAPPER_CLASS_BOILERPLATE(
5021 OmpUnifiedSharedMemoryClause, ScalarLogicalConstantExpr);
5022};
5023
5024// Ref: [5.0:254-255], [5.1:287-288], [5.2:321-322]
5025//
5026// In ATOMIC construct
5027// update-clause ->
5028// UPDATE // Since 4.5
5029//
5030// In DEPOBJ construct
5031// update-clause ->
5032// UPDATE(dependence-type) // since 5.0, until 5.1
5033// update-clause ->
5034// UPDATE(task-dependence-type) // since 5.2
5036 UNION_CLASS_BOILERPLATE(OmpUpdateClause);
5037 // The dependence type is an argument here, not a modifier.
5038 std::variant<OmpDependenceType, OmpTaskDependenceType> u;
5039};
5040
5041// Ref: [5.0:56-57], [5.1:60-62], [5.2:190-191]
5042//
5043// when-clause ->
5044// WHEN (context-selector :
5045// [directive-specification]) // since 5.0
5047 TUPLE_CLASS_BOILERPLATE(OmpWhenClause);
5048 MODIFIER_BOILERPLATE(OmpContextSelector);
5049 std::tuple<MODIFIERS(),
5050 std::optional<common::Indirection<OmpDirectiveSpecification>>>
5051 t;
5052};
5053
5054// REF: [5.1:217-220], [5.2:294]
5055//
5056// 14.1.3 use-clause -> USE (interop-var)
5058 WRAPPER_CLASS_BOILERPLATE(OmpUseClause, OmpObject);
5059};
5060
5061// OpenMP Clauses
5063 UNION_CLASS_BOILERPLATE(OmpClause);
5064 llvm::omp::Clause Id() const;
5065
5066#define GEN_FLANG_CLAUSE_PARSER_CLASSES
5067#include "llvm/Frontend/OpenMP/OMP.inc"
5068
5069 CharBlock source;
5070
5071 std::variant<
5072#define GEN_FLANG_CLAUSE_PARSER_CLASSES_LIST
5073#include "llvm/Frontend/OpenMP/OMP.inc"
5074 >
5075 u;
5076};
5077
5079 WRAPPER_CLASS_BOILERPLATE(OmpClauseList, std::list<OmpClause>);
5080 CharBlock source;
5081};
5082
5083// --- Directives and constructs
5084
5086 ENUM_CLASS(Flag, DeprecatedSyntax, CrossesLabelDo, ExplicitBegin)
5088
5089 TUPLE_CLASS_BOILERPLATE(OmpDirectiveSpecification);
5090 const OmpDirectiveName &DirName() const {
5091 return std::get<OmpDirectiveName>(t);
5092 }
5093 llvm::omp::Directive DirId() const { //
5094 return DirName().v;
5095 }
5096 const OmpArgumentList &Arguments() const;
5097 const OmpClauseList &Clauses() const;
5098
5099 CharBlock source;
5100 std::tuple<OmpDirectiveName, std::optional<OmpArgumentList>,
5101 std::optional<OmpClauseList>, Flags>
5102 t;
5103};
5104
5105// OmpBeginDirective and OmpEndDirective are needed for semantic analysis,
5106// where some checks are done specifically for either the begin or the end
5107// directive. The structure of both is identical, but the diffent types
5108// allow to distinguish them in the type-based parse-tree visitor.
5110 INHERITED_TUPLE_CLASS_BOILERPLATE(
5112};
5113
5115 INHERITED_TUPLE_CLASS_BOILERPLATE(OmpEndDirective, OmpDirectiveSpecification);
5116};
5117
5118// Common base class for block-associated constructs.
5120 TUPLE_CLASS_BOILERPLATE(OmpBlockConstruct);
5121 const OmpBeginDirective &BeginDir() const {
5122 return std::get<OmpBeginDirective>(t);
5123 }
5124 const std::optional<OmpEndDirective> &EndDir() const {
5125 return std::get<std::optional<OmpEndDirective>>(t);
5126 }
5127
5128 CharBlock source;
5129 std::tuple<OmpBeginDirective, Block, std::optional<OmpEndDirective>> t;
5130};
5131
5133 WRAPPER_CLASS_BOILERPLATE(
5135};
5136
5138 INHERITED_TUPLE_CLASS_BOILERPLATE(
5140};
5141
5142// Ref: [5.1:89-90], [5.2:216]
5143//
5144// nothing-directive ->
5145// NOTHING // since 5.1
5147 WRAPPER_CLASS_BOILERPLATE(OmpNothingDirective, OmpDirectiveSpecification);
5148};
5149
5150// Ref: OpenMP [5.2:216-218]
5151// ERROR AT(compilation|execution) SEVERITY(fatal|warning) MESSAGE("msg-str)
5153 WRAPPER_CLASS_BOILERPLATE(OmpErrorDirective, OmpDirectiveSpecification);
5154};
5155
5157 UNION_CLASS_BOILERPLATE(OmpUtilityDirective);
5158 CharBlock source;
5159 std::variant<OmpErrorDirective, OmpNothingDirective> u;
5160};
5161
5162// Ref: [5.2: 213-216]
5163//
5164// assumes-construct ->
5165// ASSUMES absent-clause | contains-clause | holds-clause | no-openmp-clause |
5166// no-openmp-routines-clause | no-parallelism-clause
5168 WRAPPER_CLASS_BOILERPLATE(OmpAssumesDirective, OmpDirectiveSpecification);
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(OmpAssumeDirective, 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(OmpSectionDirective);
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 // OmpSectionDirective. 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(
5276 CharBlock source;
5277};
5278
5279// 2.4 requires -> REQUIRES requires-clause[ [ [,] requires-clause]...]
5281 WRAPPER_CLASS_BOILERPLATE(OmpRequiresDirective, OmpDirectiveSpecification);
5282 CharBlock source;
5283};
5284
5285// 2.15.2 threadprivate -> THREADPRIVATE (variable-name-list)
5287 WRAPPER_CLASS_BOILERPLATE(
5289 CharBlock source;
5290};
5291
5292// Ref: [4.5:310-312], [5.0:156-158], [5.1:181-184], [5.2:176-177],
5293// [6.0:310-312]
5294//
5295// allocate-directive ->
5296// ALLOCATE (variable-list-item...) | // since 4.5
5297// ALLOCATE (variable-list-item...) // since 5.0, until 5.1
5298// ...
5299// allocate-stmt
5300//
5301// The first form is the "declarative-allocate", and is a declarative
5302// directive. The second is the "executable-allocate" and is an executable
5303// directive. The executable form was deprecated in 5.2.
5304//
5305// The executable-allocate consists of several ALLOCATE directives. Since
5306// in the parse tree every type corresponding to a directive only corresponds
5307// to a single directive, the executable form is represented by a sequence
5308// of nested OmpAlocateDirectives, e.g.
5309// !$OMP ALLOCATE(x)
5310// !$OMP ALLOCATE(y)
5311// ALLOCATE(x, y)
5312// will become
5313// OmpAllocateDirective
5314// |- ALLOCATE(x) // begin directive
5315// `- OmpAllocateDirective // block
5316// |- ALLOCATE(y) // begin directive
5317// `- ALLOCATE(x, y) // block
5318//
5319// The block in the declarative-allocate will be empty.
5321 INHERITED_TUPLE_CLASS_BOILERPLATE(OmpAllocateDirective, OmpBlockConstruct);
5322};
5323
5335
5337 INHERITED_TUPLE_CLASS_BOILERPLATE(OpenMPCriticalConstruct, OmpBlockConstruct);
5338};
5339
5340// Ref: [5.2:180-181], [6.0:315]
5341//
5342// allocators-construct ->
5343// ALLOCATORS [allocate-clause...]
5344// block
5345// [END ALLOCATORS]
5347 INHERITED_TUPLE_CLASS_BOILERPLATE(
5349};
5350
5352 llvm::omp::Clause GetKind() const;
5353 bool IsCapture() const;
5354 bool IsCompare() const;
5355 INHERITED_TUPLE_CLASS_BOILERPLATE(OpenMPAtomicConstruct, OmpBlockConstruct);
5356
5357 // Information filled out during semantic checks to avoid duplication
5358 // of analyses.
5359 struct Analysis {
5360 static constexpr int None = 0;
5361 static constexpr int Read = 1;
5362 static constexpr int Write = 2;
5363 static constexpr int Update = Read | Write;
5364 static constexpr int Action = 3; // Bitmask for None, Read, Write, Update
5365 static constexpr int IfTrue = 4;
5366 static constexpr int IfFalse = 8;
5367 static constexpr int Condition = 12; // Bitmask for IfTrue, IfFalse
5368
5369 struct Op {
5370 int what;
5371 TypedAssignment assign;
5372 };
5373 TypedExpr atom, cond;
5374 Op op0, op1;
5375 };
5376
5377 mutable Analysis analysis;
5378};
5379
5380// 2.14.2 cancellation-point -> CANCELLATION POINT construct-type-clause
5382 WRAPPER_CLASS_BOILERPLATE(
5384 CharBlock source;
5385};
5386
5387// 2.14.1 cancel -> CANCEL construct-type-clause [ [,] if-clause]
5389 WRAPPER_CLASS_BOILERPLATE(OpenMPCancelConstruct, OmpDirectiveSpecification);
5390 CharBlock source;
5391};
5392
5393// Ref: [5.0:254-255], [5.1:287-288], [5.2:322-323]
5394//
5395// depobj-construct -> DEPOBJ(depend-object) depobj-clause // since 5.0
5396// depobj-clause -> depend-clause | // until 5.2
5397// destroy-clause |
5398// update-clause
5400 WRAPPER_CLASS_BOILERPLATE(OpenMPDepobjConstruct, OmpDirectiveSpecification);
5401 CharBlock source;
5402};
5403
5404// Ref: [5.2: 200-201]
5405//
5406// dispatch-construct -> DISPATCH dispatch-clause
5407// dispatch-clause -> depend-clause |
5408// device-clause |
5409// is_device_ptr-clause |
5410// nocontext-clause |
5411// novariants-clause |
5412// nowait-clause
5414 INHERITED_TUPLE_CLASS_BOILERPLATE(OpenMPDispatchConstruct, OmpBlockConstruct);
5415};
5416
5417// [4.5:162-165], [5.0:242-246], [5.1:275-279], [5.2:315-316], [6.0:498-500]
5418//
5419// flush-construct ->
5420// FLUSH [(list)] // since 4.5, until 4.5
5421// flush-construct ->
5422// FLUSH [memory-order-clause] [(list)] // since 5.0, until 5.1
5423// flush-construct ->
5424// FLUSH [(list)] [clause-list] // since 5.2
5425//
5426// memory-order-clause -> // since 5.0, until 5.1
5427// ACQ_REL | RELEASE | ACQUIRE | // since 5.0
5428// SEQ_CST // since 5.1
5430 WRAPPER_CLASS_BOILERPLATE(OpenMPFlushConstruct, OmpDirectiveSpecification);
5431 CharBlock source;
5432};
5433
5434// Ref: [5.1:217-220], [5.2:291-292]
5435//
5436// interop -> INTEROP clause[ [ [,] clause]...]
5438 WRAPPER_CLASS_BOILERPLATE(OpenMPInteropConstruct, OmpDirectiveSpecification);
5439 CharBlock source;
5440};
5441
5443 WRAPPER_CLASS_BOILERPLATE(
5445 CharBlock source;
5446};
5447
5456
5457// OpenMP directives enclosing do loop
5459 INHERITED_TUPLE_CLASS_BOILERPLATE(OpenMPLoopConstruct, OmpBlockConstruct);
5460
5461 const DoConstruct *GetNestedLoop() const;
5462 const OpenMPLoopConstruct *GetNestedConstruct() const;
5463};
5464
5465// Lookahead class to identify execution-part OpenMP constructs without
5466// parsing the entire OpenMP construct.
5468 WRAPPER_CLASS_BOILERPLATE(OpenMPExecDirective, OmpDirectiveName);
5469 CharBlock source;
5470};
5471
5481
5482// Orphaned !$OMP END <directive>, i.e. not being a part of a valid OpenMP
5483// construct.
5485 INHERITED_TUPLE_CLASS_BOILERPLATE(
5487};
5488
5489// Unrecognized string after the !$OMP sentinel.
5491 using EmptyTrait = std::true_type;
5492 CharBlock source;
5493};
5494
5495// Parse tree nodes for OpenACC 3.3 directives and clauses
5496
5498 UNION_CLASS_BOILERPLATE(AccObject);
5499 std::variant<Designator, /*common block*/ Name> u;
5500};
5501
5502WRAPPER_CLASS(AccObjectList, std::list<AccObject>);
5503
5504// OpenACC directive beginning or ending a block
5506 WRAPPER_CLASS_BOILERPLATE(AccBlockDirective, llvm::acc::Directive);
5507 CharBlock source;
5508};
5509
5511 WRAPPER_CLASS_BOILERPLATE(AccLoopDirective, llvm::acc::Directive);
5512 CharBlock source;
5513};
5514
5516 WRAPPER_CLASS_BOILERPLATE(AccStandaloneDirective, llvm::acc::Directive);
5517 CharBlock source;
5518};
5519
5520// 2.11 Combined constructs
5522 WRAPPER_CLASS_BOILERPLATE(AccCombinedDirective, llvm::acc::Directive);
5523 CharBlock source;
5524};
5525
5527 WRAPPER_CLASS_BOILERPLATE(AccDeclarativeDirective, llvm::acc::Directive);
5528 CharBlock source;
5529};
5530
5531// OpenACC Clauses
5533 UNION_CLASS_BOILERPLATE(AccBindClause);
5534 std::variant<Name, ScalarDefaultCharExpr> u;
5535 CharBlock source;
5536};
5537
5539 WRAPPER_CLASS_BOILERPLATE(AccDefaultClause, llvm::acc::DefaultValue);
5540 CharBlock source;
5541};
5542
5544 ENUM_CLASS(Modifier, ReadOnly, Zero)
5545 WRAPPER_CLASS_BOILERPLATE(AccDataModifier, Modifier);
5546 CharBlock source;
5547};
5548
5550 TUPLE_CLASS_BOILERPLATE(AccObjectListWithModifier);
5551 std::tuple<std::optional<AccDataModifier>, AccObjectList> t;
5552};
5553
5555 TUPLE_CLASS_BOILERPLATE(AccObjectListWithReduction);
5556 std::tuple<ReductionOperator, AccObjectList> t;
5557};
5558
5560 TUPLE_CLASS_BOILERPLATE(AccWaitArgument);
5561 std::tuple<std::optional<ScalarIntExpr>, std::list<ScalarIntExpr>> t;
5562};
5563
5565 WRAPPER_CLASS_BOILERPLATE(
5566 AccDeviceTypeExpr, Fortran::common::OpenACCDeviceType);
5567 CharBlock source;
5568};
5569
5571 WRAPPER_CLASS_BOILERPLATE(
5572 AccDeviceTypeExprList, std::list<AccDeviceTypeExpr>);
5573};
5574
5576 TUPLE_CLASS_BOILERPLATE(AccTileExpr);
5577 CharBlock source;
5578 std::tuple<std::optional<ScalarIntConstantExpr>> t; // if null then *
5579};
5580
5582 WRAPPER_CLASS_BOILERPLATE(AccTileExprList, std::list<AccTileExpr>);
5583};
5584
5586 WRAPPER_CLASS_BOILERPLATE(AccSizeExpr, std::optional<ScalarIntExpr>);
5587};
5588
5590 WRAPPER_CLASS_BOILERPLATE(AccSizeExprList, std::list<AccSizeExpr>);
5591};
5592
5594 UNION_CLASS_BOILERPLATE(AccSelfClause);
5595 std::variant<std::optional<ScalarLogicalExpr>, AccObjectList> u;
5596 CharBlock source;
5597};
5598
5599// num, dim, static
5601 UNION_CLASS_BOILERPLATE(AccGangArg);
5602 WRAPPER_CLASS(Num, ScalarIntExpr);
5603 WRAPPER_CLASS(Dim, ScalarIntExpr);
5604 WRAPPER_CLASS(Static, AccSizeExpr);
5605 std::variant<Num, Dim, Static> u;
5606 CharBlock source;
5607};
5608
5610 WRAPPER_CLASS_BOILERPLATE(AccGangArgList, std::list<AccGangArg>);
5611};
5612
5614 TUPLE_CLASS_BOILERPLATE(AccCollapseArg);
5615 std::tuple<bool, ScalarIntConstantExpr> t;
5616};
5617
5619 UNION_CLASS_BOILERPLATE(AccClause);
5620
5621#define GEN_FLANG_CLAUSE_PARSER_CLASSES
5622#include "llvm/Frontend/OpenACC/ACC.inc"
5623
5624 CharBlock source;
5625
5626 std::variant<
5627#define GEN_FLANG_CLAUSE_PARSER_CLASSES_LIST
5628#include "llvm/Frontend/OpenACC/ACC.inc"
5629 >
5630 u;
5631};
5632
5634 WRAPPER_CLASS_BOILERPLATE(AccClauseList, std::list<AccClause>);
5635 CharBlock source;
5636};
5637
5639 TUPLE_CLASS_BOILERPLATE(OpenACCRoutineConstruct);
5640 CharBlock source;
5641 std::tuple<Verbatim, std::optional<Name>, AccClauseList> t;
5642};
5643
5645 TUPLE_CLASS_BOILERPLATE(OpenACCCacheConstruct);
5646 CharBlock source;
5647 std::tuple<Verbatim, AccObjectListWithModifier> t;
5648};
5649
5651 TUPLE_CLASS_BOILERPLATE(OpenACCWaitConstruct);
5652 CharBlock source;
5653 std::tuple<Verbatim, std::optional<AccWaitArgument>, AccClauseList> t;
5654};
5655
5657 TUPLE_CLASS_BOILERPLATE(AccBeginLoopDirective);
5658 std::tuple<AccLoopDirective, AccClauseList> t;
5659 CharBlock source;
5660};
5661
5663 TUPLE_CLASS_BOILERPLATE(AccBeginBlockDirective);
5664 CharBlock source;
5665 std::tuple<AccBlockDirective, AccClauseList> t;
5666};
5667
5669 CharBlock source;
5670 WRAPPER_CLASS_BOILERPLATE(AccEndBlockDirective, AccBlockDirective);
5671};
5672
5673// ACC END ATOMIC
5674EMPTY_CLASS(AccEndAtomic);
5675
5676// ACC ATOMIC READ
5678 TUPLE_CLASS_BOILERPLATE(AccAtomicRead);
5679 std::tuple<Verbatim, AccClauseList, Statement<AssignmentStmt>,
5680 std::optional<AccEndAtomic>>
5681 t;
5682};
5683
5684// ACC ATOMIC WRITE
5686 TUPLE_CLASS_BOILERPLATE(AccAtomicWrite);
5687 std::tuple<Verbatim, AccClauseList, Statement<AssignmentStmt>,
5688 std::optional<AccEndAtomic>>
5689 t;
5690};
5691
5692// ACC ATOMIC UPDATE
5694 TUPLE_CLASS_BOILERPLATE(AccAtomicUpdate);
5695 std::tuple<std::optional<Verbatim>, AccClauseList, Statement<AssignmentStmt>,
5696 std::optional<AccEndAtomic>>
5697 t;
5698};
5699
5700// ACC ATOMIC CAPTURE
5702 TUPLE_CLASS_BOILERPLATE(AccAtomicCapture);
5703 WRAPPER_CLASS(Stmt1, Statement<AssignmentStmt>);
5704 WRAPPER_CLASS(Stmt2, Statement<AssignmentStmt>);
5705 std::tuple<Verbatim, AccClauseList, Stmt1, Stmt2, AccEndAtomic> t;
5706};
5707
5709 UNION_CLASS_BOILERPLATE(OpenACCAtomicConstruct);
5710 std::variant<AccAtomicRead, AccAtomicWrite, AccAtomicCapture, AccAtomicUpdate>
5711 u;
5712 CharBlock source;
5713};
5714
5716 TUPLE_CLASS_BOILERPLATE(OpenACCBlockConstruct);
5717 std::tuple<AccBeginBlockDirective, Block, AccEndBlockDirective> t;
5718};
5719
5721 TUPLE_CLASS_BOILERPLATE(OpenACCStandaloneDeclarativeConstruct);
5722 CharBlock source;
5723 std::tuple<AccDeclarativeDirective, AccClauseList> t;
5724};
5725
5727 TUPLE_CLASS_BOILERPLATE(AccBeginCombinedDirective);
5728 CharBlock source;
5729 std::tuple<AccCombinedDirective, AccClauseList> t;
5730};
5731
5733 WRAPPER_CLASS_BOILERPLATE(AccEndCombinedDirective, AccCombinedDirective);
5734 CharBlock source;
5735};
5736
5737struct OpenACCCombinedConstruct {
5738 TUPLE_CLASS_BOILERPLATE(OpenACCCombinedConstruct);
5739 CharBlock source;
5740 OpenACCCombinedConstruct(AccBeginCombinedDirective &&a)
5741 : t({std::move(a), std::nullopt, std::nullopt}) {}
5742 std::tuple<AccBeginCombinedDirective, std::optional<DoConstruct>,
5743 std::optional<AccEndCombinedDirective>>
5744 t;
5745};
5746
5748 UNION_CLASS_BOILERPLATE(OpenACCDeclarativeConstruct);
5749 CharBlock source;
5750 std::variant<OpenACCStandaloneDeclarativeConstruct, OpenACCRoutineConstruct>
5751 u;
5752};
5753
5754// OpenACC directives enclosing do loop
5755EMPTY_CLASS(AccEndLoop);
5756struct OpenACCLoopConstruct {
5757 TUPLE_CLASS_BOILERPLATE(OpenACCLoopConstruct);
5758 OpenACCLoopConstruct(AccBeginLoopDirective &&a)
5759 : t({std::move(a), std::nullopt, std::nullopt}) {}
5760 std::tuple<AccBeginLoopDirective, std::optional<DoConstruct>,
5761 std::optional<AccEndLoop>>
5762 t;
5763};
5764
5766 WRAPPER_CLASS_BOILERPLATE(OpenACCEndConstruct, llvm::acc::Directive);
5767 CharBlock source;
5768};
5769
5771 TUPLE_CLASS_BOILERPLATE(OpenACCStandaloneConstruct);
5772 CharBlock source;
5773 std::tuple<AccStandaloneDirective, AccClauseList> t;
5774};
5775
5783
5784// CUF-kernel-do-construct ->
5785// !$CUF KERNEL DO [ (scalar-int-constant-expr) ]
5786// <<< grid, block [, stream] >>>
5787// [ cuf-reduction... ]
5788// do-construct
5789// star-or-expr -> * | scalar-int-expr
5790// grid -> * | scalar-int-expr | ( star-or-expr-list )
5791// block -> * | scalar-int-expr | ( star-or-expr-list )
5792// stream -> 0, scalar-int-expr | STREAM = scalar-int-expr
5793// cuf-reduction -> [ REDUCE | REDUCTION ] (
5794// reduction-op : scalar-variable-list )
5795
5797 TUPLE_CLASS_BOILERPLATE(CUFReduction);
5798 using Operator = ReductionOperator;
5799 std::tuple<Operator, std::list<Scalar<Variable>>> t;
5800};
5801
5803 TUPLE_CLASS_BOILERPLATE(CUFKernelDoConstruct);
5804 WRAPPER_CLASS(StarOrExpr, std::optional<ScalarIntExpr>);
5806 TUPLE_CLASS_BOILERPLATE(LaunchConfiguration);
5807 std::tuple<std::list<StarOrExpr>, std::list<StarOrExpr>,
5808 std::optional<ScalarIntExpr>>
5809 t;
5810 };
5811 struct Directive {
5812 TUPLE_CLASS_BOILERPLATE(Directive);
5813 CharBlock source;
5814 std::tuple<std::optional<ScalarIntConstantExpr>,
5815 std::optional<LaunchConfiguration>, std::list<CUFReduction>>
5816 t;
5817 };
5818 std::tuple<Directive, std::optional<DoConstruct>> t;
5819};
5820
5821} // namespace Fortran::parser
5822#endif // FORTRAN_PARSER_PARSE_TREE_H_
Definition enum-set.h:28
Definition indirection.h:127
Definition indirection.h:31
Definition reference.h:18
Definition call.h:234
Definition char-block.h:28
Definition parse-state.h:35
Definition symbol.h: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:5701
Definition parse-tree.h:5677
Definition parse-tree.h:5693
Definition parse-tree.h:5685
Definition parse-tree.h:5662
Definition parse-tree.h:5726
Definition parse-tree.h:5656
Definition parse-tree.h:5532
Definition parse-tree.h:5505
Definition parse-tree.h:5633
Definition parse-tree.h:5618
Definition parse-tree.h:5613
Definition parse-tree.h:5521
Definition parse-tree.h:5543
Definition parse-tree.h:5526
Definition parse-tree.h:5538
Definition parse-tree.h:5570
Definition parse-tree.h:5564
Definition parse-tree.h:5668
Definition parse-tree.h:5732
Definition parse-tree.h:5609
Definition parse-tree.h:5600
Definition parse-tree.h:5510
Definition parse-tree.h:5549
Definition parse-tree.h:5497
Definition parse-tree.h:5593
Definition parse-tree.h:5589
Definition parse-tree.h:5585
Definition parse-tree.h:5515
Definition parse-tree.h:5581
Definition parse-tree.h:5575
Definition parse-tree.h:5559
Definition parse-tree.h:897
Definition parse-tree.h:1406
Definition parse-tree.h:498
Definition parse-tree.h:3271
Definition parse-tree.h:3260
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:3493
Definition parse-tree.h:1898
Definition parse-tree.h:1332
Definition parse-tree.h:3498
Definition parse-tree.h:3503
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:3443
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:3437
Definition parse-tree.h:5802
Definition parse-tree.h:5796
Definition parse-tree.h:3298
Definition parse-tree.h:3295
Definition parse-tree.h:3278
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:3406
Definition parse-tree.h:3382
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:3252
Definition parse-tree.h:3239
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:3151
Definition parse-tree.h:2345
Definition parse-tree.h:2207
Definition parse-tree.h:1382
Definition parse-tree.h:3349
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:3283
Definition parse-tree.h:3140
Definition parse-tree.h:3315
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:3207
Definition parse-tree.h:3174
Definition parse-tree.h:3180
Definition parse-tree.h:3172
Definition parse-tree.h:3197
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:3459
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:4324
Definition parse-tree.h:4328
Definition parse-tree.h:4343
Definition parse-tree.h:4350
Definition parse-tree.h:4358
Definition parse-tree.h:4373
Definition parse-tree.h:5320
Definition parse-tree.h:4380
Definition parse-tree.h:5178
Definition parse-tree.h:5167
Definition parse-tree.h:4389
Definition parse-tree.h:5109
Definition parse-tree.h:5184
Definition parse-tree.h:4412
Definition parse-tree.h:5119
Definition parse-tree.h:5078
Definition parse-tree.h:5062
Definition parse-tree.h:4427
Definition parse-tree.h:3628
Definition parse-tree.h:4435
Definition parse-tree.h:5247
Definition parse-tree.h:5264
Definition parse-tree.h:5239
Definition parse-tree.h:4452
Definition parse-tree.h:4470
Definition parse-tree.h:4529
Definition parse-tree.h:4527
Definition parse-tree.h:4551
Definition parse-tree.h:4559
Definition parse-tree.h:4569
Definition parse-tree.h:4579
Definition parse-tree.h:4587
Definition parse-tree.h:3529
Definition parse-tree.h:5085
Definition parse-tree.h:4542
Definition parse-tree.h:4509
Definition parse-tree.h:4602
Definition parse-tree.h:5114
Definition parse-tree.h:5189
Definition parse-tree.h:4613
Definition parse-tree.h:5152
Definition parse-tree.h:4621
Definition parse-tree.h:4634
Definition parse-tree.h:4645
Definition parse-tree.h:4655
Definition parse-tree.h:4663
Definition parse-tree.h:5273
Definition parse-tree.h:4668
Definition parse-tree.h:4676
Definition parse-tree.h:4692
Definition parse-tree.h:4715
Definition parse-tree.h:4681
Definition parse-tree.h:4705
Definition parse-tree.h:4722
Definition parse-tree.h:3640
Definition parse-tree.h:4482
Definition parse-tree.h:4500
Definition parse-tree.h:4491
Definition parse-tree.h:4731
Definition parse-tree.h:4746
Definition parse-tree.h:4757
Definition parse-tree.h:4782
Definition parse-tree.h:4794
Definition parse-tree.h:4803
Definition parse-tree.h:5132
Definition parse-tree.h:5146
Definition parse-tree.h:4827
Definition parse-tree.h:4839
Definition parse-tree.h:4851
Definition parse-tree.h:3574
Definition parse-tree.h:3565
Definition parse-tree.h:3562
Definition parse-tree.h:4862
Definition parse-tree.h:4875
Definition parse-tree.h:4887
Definition parse-tree.h:4898
Definition parse-tree.h:3618
Definition parse-tree.h:4908
Definition parse-tree.h:5280
Definition parse-tree.h:4917
Definition parse-tree.h:4929
Definition parse-tree.h:5198
Definition parse-tree.h:4940
Definition parse-tree.h:4947
Definition parse-tree.h:3578
Definition parse-tree.h:3600
Definition parse-tree.h:3587
Definition parse-tree.h:4956
Definition parse-tree.h:4967
Definition parse-tree.h:5286
Definition parse-tree.h:4976
Definition parse-tree.h:4991
Definition parse-tree.h:5001
Definition parse-tree.h:3554
Definition parse-tree.h:3547
Definition parse-tree.h:5010
Definition parse-tree.h:5035
Definition parse-tree.h:5057
Definition parse-tree.h:5156
Definition parse-tree.h:5046
Definition parse-tree.h:3064
Definition parse-tree.h:5708
Definition parse-tree.h:5715
Definition parse-tree.h:5644
Definition parse-tree.h:5737
Definition parse-tree.h:5776
Definition parse-tree.h:5765
Definition parse-tree.h:5756
Definition parse-tree.h:5638
Definition parse-tree.h:5650
Definition parse-tree.h:5346
Definition parse-tree.h:5351
Definition parse-tree.h:5388
Definition parse-tree.h:5472
Definition parse-tree.h:5336
Definition parse-tree.h:5399
Definition parse-tree.h:5413
Definition parse-tree.h:5467
Definition parse-tree.h:5429
Definition parse-tree.h:5437
Definition parse-tree.h:5490
Definition parse-tree.h:5458
Definition parse-tree.h:5204
Definition parse-tree.h:5448
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:3222
Definition parse-tree.h:3190
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:3341
Definition parse-tree.h:400
Definition parse-tree.h:453
Definition parse-tree.h:1957
Definition parse-tree.h:361
Definition parse-tree.h:3359
Definition parse-tree.h:2524
Definition parse-tree.h:1877
Definition parse-tree.h:1205
Definition parse-tree.h:3480
Definition parse-tree.h:3452
Definition parse-tree.h:3475
Definition parse-tree.h:2995
Definition parse-tree.h:3006
Definition parse-tree.h:3159
Definition parse-tree.h:3325
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:3468
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:3693
Definition parse-tree.h:3652
Definition parse-tree.h:3647
Definition parse-tree.h:3857
Definition parse-tree.h:3866
Definition parse-tree.h:4011
Definition parse-tree.h:4043
Definition parse-tree.h:4065
Definition parse-tree.h:4087
Definition parse-tree.h:4113
Definition parse-tree.h:4134
Definition parse-tree.h:4121
Definition parse-tree.h:4205
Definition parse-tree.h:4246
Definition parse-tree.h:4256
Definition parse-tree.h:3740
Definition parse-tree.h:3723
Definition parse-tree.h:3764
Definition parse-tree.h:3730
Definition parse-tree.h:3791
Definition parse-tree.h:3803
Definition parse-tree.h:3816
Definition parse-tree.h:3825