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