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