Warning: This file is not a C or C++ file. It does not have highlighting.

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/Fortran.h"
26#include "flang/Common/idioms.h"
27#include "flang/Common/indirection.h"
28#include "llvm/Frontend/OpenACC/ACC.h.inc"
29#include "llvm/Frontend/OpenMP/OMPConstants.h"
30#include <cinttypes>
31#include <list>
32#include <memory>
33#include <optional>
34#include <string>
35#include <tuple>
36#include <type_traits>
37#include <utility>
38#include <variant>
39
40// Parse tree node class types do not have default constructors. They
41// explicitly declare "T() {} = delete;" to make this clear. This restriction
42// prevents the introduction of what would be a viral requirement to include
43// std::monostate among most std::variant<> discriminated union members.
44
45// Parse tree node class types do not have copy constructors or copy assignment
46// operators. They are explicitly declared "= delete;" to make this clear,
47// although a C++ compiler wouldn't default them anyway due to the presence
48// of explicitly defaulted move constructors and move assignments.
49
50CLASS_TRAIT(EmptyTrait)
51CLASS_TRAIT(WrapperTrait)
52CLASS_TRAIT(UnionTrait)
53CLASS_TRAIT(TupleTrait)
54CLASS_TRAIT(ConstraintTrait)
55
56// Some parse tree nodes have fields in them to cache the results of a
57// successful semantic analysis later. Their types are forward declared
58// here.
59namespace Fortran::semantics {
60class Symbol;
61class DeclTypeSpec;
62class DerivedTypeSpec;
63} // namespace Fortran::semantics
64
65// Expressions in the parse tree have owning pointers that can be set to
66// type-checked generic expression representations by semantic analysis.
67namespace Fortran::evaluate {
68struct GenericExprWrapper; // forward definition, wraps Expr<SomeType>
69struct GenericAssignmentWrapper; // forward definition, represent assignment
70class ProcedureRef; // forward definition, represents a CALL or function ref
71} // namespace Fortran::evaluate
72
73// Most non-template classes in this file use these default definitions
74// for their move constructor and move assignment operator=, and disable
75// their copy constructor and copy assignment operator=.
76#define COPY_AND_ASSIGN_BOILERPLATE(classname) \
77 classname(classname &&) = default; \
78 classname &operator=(classname &&) = default; \
79 classname(const classname &) = delete; \
80 classname &operator=(const classname &) = delete
81
82// Almost all classes in this file have no default constructor.
83#define BOILERPLATE(classname) \
84 COPY_AND_ASSIGN_BOILERPLATE(classname); \
85 classname() = delete
86
87// Empty classes are often used below as alternatives in std::variant<>
88// discriminated unions.
89#define EMPTY_CLASS(classname) \
90 struct classname { \
91 classname() {} \
92 classname(const classname &) {} \
93 classname(classname &&) {} \
94 classname &operator=(const classname &) { return *this; }; \
95 classname &operator=(classname &&) { return *this; }; \
96 using EmptyTrait = std::true_type; \
97 }
98
99// Many classes below simply wrap a std::variant<> discriminated union,
100// which is conventionally named "u".
101#define UNION_CLASS_BOILERPLATE(classname) \
102 template <typename A, typename = common::NoLvalue<A>> \
103 classname(A &&x) : u(std::move(x)) {} \
104 using UnionTrait = std::true_type; \
105 BOILERPLATE(classname)
106
107// Many other classes below simply wrap a std::tuple<> structure, which
108// is conventionally named "t".
109#define TUPLE_CLASS_BOILERPLATE(classname) \
110 template <typename... Ts, typename = common::NoLvalue<Ts...>> \
111 classname(Ts &&...args) : t(std::move(args)...) {} \
112 using TupleTrait = std::true_type; \
113 BOILERPLATE(classname)
114
115// Many other classes below simply wrap a single data member, which is
116// conventionally named "v".
117#define WRAPPER_CLASS_BOILERPLATE(classname, type) \
118 BOILERPLATE(classname); \
119 classname(type &&x) : v(std::move(x)) {} \
120 using WrapperTrait = std::true_type; \
121 type v
122
123#define WRAPPER_CLASS(classname, type) \
124 struct classname { \
125 WRAPPER_CLASS_BOILERPLATE(classname, type); \
126 }
127
128namespace Fortran::parser {
129
130// These are the unavoidable recursively-defined productions of Fortran.
131// Some references to the representations of their parses require
132// indirection. The Indirect<> pointer wrapper class is used to
133// enforce ownership semantics and non-nullability.
134struct SpecificationPart; // R504
135struct ExecutableConstruct; // R514
136struct ActionStmt; // R515
137struct AcImpliedDo; // R774
138struct DataImpliedDo; // R840
139struct Designator; // R901
140struct Variable; // R902
141struct Expr; // R1001
142struct WhereConstruct; // R1042
143struct ForallConstruct; // R1050
144struct InputImpliedDo; // R1218
145struct OutputImpliedDo; // R1218
146struct FunctionReference; // R1520
147struct FunctionSubprogram; // R1529
148struct SubroutineSubprogram; // R1534
149
150// These additional forward references are declared so that the order of
151// class definitions in this header file can remain reasonably consistent
152// with order of the the requirement productions in the grammar.
153struct DerivedTypeDef; // R726
154struct EnumDef; // R759
155struct TypeDeclarationStmt; // R801
156struct AccessStmt; // R827
157struct AllocatableStmt; // R829
158struct AsynchronousStmt; // R831
159struct BindStmt; // R832
160struct CodimensionStmt; // R834
161struct ContiguousStmt; // R836
162struct DataStmt; // R837
163struct DataStmtValue; // R843
164struct DimensionStmt; // R848
165struct IntentStmt; // R849
166struct OptionalStmt; // R850
167struct ParameterStmt; // R851
168struct OldParameterStmt;
169struct PointerStmt; // R853
170struct ProtectedStmt; // R855
171struct SaveStmt; // R856
172struct TargetStmt; // R859
173struct ValueStmt; // R861
174struct VolatileStmt; // R862
175struct ImplicitStmt; // R863
176struct ImportStmt; // R867
177struct NamelistStmt; // R868
178struct EquivalenceStmt; // R870
179struct CommonStmt; // R873
180struct Substring; // R908
181struct CharLiteralConstantSubstring;
182struct SubstringInquiry;
183struct DataRef; // R911
184struct StructureComponent; // R913
185struct CoindexedNamedObject; // R914
186struct ArrayElement; // R917
187struct AllocateStmt; // R927
188struct NullifyStmt; // R939
189struct DeallocateStmt; // R941
190struct AssignmentStmt; // R1032
191struct PointerAssignmentStmt; // R1033
192struct WhereStmt; // R1041, R1045, R1046
193struct ForallStmt; // R1055
194struct AssociateConstruct; // R1102
195struct BlockConstruct; // R1107
196struct ChangeTeamConstruct; // R1111
197struct CriticalConstruct; // R1116
198struct DoConstruct; // R1119
199struct LabelDoStmt; // R1121
200struct ConcurrentHeader; // R1125
201struct EndDoStmt; // R1132
202struct CycleStmt; // R1133
203struct IfConstruct; // R1134
204struct IfStmt; // R1139
205struct CaseConstruct; // R1140
206struct SelectRankConstruct; // R1148
207struct SelectTypeConstruct; // R1152
208struct ExitStmt; // R1156
209struct GotoStmt; // R1157
210struct ComputedGotoStmt; // R1158
211struct StopStmt; // R1160, R1161
212struct NotifyWaitStmt; // F2023: R1166
213struct SyncAllStmt; // R1164
214struct SyncImagesStmt; // R1166
215struct SyncMemoryStmt; // R1168
216struct SyncTeamStmt; // R1169
217struct EventPostStmt; // R1170, R1171
218struct EventWaitSpec; // F2023: R1177
219struct EventWaitStmt; // R1172, R1173, R1174
220struct FormTeamStmt; // R1175, R1176, R1177
221struct LockStmt; // R1178
222struct UnlockStmt; // R1180
223struct OpenStmt; // R1204
224struct CloseStmt; // R1208
225struct ReadStmt; // R1210
226struct WriteStmt; // R1211
227struct PrintStmt; // R1212
228struct WaitStmt; // R1222
229struct BackspaceStmt; // R1224
230struct EndfileStmt; // R1225
231struct RewindStmt; // R1226
232struct FlushStmt; // R1228
233struct InquireStmt; // R1230
234struct FormatStmt; // R1301
235struct MainProgram; // R1401
236struct Module; // R1404
237struct UseStmt; // R1409
238struct Submodule; // R1416
239struct BlockData; // R1420
240struct InterfaceBlock; // R1501
241struct GenericSpec; // R1508
242struct GenericStmt; // R1510
243struct ExternalStmt; // R1511
244struct ProcedureDeclarationStmt; // R1512
245struct IntrinsicStmt; // R1519
246struct Call; // R1520 & R1521
247struct CallStmt; // R1521
248struct ProcedureDesignator; // R1522
249struct ActualArg; // R1524
250struct SeparateModuleSubprogram; // R1538
251struct EntryStmt; // R1541
252struct ReturnStmt; // R1542
253struct StmtFunctionStmt; // R1544
254
255// Directives, extensions, and deprecated statements
256struct CompilerDirective;
257struct BasedPointerStmt;
258struct CUDAAttributesStmt;
259struct StructureDef;
260struct ArithmeticIfStmt;
261struct AssignStmt;
262struct AssignedGotoStmt;
263struct PauseStmt;
264struct OpenACCConstruct;
265struct AccEndCombinedDirective;
266struct OpenACCDeclarativeConstruct;
267struct OpenACCRoutineConstruct;
268struct OpenMPConstruct;
269struct OpenMPDeclarativeConstruct;
270struct OmpEndLoopDirective;
271struct CUFKernelDoConstruct;
272
273// Cooked character stream locations
274using Location = const char *;
275
276// A parse tree node with provenance only
277struct Verbatim {
278 // Allow a no-arg constructor for Verbatim so parsers can return `RESULT{}`.
279 constexpr Verbatim() {}
280 COPY_AND_ASSIGN_BOILERPLATE(Verbatim);
281 using EmptyTrait = std::true_type;
282 CharBlock source;
283};
284
285// Implicit definitions of the Standard
286
287// R403 scalar-xyz -> xyz
288// These template class wrappers correspond to the Standard's modifiers
289// scalar-xyz, constant-xzy, int-xzy, default-char-xyz, & logical-xyz.
290template <typename A> struct Scalar {
291 using ConstraintTrait = std::true_type;
292 Scalar(Scalar &&that) = default;
293 Scalar(A &&that) : thing(std::move(that)) {}
294 Scalar &operator=(Scalar &&) = default;
295 A thing;
296};
297
298template <typename A> struct Constant {
299 using ConstraintTrait = std::true_type;
300 Constant(Constant &&that) = default;
301 Constant(A &&that) : thing(std::move(that)) {}
302 Constant &operator=(Constant &&) = default;
303 A thing;
304};
305
306template <typename A> struct Integer {
307 using ConstraintTrait = std::true_type;
308 Integer(Integer &&that) = default;
309 Integer(A &&that) : thing(std::move(that)) {}
310 Integer &operator=(Integer &&) = default;
311 A thing;
312};
313
314template <typename A> struct Logical {
315 using ConstraintTrait = std::true_type;
316 Logical(Logical &&that) = default;
317 Logical(A &&that) : thing(std::move(that)) {}
318 Logical &operator=(Logical &&) = default;
319 A thing;
320};
321
322template <typename A> struct DefaultChar {
323 using ConstraintTrait = std::true_type;
324 DefaultChar(DefaultChar &&that) = default;
325 DefaultChar(A &&that) : thing(std::move(that)) {}
326 DefaultChar &operator=(DefaultChar &&) = default;
327 A thing;
328};
329
330using LogicalExpr = Logical<common::Indirection<Expr>>; // R1024
331using DefaultCharExpr = DefaultChar<common::Indirection<Expr>>; // R1025
332using IntExpr = Integer<common::Indirection<Expr>>; // R1026
333using ConstantExpr = Constant<common::Indirection<Expr>>; // R1029
334using IntConstantExpr = Integer<ConstantExpr>; // R1031
335using ScalarLogicalExpr = Scalar<LogicalExpr>;
336using ScalarIntExpr = Scalar<IntExpr>;
337using ScalarIntConstantExpr = Scalar<IntConstantExpr>;
338using ScalarDefaultCharExpr = Scalar<DefaultCharExpr>;
339// R1030 default-char-constant-expr is used in the Standard only as part of
340// scalar-default-char-constant-expr.
341using ScalarDefaultCharConstantExpr = Scalar<DefaultChar<ConstantExpr>>;
342
343// R611 label -> digit [digit]...
344using Label = common::Label; // validated later, must be in [1..99999]
345
346// A wrapper for xzy-stmt productions that are statements, so that
347// source provenances and labels have a uniform representation.
348template <typename A> struct UnlabeledStatement {
349 explicit UnlabeledStatement(A &&s) : statement(std::move(s)) {}
350 CharBlock source;
351 A statement;
352};
353template <typename A> struct Statement : public UnlabeledStatement<A> {
354 Statement(std::optional<long> &&lab, A &&s)
355 : UnlabeledStatement<A>{std::move(s)}, label(std::move(lab)) {}
356 std::optional<Label> label;
357};
358
359// Error recovery marker
360EMPTY_CLASS(ErrorRecovery);
361
362// R513 other-specification-stmt ->
363// access-stmt | allocatable-stmt | asynchronous-stmt | bind-stmt |
364// codimension-stmt | contiguous-stmt | dimension-stmt | external-stmt |
365// intent-stmt | intrinsic-stmt | namelist-stmt | optional-stmt |
366// pointer-stmt | protected-stmt | save-stmt | target-stmt |
367// volatile-stmt | value-stmt | common-stmt | equivalence-stmt
368// Extension: (Cray) based POINTER statement
369// Extension: CUDA data attribute statement
370struct OtherSpecificationStmt {
371 UNION_CLASS_BOILERPLATE(OtherSpecificationStmt);
372 std::variant<common::Indirection<AccessStmt>,
373 common::Indirection<AllocatableStmt>,
374 common::Indirection<AsynchronousStmt>, common::Indirection<BindStmt>,
375 common::Indirection<CodimensionStmt>, common::Indirection<ContiguousStmt>,
376 common::Indirection<DimensionStmt>, common::Indirection<ExternalStmt>,
377 common::Indirection<IntentStmt>, common::Indirection<IntrinsicStmt>,
378 common::Indirection<NamelistStmt>, common::Indirection<OptionalStmt>,
379 common::Indirection<PointerStmt>, common::Indirection<ProtectedStmt>,
380 common::Indirection<SaveStmt>, common::Indirection<TargetStmt>,
381 common::Indirection<ValueStmt>, common::Indirection<VolatileStmt>,
382 common::Indirection<CommonStmt>, common::Indirection<EquivalenceStmt>,
383 common::Indirection<BasedPointerStmt>,
384 common::Indirection<CUDAAttributesStmt>>
385 u;
386};
387
388// R508 specification-construct ->
389// derived-type-def | enum-def | generic-stmt | interface-block |
390// parameter-stmt | procedure-declaration-stmt |
391// other-specification-stmt | type-declaration-stmt
392struct SpecificationConstruct {
393 UNION_CLASS_BOILERPLATE(SpecificationConstruct);
394 std::variant<common::Indirection<DerivedTypeDef>,
395 common::Indirection<EnumDef>, Statement<common::Indirection<GenericStmt>>,
396 common::Indirection<InterfaceBlock>,
397 Statement<common::Indirection<ParameterStmt>>,
398 Statement<common::Indirection<OldParameterStmt>>,
399 Statement<common::Indirection<ProcedureDeclarationStmt>>,
400 Statement<OtherSpecificationStmt>,
401 Statement<common::Indirection<TypeDeclarationStmt>>,
402 common::Indirection<StructureDef>,
403 common::Indirection<OpenACCDeclarativeConstruct>,
404 common::Indirection<OpenMPDeclarativeConstruct>,
405 common::Indirection<CompilerDirective>>
406 u;
407};
408
409// R506 implicit-part-stmt ->
410// implicit-stmt | parameter-stmt | format-stmt | entry-stmt
411struct ImplicitPartStmt {
412 UNION_CLASS_BOILERPLATE(ImplicitPartStmt);
413 std::variant<Statement<common::Indirection<ImplicitStmt>>,
414 Statement<common::Indirection<ParameterStmt>>,
415 Statement<common::Indirection<OldParameterStmt>>,
416 Statement<common::Indirection<FormatStmt>>,
417 Statement<common::Indirection<EntryStmt>>,
418 common::Indirection<CompilerDirective>,
419 common::Indirection<OpenACCDeclarativeConstruct>>
420 u;
421};
422
423// R505 implicit-part -> [implicit-part-stmt]... implicit-stmt
424WRAPPER_CLASS(ImplicitPart, std::list<ImplicitPartStmt>);
425
426// R507 declaration-construct ->
427// specification-construct | data-stmt | format-stmt |
428// entry-stmt | stmt-function-stmt
429struct DeclarationConstruct {
430 UNION_CLASS_BOILERPLATE(DeclarationConstruct);
431 std::variant<SpecificationConstruct, Statement<common::Indirection<DataStmt>>,
432 Statement<common::Indirection<FormatStmt>>,
433 Statement<common::Indirection<EntryStmt>>,
434 Statement<common::Indirection<StmtFunctionStmt>>, ErrorRecovery>
435 u;
436};
437
438// R504 specification-part -> [use-stmt]... [import-stmt]... [implicit-part]
439// [declaration-construct]...
440// PARAMETER, FORMAT, and ENTRY statements that appear before any other
441// kind of declaration-construct will be parsed into the implicit-part,
442// even if there are no IMPLICIT statements.
443struct SpecificationPart {
444 TUPLE_CLASS_BOILERPLATE(SpecificationPart);
445 std::tuple<std::list<OpenACCDeclarativeConstruct>,
446 std::list<OpenMPDeclarativeConstruct>,
447 std::list<common::Indirection<CompilerDirective>>,
448 std::list<Statement<common::Indirection<UseStmt>>>,
449 std::list<Statement<common::Indirection<ImportStmt>>>, ImplicitPart,
450 std::list<DeclarationConstruct>>
451 t;
452};
453
454// R512 internal-subprogram -> function-subprogram | subroutine-subprogram
455struct InternalSubprogram {
456 UNION_CLASS_BOILERPLATE(InternalSubprogram);
457 std::variant<common::Indirection<FunctionSubprogram>,
458 common::Indirection<SubroutineSubprogram>>
459 u;
460};
461
462// R1543 contains-stmt -> CONTAINS
463EMPTY_CLASS(ContainsStmt);
464
465// R511 internal-subprogram-part -> contains-stmt [internal-subprogram]...
466struct InternalSubprogramPart {
467 TUPLE_CLASS_BOILERPLATE(InternalSubprogramPart);
468 std::tuple<Statement<ContainsStmt>, std::list<InternalSubprogram>> t;
469};
470
471// R1159 continue-stmt -> CONTINUE
472EMPTY_CLASS(ContinueStmt);
473
474// R1163 fail-image-stmt -> FAIL IMAGE
475EMPTY_CLASS(FailImageStmt);
476
477// R515 action-stmt ->
478// allocate-stmt | assignment-stmt | backspace-stmt | call-stmt |
479// close-stmt | continue-stmt | cycle-stmt | deallocate-stmt |
480// endfile-stmt | error-stop-stmt | event-post-stmt | event-wait-stmt |
481// exit-stmt | fail-image-stmt | flush-stmt | form-team-stmt |
482// goto-stmt | if-stmt | inquire-stmt | lock-stmt | notify-wait-stmt |
483// nullify-stmt | open-stmt | pointer-assignment-stmt | print-stmt |
484// read-stmt | return-stmt | rewind-stmt | stop-stmt | sync-all-stmt |
485// sync-images-stmt | sync-memory-stmt | sync-team-stmt | unlock-stmt |
486// wait-stmt | where-stmt | write-stmt | computed-goto-stmt | forall-stmt
487struct ActionStmt {
488 UNION_CLASS_BOILERPLATE(ActionStmt);
489 std::variant<common::Indirection<AllocateStmt>,
490 common::Indirection<AssignmentStmt>, common::Indirection<BackspaceStmt>,
491 common::Indirection<CallStmt>, common::Indirection<CloseStmt>,
492 ContinueStmt, common::Indirection<CycleStmt>,
493 common::Indirection<DeallocateStmt>, common::Indirection<EndfileStmt>,
494 common::Indirection<EventPostStmt>, common::Indirection<EventWaitStmt>,
495 common::Indirection<ExitStmt>, FailImageStmt,
496 common::Indirection<FlushStmt>, common::Indirection<FormTeamStmt>,
497 common::Indirection<GotoStmt>, common::Indirection<IfStmt>,
498 common::Indirection<InquireStmt>, common::Indirection<LockStmt>,
499 common::Indirection<NotifyWaitStmt>, common::Indirection<NullifyStmt>,
500 common::Indirection<OpenStmt>, common::Indirection<PointerAssignmentStmt>,
501 common::Indirection<PrintStmt>, common::Indirection<ReadStmt>,
502 common::Indirection<ReturnStmt>, common::Indirection<RewindStmt>,
503 common::Indirection<StopStmt>, common::Indirection<SyncAllStmt>,
504 common::Indirection<SyncImagesStmt>, common::Indirection<SyncMemoryStmt>,
505 common::Indirection<SyncTeamStmt>, common::Indirection<UnlockStmt>,
506 common::Indirection<WaitStmt>, common::Indirection<WhereStmt>,
507 common::Indirection<WriteStmt>, common::Indirection<ComputedGotoStmt>,
508 common::Indirection<ForallStmt>, common::Indirection<ArithmeticIfStmt>,
509 common::Indirection<AssignStmt>, common::Indirection<AssignedGotoStmt>,
510 common::Indirection<PauseStmt>>
511 u;
512};
513
514// R514 executable-construct ->
515// action-stmt | associate-construct | block-construct |
516// case-construct | change-team-construct | critical-construct |
517// do-construct | if-construct | select-rank-construct |
518// select-type-construct | where-construct | forall-construct |
519// (CUDA) CUF-kernel-do-construct
520struct ExecutableConstruct {
521 UNION_CLASS_BOILERPLATE(ExecutableConstruct);
522 std::variant<Statement<ActionStmt>, common::Indirection<AssociateConstruct>,
523 common::Indirection<BlockConstruct>, common::Indirection<CaseConstruct>,
524 common::Indirection<ChangeTeamConstruct>,
525 common::Indirection<CriticalConstruct>,
526 Statement<common::Indirection<LabelDoStmt>>,
527 Statement<common::Indirection<EndDoStmt>>,
528 common::Indirection<DoConstruct>, common::Indirection<IfConstruct>,
529 common::Indirection<SelectRankConstruct>,
530 common::Indirection<SelectTypeConstruct>,
531 common::Indirection<WhereConstruct>, common::Indirection<ForallConstruct>,
532 common::Indirection<CompilerDirective>,
533 common::Indirection<OpenACCConstruct>,
534 common::Indirection<AccEndCombinedDirective>,
535 common::Indirection<OpenMPConstruct>,
536 common::Indirection<OmpEndLoopDirective>,
537 common::Indirection<CUFKernelDoConstruct>>
538 u;
539};
540
541// R510 execution-part-construct ->
542// executable-construct | format-stmt | entry-stmt | data-stmt
543// Extension (PGI/Intel): also accept NAMELIST in execution part
544struct ExecutionPartConstruct {
545 UNION_CLASS_BOILERPLATE(ExecutionPartConstruct);
546 std::variant<ExecutableConstruct, Statement<common::Indirection<FormatStmt>>,
547 Statement<common::Indirection<EntryStmt>>,
548 Statement<common::Indirection<DataStmt>>,
549 Statement<common::Indirection<NamelistStmt>>, ErrorRecovery>
550 u;
551};
552
553// R509 execution-part -> executable-construct [execution-part-construct]...
554// R1101 block -> [execution-part-construct]...
555using Block = std::list<ExecutionPartConstruct>;
556WRAPPER_CLASS(ExecutionPart, Block);
557
558// R502 program-unit ->
559// main-program | external-subprogram | module | submodule | block-data
560// R503 external-subprogram -> function-subprogram | subroutine-subprogram
561struct ProgramUnit {
562 UNION_CLASS_BOILERPLATE(ProgramUnit);
563 std::variant<common::Indirection<MainProgram>,
564 common::Indirection<FunctionSubprogram>,
565 common::Indirection<SubroutineSubprogram>, common::Indirection<Module>,
566 common::Indirection<Submodule>, common::Indirection<BlockData>,
567 common::Indirection<CompilerDirective>,
568 common::Indirection<OpenACCRoutineConstruct>>
569 u;
570};
571
572// R501 program -> program-unit [program-unit]...
573// This is the top-level production.
574WRAPPER_CLASS(Program, std::list<ProgramUnit>);
575
576// R603 name -> letter [alphanumeric-character]...
577struct Name {
578 std::string ToString() const { return source.ToString(); }
579 CharBlock source;
580 mutable semantics::Symbol *symbol{nullptr}; // filled in during semantics
581};
582
583// R516 keyword -> name
584WRAPPER_CLASS(Keyword, Name);
585
586// R606 named-constant -> name
587WRAPPER_CLASS(NamedConstant, Name);
588
589// R1003 defined-unary-op -> . letter [letter]... .
590// R1023 defined-binary-op -> . letter [letter]... .
591// R1414 local-defined-operator -> defined-unary-op | defined-binary-op
592// R1415 use-defined-operator -> defined-unary-op | defined-binary-op
593// The Name here is stored with the dots; e.g., .FOO.
594WRAPPER_CLASS(DefinedOpName, Name);
595
596// R608 intrinsic-operator ->
597// ** | * | / | + | - | // | .LT. | .LE. | .EQ. | .NE. | .GE. | .GT. |
598// .NOT. | .AND. | .OR. | .EQV. | .NEQV.
599// R609 defined-operator ->
600// defined-unary-op | defined-binary-op | extended-intrinsic-op
601// R610 extended-intrinsic-op -> intrinsic-operator
602struct DefinedOperator {
603 UNION_CLASS_BOILERPLATE(DefinedOperator);
604 ENUM_CLASS(IntrinsicOperator, Power, Multiply, Divide, Add, Subtract, Concat,
605 LT, LE, EQ, NE, GE, GT, NOT, AND, OR, EQV, NEQV)
606 std::variant<DefinedOpName, IntrinsicOperator> u;
607};
608
609// R804 object-name -> name
610using ObjectName = Name;
611
612// R867 import-stmt ->
613// IMPORT [[::] import-name-list] |
614// IMPORT , ONLY : import-name-list | IMPORT , NONE | IMPORT , ALL
615struct ImportStmt {
616 BOILERPLATE(ImportStmt);
617 ImportStmt(common::ImportKind &&k) : kind{k} {}
618 ImportStmt(std::list<Name> &&n) : names(std::move(n)) {}
619 ImportStmt(common::ImportKind &&, std::list<Name> &&);
620 common::ImportKind kind{common::ImportKind::Default};
621 std::list<Name> names;
622};
623
624// R868 namelist-stmt ->
625// NAMELIST / namelist-group-name / namelist-group-object-list
626// [[,] / namelist-group-name / namelist-group-object-list]...
627// R869 namelist-group-object -> variable-name
628struct NamelistStmt {
629 struct Group {
630 TUPLE_CLASS_BOILERPLATE(Group);
631 std::tuple<Name, std::list<Name>> t;
632 };
633 WRAPPER_CLASS_BOILERPLATE(NamelistStmt, std::list<Group>);
634};
635
636// R701 type-param-value -> scalar-int-expr | * | :
637EMPTY_CLASS(Star);
638
639struct TypeParamValue {
640 UNION_CLASS_BOILERPLATE(TypeParamValue);
641 EMPTY_CLASS(Deferred); // :
642 std::variant<ScalarIntExpr, Star, Deferred> u;
643};
644
645// R706 kind-selector -> ( [KIND =] scalar-int-constant-expr )
646// Legacy extension: kind-selector -> * digit-string
647// N.B. These are not semantically identical in the case of COMPLEX.
648struct KindSelector {
649 UNION_CLASS_BOILERPLATE(KindSelector);
650 WRAPPER_CLASS(StarSize, std::uint64_t);
651 std::variant<ScalarIntConstantExpr, StarSize> u;
652};
653
654// R705 integer-type-spec -> INTEGER [kind-selector]
655WRAPPER_CLASS(IntegerTypeSpec, std::optional<KindSelector>);
656
657// R723 char-length -> ( type-param-value ) | digit-string
658struct CharLength {
659 UNION_CLASS_BOILERPLATE(CharLength);
660 std::variant<TypeParamValue, std::uint64_t> u;
661};
662
663// R722 length-selector -> ( [LEN =] type-param-value ) | * char-length [,]
664struct LengthSelector {
665 UNION_CLASS_BOILERPLATE(LengthSelector);
666 std::variant<TypeParamValue, CharLength> u;
667};
668
669// R721 char-selector ->
670// length-selector |
671// ( LEN = type-param-value , KIND = scalar-int-constant-expr ) |
672// ( type-param-value , [KIND =] scalar-int-constant-expr ) |
673// ( KIND = scalar-int-constant-expr [, LEN = type-param-value] )
674struct CharSelector {
675 UNION_CLASS_BOILERPLATE(CharSelector);
676 struct LengthAndKind {
677 BOILERPLATE(LengthAndKind);
678 LengthAndKind(std::optional<TypeParamValue> &&l, ScalarIntConstantExpr &&k)
679 : length(std::move(l)), kind(std::move(k)) {}
680 std::optional<TypeParamValue> length;
681 ScalarIntConstantExpr kind;
682 };
683 CharSelector(TypeParamValue &&l, ScalarIntConstantExpr &&k)
684 : u{LengthAndKind{std::make_optional(std::move(l)), std::move(k)}} {}
685 CharSelector(ScalarIntConstantExpr &&k, std::optional<TypeParamValue> &&l)
686 : u{LengthAndKind{std::move(l), std::move(k)}} {}
687 std::variant<LengthSelector, LengthAndKind> u;
688};
689
690// R704 intrinsic-type-spec ->
691// integer-type-spec | REAL [kind-selector] | DOUBLE PRECISION |
692// COMPLEX [kind-selector] | CHARACTER [char-selector] |
693// LOGICAL [kind-selector]
694// Extensions: DOUBLE COMPLEX
695struct IntrinsicTypeSpec {
696 UNION_CLASS_BOILERPLATE(IntrinsicTypeSpec);
697 struct Real {
698 BOILERPLATE(Real);
699 Real(std::optional<KindSelector> &&k) : kind{std::move(k)} {}
700 std::optional<KindSelector> kind;
701 };
702 EMPTY_CLASS(DoublePrecision);
703 struct Complex {
704 BOILERPLATE(Complex);
705 Complex(std::optional<KindSelector> &&k) : kind{std::move(k)} {}
706 std::optional<KindSelector> kind;
707 };
708 struct Character {
709 BOILERPLATE(Character);
710 Character(std::optional<CharSelector> &&s) : selector{std::move(s)} {}
711 std::optional<CharSelector> selector;
712 };
713 struct Logical {
714 BOILERPLATE(Logical);
715 Logical(std::optional<KindSelector> &&k) : kind{std::move(k)} {}
716 std::optional<KindSelector> kind;
717 };
718 EMPTY_CLASS(DoubleComplex);
719 std::variant<IntegerTypeSpec, Real, DoublePrecision, Complex, Character,
720 Logical, DoubleComplex>
721 u;
722};
723
724// Extension: Vector type
725WRAPPER_CLASS(UnsignedTypeSpec, std::optional<KindSelector>);
726struct VectorElementType {
727 UNION_CLASS_BOILERPLATE(VectorElementType);
728 std::variant<IntegerTypeSpec, IntrinsicTypeSpec::Real, UnsignedTypeSpec> u;
729};
730WRAPPER_CLASS(IntrinsicVectorTypeSpec, VectorElementType);
731struct VectorTypeSpec {
732 UNION_CLASS_BOILERPLATE(VectorTypeSpec);
733 EMPTY_CLASS(PairVectorTypeSpec);
734 EMPTY_CLASS(QuadVectorTypeSpec);
735 std::variant<IntrinsicVectorTypeSpec, PairVectorTypeSpec, QuadVectorTypeSpec>
736 u;
737};
738
739// R755 type-param-spec -> [keyword =] type-param-value
740struct TypeParamSpec {
741 TUPLE_CLASS_BOILERPLATE(TypeParamSpec);
742 std::tuple<std::optional<Keyword>, TypeParamValue> t;
743};
744
745// R754 derived-type-spec -> type-name [(type-param-spec-list)]
746struct DerivedTypeSpec {
747 TUPLE_CLASS_BOILERPLATE(DerivedTypeSpec);
748 mutable const semantics::DerivedTypeSpec *derivedTypeSpec{nullptr};
749 std::tuple<Name, std::list<TypeParamSpec>> t;
750};
751
752// R702 type-spec -> intrinsic-type-spec | derived-type-spec
753struct TypeSpec {
754 UNION_CLASS_BOILERPLATE(TypeSpec);
755 mutable const semantics::DeclTypeSpec *declTypeSpec{nullptr};
756 std::variant<IntrinsicTypeSpec, DerivedTypeSpec> u;
757};
758
759// R703 declaration-type-spec ->
760// intrinsic-type-spec | TYPE ( intrinsic-type-spec ) |
761// TYPE ( derived-type-spec ) | CLASS ( derived-type-spec ) |
762// CLASS ( * ) | TYPE ( * )
763// Legacy extension: RECORD /struct/
764struct DeclarationTypeSpec {
765 UNION_CLASS_BOILERPLATE(DeclarationTypeSpec);
766 struct Type {
767 BOILERPLATE(Type);
768 Type(DerivedTypeSpec &&dt) : derived(std::move(dt)) {}
769 DerivedTypeSpec derived;
770 };
771 struct Class {
772 BOILERPLATE(Class);
773 Class(DerivedTypeSpec &&dt) : derived(std::move(dt)) {}
774 DerivedTypeSpec derived;
775 };
776 EMPTY_CLASS(ClassStar);
777 EMPTY_CLASS(TypeStar);
778 WRAPPER_CLASS(Record, Name);
779 std::variant<IntrinsicTypeSpec, Type, Class, ClassStar, TypeStar, Record,
780 VectorTypeSpec>
781 u;
782};
783
784// R709 kind-param -> digit-string | scalar-int-constant-name
785struct KindParam {
786 UNION_CLASS_BOILERPLATE(KindParam);
787 std::variant<std::uint64_t, Scalar<Integer<Constant<Name>>>> u;
788};
789
790// R707 signed-int-literal-constant -> [sign] int-literal-constant
791struct SignedIntLiteralConstant {
792 TUPLE_CLASS_BOILERPLATE(SignedIntLiteralConstant);
793 CharBlock source;
794 std::tuple<CharBlock, std::optional<KindParam>> t;
795};
796
797// R708 int-literal-constant -> digit-string [_ kind-param]
798struct IntLiteralConstant {
799 TUPLE_CLASS_BOILERPLATE(IntLiteralConstant);
800 std::tuple<CharBlock, std::optional<KindParam>> t;
801};
802
803// R712 sign -> + | -
804enum class Sign { Positive, Negative };
805
806// R714 real-literal-constant ->
807// significand [exponent-letter exponent] [_ kind-param] |
808// digit-string exponent-letter exponent [_ kind-param]
809// R715 significand -> digit-string . [digit-string] | . digit-string
810// R717 exponent -> signed-digit-string
811struct RealLiteralConstant {
812 BOILERPLATE(RealLiteralConstant);
813 struct Real {
814 COPY_AND_ASSIGN_BOILERPLATE(Real);
815 Real() {}
816 CharBlock source;
817 };
818 RealLiteralConstant(Real &&r, std::optional<KindParam> &&k)
819 : real{std::move(r)}, kind{std::move(k)} {}
820 Real real;
821 std::optional<KindParam> kind;
822};
823
824// R713 signed-real-literal-constant -> [sign] real-literal-constant
825struct SignedRealLiteralConstant {
826 TUPLE_CLASS_BOILERPLATE(SignedRealLiteralConstant);
827 std::tuple<std::optional<Sign>, RealLiteralConstant> t;
828};
829
830// R719 real-part ->
831// signed-int-literal-constant | signed-real-literal-constant |
832// named-constant
833// R720 imag-part ->
834// signed-int-literal-constant | signed-real-literal-constant |
835// named-constant
836struct ComplexPart {
837 UNION_CLASS_BOILERPLATE(ComplexPart);
838 std::variant<SignedIntLiteralConstant, SignedRealLiteralConstant,
839 NamedConstant>
840 u;
841};
842
843// R718 complex-literal-constant -> ( real-part , imag-part )
844struct ComplexLiteralConstant {
845 TUPLE_CLASS_BOILERPLATE(ComplexLiteralConstant);
846 std::tuple<ComplexPart, ComplexPart> t; // real, imaginary
847};
848
849// Extension: signed COMPLEX constant
850struct SignedComplexLiteralConstant {
851 TUPLE_CLASS_BOILERPLATE(SignedComplexLiteralConstant);
852 std::tuple<Sign, ComplexLiteralConstant> t;
853};
854
855// R724 char-literal-constant ->
856// [kind-param _] ' [rep-char]... ' |
857// [kind-param _] " [rep-char]... "
858struct CharLiteralConstant {
859 TUPLE_CLASS_BOILERPLATE(CharLiteralConstant);
860 std::tuple<std::optional<KindParam>, std::string> t;
861 std::string GetString() const { return std::get<std::string>(t); }
862};
863
864// legacy extension
865struct HollerithLiteralConstant {
866 WRAPPER_CLASS_BOILERPLATE(HollerithLiteralConstant, std::string);
867 std::string GetString() const { return v; }
868};
869
870// R725 logical-literal-constant ->
871// .TRUE. [_ kind-param] | .FALSE. [_ kind-param]
872struct LogicalLiteralConstant {
873 TUPLE_CLASS_BOILERPLATE(LogicalLiteralConstant);
874 std::tuple<bool, std::optional<KindParam>> t;
875};
876
877// R764 boz-literal-constant -> binary-constant | octal-constant | hex-constant
878// R765 binary-constant -> B ' digit [digit]... ' | B " digit [digit]... "
879// R766 octal-constant -> O ' digit [digit]... ' | O " digit [digit]... "
880// R767 hex-constant ->
881// Z ' hex-digit [hex-digit]... ' | Z " hex-digit [hex-digit]... "
882// The constant must be large enough to hold any real or integer scalar
883// of any supported kind (F'2018 7.7).
884WRAPPER_CLASS(BOZLiteralConstant, std::string);
885
886// R605 literal-constant ->
887// int-literal-constant | real-literal-constant |
888// complex-literal-constant | logical-literal-constant |
889// char-literal-constant | boz-literal-constant
890struct LiteralConstant {
891 UNION_CLASS_BOILERPLATE(LiteralConstant);
892 std::variant<HollerithLiteralConstant, IntLiteralConstant,
893 RealLiteralConstant, ComplexLiteralConstant, BOZLiteralConstant,
894 CharLiteralConstant, LogicalLiteralConstant>
895 u;
896};
897
898// R807 access-spec -> PUBLIC | PRIVATE
899struct AccessSpec {
900 ENUM_CLASS(Kind, Public, Private)
901 WRAPPER_CLASS_BOILERPLATE(AccessSpec, Kind);
902};
903
904// R728 type-attr-spec ->
905// ABSTRACT | access-spec | BIND(C) | EXTENDS ( parent-type-name )
906EMPTY_CLASS(Abstract);
907struct TypeAttrSpec {
908 UNION_CLASS_BOILERPLATE(TypeAttrSpec);
909 EMPTY_CLASS(BindC);
910 WRAPPER_CLASS(Extends, Name);
911 std::variant<Abstract, AccessSpec, BindC, Extends> u;
912};
913
914// R727 derived-type-stmt ->
915// TYPE [[, type-attr-spec-list] ::] type-name [( type-param-name-list )]
916struct DerivedTypeStmt {
917 TUPLE_CLASS_BOILERPLATE(DerivedTypeStmt);
918 std::tuple<std::list<TypeAttrSpec>, Name, std::list<Name>> t;
919};
920
921// R731 sequence-stmt -> SEQUENCE
922EMPTY_CLASS(SequenceStmt);
923
924// R745 private-components-stmt -> PRIVATE
925// R747 binding-private-stmt -> PRIVATE
926EMPTY_CLASS(PrivateStmt);
927
928// R729 private-or-sequence -> private-components-stmt | sequence-stmt
929struct PrivateOrSequence {
930 UNION_CLASS_BOILERPLATE(PrivateOrSequence);
931 std::variant<PrivateStmt, SequenceStmt> u;
932};
933
934// R733 type-param-decl -> type-param-name [= scalar-int-constant-expr]
935struct TypeParamDecl {
936 TUPLE_CLASS_BOILERPLATE(TypeParamDecl);
937 std::tuple<Name, std::optional<ScalarIntConstantExpr>> t;
938};
939
940// R732 type-param-def-stmt ->
941// integer-type-spec , type-param-attr-spec :: type-param-decl-list
942// R734 type-param-attr-spec -> KIND | LEN
943struct TypeParamDefStmt {
944 TUPLE_CLASS_BOILERPLATE(TypeParamDefStmt);
945 std::tuple<IntegerTypeSpec, common::TypeParamAttr, std::list<TypeParamDecl>>
946 t;
947};
948
949// R1028 specification-expr -> scalar-int-expr
950WRAPPER_CLASS(SpecificationExpr, ScalarIntExpr);
951
952// R816 explicit-shape-spec -> [lower-bound :] upper-bound
953// R817 lower-bound -> specification-expr
954// R818 upper-bound -> specification-expr
955struct ExplicitShapeSpec {
956 TUPLE_CLASS_BOILERPLATE(ExplicitShapeSpec);
957 std::tuple<std::optional<SpecificationExpr>, SpecificationExpr> t;
958};
959
960// R810 deferred-coshape-spec -> :
961// deferred-coshape-spec-list is just a count of the colons (i.e., the rank).
962WRAPPER_CLASS(DeferredCoshapeSpecList, int);
963
964// R811 explicit-coshape-spec ->
965// [[lower-cobound :] upper-cobound ,]... [lower-cobound :] *
966// R812 lower-cobound -> specification-expr
967// R813 upper-cobound -> specification-expr
968struct ExplicitCoshapeSpec {
969 TUPLE_CLASS_BOILERPLATE(ExplicitCoshapeSpec);
970 std::tuple<std::list<ExplicitShapeSpec>, std::optional<SpecificationExpr>> t;
971};
972
973// R809 coarray-spec -> deferred-coshape-spec-list | explicit-coshape-spec
974struct CoarraySpec {
975 UNION_CLASS_BOILERPLATE(CoarraySpec);
976 std::variant<DeferredCoshapeSpecList, ExplicitCoshapeSpec> u;
977};
978
979// R820 deferred-shape-spec -> :
980// deferred-shape-spec-list is just a count of the colons (i.e., the rank).
981WRAPPER_CLASS(DeferredShapeSpecList, int);
982
983// R740 component-array-spec ->
984// explicit-shape-spec-list | deferred-shape-spec-list
985struct ComponentArraySpec {
986 UNION_CLASS_BOILERPLATE(ComponentArraySpec);
987 std::variant<std::list<ExplicitShapeSpec>, DeferredShapeSpecList> u;
988};
989
990// R738 component-attr-spec ->
991// access-spec | ALLOCATABLE |
992// CODIMENSION lbracket coarray-spec rbracket |
993// CONTIGUOUS | DIMENSION ( component-array-spec ) | POINTER |
994// (CUDA) CONSTANT | DEVICE | MANAGED | PINNED | SHARED | TEXTURE | UNIFIED
995EMPTY_CLASS(Allocatable);
996EMPTY_CLASS(Pointer);
997EMPTY_CLASS(Contiguous);
998struct ComponentAttrSpec {
999 UNION_CLASS_BOILERPLATE(ComponentAttrSpec);
1000 std::variant<AccessSpec, Allocatable, CoarraySpec, Contiguous,
1001 ComponentArraySpec, Pointer, common::CUDADataAttr, ErrorRecovery>
1002 u;
1003};
1004
1005// R806 null-init -> function-reference ... which must be NULL()
1006WRAPPER_CLASS(NullInit, common::Indirection<Expr>);
1007
1008// R744 initial-data-target -> designator
1009using InitialDataTarget = common::Indirection<Designator>;
1010
1011// R743 component-initialization ->
1012// = constant-expr | => null-init | => initial-data-target
1013// R805 initialization ->
1014// = constant-expr | => null-init | => initial-data-target
1015// Universal extension: initialization -> / data-stmt-value-list /
1016struct Initialization {
1017 UNION_CLASS_BOILERPLATE(Initialization);
1018 std::variant<ConstantExpr, NullInit, InitialDataTarget,
1019 std::list<common::Indirection<DataStmtValue>>>
1020 u;
1021};
1022
1023// R739 component-decl ->
1024// component-name [( component-array-spec )]
1025// [lbracket coarray-spec rbracket] [* char-length]
1026// [component-initialization]
1027struct ComponentDecl {
1028 TUPLE_CLASS_BOILERPLATE(ComponentDecl);
1029 std::tuple<Name, std::optional<ComponentArraySpec>,
1030 std::optional<CoarraySpec>, std::optional<CharLength>,
1031 std::optional<Initialization>>
1032 t;
1033};
1034
1035// A %FILL component for a DEC STRUCTURE. The name will be replaced
1036// with a distinct compiler-generated name.
1037struct FillDecl {
1038 TUPLE_CLASS_BOILERPLATE(FillDecl);
1039 std::tuple<Name, std::optional<ComponentArraySpec>, std::optional<CharLength>>
1040 t;
1041};
1042
1043struct ComponentOrFill {
1044 UNION_CLASS_BOILERPLATE(ComponentOrFill);
1045 std::variant<ComponentDecl, FillDecl> u;
1046};
1047
1048// R737 data-component-def-stmt ->
1049// declaration-type-spec [[, component-attr-spec-list] ::]
1050// component-decl-list
1051struct DataComponentDefStmt {
1052 TUPLE_CLASS_BOILERPLATE(DataComponentDefStmt);
1053 std::tuple<DeclarationTypeSpec, std::list<ComponentAttrSpec>,
1054 std::list<ComponentOrFill>>
1055 t;
1056};
1057
1058// R742 proc-component-attr-spec ->
1059// access-spec | NOPASS | PASS [(arg-name)] | POINTER
1060EMPTY_CLASS(NoPass);
1061WRAPPER_CLASS(Pass, std::optional<Name>);
1062struct ProcComponentAttrSpec {
1063 UNION_CLASS_BOILERPLATE(ProcComponentAttrSpec);
1064 std::variant<AccessSpec, NoPass, Pass, Pointer> u;
1065};
1066
1067// R1517 proc-pointer-init -> null-init | initial-proc-target
1068// R1518 initial-proc-target -> procedure-name
1069struct ProcPointerInit {
1070 UNION_CLASS_BOILERPLATE(ProcPointerInit);
1071 std::variant<NullInit, Name> u;
1072};
1073
1074// R1513 proc-interface -> interface-name | declaration-type-spec
1075// R1516 interface-name -> name
1076struct ProcInterface {
1077 UNION_CLASS_BOILERPLATE(ProcInterface);
1078 std::variant<Name, DeclarationTypeSpec> u;
1079};
1080
1081// R1515 proc-decl -> procedure-entity-name [=> proc-pointer-init]
1082struct ProcDecl {
1083 TUPLE_CLASS_BOILERPLATE(ProcDecl);
1084 std::tuple<Name, std::optional<ProcPointerInit>> t;
1085};
1086
1087// R741 proc-component-def-stmt ->
1088// PROCEDURE ( [proc-interface] ) , proc-component-attr-spec-list
1089// :: proc-decl-list
1090struct ProcComponentDefStmt {
1091 TUPLE_CLASS_BOILERPLATE(ProcComponentDefStmt);
1092 std::tuple<std::optional<ProcInterface>, std::list<ProcComponentAttrSpec>,
1093 std::list<ProcDecl>>
1094 t;
1095};
1096
1097// R736 component-def-stmt -> data-component-def-stmt | proc-component-def-stmt
1098struct ComponentDefStmt {
1099 UNION_CLASS_BOILERPLATE(ComponentDefStmt);
1100 std::variant<DataComponentDefStmt, ProcComponentDefStmt,
1101 common::Indirection<CompilerDirective>, ErrorRecovery
1102 // , TypeParamDefStmt -- PGI accidental extension, not enabled
1103 >
1104 u;
1105};
1106
1107// R752 bind-attr ->
1108// access-spec | DEFERRED | NON_OVERRIDABLE | NOPASS | PASS [(arg-name)]
1109struct BindAttr {
1110 UNION_CLASS_BOILERPLATE(BindAttr);
1111 EMPTY_CLASS(Deferred);
1112 EMPTY_CLASS(Non_Overridable);
1113 std::variant<AccessSpec, Deferred, Non_Overridable, NoPass, Pass> u;
1114};
1115
1116// R750 type-bound-proc-decl -> binding-name [=> procedure-name]
1117struct TypeBoundProcDecl {
1118 TUPLE_CLASS_BOILERPLATE(TypeBoundProcDecl);
1119 std::tuple<Name, std::optional<Name>> t;
1120};
1121
1122// R749 type-bound-procedure-stmt ->
1123// PROCEDURE [[, bind-attr-list] ::] type-bound-proc-decl-list |
1124// PROCEDURE ( interface-name ) , bind-attr-list :: binding-name-list
1125// The second form, with interface-name, requires DEFERRED in bind-attr-list,
1126// and thus can appear only in an abstract type.
1127struct TypeBoundProcedureStmt {
1128 UNION_CLASS_BOILERPLATE(TypeBoundProcedureStmt);
1129 struct WithoutInterface {
1130 BOILERPLATE(WithoutInterface);
1131 WithoutInterface(
1132 std::list<BindAttr> &&as, std::list<TypeBoundProcDecl> &&ds)
1133 : attributes(std::move(as)), declarations(std::move(ds)) {}
1134 std::list<BindAttr> attributes;
1135 std::list<TypeBoundProcDecl> declarations;
1136 };
1137 struct WithInterface {
1138 BOILERPLATE(WithInterface);
1139 WithInterface(Name &&n, std::list<BindAttr> &&as, std::list<Name> &&bs)
1140 : interfaceName(std::move(n)), attributes(std::move(as)),
1141 bindingNames(std::move(bs)) {}
1142 Name interfaceName;
1143 std::list<BindAttr> attributes;
1144 std::list<Name> bindingNames;
1145 };
1146 std::variant<WithoutInterface, WithInterface> u;
1147};
1148
1149// R751 type-bound-generic-stmt ->
1150// GENERIC [, access-spec] :: generic-spec => binding-name-list
1151struct TypeBoundGenericStmt {
1152 TUPLE_CLASS_BOILERPLATE(TypeBoundGenericStmt);
1153 std::tuple<std::optional<AccessSpec>, common::Indirection<GenericSpec>,
1154 std::list<Name>>
1155 t;
1156};
1157
1158// R753 final-procedure-stmt -> FINAL [::] final-subroutine-name-list
1159WRAPPER_CLASS(FinalProcedureStmt, std::list<Name>);
1160
1161// R748 type-bound-proc-binding ->
1162// type-bound-procedure-stmt | type-bound-generic-stmt |
1163// final-procedure-stmt
1164struct TypeBoundProcBinding {
1165 UNION_CLASS_BOILERPLATE(TypeBoundProcBinding);
1166 std::variant<TypeBoundProcedureStmt, TypeBoundGenericStmt, FinalProcedureStmt,
1167 ErrorRecovery>
1168 u;
1169};
1170
1171// R746 type-bound-procedure-part ->
1172// contains-stmt [binding-private-stmt] [type-bound-proc-binding]...
1173struct TypeBoundProcedurePart {
1174 TUPLE_CLASS_BOILERPLATE(TypeBoundProcedurePart);
1175 std::tuple<Statement<ContainsStmt>, std::optional<Statement<PrivateStmt>>,
1176 std::list<Statement<TypeBoundProcBinding>>>
1177 t;
1178};
1179
1180// R730 end-type-stmt -> END TYPE [type-name]
1181WRAPPER_CLASS(EndTypeStmt, std::optional<Name>);
1182
1183// R726 derived-type-def ->
1184// derived-type-stmt [type-param-def-stmt]... [private-or-sequence]...
1185// [component-part] [type-bound-procedure-part] end-type-stmt
1186// R735 component-part -> [component-def-stmt]...
1187struct DerivedTypeDef {
1188 TUPLE_CLASS_BOILERPLATE(DerivedTypeDef);
1189 std::tuple<Statement<DerivedTypeStmt>, std::list<Statement<TypeParamDefStmt>>,
1190 std::list<Statement<PrivateOrSequence>>,
1191 std::list<Statement<ComponentDefStmt>>,
1192 std::optional<TypeBoundProcedurePart>, Statement<EndTypeStmt>>
1193 t;
1194};
1195
1196// R758 component-data-source -> expr | data-target | proc-target
1197// R1037 data-target -> expr
1198// R1040 proc-target -> expr | procedure-name | proc-component-ref
1199WRAPPER_CLASS(ComponentDataSource, common::Indirection<Expr>);
1200
1201// R757 component-spec -> [keyword =] component-data-source
1202struct ComponentSpec {
1203 TUPLE_CLASS_BOILERPLATE(ComponentSpec);
1204 std::tuple<std::optional<Keyword>, ComponentDataSource> t;
1205};
1206
1207// R756 structure-constructor -> derived-type-spec ( [component-spec-list] )
1208struct StructureConstructor {
1209 TUPLE_CLASS_BOILERPLATE(StructureConstructor);
1210 std::tuple<DerivedTypeSpec, std::list<ComponentSpec>> t;
1211};
1212
1213// R760 enum-def-stmt -> ENUM, BIND(C)
1214EMPTY_CLASS(EnumDefStmt);
1215
1216// R762 enumerator -> named-constant [= scalar-int-constant-expr]
1217struct Enumerator {
1218 TUPLE_CLASS_BOILERPLATE(Enumerator);
1219 std::tuple<NamedConstant, std::optional<ScalarIntConstantExpr>> t;
1220};
1221
1222// R761 enumerator-def-stmt -> ENUMERATOR [::] enumerator-list
1223WRAPPER_CLASS(EnumeratorDefStmt, std::list<Enumerator>);
1224
1225// R763 end-enum-stmt -> END ENUM
1226EMPTY_CLASS(EndEnumStmt);
1227
1228// R759 enum-def ->
1229// enum-def-stmt enumerator-def-stmt [enumerator-def-stmt]...
1230// end-enum-stmt
1231struct EnumDef {
1232 TUPLE_CLASS_BOILERPLATE(EnumDef);
1233 std::tuple<Statement<EnumDefStmt>, std::list<Statement<EnumeratorDefStmt>>,
1234 Statement<EndEnumStmt>>
1235 t;
1236};
1237
1238// R773 ac-value -> expr | ac-implied-do
1239struct AcValue {
1240 struct Triplet { // PGI/Intel extension
1241 TUPLE_CLASS_BOILERPLATE(Triplet);
1242 std::tuple<ScalarIntExpr, ScalarIntExpr, std::optional<ScalarIntExpr>> t;
1243 };
1244 UNION_CLASS_BOILERPLATE(AcValue);
1245 std::variant<Triplet, common::Indirection<Expr>,
1246 common::Indirection<AcImpliedDo>>
1247 u;
1248};
1249
1250// R770 ac-spec -> type-spec :: | [type-spec ::] ac-value-list
1251struct AcSpec {
1252 BOILERPLATE(AcSpec);
1253 AcSpec(std::optional<TypeSpec> &&ts, std::list<AcValue> &&xs)
1254 : type(std::move(ts)), values(std::move(xs)) {}
1255 explicit AcSpec(TypeSpec &&ts) : type{std::move(ts)} {}
1256 std::optional<TypeSpec> type;
1257 std::list<AcValue> values;
1258};
1259
1260// R769 array-constructor -> (/ ac-spec /) | lbracket ac-spec rbracket
1261WRAPPER_CLASS(ArrayConstructor, AcSpec);
1262
1263// R1124 do-variable -> scalar-int-variable-name
1264using DoVariable = Scalar<Integer<Name>>;
1265
1266template <typename VAR, typename BOUND> struct LoopBounds {
1267 LoopBounds(LoopBounds &&that) = default;
1268 LoopBounds(
1269 VAR &&name, BOUND &&lower, BOUND &&upper, std::optional<BOUND> &&step)
1270 : name{std::move(name)}, lower{std::move(lower)}, upper{std::move(upper)},
1271 step{std::move(step)} {}
1272 LoopBounds &operator=(LoopBounds &&) = default;
1273 VAR name;
1274 BOUND lower, upper;
1275 std::optional<BOUND> step;
1276};
1277
1278using ScalarName = Scalar<Name>;
1279using ScalarExpr = Scalar<common::Indirection<Expr>>;
1280
1281// R775 ac-implied-do-control ->
1282// [integer-type-spec ::] ac-do-variable = scalar-int-expr ,
1283// scalar-int-expr [, scalar-int-expr]
1284// R776 ac-do-variable -> do-variable
1285struct AcImpliedDoControl {
1286 TUPLE_CLASS_BOILERPLATE(AcImpliedDoControl);
1287 using Bounds = LoopBounds<DoVariable, ScalarIntExpr>;
1288 std::tuple<std::optional<IntegerTypeSpec>, Bounds> t;
1289};
1290
1291// R774 ac-implied-do -> ( ac-value-list , ac-implied-do-control )
1292struct AcImpliedDo {
1293 TUPLE_CLASS_BOILERPLATE(AcImpliedDo);
1294 std::tuple<std::list<AcValue>, AcImpliedDoControl> t;
1295};
1296
1297// R808 language-binding-spec ->
1298// BIND ( C [, NAME = scalar-default-char-constant-expr] )
1299// R1528 proc-language-binding-spec -> language-binding-spec
1300WRAPPER_CLASS(
1301 LanguageBindingSpec, std::optional<ScalarDefaultCharConstantExpr>);
1302
1303// R852 named-constant-def -> named-constant = constant-expr
1304struct NamedConstantDef {
1305 TUPLE_CLASS_BOILERPLATE(NamedConstantDef);
1306 std::tuple<NamedConstant, ConstantExpr> t;
1307};
1308
1309// R851 parameter-stmt -> PARAMETER ( named-constant-def-list )
1310WRAPPER_CLASS(ParameterStmt, std::list<NamedConstantDef>);
1311
1312// R819 assumed-shape-spec -> [lower-bound] :
1313WRAPPER_CLASS(AssumedShapeSpec, std::optional<SpecificationExpr>);
1314
1315// R821 assumed-implied-spec -> [lower-bound :] *
1316WRAPPER_CLASS(AssumedImpliedSpec, std::optional<SpecificationExpr>);
1317
1318// R822 assumed-size-spec -> explicit-shape-spec-list , assumed-implied-spec
1319struct AssumedSizeSpec {
1320 TUPLE_CLASS_BOILERPLATE(AssumedSizeSpec);
1321 std::tuple<std::list<ExplicitShapeSpec>, AssumedImpliedSpec> t;
1322};
1323
1324// R823 implied-shape-or-assumed-size-spec -> assumed-implied-spec
1325// R824 implied-shape-spec -> assumed-implied-spec , assumed-implied-spec-list
1326// I.e., when the assumed-implied-spec-list has a single item, it constitutes an
1327// implied-shape-or-assumed-size-spec; otherwise, an implied-shape-spec.
1328WRAPPER_CLASS(ImpliedShapeSpec, std::list<AssumedImpliedSpec>);
1329
1330// R825 assumed-rank-spec -> ..
1331EMPTY_CLASS(AssumedRankSpec);
1332
1333// R815 array-spec ->
1334// explicit-shape-spec-list | assumed-shape-spec-list |
1335// deferred-shape-spec-list | assumed-size-spec | implied-shape-spec |
1336// implied-shape-or-assumed-size-spec | assumed-rank-spec
1337struct ArraySpec {
1338 UNION_CLASS_BOILERPLATE(ArraySpec);
1339 std::variant<std::list<ExplicitShapeSpec>, std::list<AssumedShapeSpec>,
1340 DeferredShapeSpecList, AssumedSizeSpec, ImpliedShapeSpec, AssumedRankSpec>
1341 u;
1342};
1343
1344// R826 intent-spec -> IN | OUT | INOUT
1345struct IntentSpec {
1346 ENUM_CLASS(Intent, In, Out, InOut)
1347 WRAPPER_CLASS_BOILERPLATE(IntentSpec, Intent);
1348};
1349
1350// R802 attr-spec ->
1351// access-spec | ALLOCATABLE | ASYNCHRONOUS |
1352// CODIMENSION lbracket coarray-spec rbracket | CONTIGUOUS |
1353// DIMENSION ( array-spec ) | EXTERNAL | INTENT ( intent-spec ) |
1354// INTRINSIC | language-binding-spec | OPTIONAL | PARAMETER | POINTER |
1355// PROTECTED | SAVE | TARGET | VALUE | VOLATILE |
1356// (CUDA) CONSTANT | DEVICE | MANAGED | PINNED | SHARED | TEXTURE
1357EMPTY_CLASS(Asynchronous);
1358EMPTY_CLASS(External);
1359EMPTY_CLASS(Intrinsic);
1360EMPTY_CLASS(Optional);
1361EMPTY_CLASS(Parameter);
1362EMPTY_CLASS(Protected);
1363EMPTY_CLASS(Save);
1364EMPTY_CLASS(Target);
1365EMPTY_CLASS(Value);
1366EMPTY_CLASS(Volatile);
1367struct AttrSpec {
1368 UNION_CLASS_BOILERPLATE(AttrSpec);
1369 std::variant<AccessSpec, Allocatable, Asynchronous, CoarraySpec, Contiguous,
1370 ArraySpec, External, IntentSpec, Intrinsic, LanguageBindingSpec, Optional,
1371 Parameter, Pointer, Protected, Save, Target, Value, Volatile,
1372 common::CUDADataAttr>
1373 u;
1374};
1375
1376// R803 entity-decl ->
1377// object-name [( array-spec )] [lbracket coarray-spec rbracket]
1378// [* char-length] [initialization] |
1379// function-name [* char-length]
1380struct EntityDecl {
1381 TUPLE_CLASS_BOILERPLATE(EntityDecl);
1382 std::tuple<ObjectName, std::optional<ArraySpec>, std::optional<CoarraySpec>,
1383 std::optional<CharLength>, std::optional<Initialization>>
1384 t;
1385};
1386
1387// R801 type-declaration-stmt ->
1388// declaration-type-spec [[, attr-spec]... ::] entity-decl-list
1389struct TypeDeclarationStmt {
1390 TUPLE_CLASS_BOILERPLATE(TypeDeclarationStmt);
1391 std::tuple<DeclarationTypeSpec, std::list<AttrSpec>, std::list<EntityDecl>> t;
1392};
1393
1394// R828 access-id -> access-name | generic-spec
1395// "access-name" is ambiguous with "generic-spec", so that's what's parsed
1396WRAPPER_CLASS(AccessId, common::Indirection<GenericSpec>);
1397
1398// R827 access-stmt -> access-spec [[::] access-id-list]
1399struct AccessStmt {
1400 TUPLE_CLASS_BOILERPLATE(AccessStmt);
1401 std::tuple<AccessSpec, std::list<AccessId>> t;
1402};
1403
1404// R830 allocatable-decl ->
1405// object-name [( array-spec )] [lbracket coarray-spec rbracket]
1406// R860 target-decl ->
1407// object-name [( array-spec )] [lbracket coarray-spec rbracket]
1408struct ObjectDecl {
1409 TUPLE_CLASS_BOILERPLATE(ObjectDecl);
1410 std::tuple<ObjectName, std::optional<ArraySpec>, std::optional<CoarraySpec>>
1411 t;
1412};
1413
1414// R829 allocatable-stmt -> ALLOCATABLE [::] allocatable-decl-list
1415WRAPPER_CLASS(AllocatableStmt, std::list<ObjectDecl>);
1416
1417// R831 asynchronous-stmt -> ASYNCHRONOUS [::] object-name-list
1418WRAPPER_CLASS(AsynchronousStmt, std::list<ObjectName>);
1419
1420// R833 bind-entity -> entity-name | / common-block-name /
1421struct BindEntity {
1422 TUPLE_CLASS_BOILERPLATE(BindEntity);
1423 ENUM_CLASS(Kind, Object, Common)
1424 std::tuple<Kind, Name> t;
1425};
1426
1427// R832 bind-stmt -> language-binding-spec [::] bind-entity-list
1428struct BindStmt {
1429 TUPLE_CLASS_BOILERPLATE(BindStmt);
1430 std::tuple<LanguageBindingSpec, std::list<BindEntity>> t;
1431};
1432
1433// R835 codimension-decl -> coarray-name lbracket coarray-spec rbracket
1434struct CodimensionDecl {
1435 TUPLE_CLASS_BOILERPLATE(CodimensionDecl);
1436 std::tuple<Name, CoarraySpec> t;
1437};
1438
1439// R834 codimension-stmt -> CODIMENSION [::] codimension-decl-list
1440WRAPPER_CLASS(CodimensionStmt, std::list<CodimensionDecl>);
1441
1442// R836 contiguous-stmt -> CONTIGUOUS [::] object-name-list
1443WRAPPER_CLASS(ContiguousStmt, std::list<ObjectName>);
1444
1445// R847 constant-subobject -> designator
1446// R846 int-constant-subobject -> constant-subobject
1447using ConstantSubobject = Constant<common::Indirection<Designator>>;
1448
1449// Represents an analyzed expression
1450using TypedExpr = common::ForwardOwningPointer<evaluate::GenericExprWrapper>;
1451
1452// R845 data-stmt-constant ->
1453// scalar-constant | scalar-constant-subobject |
1454// signed-int-literal-constant | signed-real-literal-constant |
1455// null-init | initial-data-target |
1456// structure-constructor
1457// N.B. Parsing ambiguities abound here without recourse to symbols
1458// (see comments on R845's parser).
1459struct DataStmtConstant {
1460 UNION_CLASS_BOILERPLATE(DataStmtConstant);
1461 CharBlock source;
1462 mutable TypedExpr typedExpr;
1463 std::variant<LiteralConstant, SignedIntLiteralConstant,
1464 SignedRealLiteralConstant, SignedComplexLiteralConstant, NullInit,
1465 common::Indirection<Designator>, StructureConstructor>
1466 u;
1467};
1468
1469// R844 data-stmt-repeat -> scalar-int-constant | scalar-int-constant-subobject
1470// R607 int-constant -> constant
1471// R604 constant -> literal-constant | named-constant
1472// (only literal-constant -> int-literal-constant applies)
1473struct DataStmtRepeat {
1474 UNION_CLASS_BOILERPLATE(DataStmtRepeat);
1475 std::variant<IntLiteralConstant, Scalar<Integer<ConstantSubobject>>> u;
1476};
1477
1478// R843 data-stmt-value -> [data-stmt-repeat *] data-stmt-constant
1479struct DataStmtValue {
1480 TUPLE_CLASS_BOILERPLATE(DataStmtValue);
1481 mutable std::int64_t repetitions{1}; // replaced during semantics
1482 std::tuple<std::optional<DataStmtRepeat>, DataStmtConstant> t;
1483};
1484
1485// R841 data-i-do-object ->
1486// array-element | scalar-structure-component | data-implied-do
1487struct DataIDoObject {
1488 UNION_CLASS_BOILERPLATE(DataIDoObject);
1489 std::variant<Scalar<common::Indirection<Designator>>,
1490 common::Indirection<DataImpliedDo>>
1491 u;
1492};
1493
1494// R840 data-implied-do ->
1495// ( data-i-do-object-list , [integer-type-spec ::] data-i-do-variable
1496// = scalar-int-constant-expr , scalar-int-constant-expr
1497// [, scalar-int-constant-expr] )
1498// R842 data-i-do-variable -> do-variable
1499struct DataImpliedDo {
1500 TUPLE_CLASS_BOILERPLATE(DataImpliedDo);
1501 using Bounds = LoopBounds<DoVariable, ScalarIntConstantExpr>;
1502 std::tuple<std::list<DataIDoObject>, std::optional<IntegerTypeSpec>, Bounds>
1503 t;
1504};
1505
1506// R839 data-stmt-object -> variable | data-implied-do
1507struct DataStmtObject {
1508 UNION_CLASS_BOILERPLATE(DataStmtObject);
1509 std::variant<common::Indirection<Variable>, DataImpliedDo> u;
1510};
1511
1512// R838 data-stmt-set -> data-stmt-object-list / data-stmt-value-list /
1513struct DataStmtSet {
1514 TUPLE_CLASS_BOILERPLATE(DataStmtSet);
1515 std::tuple<std::list<DataStmtObject>, std::list<DataStmtValue>> t;
1516};
1517
1518// R837 data-stmt -> DATA data-stmt-set [[,] data-stmt-set]...
1519WRAPPER_CLASS(DataStmt, std::list<DataStmtSet>);
1520
1521// R848 dimension-stmt ->
1522// DIMENSION [::] array-name ( array-spec )
1523// [, array-name ( array-spec )]...
1524struct DimensionStmt {
1525 struct Declaration {
1526 TUPLE_CLASS_BOILERPLATE(Declaration);
1527 std::tuple<Name, ArraySpec> t;
1528 };
1529 WRAPPER_CLASS_BOILERPLATE(DimensionStmt, std::list<Declaration>);
1530};
1531
1532// R849 intent-stmt -> INTENT ( intent-spec ) [::] dummy-arg-name-list
1533struct IntentStmt {
1534 TUPLE_CLASS_BOILERPLATE(IntentStmt);
1535 std::tuple<IntentSpec, std::list<Name>> t;
1536};
1537
1538// R850 optional-stmt -> OPTIONAL [::] dummy-arg-name-list
1539WRAPPER_CLASS(OptionalStmt, std::list<Name>);
1540
1541// R854 pointer-decl ->
1542// object-name [( deferred-shape-spec-list )] | proc-entity-name
1543struct PointerDecl {
1544 TUPLE_CLASS_BOILERPLATE(PointerDecl);
1545 std::tuple<Name, std::optional<DeferredShapeSpecList>> t;
1546};
1547
1548// R853 pointer-stmt -> POINTER [::] pointer-decl-list
1549WRAPPER_CLASS(PointerStmt, std::list<PointerDecl>);
1550
1551// R855 protected-stmt -> PROTECTED [::] entity-name-list
1552WRAPPER_CLASS(ProtectedStmt, std::list<Name>);
1553
1554// R857 saved-entity -> object-name | proc-pointer-name | / common-block-name /
1555// R858 proc-pointer-name -> name
1556struct SavedEntity {
1557 TUPLE_CLASS_BOILERPLATE(SavedEntity);
1558 ENUM_CLASS(Kind, Entity, Common)
1559 std::tuple<Kind, Name> t;
1560};
1561
1562// R856 save-stmt -> SAVE [[::] saved-entity-list]
1563WRAPPER_CLASS(SaveStmt, std::list<SavedEntity>);
1564
1565// R859 target-stmt -> TARGET [::] target-decl-list
1566WRAPPER_CLASS(TargetStmt, std::list<ObjectDecl>);
1567
1568// R861 value-stmt -> VALUE [::] dummy-arg-name-list
1569WRAPPER_CLASS(ValueStmt, std::list<Name>);
1570
1571// R862 volatile-stmt -> VOLATILE [::] object-name-list
1572WRAPPER_CLASS(VolatileStmt, std::list<ObjectName>);
1573
1574// R865 letter-spec -> letter [- letter]
1575struct LetterSpec {
1576 TUPLE_CLASS_BOILERPLATE(LetterSpec);
1577 std::tuple<Location, std::optional<Location>> t;
1578};
1579
1580// R864 implicit-spec -> declaration-type-spec ( letter-spec-list )
1581struct ImplicitSpec {
1582 TUPLE_CLASS_BOILERPLATE(ImplicitSpec);
1583 std::tuple<DeclarationTypeSpec, std::list<LetterSpec>> t;
1584};
1585
1586// R863 implicit-stmt ->
1587// IMPLICIT implicit-spec-list |
1588// IMPLICIT NONE [( [implicit-name-spec-list] )]
1589// R866 implicit-name-spec -> EXTERNAL | TYPE
1590struct ImplicitStmt {
1591 UNION_CLASS_BOILERPLATE(ImplicitStmt);
1592 ENUM_CLASS(ImplicitNoneNameSpec, External, Type) // R866
1593 std::variant<std::list<ImplicitSpec>, std::list<ImplicitNoneNameSpec>> u;
1594};
1595
1596// R874 common-block-object -> variable-name [( array-spec )]
1597struct CommonBlockObject {
1598 TUPLE_CLASS_BOILERPLATE(CommonBlockObject);
1599 std::tuple<Name, std::optional<ArraySpec>> t;
1600};
1601
1602// R873 common-stmt ->
1603// COMMON [/ [common-block-name] /] common-block-object-list
1604// [[,] / [common-block-name] / common-block-object-list]...
1605struct CommonStmt {
1606 struct Block {
1607 TUPLE_CLASS_BOILERPLATE(Block);
1608 std::tuple<std::optional<Name>, std::list<CommonBlockObject>> t;
1609 };
1610 BOILERPLATE(CommonStmt);
1611 CommonStmt(std::optional<Name> &&, std::list<CommonBlockObject> &&,
1612 std::list<Block> &&);
1613 std::list<Block> blocks;
1614};
1615
1616// R872 equivalence-object -> variable-name | array-element | substring
1617WRAPPER_CLASS(EquivalenceObject, common::Indirection<Designator>);
1618
1619// R870 equivalence-stmt -> EQUIVALENCE equivalence-set-list
1620// R871 equivalence-set -> ( equivalence-object , equivalence-object-list )
1621WRAPPER_CLASS(EquivalenceStmt, std::list<std::list<EquivalenceObject>>);
1622
1623// R910 substring-range -> [scalar-int-expr] : [scalar-int-expr]
1624struct SubstringRange {
1625 TUPLE_CLASS_BOILERPLATE(SubstringRange);
1626 std::tuple<std::optional<ScalarIntExpr>, std::optional<ScalarIntExpr>> t;
1627};
1628
1629// R919 subscript -> scalar-int-expr
1630using Subscript = ScalarIntExpr;
1631
1632// R921 subscript-triplet -> [subscript] : [subscript] [: stride]
1633struct SubscriptTriplet {
1634 TUPLE_CLASS_BOILERPLATE(SubscriptTriplet);
1635 std::tuple<std::optional<Subscript>, std::optional<Subscript>,
1636 std::optional<Subscript>>
1637 t;
1638};
1639
1640// R920 section-subscript -> subscript | subscript-triplet | vector-subscript
1641// R923 vector-subscript -> int-expr
1642struct SectionSubscript {
1643 UNION_CLASS_BOILERPLATE(SectionSubscript);
1644 std::variant<IntExpr, SubscriptTriplet> u;
1645};
1646
1647// R925 cosubscript -> scalar-int-expr
1648using Cosubscript = ScalarIntExpr;
1649
1650// R1115 team-value -> scalar-expr
1651WRAPPER_CLASS(TeamValue, Scalar<common::Indirection<Expr>>);
1652
1653// R926 image-selector-spec ->
1654// STAT = stat-variable | TEAM = team-value |
1655// TEAM_NUMBER = scalar-int-expr
1656struct ImageSelectorSpec {
1657 WRAPPER_CLASS(Stat, Scalar<Integer<common::Indirection<Variable>>>);
1658 WRAPPER_CLASS(Team_Number, ScalarIntExpr);
1659 UNION_CLASS_BOILERPLATE(ImageSelectorSpec);
1660 std::variant<Stat, TeamValue, Team_Number> u;
1661};
1662
1663// R924 image-selector ->
1664// lbracket cosubscript-list [, image-selector-spec-list] rbracket
1665struct ImageSelector {
1666 TUPLE_CLASS_BOILERPLATE(ImageSelector);
1667 std::tuple<std::list<Cosubscript>, std::list<ImageSelectorSpec>> t;
1668};
1669
1670// R1001 - R1022 expressions
1671struct Expr {
1672 UNION_CLASS_BOILERPLATE(Expr);
1673
1674 WRAPPER_CLASS(IntrinsicUnary, common::Indirection<Expr>);
1675 struct Parentheses : public IntrinsicUnary {
1676 using IntrinsicUnary::IntrinsicUnary;
1677 };
1678 struct UnaryPlus : public IntrinsicUnary {
1679 using IntrinsicUnary::IntrinsicUnary;
1680 };
1681 struct Negate : public IntrinsicUnary {
1682 using IntrinsicUnary::IntrinsicUnary;
1683 };
1684 struct NOT : public IntrinsicUnary {
1685 using IntrinsicUnary::IntrinsicUnary;
1686 };
1687
1688 WRAPPER_CLASS(PercentLoc, common::Indirection<Variable>); // %LOC(v) extension
1689
1690 struct DefinedUnary {
1691 TUPLE_CLASS_BOILERPLATE(DefinedUnary);
1692 std::tuple<DefinedOpName, common::Indirection<Expr>> t;
1693 };
1694
1695 struct IntrinsicBinary {
1696 TUPLE_CLASS_BOILERPLATE(IntrinsicBinary);
1697 std::tuple<common::Indirection<Expr>, common::Indirection<Expr>> t;
1698 };
1699 struct Power : public IntrinsicBinary {
1700 using IntrinsicBinary::IntrinsicBinary;
1701 };
1702 struct Multiply : public IntrinsicBinary {
1703 using IntrinsicBinary::IntrinsicBinary;
1704 };
1705 struct Divide : public IntrinsicBinary {
1706 using IntrinsicBinary::IntrinsicBinary;
1707 };
1708 struct Add : public IntrinsicBinary {
1709 using IntrinsicBinary::IntrinsicBinary;
1710 };
1711 struct Subtract : public IntrinsicBinary {
1712 using IntrinsicBinary::IntrinsicBinary;
1713 };
1714 struct Concat : public IntrinsicBinary {
1715 using IntrinsicBinary::IntrinsicBinary;
1716 };
1717 struct LT : public IntrinsicBinary {
1718 using IntrinsicBinary::IntrinsicBinary;
1719 };
1720 struct LE : public IntrinsicBinary {
1721 using IntrinsicBinary::IntrinsicBinary;
1722 };
1723 struct EQ : public IntrinsicBinary {
1724 using IntrinsicBinary::IntrinsicBinary;
1725 };
1726 struct NE : public IntrinsicBinary {
1727 using IntrinsicBinary::IntrinsicBinary;
1728 };
1729 struct GE : public IntrinsicBinary {
1730 using IntrinsicBinary::IntrinsicBinary;
1731 };
1732 struct GT : public IntrinsicBinary {
1733 using IntrinsicBinary::IntrinsicBinary;
1734 };
1735 struct AND : public IntrinsicBinary {
1736 using IntrinsicBinary::IntrinsicBinary;
1737 };
1738 struct OR : public IntrinsicBinary {
1739 using IntrinsicBinary::IntrinsicBinary;
1740 };
1741 struct EQV : public IntrinsicBinary {
1742 using IntrinsicBinary::IntrinsicBinary;
1743 };
1744 struct NEQV : public IntrinsicBinary {
1745 using IntrinsicBinary::IntrinsicBinary;
1746 };
1747
1748 // PGI/XLF extension: (x,y), not both constant
1749 struct ComplexConstructor : public IntrinsicBinary {
1750 using IntrinsicBinary::IntrinsicBinary;
1751 };
1752
1753 struct DefinedBinary {
1754 TUPLE_CLASS_BOILERPLATE(DefinedBinary);
1755 std::tuple<DefinedOpName, common::Indirection<Expr>,
1756 common::Indirection<Expr>>
1757 t;
1758 };
1759
1760 explicit Expr(Designator &&);
1761 explicit Expr(FunctionReference &&);
1762
1763 mutable TypedExpr typedExpr;
1764
1765 CharBlock source;
1766
1767 std::variant<common::Indirection<CharLiteralConstantSubstring>,
1768 LiteralConstant, common::Indirection<Designator>, ArrayConstructor,
1769 StructureConstructor, common::Indirection<FunctionReference>, Parentheses,
1770 UnaryPlus, Negate, NOT, PercentLoc, DefinedUnary, Power, Multiply, Divide,
1771 Add, Subtract, Concat, LT, LE, EQ, NE, GE, GT, AND, OR, EQV, NEQV,
1772 DefinedBinary, ComplexConstructor, common::Indirection<SubstringInquiry>>
1773 u;
1774};
1775
1776// R912 part-ref -> part-name [( section-subscript-list )] [image-selector]
1777struct PartRef {
1778 BOILERPLATE(PartRef);
1779 PartRef(Name &&n, std::list<SectionSubscript> &&ss,
1780 std::optional<ImageSelector> &&is)
1781 : name{std::move(n)},
1782 subscripts(std::move(ss)), imageSelector{std::move(is)} {}
1783 Name name;
1784 std::list<SectionSubscript> subscripts;
1785 std::optional<ImageSelector> imageSelector;
1786};
1787
1788// R911 data-ref -> part-ref [% part-ref]...
1789struct DataRef {
1790 UNION_CLASS_BOILERPLATE(DataRef);
1791 explicit DataRef(std::list<PartRef> &&);
1792 std::variant<Name, common::Indirection<StructureComponent>,
1793 common::Indirection<ArrayElement>,
1794 common::Indirection<CoindexedNamedObject>>
1795 u;
1796};
1797
1798// R908 substring -> parent-string ( substring-range )
1799// R909 parent-string ->
1800// scalar-variable-name | array-element | coindexed-named-object |
1801// scalar-structure-component | scalar-char-literal-constant |
1802// scalar-named-constant
1803// Substrings of character literals have been factored out into their
1804// own productions so that they can't appear as designators in any context
1805// other than a primary expression.
1806struct Substring {
1807 TUPLE_CLASS_BOILERPLATE(Substring);
1808 std::tuple<DataRef, SubstringRange> t;
1809};
1810
1811struct CharLiteralConstantSubstring {
1812 TUPLE_CLASS_BOILERPLATE(CharLiteralConstantSubstring);
1813 std::tuple<CharLiteralConstant, SubstringRange> t;
1814};
1815
1816// substring%KIND/LEN type parameter inquiry for cases that could not be
1817// parsed as part-refs and fixed up afterwards. N.B. we only have to
1818// handle inquiries into designator-based substrings, not those based on
1819// char-literal-constants.
1820struct SubstringInquiry {
1821 CharBlock source;
1822 WRAPPER_CLASS_BOILERPLATE(SubstringInquiry, Substring);
1823};
1824
1825// R901 designator -> object-name | array-element | array-section |
1826// coindexed-named-object | complex-part-designator |
1827// structure-component | substring
1828struct Designator {
1829 UNION_CLASS_BOILERPLATE(Designator);
1830 bool EndsInBareName() const;
1831 CharBlock source;
1832 std::variant<DataRef, Substring> u;
1833};
1834
1835// R902 variable -> designator | function-reference
1836struct Variable {
1837 UNION_CLASS_BOILERPLATE(Variable);
1838 mutable TypedExpr typedExpr;
1839 CharBlock GetSource() const;
1840 std::variant<common::Indirection<Designator>,
1841 common::Indirection<FunctionReference>>
1842 u;
1843};
1844
1845// R904 logical-variable -> variable
1846// Appears only as part of scalar-logical-variable.
1847using ScalarLogicalVariable = Scalar<Logical<Variable>>;
1848
1849// R906 default-char-variable -> variable
1850// Appears only as part of scalar-default-char-variable.
1851using ScalarDefaultCharVariable = Scalar<DefaultChar<Variable>>;
1852
1853// R907 int-variable -> variable
1854// Appears only as part of scalar-int-variable.
1855using ScalarIntVariable = Scalar<Integer<Variable>>;
1856
1857// R913 structure-component -> data-ref
1858struct StructureComponent {
1859 BOILERPLATE(StructureComponent);
1860 StructureComponent(DataRef &&dr, Name &&n)
1861 : base{std::move(dr)}, component(std::move(n)) {}
1862 DataRef base;
1863 Name component;
1864};
1865
1866// R1039 proc-component-ref -> scalar-variable % procedure-component-name
1867// C1027 constrains the scalar-variable to be a data-ref without coindices.
1868struct ProcComponentRef {
1869 WRAPPER_CLASS_BOILERPLATE(ProcComponentRef, Scalar<StructureComponent>);
1870};
1871
1872// R914 coindexed-named-object -> data-ref
1873struct CoindexedNamedObject {
1874 BOILERPLATE(CoindexedNamedObject);
1875 CoindexedNamedObject(DataRef &&dr, ImageSelector &&is)
1876 : base{std::move(dr)}, imageSelector{std::move(is)} {}
1877 DataRef base;
1878 ImageSelector imageSelector;
1879};
1880
1881// R917 array-element -> data-ref
1882struct ArrayElement {
1883 BOILERPLATE(ArrayElement);
1884 ArrayElement(DataRef &&dr, std::list<SectionSubscript> &&ss)
1885 : base{std::move(dr)}, subscripts(std::move(ss)) {}
1886 Substring ConvertToSubstring();
1887 StructureConstructor ConvertToStructureConstructor(
1888 const semantics::DerivedTypeSpec &);
1889 DataRef base;
1890 std::list<SectionSubscript> subscripts;
1891};
1892
1893// R933 allocate-object -> variable-name | structure-component
1894struct AllocateObject {
1895 UNION_CLASS_BOILERPLATE(AllocateObject);
1896 mutable TypedExpr typedExpr;
1897 std::variant<Name, StructureComponent> u;
1898};
1899
1900// R935 lower-bound-expr -> scalar-int-expr
1901// R936 upper-bound-expr -> scalar-int-expr
1902using BoundExpr = ScalarIntExpr;
1903
1904// R934 allocate-shape-spec -> [lower-bound-expr :] upper-bound-expr
1905// R938 allocate-coshape-spec -> [lower-bound-expr :] upper-bound-expr
1906struct AllocateShapeSpec {
1907 TUPLE_CLASS_BOILERPLATE(AllocateShapeSpec);
1908 std::tuple<std::optional<BoundExpr>, BoundExpr> t;
1909};
1910
1911using AllocateCoshapeSpec = AllocateShapeSpec;
1912
1913// R937 allocate-coarray-spec ->
1914// [allocate-coshape-spec-list ,] [lower-bound-expr :] *
1915struct AllocateCoarraySpec {
1916 TUPLE_CLASS_BOILERPLATE(AllocateCoarraySpec);
1917 std::tuple<std::list<AllocateCoshapeSpec>, std::optional<BoundExpr>> t;
1918};
1919
1920// R932 allocation ->
1921// allocate-object [( allocate-shape-spec-list )]
1922// [lbracket allocate-coarray-spec rbracket]
1923struct Allocation {
1924 TUPLE_CLASS_BOILERPLATE(Allocation);
1925 std::tuple<AllocateObject, std::list<AllocateShapeSpec>,
1926 std::optional<AllocateCoarraySpec>>
1927 t;
1928};
1929
1930// R929 stat-variable -> scalar-int-variable
1931WRAPPER_CLASS(StatVariable, ScalarIntVariable);
1932
1933// R930 errmsg-variable -> scalar-default-char-variable
1934// R1207 iomsg-variable -> scalar-default-char-variable
1935WRAPPER_CLASS(MsgVariable, ScalarDefaultCharVariable);
1936
1937// R942 dealloc-opt -> STAT = stat-variable | ERRMSG = errmsg-variable
1938// R1165 sync-stat -> STAT = stat-variable | ERRMSG = errmsg-variable
1939struct StatOrErrmsg {
1940 UNION_CLASS_BOILERPLATE(StatOrErrmsg);
1941 std::variant<StatVariable, MsgVariable> u;
1942};
1943
1944// R928 alloc-opt ->
1945// ERRMSG = errmsg-variable | MOLD = source-expr |
1946// SOURCE = source-expr | STAT = stat-variable |
1947// (CUDA) STREAM = scalar-int-expr
1948// PINNED = scalar-logical-variable
1949// R931 source-expr -> expr
1950struct AllocOpt {
1951 UNION_CLASS_BOILERPLATE(AllocOpt);
1952 WRAPPER_CLASS(Mold, common::Indirection<Expr>);
1953 WRAPPER_CLASS(Source, common::Indirection<Expr>);
1954 WRAPPER_CLASS(Stream, common::Indirection<ScalarIntExpr>);
1955 WRAPPER_CLASS(Pinned, common::Indirection<ScalarLogicalVariable>);
1956 std::variant<Mold, Source, StatOrErrmsg, Stream, Pinned> u;
1957};
1958
1959// R927 allocate-stmt ->
1960// ALLOCATE ( [type-spec ::] allocation-list [, alloc-opt-list] )
1961struct AllocateStmt {
1962 TUPLE_CLASS_BOILERPLATE(AllocateStmt);
1963 std::tuple<std::optional<TypeSpec>, std::list<Allocation>,
1964 std::list<AllocOpt>>
1965 t;
1966};
1967
1968// R940 pointer-object ->
1969// variable-name | structure-component | proc-pointer-name
1970struct PointerObject {
1971 UNION_CLASS_BOILERPLATE(PointerObject);
1972 mutable TypedExpr typedExpr;
1973 std::variant<Name, StructureComponent> u;
1974};
1975
1976// R939 nullify-stmt -> NULLIFY ( pointer-object-list )
1977WRAPPER_CLASS(NullifyStmt, std::list<PointerObject>);
1978
1979// R941 deallocate-stmt ->
1980// DEALLOCATE ( allocate-object-list [, dealloc-opt-list] )
1981struct DeallocateStmt {
1982 TUPLE_CLASS_BOILERPLATE(DeallocateStmt);
1983 std::tuple<std::list<AllocateObject>, std::list<StatOrErrmsg>> t;
1984};
1985
1986// R1032 assignment-stmt -> variable = expr
1987struct AssignmentStmt {
1988 TUPLE_CLASS_BOILERPLATE(AssignmentStmt);
1989 using TypedAssignment =
1990 common::ForwardOwningPointer<evaluate::GenericAssignmentWrapper>;
1991 mutable TypedAssignment typedAssignment;
1992 std::tuple<Variable, Expr> t;
1993};
1994
1995// R1035 bounds-spec -> lower-bound-expr :
1996WRAPPER_CLASS(BoundsSpec, BoundExpr);
1997
1998// R1036 bounds-remapping -> lower-bound-expr : upper-bound-expr
1999struct BoundsRemapping {
2000 TUPLE_CLASS_BOILERPLATE(BoundsRemapping);
2001 std::tuple<BoundExpr, BoundExpr> t;
2002};
2003
2004// R1033 pointer-assignment-stmt ->
2005// data-pointer-object [( bounds-spec-list )] => data-target |
2006// data-pointer-object ( bounds-remapping-list ) => data-target |
2007// proc-pointer-object => proc-target
2008// R1034 data-pointer-object ->
2009// variable-name | scalar-variable % data-pointer-component-name
2010// R1038 proc-pointer-object -> proc-pointer-name | proc-component-ref
2011struct PointerAssignmentStmt {
2012 struct Bounds {
2013 UNION_CLASS_BOILERPLATE(Bounds);
2014 std::variant<std::list<BoundsRemapping>, std::list<BoundsSpec>> u;
2015 };
2016 TUPLE_CLASS_BOILERPLATE(PointerAssignmentStmt);
2017 mutable AssignmentStmt::TypedAssignment typedAssignment;
2018 std::tuple<DataRef, Bounds, Expr> t;
2019};
2020
2021// R1041 where-stmt -> WHERE ( mask-expr ) where-assignment-stmt
2022// R1045 where-assignment-stmt -> assignment-stmt
2023// R1046 mask-expr -> logical-expr
2024struct WhereStmt {
2025 TUPLE_CLASS_BOILERPLATE(WhereStmt);
2026 std::tuple<LogicalExpr, AssignmentStmt> t;
2027};
2028
2029// R1043 where-construct-stmt -> [where-construct-name :] WHERE ( mask-expr )
2030struct WhereConstructStmt {
2031 TUPLE_CLASS_BOILERPLATE(WhereConstructStmt);
2032 std::tuple<std::optional<Name>, LogicalExpr> t;
2033};
2034
2035// R1044 where-body-construct ->
2036// where-assignment-stmt | where-stmt | where-construct
2037struct WhereBodyConstruct {
2038 UNION_CLASS_BOILERPLATE(WhereBodyConstruct);
2039 std::variant<Statement<AssignmentStmt>, Statement<WhereStmt>,
2040 common::Indirection<WhereConstruct>>
2041 u;
2042};
2043
2044// R1047 masked-elsewhere-stmt ->
2045// ELSEWHERE ( mask-expr ) [where-construct-name]
2046struct MaskedElsewhereStmt {
2047 TUPLE_CLASS_BOILERPLATE(MaskedElsewhereStmt);
2048 std::tuple<LogicalExpr, std::optional<Name>> t;
2049};
2050
2051// R1048 elsewhere-stmt -> ELSEWHERE [where-construct-name]
2052WRAPPER_CLASS(ElsewhereStmt, std::optional<Name>);
2053
2054// R1049 end-where-stmt -> END WHERE [where-construct-name]
2055WRAPPER_CLASS(EndWhereStmt, std::optional<Name>);
2056
2057// R1042 where-construct ->
2058// where-construct-stmt [where-body-construct]...
2059// [masked-elsewhere-stmt [where-body-construct]...]...
2060// [elsewhere-stmt [where-body-construct]...] end-where-stmt
2061struct WhereConstruct {
2062 struct MaskedElsewhere {
2063 TUPLE_CLASS_BOILERPLATE(MaskedElsewhere);
2064 std::tuple<Statement<MaskedElsewhereStmt>, std::list<WhereBodyConstruct>> t;
2065 };
2066 struct Elsewhere {
2067 TUPLE_CLASS_BOILERPLATE(Elsewhere);
2068 std::tuple<Statement<ElsewhereStmt>, std::list<WhereBodyConstruct>> t;
2069 };
2070 TUPLE_CLASS_BOILERPLATE(WhereConstruct);
2071 std::tuple<Statement<WhereConstructStmt>, std::list<WhereBodyConstruct>,
2072 std::list<MaskedElsewhere>, std::optional<Elsewhere>,
2073 Statement<EndWhereStmt>>
2074 t;
2075};
2076
2077// R1051 forall-construct-stmt ->
2078// [forall-construct-name :] FORALL concurrent-header
2079struct ForallConstructStmt {
2080 TUPLE_CLASS_BOILERPLATE(ForallConstructStmt);
2081 std::tuple<std::optional<Name>, common::Indirection<ConcurrentHeader>> t;
2082};
2083
2084// R1053 forall-assignment-stmt -> assignment-stmt | pointer-assignment-stmt
2085struct ForallAssignmentStmt {
2086 UNION_CLASS_BOILERPLATE(ForallAssignmentStmt);
2087 std::variant<AssignmentStmt, PointerAssignmentStmt> u;
2088};
2089
2090// R1055 forall-stmt -> FORALL concurrent-header forall-assignment-stmt
2091struct ForallStmt {
2092 TUPLE_CLASS_BOILERPLATE(ForallStmt);
2093 std::tuple<common::Indirection<ConcurrentHeader>,
2094 UnlabeledStatement<ForallAssignmentStmt>>
2095 t;
2096};
2097
2098// R1052 forall-body-construct ->
2099// forall-assignment-stmt | where-stmt | where-construct |
2100// forall-construct | forall-stmt
2101struct ForallBodyConstruct {
2102 UNION_CLASS_BOILERPLATE(ForallBodyConstruct);
2103 std::variant<Statement<ForallAssignmentStmt>, Statement<WhereStmt>,
2104 WhereConstruct, common::Indirection<ForallConstruct>,
2105 Statement<ForallStmt>>
2106 u;
2107};
2108
2109// R1054 end-forall-stmt -> END FORALL [forall-construct-name]
2110WRAPPER_CLASS(EndForallStmt, std::optional<Name>);
2111
2112// R1050 forall-construct ->
2113// forall-construct-stmt [forall-body-construct]... end-forall-stmt
2114struct ForallConstruct {
2115 TUPLE_CLASS_BOILERPLATE(ForallConstruct);
2116 std::tuple<Statement<ForallConstructStmt>, std::list<ForallBodyConstruct>,
2117 Statement<EndForallStmt>>
2118 t;
2119};
2120
2121// R1105 selector -> expr | variable
2122struct Selector {
2123 UNION_CLASS_BOILERPLATE(Selector);
2124 std::variant<Expr, Variable> u;
2125};
2126
2127// R1104 association -> associate-name => selector
2128struct Association {
2129 TUPLE_CLASS_BOILERPLATE(Association);
2130 std::tuple<Name, Selector> t;
2131};
2132
2133// R1103 associate-stmt ->
2134// [associate-construct-name :] ASSOCIATE ( association-list )
2135struct AssociateStmt {
2136 TUPLE_CLASS_BOILERPLATE(AssociateStmt);
2137 std::tuple<std::optional<Name>, std::list<Association>> t;
2138};
2139
2140// R1106 end-associate-stmt -> END ASSOCIATE [associate-construct-name]
2141WRAPPER_CLASS(EndAssociateStmt, std::optional<Name>);
2142
2143// R1102 associate-construct -> associate-stmt block end-associate-stmt
2144struct AssociateConstruct {
2145 TUPLE_CLASS_BOILERPLATE(AssociateConstruct);
2146 std::tuple<Statement<AssociateStmt>, Block, Statement<EndAssociateStmt>> t;
2147};
2148
2149// R1108 block-stmt -> [block-construct-name :] BLOCK
2150WRAPPER_CLASS(BlockStmt, std::optional<Name>);
2151
2152// R1110 end-block-stmt -> END BLOCK [block-construct-name]
2153WRAPPER_CLASS(EndBlockStmt, std::optional<Name>);
2154
2155// R1109 block-specification-part ->
2156// [use-stmt]... [import-stmt]...
2157// [[declaration-construct]... specification-construct]
2158// N.B. Because BlockSpecificationPart just wraps the more general
2159// SpecificationPart, it can misrecognize an ImplicitPart as part of
2160// the BlockSpecificationPart during parsing, and we have to detect and
2161// flag such usage in semantics.
2162WRAPPER_CLASS(BlockSpecificationPart, SpecificationPart);
2163
2164// R1107 block-construct ->
2165// block-stmt [block-specification-part] block end-block-stmt
2166struct BlockConstruct {
2167 TUPLE_CLASS_BOILERPLATE(BlockConstruct);
2168 std::tuple<Statement<BlockStmt>, BlockSpecificationPart, Block,
2169 Statement<EndBlockStmt>>
2170 t;
2171};
2172
2173// R1113 coarray-association -> codimension-decl => selector
2174struct CoarrayAssociation {
2175 TUPLE_CLASS_BOILERPLATE(CoarrayAssociation);
2176 std::tuple<CodimensionDecl, Selector> t;
2177};
2178
2179// R1112 change-team-stmt ->
2180// [team-construct-name :] CHANGE TEAM
2181// ( team-value [, coarray-association-list] [, sync-stat-list] )
2182struct ChangeTeamStmt {
2183 TUPLE_CLASS_BOILERPLATE(ChangeTeamStmt);
2184 std::tuple<std::optional<Name>, TeamValue, std::list<CoarrayAssociation>,
2185 std::list<StatOrErrmsg>>
2186 t;
2187};
2188
2189// R1114 end-change-team-stmt ->
2190// END TEAM [( [sync-stat-list] )] [team-construct-name]
2191struct EndChangeTeamStmt {
2192 TUPLE_CLASS_BOILERPLATE(EndChangeTeamStmt);
2193 std::tuple<std::list<StatOrErrmsg>, std::optional<Name>> t;
2194};
2195
2196// R1111 change-team-construct -> change-team-stmt block end-change-team-stmt
2197struct ChangeTeamConstruct {
2198 TUPLE_CLASS_BOILERPLATE(ChangeTeamConstruct);
2199 std::tuple<Statement<ChangeTeamStmt>, Block, Statement<EndChangeTeamStmt>> t;
2200};
2201
2202// R1117 critical-stmt ->
2203// [critical-construct-name :] CRITICAL [( [sync-stat-list] )]
2204struct CriticalStmt {
2205 TUPLE_CLASS_BOILERPLATE(CriticalStmt);
2206 std::tuple<std::optional<Name>, std::list<StatOrErrmsg>> t;
2207};
2208
2209// R1118 end-critical-stmt -> END CRITICAL [critical-construct-name]
2210WRAPPER_CLASS(EndCriticalStmt, std::optional<Name>);
2211
2212// R1116 critical-construct -> critical-stmt block end-critical-stmt
2213struct CriticalConstruct {
2214 TUPLE_CLASS_BOILERPLATE(CriticalConstruct);
2215 std::tuple<Statement<CriticalStmt>, Block, Statement<EndCriticalStmt>> t;
2216};
2217
2218// R1126 concurrent-control ->
2219// index-name = concurrent-limit : concurrent-limit [: concurrent-step]
2220// R1127 concurrent-limit -> scalar-int-expr
2221// R1128 concurrent-step -> scalar-int-expr
2222struct ConcurrentControl {
2223 TUPLE_CLASS_BOILERPLATE(ConcurrentControl);
2224 std::tuple<Name, ScalarIntExpr, ScalarIntExpr, std::optional<ScalarIntExpr>>
2225 t;
2226};
2227
2228// R1125 concurrent-header ->
2229// ( [integer-type-spec ::] concurrent-control-list
2230// [, scalar-mask-expr] )
2231struct ConcurrentHeader {
2232 TUPLE_CLASS_BOILERPLATE(ConcurrentHeader);
2233 std::tuple<std::optional<IntegerTypeSpec>, std::list<ConcurrentControl>,
2234 std::optional<ScalarLogicalExpr>>
2235 t;
2236};
2237
2238// R1130 locality-spec ->
2239// LOCAL ( variable-name-list ) | LOCAL_INIT ( variable-name-list ) |
2240// SHARED ( variable-name-list ) | DEFAULT ( NONE )
2241struct LocalitySpec {
2242 UNION_CLASS_BOILERPLATE(LocalitySpec);
2243 WRAPPER_CLASS(Local, std::list<Name>);
2244 WRAPPER_CLASS(LocalInit, std::list<Name>);
2245 WRAPPER_CLASS(Shared, std::list<Name>);
2246 EMPTY_CLASS(DefaultNone);
2247 std::variant<Local, LocalInit, Shared, DefaultNone> u;
2248};
2249
2250// R1123 loop-control ->
2251// [,] do-variable = scalar-int-expr , scalar-int-expr
2252// [, scalar-int-expr] |
2253// [,] WHILE ( scalar-logical-expr ) |
2254// [,] CONCURRENT concurrent-header concurrent-locality
2255// R1129 concurrent-locality -> [locality-spec]...
2256struct LoopControl {
2257 UNION_CLASS_BOILERPLATE(LoopControl);
2258 struct Concurrent {
2259 TUPLE_CLASS_BOILERPLATE(Concurrent);
2260 std::tuple<ConcurrentHeader, std::list<LocalitySpec>> t;
2261 };
2262 using Bounds = LoopBounds<ScalarName, ScalarExpr>;
2263 std::variant<Bounds, ScalarLogicalExpr, Concurrent> u;
2264};
2265
2266// R1121 label-do-stmt -> [do-construct-name :] DO label [loop-control]
2267// A label-do-stmt with a do-construct-name is parsed as a non-label-do-stmt.
2268struct LabelDoStmt {
2269 TUPLE_CLASS_BOILERPLATE(LabelDoStmt);
2270 std::tuple<Label, std::optional<LoopControl>> t;
2271};
2272
2273// R1122 nonlabel-do-stmt -> [do-construct-name :] DO [loop-control]
2274struct NonLabelDoStmt {
2275 TUPLE_CLASS_BOILERPLATE(NonLabelDoStmt);
2276 std::tuple<std::optional<Name>, std::optional<Label>,
2277 std::optional<LoopControl>>
2278 t;
2279};
2280
2281// R1132 end-do-stmt -> END DO [do-construct-name]
2282WRAPPER_CLASS(EndDoStmt, std::optional<Name>);
2283
2284// R1131 end-do -> end-do-stmt | continue-stmt
2285
2286// R1119 do-construct -> do-stmt block end-do
2287// R1120 do-stmt -> nonlabel-do-stmt | label-do-stmt
2288// Deprecated, but supported: "label DO" loops ending on statements other
2289// than END DO and CONTINUE, and multiple "label DO" loops ending on the
2290// same label.
2291struct DoConstruct {
2292 TUPLE_CLASS_BOILERPLATE(DoConstruct);
2293 const std::optional<LoopControl> &GetLoopControl() const;
2294 bool IsDoNormal() const;
2295 bool IsDoWhile() const;
2296 bool IsDoConcurrent() const;
2297 std::tuple<Statement<NonLabelDoStmt>, Block, Statement<EndDoStmt>> t;
2298};
2299
2300// R1133 cycle-stmt -> CYCLE [do-construct-name]
2301WRAPPER_CLASS(CycleStmt, std::optional<Name>);
2302
2303// R1135 if-then-stmt -> [if-construct-name :] IF ( scalar-logical-expr ) THEN
2304struct IfThenStmt {
2305 TUPLE_CLASS_BOILERPLATE(IfThenStmt);
2306 std::tuple<std::optional<Name>, ScalarLogicalExpr> t;
2307};
2308
2309// R1136 else-if-stmt ->
2310// ELSE IF ( scalar-logical-expr ) THEN [if-construct-name]
2311struct ElseIfStmt {
2312 TUPLE_CLASS_BOILERPLATE(ElseIfStmt);
2313 std::tuple<ScalarLogicalExpr, std::optional<Name>> t;
2314};
2315
2316// R1137 else-stmt -> ELSE [if-construct-name]
2317WRAPPER_CLASS(ElseStmt, std::optional<Name>);
2318
2319// R1138 end-if-stmt -> END IF [if-construct-name]
2320WRAPPER_CLASS(EndIfStmt, std::optional<Name>);
2321
2322// R1134 if-construct ->
2323// if-then-stmt block [else-if-stmt block]...
2324// [else-stmt block] end-if-stmt
2325struct IfConstruct {
2326 struct ElseIfBlock {
2327 TUPLE_CLASS_BOILERPLATE(ElseIfBlock);
2328 std::tuple<Statement<ElseIfStmt>, Block> t;
2329 };
2330 struct ElseBlock {
2331 TUPLE_CLASS_BOILERPLATE(ElseBlock);
2332 std::tuple<Statement<ElseStmt>, Block> t;
2333 };
2334 TUPLE_CLASS_BOILERPLATE(IfConstruct);
2335 std::tuple<Statement<IfThenStmt>, Block, std::list<ElseIfBlock>,
2336 std::optional<ElseBlock>, Statement<EndIfStmt>>
2337 t;
2338};
2339
2340// R1139 if-stmt -> IF ( scalar-logical-expr ) action-stmt
2341struct IfStmt {
2342 TUPLE_CLASS_BOILERPLATE(IfStmt);
2343 std::tuple<ScalarLogicalExpr, UnlabeledStatement<ActionStmt>> t;
2344};
2345
2346// R1141 select-case-stmt -> [case-construct-name :] SELECT CASE ( case-expr )
2347// R1144 case-expr -> scalar-expr
2348struct SelectCaseStmt {
2349 TUPLE_CLASS_BOILERPLATE(SelectCaseStmt);
2350 std::tuple<std::optional<Name>, Scalar<Expr>> t;
2351};
2352
2353// R1147 case-value -> scalar-constant-expr
2354using CaseValue = Scalar<ConstantExpr>;
2355
2356// R1146 case-value-range ->
2357// case-value | case-value : | : case-value | case-value : case-value
2358struct CaseValueRange {
2359 UNION_CLASS_BOILERPLATE(CaseValueRange);
2360 struct Range {
2361 BOILERPLATE(Range);
2362 Range(std::optional<CaseValue> &&l, std::optional<CaseValue> &&u)
2363 : lower{std::move(l)}, upper{std::move(u)} {}
2364 std::optional<CaseValue> lower, upper; // not both missing
2365 };
2366 std::variant<CaseValue, Range> u;
2367};
2368
2369// R1145 case-selector -> ( case-value-range-list ) | DEFAULT
2370EMPTY_CLASS(Default);
2371
2372struct CaseSelector {
2373 UNION_CLASS_BOILERPLATE(CaseSelector);
2374 std::variant<std::list<CaseValueRange>, Default> u;
2375};
2376
2377// R1142 case-stmt -> CASE case-selector [case-construct-name]
2378struct CaseStmt {
2379 TUPLE_CLASS_BOILERPLATE(CaseStmt);
2380 std::tuple<CaseSelector, std::optional<Name>> t;
2381};
2382
2383// R1143 end-select-stmt -> END SELECT [case-construct-name]
2384// R1151 end-select-rank-stmt -> END SELECT [select-construct-name]
2385// R1155 end-select-type-stmt -> END SELECT [select-construct-name]
2386WRAPPER_CLASS(EndSelectStmt, std::optional<Name>);
2387
2388// R1140 case-construct ->
2389// select-case-stmt [case-stmt block]... end-select-stmt
2390struct CaseConstruct {
2391 struct Case {
2392 TUPLE_CLASS_BOILERPLATE(Case);
2393 std::tuple<Statement<CaseStmt>, Block> t;
2394 };
2395 TUPLE_CLASS_BOILERPLATE(CaseConstruct);
2396 std::tuple<Statement<SelectCaseStmt>, std::list<Case>,
2397 Statement<EndSelectStmt>>
2398 t;
2399};
2400
2401// R1149 select-rank-stmt ->
2402// [select-construct-name :] SELECT RANK
2403// ( [associate-name =>] selector )
2404struct SelectRankStmt {
2405 TUPLE_CLASS_BOILERPLATE(SelectRankStmt);
2406 std::tuple<std::optional<Name>, std::optional<Name>, Selector> t;
2407};
2408
2409// R1150 select-rank-case-stmt ->
2410// RANK ( scalar-int-constant-expr ) [select-construct-name] |
2411// RANK ( * ) [select-construct-name] |
2412// RANK DEFAULT [select-construct-name]
2413struct SelectRankCaseStmt {
2414 struct Rank {
2415 UNION_CLASS_BOILERPLATE(Rank);
2416 std::variant<ScalarIntConstantExpr, Star, Default> u;
2417 };
2418 TUPLE_CLASS_BOILERPLATE(SelectRankCaseStmt);
2419 std::tuple<Rank, std::optional<Name>> t;
2420};
2421
2422// R1148 select-rank-construct ->
2423// select-rank-stmt [select-rank-case-stmt block]...
2424// end-select-rank-stmt
2425struct SelectRankConstruct {
2426 TUPLE_CLASS_BOILERPLATE(SelectRankConstruct);
2427 struct RankCase {
2428 TUPLE_CLASS_BOILERPLATE(RankCase);
2429 std::tuple<Statement<SelectRankCaseStmt>, Block> t;
2430 };
2431 std::tuple<Statement<SelectRankStmt>, std::list<RankCase>,
2432 Statement<EndSelectStmt>>
2433 t;
2434};
2435
2436// R1153 select-type-stmt ->
2437// [select-construct-name :] SELECT TYPE
2438// ( [associate-name =>] selector )
2439struct SelectTypeStmt {
2440 TUPLE_CLASS_BOILERPLATE(SelectTypeStmt);
2441 std::tuple<std::optional<Name>, std::optional<Name>, Selector> t;
2442};
2443
2444// R1154 type-guard-stmt ->
2445// TYPE IS ( type-spec ) [select-construct-name] |
2446// CLASS IS ( derived-type-spec ) [select-construct-name] |
2447// CLASS DEFAULT [select-construct-name]
2448struct TypeGuardStmt {
2449 struct Guard {
2450 UNION_CLASS_BOILERPLATE(Guard);
2451 std::variant<TypeSpec, DerivedTypeSpec, Default> u;
2452 };
2453 TUPLE_CLASS_BOILERPLATE(TypeGuardStmt);
2454 std::tuple<Guard, std::optional<Name>> t;
2455};
2456
2457// R1152 select-type-construct ->
2458// select-type-stmt [type-guard-stmt block]... end-select-type-stmt
2459struct SelectTypeConstruct {
2460 TUPLE_CLASS_BOILERPLATE(SelectTypeConstruct);
2461 struct TypeCase {
2462 TUPLE_CLASS_BOILERPLATE(TypeCase);
2463 std::tuple<Statement<TypeGuardStmt>, Block> t;
2464 };
2465 std::tuple<Statement<SelectTypeStmt>, std::list<TypeCase>,
2466 Statement<EndSelectStmt>>
2467 t;
2468};
2469
2470// R1156 exit-stmt -> EXIT [construct-name]
2471WRAPPER_CLASS(ExitStmt, std::optional<Name>);
2472
2473// R1157 goto-stmt -> GO TO label
2474WRAPPER_CLASS(GotoStmt, Label);
2475
2476// R1158 computed-goto-stmt -> GO TO ( label-list ) [,] scalar-int-expr
2477struct ComputedGotoStmt {
2478 TUPLE_CLASS_BOILERPLATE(ComputedGotoStmt);
2479 std::tuple<std::list<Label>, ScalarIntExpr> t;
2480};
2481
2482// R1162 stop-code -> scalar-default-char-expr | scalar-int-expr
2483// We can't distinguish character expressions from integer
2484// expressions during parsing, so we just parse an expr and
2485// check its type later.
2486WRAPPER_CLASS(StopCode, Scalar<Expr>);
2487
2488// R1160 stop-stmt -> STOP [stop-code] [, QUIET = scalar-logical-expr]
2489// R1161 error-stop-stmt ->
2490// ERROR STOP [stop-code] [, QUIET = scalar-logical-expr]
2491struct StopStmt {
2492 ENUM_CLASS(Kind, Stop, ErrorStop)
2493 TUPLE_CLASS_BOILERPLATE(StopStmt);
2494 std::tuple<Kind, std::optional<StopCode>, std::optional<ScalarLogicalExpr>> t;
2495};
2496
2497// F2023: R1166 notify-wait-stmt -> NOTIFY WAIT ( notify-variable [,
2498// event-wait-spec-list] )
2499struct NotifyWaitStmt {
2500 TUPLE_CLASS_BOILERPLATE(NotifyWaitStmt);
2501 std::tuple<Scalar<Variable>, std::list<EventWaitSpec>> t;
2502};
2503
2504// R1164 sync-all-stmt -> SYNC ALL [( [sync-stat-list] )]
2505WRAPPER_CLASS(SyncAllStmt, std::list<StatOrErrmsg>);
2506
2507// R1166 sync-images-stmt -> SYNC IMAGES ( image-set [, sync-stat-list] )
2508// R1167 image-set -> int-expr | *
2509struct SyncImagesStmt {
2510 struct ImageSet {
2511 UNION_CLASS_BOILERPLATE(ImageSet);
2512 std::variant<IntExpr, Star> u;
2513 };
2514 TUPLE_CLASS_BOILERPLATE(SyncImagesStmt);
2515 std::tuple<ImageSet, std::list<StatOrErrmsg>> t;
2516};
2517
2518// R1168 sync-memory-stmt -> SYNC MEMORY [( [sync-stat-list] )]
2519WRAPPER_CLASS(SyncMemoryStmt, std::list<StatOrErrmsg>);
2520
2521// R1169 sync-team-stmt -> SYNC TEAM ( team-value [, sync-stat-list] )
2522struct SyncTeamStmt {
2523 TUPLE_CLASS_BOILERPLATE(SyncTeamStmt);
2524 std::tuple<TeamValue, std::list<StatOrErrmsg>> t;
2525};
2526
2527// R1171 event-variable -> scalar-variable
2528using EventVariable = Scalar<Variable>;
2529
2530// R1170 event-post-stmt -> EVENT POST ( event-variable [, sync-stat-list] )
2531struct EventPostStmt {
2532 TUPLE_CLASS_BOILERPLATE(EventPostStmt);
2533 std::tuple<EventVariable, std::list<StatOrErrmsg>> t;
2534};
2535
2536// R1173 event-wait-spec -> until-spec | sync-stat
2537struct EventWaitSpec {
2538 UNION_CLASS_BOILERPLATE(EventWaitSpec);
2539 std::variant<ScalarIntExpr, StatOrErrmsg> u;
2540};
2541
2542// R1172 event-wait-stmt ->
2543// EVENT WAIT ( event-variable [, event-wait-spec-list] )
2544// R1174 until-spec -> UNTIL_COUNT = scalar-int-expr
2545struct EventWaitStmt {
2546 TUPLE_CLASS_BOILERPLATE(EventWaitStmt);
2547 std::tuple<EventVariable, std::list<EventWaitSpec>> t;
2548};
2549
2550// R1177 team-variable -> scalar-variable
2551using TeamVariable = Scalar<Variable>;
2552
2553// R1175 form-team-stmt ->
2554// FORM TEAM ( team-number , team-variable [, form-team-spec-list] )
2555// R1176 team-number -> scalar-int-expr
2556// R1178 form-team-spec -> NEW_INDEX = scalar-int-expr | sync-stat
2557struct FormTeamStmt {
2558 struct FormTeamSpec {
2559 UNION_CLASS_BOILERPLATE(FormTeamSpec);
2560 std::variant<ScalarIntExpr, StatOrErrmsg> u;
2561 };
2562 TUPLE_CLASS_BOILERPLATE(FormTeamStmt);
2563 std::tuple<ScalarIntExpr, TeamVariable, std::list<FormTeamSpec>> t;
2564};
2565
2566// R1182 lock-variable -> scalar-variable
2567using LockVariable = Scalar<Variable>;
2568
2569// R1179 lock-stmt -> LOCK ( lock-variable [, lock-stat-list] )
2570// R1180 lock-stat -> ACQUIRED_LOCK = scalar-logical-variable | sync-stat
2571struct LockStmt {
2572 struct LockStat {
2573 UNION_CLASS_BOILERPLATE(LockStat);
2574 std::variant<Scalar<Logical<Variable>>, StatOrErrmsg> u;
2575 };
2576 TUPLE_CLASS_BOILERPLATE(LockStmt);
2577 std::tuple<LockVariable, std::list<LockStat>> t;
2578};
2579
2580// R1181 unlock-stmt -> UNLOCK ( lock-variable [, sync-stat-list] )
2581struct UnlockStmt {
2582 TUPLE_CLASS_BOILERPLATE(UnlockStmt);
2583 std::tuple<LockVariable, std::list<StatOrErrmsg>> t;
2584};
2585
2586// R1202 file-unit-number -> scalar-int-expr
2587WRAPPER_CLASS(FileUnitNumber, ScalarIntExpr);
2588
2589// R1201 io-unit -> file-unit-number | * | internal-file-variable
2590// R1203 internal-file-variable -> char-variable
2591// R905 char-variable -> variable
2592// When Variable appears as an IoUnit, it must be character of a default,
2593// ASCII, or Unicode kind; this constraint is not automatically checked.
2594// The parse is ambiguous and is repaired if necessary once the types of
2595// symbols are known.
2596struct IoUnit {
2597 UNION_CLASS_BOILERPLATE(IoUnit);
2598 std::variant<Variable, FileUnitNumber, Star> u;
2599};
2600
2601// R1206 file-name-expr -> scalar-default-char-expr
2602using FileNameExpr = ScalarDefaultCharExpr;
2603
2604// R1205 connect-spec ->
2605// [UNIT =] file-unit-number | ACCESS = scalar-default-char-expr |
2606// ACTION = scalar-default-char-expr |
2607// ASYNCHRONOUS = scalar-default-char-expr |
2608// BLANK = scalar-default-char-expr |
2609// DECIMAL = scalar-default-char-expr |
2610// DELIM = scalar-default-char-expr |
2611// ENCODING = scalar-default-char-expr | ERR = label |
2612// FILE = file-name-expr | FORM = scalar-default-char-expr |
2613// IOMSG = iomsg-variable | IOSTAT = scalar-int-variable |
2614// NEWUNIT = scalar-int-variable | PAD = scalar-default-char-expr |
2615// POSITION = scalar-default-char-expr | RECL = scalar-int-expr |
2616// ROUND = scalar-default-char-expr | SIGN = scalar-default-char-expr |
2617// STATUS = scalar-default-char-expr
2618// @ | CARRIAGECONTROL = scalar-default-char-variable
2619// | CONVERT = scalar-default-char-variable
2620// | DISPOSE = scalar-default-char-variable
2621WRAPPER_CLASS(StatusExpr, ScalarDefaultCharExpr);
2622WRAPPER_CLASS(ErrLabel, Label);
2623
2624struct ConnectSpec {
2625 UNION_CLASS_BOILERPLATE(ConnectSpec);
2626 struct CharExpr {
2627 ENUM_CLASS(Kind, Access, Action, Asynchronous, Blank, Decimal, Delim,
2628 Encoding, Form, Pad, Position, Round, Sign,
2629 /* extensions: */ Carriagecontrol, Convert, Dispose)
2630 TUPLE_CLASS_BOILERPLATE(CharExpr);
2631 std::tuple<Kind, ScalarDefaultCharExpr> t;
2632 };
2633 WRAPPER_CLASS(Recl, ScalarIntExpr);
2634 WRAPPER_CLASS(Newunit, ScalarIntVariable);
2635 std::variant<FileUnitNumber, FileNameExpr, CharExpr, MsgVariable,
2636 StatVariable, Recl, Newunit, ErrLabel, StatusExpr>
2637 u;
2638};
2639
2640// R1204 open-stmt -> OPEN ( connect-spec-list )
2641WRAPPER_CLASS(OpenStmt, std::list<ConnectSpec>);
2642
2643// R1208 close-stmt -> CLOSE ( close-spec-list )
2644// R1209 close-spec ->
2645// [UNIT =] file-unit-number | IOSTAT = scalar-int-variable |
2646// IOMSG = iomsg-variable | ERR = label |
2647// STATUS = scalar-default-char-expr
2648struct CloseStmt {
2649 struct CloseSpec {
2650 UNION_CLASS_BOILERPLATE(CloseSpec);
2651 std::variant<FileUnitNumber, StatVariable, MsgVariable, ErrLabel,
2652 StatusExpr>
2653 u;
2654 };
2655 WRAPPER_CLASS_BOILERPLATE(CloseStmt, std::list<CloseSpec>);
2656};
2657
2658// R1215 format -> default-char-expr | label | *
2659// deprecated(ASSIGN): | scalar-int-name
2660struct Format {
2661 UNION_CLASS_BOILERPLATE(Format);
2662 std::variant<Expr, Label, Star> u;
2663};
2664
2665// R1214 id-variable -> scalar-int-variable
2666WRAPPER_CLASS(IdVariable, ScalarIntVariable);
2667
2668// R1213 io-control-spec ->
2669// [UNIT =] io-unit | [FMT =] format | [NML =] namelist-group-name |
2670// ADVANCE = scalar-default-char-expr |
2671// ASYNCHRONOUS = scalar-default-char-constant-expr |
2672// BLANK = scalar-default-char-expr |
2673// DECIMAL = scalar-default-char-expr |
2674// DELIM = scalar-default-char-expr | END = label | EOR = label |
2675// ERR = label | ID = id-variable | IOMSG = iomsg-variable |
2676// IOSTAT = scalar-int-variable | PAD = scalar-default-char-expr |
2677// POS = scalar-int-expr | REC = scalar-int-expr |
2678// ROUND = scalar-default-char-expr | SIGN = scalar-default-char-expr |
2679// SIZE = scalar-int-variable
2680WRAPPER_CLASS(EndLabel, Label);
2681WRAPPER_CLASS(EorLabel, Label);
2682struct IoControlSpec {
2683 UNION_CLASS_BOILERPLATE(IoControlSpec);
2684 struct CharExpr {
2685 ENUM_CLASS(Kind, Advance, Blank, Decimal, Delim, Pad, Round, Sign)
2686 TUPLE_CLASS_BOILERPLATE(CharExpr);
2687 std::tuple<Kind, ScalarDefaultCharExpr> t;
2688 };
2689 WRAPPER_CLASS(Asynchronous, ScalarDefaultCharConstantExpr);
2690 WRAPPER_CLASS(Pos, ScalarIntExpr);
2691 WRAPPER_CLASS(Rec, ScalarIntExpr);
2692 WRAPPER_CLASS(Size, ScalarIntVariable);
2693 std::variant<IoUnit, Format, Name, CharExpr, Asynchronous, EndLabel, EorLabel,
2694 ErrLabel, IdVariable, MsgVariable, StatVariable, Pos, Rec, Size>
2695 u;
2696};
2697
2698// R1216 input-item -> variable | io-implied-do
2699struct InputItem {
2700 UNION_CLASS_BOILERPLATE(InputItem);
2701 std::variant<Variable, common::Indirection<InputImpliedDo>> u;
2702};
2703
2704// R1210 read-stmt ->
2705// READ ( io-control-spec-list ) [input-item-list] |
2706// READ format [, input-item-list]
2707struct ReadStmt {
2708 BOILERPLATE(ReadStmt);
2709 ReadStmt(std::optional<IoUnit> &&i, std::optional<Format> &&f,
2710 std::list<IoControlSpec> &&cs, std::list<InputItem> &&its)
2711 : iounit{std::move(i)}, format{std::move(f)}, controls(std::move(cs)),
2712 items(std::move(its)) {}
2713 std::optional<IoUnit> iounit; // if first in controls without UNIT= &/or
2714 // followed by untagged format/namelist
2715 std::optional<Format> format; // if second in controls without FMT=/NML=, or
2716 // no (io-control-spec-list); might be
2717 // an untagged namelist group name
2718 std::list<IoControlSpec> controls;
2719 std::list<InputItem> items;
2720};
2721
2722// R1217 output-item -> expr | io-implied-do
2723struct OutputItem {
2724 UNION_CLASS_BOILERPLATE(OutputItem);
2725 std::variant<Expr, common::Indirection<OutputImpliedDo>> u;
2726};
2727
2728// R1211 write-stmt -> WRITE ( io-control-spec-list ) [output-item-list]
2729struct WriteStmt {
2730 BOILERPLATE(WriteStmt);
2731 WriteStmt(std::optional<IoUnit> &&i, std::optional<Format> &&f,
2732 std::list<IoControlSpec> &&cs, std::list<OutputItem> &&its)
2733 : iounit{std::move(i)}, format{std::move(f)}, controls(std::move(cs)),
2734 items(std::move(its)) {}
2735 std::optional<IoUnit> iounit; // if first in controls without UNIT= &/or
2736 // followed by untagged format/namelist
2737 std::optional<Format> format; // if second in controls without FMT=/NML=;
2738 // might be an untagged namelist group, too
2739 std::list<IoControlSpec> controls;
2740 std::list<OutputItem> items;
2741};
2742
2743// R1212 print-stmt PRINT format [, output-item-list]
2744struct PrintStmt {
2745 TUPLE_CLASS_BOILERPLATE(PrintStmt);
2746 std::tuple<Format, std::list<OutputItem>> t;
2747};
2748
2749// R1220 io-implied-do-control ->
2750// do-variable = scalar-int-expr , scalar-int-expr [, scalar-int-expr]
2751using IoImpliedDoControl = LoopBounds<DoVariable, ScalarIntExpr>;
2752
2753// R1218 io-implied-do -> ( io-implied-do-object-list , io-implied-do-control )
2754// R1219 io-implied-do-object -> input-item | output-item
2755struct InputImpliedDo {
2756 TUPLE_CLASS_BOILERPLATE(InputImpliedDo);
2757 std::tuple<std::list<InputItem>, IoImpliedDoControl> t;
2758};
2759
2760struct OutputImpliedDo {
2761 TUPLE_CLASS_BOILERPLATE(OutputImpliedDo);
2762 std::tuple<std::list<OutputItem>, IoImpliedDoControl> t;
2763};
2764
2765// R1223 wait-spec ->
2766// [UNIT =] file-unit-number | END = label | EOR = label | ERR = label |
2767// ID = scalar-int-expr | IOMSG = iomsg-variable |
2768// IOSTAT = scalar-int-variable
2769WRAPPER_CLASS(IdExpr, ScalarIntExpr);
2770struct WaitSpec {
2771 UNION_CLASS_BOILERPLATE(WaitSpec);
2772 std::variant<FileUnitNumber, EndLabel, EorLabel, ErrLabel, IdExpr,
2773 MsgVariable, StatVariable>
2774 u;
2775};
2776
2777// R1222 wait-stmt -> WAIT ( wait-spec-list )
2778WRAPPER_CLASS(WaitStmt, std::list<WaitSpec>);
2779
2780// R1227 position-spec ->
2781// [UNIT =] file-unit-number | IOMSG = iomsg-variable |
2782// IOSTAT = scalar-int-variable | ERR = label
2783// R1229 flush-spec ->
2784// [UNIT =] file-unit-number | IOSTAT = scalar-int-variable |
2785// IOMSG = iomsg-variable | ERR = label
2786struct PositionOrFlushSpec {
2787 UNION_CLASS_BOILERPLATE(PositionOrFlushSpec);
2788 std::variant<FileUnitNumber, MsgVariable, StatVariable, ErrLabel> u;
2789};
2790
2791// R1224 backspace-stmt ->
2792// BACKSPACE file-unit-number | BACKSPACE ( position-spec-list )
2793WRAPPER_CLASS(BackspaceStmt, std::list<PositionOrFlushSpec>);
2794
2795// R1225 endfile-stmt ->
2796// ENDFILE file-unit-number | ENDFILE ( position-spec-list )
2797WRAPPER_CLASS(EndfileStmt, std::list<PositionOrFlushSpec>);
2798
2799// R1226 rewind-stmt -> REWIND file-unit-number | REWIND ( position-spec-list )
2800WRAPPER_CLASS(RewindStmt, std::list<PositionOrFlushSpec>);
2801
2802// R1228 flush-stmt -> FLUSH file-unit-number | FLUSH ( flush-spec-list )
2803WRAPPER_CLASS(FlushStmt, std::list<PositionOrFlushSpec>);
2804
2805// R1231 inquire-spec ->
2806// [UNIT =] file-unit-number | FILE = file-name-expr |
2807// ACCESS = scalar-default-char-variable |
2808// ACTION = scalar-default-char-variable |
2809// ASYNCHRONOUS = scalar-default-char-variable |
2810// BLANK = scalar-default-char-variable |
2811// DECIMAL = scalar-default-char-variable |
2812// DELIM = scalar-default-char-variable |
2813// DIRECT = scalar-default-char-variable |
2814// ENCODING = scalar-default-char-variable |
2815// ERR = label | EXIST = scalar-logical-variable |
2816// FORM = scalar-default-char-variable |
2817// FORMATTED = scalar-default-char-variable |
2818// ID = scalar-int-expr | IOMSG = iomsg-variable |
2819// IOSTAT = scalar-int-variable |
2820// NAME = scalar-default-char-variable |
2821// NAMED = scalar-logical-variable |
2822// NEXTREC = scalar-int-variable | NUMBER = scalar-int-variable |
2823// OPENED = scalar-logical-variable |
2824// PAD = scalar-default-char-variable |
2825// PENDING = scalar-logical-variable | POS = scalar-int-variable |
2826// POSITION = scalar-default-char-variable |
2827// READ = scalar-default-char-variable |
2828// READWRITE = scalar-default-char-variable |
2829// RECL = scalar-int-variable | ROUND = scalar-default-char-variable |
2830// SEQUENTIAL = scalar-default-char-variable |
2831// SIGN = scalar-default-char-variable |
2832// SIZE = scalar-int-variable |
2833// STREAM = scalar-default-char-variable |
2834// STATUS = scalar-default-char-variable |
2835// UNFORMATTED = scalar-default-char-variable |
2836// WRITE = scalar-default-char-variable
2837// @ | CARRIAGECONTROL = scalar-default-char-variable
2838// | CONVERT = scalar-default-char-variable
2839// | DISPOSE = scalar-default-char-variable
2840struct InquireSpec {
2841 UNION_CLASS_BOILERPLATE(InquireSpec);
2842 struct CharVar {
2843 ENUM_CLASS(Kind, Access, Action, Asynchronous, Blank, Decimal, Delim,
2844 Direct, Encoding, Form, Formatted, Iomsg, Name, Pad, Position, Read,
2845 Readwrite, Round, Sequential, Sign, Stream, Status, Unformatted, Write,
2846 /* extensions: */ Carriagecontrol, Convert, Dispose)
2847 TUPLE_CLASS_BOILERPLATE(CharVar);
2848 std::tuple<Kind, ScalarDefaultCharVariable> t;
2849 };
2850 struct IntVar {
2851 ENUM_CLASS(Kind, Iostat, Nextrec, Number, Pos, Recl, Size)
2852 TUPLE_CLASS_BOILERPLATE(IntVar);
2853 std::tuple<Kind, ScalarIntVariable> t;
2854 };
2855 struct LogVar {
2856 ENUM_CLASS(Kind, Exist, Named, Opened, Pending)
2857 TUPLE_CLASS_BOILERPLATE(LogVar);
2858 std::tuple<Kind, Scalar<Logical<Variable>>> t;
2859 };
2860 std::variant<FileUnitNumber, FileNameExpr, CharVar, IntVar, LogVar, IdExpr,
2861 ErrLabel>
2862 u;
2863};
2864
2865// R1230 inquire-stmt ->
2866// INQUIRE ( inquire-spec-list ) |
2867// INQUIRE ( IOLENGTH = scalar-int-variable ) output-item-list
2868struct InquireStmt {
2869 UNION_CLASS_BOILERPLATE(InquireStmt);
2870 struct Iolength {
2871 TUPLE_CLASS_BOILERPLATE(Iolength);
2872 std::tuple<ScalarIntVariable, std::list<OutputItem>> t;
2873 };
2874 std::variant<std::list<InquireSpec>, Iolength> u;
2875};
2876
2877// R1301 format-stmt -> FORMAT format-specification
2878WRAPPER_CLASS(FormatStmt, format::FormatSpecification);
2879
2880// R1402 program-stmt -> PROGRAM program-name
2881WRAPPER_CLASS(ProgramStmt, Name);
2882
2883// R1403 end-program-stmt -> END [PROGRAM [program-name]]
2884WRAPPER_CLASS(EndProgramStmt, std::optional<Name>);
2885
2886// R1401 main-program ->
2887// [program-stmt] [specification-part] [execution-part]
2888// [internal-subprogram-part] end-program-stmt
2889struct MainProgram {
2890 TUPLE_CLASS_BOILERPLATE(MainProgram);
2891 std::tuple<std::optional<Statement<ProgramStmt>>, SpecificationPart,
2892 ExecutionPart, std::optional<InternalSubprogramPart>,
2893 Statement<EndProgramStmt>>
2894 t;
2895};
2896
2897// R1405 module-stmt -> MODULE module-name
2898WRAPPER_CLASS(ModuleStmt, Name);
2899
2900// R1408 module-subprogram ->
2901// function-subprogram | subroutine-subprogram |
2902// separate-module-subprogram
2903struct ModuleSubprogram {
2904 UNION_CLASS_BOILERPLATE(ModuleSubprogram);
2905 std::variant<common::Indirection<FunctionSubprogram>,
2906 common::Indirection<SubroutineSubprogram>,
2907 common::Indirection<SeparateModuleSubprogram>>
2908 u;
2909};
2910
2911// R1407 module-subprogram-part -> contains-stmt [module-subprogram]...
2912struct ModuleSubprogramPart {
2913 TUPLE_CLASS_BOILERPLATE(ModuleSubprogramPart);
2914 std::tuple<Statement<ContainsStmt>, std::list<ModuleSubprogram>> t;
2915};
2916
2917// R1406 end-module-stmt -> END [MODULE [module-name]]
2918WRAPPER_CLASS(EndModuleStmt, std::optional<Name>);
2919
2920// R1404 module ->
2921// module-stmt [specification-part] [module-subprogram-part]
2922// end-module-stmt
2923struct Module {
2924 TUPLE_CLASS_BOILERPLATE(Module);
2925 std::tuple<Statement<ModuleStmt>, SpecificationPart,
2926 std::optional<ModuleSubprogramPart>, Statement<EndModuleStmt>>
2927 t;
2928};
2929
2930// R1411 rename ->
2931// local-name => use-name |
2932// OPERATOR ( local-defined-operator ) =>
2933// OPERATOR ( use-defined-operator )
2934struct Rename {
2935 UNION_CLASS_BOILERPLATE(Rename);
2936 struct Names {
2937 TUPLE_CLASS_BOILERPLATE(Names);
2938 std::tuple<Name, Name> t;
2939 };
2940 struct Operators {
2941 TUPLE_CLASS_BOILERPLATE(Operators);
2942 std::tuple<DefinedOpName, DefinedOpName> t;
2943 };
2944 std::variant<Names, Operators> u;
2945};
2946
2947// R1418 parent-identifier -> ancestor-module-name [: parent-submodule-name]
2948struct ParentIdentifier {
2949 TUPLE_CLASS_BOILERPLATE(ParentIdentifier);
2950 std::tuple<Name, std::optional<Name>> t;
2951};
2952
2953// R1417 submodule-stmt -> SUBMODULE ( parent-identifier ) submodule-name
2954struct SubmoduleStmt {
2955 TUPLE_CLASS_BOILERPLATE(SubmoduleStmt);
2956 std::tuple<ParentIdentifier, Name> t;
2957};
2958
2959// R1419 end-submodule-stmt -> END [SUBMODULE [submodule-name]]
2960WRAPPER_CLASS(EndSubmoduleStmt, std::optional<Name>);
2961
2962// R1416 submodule ->
2963// submodule-stmt [specification-part] [module-subprogram-part]
2964// end-submodule-stmt
2965struct Submodule {
2966 TUPLE_CLASS_BOILERPLATE(Submodule);
2967 std::tuple<Statement<SubmoduleStmt>, SpecificationPart,
2968 std::optional<ModuleSubprogramPart>, Statement<EndSubmoduleStmt>>
2969 t;
2970};
2971
2972// R1421 block-data-stmt -> BLOCK DATA [block-data-name]
2973WRAPPER_CLASS(BlockDataStmt, std::optional<Name>);
2974
2975// R1422 end-block-data-stmt -> END [BLOCK DATA [block-data-name]]
2976WRAPPER_CLASS(EndBlockDataStmt, std::optional<Name>);
2977
2978// R1420 block-data -> block-data-stmt [specification-part] end-block-data-stmt
2979struct BlockData {
2980 TUPLE_CLASS_BOILERPLATE(BlockData);
2981 std::tuple<Statement<BlockDataStmt>, SpecificationPart,
2982 Statement<EndBlockDataStmt>>
2983 t;
2984};
2985
2986// R1508 generic-spec ->
2987// generic-name | OPERATOR ( defined-operator ) |
2988// ASSIGNMENT ( = ) | defined-io-generic-spec
2989// R1509 defined-io-generic-spec ->
2990// READ ( FORMATTED ) | READ ( UNFORMATTED ) |
2991// WRITE ( FORMATTED ) | WRITE ( UNFORMATTED )
2992struct GenericSpec {
2993 UNION_CLASS_BOILERPLATE(GenericSpec);
2994 EMPTY_CLASS(Assignment);
2995 EMPTY_CLASS(ReadFormatted);
2996 EMPTY_CLASS(ReadUnformatted);
2997 EMPTY_CLASS(WriteFormatted);
2998 EMPTY_CLASS(WriteUnformatted);
2999 CharBlock source;
3000 std::variant<Name, DefinedOperator, Assignment, ReadFormatted,
3001 ReadUnformatted, WriteFormatted, WriteUnformatted>
3002 u;
3003};
3004
3005// R1510 generic-stmt ->
3006// GENERIC [, access-spec] :: generic-spec => specific-procedure-list
3007struct GenericStmt {
3008 TUPLE_CLASS_BOILERPLATE(GenericStmt);
3009 std::tuple<std::optional<AccessSpec>, GenericSpec, std::list<Name>> t;
3010};
3011
3012// R1503 interface-stmt -> INTERFACE [generic-spec] | ABSTRACT INTERFACE
3013struct InterfaceStmt {
3014 UNION_CLASS_BOILERPLATE(InterfaceStmt);
3015 // Workaround for clang with libstc++10 bug
3016 InterfaceStmt(Abstract x) : u{x} {}
3017
3018 std::variant<std::optional<GenericSpec>, Abstract> u;
3019};
3020
3021// R1412 only -> generic-spec | only-use-name | rename
3022// R1413 only-use-name -> use-name
3023struct Only {
3024 UNION_CLASS_BOILERPLATE(Only);
3025 std::variant<common::Indirection<GenericSpec>, Name, Rename> u;
3026};
3027
3028// R1409 use-stmt ->
3029// USE [[, module-nature] ::] module-name [, rename-list] |
3030// USE [[, module-nature] ::] module-name , ONLY : [only-list]
3031// R1410 module-nature -> INTRINSIC | NON_INTRINSIC
3032struct UseStmt {
3033 BOILERPLATE(UseStmt);
3034 ENUM_CLASS(ModuleNature, Intrinsic, Non_Intrinsic) // R1410
3035 template <typename A>
3036 UseStmt(std::optional<ModuleNature> &&nat, Name &&n, std::list<A> &&x)
3037 : nature(std::move(nat)), moduleName(std::move(n)), u(std::move(x)) {}
3038 std::optional<ModuleNature> nature;
3039 Name moduleName;
3040 std::variant<std::list<Rename>, std::list<Only>> u;
3041};
3042
3043// R1514 proc-attr-spec ->
3044// access-spec | proc-language-binding-spec | INTENT ( intent-spec ) |
3045// OPTIONAL | POINTER | PROTECTED | SAVE
3046struct ProcAttrSpec {
3047 UNION_CLASS_BOILERPLATE(ProcAttrSpec);
3048 std::variant<AccessSpec, LanguageBindingSpec, IntentSpec, Optional, Pointer,
3049 Protected, Save>
3050 u;
3051};
3052
3053// R1512 procedure-declaration-stmt ->
3054// PROCEDURE ( [proc-interface] ) [[, proc-attr-spec]... ::]
3055// proc-decl-list
3056struct ProcedureDeclarationStmt {
3057 TUPLE_CLASS_BOILERPLATE(ProcedureDeclarationStmt);
3058 std::tuple<std::optional<ProcInterface>, std::list<ProcAttrSpec>,
3059 std::list<ProcDecl>>
3060 t;
3061};
3062
3063// R1527 prefix-spec ->
3064// declaration-type-spec | ELEMENTAL | IMPURE | MODULE |
3065// NON_RECURSIVE | PURE | RECURSIVE |
3066// (CUDA) ATTRIBUTES ( (DEVICE | GLOBAL | GRID_GLOBAL | HOST)... )
3067// LAUNCH_BOUNDS(expr-list) | CLUSTER_DIMS(expr-list)
3068struct PrefixSpec {
3069 UNION_CLASS_BOILERPLATE(PrefixSpec);
3070 EMPTY_CLASS(Elemental);
3071 EMPTY_CLASS(Impure);
3072 EMPTY_CLASS(Module);
3073 EMPTY_CLASS(Non_Recursive);
3074 EMPTY_CLASS(Pure);
3075 EMPTY_CLASS(Recursive);
3076 WRAPPER_CLASS(Attributes, std::list<common::CUDASubprogramAttrs>);
3077 WRAPPER_CLASS(Launch_Bounds, std::list<ScalarIntConstantExpr>);
3078 WRAPPER_CLASS(Cluster_Dims, std::list<ScalarIntConstantExpr>);
3079 std::variant<DeclarationTypeSpec, Elemental, Impure, Module, Non_Recursive,
3080 Pure, Recursive, Attributes, Launch_Bounds, Cluster_Dims>
3081 u;
3082};
3083
3084// R1532 suffix ->
3085// proc-language-binding-spec [RESULT ( result-name )] |
3086// RESULT ( result-name ) [proc-language-binding-spec]
3087struct Suffix {
3088 BOILERPLATE(Suffix);
3089 Suffix(LanguageBindingSpec &&lbs, std::optional<Name> &&rn)
3090 : binding(std::move(lbs)), resultName(std::move(rn)) {}
3091 Suffix(Name &&rn, std::optional<LanguageBindingSpec> &&lbs)
3092 : binding(std::move(lbs)), resultName(std::move(rn)) {}
3093 std::optional<LanguageBindingSpec> binding;
3094 std::optional<Name> resultName;
3095};
3096
3097// R1530 function-stmt ->
3098// [prefix] FUNCTION function-name ( [dummy-arg-name-list] ) [suffix]
3099// R1526 prefix -> prefix-spec [prefix-spec]...
3100// R1531 dummy-arg-name -> name
3101struct FunctionStmt {
3102 TUPLE_CLASS_BOILERPLATE(FunctionStmt);
3103 std::tuple<std::list<PrefixSpec>, Name, std::list<Name>,
3104 std::optional<Suffix>>
3105 t;
3106};
3107
3108// R1533 end-function-stmt -> END [FUNCTION [function-name]]
3109WRAPPER_CLASS(EndFunctionStmt, std::optional<Name>);
3110
3111// R1536 dummy-arg -> dummy-arg-name | *
3112struct DummyArg {
3113 UNION_CLASS_BOILERPLATE(DummyArg);
3114 std::variant<Name, Star> u;
3115};
3116
3117// R1535 subroutine-stmt ->
3118// [prefix] SUBROUTINE subroutine-name [( [dummy-arg-list] )
3119// [proc-language-binding-spec]]
3120struct SubroutineStmt {
3121 TUPLE_CLASS_BOILERPLATE(SubroutineStmt);
3122 std::tuple<std::list<PrefixSpec>, Name, std::list<DummyArg>,
3123 std::optional<LanguageBindingSpec>>
3124 t;
3125};
3126
3127// R1537 end-subroutine-stmt -> END [SUBROUTINE [subroutine-name]]
3128WRAPPER_CLASS(EndSubroutineStmt, std::optional<Name>);
3129
3130// R1505 interface-body ->
3131// function-stmt [specification-part] end-function-stmt |
3132// subroutine-stmt [specification-part] end-subroutine-stmt
3133struct InterfaceBody {
3134 UNION_CLASS_BOILERPLATE(InterfaceBody);
3135 struct Function {
3136 TUPLE_CLASS_BOILERPLATE(Function);
3137 std::tuple<Statement<FunctionStmt>, common::Indirection<SpecificationPart>,
3138 Statement<EndFunctionStmt>>
3139 t;
3140 };
3141 struct Subroutine {
3142 TUPLE_CLASS_BOILERPLATE(Subroutine);
3143 std::tuple<Statement<SubroutineStmt>,
3144 common::Indirection<SpecificationPart>, Statement<EndSubroutineStmt>>
3145 t;
3146 };
3147 std::variant<Function, Subroutine> u;
3148};
3149
3150// R1506 procedure-stmt -> [MODULE] PROCEDURE [::] specific-procedure-list
3151struct ProcedureStmt {
3152 ENUM_CLASS(Kind, ModuleProcedure, Procedure)
3153 TUPLE_CLASS_BOILERPLATE(ProcedureStmt);
3154 std::tuple<Kind, std::list<Name>> t;
3155};
3156
3157// R1502 interface-specification -> interface-body | procedure-stmt
3158struct InterfaceSpecification {
3159 UNION_CLASS_BOILERPLATE(InterfaceSpecification);
3160 std::variant<InterfaceBody, Statement<ProcedureStmt>> u;
3161};
3162
3163// R1504 end-interface-stmt -> END INTERFACE [generic-spec]
3164WRAPPER_CLASS(EndInterfaceStmt, std::optional<GenericSpec>);
3165
3166// R1501 interface-block ->
3167// interface-stmt [interface-specification]... end-interface-stmt
3168struct InterfaceBlock {
3169 TUPLE_CLASS_BOILERPLATE(InterfaceBlock);
3170 std::tuple<Statement<InterfaceStmt>, std::list<InterfaceSpecification>,
3171 Statement<EndInterfaceStmt>>
3172 t;
3173};
3174
3175// R1511 external-stmt -> EXTERNAL [::] external-name-list
3176WRAPPER_CLASS(ExternalStmt, std::list<Name>);
3177
3178// R1519 intrinsic-stmt -> INTRINSIC [::] intrinsic-procedure-name-list
3179WRAPPER_CLASS(IntrinsicStmt, std::list<Name>);
3180
3181// R1522 procedure-designator ->
3182// procedure-name | proc-component-ref | data-ref % binding-name
3183struct ProcedureDesignator {
3184 UNION_CLASS_BOILERPLATE(ProcedureDesignator);
3185 std::variant<Name, ProcComponentRef> u;
3186};
3187
3188// R1525 alt-return-spec -> * label
3189WRAPPER_CLASS(AltReturnSpec, Label);
3190
3191// R1524 actual-arg ->
3192// expr | variable | procedure-name | proc-component-ref |
3193// alt-return-spec
3194struct ActualArg {
3195 WRAPPER_CLASS(PercentRef, Variable); // %REF(v) extension
3196 WRAPPER_CLASS(PercentVal, Expr); // %VAL(x) extension
3197 UNION_CLASS_BOILERPLATE(ActualArg);
3198 ActualArg(Expr &&x) : u{common::Indirection<Expr>(std::move(x))} {}
3199 std::variant<common::Indirection<Expr>, AltReturnSpec, PercentRef, PercentVal>
3200 u;
3201};
3202
3203// R1523 actual-arg-spec -> [keyword =] actual-arg
3204struct ActualArgSpec {
3205 TUPLE_CLASS_BOILERPLATE(ActualArgSpec);
3206 std::tuple<std::optional<Keyword>, ActualArg> t;
3207};
3208
3209// R1520 function-reference -> procedure-designator
3210// ( [actual-arg-spec-list] )
3211struct Call {
3212 TUPLE_CLASS_BOILERPLATE(Call);
3213 std::tuple<ProcedureDesignator, std::list<ActualArgSpec>> t;
3214};
3215
3216struct FunctionReference {
3217 WRAPPER_CLASS_BOILERPLATE(FunctionReference, Call);
3218 CharBlock source;
3219 Designator ConvertToArrayElementRef();
3220 StructureConstructor ConvertToStructureConstructor(
3221 const semantics::DerivedTypeSpec &);
3222};
3223
3224// R1521 call-stmt -> CALL procedure-designator [ chevrons ]
3225// [( [actual-arg-spec-list] )]
3226// (CUDA) chevrons -> <<< scalar-expr, scalar-expr [,
3227// scalar-int-expr [, scalar-int-expr ] ] >>>
3228struct CallStmt {
3229 BOILERPLATE(CallStmt);
3230 struct Chevrons {
3231 TUPLE_CLASS_BOILERPLATE(Chevrons);
3232 std::tuple<ScalarExpr, ScalarExpr, std::optional<ScalarIntExpr>,
3233 std::optional<ScalarIntExpr>>
3234 t;
3235 };
3236 explicit CallStmt(ProcedureDesignator &&pd, std::optional<Chevrons> &&ch,
3237 std::list<ActualArgSpec> &&args)
3238 : call{std::move(pd), std::move(args)}, chevrons{std::move(ch)} {}
3239 Call call;
3240 std::optional<Chevrons> chevrons;
3241 CharBlock source;
3242 mutable common::ForwardOwningPointer<evaluate::ProcedureRef>
3243 typedCall; // filled by semantics
3244};
3245
3246// R1529 function-subprogram ->
3247// function-stmt [specification-part] [execution-part]
3248// [internal-subprogram-part] end-function-stmt
3249struct FunctionSubprogram {
3250 TUPLE_CLASS_BOILERPLATE(FunctionSubprogram);
3251 std::tuple<Statement<FunctionStmt>, SpecificationPart, ExecutionPart,
3252 std::optional<InternalSubprogramPart>, Statement<EndFunctionStmt>>
3253 t;
3254};
3255
3256// R1534 subroutine-subprogram ->
3257// subroutine-stmt [specification-part] [execution-part]
3258// [internal-subprogram-part] end-subroutine-stmt
3259struct SubroutineSubprogram {
3260 TUPLE_CLASS_BOILERPLATE(SubroutineSubprogram);
3261 std::tuple<Statement<SubroutineStmt>, SpecificationPart, ExecutionPart,
3262 std::optional<InternalSubprogramPart>, Statement<EndSubroutineStmt>>
3263 t;
3264};
3265
3266// R1539 mp-subprogram-stmt -> MODULE PROCEDURE procedure-name
3267WRAPPER_CLASS(MpSubprogramStmt, Name);
3268
3269// R1540 end-mp-subprogram-stmt -> END [PROCEDURE [procedure-name]]
3270WRAPPER_CLASS(EndMpSubprogramStmt, std::optional<Name>);
3271
3272// R1538 separate-module-subprogram ->
3273// mp-subprogram-stmt [specification-part] [execution-part]
3274// [internal-subprogram-part] end-mp-subprogram-stmt
3275struct SeparateModuleSubprogram {
3276 TUPLE_CLASS_BOILERPLATE(SeparateModuleSubprogram);
3277 std::tuple<Statement<MpSubprogramStmt>, SpecificationPart, ExecutionPart,
3278 std::optional<InternalSubprogramPart>, Statement<EndMpSubprogramStmt>>
3279 t;
3280};
3281
3282// R1541 entry-stmt -> ENTRY entry-name [( [dummy-arg-list] ) [suffix]]
3283struct EntryStmt {
3284 TUPLE_CLASS_BOILERPLATE(EntryStmt);
3285 std::tuple<Name, std::list<DummyArg>, std::optional<Suffix>> t;
3286};
3287
3288// R1542 return-stmt -> RETURN [scalar-int-expr]
3289WRAPPER_CLASS(ReturnStmt, std::optional<ScalarIntExpr>);
3290
3291// R1544 stmt-function-stmt ->
3292// function-name ( [dummy-arg-name-list] ) = scalar-expr
3293struct StmtFunctionStmt {
3294 TUPLE_CLASS_BOILERPLATE(StmtFunctionStmt);
3295 std::tuple<Name, std::list<Name>, Scalar<Expr>> t;
3296 Statement<ActionStmt> ConvertToAssignment();
3297};
3298
3299// Compiler directives
3300// !DIR$ IGNORE_TKR [ [(tkrdmac...)] name ]...
3301// !DIR$ LOOP COUNT (n1[, n2]...)
3302// !DIR$ name[=value] [, name[=value]]... = can be :
3303// !DIR$ <anything else>
3304struct CompilerDirective {
3305 UNION_CLASS_BOILERPLATE(CompilerDirective);
3306 struct IgnoreTKR {
3307 TUPLE_CLASS_BOILERPLATE(IgnoreTKR);
3308 std::tuple<std::optional<std::list<const char *>>, Name> t;
3309 };
3310 struct LoopCount {
3311 WRAPPER_CLASS_BOILERPLATE(LoopCount, std::list<std::uint64_t>);
3312 };
3313 struct AssumeAligned {
3314 TUPLE_CLASS_BOILERPLATE(AssumeAligned);
3315 std::tuple<common::Indirection<Designator>, uint64_t> t;
3316 };
3317 struct NameValue {
3318 TUPLE_CLASS_BOILERPLATE(NameValue);
3319 std::tuple<Name, std::optional<std::uint64_t>> t;
3320 };
3321 EMPTY_CLASS(Unrecognized);
3322 CharBlock source;
3323 std::variant<std::list<IgnoreTKR>, LoopCount, std::list<AssumeAligned>,
3324 std::list<NameValue>, Unrecognized>
3325 u;
3326};
3327
3328// (CUDA) ATTRIBUTE(attribute) [::] name-list
3329struct CUDAAttributesStmt {
3330 TUPLE_CLASS_BOILERPLATE(CUDAAttributesStmt);
3331 std::tuple<common::CUDADataAttr, std::list<Name>> t;
3332};
3333
3334// Legacy extensions
3335struct BasedPointer {
3336 TUPLE_CLASS_BOILERPLATE(BasedPointer);
3337 std::tuple<ObjectName, ObjectName, std::optional<ArraySpec>> t;
3338};
3339WRAPPER_CLASS(BasedPointerStmt, std::list<BasedPointer>);
3340
3341struct Union;
3342struct StructureDef;
3343
3344struct StructureField {
3345 UNION_CLASS_BOILERPLATE(StructureField);
3346 std::variant<Statement<DataComponentDefStmt>,
3347 common::Indirection<StructureDef>, common::Indirection<Union>>
3348 u;
3349};
3350
3351struct Map {
3352 EMPTY_CLASS(MapStmt);
3353 EMPTY_CLASS(EndMapStmt);
3354 TUPLE_CLASS_BOILERPLATE(Map);
3355 std::tuple<Statement<MapStmt>, std::list<StructureField>,
3356 Statement<EndMapStmt>>
3357 t;
3358};
3359
3360struct Union {
3361 EMPTY_CLASS(UnionStmt);
3362 EMPTY_CLASS(EndUnionStmt);
3363 TUPLE_CLASS_BOILERPLATE(Union);
3364 std::tuple<Statement<UnionStmt>, std::list<Map>, Statement<EndUnionStmt>> t;
3365};
3366
3367struct StructureStmt {
3368 TUPLE_CLASS_BOILERPLATE(StructureStmt);
3369 std::tuple<std::optional<Name>, std::list<EntityDecl>> t;
3370};
3371
3372struct StructureDef {
3373 EMPTY_CLASS(EndStructureStmt);
3374 TUPLE_CLASS_BOILERPLATE(StructureDef);
3375 std::tuple<Statement<StructureStmt>, std::list<StructureField>,
3376 Statement<EndStructureStmt>>
3377 t;
3378};
3379
3380// Old style PARAMETER statement without parentheses.
3381// Types are determined entirely from the right-hand sides, not the names.
3382WRAPPER_CLASS(OldParameterStmt, std::list<NamedConstantDef>);
3383
3384// Deprecations
3385struct ArithmeticIfStmt {
3386 TUPLE_CLASS_BOILERPLATE(ArithmeticIfStmt);
3387 std::tuple<Expr, Label, Label, Label> t;
3388};
3389
3390struct AssignStmt {
3391 TUPLE_CLASS_BOILERPLATE(AssignStmt);
3392 std::tuple<Label, Name> t;
3393};
3394
3395struct AssignedGotoStmt {
3396 TUPLE_CLASS_BOILERPLATE(AssignedGotoStmt);
3397 std::tuple<Name, std::list<Label>> t;
3398};
3399
3400WRAPPER_CLASS(PauseStmt, std::optional<StopCode>);
3401
3402// Parse tree nodes for OpenMP 4.5 directives and clauses
3403
3404// 2.5 proc-bind-clause -> PROC_BIND (MASTER | CLOSE | SPREAD)
3405struct OmpProcBindClause {
3406 ENUM_CLASS(Type, Close, Master, Spread, Primary)
3407 WRAPPER_CLASS_BOILERPLATE(OmpProcBindClause, Type);
3408};
3409
3410// 2.15.3.1 default-clause -> DEFAULT (PRIVATE | FIRSTPRIVATE | SHARED | NONE)
3411struct OmpDefaultClause {
3412 ENUM_CLASS(Type, Private, Firstprivate, Shared, None)
3413 WRAPPER_CLASS_BOILERPLATE(OmpDefaultClause, Type);
3414};
3415
3416// 2.1 Directives or clauses may accept a list or extended-list.
3417// A list item is a variable, array section or common block name (enclosed
3418// in slashes). An extended list item is a list item or a procedure Name.
3419// variable-name | / common-block / | array-sections
3420struct OmpObject {
3421 UNION_CLASS_BOILERPLATE(OmpObject);
3422 std::variant<Designator, /*common block*/ Name> u;
3423};
3424
3425WRAPPER_CLASS(OmpObjectList, std::list<OmpObject>);
3426
3427// 2.15.5.1 map-type -> TO | FROM | TOFROM | ALLOC | RELEASE | DELETE
3428struct OmpMapType {
3429 TUPLE_CLASS_BOILERPLATE(OmpMapType);
3430 EMPTY_CLASS(Always);
3431 ENUM_CLASS(Type, To, From, Tofrom, Alloc, Release, Delete)
3432 std::tuple<std::optional<Always>, Type> t;
3433};
3434
3435// 2.15.5.1 map -> MAP ([ [ALWAYS[,]] map-type : ] variable-name-list)
3436struct OmpMapClause {
3437 TUPLE_CLASS_BOILERPLATE(OmpMapClause);
3438 std::tuple<std::optional<OmpMapType>, OmpObjectList> t;
3439};
3440
3441// 2.15.5.2 defaultmap -> DEFAULTMAP (implicit-behavior[:variable-category])
3442struct OmpDefaultmapClause {
3443 TUPLE_CLASS_BOILERPLATE(OmpDefaultmapClause);
3444 ENUM_CLASS(
3445 ImplicitBehavior, Alloc, To, From, Tofrom, Firstprivate, None, Default)
3446 ENUM_CLASS(VariableCategory, Scalar, Aggregate, Allocatable, Pointer)
3447 std::tuple<ImplicitBehavior, std::optional<VariableCategory>> t;
3448};
3449
3450// 2.7.1 sched-modifier -> MONOTONIC | NONMONOTONIC | SIMD
3451struct OmpScheduleModifierType {
3452 ENUM_CLASS(ModType, Monotonic, Nonmonotonic, Simd)
3453 WRAPPER_CLASS_BOILERPLATE(OmpScheduleModifierType, ModType);
3454};
3455
3456struct OmpScheduleModifier {
3457 TUPLE_CLASS_BOILERPLATE(OmpScheduleModifier);
3458 WRAPPER_CLASS(Modifier1, OmpScheduleModifierType);
3459 WRAPPER_CLASS(Modifier2, OmpScheduleModifierType);
3460 std::tuple<Modifier1, std::optional<Modifier2>> t;
3461};
3462
3463// 2.7.1 schedule-clause -> SCHEDULE ([sched-modifier1] [, sched-modifier2]:]
3464// kind[, chunk_size])
3465struct OmpScheduleClause {
3466 TUPLE_CLASS_BOILERPLATE(OmpScheduleClause);
3467 ENUM_CLASS(ScheduleType, Static, Dynamic, Guided, Auto, Runtime)
3468 std::tuple<std::optional<OmpScheduleModifier>, ScheduleType,
3469 std::optional<ScalarIntExpr>>
3470 t;
3471};
3472
3473// device([ device-modifier :] scalar-integer-expression)
3474struct OmpDeviceClause {
3475 TUPLE_CLASS_BOILERPLATE(OmpDeviceClause);
3476 ENUM_CLASS(DeviceModifier, Ancestor, Device_Num)
3477 std::tuple<std::optional<DeviceModifier>, ScalarIntExpr> t;
3478};
3479
3480// device_type(any | host | nohost)
3481struct OmpDeviceTypeClause {
3482 ENUM_CLASS(Type, Any, Host, Nohost)
3483 WRAPPER_CLASS_BOILERPLATE(OmpDeviceTypeClause, Type);
3484};
3485
3486// 2.12 if-clause -> IF ([ directive-name-modifier :] scalar-logical-expr)
3487struct OmpIfClause {
3488 TUPLE_CLASS_BOILERPLATE(OmpIfClause);
3489 ENUM_CLASS(DirectiveNameModifier, Parallel, Simd, Target, TargetData,
3490 TargetEnterData, TargetExitData, TargetUpdate, Task, Taskloop, Teams)
3491 std::tuple<std::optional<DirectiveNameModifier>, ScalarLogicalExpr> t;
3492};
3493
3494// 2.8.1 aligned-clause -> ALIGNED (variable-name-list[ : scalar-constant])
3495struct OmpAlignedClause {
3496 TUPLE_CLASS_BOILERPLATE(OmpAlignedClause);
3497 CharBlock source;
3498 std::tuple<OmpObjectList, std::optional<ScalarIntConstantExpr>> t;
3499};
3500
3501// 2.9.5 order-clause -> ORDER ([order-modifier :]concurrent)
3502struct OmpOrderModifier {
3503 UNION_CLASS_BOILERPLATE(OmpOrderModifier);
3504 ENUM_CLASS(Kind, Reproducible, Unconstrained)
3505 std::variant<Kind> u;
3506};
3507
3508struct OmpOrderClause {
3509 TUPLE_CLASS_BOILERPLATE(OmpOrderClause);
3510 ENUM_CLASS(Type, Concurrent)
3511 std::tuple<std::optional<OmpOrderModifier>, Type> t;
3512};
3513
3514// 2.15.3.7 linear-modifier -> REF | VAL | UVAL
3515struct OmpLinearModifier {
3516 ENUM_CLASS(Type, Ref, Val, Uval)
3517 WRAPPER_CLASS_BOILERPLATE(OmpLinearModifier, Type);
3518};
3519
3520// 2.15.3.7 linear-clause -> LINEAR (linear-list[ : linear-step])
3521// linear-list -> list | linear-modifier(list)
3522struct OmpLinearClause {
3523 UNION_CLASS_BOILERPLATE(OmpLinearClause);
3524 struct WithModifier {
3525 BOILERPLATE(WithModifier);
3526 WithModifier(OmpLinearModifier &&m, std::list<Name> &&n,
3527 std::optional<ScalarIntConstantExpr> &&s)
3528 : modifier(std::move(m)), names(std::move(n)), step(std::move(s)) {}
3529 OmpLinearModifier modifier;
3530 std::list<Name> names;
3531 std::optional<ScalarIntConstantExpr> step;
3532 };
3533 struct WithoutModifier {
3534 BOILERPLATE(WithoutModifier);
3535 WithoutModifier(
3536 std::list<Name> &&n, std::optional<ScalarIntConstantExpr> &&s)
3537 : names(std::move(n)), step(std::move(s)) {}
3538 std::list<Name> names;
3539 std::optional<ScalarIntConstantExpr> step;
3540 };
3541 std::variant<WithModifier, WithoutModifier> u;
3542};
3543
3544// 2.15.3.6 reduction-identifier -> + | - | * | .AND. | .OR. | .EQV. | .NEQV. |
3545// MAX | MIN | IAND | IOR | IEOR
3546struct OmpReductionOperator {
3547 UNION_CLASS_BOILERPLATE(OmpReductionOperator);
3548 std::variant<DefinedOperator, ProcedureDesignator> u;
3549};
3550
3551// 2.15.3.6 reduction-clause -> REDUCTION (reduction-identifier:
3552// variable-name-list)
3553struct OmpReductionClause {
3554 TUPLE_CLASS_BOILERPLATE(OmpReductionClause);
3555 ENUM_CLASS(ReductionModifier, Inscan, Task, Default)
3556 std::tuple<std::optional<ReductionModifier>, OmpReductionOperator,
3557 OmpObjectList>
3558 t;
3559};
3560
3561// OMP 5.0 2.19.5.6 in_reduction-clause -> IN_REDUCTION (reduction-identifier:
3562// variable-name-list)
3563struct OmpInReductionClause {
3564 TUPLE_CLASS_BOILERPLATE(OmpInReductionClause);
3565 std::tuple<OmpReductionOperator, OmpObjectList> t;
3566};
3567
3568// OMP 5.0 2.11.4 allocate-clause -> ALLOCATE ([allocator:] variable-name-list)
3569// OMP 5.2 2.13.4 allocate-clause -> ALLOCATE ([allocate-modifier [,
3570// allocate-modifier] :]
3571// variable-name-list)
3572// allocate-modifier -> allocator | align
3573struct OmpAllocateClause {
3574 struct AllocateModifier {
3575 WRAPPER_CLASS(Allocator, ScalarIntExpr);
3576 WRAPPER_CLASS(Align, ScalarIntExpr);
3577 struct ComplexModifier {
3578 TUPLE_CLASS_BOILERPLATE(ComplexModifier);
3579 std::tuple<Allocator, Align> t;
3580 };
3581 UNION_CLASS_BOILERPLATE(AllocateModifier);
3582 std::variant<Allocator, ComplexModifier, Align> u;
3583 };
3584 TUPLE_CLASS_BOILERPLATE(OmpAllocateClause);
3585 std::tuple<std::optional<AllocateModifier>, OmpObjectList> t;
3586};
3587
3588// 2.13.9 depend-vec-length -> +/- non-negative-constant
3589struct OmpDependSinkVecLength {
3590 TUPLE_CLASS_BOILERPLATE(OmpDependSinkVecLength);
3591 std::tuple<DefinedOperator, ScalarIntConstantExpr> t;
3592};
3593
3594// 2.13.9 depend-vec -> iterator [+/- depend-vec-length],...,iterator[...]
3595struct OmpDependSinkVec {
3596 TUPLE_CLASS_BOILERPLATE(OmpDependSinkVec);
3597 std::tuple<Name, std::optional<OmpDependSinkVecLength>> t;
3598};
3599
3600// 2.13.9 depend-type -> IN | OUT | INOUT | SOURCE | SINK
3601struct OmpDependenceType {
3602 ENUM_CLASS(Type, In, Out, Inout, Source, Sink)
3603 WRAPPER_CLASS_BOILERPLATE(OmpDependenceType, Type);
3604};
3605
3606// 2.13.9 depend-clause -> DEPEND (((IN | OUT | INOUT) : variable-name-list) |
3607// SOURCE | SINK : depend-vec)
3608struct OmpDependClause {
3609 UNION_CLASS_BOILERPLATE(OmpDependClause);
3610 EMPTY_CLASS(Source);
3611 WRAPPER_CLASS(Sink, std::list<OmpDependSinkVec>);
3612 struct InOut {
3613 TUPLE_CLASS_BOILERPLATE(InOut);
3614 std::tuple<OmpDependenceType, std::list<Designator>> t;
3615 };
3616 std::variant<Source, Sink, InOut> u;
3617};
3618
3619// OMP 5.0 2.4 atomic-default-mem-order-clause ->
3620// ATOMIC_DEFAULT_MEM_ORDER (SEQ_CST | ACQ_REL |
3621// RELAXED)
3622struct OmpAtomicDefaultMemOrderClause {
3623 WRAPPER_CLASS_BOILERPLATE(
3624 OmpAtomicDefaultMemOrderClause, common::OmpAtomicDefaultMemOrderType);
3625};
3626
3627// OpenMP Clauses
3628struct OmpClause {
3629 UNION_CLASS_BOILERPLATE(OmpClause);
3630
3631#define GEN_FLANG_CLAUSE_PARSER_CLASSES
3632#include "llvm/Frontend/OpenMP/OMP.inc"
3633
3634 CharBlock source;
3635
3636 std::variant<
3637#define GEN_FLANG_CLAUSE_PARSER_CLASSES_LIST
3638#include "llvm/Frontend/OpenMP/OMP.inc"
3639 >
3640 u;
3641};
3642
3643struct OmpClauseList {
3644 WRAPPER_CLASS_BOILERPLATE(OmpClauseList, std::list<OmpClause>);
3645 CharBlock source;
3646};
3647
3648// 2.7.2 SECTIONS
3649// 2.11.2 PARALLEL SECTIONS
3650struct OmpSectionsDirective {
3651 WRAPPER_CLASS_BOILERPLATE(OmpSectionsDirective, llvm::omp::Directive);
3652 CharBlock source;
3653};
3654
3655struct OmpBeginSectionsDirective {
3656 TUPLE_CLASS_BOILERPLATE(OmpBeginSectionsDirective);
3657 std::tuple<OmpSectionsDirective, OmpClauseList> t;
3658 CharBlock source;
3659};
3660struct OmpEndSectionsDirective {
3661 TUPLE_CLASS_BOILERPLATE(OmpEndSectionsDirective);
3662 std::tuple<OmpSectionsDirective, OmpClauseList> t;
3663 CharBlock source;
3664};
3665
3666// [!$omp section]
3667// structured-block
3668// [!$omp section
3669// structured-block]
3670// ...
3671struct OpenMPSectionConstruct {
3672 WRAPPER_CLASS_BOILERPLATE(OpenMPSectionConstruct, Block);
3673 CharBlock source;
3674};
3675
3676// `OmpSectionBlocks` is a list of section constructs. The parser guarentees
3677// that the `OpenMPConstruct` here always encapsulates an
3678// `OpenMPSectionConstruct` and not any other OpenMP construct.
3679WRAPPER_CLASS(OmpSectionBlocks, std::list<OpenMPConstruct>);
3680
3681struct OpenMPSectionsConstruct {
3682 TUPLE_CLASS_BOILERPLATE(OpenMPSectionsConstruct);
3683 std::tuple<OmpBeginSectionsDirective, OmpSectionBlocks,
3684 OmpEndSectionsDirective>
3685 t;
3686};
3687
3688// OpenMP directive beginning or ending a block
3689struct OmpBlockDirective {
3690 WRAPPER_CLASS_BOILERPLATE(OmpBlockDirective, llvm::omp::Directive);
3691 CharBlock source;
3692};
3693
3694// 2.10.6 declare-target -> DECLARE TARGET (extended-list) |
3695// DECLARE TARGET [declare-target-clause[ [,]
3696// declare-target-clause]...]
3697struct OmpDeclareTargetWithList {
3698 WRAPPER_CLASS_BOILERPLATE(OmpDeclareTargetWithList, OmpObjectList);
3699 CharBlock source;
3700};
3701
3702struct OmpDeclareTargetWithClause {
3703 WRAPPER_CLASS_BOILERPLATE(OmpDeclareTargetWithClause, OmpClauseList);
3704 CharBlock source;
3705};
3706
3707struct OmpDeclareTargetSpecifier {
3708 UNION_CLASS_BOILERPLATE(OmpDeclareTargetSpecifier);
3709 std::variant<OmpDeclareTargetWithList, OmpDeclareTargetWithClause> u;
3710};
3711
3712struct OpenMPDeclareTargetConstruct {
3713 TUPLE_CLASS_BOILERPLATE(OpenMPDeclareTargetConstruct);
3714 CharBlock source;
3715 std::tuple<Verbatim, OmpDeclareTargetSpecifier> t;
3716};
3717
3718// 2.16 declare-reduction -> DECLARE REDUCTION (reduction-identifier : type-list
3719// : combiner) [initializer-clause]
3720struct OmpReductionCombiner {
3721 UNION_CLASS_BOILERPLATE(OmpReductionCombiner);
3722 WRAPPER_CLASS(FunctionCombiner, Call);
3723 std::variant<AssignmentStmt, FunctionCombiner> u;
3724};
3725
3726WRAPPER_CLASS(OmpReductionInitializerClause, Expr);
3727
3728struct OpenMPDeclareReductionConstruct {
3729 TUPLE_CLASS_BOILERPLATE(OpenMPDeclareReductionConstruct);
3730 CharBlock source;
3731 std::tuple<Verbatim, OmpReductionOperator, std::list<DeclarationTypeSpec>,
3732 OmpReductionCombiner, std::optional<OmpReductionInitializerClause>>
3733 t;
3734};
3735
3736// 2.8.2 declare-simd -> DECLARE SIMD [(proc-name)] [declare-simd-clause[ [,]
3737// declare-simd-clause]...]
3738struct OpenMPDeclareSimdConstruct {
3739 TUPLE_CLASS_BOILERPLATE(OpenMPDeclareSimdConstruct);
3740 CharBlock source;
3741 std::tuple<Verbatim, std::optional<Name>, OmpClauseList> t;
3742};
3743
3744// 2.4 requires -> REQUIRES requires-clause[ [ [,] requires-clause]...]
3745struct OpenMPRequiresConstruct {
3746 TUPLE_CLASS_BOILERPLATE(OpenMPRequiresConstruct);
3747 CharBlock source;
3748 std::tuple<Verbatim, OmpClauseList> t;
3749};
3750
3751// 2.15.2 threadprivate -> THREADPRIVATE (variable-name-list)
3752struct OpenMPThreadprivate {
3753 TUPLE_CLASS_BOILERPLATE(OpenMPThreadprivate);
3754 CharBlock source;
3755 std::tuple<Verbatim, OmpObjectList> t;
3756};
3757
3758// 2.11.3 allocate -> ALLOCATE (variable-name-list) [clause]
3759struct OpenMPDeclarativeAllocate {
3760 TUPLE_CLASS_BOILERPLATE(OpenMPDeclarativeAllocate);
3761 CharBlock source;
3762 std::tuple<Verbatim, OmpObjectList, OmpClauseList> t;
3763};
3764
3765struct OpenMPDeclarativeConstruct {
3766 UNION_CLASS_BOILERPLATE(OpenMPDeclarativeConstruct);
3767 CharBlock source;
3768 std::variant<OpenMPDeclarativeAllocate, OpenMPDeclareReductionConstruct,
3769 OpenMPDeclareSimdConstruct, OpenMPDeclareTargetConstruct,
3770 OpenMPThreadprivate, OpenMPRequiresConstruct>
3771 u;
3772};
3773
3774// 2.13.2 CRITICAL [Name] <block> END CRITICAL [Name]
3775struct OmpCriticalDirective {
3776 TUPLE_CLASS_BOILERPLATE(OmpCriticalDirective);
3777 CharBlock source;
3778 std::tuple<Verbatim, std::optional<Name>, OmpClauseList> t;
3779};
3780struct OmpEndCriticalDirective {
3781 TUPLE_CLASS_BOILERPLATE(OmpEndCriticalDirective);
3782 CharBlock source;
3783 std::tuple<Verbatim, std::optional<Name>> t;
3784};
3785struct OpenMPCriticalConstruct {
3786 TUPLE_CLASS_BOILERPLATE(OpenMPCriticalConstruct);
3787 std::tuple<OmpCriticalDirective, Block, OmpEndCriticalDirective> t;
3788};
3789
3790// 2.11.3 allocate -> ALLOCATE [(variable-name-list)] [clause]
3791// [ALLOCATE (variable-name-list) [clause] [...]]
3792// allocate-statement
3793// clause -> allocator-clause
3794struct OpenMPExecutableAllocate {
3795 TUPLE_CLASS_BOILERPLATE(OpenMPExecutableAllocate);
3796 CharBlock source;
3797 std::tuple<Verbatim, std::optional<OmpObjectList>, OmpClauseList,
3798 std::optional<std::list<OpenMPDeclarativeAllocate>>,
3799 Statement<AllocateStmt>>
3800 t;
3801};
3802
3803EMPTY_CLASS(OmpEndAllocators);
3804
3805// 6.7 Allocators construct [OpenMP 5.2]
3806// allocators-construct -> ALLOCATORS [allocate-clause [,]]
3807// allocate-stmt
3808// [omp-end-allocators-construct]
3809struct OpenMPAllocatorsConstruct {
3810 TUPLE_CLASS_BOILERPLATE(OpenMPAllocatorsConstruct);
3811 CharBlock source;
3812 std::tuple<Verbatim, OmpClauseList, Statement<AllocateStmt>,
3813 std::optional<OmpEndAllocators>>
3814 t;
3815};
3816
3817// 2.17.7 Atomic construct/2.17.8 Flush construct [OpenMP 5.0]
3818// memory-order-clause -> acq_rel
3819// release
3820// acquire
3821// seq_cst
3822// relaxed
3823struct OmpMemoryOrderClause {
3824 WRAPPER_CLASS_BOILERPLATE(OmpMemoryOrderClause, OmpClause);
3825 CharBlock source;
3826};
3827
3828// 2.17.7 Atomic construct
3829// atomic-clause -> memory-order-clause | HINT(hint-expression)
3830struct OmpAtomicClause {
3831 UNION_CLASS_BOILERPLATE(OmpAtomicClause);
3832 CharBlock source;
3833 std::variant<OmpMemoryOrderClause, OmpClause> u;
3834};
3835
3836// atomic-clause-list -> [atomic-clause, [atomic-clause], ...]
3837struct OmpAtomicClauseList {
3838 WRAPPER_CLASS_BOILERPLATE(OmpAtomicClauseList, std::list<OmpAtomicClause>);
3839 CharBlock source;
3840};
3841
3842// END ATOMIC
3843EMPTY_CLASS(OmpEndAtomic);
3844
3845// ATOMIC READ
3846struct OmpAtomicRead {
3847 TUPLE_CLASS_BOILERPLATE(OmpAtomicRead);
3848 CharBlock source;
3849 std::tuple<OmpAtomicClauseList, Verbatim, OmpAtomicClauseList,
3850 Statement<AssignmentStmt>, std::optional<OmpEndAtomic>>
3851 t;
3852};
3853
3854// ATOMIC WRITE
3855struct OmpAtomicWrite {
3856 TUPLE_CLASS_BOILERPLATE(OmpAtomicWrite);
3857 CharBlock source;
3858 std::tuple<OmpAtomicClauseList, Verbatim, OmpAtomicClauseList,
3859 Statement<AssignmentStmt>, std::optional<OmpEndAtomic>>
3860 t;
3861};
3862
3863// ATOMIC UPDATE
3864struct OmpAtomicUpdate {
3865 TUPLE_CLASS_BOILERPLATE(OmpAtomicUpdate);
3866 CharBlock source;
3867 std::tuple<OmpAtomicClauseList, Verbatim, OmpAtomicClauseList,
3868 Statement<AssignmentStmt>, std::optional<OmpEndAtomic>>
3869 t;
3870};
3871
3872// ATOMIC CAPTURE
3873struct OmpAtomicCapture {
3874 TUPLE_CLASS_BOILERPLATE(OmpAtomicCapture);
3875 CharBlock source;
3876 WRAPPER_CLASS(Stmt1, Statement<AssignmentStmt>);
3877 WRAPPER_CLASS(Stmt2, Statement<AssignmentStmt>);
3878 std::tuple<OmpAtomicClauseList, Verbatim, OmpAtomicClauseList, Stmt1, Stmt2,
3879 OmpEndAtomic>
3880 t;
3881};
3882
3883// ATOMIC
3884struct OmpAtomic {
3885 TUPLE_CLASS_BOILERPLATE(OmpAtomic);
3886 CharBlock source;
3887 std::tuple<Verbatim, OmpAtomicClauseList, Statement<AssignmentStmt>,
3888 std::optional<OmpEndAtomic>>
3889 t;
3890};
3891
3892// 2.17.7 atomic ->
3893// ATOMIC [atomic-clause-list] atomic-construct [atomic-clause-list] |
3894// ATOMIC [atomic-clause-list]
3895// atomic-construct -> READ | WRITE | UPDATE | CAPTURE
3896struct OpenMPAtomicConstruct {
3897 UNION_CLASS_BOILERPLATE(OpenMPAtomicConstruct);
3898 std::variant<OmpAtomicRead, OmpAtomicWrite, OmpAtomicCapture, OmpAtomicUpdate,
3899 OmpAtomic>
3900 u;
3901};
3902
3903// OpenMP directives that associate with loop(s)
3904struct OmpLoopDirective {
3905 WRAPPER_CLASS_BOILERPLATE(OmpLoopDirective, llvm::omp::Directive);
3906 CharBlock source;
3907};
3908
3909// 2.14.1 construct-type-clause -> PARALLEL | SECTIONS | DO | TASKGROUP
3910struct OmpCancelType {
3911 ENUM_CLASS(Type, Parallel, Sections, Do, Taskgroup)
3912 WRAPPER_CLASS_BOILERPLATE(OmpCancelType, Type);
3913 CharBlock source;
3914};
3915
3916// 2.14.2 cancellation-point -> CANCELLATION POINT construct-type-clause
3917struct OpenMPCancellationPointConstruct {
3918 TUPLE_CLASS_BOILERPLATE(OpenMPCancellationPointConstruct);
3919 CharBlock source;
3920 std::tuple<Verbatim, OmpCancelType> t;
3921};
3922
3923// 2.14.1 cancel -> CANCEL construct-type-clause [ [,] if-clause]
3924struct OpenMPCancelConstruct {
3925 TUPLE_CLASS_BOILERPLATE(OpenMPCancelConstruct);
3926 WRAPPER_CLASS(If, ScalarLogicalExpr);
3927 CharBlock source;
3928 std::tuple<Verbatim, OmpCancelType, std::optional<If>> t;
3929};
3930
3931// 2.17.8 flush -> FLUSH [memory-order-clause] [(variable-name-list)]
3932struct OpenMPFlushConstruct {
3933 TUPLE_CLASS_BOILERPLATE(OpenMPFlushConstruct);
3934 CharBlock source;
3935 std::tuple<Verbatim, std::optional<std::list<OmpMemoryOrderClause>>,
3936 std::optional<OmpObjectList>>
3937 t;
3938};
3939
3940struct OmpSimpleStandaloneDirective {
3941 WRAPPER_CLASS_BOILERPLATE(OmpSimpleStandaloneDirective, llvm::omp::Directive);
3942 CharBlock source;
3943};
3944
3945struct OpenMPSimpleStandaloneConstruct {
3946 TUPLE_CLASS_BOILERPLATE(OpenMPSimpleStandaloneConstruct);
3947 CharBlock source;
3948 std::tuple<OmpSimpleStandaloneDirective, OmpClauseList> t;
3949};
3950
3951struct OpenMPStandaloneConstruct {
3952 UNION_CLASS_BOILERPLATE(OpenMPStandaloneConstruct);
3953 CharBlock source;
3954 std::variant<OpenMPSimpleStandaloneConstruct, OpenMPFlushConstruct,
3955 OpenMPCancelConstruct, OpenMPCancellationPointConstruct>
3956 u;
3957};
3958
3959struct OmpBeginLoopDirective {
3960 TUPLE_CLASS_BOILERPLATE(OmpBeginLoopDirective);
3961 std::tuple<OmpLoopDirective, OmpClauseList> t;
3962 CharBlock source;
3963};
3964
3965struct OmpEndLoopDirective {
3966 TUPLE_CLASS_BOILERPLATE(OmpEndLoopDirective);
3967 std::tuple<OmpLoopDirective, OmpClauseList> t;
3968 CharBlock source;
3969};
3970
3971struct OmpBeginBlockDirective {
3972 TUPLE_CLASS_BOILERPLATE(OmpBeginBlockDirective);
3973 std::tuple<OmpBlockDirective, OmpClauseList> t;
3974 CharBlock source;
3975};
3976
3977struct OmpEndBlockDirective {
3978 TUPLE_CLASS_BOILERPLATE(OmpEndBlockDirective);
3979 std::tuple<OmpBlockDirective, OmpClauseList> t;
3980 CharBlock source;
3981};
3982
3983struct OpenMPBlockConstruct {
3984 TUPLE_CLASS_BOILERPLATE(OpenMPBlockConstruct);
3985 std::tuple<OmpBeginBlockDirective, Block, OmpEndBlockDirective> t;
3986};
3987
3988// OpenMP directives enclosing do loop
3989struct OpenMPLoopConstruct {
3990 TUPLE_CLASS_BOILERPLATE(OpenMPLoopConstruct);
3991 OpenMPLoopConstruct(OmpBeginLoopDirective &&a)
3992 : t({std::move(a), std::nullopt, std::nullopt}) {}
3993 std::tuple<OmpBeginLoopDirective, std::optional<DoConstruct>,
3994 std::optional<OmpEndLoopDirective>>
3995 t;
3996};
3997
3998struct OpenMPConstruct {
3999 UNION_CLASS_BOILERPLATE(OpenMPConstruct);
4000 std::variant<OpenMPStandaloneConstruct, OpenMPSectionsConstruct,
4001 OpenMPSectionConstruct, OpenMPLoopConstruct, OpenMPBlockConstruct,
4002 OpenMPAtomicConstruct, OpenMPDeclarativeAllocate,
4003 OpenMPExecutableAllocate, OpenMPAllocatorsConstruct,
4004 OpenMPCriticalConstruct>
4005 u;
4006};
4007
4008// Parse tree nodes for OpenACC 3.3 directives and clauses
4009
4010struct AccObject {
4011 UNION_CLASS_BOILERPLATE(AccObject);
4012 std::variant<Designator, /*common block*/ Name> u;
4013};
4014
4015WRAPPER_CLASS(AccObjectList, std::list<AccObject>);
4016
4017// OpenACC directive beginning or ending a block
4018struct AccBlockDirective {
4019 WRAPPER_CLASS_BOILERPLATE(AccBlockDirective, llvm::acc::Directive);
4020 CharBlock source;
4021};
4022
4023struct AccLoopDirective {
4024 WRAPPER_CLASS_BOILERPLATE(AccLoopDirective, llvm::acc::Directive);
4025 CharBlock source;
4026};
4027
4028struct AccStandaloneDirective {
4029 WRAPPER_CLASS_BOILERPLATE(AccStandaloneDirective, llvm::acc::Directive);
4030 CharBlock source;
4031};
4032
4033// 2.11 Combined constructs
4034struct AccCombinedDirective {
4035 WRAPPER_CLASS_BOILERPLATE(AccCombinedDirective, llvm::acc::Directive);
4036 CharBlock source;
4037};
4038
4039struct AccDeclarativeDirective {
4040 WRAPPER_CLASS_BOILERPLATE(AccDeclarativeDirective, llvm::acc::Directive);
4041 CharBlock source;
4042};
4043
4044// OpenACC Clauses
4045struct AccBindClause {
4046 UNION_CLASS_BOILERPLATE(AccBindClause);
4047 std::variant<Name, ScalarDefaultCharExpr> u;
4048 CharBlock source;
4049};
4050
4051struct AccDefaultClause {
4052 WRAPPER_CLASS_BOILERPLATE(AccDefaultClause, llvm::acc::DefaultValue);
4053 CharBlock source;
4054};
4055
4056struct AccDataModifier {
4057 ENUM_CLASS(Modifier, ReadOnly, Zero)
4058 WRAPPER_CLASS_BOILERPLATE(AccDataModifier, Modifier);
4059 CharBlock source;
4060};
4061
4062struct AccObjectListWithModifier {
4063 TUPLE_CLASS_BOILERPLATE(AccObjectListWithModifier);
4064 std::tuple<std::optional<AccDataModifier>, AccObjectList> t;
4065};
4066
4067// 2.5.15: + | * | max | min | iand | ior | ieor | .and. | .or. | .eqv. | .neqv.
4068struct AccReductionOperator {
4069 ENUM_CLASS(
4070 Operator, Plus, Multiply, Max, Min, Iand, Ior, Ieor, And, Or, Eqv, Neqv)
4071 WRAPPER_CLASS_BOILERPLATE(AccReductionOperator, Operator);
4072 CharBlock source;
4073};
4074
4075struct AccObjectListWithReduction {
4076 TUPLE_CLASS_BOILERPLATE(AccObjectListWithReduction);
4077 std::tuple<AccReductionOperator, AccObjectList> t;
4078};
4079
4080struct AccWaitArgument {
4081 TUPLE_CLASS_BOILERPLATE(AccWaitArgument);
4082 std::tuple<std::optional<ScalarIntExpr>, std::list<ScalarIntExpr>> t;
4083};
4084
4085struct AccDeviceTypeExpr {
4086 WRAPPER_CLASS_BOILERPLATE(
4087 AccDeviceTypeExpr, Fortran::common::OpenACCDeviceType);
4088 CharBlock source;
4089};
4090
4091struct AccDeviceTypeExprList {
4092 WRAPPER_CLASS_BOILERPLATE(
4093 AccDeviceTypeExprList, std::list<AccDeviceTypeExpr>);
4094};
4095
4096struct AccTileExpr {
4097 TUPLE_CLASS_BOILERPLATE(AccTileExpr);
4098 CharBlock source;
4099 std::tuple<std::optional<ScalarIntConstantExpr>> t; // if null then *
4100};
4101
4102struct AccTileExprList {
4103 WRAPPER_CLASS_BOILERPLATE(AccTileExprList, std::list<AccTileExpr>);
4104};
4105
4106struct AccSizeExpr {
4107 WRAPPER_CLASS_BOILERPLATE(AccSizeExpr, std::optional<ScalarIntExpr>);
4108};
4109
4110struct AccSizeExprList {
4111 WRAPPER_CLASS_BOILERPLATE(AccSizeExprList, std::list<AccSizeExpr>);
4112};
4113
4114struct AccSelfClause {
4115 UNION_CLASS_BOILERPLATE(AccSelfClause);
4116 std::variant<std::optional<ScalarLogicalExpr>, AccObjectList> u;
4117 CharBlock source;
4118};
4119
4120// num, dim, static
4121struct AccGangArg {
4122 UNION_CLASS_BOILERPLATE(AccGangArg);
4123 WRAPPER_CLASS(Num, ScalarIntExpr);
4124 WRAPPER_CLASS(Dim, ScalarIntExpr);
4125 WRAPPER_CLASS(Static, AccSizeExpr);
4126 std::variant<Num, Dim, Static> u;
4127 CharBlock source;
4128};
4129
4130struct AccGangArgList {
4131 WRAPPER_CLASS_BOILERPLATE(AccGangArgList, std::list<AccGangArg>);
4132};
4133
4134struct AccCollapseArg {
4135 TUPLE_CLASS_BOILERPLATE(AccCollapseArg);
4136 std::tuple<bool, ScalarIntConstantExpr> t;
4137};
4138
4139struct AccClause {
4140 UNION_CLASS_BOILERPLATE(AccClause);
4141
4142#define GEN_FLANG_CLAUSE_PARSER_CLASSES
4143#include "llvm/Frontend/OpenACC/ACC.inc"
4144
4145 CharBlock source;
4146
4147 std::variant<
4148#define GEN_FLANG_CLAUSE_PARSER_CLASSES_LIST
4149#include "llvm/Frontend/OpenACC/ACC.inc"
4150 >
4151 u;
4152};
4153
4154struct AccClauseList {
4155 WRAPPER_CLASS_BOILERPLATE(AccClauseList, std::list<AccClause>);
4156 CharBlock source;
4157};
4158
4159struct OpenACCRoutineConstruct {
4160 TUPLE_CLASS_BOILERPLATE(OpenACCRoutineConstruct);
4161 CharBlock source;
4162 std::tuple<Verbatim, std::optional<Name>, AccClauseList> t;
4163};
4164
4165struct OpenACCCacheConstruct {
4166 TUPLE_CLASS_BOILERPLATE(OpenACCCacheConstruct);
4167 CharBlock source;
4168 std::tuple<Verbatim, AccObjectListWithModifier> t;
4169};
4170
4171struct OpenACCWaitConstruct {
4172 TUPLE_CLASS_BOILERPLATE(OpenACCWaitConstruct);
4173 CharBlock source;
4174 std::tuple<Verbatim, std::optional<AccWaitArgument>, AccClauseList> t;
4175};
4176
4177struct AccBeginLoopDirective {
4178 TUPLE_CLASS_BOILERPLATE(AccBeginLoopDirective);
4179 std::tuple<AccLoopDirective, AccClauseList> t;
4180 CharBlock source;
4181};
4182
4183struct AccBeginBlockDirective {
4184 TUPLE_CLASS_BOILERPLATE(AccBeginBlockDirective);
4185 CharBlock source;
4186 std::tuple<AccBlockDirective, AccClauseList> t;
4187};
4188
4189struct AccEndBlockDirective {
4190 CharBlock source;
4191 WRAPPER_CLASS_BOILERPLATE(AccEndBlockDirective, AccBlockDirective);
4192};
4193
4194// ACC END ATOMIC
4195EMPTY_CLASS(AccEndAtomic);
4196
4197// ACC ATOMIC READ
4198struct AccAtomicRead {
4199 TUPLE_CLASS_BOILERPLATE(AccAtomicRead);
4200 std::tuple<Verbatim, Statement<AssignmentStmt>, std::optional<AccEndAtomic>>
4201 t;
4202};
4203
4204// ACC ATOMIC WRITE
4205struct AccAtomicWrite {
4206 TUPLE_CLASS_BOILERPLATE(AccAtomicWrite);
4207 std::tuple<Verbatim, Statement<AssignmentStmt>, std::optional<AccEndAtomic>>
4208 t;
4209};
4210
4211// ACC ATOMIC UPDATE
4212struct AccAtomicUpdate {
4213 TUPLE_CLASS_BOILERPLATE(AccAtomicUpdate);
4214 std::tuple<std::optional<Verbatim>, Statement<AssignmentStmt>,
4215 std::optional<AccEndAtomic>>
4216 t;
4217};
4218
4219// ACC ATOMIC CAPTURE
4220struct AccAtomicCapture {
4221 TUPLE_CLASS_BOILERPLATE(AccAtomicCapture);
4222 WRAPPER_CLASS(Stmt1, Statement<AssignmentStmt>);
4223 WRAPPER_CLASS(Stmt2, Statement<AssignmentStmt>);
4224 std::tuple<Verbatim, Stmt1, Stmt2, AccEndAtomic> t;
4225};
4226
4227struct OpenACCAtomicConstruct {
4228 UNION_CLASS_BOILERPLATE(OpenACCAtomicConstruct);
4229 std::variant<AccAtomicRead, AccAtomicWrite, AccAtomicCapture, AccAtomicUpdate>
4230 u;
4231 CharBlock source;
4232};
4233
4234struct OpenACCBlockConstruct {
4235 TUPLE_CLASS_BOILERPLATE(OpenACCBlockConstruct);
4236 std::tuple<AccBeginBlockDirective, Block, AccEndBlockDirective> t;
4237};
4238
4239struct OpenACCStandaloneDeclarativeConstruct {
4240 TUPLE_CLASS_BOILERPLATE(OpenACCStandaloneDeclarativeConstruct);
4241 CharBlock source;
4242 std::tuple<AccDeclarativeDirective, AccClauseList> t;
4243};
4244
4245struct AccBeginCombinedDirective {
4246 TUPLE_CLASS_BOILERPLATE(AccBeginCombinedDirective);
4247 CharBlock source;
4248 std::tuple<AccCombinedDirective, AccClauseList> t;
4249};
4250
4251struct AccEndCombinedDirective {
4252 WRAPPER_CLASS_BOILERPLATE(AccEndCombinedDirective, AccCombinedDirective);
4253 CharBlock source;
4254};
4255
4256struct OpenACCCombinedConstruct {
4257 TUPLE_CLASS_BOILERPLATE(OpenACCCombinedConstruct);
4258 CharBlock source;
4259 OpenACCCombinedConstruct(AccBeginCombinedDirective &&a)
4260 : t({std::move(a), std::nullopt, std::nullopt}) {}
4261 std::tuple<AccBeginCombinedDirective, std::optional<DoConstruct>,
4262 std::optional<AccEndCombinedDirective>>
4263 t;
4264};
4265
4266struct OpenACCDeclarativeConstruct {
4267 UNION_CLASS_BOILERPLATE(OpenACCDeclarativeConstruct);
4268 CharBlock source;
4269 std::variant<OpenACCStandaloneDeclarativeConstruct, OpenACCRoutineConstruct>
4270 u;
4271};
4272
4273// OpenACC directives enclosing do loop
4274EMPTY_CLASS(AccEndLoop);
4275struct OpenACCLoopConstruct {
4276 TUPLE_CLASS_BOILERPLATE(OpenACCLoopConstruct);
4277 OpenACCLoopConstruct(AccBeginLoopDirective &&a)
4278 : t({std::move(a), std::nullopt, std::nullopt}) {}
4279 std::tuple<AccBeginLoopDirective, std::optional<DoConstruct>,
4280 std::optional<AccEndLoop>>
4281 t;
4282};
4283
4284struct OpenACCEndConstruct {
4285 WRAPPER_CLASS_BOILERPLATE(OpenACCEndConstruct, llvm::acc::Directive);
4286 CharBlock source;
4287};
4288
4289struct OpenACCStandaloneConstruct {
4290 TUPLE_CLASS_BOILERPLATE(OpenACCStandaloneConstruct);
4291 CharBlock source;
4292 std::tuple<AccStandaloneDirective, AccClauseList> t;
4293};
4294
4295struct OpenACCConstruct {
4296 UNION_CLASS_BOILERPLATE(OpenACCConstruct);
4297 std::variant<OpenACCBlockConstruct, OpenACCCombinedConstruct,
4298 OpenACCLoopConstruct, OpenACCStandaloneConstruct, OpenACCCacheConstruct,
4299 OpenACCWaitConstruct, OpenACCAtomicConstruct, OpenACCEndConstruct>
4300 u;
4301};
4302
4303// CUF-kernel-do-construct ->
4304// !$CUF KERNEL DO [ (scalar-int-constant-expr) ] <<< grid, block [, stream]
4305// >>> do-construct
4306// star-or-expr -> * | scalar-int-expr
4307// grid -> * | scalar-int-expr | ( star-or-expr-list )
4308// block -> * | scalar-int-expr | ( star-or-expr-list )
4309// stream -> 0, scalar-int-expr | STREAM = scalar-int-expr
4310struct CUFKernelDoConstruct {
4311 TUPLE_CLASS_BOILERPLATE(CUFKernelDoConstruct);
4312 WRAPPER_CLASS(StarOrExpr, std::optional<ScalarIntExpr>);
4313 struct Directive {
4314 TUPLE_CLASS_BOILERPLATE(Directive);
4315 CharBlock source;
4316 std::tuple<std::optional<ScalarIntConstantExpr>, std::list<StarOrExpr>,
4317 std::list<StarOrExpr>, std::optional<ScalarIntExpr>>
4318 t;
4319 };
4320 std::tuple<Directive, std::optional<DoConstruct>> t;
4321};
4322
4323} // namespace Fortran::parser
4324#endif // FORTRAN_PARSER_PARSE_TREE_H_
4325

Warning: This file is not a C or C++ file. It does not have highlighting.

source code of flang/include/flang/Parser/parse-tree.h