1 /** 2 * Defines AST nodes for statements. 3 * 4 * Specification: $(LINK2 https://dlang.org/spec/statement.html, Statements) 5 * 6 * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved 7 * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright) 8 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 9 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/statement.d, _statement.d) 10 * Documentation: https://dlang.org/phobos/dmd_statement.html 11 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/statement.d 12 */ 13 14 module dmd.statement; 15 16 import core.stdc.stdarg; 17 import core.stdc.stdio; 18 19 import dmd.aggregate; 20 import dmd.arraytypes; 21 import dmd.attrib; 22 import dmd.astcodegen; 23 import dmd.ast_node; 24 import dmd.gluelayer; 25 import dmd.canthrow; 26 import dmd.cond; 27 import dmd.dclass; 28 import dmd.declaration; 29 import dmd.denum; 30 import dmd.dimport; 31 import dmd.dscope; 32 import dmd.dsymbol; 33 import dmd.dsymbolsem; 34 import dmd.dtemplate; 35 import dmd.errors; 36 import dmd.expression; 37 import dmd.expressionsem; 38 import dmd.func; 39 import dmd.globals; 40 import dmd.hdrgen; 41 import dmd.id; 42 import dmd.identifier; 43 import dmd.dinterpret; 44 import dmd.mtype; 45 import dmd.parse; 46 import dmd.root.outbuffer; 47 import dmd.root.rootobject; 48 import dmd.sapply; 49 import dmd.sideeffect; 50 import dmd.staticassert; 51 import dmd.tokens; 52 import dmd.visitor; 53 54 /** 55 * Returns: 56 * `TypeIdentifier` corresponding to `object.Throwable` 57 */ 58 TypeIdentifier getThrowable() 59 { 60 auto tid = new TypeIdentifier(Loc.initial, Id.empty); 61 tid.addIdent(Id.object); 62 tid.addIdent(Id.Throwable); 63 return tid; 64 } 65 66 /** 67 * Returns: 68 * TypeIdentifier corresponding to `object.Exception` 69 */ 70 TypeIdentifier getException() 71 { 72 auto tid = new TypeIdentifier(Loc.initial, Id.empty); 73 tid.addIdent(Id.object); 74 tid.addIdent(Id.Exception); 75 return tid; 76 } 77 78 /******************************** 79 * Identify Statement types with this enum rather than 80 * virtual functions. 81 */ 82 83 enum STMT : ubyte 84 { 85 Error, 86 Peel, 87 Exp, DtorExp, 88 Compile, 89 Compound, CompoundDeclaration, CompoundAsm, 90 UnrolledLoop, 91 Scope, 92 Forwarding, 93 While, 94 Do, 95 For, 96 Foreach, 97 ForeachRange, 98 If, 99 Conditional, 100 StaticForeach, 101 Pragma, 102 StaticAssert, 103 Switch, 104 Case, 105 CaseRange, 106 Default, 107 GotoDefault, 108 GotoCase, 109 SwitchError, 110 Return, 111 Break, 112 Continue, 113 Synchronized, 114 With, 115 TryCatch, 116 TryFinally, 117 ScopeGuard, 118 Throw, 119 Debug, 120 Goto, 121 Label, 122 Asm, InlineAsm, GccAsm, 123 Import, 124 } 125 126 127 /*********************************************************** 128 * Specification: http://dlang.org/spec/statement.html 129 */ 130 extern (C++) abstract class Statement : ASTNode 131 { 132 const Loc loc; 133 const STMT stmt; 134 135 override final DYNCAST dyncast() const 136 { 137 return DYNCAST.statement; 138 } 139 140 final extern (D) this(const ref Loc loc, STMT stmt) 141 { 142 this.loc = loc; 143 this.stmt = stmt; 144 // If this is an in{} contract scope statement (skip for determining 145 // inlineStatus of a function body for header content) 146 } 147 148 Statement syntaxCopy() 149 { 150 assert(0); 151 } 152 153 /************************************* 154 * Do syntax copy of an array of Statement's. 155 */ 156 static Statements* arraySyntaxCopy(Statements* a) 157 { 158 Statements* b = null; 159 if (a) 160 { 161 b = a.copy(); 162 foreach (i, s; *a) 163 { 164 (*b)[i] = s ? s.syntaxCopy() : null; 165 } 166 } 167 return b; 168 } 169 170 override final const(char)* toChars() const 171 { 172 HdrGenState hgs; 173 OutBuffer buf; 174 .toCBuffer(this, &buf, &hgs); 175 buf.writeByte(0); 176 return buf.extractSlice().ptr; 177 } 178 179 static if (__VERSION__ < 2092) 180 { 181 final void error(const(char)* format, ...) 182 { 183 va_list ap; 184 va_start(ap, format); 185 .verror(loc, format, ap); 186 va_end(ap); 187 } 188 189 final void warning(const(char)* format, ...) 190 { 191 va_list ap; 192 va_start(ap, format); 193 .vwarning(loc, format, ap); 194 va_end(ap); 195 } 196 197 final void deprecation(const(char)* format, ...) 198 { 199 va_list ap; 200 va_start(ap, format); 201 .vdeprecation(loc, format, ap); 202 va_end(ap); 203 } 204 } 205 else 206 { 207 pragma(printf) final void error(const(char)* format, ...) 208 { 209 va_list ap; 210 va_start(ap, format); 211 .verror(loc, format, ap); 212 va_end(ap); 213 } 214 215 pragma(printf) final void warning(const(char)* format, ...) 216 { 217 va_list ap; 218 va_start(ap, format); 219 .vwarning(loc, format, ap); 220 va_end(ap); 221 } 222 223 pragma(printf) final void deprecation(const(char)* format, ...) 224 { 225 va_list ap; 226 va_start(ap, format); 227 .vdeprecation(loc, format, ap); 228 va_end(ap); 229 } 230 } 231 232 Statement getRelatedLabeled() 233 { 234 return this; 235 } 236 237 /**************************** 238 * Determine if an enclosed `break` would apply to this 239 * statement, such as if it is a loop or switch statement. 240 * Returns: 241 * `true` if it does 242 */ 243 bool hasBreak() const pure nothrow 244 { 245 //printf("Statement::hasBreak()\n"); 246 return false; 247 } 248 249 /**************************** 250 * Determine if an enclosed `continue` would apply to this 251 * statement, such as if it is a loop statement. 252 * Returns: 253 * `true` if it does 254 */ 255 bool hasContinue() const pure nothrow 256 { 257 return false; 258 } 259 260 /********************************** 261 * Returns: 262 * `true` if statement uses exception handling 263 */ 264 final bool usesEH() 265 { 266 extern (C++) final class UsesEH : StoppableVisitor 267 { 268 alias visit = typeof(super).visit; 269 public: 270 override void visit(Statement s) 271 { 272 } 273 274 override void visit(TryCatchStatement s) 275 { 276 stop = true; 277 } 278 279 override void visit(TryFinallyStatement s) 280 { 281 stop = true; 282 } 283 284 override void visit(ScopeGuardStatement s) 285 { 286 stop = true; 287 } 288 289 override void visit(SynchronizedStatement s) 290 { 291 stop = true; 292 } 293 } 294 295 scope UsesEH ueh = new UsesEH(); 296 return walkPostorder(this, ueh); 297 } 298 299 /********************************** 300 * Returns: 301 * `true` if statement 'comes from' somewhere else, like a goto 302 */ 303 final bool comeFrom() 304 { 305 extern (C++) final class ComeFrom : StoppableVisitor 306 { 307 alias visit = typeof(super).visit; 308 public: 309 override void visit(Statement s) 310 { 311 } 312 313 override void visit(CaseStatement s) 314 { 315 stop = true; 316 } 317 318 override void visit(DefaultStatement s) 319 { 320 stop = true; 321 } 322 323 override void visit(LabelStatement s) 324 { 325 stop = true; 326 } 327 328 override void visit(AsmStatement s) 329 { 330 stop = true; 331 } 332 } 333 334 scope ComeFrom cf = new ComeFrom(); 335 return walkPostorder(this, cf); 336 } 337 338 /********************************** 339 * Returns: 340 * `true` if statement has executable code. 341 */ 342 final bool hasCode() 343 { 344 extern (C++) final class HasCode : StoppableVisitor 345 { 346 alias visit = typeof(super).visit; 347 public: 348 override void visit(Statement s) 349 { 350 stop = true; 351 } 352 353 override void visit(ExpStatement s) 354 { 355 if (s.exp !is null) 356 { 357 stop = s.exp.hasCode(); 358 } 359 } 360 361 override void visit(CompoundStatement s) 362 { 363 } 364 365 override void visit(ScopeStatement s) 366 { 367 } 368 369 override void visit(ImportStatement s) 370 { 371 } 372 } 373 374 scope HasCode hc = new HasCode(); 375 return walkPostorder(this, hc); 376 } 377 378 /**************************************** 379 * If this statement has code that needs to run in a finally clause 380 * at the end of the current scope, return that code in the form of 381 * a Statement. 382 * Params: 383 * sc = context 384 * sentry = set to code executed upon entry to the scope 385 * sexception = set to code executed upon exit from the scope via exception 386 * sfinally = set to code executed in finally block 387 * Returns: 388 * code to be run in the finally clause 389 */ 390 Statement scopeCode(Scope* sc, Statement* sentry, Statement* sexception, Statement* sfinally) 391 { 392 //printf("Statement::scopeCode()\n"); 393 *sentry = null; 394 *sexception = null; 395 *sfinally = null; 396 return this; 397 } 398 399 /********************************* 400 * Flatten out the scope by presenting the statement 401 * as an array of statements. 402 * Params: 403 * sc = context 404 * Returns: 405 * The array of `Statements`, or `null` if no flattening necessary 406 */ 407 Statements* flatten(Scope* sc) 408 { 409 return null; 410 } 411 412 /******************************* 413 * Find last statement in a sequence of statements. 414 * Returns: 415 * the last statement, or `null` if there isn't one 416 */ 417 inout(Statement) last() inout nothrow pure 418 { 419 return this; 420 } 421 422 /************************** 423 * Support Visitor Pattern 424 * Params: 425 * v = visitor 426 */ 427 override void accept(Visitor v) 428 { 429 v.visit(this); 430 } 431 432 /************************************ 433 * Does this statement end with a return statement? 434 * 435 * I.e. is it a single return statement or some compound statement 436 * that unconditionally hits a return statement. 437 * Returns: 438 * return statement it ends with, otherwise null 439 */ 440 pure nothrow @nogc 441 inout(ReturnStatement) endsWithReturnStatement() inout { return null; } 442 443 final pure inout nothrow @nogc: 444 445 /******************** 446 * A cheaper method of doing downcasting of Statements. 447 * Returns: 448 * the downcast statement if it can be downcasted, otherwise `null` 449 */ 450 inout(ErrorStatement) isErrorStatement() { return stmt == STMT.Error ? cast(typeof(return))this : null; } 451 inout(ScopeStatement) isScopeStatement() { return stmt == STMT.Scope ? cast(typeof(return))this : null; } 452 inout(ExpStatement) isExpStatement() { return stmt == STMT.Exp ? cast(typeof(return))this : null; } 453 inout(CompoundStatement) isCompoundStatement() { return stmt == STMT.Compound ? cast(typeof(return))this : null; } 454 inout(ReturnStatement) isReturnStatement() { return stmt == STMT.Return ? cast(typeof(return))this : null; } 455 inout(IfStatement) isIfStatement() { return stmt == STMT.If ? cast(typeof(return))this : null; } 456 inout(CaseStatement) isCaseStatement() { return stmt == STMT.Case ? cast(typeof(return))this : null; } 457 inout(DefaultStatement) isDefaultStatement() { return stmt == STMT.Default ? cast(typeof(return))this : null; } 458 inout(LabelStatement) isLabelStatement() { return stmt == STMT.Label ? cast(typeof(return))this : null; } 459 inout(GotoStatement) isGotoStatement() { return stmt == STMT.Goto ? cast(typeof(return))this : null; } 460 inout(GotoDefaultStatement) isGotoDefaultStatement() { return stmt == STMT.GotoDefault ? cast(typeof(return))this : null; } 461 inout(GotoCaseStatement) isGotoCaseStatement() { return stmt == STMT.GotoCase ? cast(typeof(return))this : null; } 462 inout(BreakStatement) isBreakStatement() { return stmt == STMT.Break ? cast(typeof(return))this : null; } 463 inout(DtorExpStatement) isDtorExpStatement() { return stmt == STMT.DtorExp ? cast(typeof(return))this : null; } 464 inout(ForwardingStatement) isForwardingStatement() { return stmt == STMT.Forwarding ? cast(typeof(return))this : null; } 465 inout(DoStatement) isDoStatement() { return stmt == STMT.Do ? cast(typeof(return))this : null; } 466 inout(WhileStatement) isWhileStatement() { return stmt == STMT.While ? cast(typeof(return))this : null; } 467 inout(ForStatement) isForStatement() { return stmt == STMT.For ? cast(typeof(return))this : null; } 468 inout(ForeachStatement) isForeachStatement() { return stmt == STMT.Foreach ? cast(typeof(return))this : null; } 469 inout(SwitchStatement) isSwitchStatement() { return stmt == STMT.Switch ? cast(typeof(return))this : null; } 470 inout(ContinueStatement) isContinueStatement() { return stmt == STMT.Continue ? cast(typeof(return))this : null; } 471 inout(WithStatement) isWithStatement() { return stmt == STMT.With ? cast(typeof(return))this : null; } 472 inout(TryCatchStatement) isTryCatchStatement() { return stmt == STMT.TryCatch ? cast(typeof(return))this : null; } 473 inout(ThrowStatement) isThrowStatement() { return stmt == STMT.Throw ? cast(typeof(return))this : null; } 474 inout(TryFinallyStatement) isTryFinallyStatement() { return stmt == STMT.TryFinally ? cast(typeof(return))this : null; } 475 inout(SwitchErrorStatement) isSwitchErrorStatement() { return stmt == STMT.SwitchError ? cast(typeof(return))this : null; } 476 inout(UnrolledLoopStatement) isUnrolledLoopStatement() { return stmt == STMT.UnrolledLoop ? cast(typeof(return))this : null; } 477 inout(ForeachRangeStatement) isForeachRangeStatement() { return stmt == STMT.ForeachRange ? cast(typeof(return))this : null; } 478 inout(CompoundDeclarationStatement) isCompoundDeclarationStatement() { return stmt == STMT.CompoundDeclaration ? cast(typeof(return))this : null; } 479 } 480 481 /*********************************************************** 482 * Any Statement that fails semantic() or has a component that is an ErrorExp or 483 * a TypeError should return an ErrorStatement from semantic(). 484 */ 485 extern (C++) final class ErrorStatement : Statement 486 { 487 extern (D) this() 488 { 489 super(Loc.initial, STMT.Error); 490 assert(global.gaggedErrors || global.errors); 491 } 492 493 override ErrorStatement syntaxCopy() 494 { 495 return this; 496 } 497 498 override void accept(Visitor v) 499 { 500 v.visit(this); 501 } 502 } 503 504 /*********************************************************** 505 */ 506 extern (C++) final class PeelStatement : Statement 507 { 508 Statement s; 509 510 extern (D) this(Statement s) 511 { 512 super(s.loc, STMT.Peel); 513 this.s = s; 514 } 515 516 override void accept(Visitor v) 517 { 518 v.visit(this); 519 } 520 } 521 522 /*********************************************************** 523 * Convert TemplateMixin members (== Dsymbols) to Statements. 524 */ 525 private Statement toStatement(Dsymbol s) 526 { 527 extern (C++) final class ToStmt : Visitor 528 { 529 alias visit = Visitor.visit; 530 public: 531 Statement result; 532 533 Statement visitMembers(Loc loc, Dsymbols* a) 534 { 535 if (!a) 536 return null; 537 538 auto statements = new Statements(); 539 foreach (s; *a) 540 { 541 statements.push(toStatement(s)); 542 } 543 return new CompoundStatement(loc, statements); 544 } 545 546 override void visit(Dsymbol s) 547 { 548 .error(Loc.initial, "Internal Compiler Error: cannot mixin %s `%s`\n", s.kind(), s.toChars()); 549 result = new ErrorStatement(); 550 } 551 552 override void visit(TemplateMixin tm) 553 { 554 auto a = new Statements(); 555 foreach (m; *tm.members) 556 { 557 Statement s = toStatement(m); 558 if (s) 559 a.push(s); 560 } 561 result = new CompoundStatement(tm.loc, a); 562 } 563 564 /* An actual declaration symbol will be converted to DeclarationExp 565 * with ExpStatement. 566 */ 567 Statement declStmt(Dsymbol s) 568 { 569 auto de = new DeclarationExp(s.loc, s); 570 de.type = Type.tvoid; // avoid repeated semantic 571 return new ExpStatement(s.loc, de); 572 } 573 574 override void visit(VarDeclaration d) 575 { 576 result = declStmt(d); 577 } 578 579 override void visit(AggregateDeclaration d) 580 { 581 result = declStmt(d); 582 } 583 584 override void visit(FuncDeclaration d) 585 { 586 result = declStmt(d); 587 } 588 589 override void visit(EnumDeclaration d) 590 { 591 result = declStmt(d); 592 } 593 594 override void visit(AliasDeclaration d) 595 { 596 result = declStmt(d); 597 } 598 599 override void visit(TemplateDeclaration d) 600 { 601 result = declStmt(d); 602 } 603 604 /* All attributes have been already picked by the semantic analysis of 605 * 'bottom' declarations (function, struct, class, etc). 606 * So we don't have to copy them. 607 */ 608 override void visit(StorageClassDeclaration d) 609 { 610 result = visitMembers(d.loc, d.decl); 611 } 612 613 override void visit(DeprecatedDeclaration d) 614 { 615 result = visitMembers(d.loc, d.decl); 616 } 617 618 override void visit(LinkDeclaration d) 619 { 620 result = visitMembers(d.loc, d.decl); 621 } 622 623 override void visit(VisibilityDeclaration d) 624 { 625 result = visitMembers(d.loc, d.decl); 626 } 627 628 override void visit(AlignDeclaration d) 629 { 630 result = visitMembers(d.loc, d.decl); 631 } 632 633 override void visit(UserAttributeDeclaration d) 634 { 635 result = visitMembers(d.loc, d.decl); 636 } 637 638 override void visit(ForwardingAttribDeclaration d) 639 { 640 result = visitMembers(d.loc, d.decl); 641 } 642 643 override void visit(StaticAssert s) 644 { 645 } 646 647 override void visit(Import s) 648 { 649 } 650 651 override void visit(PragmaDeclaration d) 652 { 653 } 654 655 override void visit(ConditionalDeclaration d) 656 { 657 result = visitMembers(d.loc, d.include(null)); 658 } 659 660 override void visit(StaticForeachDeclaration d) 661 { 662 assert(d.sfe && !!d.sfe.aggrfe ^ !!d.sfe.rangefe); 663 result = visitMembers(d.loc, d.include(null)); 664 } 665 666 override void visit(CompileDeclaration d) 667 { 668 result = visitMembers(d.loc, d.include(null)); 669 } 670 } 671 672 if (!s) 673 return null; 674 675 scope ToStmt v = new ToStmt(); 676 s.accept(v); 677 return v.result; 678 } 679 680 /*********************************************************** 681 * https://dlang.org/spec/statement.html#ExpressionStatement 682 */ 683 extern (C++) class ExpStatement : Statement 684 { 685 Expression exp; 686 687 final extern (D) this(const ref Loc loc, Expression exp) 688 { 689 super(loc, STMT.Exp); 690 this.exp = exp; 691 } 692 693 final extern (D) this(const ref Loc loc, Expression exp, STMT stmt) 694 { 695 super(loc, stmt); 696 this.exp = exp; 697 } 698 699 final extern (D) this(const ref Loc loc, Dsymbol declaration) 700 { 701 super(loc, STMT.Exp); 702 this.exp = new DeclarationExp(loc, declaration); 703 } 704 705 static ExpStatement create(Loc loc, Expression exp) 706 { 707 return new ExpStatement(loc, exp); 708 } 709 710 override ExpStatement syntaxCopy() 711 { 712 return new ExpStatement(loc, exp ? exp.syntaxCopy() : null); 713 } 714 715 override final Statement scopeCode(Scope* sc, Statement* sentry, Statement* sexception, Statement* sfinally) 716 { 717 //printf("ExpStatement::scopeCode()\n"); 718 719 *sentry = null; 720 *sexception = null; 721 *sfinally = null; 722 723 if (exp && exp.op == TOK.declaration) 724 { 725 auto de = cast(DeclarationExp)exp; 726 auto v = de.declaration.isVarDeclaration(); 727 if (v && !v.isDataseg()) 728 { 729 if (v.needsScopeDtor()) 730 { 731 *sfinally = new DtorExpStatement(loc, v.edtor, v); 732 v.storage_class |= STC.nodtor; // don't add in dtor again 733 } 734 } 735 } 736 return this; 737 } 738 739 override final Statements* flatten(Scope* sc) 740 { 741 /* https://issues.dlang.org/show_bug.cgi?id=14243 742 * expand template mixin in statement scope 743 * to handle variable destructors. 744 */ 745 if (exp && exp.op == TOK.declaration) 746 { 747 Dsymbol d = (cast(DeclarationExp)exp).declaration; 748 if (TemplateMixin tm = d.isTemplateMixin()) 749 { 750 Expression e = exp.expressionSemantic(sc); 751 if (e.op == TOK.error || tm.errors) 752 { 753 auto a = new Statements(); 754 a.push(new ErrorStatement()); 755 return a; 756 } 757 assert(tm.members); 758 759 Statement s = toStatement(tm); 760 version (none) 761 { 762 OutBuffer buf; 763 buf.doindent = 1; 764 HdrGenState hgs; 765 hgs.hdrgen = true; 766 toCBuffer(s, &buf, &hgs); 767 printf("tm ==> s = %s\n", buf.peekChars()); 768 } 769 auto a = new Statements(); 770 a.push(s); 771 return a; 772 } 773 } 774 return null; 775 } 776 777 override void accept(Visitor v) 778 { 779 v.visit(this); 780 } 781 } 782 783 /*********************************************************** 784 */ 785 extern (C++) final class DtorExpStatement : ExpStatement 786 { 787 // Wraps an expression that is the destruction of 'var' 788 VarDeclaration var; 789 790 extern (D) this(const ref Loc loc, Expression exp, VarDeclaration var) 791 { 792 super(loc, exp, STMT.DtorExp); 793 this.var = var; 794 } 795 796 override DtorExpStatement syntaxCopy() 797 { 798 return new DtorExpStatement(loc, exp ? exp.syntaxCopy() : null, var); 799 } 800 801 override void accept(Visitor v) 802 { 803 v.visit(this); 804 } 805 } 806 807 /*********************************************************** 808 * https://dlang.org/spec/statement.html#mixin-statement 809 */ 810 extern (C++) final class CompileStatement : Statement 811 { 812 Expressions* exps; 813 814 extern (D) this(const ref Loc loc, Expression exp) 815 { 816 Expressions* exps = new Expressions(); 817 exps.push(exp); 818 this(loc, exps); 819 } 820 821 extern (D) this(const ref Loc loc, Expressions* exps) 822 { 823 super(loc, STMT.Compile); 824 this.exps = exps; 825 } 826 827 override CompileStatement syntaxCopy() 828 { 829 return new CompileStatement(loc, Expression.arraySyntaxCopy(exps)); 830 } 831 832 private Statements* compileIt(Scope* sc) 833 { 834 //printf("CompileStatement::compileIt() %s\n", exp.toChars()); 835 836 auto errorStatements() 837 { 838 auto a = new Statements(); 839 a.push(new ErrorStatement()); 840 return a; 841 } 842 843 844 OutBuffer buf; 845 if (expressionsToString(buf, sc, exps)) 846 return errorStatements(); 847 848 const errors = global.errors; 849 const len = buf.length; 850 buf.writeByte(0); 851 const str = buf.extractSlice()[0 .. len]; 852 scope p = new Parser!ASTCodegen(loc, sc._module, str, false); 853 p.nextToken(); 854 855 auto a = new Statements(); 856 while (p.token.value != TOK.endOfFile) 857 { 858 Statement s = p.parseStatement(ParseStatementFlags.semi | ParseStatementFlags.curlyScope); 859 p.reportDiagnostics(); 860 if (!s || global.errors != errors) 861 return errorStatements(); 862 a.push(s); 863 } 864 return a; 865 } 866 867 override Statements* flatten(Scope* sc) 868 { 869 //printf("CompileStatement::flatten() %s\n", exp.toChars()); 870 return compileIt(sc); 871 } 872 873 override void accept(Visitor v) 874 { 875 v.visit(this); 876 } 877 } 878 879 /*********************************************************** 880 */ 881 extern (C++) class CompoundStatement : Statement 882 { 883 Statements* statements; 884 885 /** 886 * Construct a `CompoundStatement` using an already existing 887 * array of `Statement`s 888 * 889 * Params: 890 * loc = Instantiation information 891 * statements = An array of `Statement`s, that will referenced by this class 892 */ 893 final extern (D) this(const ref Loc loc, Statements* statements) 894 { 895 super(loc, STMT.Compound); 896 this.statements = statements; 897 } 898 899 final extern (D) this(const ref Loc loc, Statements* statements, STMT stmt) 900 { 901 super(loc, stmt); 902 this.statements = statements; 903 } 904 905 /** 906 * Construct a `CompoundStatement` from an array of `Statement`s 907 * 908 * Params: 909 * loc = Instantiation information 910 * sts = A variadic array of `Statement`s, that will copied in this class 911 * The entries themselves will not be copied. 912 */ 913 final extern (D) this(const ref Loc loc, Statement[] sts...) 914 { 915 super(loc, STMT.Compound); 916 statements = new Statements(); 917 statements.reserve(sts.length); 918 foreach (s; sts) 919 statements.push(s); 920 } 921 922 static CompoundStatement create(Loc loc, Statement s1, Statement s2) 923 { 924 return new CompoundStatement(loc, s1, s2); 925 } 926 927 override CompoundStatement syntaxCopy() 928 { 929 return new CompoundStatement(loc, Statement.arraySyntaxCopy(statements)); 930 } 931 932 override Statements* flatten(Scope* sc) 933 { 934 return statements; 935 } 936 937 override final inout(ReturnStatement) endsWithReturnStatement() inout nothrow pure 938 { 939 foreach (s; *statements) 940 { 941 if (s) 942 { 943 if (inout rs = s.endsWithReturnStatement()) 944 return rs; 945 } 946 } 947 return null; 948 } 949 950 override final inout(Statement) last() inout nothrow pure 951 { 952 Statement s = null; 953 for (size_t i = statements.dim; i; --i) 954 { 955 s = cast(Statement)(*statements)[i - 1]; 956 if (s) 957 { 958 s = cast(Statement)s.last(); 959 if (s) 960 break; 961 } 962 } 963 return cast(inout)s; 964 } 965 966 override void accept(Visitor v) 967 { 968 v.visit(this); 969 } 970 } 971 972 /*********************************************************** 973 */ 974 extern (C++) final class CompoundDeclarationStatement : CompoundStatement 975 { 976 extern (D) this(const ref Loc loc, Statements* statements) 977 { 978 super(loc, statements, STMT.CompoundDeclaration); 979 } 980 981 override CompoundDeclarationStatement syntaxCopy() 982 { 983 auto a = new Statements(statements.dim); 984 foreach (i, s; *statements) 985 { 986 (*a)[i] = s ? s.syntaxCopy() : null; 987 } 988 return new CompoundDeclarationStatement(loc, a); 989 } 990 991 override void accept(Visitor v) 992 { 993 v.visit(this); 994 } 995 } 996 997 /*********************************************************** 998 * The purpose of this is so that continue will go to the next 999 * of the statements, and break will go to the end of the statements. 1000 */ 1001 extern (C++) final class UnrolledLoopStatement : Statement 1002 { 1003 Statements* statements; 1004 1005 extern (D) this(const ref Loc loc, Statements* statements) 1006 { 1007 super(loc, STMT.UnrolledLoop); 1008 this.statements = statements; 1009 } 1010 1011 override UnrolledLoopStatement syntaxCopy() 1012 { 1013 auto a = new Statements(statements.dim); 1014 foreach (i, s; *statements) 1015 { 1016 (*a)[i] = s ? s.syntaxCopy() : null; 1017 } 1018 return new UnrolledLoopStatement(loc, a); 1019 } 1020 1021 override bool hasBreak() const pure nothrow 1022 { 1023 return true; 1024 } 1025 1026 override bool hasContinue() const pure nothrow 1027 { 1028 return true; 1029 } 1030 1031 override void accept(Visitor v) 1032 { 1033 v.visit(this); 1034 } 1035 } 1036 1037 /*********************************************************** 1038 */ 1039 extern (C++) class ScopeStatement : Statement 1040 { 1041 Statement statement; 1042 Loc endloc; // location of closing curly bracket 1043 1044 extern (D) this(const ref Loc loc, Statement statement, Loc endloc) 1045 { 1046 super(loc, STMT.Scope); 1047 this.statement = statement; 1048 this.endloc = endloc; 1049 } 1050 1051 override ScopeStatement syntaxCopy() 1052 { 1053 return new ScopeStatement(loc, statement ? statement.syntaxCopy() : null, endloc); 1054 } 1055 1056 override inout(ReturnStatement) endsWithReturnStatement() inout nothrow pure 1057 { 1058 if (statement) 1059 return statement.endsWithReturnStatement(); 1060 return null; 1061 } 1062 1063 override bool hasBreak() const pure nothrow 1064 { 1065 //printf("ScopeStatement::hasBreak() %s\n", toChars()); 1066 return statement ? statement.hasBreak() : false; 1067 } 1068 1069 override bool hasContinue() const pure nothrow 1070 { 1071 return statement ? statement.hasContinue() : false; 1072 } 1073 1074 override void accept(Visitor v) 1075 { 1076 v.visit(this); 1077 } 1078 } 1079 1080 /*********************************************************** 1081 * Statement whose symbol table contains foreach index variables in a 1082 * local scope and forwards other members to the parent scope. This 1083 * wraps a statement. 1084 * 1085 * Also see: `dmd.attrib.ForwardingAttribDeclaration` 1086 */ 1087 extern (C++) final class ForwardingStatement : Statement 1088 { 1089 /// The symbol containing the `static foreach` variables. 1090 ForwardingScopeDsymbol sym = null; 1091 /// The wrapped statement. 1092 Statement statement; 1093 1094 extern (D) this(const ref Loc loc, ForwardingScopeDsymbol sym, Statement statement) 1095 { 1096 super(loc, STMT.Forwarding); 1097 this.sym = sym; 1098 assert(statement); 1099 this.statement = statement; 1100 } 1101 1102 extern (D) this(const ref Loc loc, Statement statement) 1103 { 1104 auto sym = new ForwardingScopeDsymbol(null); 1105 sym.symtab = new DsymbolTable(); 1106 this(loc, sym, statement); 1107 } 1108 1109 override ForwardingStatement syntaxCopy() 1110 { 1111 return new ForwardingStatement(loc, statement.syntaxCopy()); 1112 } 1113 1114 /*********************** 1115 * ForwardingStatements are distributed over the flattened 1116 * sequence of statements. This prevents flattening to be 1117 * "blocked" by a ForwardingStatement and is necessary, for 1118 * example, to support generating scope guards with `static 1119 * foreach`: 1120 * 1121 * static foreach(i; 0 .. 10) scope(exit) writeln(i); 1122 * writeln("this is printed first"); 1123 * // then, it prints 10, 9, 8, 7, ... 1124 */ 1125 1126 override Statements* flatten(Scope* sc) 1127 { 1128 if (!statement) 1129 { 1130 return null; 1131 } 1132 sc = sc.push(sym); 1133 auto a = statement.flatten(sc); 1134 sc = sc.pop(); 1135 if (!a) 1136 { 1137 return a; 1138 } 1139 auto b = new Statements(a.dim); 1140 foreach (i, s; *a) 1141 { 1142 (*b)[i] = s ? new ForwardingStatement(s.loc, sym, s) : null; 1143 } 1144 return b; 1145 } 1146 1147 override void accept(Visitor v) 1148 { 1149 v.visit(this); 1150 } 1151 } 1152 1153 1154 /*********************************************************** 1155 * https://dlang.org/spec/statement.html#while-statement 1156 */ 1157 extern (C++) final class WhileStatement : Statement 1158 { 1159 Expression condition; 1160 Statement _body; 1161 Loc endloc; // location of closing curly bracket 1162 1163 extern (D) this(const ref Loc loc, Expression condition, Statement _body, Loc endloc) 1164 { 1165 super(loc, STMT.While); 1166 this.condition = condition; 1167 this._body = _body; 1168 this.endloc = endloc; 1169 } 1170 1171 override WhileStatement syntaxCopy() 1172 { 1173 return new WhileStatement(loc, 1174 condition.syntaxCopy(), 1175 _body ? _body.syntaxCopy() : null, 1176 endloc); 1177 } 1178 1179 override bool hasBreak() const pure nothrow 1180 { 1181 return true; 1182 } 1183 1184 override bool hasContinue() const pure nothrow 1185 { 1186 return true; 1187 } 1188 1189 override void accept(Visitor v) 1190 { 1191 v.visit(this); 1192 } 1193 } 1194 1195 /*********************************************************** 1196 * https://dlang.org/spec/statement.html#do-statement 1197 */ 1198 extern (C++) final class DoStatement : Statement 1199 { 1200 Statement _body; 1201 Expression condition; 1202 Loc endloc; // location of ';' after while 1203 1204 extern (D) this(const ref Loc loc, Statement _body, Expression condition, Loc endloc) 1205 { 1206 super(loc, STMT.Do); 1207 this._body = _body; 1208 this.condition = condition; 1209 this.endloc = endloc; 1210 } 1211 1212 override DoStatement syntaxCopy() 1213 { 1214 return new DoStatement(loc, 1215 _body ? _body.syntaxCopy() : null, 1216 condition.syntaxCopy(), 1217 endloc); 1218 } 1219 1220 override bool hasBreak() const pure nothrow 1221 { 1222 return true; 1223 } 1224 1225 override bool hasContinue() const pure nothrow 1226 { 1227 return true; 1228 } 1229 1230 override void accept(Visitor v) 1231 { 1232 v.visit(this); 1233 } 1234 } 1235 1236 /*********************************************************** 1237 * https://dlang.org/spec/statement.html#for-statement 1238 */ 1239 extern (C++) final class ForStatement : Statement 1240 { 1241 Statement _init; 1242 Expression condition; 1243 Expression increment; 1244 Statement _body; 1245 Loc endloc; // location of closing curly bracket 1246 1247 // When wrapped in try/finally clauses, this points to the outermost one, 1248 // which may have an associated label. Internal break/continue statements 1249 // treat that label as referring to this loop. 1250 Statement relatedLabeled; 1251 1252 extern (D) this(const ref Loc loc, Statement _init, Expression condition, Expression increment, Statement _body, Loc endloc) 1253 { 1254 super(loc, STMT.For); 1255 this._init = _init; 1256 this.condition = condition; 1257 this.increment = increment; 1258 this._body = _body; 1259 this.endloc = endloc; 1260 } 1261 1262 override ForStatement syntaxCopy() 1263 { 1264 return new ForStatement(loc, 1265 _init ? _init.syntaxCopy() : null, 1266 condition ? condition.syntaxCopy() : null, 1267 increment ? increment.syntaxCopy() : null, 1268 _body.syntaxCopy(), 1269 endloc); 1270 } 1271 1272 override Statement scopeCode(Scope* sc, Statement* sentry, Statement* sexception, Statement* sfinally) 1273 { 1274 //printf("ForStatement::scopeCode()\n"); 1275 Statement.scopeCode(sc, sentry, sexception, sfinally); 1276 return this; 1277 } 1278 1279 override Statement getRelatedLabeled() 1280 { 1281 return relatedLabeled ? relatedLabeled : this; 1282 } 1283 1284 override bool hasBreak() const pure nothrow 1285 { 1286 //printf("ForStatement::hasBreak()\n"); 1287 return true; 1288 } 1289 1290 override bool hasContinue() const pure nothrow 1291 { 1292 return true; 1293 } 1294 1295 override void accept(Visitor v) 1296 { 1297 v.visit(this); 1298 } 1299 } 1300 1301 /*********************************************************** 1302 * https://dlang.org/spec/statement.html#foreach-statement 1303 */ 1304 extern (C++) final class ForeachStatement : Statement 1305 { 1306 TOK op; // TOK.foreach_ or TOK.foreach_reverse_ 1307 Parameters* parameters; // array of Parameters, one for each ForeachType 1308 Expression aggr; // ForeachAggregate 1309 Statement _body; // NoScopeNonEmptyStatement 1310 Loc endloc; // location of closing curly bracket 1311 1312 VarDeclaration key; 1313 VarDeclaration value; 1314 1315 FuncDeclaration func; // function we're lexically in 1316 1317 Statements* cases; // put breaks, continues, gotos and returns here 1318 ScopeStatements* gotos; // forward referenced goto's go here 1319 1320 extern (D) this(const ref Loc loc, TOK op, Parameters* parameters, Expression aggr, Statement _body, Loc endloc) 1321 { 1322 super(loc, STMT.Foreach); 1323 this.op = op; 1324 this.parameters = parameters; 1325 this.aggr = aggr; 1326 this._body = _body; 1327 this.endloc = endloc; 1328 } 1329 1330 override ForeachStatement syntaxCopy() 1331 { 1332 return new ForeachStatement(loc, op, 1333 Parameter.arraySyntaxCopy(parameters), 1334 aggr.syntaxCopy(), 1335 _body ? _body.syntaxCopy() : null, 1336 endloc); 1337 } 1338 1339 override bool hasBreak() const pure nothrow 1340 { 1341 return true; 1342 } 1343 1344 override bool hasContinue() const pure nothrow 1345 { 1346 return true; 1347 } 1348 1349 override void accept(Visitor v) 1350 { 1351 v.visit(this); 1352 } 1353 } 1354 1355 /*********************************************************** 1356 * https://dlang.org/spec/statement.html#foreach-range-statement 1357 */ 1358 extern (C++) final class ForeachRangeStatement : Statement 1359 { 1360 TOK op; // TOK.foreach_ or TOK.foreach_reverse_ 1361 Parameter prm; // loop index variable 1362 Expression lwr; 1363 Expression upr; 1364 Statement _body; 1365 Loc endloc; // location of closing curly bracket 1366 1367 VarDeclaration key; 1368 1369 extern (D) this(const ref Loc loc, TOK op, Parameter prm, Expression lwr, Expression upr, Statement _body, Loc endloc) 1370 { 1371 super(loc, STMT.ForeachRange); 1372 this.op = op; 1373 this.prm = prm; 1374 this.lwr = lwr; 1375 this.upr = upr; 1376 this._body = _body; 1377 this.endloc = endloc; 1378 } 1379 1380 override ForeachRangeStatement syntaxCopy() 1381 { 1382 return new ForeachRangeStatement(loc, op, prm.syntaxCopy(), lwr.syntaxCopy(), upr.syntaxCopy(), _body ? _body.syntaxCopy() : null, endloc); 1383 } 1384 1385 override bool hasBreak() const pure nothrow 1386 { 1387 return true; 1388 } 1389 1390 override bool hasContinue() const pure nothrow 1391 { 1392 return true; 1393 } 1394 1395 override void accept(Visitor v) 1396 { 1397 v.visit(this); 1398 } 1399 } 1400 1401 /*********************************************************** 1402 * https://dlang.org/spec/statement.html#if-statement 1403 */ 1404 extern (C++) final class IfStatement : Statement 1405 { 1406 Parameter prm; 1407 Expression condition; 1408 Statement ifbody; 1409 Statement elsebody; 1410 VarDeclaration match; // for MatchExpression results 1411 Loc endloc; // location of closing curly bracket 1412 1413 extern (D) this(const ref Loc loc, Parameter prm, Expression condition, Statement ifbody, Statement elsebody, Loc endloc) 1414 { 1415 super(loc, STMT.If); 1416 this.prm = prm; 1417 this.condition = condition; 1418 this.ifbody = ifbody; 1419 this.elsebody = elsebody; 1420 this.endloc = endloc; 1421 } 1422 1423 override IfStatement syntaxCopy() 1424 { 1425 return new IfStatement(loc, 1426 prm ? prm.syntaxCopy() : null, 1427 condition.syntaxCopy(), 1428 ifbody ? ifbody.syntaxCopy() : null, 1429 elsebody ? elsebody.syntaxCopy() : null, 1430 endloc); 1431 } 1432 1433 override void accept(Visitor v) 1434 { 1435 v.visit(this); 1436 } 1437 } 1438 1439 /*********************************************************** 1440 * https://dlang.org/spec/version.html#ConditionalStatement 1441 */ 1442 extern (C++) final class ConditionalStatement : Statement 1443 { 1444 Condition condition; 1445 Statement ifbody; 1446 Statement elsebody; 1447 1448 extern (D) this(const ref Loc loc, Condition condition, Statement ifbody, Statement elsebody) 1449 { 1450 super(loc, STMT.Conditional); 1451 this.condition = condition; 1452 this.ifbody = ifbody; 1453 this.elsebody = elsebody; 1454 } 1455 1456 override ConditionalStatement syntaxCopy() 1457 { 1458 return new ConditionalStatement(loc, condition.syntaxCopy(), ifbody.syntaxCopy(), elsebody ? elsebody.syntaxCopy() : null); 1459 } 1460 1461 override Statements* flatten(Scope* sc) 1462 { 1463 Statement s; 1464 1465 //printf("ConditionalStatement::flatten()\n"); 1466 if (condition.include(sc)) 1467 { 1468 DebugCondition dc = condition.isDebugCondition(); 1469 if (dc) 1470 { 1471 s = new DebugStatement(loc, ifbody); 1472 debugThrowWalker(ifbody); 1473 } 1474 else 1475 s = ifbody; 1476 } 1477 else 1478 s = elsebody; 1479 1480 auto a = new Statements(); 1481 a.push(s); 1482 return a; 1483 } 1484 1485 override void accept(Visitor v) 1486 { 1487 v.visit(this); 1488 } 1489 } 1490 1491 /** 1492 Marks all occurring ThrowStatements as internalThrows. 1493 This is intended to be called from a DebugStatement as it allows 1494 to mark all its nodes as nothrow. 1495 1496 Params: 1497 s = AST Node to traverse 1498 */ 1499 private void debugThrowWalker(Statement s) 1500 { 1501 1502 extern(C++) final class DebugWalker : SemanticTimeTransitiveVisitor 1503 { 1504 alias visit = SemanticTimeTransitiveVisitor.visit; 1505 public: 1506 1507 override void visit(ThrowStatement s) 1508 { 1509 s.internalThrow = true; 1510 } 1511 1512 override void visit(CallExp s) 1513 { 1514 s.inDebugStatement = true; 1515 } 1516 } 1517 1518 scope walker = new DebugWalker(); 1519 s.accept(walker); 1520 } 1521 1522 /*********************************************************** 1523 * https://dlang.org/spec/version.html#StaticForeachStatement 1524 * Static foreach statements, like: 1525 * void main() 1526 * { 1527 * static foreach(i; 0 .. 10) 1528 * { 1529 * pragma(msg, i); 1530 * } 1531 * } 1532 */ 1533 extern (C++) final class StaticForeachStatement : Statement 1534 { 1535 StaticForeach sfe; 1536 1537 extern (D) this(const ref Loc loc, StaticForeach sfe) 1538 { 1539 super(loc, STMT.StaticForeach); 1540 this.sfe = sfe; 1541 } 1542 1543 override StaticForeachStatement syntaxCopy() 1544 { 1545 return new StaticForeachStatement(loc, sfe.syntaxCopy()); 1546 } 1547 1548 override Statements* flatten(Scope* sc) 1549 { 1550 sfe.prepare(sc); 1551 if (sfe.ready()) 1552 { 1553 import dmd.statementsem; 1554 auto s = makeTupleForeach!(true, false)(sc, sfe.aggrfe, sfe.needExpansion); 1555 auto result = s.flatten(sc); 1556 if (result) 1557 { 1558 return result; 1559 } 1560 result = new Statements(); 1561 result.push(s); 1562 return result; 1563 } 1564 else 1565 { 1566 auto result = new Statements(); 1567 result.push(new ErrorStatement()); 1568 return result; 1569 } 1570 } 1571 1572 override void accept(Visitor v) 1573 { 1574 v.visit(this); 1575 } 1576 } 1577 1578 /*********************************************************** 1579 * https://dlang.org/spec/statement.html#pragma-statement 1580 */ 1581 extern (C++) final class PragmaStatement : Statement 1582 { 1583 const Identifier ident; 1584 Expressions* args; // array of Expression's 1585 Statement _body; 1586 1587 extern (D) this(const ref Loc loc, const Identifier ident, Expressions* args, Statement _body) 1588 { 1589 super(loc, STMT.Pragma); 1590 this.ident = ident; 1591 this.args = args; 1592 this._body = _body; 1593 } 1594 1595 override PragmaStatement syntaxCopy() 1596 { 1597 return new PragmaStatement(loc, ident, Expression.arraySyntaxCopy(args), _body ? _body.syntaxCopy() : null); 1598 } 1599 1600 override void accept(Visitor v) 1601 { 1602 v.visit(this); 1603 } 1604 } 1605 1606 /*********************************************************** 1607 * https://dlang.org/spec/version.html#StaticAssert 1608 */ 1609 extern (C++) final class StaticAssertStatement : Statement 1610 { 1611 StaticAssert sa; 1612 1613 extern (D) this(StaticAssert sa) 1614 { 1615 super(sa.loc, STMT.StaticAssert); 1616 this.sa = sa; 1617 } 1618 1619 override StaticAssertStatement syntaxCopy() 1620 { 1621 return new StaticAssertStatement(sa.syntaxCopy(null)); 1622 } 1623 1624 override void accept(Visitor v) 1625 { 1626 v.visit(this); 1627 } 1628 } 1629 1630 /*********************************************************** 1631 * https://dlang.org/spec/statement.html#switch-statement 1632 */ 1633 extern (C++) final class SwitchStatement : Statement 1634 { 1635 Expression condition; /// switch(condition) 1636 Statement _body; /// 1637 bool isFinal; /// https://dlang.org/spec/statement.html#final-switch-statement 1638 1639 DefaultStatement sdefault; /// default: 1640 Statement tryBody; /// set to TryCatchStatement or TryFinallyStatement if in _body portion 1641 TryFinallyStatement tf; /// set if in the 'finally' block of a TryFinallyStatement 1642 GotoCaseStatements gotoCases; /// array of unresolved GotoCaseStatement's 1643 CaseStatements* cases; /// array of CaseStatement's 1644 int hasNoDefault; /// !=0 if no default statement 1645 int hasVars; /// !=0 if has variable case values 1646 VarDeclaration lastVar; /// last observed variable declaration in this statement 1647 1648 extern (D) this(const ref Loc loc, Expression condition, Statement _body, bool isFinal) 1649 { 1650 super(loc, STMT.Switch); 1651 this.condition = condition; 1652 this._body = _body; 1653 this.isFinal = isFinal; 1654 } 1655 1656 override SwitchStatement syntaxCopy() 1657 { 1658 return new SwitchStatement(loc, condition.syntaxCopy(), _body.syntaxCopy(), isFinal); 1659 } 1660 1661 override bool hasBreak() const pure nothrow 1662 { 1663 return true; 1664 } 1665 1666 /************************************ 1667 * Returns: 1668 * true if error 1669 */ 1670 extern (D) bool checkLabel() 1671 { 1672 /* 1673 * Checks the scope of a label for existing variable declaration. 1674 * Params: 1675 * vd = last variable declared before this case/default label 1676 * Returns: `true` if the variables declared in this label would be skipped. 1677 */ 1678 bool checkVar(VarDeclaration vd) 1679 { 1680 for (auto v = vd; v && v != lastVar; v = v.lastVar) 1681 { 1682 if (v.isDataseg() || (v.storage_class & (STC.manifest | STC.temp)) || v._init.isVoidInitializer()) 1683 continue; 1684 if (vd.ident == Id.withSym) 1685 error("`switch` skips declaration of `with` temporary at %s", v.loc.toChars()); 1686 else 1687 error("`switch` skips declaration of variable `%s` at %s", v.toPrettyChars(), v.loc.toChars()); 1688 return true; 1689 } 1690 return false; 1691 } 1692 1693 enum error = true; 1694 1695 if (sdefault && checkVar(sdefault.lastVar)) 1696 return !error; // return error once fully deprecated 1697 1698 foreach (scase; *cases) 1699 { 1700 if (scase && checkVar(scase.lastVar)) 1701 return !error; // return error once fully deprecated 1702 } 1703 return !error; 1704 } 1705 1706 override void accept(Visitor v) 1707 { 1708 v.visit(this); 1709 } 1710 } 1711 1712 /*********************************************************** 1713 * https://dlang.org/spec/statement.html#CaseStatement 1714 */ 1715 extern (C++) final class CaseStatement : Statement 1716 { 1717 Expression exp; 1718 Statement statement; 1719 1720 int index; // which case it is (since we sort this) 1721 VarDeclaration lastVar; 1722 void* extra; // for use by Statement_toIR() 1723 1724 extern (D) this(const ref Loc loc, Expression exp, Statement statement) 1725 { 1726 super(loc, STMT.Case); 1727 this.exp = exp; 1728 this.statement = statement; 1729 } 1730 1731 override CaseStatement syntaxCopy() 1732 { 1733 return new CaseStatement(loc, exp.syntaxCopy(), statement.syntaxCopy()); 1734 } 1735 1736 override void accept(Visitor v) 1737 { 1738 v.visit(this); 1739 } 1740 } 1741 1742 /*********************************************************** 1743 * https://dlang.org/spec/statement.html#CaseRangeStatement 1744 */ 1745 extern (C++) final class CaseRangeStatement : Statement 1746 { 1747 Expression first; 1748 Expression last; 1749 Statement statement; 1750 1751 extern (D) this(const ref Loc loc, Expression first, Expression last, Statement statement) 1752 { 1753 super(loc, STMT.CaseRange); 1754 this.first = first; 1755 this.last = last; 1756 this.statement = statement; 1757 } 1758 1759 override CaseRangeStatement syntaxCopy() 1760 { 1761 return new CaseRangeStatement(loc, first.syntaxCopy(), last.syntaxCopy(), statement.syntaxCopy()); 1762 } 1763 1764 override void accept(Visitor v) 1765 { 1766 v.visit(this); 1767 } 1768 } 1769 1770 /*********************************************************** 1771 * https://dlang.org/spec/statement.html#DefaultStatement 1772 */ 1773 extern (C++) final class DefaultStatement : Statement 1774 { 1775 Statement statement; 1776 1777 VarDeclaration lastVar; 1778 1779 extern (D) this(const ref Loc loc, Statement statement) 1780 { 1781 super(loc, STMT.Default); 1782 this.statement = statement; 1783 } 1784 1785 override DefaultStatement syntaxCopy() 1786 { 1787 return new DefaultStatement(loc, statement.syntaxCopy()); 1788 } 1789 1790 override void accept(Visitor v) 1791 { 1792 v.visit(this); 1793 } 1794 } 1795 1796 /*********************************************************** 1797 * https://dlang.org/spec/statement.html#GotoStatement 1798 */ 1799 extern (C++) final class GotoDefaultStatement : Statement 1800 { 1801 SwitchStatement sw; 1802 1803 extern (D) this(const ref Loc loc) 1804 { 1805 super(loc, STMT.GotoDefault); 1806 } 1807 1808 override GotoDefaultStatement syntaxCopy() 1809 { 1810 return new GotoDefaultStatement(loc); 1811 } 1812 1813 override void accept(Visitor v) 1814 { 1815 v.visit(this); 1816 } 1817 } 1818 1819 /*********************************************************** 1820 * https://dlang.org/spec/statement.html#GotoStatement 1821 */ 1822 extern (C++) final class GotoCaseStatement : Statement 1823 { 1824 Expression exp; // null, or which case to goto 1825 1826 CaseStatement cs; // case statement it resolves to 1827 1828 extern (D) this(const ref Loc loc, Expression exp) 1829 { 1830 super(loc, STMT.GotoCase); 1831 this.exp = exp; 1832 } 1833 1834 override GotoCaseStatement syntaxCopy() 1835 { 1836 return new GotoCaseStatement(loc, exp ? exp.syntaxCopy() : null); 1837 } 1838 1839 override void accept(Visitor v) 1840 { 1841 v.visit(this); 1842 } 1843 } 1844 1845 /*********************************************************** 1846 */ 1847 extern (C++) final class SwitchErrorStatement : Statement 1848 { 1849 Expression exp; 1850 1851 extern (D) this(const ref Loc loc) 1852 { 1853 super(loc, STMT.SwitchError); 1854 } 1855 1856 final extern (D) this(const ref Loc loc, Expression exp) 1857 { 1858 super(loc, STMT.SwitchError); 1859 this.exp = exp; 1860 } 1861 1862 override void accept(Visitor v) 1863 { 1864 v.visit(this); 1865 } 1866 } 1867 1868 /*********************************************************** 1869 * https://dlang.org/spec/statement.html#return-statement 1870 */ 1871 extern (C++) final class ReturnStatement : Statement 1872 { 1873 Expression exp; 1874 size_t caseDim; 1875 1876 extern (D) this(const ref Loc loc, Expression exp) 1877 { 1878 super(loc, STMT.Return); 1879 this.exp = exp; 1880 } 1881 1882 override ReturnStatement syntaxCopy() 1883 { 1884 return new ReturnStatement(loc, exp ? exp.syntaxCopy() : null); 1885 } 1886 1887 override inout(ReturnStatement) endsWithReturnStatement() inout nothrow pure 1888 { 1889 return this; 1890 } 1891 1892 override void accept(Visitor v) 1893 { 1894 v.visit(this); 1895 } 1896 } 1897 1898 /*********************************************************** 1899 * https://dlang.org/spec/statement.html#break-statement 1900 */ 1901 extern (C++) final class BreakStatement : Statement 1902 { 1903 Identifier ident; 1904 1905 extern (D) this(const ref Loc loc, Identifier ident) 1906 { 1907 super(loc, STMT.Break); 1908 this.ident = ident; 1909 } 1910 1911 override BreakStatement syntaxCopy() 1912 { 1913 return new BreakStatement(loc, ident); 1914 } 1915 1916 override void accept(Visitor v) 1917 { 1918 v.visit(this); 1919 } 1920 } 1921 1922 /*********************************************************** 1923 * https://dlang.org/spec/statement.html#continue-statement 1924 */ 1925 extern (C++) final class ContinueStatement : Statement 1926 { 1927 Identifier ident; 1928 1929 extern (D) this(const ref Loc loc, Identifier ident) 1930 { 1931 super(loc, STMT.Continue); 1932 this.ident = ident; 1933 } 1934 1935 override ContinueStatement syntaxCopy() 1936 { 1937 return new ContinueStatement(loc, ident); 1938 } 1939 1940 override void accept(Visitor v) 1941 { 1942 v.visit(this); 1943 } 1944 } 1945 1946 /*********************************************************** 1947 * https://dlang.org/spec/statement.html#SynchronizedStatement 1948 */ 1949 extern (C++) final class SynchronizedStatement : Statement 1950 { 1951 Expression exp; 1952 Statement _body; 1953 1954 extern (D) this(const ref Loc loc, Expression exp, Statement _body) 1955 { 1956 super(loc, STMT.Synchronized); 1957 this.exp = exp; 1958 this._body = _body; 1959 } 1960 1961 override SynchronizedStatement syntaxCopy() 1962 { 1963 return new SynchronizedStatement(loc, exp ? exp.syntaxCopy() : null, _body ? _body.syntaxCopy() : null); 1964 } 1965 1966 override bool hasBreak() const pure nothrow 1967 { 1968 return false; //true; 1969 } 1970 1971 override bool hasContinue() const pure nothrow 1972 { 1973 return false; //true; 1974 } 1975 1976 override void accept(Visitor v) 1977 { 1978 v.visit(this); 1979 } 1980 } 1981 1982 /*********************************************************** 1983 * https://dlang.org/spec/statement.html#with-statement 1984 */ 1985 extern (C++) final class WithStatement : Statement 1986 { 1987 Expression exp; 1988 Statement _body; 1989 VarDeclaration wthis; 1990 Loc endloc; 1991 1992 extern (D) this(const ref Loc loc, Expression exp, Statement _body, Loc endloc) 1993 { 1994 super(loc, STMT.With); 1995 this.exp = exp; 1996 this._body = _body; 1997 this.endloc = endloc; 1998 } 1999 2000 override WithStatement syntaxCopy() 2001 { 2002 return new WithStatement(loc, exp.syntaxCopy(), _body ? _body.syntaxCopy() : null, endloc); 2003 } 2004 2005 override void accept(Visitor v) 2006 { 2007 v.visit(this); 2008 } 2009 } 2010 2011 /*********************************************************** 2012 * https://dlang.org/spec/statement.html#try-statement 2013 */ 2014 extern (C++) final class TryCatchStatement : Statement 2015 { 2016 Statement _body; 2017 Catches* catches; 2018 2019 Statement tryBody; /// set to enclosing TryCatchStatement or TryFinallyStatement if in _body portion 2020 2021 extern (D) this(const ref Loc loc, Statement _body, Catches* catches) 2022 { 2023 super(loc, STMT.TryCatch); 2024 this._body = _body; 2025 this.catches = catches; 2026 } 2027 2028 override TryCatchStatement syntaxCopy() 2029 { 2030 auto a = new Catches(catches.dim); 2031 foreach (i, c; *catches) 2032 { 2033 (*a)[i] = c.syntaxCopy(); 2034 } 2035 return new TryCatchStatement(loc, _body.syntaxCopy(), a); 2036 } 2037 2038 override bool hasBreak() const pure nothrow 2039 { 2040 return false; 2041 } 2042 2043 override void accept(Visitor v) 2044 { 2045 v.visit(this); 2046 } 2047 } 2048 2049 /*********************************************************** 2050 * https://dlang.org/spec/statement.html#Catch 2051 */ 2052 extern (C++) final class Catch : RootObject 2053 { 2054 const Loc loc; 2055 Type type; 2056 Identifier ident; 2057 Statement handler; 2058 2059 VarDeclaration var; 2060 bool errors; // set if semantic processing errors 2061 2062 // was generated by the compiler, wasn't present in source code 2063 bool internalCatch; 2064 2065 extern (D) this(const ref Loc loc, Type type, Identifier ident, Statement handler) 2066 { 2067 //printf("Catch(%s, loc = %s)\n", id.toChars(), loc.toChars()); 2068 this.loc = loc; 2069 this.type = type; 2070 this.ident = ident; 2071 this.handler = handler; 2072 } 2073 2074 Catch syntaxCopy() 2075 { 2076 auto c = new Catch(loc, type ? type.syntaxCopy() : getThrowable(), ident, (handler ? handler.syntaxCopy() : null)); 2077 c.internalCatch = internalCatch; 2078 return c; 2079 } 2080 } 2081 2082 /*********************************************************** 2083 * https://dlang.org/spec/statement.html#try-statement 2084 */ 2085 extern (C++) final class TryFinallyStatement : Statement 2086 { 2087 Statement _body; 2088 Statement finalbody; 2089 2090 Statement tryBody; /// set to enclosing TryCatchStatement or TryFinallyStatement if in _body portion 2091 bool bodyFallsThru; /// true if _body falls through to finally 2092 2093 extern (D) this(const ref Loc loc, Statement _body, Statement finalbody) 2094 { 2095 super(loc, STMT.TryFinally); 2096 this._body = _body; 2097 this.finalbody = finalbody; 2098 this.bodyFallsThru = true; // assume true until statementSemantic() 2099 } 2100 2101 static TryFinallyStatement create(Loc loc, Statement _body, Statement finalbody) 2102 { 2103 return new TryFinallyStatement(loc, _body, finalbody); 2104 } 2105 2106 override TryFinallyStatement syntaxCopy() 2107 { 2108 return new TryFinallyStatement(loc, _body.syntaxCopy(), finalbody.syntaxCopy()); 2109 } 2110 2111 override bool hasBreak() const pure nothrow 2112 { 2113 return false; //true; 2114 } 2115 2116 override bool hasContinue() const pure nothrow 2117 { 2118 return false; //true; 2119 } 2120 2121 override void accept(Visitor v) 2122 { 2123 v.visit(this); 2124 } 2125 } 2126 2127 /*********************************************************** 2128 * https://dlang.org/spec/statement.html#scope-guard-statement 2129 */ 2130 extern (C++) final class ScopeGuardStatement : Statement 2131 { 2132 TOK tok; 2133 Statement statement; 2134 2135 extern (D) this(const ref Loc loc, TOK tok, Statement statement) 2136 { 2137 super(loc, STMT.ScopeGuard); 2138 this.tok = tok; 2139 this.statement = statement; 2140 } 2141 2142 override ScopeGuardStatement syntaxCopy() 2143 { 2144 return new ScopeGuardStatement(loc, tok, statement.syntaxCopy()); 2145 } 2146 2147 override Statement scopeCode(Scope* sc, Statement* sentry, Statement* sexception, Statement* sfinally) 2148 { 2149 //printf("ScopeGuardStatement::scopeCode()\n"); 2150 *sentry = null; 2151 *sexception = null; 2152 *sfinally = null; 2153 2154 Statement s = new PeelStatement(statement); 2155 2156 switch (tok) 2157 { 2158 case TOK.onScopeExit: 2159 *sfinally = s; 2160 break; 2161 2162 case TOK.onScopeFailure: 2163 *sexception = s; 2164 break; 2165 2166 case TOK.onScopeSuccess: 2167 { 2168 /* Create: 2169 * sentry: bool x = false; 2170 * sexception: x = true; 2171 * sfinally: if (!x) statement; 2172 */ 2173 auto v = copyToTemp(0, "__os", IntegerExp.createBool(false)); 2174 v.dsymbolSemantic(sc); 2175 *sentry = new ExpStatement(loc, v); 2176 2177 Expression e = IntegerExp.createBool(true); 2178 e = new AssignExp(Loc.initial, new VarExp(Loc.initial, v), e); 2179 *sexception = new ExpStatement(Loc.initial, e); 2180 2181 e = new VarExp(Loc.initial, v); 2182 e = new NotExp(Loc.initial, e); 2183 *sfinally = new IfStatement(Loc.initial, null, e, s, null, Loc.initial); 2184 2185 break; 2186 } 2187 default: 2188 assert(0); 2189 } 2190 return null; 2191 } 2192 2193 override void accept(Visitor v) 2194 { 2195 v.visit(this); 2196 } 2197 } 2198 2199 /*********************************************************** 2200 * https://dlang.org/spec/statement.html#throw-statement 2201 */ 2202 extern (C++) final class ThrowStatement : Statement 2203 { 2204 Expression exp; 2205 2206 // was generated by the compiler, wasn't present in source code 2207 bool internalThrow; 2208 2209 extern (D) this(const ref Loc loc, Expression exp) 2210 { 2211 super(loc, STMT.Throw); 2212 this.exp = exp; 2213 } 2214 2215 override ThrowStatement syntaxCopy() 2216 { 2217 auto s = new ThrowStatement(loc, exp.syntaxCopy()); 2218 s.internalThrow = internalThrow; 2219 return s; 2220 } 2221 2222 override void accept(Visitor v) 2223 { 2224 v.visit(this); 2225 } 2226 } 2227 2228 /*********************************************************** 2229 */ 2230 extern (C++) final class DebugStatement : Statement 2231 { 2232 Statement statement; 2233 2234 extern (D) this(const ref Loc loc, Statement statement) 2235 { 2236 super(loc, STMT.Debug); 2237 this.statement = statement; 2238 } 2239 2240 override DebugStatement syntaxCopy() 2241 { 2242 return new DebugStatement(loc, statement ? statement.syntaxCopy() : null); 2243 } 2244 2245 override Statements* flatten(Scope* sc) 2246 { 2247 Statements* a = statement ? statement.flatten(sc) : null; 2248 if (a) 2249 { 2250 foreach (ref s; *a) 2251 { 2252 s = new DebugStatement(loc, s); 2253 } 2254 } 2255 return a; 2256 } 2257 2258 override void accept(Visitor v) 2259 { 2260 v.visit(this); 2261 } 2262 } 2263 2264 /*********************************************************** 2265 * https://dlang.org/spec/statement.html#goto-statement 2266 */ 2267 extern (C++) final class GotoStatement : Statement 2268 { 2269 Identifier ident; 2270 LabelDsymbol label; 2271 Statement tryBody; /// set to TryCatchStatement or TryFinallyStatement if in _body portion 2272 TryFinallyStatement tf; 2273 ScopeGuardStatement os; 2274 VarDeclaration lastVar; 2275 2276 extern (D) this(const ref Loc loc, Identifier ident) 2277 { 2278 super(loc, STMT.Goto); 2279 this.ident = ident; 2280 } 2281 2282 override GotoStatement syntaxCopy() 2283 { 2284 return new GotoStatement(loc, ident); 2285 } 2286 2287 extern (D) bool checkLabel() 2288 { 2289 if (!label.statement) 2290 return true; // error should have been issued for this already 2291 2292 if (label.statement.os != os) 2293 { 2294 if (os && os.tok == TOK.onScopeFailure && !label.statement.os) 2295 { 2296 // Jump out from scope(failure) block is allowed. 2297 } 2298 else 2299 { 2300 if (label.statement.os) 2301 error("cannot `goto` in to `%s` block", Token.toChars(label.statement.os.tok)); 2302 else 2303 error("cannot `goto` out of `%s` block", Token.toChars(os.tok)); 2304 return true; 2305 } 2306 } 2307 2308 if (label.statement.tf != tf) 2309 { 2310 error("cannot `goto` in or out of `finally` block"); 2311 return true; 2312 } 2313 2314 Statement stbnext; 2315 for (auto stb = tryBody; stb != label.statement.tryBody; stb = stbnext) 2316 { 2317 if (!stb) 2318 { 2319 error("cannot `goto` into `try` block"); 2320 return true; 2321 } 2322 if (auto stf = stb.isTryFinallyStatement()) 2323 stbnext = stf.tryBody; 2324 else if (auto stc = stb.isTryCatchStatement()) 2325 stbnext = stc.tryBody; 2326 else 2327 assert(0); 2328 } 2329 2330 VarDeclaration vd = label.statement.lastVar; 2331 if (!vd || vd.isDataseg() || (vd.storage_class & STC.manifest)) 2332 return false; 2333 2334 VarDeclaration last = lastVar; 2335 while (last && last != vd) 2336 last = last.lastVar; 2337 if (last == vd) 2338 { 2339 // All good, the label's scope has no variables 2340 } 2341 else if (vd.storage_class & STC.exptemp) 2342 { 2343 // Lifetime ends at end of expression, so no issue with skipping the statement 2344 } 2345 else if (vd.ident == Id.withSym) 2346 { 2347 error("`goto` skips declaration of `with` temporary at %s", vd.loc.toChars()); 2348 return true; 2349 } 2350 else 2351 { 2352 error("`goto` skips declaration of variable `%s` at %s", vd.toPrettyChars(), vd.loc.toChars()); 2353 return true; 2354 } 2355 2356 return false; 2357 } 2358 2359 override void accept(Visitor v) 2360 { 2361 v.visit(this); 2362 } 2363 } 2364 2365 /*********************************************************** 2366 * https://dlang.org/spec/statement.html#LabeledStatement 2367 */ 2368 extern (C++) final class LabelStatement : Statement 2369 { 2370 Identifier ident; 2371 Statement statement; 2372 2373 Statement tryBody; /// set to TryCatchStatement or TryFinallyStatement if in _body portion 2374 TryFinallyStatement tf; 2375 ScopeGuardStatement os; 2376 VarDeclaration lastVar; 2377 Statement gotoTarget; // interpret 2378 void* extra; // used by Statement_toIR() 2379 bool breaks; // someone did a 'break ident' 2380 2381 extern (D) this(const ref Loc loc, Identifier ident, Statement statement) 2382 { 2383 super(loc, STMT.Label); 2384 this.ident = ident; 2385 this.statement = statement; 2386 } 2387 2388 override LabelStatement syntaxCopy() 2389 { 2390 return new LabelStatement(loc, ident, statement ? statement.syntaxCopy() : null); 2391 } 2392 2393 override Statements* flatten(Scope* sc) 2394 { 2395 Statements* a = null; 2396 if (statement) 2397 { 2398 a = statement.flatten(sc); 2399 if (a) 2400 { 2401 if (!a.dim) 2402 { 2403 a.push(new ExpStatement(loc, cast(Expression)null)); 2404 } 2405 2406 // reuse 'this' LabelStatement 2407 this.statement = (*a)[0]; 2408 (*a)[0] = this; 2409 } 2410 } 2411 return a; 2412 } 2413 2414 override Statement scopeCode(Scope* sc, Statement* sentry, Statement* sexit, Statement* sfinally) 2415 { 2416 //printf("LabelStatement::scopeCode()\n"); 2417 if (statement) 2418 statement = statement.scopeCode(sc, sentry, sexit, sfinally); 2419 else 2420 { 2421 *sentry = null; 2422 *sexit = null; 2423 *sfinally = null; 2424 } 2425 return this; 2426 } 2427 2428 override void accept(Visitor v) 2429 { 2430 v.visit(this); 2431 } 2432 } 2433 2434 /*********************************************************** 2435 */ 2436 extern (C++) final class LabelDsymbol : Dsymbol 2437 { 2438 LabelStatement statement; 2439 2440 bool deleted; // set if rewritten to return in foreach delegate 2441 bool iasm; // set if used by inline assembler 2442 2443 extern (D) this(Identifier ident) 2444 { 2445 super(ident); 2446 } 2447 2448 static LabelDsymbol create(Identifier ident) 2449 { 2450 return new LabelDsymbol(ident); 2451 } 2452 2453 // is this a LabelDsymbol()? 2454 override LabelDsymbol isLabel() 2455 { 2456 return this; 2457 } 2458 2459 override void accept(Visitor v) 2460 { 2461 v.visit(this); 2462 } 2463 } 2464 2465 /*********************************************************** 2466 * https://dlang.org/spec/statement.html#asm 2467 */ 2468 extern (C++) class AsmStatement : Statement 2469 { 2470 Token* tokens; 2471 2472 extern (D) this(const ref Loc loc, Token* tokens) 2473 { 2474 super(loc, STMT.Asm); 2475 this.tokens = tokens; 2476 } 2477 2478 extern (D) this(const ref Loc loc, Token* tokens, STMT stmt) 2479 { 2480 super(loc, stmt); 2481 this.tokens = tokens; 2482 } 2483 2484 override AsmStatement syntaxCopy() 2485 { 2486 return new AsmStatement(loc, tokens); 2487 } 2488 2489 override void accept(Visitor v) 2490 { 2491 v.visit(this); 2492 } 2493 } 2494 2495 /*********************************************************** 2496 * https://dlang.org/spec/iasm.html 2497 */ 2498 extern (C++) final class InlineAsmStatement : AsmStatement 2499 { 2500 code* asmcode; 2501 uint asmalign; // alignment of this statement 2502 uint regs; // mask of registers modified (must match regm_t in back end) 2503 bool refparam; // true if function parameter is referenced 2504 bool naked; // true if function is to be naked 2505 2506 extern (D) this(const ref Loc loc, Token* tokens) 2507 { 2508 super(loc, tokens, STMT.InlineAsm); 2509 } 2510 2511 override InlineAsmStatement syntaxCopy() 2512 { 2513 return new InlineAsmStatement(loc, tokens); 2514 } 2515 2516 override void accept(Visitor v) 2517 { 2518 v.visit(this); 2519 } 2520 } 2521 2522 /*********************************************************** 2523 * https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html 2524 * Assembler instructions with D expression operands. 2525 */ 2526 extern (C++) final class GccAsmStatement : AsmStatement 2527 { 2528 StorageClass stc; // attributes of the asm {} block 2529 Expression insn; // string expression that is the template for assembler code 2530 Expressions* args; // input and output operands of the statement 2531 uint outputargs; // of the operands in 'args', the number of output operands 2532 Identifiers* names; // list of symbolic names for the operands 2533 Expressions* constraints; // list of string constants specifying constraints on operands 2534 Expressions* clobbers; // list of string constants specifying clobbers and scratch registers 2535 Identifiers* labels; // list of goto labels 2536 GotoStatements* gotos; // of the goto labels, the equivalent statements they represent 2537 2538 extern (D) this(const ref Loc loc, Token* tokens) 2539 { 2540 super(loc, tokens, STMT.GccAsm); 2541 } 2542 2543 override GccAsmStatement syntaxCopy() 2544 { 2545 return new GccAsmStatement(loc, tokens); 2546 } 2547 2548 override void accept(Visitor v) 2549 { 2550 v.visit(this); 2551 } 2552 } 2553 2554 /*********************************************************** 2555 * a complete asm {} block 2556 */ 2557 extern (C++) final class CompoundAsmStatement : CompoundStatement 2558 { 2559 StorageClass stc; // postfix attributes like nothrow/pure/@trusted 2560 2561 extern (D) this(const ref Loc loc, Statements* statements, StorageClass stc) 2562 { 2563 super(loc, statements, STMT.CompoundAsm); 2564 this.stc = stc; 2565 } 2566 2567 override CompoundAsmStatement syntaxCopy() 2568 { 2569 auto a = new Statements(statements.dim); 2570 foreach (i, s; *statements) 2571 { 2572 (*a)[i] = s ? s.syntaxCopy() : null; 2573 } 2574 return new CompoundAsmStatement(loc, a, stc); 2575 } 2576 2577 override Statements* flatten(Scope* sc) 2578 { 2579 return null; 2580 } 2581 2582 override void accept(Visitor v) 2583 { 2584 v.visit(this); 2585 } 2586 } 2587 2588 /*********************************************************** 2589 * https://dlang.org/spec/module.html#ImportDeclaration 2590 */ 2591 extern (C++) final class ImportStatement : Statement 2592 { 2593 Dsymbols* imports; // Array of Import's 2594 2595 extern (D) this(const ref Loc loc, Dsymbols* imports) 2596 { 2597 super(loc, STMT.Import); 2598 this.imports = imports; 2599 } 2600 2601 override ImportStatement syntaxCopy() 2602 { 2603 auto m = new Dsymbols(imports.dim); 2604 foreach (i, s; *imports) 2605 { 2606 (*m)[i] = s.syntaxCopy(null); 2607 } 2608 return new ImportStatement(loc, m); 2609 } 2610 2611 override void accept(Visitor v) 2612 { 2613 v.visit(this); 2614 } 2615 }