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); }
384 bool isIfCtfeBlock();
387 class ConditionalStatement final
: public Statement
390 Condition
*condition
;
394 ConditionalStatement
*syntaxCopy() override
;
396 void accept(Visitor
*v
) override
{ v
->visit(this); }
399 class StaticForeachStatement final
: public Statement
404 StaticForeachStatement
*syntaxCopy() override
;
406 void accept(Visitor
*v
) override
{ v
->visit(this); }
409 class PragmaStatement final
: public Statement
413 Expressions
*args
; // array of Expression's
416 PragmaStatement
*syntaxCopy() override
;
418 void accept(Visitor
*v
) override
{ v
->visit(this); }
421 class StaticAssertStatement final
: public Statement
426 StaticAssertStatement
*syntaxCopy() override
;
428 void accept(Visitor
*v
) override
{ v
->visit(this); }
431 class SwitchStatement final
: public Statement
434 Expression
*condition
;
438 DefaultStatement
*sdefault
;
439 Statement
*tryBody
; // set to TryCatchStatement or TryFinallyStatement if in _body portion
440 TryFinallyStatement
*tf
;
441 GotoCaseStatements gotoCases
; // array of unresolved GotoCaseStatement's
442 CaseStatements
*cases
; // array of CaseStatement's
443 int hasNoDefault
; // !=0 if no default statement
444 int hasVars
; // !=0 if has variable case values
445 VarDeclaration
*lastVar
;
447 SwitchStatement
*syntaxCopy() override
;
448 bool hasBreak() const override
;
450 void accept(Visitor
*v
) override
{ v
->visit(this); }
453 class CaseStatement final
: public Statement
457 Statement
*statement
;
459 int index
; // which case it is (since we sort this)
460 VarDeclaration
*lastVar
;
461 void* extra
; // for use by Statement_toIR()
463 CaseStatement
*syntaxCopy() override
;
465 void accept(Visitor
*v
) override
{ v
->visit(this); }
469 class CaseRangeStatement final
: public Statement
474 Statement
*statement
;
476 CaseRangeStatement
*syntaxCopy() override
;
477 void accept(Visitor
*v
) override
{ v
->visit(this); }
481 class DefaultStatement final
: public Statement
484 Statement
*statement
;
485 VarDeclaration
*lastVar
;
487 DefaultStatement
*syntaxCopy() override
;
489 void accept(Visitor
*v
) override
{ v
->visit(this); }
492 class GotoDefaultStatement final
: public Statement
497 GotoDefaultStatement
*syntaxCopy() override
;
499 void accept(Visitor
*v
) override
{ v
->visit(this); }
502 class GotoCaseStatement final
: public Statement
505 Expression
*exp
; // NULL, or which case to goto
506 CaseStatement
*cs
; // case statement it resolves to
508 GotoCaseStatement
*syntaxCopy() override
;
510 void accept(Visitor
*v
) override
{ v
->visit(this); }
513 class SwitchErrorStatement final
: public Statement
518 void accept(Visitor
*v
) override
{ v
->visit(this); }
521 class ReturnStatement final
: public Statement
527 ReturnStatement
*syntaxCopy() override
;
529 ReturnStatement
*endsWithReturnStatement() override
{ return this; }
530 void accept(Visitor
*v
) override
{ v
->visit(this); }
533 class BreakStatement final
: public Statement
538 BreakStatement
*syntaxCopy() override
;
540 void accept(Visitor
*v
) override
{ v
->visit(this); }
543 class ContinueStatement final
: public Statement
548 ContinueStatement
*syntaxCopy() override
;
550 void accept(Visitor
*v
) override
{ v
->visit(this); }
553 class SynchronizedStatement final
: public Statement
559 SynchronizedStatement
*syntaxCopy() override
;
560 bool hasBreak() const override
;
561 bool hasContinue() const override
;
563 void accept(Visitor
*v
) override
{ v
->visit(this); }
566 class WithStatement final
: public Statement
571 VarDeclaration
*wthis
;
574 WithStatement
*syntaxCopy() override
;
576 void accept(Visitor
*v
) override
{ v
->visit(this); }
579 class TryCatchStatement final
: public Statement
585 Statement
*tryBody
; /// set to enclosing TryCatchStatement or TryFinallyStatement if in _body portion
587 TryCatchStatement
*syntaxCopy() override
;
588 bool hasBreak() const override
;
590 void accept(Visitor
*v
) override
{ v
->visit(this); }
593 class Catch final
: public RootObject
602 // set if semantic processing errors
605 // was generated by the compiler,
606 // wasn't present in source code
612 class TryFinallyStatement final
: public Statement
616 Statement
*finalbody
;
618 Statement
*tryBody
; // set to enclosing TryCatchStatement or TryFinallyStatement if in _body portion
619 bool bodyFallsThru
; // true if _body falls through to finally
621 static TryFinallyStatement
*create(const Loc
&loc
, Statement
*body
, Statement
*finalbody
);
622 TryFinallyStatement
*syntaxCopy() override
;
623 bool hasBreak() const override
;
624 bool hasContinue() const override
;
626 void accept(Visitor
*v
) override
{ v
->visit(this); }
629 class ScopeGuardStatement final
: public Statement
633 Statement
*statement
;
635 ScopeGuardStatement
*syntaxCopy() override
;
637 void accept(Visitor
*v
) override
{ v
->visit(this); }
640 class ThrowStatement final
: public Statement
644 // was generated by the compiler,
645 // wasn't present in source code
648 ThrowStatement
*syntaxCopy() override
;
650 void accept(Visitor
*v
) override
{ v
->visit(this); }
653 class DebugStatement final
: public Statement
656 Statement
*statement
;
658 DebugStatement
*syntaxCopy() override
;
659 void accept(Visitor
*v
) override
{ v
->visit(this); }
662 class GotoStatement final
: public Statement
667 Statement
*tryBody
; /// set to enclosing TryCatchStatement or TryFinallyStatement if in _body portion
668 TryFinallyStatement
*tf
;
669 ScopeGuardStatement
*os
;
670 VarDeclaration
*lastVar
;
672 GotoStatement
*syntaxCopy() override
;
674 void accept(Visitor
*v
) override
{ v
->visit(this); }
677 class LabelStatement final
: public Statement
681 Statement
*statement
;
682 Statement
*tryBody
; /// set to enclosing TryCatchStatement or TryFinallyStatement if in _body portion
683 TryFinallyStatement
*tf
;
684 ScopeGuardStatement
*os
;
685 VarDeclaration
*lastVar
;
686 Statement
*gotoTarget
; // interpret
687 void* extra
; // used by Statement_toIR()
688 bool breaks
; // someone did a 'break ident'
690 LabelStatement
*syntaxCopy() override
;
692 void accept(Visitor
*v
) override
{ v
->visit(this); }
695 class LabelDsymbol final
: public Dsymbol
698 LabelStatement
*statement
;
700 bool deleted
; // set if rewritten to return in foreach delegate
701 bool iasm
; // set if used by inline assembler
703 static LabelDsymbol
*create(Identifier
*ident
);
704 LabelDsymbol
*isLabel() override
;
705 void accept(Visitor
*v
) override
{ v
->visit(this); }
708 Statement
* asmSemantic(AsmStatement
*s
, Scope
*sc
);
710 class AsmStatement
: public Statement
715 AsmStatement
*syntaxCopy() override
;
716 void accept(Visitor
*v
) override
{ v
->visit(this); }
719 class InlineAsmStatement final
: public AsmStatement
723 unsigned asmalign
; // alignment of this statement
724 unsigned regs
; // mask of registers modified (must match regm_t in back end)
725 bool refparam
; // true if function parameter is referenced
726 bool naked
; // true if function is to be naked
728 InlineAsmStatement
*syntaxCopy() override
;
729 void accept(Visitor
*v
) override
{ v
->visit(this); }
732 // A GCC asm statement - assembler instructions with D expression operands
733 class GccAsmStatement final
: public AsmStatement
736 StorageClass stc
; // attributes of the asm {} block
737 Expression
*insn
; // string expression that is the template for assembler code
738 Expressions
*args
; // input and output operands of the statement
739 unsigned outputargs
; // of the operands in 'args', the number of output operands
740 Identifiers
*names
; // list of symbolic names for the operands
741 Expressions
*constraints
; // list of string constants specifying constraints on operands
742 Expressions
*clobbers
; // list of string constants specifying clobbers and scratch registers
743 Identifiers
*labels
; // list of goto labels
744 GotoStatements
*gotos
; // of the goto labels, the equivalent statements they represent
746 GccAsmStatement
*syntaxCopy() override
;
747 void accept(Visitor
*v
) override
{ v
->visit(this); }
750 // a complete asm {} block
751 class CompoundAsmStatement final
: public CompoundStatement
754 StorageClass stc
; // postfix attributes like nothrow/pure/@trusted
756 CompoundAsmStatement
*syntaxCopy() override
;
758 void accept(Visitor
*v
) override
{ v
->visit(this); }
761 class ImportStatement final
: public Statement
764 Dsymbols
*imports
; // Array of Import's
766 ImportStatement
*syntaxCopy() override
;
768 void accept(Visitor
*v
) override
{ v
->visit(this); }