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