2 /* Compiler implementation of the D programming language
3 * Copyright (C) 1999-2023 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
13 #include "arraytypes.h"
25 class DefaultStatement
;
29 class ReturnStatement
;
30 class CompoundStatement
;
36 class TryCatchStatement
;
37 class TryFinallyStatement
;
39 class DefaultStatement
;
46 /* How a statement exits; this is returned by blockExit()
59 BEany
= (BEfallthru
| BEthrow
| BEreturn
| BEgoto
| BEhalt
)
62 typedef unsigned char STMT
;
69 STMTcompound
, STMTcompoundDeclaration
, STMTcompoundAsm
,
102 STMTasm
, STMTinlineAsm
, STMTgccAsm
,
106 class Statement
: public ASTNode
112 DYNCAST
dyncast() const override final
{ return DYNCAST_STATEMENT
; }
114 virtual Statement
*syntaxCopy();
116 const char *toChars() const override final
;
118 void error(const char *format
, ...);
119 void warning(const char *format
, ...);
120 void deprecation(const char *format
, ...);
121 virtual Statement
*getRelatedLabeled() { return this; }
122 virtual bool hasBreak() const;
123 virtual bool hasContinue() const;
127 virtual Statement
*last();
129 virtual ReturnStatement
*endsWithReturnStatement() { return NULL
; }
131 ErrorStatement
*isErrorStatement() { return stmt
== STMTerror
? (ErrorStatement
*)this : NULL
; }
132 ScopeStatement
*isScopeStatement() { return stmt
== STMTscope
? (ScopeStatement
*)this : NULL
; }
133 ExpStatement
*isExpStatement() { return stmt
== STMTexp
? (ExpStatement
*)this : NULL
; }
134 CompoundStatement
*isCompoundStatement() { return stmt
== STMTcompound
? (CompoundStatement
*)this : NULL
; }
135 ReturnStatement
*isReturnStatement() { return stmt
== STMTreturn
? (ReturnStatement
*)this : NULL
; }
136 IfStatement
*isIfStatement() { return stmt
== STMTif
? (IfStatement
*)this : NULL
; }
137 ConditionalStatement
*isConditionalStatement() { return stmt
== STMTconditional
? (ConditionalStatement
*)this : NULL
; }
138 StaticForeachStatement
*isStaticForeachStatement() { return stmt
== STMTstaticForeach
? (StaticForeachStatement
*)this : NULL
; }
139 CaseStatement
*isCaseStatement() { return stmt
== STMTcase
? (CaseStatement
*)this : NULL
; }
140 DefaultStatement
*isDefaultStatement() { return stmt
== STMTdefault
? (DefaultStatement
*)this : NULL
; }
141 LabelStatement
*isLabelStatement() { return stmt
== STMTlabel
? (LabelStatement
*)this : NULL
; }
142 GotoDefaultStatement
*isGotoDefaultStatement() { return stmt
== STMTgotoDefault
? (GotoDefaultStatement
*)this : NULL
; }
143 GotoCaseStatement
*isGotoCaseStatement() { return stmt
== STMTgotoCase
? (GotoCaseStatement
*)this : NULL
; }
144 BreakStatement
*isBreakStatement() { return stmt
== STMTbreak
? (BreakStatement
*)this : NULL
; }
145 DtorExpStatement
*isDtorExpStatement() { return stmt
== STMTdtorExp
? (DtorExpStatement
*)this : NULL
; }
146 CompileStatement
*isCompileStatement() { return stmt
== STMTcompile
? (CompileStatement
*)this : NULL
; }
147 ForwardingStatement
*isForwardingStatement() { return stmt
== STMTforwarding
? (ForwardingStatement
*)this : NULL
; }
148 DoStatement
*isDoStatement() { return stmt
== STMTdo
? (DoStatement
*)this : NULL
; }
149 ForStatement
*isForStatement() { return stmt
== STMTfor
? (ForStatement
*)this : NULL
; }
150 ForeachStatement
*isForeachStatement() { return stmt
== STMTforeach
? (ForeachStatement
*)this : NULL
; }
151 SwitchStatement
*isSwitchStatement() { return stmt
== STMTswitch
? (SwitchStatement
*)this : NULL
; }
152 ContinueStatement
*isContinueStatement() { return stmt
== STMTcontinue
? (ContinueStatement
*)this : NULL
; }
153 WithStatement
*isWithStatement() { return stmt
== STMTwith
? (WithStatement
*)this : NULL
; }
154 TryCatchStatement
*isTryCatchStatement() { return stmt
== STMTtryCatch
? (TryCatchStatement
*)this : NULL
; }
155 ThrowStatement
*isThrowStatement() { return stmt
== STMTthrow
? (ThrowStatement
*)this : NULL
; }
156 DebugStatement
*isDebugStatement() { return stmt
== STMTdebug
? (DebugStatement
*)this : NULL
; }
157 TryFinallyStatement
*isTryFinallyStatement() { return stmt
== STMTtryFinally
? (TryFinallyStatement
*)this : NULL
; }
158 ScopeGuardStatement
*isScopeGuardStatement() { return stmt
== STMTscopeGuard
? (ScopeGuardStatement
*)this : NULL
; }
159 SwitchErrorStatement
*isSwitchErrorStatement() { return stmt
== STMTswitchError
? (SwitchErrorStatement
*)this : NULL
; }
160 UnrolledLoopStatement
*isUnrolledLoopStatement() { return stmt
== STMTunrolledLoop
? (UnrolledLoopStatement
*)this : NULL
; }
161 ForeachRangeStatement
*isForeachRangeStatement() { return stmt
== STMTforeachRange
? (ForeachRangeStatement
*)this : NULL
; }
162 CompoundDeclarationStatement
*isCompoundDeclarationStatement() { return stmt
== STMTcompoundDeclaration
? (CompoundDeclarationStatement
*)this : NULL
; }
164 void accept(Visitor
*v
) override
{ v
->visit(this); }
167 /** Any Statement that fails semantic() or has a component that is an ErrorExp or
168 * a TypeError should return an ErrorStatement from semantic().
170 class ErrorStatement final
: public Statement
173 ErrorStatement
*syntaxCopy() override
;
175 void accept(Visitor
*v
) override
{ v
->visit(this); }
178 class PeelStatement final
: public Statement
183 void accept(Visitor
*v
) override
{ v
->visit(this); }
186 class ExpStatement
: public Statement
191 static ExpStatement
*create(const Loc
&loc
, Expression
*exp
);
192 ExpStatement
*syntaxCopy() override
;
194 void accept(Visitor
*v
) override
{ v
->visit(this); }
197 class DtorExpStatement final
: public ExpStatement
200 /* Wraps an expression that is the destruction of 'var'
205 DtorExpStatement
*syntaxCopy() override
;
206 void accept(Visitor
*v
) override
{ v
->visit(this); }
209 class CompileStatement final
: public Statement
214 CompileStatement
*syntaxCopy() override
;
215 void accept(Visitor
*v
) override
{ v
->visit(this); }
218 class CompoundStatement
: public Statement
221 Statements
*statements
;
223 static CompoundStatement
*create(const Loc
&loc
, Statement
*s1
, Statement
*s2
);
224 CompoundStatement
*syntaxCopy() override
;
225 ReturnStatement
*endsWithReturnStatement() override final
;
226 Statement
*last() override final
;
228 void accept(Visitor
*v
) override
{ v
->visit(this); }
231 class CompoundDeclarationStatement final
: public CompoundStatement
234 CompoundDeclarationStatement
*syntaxCopy() override
;
235 void accept(Visitor
*v
) override
{ v
->visit(this); }
238 /* The purpose of this is so that continue will go to the next
239 * of the statements, and break will go to the end of the statements.
241 class UnrolledLoopStatement final
: public Statement
244 Statements
*statements
;
246 UnrolledLoopStatement
*syntaxCopy() override
;
247 bool hasBreak() const override
;
248 bool hasContinue() const override
;
250 void accept(Visitor
*v
) override
{ v
->visit(this); }
253 class ScopeStatement final
: public Statement
256 Statement
*statement
;
257 Loc endloc
; // location of closing curly bracket
259 ScopeStatement
*syntaxCopy() override
;
260 ReturnStatement
*endsWithReturnStatement() override
;
261 bool hasBreak() const override
;
262 bool hasContinue() const override
;
264 void accept(Visitor
*v
) override
{ v
->visit(this); }
267 class ForwardingStatement final
: public Statement
270 ForwardingScopeDsymbol
*sym
;
271 Statement
*statement
;
273 ForwardingStatement
*syntaxCopy() override
;
274 void accept(Visitor
*v
) override
{ v
->visit(this); }
277 class WhileStatement final
: public Statement
281 Expression
*condition
;
283 Loc endloc
; // location of closing curly bracket
285 WhileStatement
*syntaxCopy() override
;
286 bool hasBreak() const override
;
287 bool hasContinue() const override
;
289 void accept(Visitor
*v
) override
{ v
->visit(this); }
292 class DoStatement final
: public Statement
296 Expression
*condition
;
297 Loc endloc
; // location of ';' after while
299 DoStatement
*syntaxCopy() override
;
300 bool hasBreak() const override
;
301 bool hasContinue() const override
;
303 void accept(Visitor
*v
) override
{ v
->visit(this); }
306 class ForStatement final
: public Statement
310 Expression
*condition
;
311 Expression
*increment
;
313 Loc endloc
; // location of closing curly bracket
315 // When wrapped in try/finally clauses, this points to the outermost one,
316 // which may have an associated label. Internal break/continue statements
317 // treat that label as referring to this loop.
318 Statement
*relatedLabeled
;
320 ForStatement
*syntaxCopy() override
;
321 Statement
*getRelatedLabeled() override
{ return relatedLabeled
? relatedLabeled
: this; }
322 bool hasBreak() const override
;
323 bool hasContinue() const override
;
325 void accept(Visitor
*v
) override
{ v
->visit(this); }
328 class ForeachStatement final
: public Statement
331 TOK op
; // TOKforeach or TOKforeach_reverse
332 Parameters
*parameters
; // array of Parameter*'s
335 Loc endloc
; // location of closing curly bracket
338 VarDeclaration
*value
;
340 FuncDeclaration
*func
; // function we're lexically in
342 Statements
*cases
; // put breaks, continues, gotos and returns here
343 ScopeStatements
*gotos
; // forward referenced goto's go here
345 ForeachStatement
*syntaxCopy() override
;
346 bool hasBreak() const override
;
347 bool hasContinue() const override
;
349 void accept(Visitor
*v
) override
{ v
->visit(this); }
352 class ForeachRangeStatement final
: public Statement
355 TOK op
; // TOKforeach or TOKforeach_reverse
356 Parameter
*prm
; // loop index variable
360 Loc endloc
; // location of closing curly bracket
364 ForeachRangeStatement
*syntaxCopy() override
;
365 bool hasBreak() const override
;
366 bool hasContinue() const override
;
368 void accept(Visitor
*v
) override
{ v
->visit(this); }
371 class IfStatement final
: public Statement
375 Expression
*condition
;
378 VarDeclaration
*match
; // for MatchExpression results
379 Loc endloc
; // location of closing curly bracket
381 IfStatement
*syntaxCopy() override
;
383 void accept(Visitor
*v
) override
{ v
->visit(this); }
386 class ConditionalStatement final
: public Statement
389 Condition
*condition
;
393 ConditionalStatement
*syntaxCopy() override
;
395 void accept(Visitor
*v
) override
{ v
->visit(this); }
398 class StaticForeachStatement final
: public Statement
403 StaticForeachStatement
*syntaxCopy() override
;
405 void accept(Visitor
*v
) override
{ v
->visit(this); }
408 class PragmaStatement final
: public Statement
412 Expressions
*args
; // array of Expression's
415 PragmaStatement
*syntaxCopy() override
;
417 void accept(Visitor
*v
) override
{ v
->visit(this); }
420 class StaticAssertStatement final
: public Statement
425 StaticAssertStatement
*syntaxCopy() override
;
427 void accept(Visitor
*v
) override
{ v
->visit(this); }
430 class SwitchStatement final
: public Statement
433 Expression
*condition
;
437 DefaultStatement
*sdefault
;
438 Statement
*tryBody
; // set to TryCatchStatement or TryFinallyStatement if in _body portion
439 TryFinallyStatement
*tf
;
440 GotoCaseStatements gotoCases
; // array of unresolved GotoCaseStatement's
441 CaseStatements
*cases
; // array of CaseStatement's
442 int hasNoDefault
; // !=0 if no default statement
443 int hasVars
; // !=0 if has variable case values
444 VarDeclaration
*lastVar
;
446 SwitchStatement
*syntaxCopy() override
;
447 bool hasBreak() const override
;
449 void accept(Visitor
*v
) override
{ v
->visit(this); }
452 class CaseStatement final
: public Statement
456 Statement
*statement
;
458 int index
; // which case it is (since we sort this)
459 VarDeclaration
*lastVar
;
460 void* extra
; // for use by Statement_toIR()
462 CaseStatement
*syntaxCopy() override
;
464 void accept(Visitor
*v
) override
{ v
->visit(this); }
468 class CaseRangeStatement final
: public Statement
473 Statement
*statement
;
475 CaseRangeStatement
*syntaxCopy() override
;
476 void accept(Visitor
*v
) override
{ v
->visit(this); }
480 class DefaultStatement final
: public Statement
483 Statement
*statement
;
484 VarDeclaration
*lastVar
;
486 DefaultStatement
*syntaxCopy() override
;
488 void accept(Visitor
*v
) override
{ v
->visit(this); }
491 class GotoDefaultStatement final
: public Statement
496 GotoDefaultStatement
*syntaxCopy() override
;
498 void accept(Visitor
*v
) override
{ v
->visit(this); }
501 class GotoCaseStatement final
: public Statement
504 Expression
*exp
; // NULL, or which case to goto
505 CaseStatement
*cs
; // case statement it resolves to
507 GotoCaseStatement
*syntaxCopy() override
;
509 void accept(Visitor
*v
) override
{ v
->visit(this); }
512 class SwitchErrorStatement final
: public Statement
517 void accept(Visitor
*v
) override
{ v
->visit(this); }
520 class ReturnStatement final
: public Statement
526 ReturnStatement
*syntaxCopy() override
;
528 ReturnStatement
*endsWithReturnStatement() override
{ return this; }
529 void accept(Visitor
*v
) override
{ v
->visit(this); }
532 class BreakStatement final
: public Statement
537 BreakStatement
*syntaxCopy() override
;
539 void accept(Visitor
*v
) override
{ v
->visit(this); }
542 class ContinueStatement final
: public Statement
547 ContinueStatement
*syntaxCopy() override
;
549 void accept(Visitor
*v
) override
{ v
->visit(this); }
552 class SynchronizedStatement final
: public Statement
558 SynchronizedStatement
*syntaxCopy() override
;
559 bool hasBreak() const override
;
560 bool hasContinue() const override
;
562 void accept(Visitor
*v
) override
{ v
->visit(this); }
565 class WithStatement final
: public Statement
570 VarDeclaration
*wthis
;
573 WithStatement
*syntaxCopy() override
;
575 void accept(Visitor
*v
) override
{ v
->visit(this); }
578 class TryCatchStatement final
: public Statement
584 Statement
*tryBody
; /// set to enclosing TryCatchStatement or TryFinallyStatement if in _body portion
586 TryCatchStatement
*syntaxCopy() override
;
587 bool hasBreak() const override
;
589 void accept(Visitor
*v
) override
{ v
->visit(this); }
592 class Catch final
: public RootObject
601 // set if semantic processing errors
604 // was generated by the compiler,
605 // wasn't present in source code
611 class TryFinallyStatement final
: public Statement
615 Statement
*finalbody
;
617 Statement
*tryBody
; // set to enclosing TryCatchStatement or TryFinallyStatement if in _body portion
618 bool bodyFallsThru
; // true if _body falls through to finally
620 static TryFinallyStatement
*create(const Loc
&loc
, Statement
*body
, Statement
*finalbody
);
621 TryFinallyStatement
*syntaxCopy() override
;
622 bool hasBreak() const override
;
623 bool hasContinue() const override
;
625 void accept(Visitor
*v
) override
{ v
->visit(this); }
628 class ScopeGuardStatement final
: public Statement
632 Statement
*statement
;
634 ScopeGuardStatement
*syntaxCopy() override
;
636 void accept(Visitor
*v
) override
{ v
->visit(this); }
639 class ThrowStatement final
: public Statement
643 // was generated by the compiler,
644 // wasn't present in source code
647 ThrowStatement
*syntaxCopy() override
;
649 void accept(Visitor
*v
) override
{ v
->visit(this); }
652 class DebugStatement final
: public Statement
655 Statement
*statement
;
657 DebugStatement
*syntaxCopy() override
;
658 void accept(Visitor
*v
) override
{ v
->visit(this); }
661 class GotoStatement final
: public Statement
666 Statement
*tryBody
; /// set to enclosing TryCatchStatement or TryFinallyStatement if in _body portion
667 TryFinallyStatement
*tf
;
668 ScopeGuardStatement
*os
;
669 VarDeclaration
*lastVar
;
671 GotoStatement
*syntaxCopy() override
;
673 void accept(Visitor
*v
) override
{ v
->visit(this); }
676 class LabelStatement final
: public Statement
680 Statement
*statement
;
681 Statement
*tryBody
; /// set to enclosing TryCatchStatement or TryFinallyStatement if in _body portion
682 TryFinallyStatement
*tf
;
683 ScopeGuardStatement
*os
;
684 VarDeclaration
*lastVar
;
685 Statement
*gotoTarget
; // interpret
686 void* extra
; // used by Statement_toIR()
687 bool breaks
; // someone did a 'break ident'
689 LabelStatement
*syntaxCopy() override
;
691 void accept(Visitor
*v
) override
{ v
->visit(this); }
694 class LabelDsymbol final
: public Dsymbol
697 LabelStatement
*statement
;
699 bool deleted
; // set if rewritten to return in foreach delegate
700 bool iasm
; // set if used by inline assembler
702 static LabelDsymbol
*create(Identifier
*ident
);
703 LabelDsymbol
*isLabel() override
;
704 void accept(Visitor
*v
) override
{ v
->visit(this); }
707 Statement
* asmSemantic(AsmStatement
*s
, Scope
*sc
);
709 class AsmStatement
: public Statement
714 AsmStatement
*syntaxCopy() override
;
715 void accept(Visitor
*v
) override
{ v
->visit(this); }
718 class InlineAsmStatement final
: public AsmStatement
722 unsigned asmalign
; // alignment of this statement
723 unsigned regs
; // mask of registers modified (must match regm_t in back end)
724 bool refparam
; // true if function parameter is referenced
725 bool naked
; // true if function is to be naked
727 InlineAsmStatement
*syntaxCopy() override
;
728 void accept(Visitor
*v
) override
{ v
->visit(this); }
731 // A GCC asm statement - assembler instructions with D expression operands
732 class GccAsmStatement final
: public AsmStatement
735 StorageClass stc
; // attributes of the asm {} block
736 Expression
*insn
; // string expression that is the template for assembler code
737 Expressions
*args
; // input and output operands of the statement
738 unsigned outputargs
; // of the operands in 'args', the number of output operands
739 Identifiers
*names
; // list of symbolic names for the operands
740 Expressions
*constraints
; // list of string constants specifying constraints on operands
741 Expressions
*clobbers
; // list of string constants specifying clobbers and scratch registers
742 Identifiers
*labels
; // list of goto labels
743 GotoStatements
*gotos
; // of the goto labels, the equivalent statements they represent
745 GccAsmStatement
*syntaxCopy() override
;
746 void accept(Visitor
*v
) override
{ v
->visit(this); }
749 // a complete asm {} block
750 class CompoundAsmStatement final
: public CompoundStatement
753 StorageClass stc
; // postfix attributes like nothrow/pure/@trusted
755 CompoundAsmStatement
*syntaxCopy() override
;
757 void accept(Visitor
*v
) override
{ v
->visit(this); }
760 class ImportStatement final
: public Statement
763 Dsymbols
*imports
; // Array of Import's
765 ImportStatement
*syntaxCopy() override
;
767 void accept(Visitor
*v
) override
{ v
->visit(this); }