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