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