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