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