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