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