1 2 /* Compiler implementation of the D programming language 3 * Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved 4 * written by Walter Bright 5 * https://www.digitalmars.com 6 * Distributed under the Boost Software License, Version 1.0. 7 * https://www.boost.org/LICENSE_1_0.txt 8 * https://github.com/dlang/dmd/blob/master/src/dmd/statement.h 9 */ 10 11 #pragma once 12 13 #include "arraytypes.h" 14 #include "ast_node.h" 15 #include "dsymbol.h" 16 #include "visitor.h" 17 #include "tokens.h" 18 19 struct Scope; 20 class Expression; 21 class LabelDsymbol; 22 class Identifier; 23 class IfStatement; 24 class ExpStatement; 25 class DefaultStatement; 26 class VarDeclaration; 27 class Condition; 28 class ErrorStatement; 29 class ReturnStatement; 30 class CompoundStatement; 31 class Parameter; 32 class StaticAssert; 33 class AsmStatement; 34 class GotoStatement; 35 class ScopeStatement; 36 class TryCatchStatement; 37 class TryFinallyStatement; 38 class CaseStatement; 39 class DefaultStatement; 40 class LabelStatement; 41 class StaticForeach; 42 43 // Back end 44 struct code; 45 46 /* How a statement exits; this is returned by blockExit() 47 */ 48 enum BE : int32_t 49 { 50 BEnone = 0, 51 BEfallthru = 1, 52 BEthrow = 2, 53 BEreturn = 4, 54 BEgoto = 8, 55 BEhalt = 0x10, 56 BEbreak = 0x20, 57 BEcontinue = 0x40, 58 BEerrthrow = 0x80, 59 BEany = (BEfallthru | BEthrow | BEreturn | BEgoto | BEhalt) 60 }; 61 62 typedef unsigned char STMT; 63 enum 64 { 65 STMTerror, 66 STMTpeel, 67 STMTexp, STMTdtorExp, 68 STMTcompile, 69 STMTcompound, STMTcompoundDeclaration, STMTcompoundAsm, 70 STMTunrolledLoop, 71 STMTscope, 72 STMTforwarding, 73 STMTwhile, 74 STMTdo, 75 STMTfor, 76 STMTforeach, 77 STMTforeachRange, 78 STMTif, 79 STMTconditional, 80 STMTstaticForeach, 81 STMTpragma, 82 STMTstaticAssert, 83 STMTswitch, 84 STMTcase, 85 STMTcaseRange, 86 STMTdefault, 87 STMTgotoDefault, 88 STMTgotoCase, 89 STMTswitchError, 90 STMTreturn, 91 STMTbreak, 92 STMTcontinue, 93 STMTsynchronized, 94 STMTwith, 95 STMTtryCatch, 96 STMTtryFinally, 97 STMTscopeGuard, 98 STMTthrow, 99 STMTdebug, 100 STMTgoto, 101 STMTlabel, 102 STMTasm, STMTinlineAsm, STMTgccAsm, 103 STMTimport 104 }; 105 106 class Statement : public ASTNode 107 { 108 public: 109 Loc loc; 110 STMT stmt; 111 112 virtual Statement *syntaxCopy(); 113 114 const char *toChars() const; 115 116 void error(const char *format, ...); 117 void warning(const char *format, ...); 118 void deprecation(const char *format, ...); 119 virtual Statement *getRelatedLabeled() { return this; } 120 virtual bool hasBreak() const; 121 virtual bool hasContinue() const; 122 bool usesEH(); 123 bool comeFrom(); 124 bool hasCode(); 125 virtual Statement *last(); 126 127 virtual ReturnStatement *endsWithReturnStatement() { return NULL; } 128 129 ErrorStatement *isErrorStatement() { return stmt == STMTerror ? (ErrorStatement*)this : NULL; } 130 ScopeStatement *isScopeStatement() { return stmt == STMTscope ? (ScopeStatement*)this : NULL; } 131 ExpStatement *isExpStatement() { return stmt == STMTexp ? (ExpStatement*)this : NULL; } 132 CompoundStatement *isCompoundStatement() { return stmt == STMTcompound ? (CompoundStatement*)this : NULL; } 133 ReturnStatement *isReturnStatement() { return stmt == STMTreturn ? (ReturnStatement*)this : NULL; } 134 IfStatement *isIfStatement() { return stmt == STMTif ? (IfStatement*)this : NULL; } 135 ConditionalStatement *isConditionalStatement() { return stmt == STMTconditional ? (ConditionalStatement*)this : NULL; } 136 StaticForeachStatement *isStaticForeachStatement() { return stmt == STMTstaticForeach ? (StaticForeachStatement*)this : NULL; } 137 CaseStatement *isCaseStatement() { return stmt == STMTcase ? (CaseStatement*)this : NULL; } 138 DefaultStatement *isDefaultStatement() { return stmt == STMTdefault ? (DefaultStatement*)this : NULL; } 139 LabelStatement *isLabelStatement() { return stmt == STMTlabel ? (LabelStatement*)this : NULL; } 140 GotoDefaultStatement *isGotoDefaultStatement() { return stmt == STMTgotoDefault ? (GotoDefaultStatement*)this : NULL; } 141 GotoCaseStatement *isGotoCaseStatement() { return stmt == STMTgotoCase ? (GotoCaseStatement*)this : NULL; } 142 BreakStatement *isBreakStatement() { return stmt == STMTbreak ? (BreakStatement*)this : NULL; } 143 DtorExpStatement *isDtorExpStatement() { return stmt == STMTdtorExp ? (DtorExpStatement*)this : NULL; } 144 CompileStatement *isCompileStatement() { return stmt == STMTcompile ? (CompileStatement*)this : NULL; } 145 ForwardingStatement *isForwardingStatement() { return stmt == STMTforwarding ? (ForwardingStatement*)this : NULL; } 146 DoStatement *isDoStatement() { return stmt == STMTdo ? (DoStatement*)this : NULL; } 147 ForStatement *isForStatement() { return stmt == STMTfor ? (ForStatement*)this : NULL; } 148 ForeachStatement *isForeachStatement() { return stmt == STMTforeach ? (ForeachStatement*)this : NULL; } 149 SwitchStatement *isSwitchStatement() { return stmt == STMTswitch ? (SwitchStatement*)this : NULL; } 150 ContinueStatement *isContinueStatement() { return stmt == STMTcontinue ? (ContinueStatement*)this : NULL; } 151 WithStatement *isWithStatement() { return stmt == STMTwith ? (WithStatement*)this : NULL; } 152 TryCatchStatement *isTryCatchStatement() { return stmt == STMTtryCatch ? (TryCatchStatement*)this : NULL; } 153 ThrowStatement *isThrowStatement() { return stmt == STMTthrow ? (ThrowStatement*)this : NULL; } 154 DebugStatement *isDebugStatement() { return stmt == STMTdebug ? (DebugStatement*)this : NULL; } 155 TryFinallyStatement *isTryFinallyStatement() { return stmt == STMTtryFinally ? (TryFinallyStatement*)this : NULL; } 156 ScopeGuardStatement *isScopeGuardStatement() { return stmt == STMTscopeGuard ? (ScopeGuardStatement*)this : NULL; } 157 SwitchErrorStatement *isSwitchErrorStatement() { return stmt == STMTswitchError ? (SwitchErrorStatement*)this : NULL; } 158 UnrolledLoopStatement *isUnrolledLoopStatement() { return stmt == STMTunrolledLoop ? (UnrolledLoopStatement*)this : NULL; } 159 ForeachRangeStatement *isForeachRangeStatement() { return stmt == STMTforeachRange ? (ForeachRangeStatement*)this : NULL; } 160 CompoundDeclarationStatement *isCompoundDeclarationStatement() { return stmt == STMTcompoundDeclaration ? (CompoundDeclarationStatement*)this : NULL; } 161 162 void accept(Visitor *v) { v->visit(this); } 163 }; 164 165 /** Any Statement that fails semantic() or has a component that is an ErrorExp or 166 * a TypeError should return an ErrorStatement from semantic(). 167 */ 168 class ErrorStatement : public Statement 169 { 170 public: 171 ErrorStatement *syntaxCopy(); 172 173 void accept(Visitor *v) { v->visit(this); } 174 }; 175 176 class PeelStatement : public Statement 177 { 178 public: 179 Statement *s; 180 181 void accept(Visitor *v) { v->visit(this); } 182 }; 183 184 class ExpStatement : public Statement 185 { 186 public: 187 Expression *exp; 188 189 static ExpStatement *create(const Loc &loc, Expression *exp); 190 ExpStatement *syntaxCopy(); 191 192 void accept(Visitor *v) { v->visit(this); } 193 }; 194 195 class DtorExpStatement : public ExpStatement 196 { 197 public: 198 /* Wraps an expression that is the destruction of 'var' 199 */ 200 201 VarDeclaration *var; 202 203 DtorExpStatement *syntaxCopy(); 204 void accept(Visitor *v) { v->visit(this); } 205 }; 206 207 class CompileStatement : public Statement 208 { 209 public: 210 Expressions *exps; 211 212 CompileStatement *syntaxCopy(); 213 void accept(Visitor *v) { v->visit(this); } 214 }; 215 216 class CompoundStatement : public Statement 217 { 218 public: 219 Statements *statements; 220 221 static CompoundStatement *create(const Loc &loc, Statement *s1, Statement *s2); 222 CompoundStatement *syntaxCopy(); 223 ReturnStatement *endsWithReturnStatement(); 224 Statement *last(); 225 226 void accept(Visitor *v) { v->visit(this); } 227 }; 228 229 class CompoundDeclarationStatement : public CompoundStatement 230 { 231 public: 232 CompoundDeclarationStatement *syntaxCopy(); 233 void accept(Visitor *v) { v->visit(this); } 234 }; 235 236 /* The purpose of this is so that continue will go to the next 237 * of the statements, and break will go to the end of the statements. 238 */ 239 class UnrolledLoopStatement : public Statement 240 { 241 public: 242 Statements *statements; 243 244 UnrolledLoopStatement *syntaxCopy(); 245 bool hasBreak() const; 246 bool hasContinue() const; 247 248 void accept(Visitor *v) { v->visit(this); } 249 }; 250 251 class ScopeStatement : public Statement 252 { 253 public: 254 Statement *statement; 255 Loc endloc; // location of closing curly bracket 256 257 ScopeStatement *syntaxCopy(); 258 ReturnStatement *endsWithReturnStatement(); 259 bool hasBreak() const; 260 bool hasContinue() const; 261 262 void accept(Visitor *v) { v->visit(this); } 263 }; 264 265 class ForwardingStatement : public Statement 266 { 267 public: 268 ForwardingScopeDsymbol *sym; 269 Statement *statement; 270 271 ForwardingStatement *syntaxCopy(); 272 void accept(Visitor *v) { v->visit(this); } 273 }; 274 275 class WhileStatement : public Statement 276 { 277 public: 278 Parameter *param; 279 Expression *condition; 280 Statement *_body; 281 Loc endloc; // location of closing curly bracket 282 283 WhileStatement *syntaxCopy(); 284 bool hasBreak() const; 285 bool hasContinue() const; 286 287 void accept(Visitor *v) { v->visit(this); } 288 }; 289 290 class DoStatement : public Statement 291 { 292 public: 293 Statement *_body; 294 Expression *condition; 295 Loc endloc; // location of ';' after while 296 297 DoStatement *syntaxCopy(); 298 bool hasBreak() const; 299 bool hasContinue() const; 300 301 void accept(Visitor *v) { v->visit(this); } 302 }; 303 304 class ForStatement : public Statement 305 { 306 public: 307 Statement *_init; 308 Expression *condition; 309 Expression *increment; 310 Statement *_body; 311 Loc endloc; // location of closing curly bracket 312 313 // When wrapped in try/finally clauses, this points to the outermost one, 314 // which may have an associated label. Internal break/continue statements 315 // treat that label as referring to this loop. 316 Statement *relatedLabeled; 317 318 ForStatement *syntaxCopy(); 319 Statement *getRelatedLabeled() { return relatedLabeled ? relatedLabeled : this; } 320 bool hasBreak() const; 321 bool hasContinue() const; 322 323 void accept(Visitor *v) { v->visit(this); } 324 }; 325 326 class ForeachStatement : public Statement 327 { 328 public: 329 TOK op; // TOKforeach or TOKforeach_reverse 330 Parameters *parameters; // array of Parameter*'s 331 Expression *aggr; 332 Statement *_body; 333 Loc endloc; // location of closing curly bracket 334 335 VarDeclaration *key; 336 VarDeclaration *value; 337 338 FuncDeclaration *func; // function we're lexically in 339 340 Statements *cases; // put breaks, continues, gotos and returns here 341 ScopeStatements *gotos; // forward referenced goto's go here 342 343 ForeachStatement *syntaxCopy(); 344 bool hasBreak() const; 345 bool hasContinue() const; 346 347 void accept(Visitor *v) { v->visit(this); } 348 }; 349 350 class ForeachRangeStatement : public Statement 351 { 352 public: 353 TOK op; // TOKforeach or TOKforeach_reverse 354 Parameter *prm; // loop index variable 355 Expression *lwr; 356 Expression *upr; 357 Statement *_body; 358 Loc endloc; // location of closing curly bracket 359 360 VarDeclaration *key; 361 362 ForeachRangeStatement *syntaxCopy(); 363 bool hasBreak() const; 364 bool hasContinue() const; 365 366 void accept(Visitor *v) { v->visit(this); } 367 }; 368 369 class IfStatement : public Statement 370 { 371 public: 372 Parameter *prm; 373 Expression *condition; 374 Statement *ifbody; 375 Statement *elsebody; 376 VarDeclaration *match; // for MatchExpression results 377 Loc endloc; // location of closing curly bracket 378 379 IfStatement *syntaxCopy(); 380 381 void accept(Visitor *v) { v->visit(this); } 382 }; 383 384 class ConditionalStatement : public Statement 385 { 386 public: 387 Condition *condition; 388 Statement *ifbody; 389 Statement *elsebody; 390 391 ConditionalStatement *syntaxCopy(); 392 393 void accept(Visitor *v) { v->visit(this); } 394 }; 395 396 class StaticForeachStatement : public Statement 397 { 398 public: 399 StaticForeach *sfe; 400 401 StaticForeachStatement *syntaxCopy(); 402 403 void accept(Visitor *v) { v->visit(this); } 404 }; 405 406 class PragmaStatement : public Statement 407 { 408 public: 409 Identifier *ident; 410 Expressions *args; // array of Expression's 411 Statement *_body; 412 413 PragmaStatement *syntaxCopy(); 414 415 void accept(Visitor *v) { v->visit(this); } 416 }; 417 418 class StaticAssertStatement : public Statement 419 { 420 public: 421 StaticAssert *sa; 422 423 StaticAssertStatement *syntaxCopy(); 424 425 void accept(Visitor *v) { v->visit(this); } 426 }; 427 428 class SwitchStatement : public Statement 429 { 430 public: 431 Expression *condition; 432 Statement *_body; 433 bool isFinal; 434 435 DefaultStatement *sdefault; 436 Statement *tryBody; // set to TryCatchStatement or TryFinallyStatement if in _body portion 437 TryFinallyStatement *tf; 438 GotoCaseStatements gotoCases; // array of unresolved GotoCaseStatement's 439 CaseStatements *cases; // array of CaseStatement's 440 int hasNoDefault; // !=0 if no default statement 441 int hasVars; // !=0 if has variable case values 442 VarDeclaration *lastVar; 443 444 SwitchStatement *syntaxCopy(); 445 bool hasBreak() const; 446 447 void accept(Visitor *v) { v->visit(this); } 448 }; 449 450 class CaseStatement : public Statement 451 { 452 public: 453 Expression *exp; 454 Statement *statement; 455 456 int index; // which case it is (since we sort this) 457 VarDeclaration *lastVar; 458 void* extra; // for use by Statement_toIR() 459 460 CaseStatement *syntaxCopy(); 461 462 void accept(Visitor *v) { v->visit(this); } 463 }; 464 465 466 class CaseRangeStatement : public Statement 467 { 468 public: 469 Expression *first; 470 Expression *last; 471 Statement *statement; 472 473 CaseRangeStatement *syntaxCopy(); 474 void accept(Visitor *v) { v->visit(this); } 475 }; 476 477 478 class DefaultStatement : public Statement 479 { 480 public: 481 Statement *statement; 482 VarDeclaration *lastVar; 483 484 DefaultStatement *syntaxCopy(); 485 486 void accept(Visitor *v) { v->visit(this); } 487 }; 488 489 class GotoDefaultStatement : public Statement 490 { 491 public: 492 SwitchStatement *sw; 493 494 GotoDefaultStatement *syntaxCopy(); 495 496 void accept(Visitor *v) { v->visit(this); } 497 }; 498 499 class GotoCaseStatement : public Statement 500 { 501 public: 502 Expression *exp; // NULL, or which case to goto 503 CaseStatement *cs; // case statement it resolves to 504 505 GotoCaseStatement *syntaxCopy(); 506 507 void accept(Visitor *v) { v->visit(this); } 508 }; 509 510 class SwitchErrorStatement : public Statement 511 { 512 public: 513 Expression *exp; 514 515 void accept(Visitor *v) { v->visit(this); } 516 }; 517 518 class ReturnStatement : public Statement 519 { 520 public: 521 Expression *exp; 522 size_t caseDim; 523 524 ReturnStatement *syntaxCopy(); 525 526 ReturnStatement *endsWithReturnStatement() { return this; } 527 void accept(Visitor *v) { v->visit(this); } 528 }; 529 530 class BreakStatement : public Statement 531 { 532 public: 533 Identifier *ident; 534 535 BreakStatement *syntaxCopy(); 536 537 void accept(Visitor *v) { v->visit(this); } 538 }; 539 540 class ContinueStatement : public Statement 541 { 542 public: 543 Identifier *ident; 544 545 ContinueStatement *syntaxCopy(); 546 547 void accept(Visitor *v) { v->visit(this); } 548 }; 549 550 class SynchronizedStatement : public Statement 551 { 552 public: 553 Expression *exp; 554 Statement *_body; 555 556 SynchronizedStatement *syntaxCopy(); 557 bool hasBreak() const; 558 bool hasContinue() const; 559 560 void accept(Visitor *v) { v->visit(this); } 561 }; 562 563 class WithStatement : public Statement 564 { 565 public: 566 Expression *exp; 567 Statement *_body; 568 VarDeclaration *wthis; 569 Loc endloc; 570 571 WithStatement *syntaxCopy(); 572 573 void accept(Visitor *v) { v->visit(this); } 574 }; 575 576 class TryCatchStatement : public Statement 577 { 578 public: 579 Statement *_body; 580 Catches *catches; 581 582 Statement *tryBody; /// set to enclosing TryCatchStatement or TryFinallyStatement if in _body portion 583 584 TryCatchStatement *syntaxCopy(); 585 bool hasBreak() const; 586 587 void accept(Visitor *v) { v->visit(this); } 588 }; 589 590 class Catch : public RootObject 591 { 592 public: 593 Loc loc; 594 Type *type; 595 Identifier *ident; 596 Statement *handler; 597 598 VarDeclaration *var; 599 // set if semantic processing errors 600 bool errors; 601 602 // was generated by the compiler, 603 // wasn't present in source code 604 bool internalCatch; 605 606 Catch *syntaxCopy(); 607 }; 608 609 class TryFinallyStatement : public Statement 610 { 611 public: 612 Statement *_body; 613 Statement *finalbody; 614 615 Statement *tryBody; // set to enclosing TryCatchStatement or TryFinallyStatement if in _body portion 616 bool bodyFallsThru; // true if _body falls through to finally 617 618 static TryFinallyStatement *create(const Loc &loc, Statement *body, Statement *finalbody); 619 TryFinallyStatement *syntaxCopy(); 620 bool hasBreak() const; 621 bool hasContinue() const; 622 623 void accept(Visitor *v) { v->visit(this); } 624 }; 625 626 class ScopeGuardStatement : public Statement 627 { 628 public: 629 TOK tok; 630 Statement *statement; 631 632 ScopeGuardStatement *syntaxCopy(); 633 634 void accept(Visitor *v) { v->visit(this); } 635 }; 636 637 class ThrowStatement : public Statement 638 { 639 public: 640 Expression *exp; 641 // was generated by the compiler, 642 // wasn't present in source code 643 bool internalThrow; 644 645 ThrowStatement *syntaxCopy(); 646 647 void accept(Visitor *v) { v->visit(this); } 648 }; 649 650 class DebugStatement : public Statement 651 { 652 public: 653 Statement *statement; 654 655 DebugStatement *syntaxCopy(); 656 void accept(Visitor *v) { v->visit(this); } 657 }; 658 659 class GotoStatement : public Statement 660 { 661 public: 662 Identifier *ident; 663 LabelDsymbol *label; 664 Statement *tryBody; /// set to enclosing TryCatchStatement or TryFinallyStatement if in _body portion 665 TryFinallyStatement *tf; 666 ScopeGuardStatement *os; 667 VarDeclaration *lastVar; 668 669 GotoStatement *syntaxCopy(); 670 671 void accept(Visitor *v) { v->visit(this); } 672 }; 673 674 class LabelStatement : public Statement 675 { 676 public: 677 Identifier *ident; 678 Statement *statement; 679 Statement *tryBody; /// set to enclosing TryCatchStatement or TryFinallyStatement if in _body portion 680 TryFinallyStatement *tf; 681 ScopeGuardStatement *os; 682 VarDeclaration *lastVar; 683 Statement *gotoTarget; // interpret 684 void* extra; // used by Statement_toIR() 685 bool breaks; // someone did a 'break ident' 686 687 LabelStatement *syntaxCopy(); 688 689 void accept(Visitor *v) { v->visit(this); } 690 }; 691 692 class LabelDsymbol : public Dsymbol 693 { 694 public: 695 LabelStatement *statement; 696 697 bool deleted; // set if rewritten to return in foreach delegate 698 bool iasm; // set if used by inline assembler 699 700 static LabelDsymbol *create(Identifier *ident); 701 LabelDsymbol *isLabel(); 702 void accept(Visitor *v) { v->visit(this); } 703 }; 704 705 Statement* asmSemantic(AsmStatement *s, Scope *sc); 706 707 class AsmStatement : public Statement 708 { 709 public: 710 Token *tokens; 711 712 AsmStatement *syntaxCopy(); 713 void accept(Visitor *v) { v->visit(this); } 714 }; 715 716 class InlineAsmStatement : public AsmStatement 717 { 718 public: 719 code *asmcode; 720 unsigned asmalign; // alignment of this statement 721 unsigned regs; // mask of registers modified (must match regm_t in back end) 722 bool refparam; // true if function parameter is referenced 723 bool naked; // true if function is to be naked 724 725 InlineAsmStatement *syntaxCopy(); 726 void accept(Visitor *v) { v->visit(this); } 727 }; 728 729 // A GCC asm statement - assembler instructions with D expression operands 730 class GccAsmStatement : public AsmStatement 731 { 732 public: 733 StorageClass stc; // attributes of the asm {} block 734 Expression *insn; // string expression that is the template for assembler code 735 Expressions *args; // input and output operands of the statement 736 unsigned outputargs; // of the operands in 'args', the number of output operands 737 Identifiers *names; // list of symbolic names for the operands 738 Expressions *constraints; // list of string constants specifying constraints on operands 739 Expressions *clobbers; // list of string constants specifying clobbers and scratch registers 740 Identifiers *labels; // list of goto labels 741 GotoStatements *gotos; // of the goto labels, the equivalent statements they represent 742 743 GccAsmStatement *syntaxCopy(); 744 void accept(Visitor *v) { v->visit(this); } 745 }; 746 747 // a complete asm {} block 748 class CompoundAsmStatement : public CompoundStatement 749 { 750 public: 751 StorageClass stc; // postfix attributes like nothrow/pure/@trusted 752 753 CompoundAsmStatement *syntaxCopy(); 754 755 void accept(Visitor *v) { v->visit(this); } 756 }; 757 758 class ImportStatement : public Statement 759 { 760 public: 761 Dsymbols *imports; // Array of Import's 762 763 ImportStatement *syntaxCopy(); 764 765 void accept(Visitor *v) { v->visit(this); } 766 }; 767