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