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