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