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 void error(const char *format
, ...);
117 void warning(unsigned flag
, const char *format
, ...);
118 void deprecation(const char *format
, ...);
119 virtual Statement
*getRelatedLabeled() { return this; }
120 virtual bool hasBreak() const;
121 virtual bool hasContinue() const;
125 virtual Statement
*last();
127 virtual ReturnStatement
*endsWithReturnStatement() { return NULL
; }
129 ErrorStatement
*isErrorStatement() { return stmt
== STMTerror
? (ErrorStatement
*)this : NULL
; }
130 ScopeStatement
*isScopeStatement() { return stmt
== STMTscope
? (ScopeStatement
*)this : NULL
; }
131 ExpStatement
*isExpStatement() { return stmt
== STMTexp
? (ExpStatement
*)this : NULL
; }
132 CompoundStatement
*isCompoundStatement() { return stmt
== STMTcompound
? (CompoundStatement
*)this : NULL
; }
133 ReturnStatement
*isReturnStatement() { return stmt
== STMTreturn
? (ReturnStatement
*)this : NULL
; }
134 IfStatement
*isIfStatement() { return stmt
== STMTif
? (IfStatement
*)this : NULL
; }
135 ConditionalStatement
*isConditionalStatement() { return stmt
== STMTconditional
? (ConditionalStatement
*)this : NULL
; }
136 StaticForeachStatement
*isStaticForeachStatement() { return stmt
== STMTstaticForeach
? (StaticForeachStatement
*)this : NULL
; }
137 CaseStatement
*isCaseStatement() { return stmt
== STMTcase
? (CaseStatement
*)this : NULL
; }
138 DefaultStatement
*isDefaultStatement() { return stmt
== STMTdefault
? (DefaultStatement
*)this : NULL
; }
139 LabelStatement
*isLabelStatement() { return stmt
== STMTlabel
? (LabelStatement
*)this : NULL
; }
140 GotoDefaultStatement
*isGotoDefaultStatement() { return stmt
== STMTgotoDefault
? (GotoDefaultStatement
*)this : NULL
; }
141 GotoCaseStatement
*isGotoCaseStatement() { return stmt
== STMTgotoCase
? (GotoCaseStatement
*)this : NULL
; }
142 BreakStatement
*isBreakStatement() { return stmt
== STMTbreak
? (BreakStatement
*)this : NULL
; }
143 DtorExpStatement
*isDtorExpStatement() { return stmt
== STMTdtorExp
? (DtorExpStatement
*)this : NULL
; }
144 MixinStatement
*isMixinStatement() { return stmt
== STMTmixin
? (MixinStatement
*)this : NULL
; }
145 ForwardingStatement
*isForwardingStatement() { return stmt
== STMTforwarding
? (ForwardingStatement
*)this : NULL
; }
146 DoStatement
*isDoStatement() { return stmt
== STMTdo
? (DoStatement
*)this : NULL
; }
147 ForStatement
*isForStatement() { return stmt
== STMTfor
? (ForStatement
*)this : NULL
; }
148 ForeachStatement
*isForeachStatement() { return stmt
== STMTforeach
? (ForeachStatement
*)this : NULL
; }
149 SwitchStatement
*isSwitchStatement() { return stmt
== STMTswitch
? (SwitchStatement
*)this : NULL
; }
150 ContinueStatement
*isContinueStatement() { return stmt
== STMTcontinue
? (ContinueStatement
*)this : NULL
; }
151 WithStatement
*isWithStatement() { return stmt
== STMTwith
? (WithStatement
*)this : NULL
; }
152 TryCatchStatement
*isTryCatchStatement() { return stmt
== STMTtryCatch
? (TryCatchStatement
*)this : NULL
; }
153 ThrowStatement
*isThrowStatement() { return stmt
== STMTthrow
? (ThrowStatement
*)this : NULL
; }
154 DebugStatement
*isDebugStatement() { return stmt
== STMTdebug
? (DebugStatement
*)this : NULL
; }
155 TryFinallyStatement
*isTryFinallyStatement() { return stmt
== STMTtryFinally
? (TryFinallyStatement
*)this : NULL
; }
156 ScopeGuardStatement
*isScopeGuardStatement() { return stmt
== STMTscopeGuard
? (ScopeGuardStatement
*)this : NULL
; }
157 SwitchErrorStatement
*isSwitchErrorStatement() { return stmt
== STMTswitchError
? (SwitchErrorStatement
*)this : NULL
; }
158 UnrolledLoopStatement
*isUnrolledLoopStatement() { return stmt
== STMTunrolledLoop
? (UnrolledLoopStatement
*)this : NULL
; }
159 ForeachRangeStatement
*isForeachRangeStatement() { return stmt
== STMTforeachRange
? (ForeachRangeStatement
*)this : NULL
; }
160 CompoundDeclarationStatement
*isCompoundDeclarationStatement() { return stmt
== STMTcompoundDeclaration
? (CompoundDeclarationStatement
*)this : NULL
; }
162 void accept(Visitor
*v
) override
{ v
->visit(this); }
165 /** Any Statement that fails semantic() or has a component that is an ErrorExp or
166 * a TypeError should return an ErrorStatement from semantic().
168 class ErrorStatement final
: public Statement
171 ErrorStatement
*syntaxCopy() override
;
173 void accept(Visitor
*v
) override
{ v
->visit(this); }
176 class PeelStatement final
: public Statement
181 void accept(Visitor
*v
) override
{ v
->visit(this); }
184 class ExpStatement
: public Statement
189 static ExpStatement
*create(const Loc
&loc
, Expression
*exp
);
190 ExpStatement
*syntaxCopy() override
;
192 void accept(Visitor
*v
) override
{ v
->visit(this); }
195 class DtorExpStatement final
: public ExpStatement
198 /* Wraps an expression that is the destruction of 'var'
203 DtorExpStatement
*syntaxCopy() override
;
204 void accept(Visitor
*v
) override
{ v
->visit(this); }
207 class MixinStatement final
: public Statement
212 MixinStatement
*syntaxCopy() override
;
213 void accept(Visitor
*v
) override
{ v
->visit(this); }
216 class CompoundStatement
: public Statement
219 Statements
*statements
;
221 static CompoundStatement
*create(const Loc
&loc
, Statement
*s1
, Statement
*s2
);
222 CompoundStatement
*syntaxCopy() override
;
223 ReturnStatement
*endsWithReturnStatement() override final
;
224 Statement
*last() override final
;
226 void accept(Visitor
*v
) override
{ v
->visit(this); }
229 class CompoundDeclarationStatement final
: public CompoundStatement
232 CompoundDeclarationStatement
*syntaxCopy() override
;
233 void accept(Visitor
*v
) override
{ v
->visit(this); }
236 /* The purpose of this is so that continue will go to the next
237 * of the statements, and break will go to the end of the statements.
239 class UnrolledLoopStatement final
: public Statement
242 Statements
*statements
;
244 UnrolledLoopStatement
*syntaxCopy() override
;
245 bool hasBreak() const override
;
246 bool hasContinue() const override
;
248 void accept(Visitor
*v
) override
{ v
->visit(this); }
251 class ScopeStatement final
: public Statement
254 Statement
*statement
;
255 Loc endloc
; // location of closing curly bracket
257 ScopeStatement
*syntaxCopy() override
;
258 ReturnStatement
*endsWithReturnStatement() override
;
259 bool hasBreak() const override
;
260 bool hasContinue() const override
;
262 void accept(Visitor
*v
) override
{ v
->visit(this); }
265 class ForwardingStatement final
: public Statement
268 ForwardingScopeDsymbol
*sym
;
269 Statement
*statement
;
271 ForwardingStatement
*syntaxCopy() override
;
272 void accept(Visitor
*v
) override
{ v
->visit(this); }
275 class WhileStatement final
: public Statement
279 Expression
*condition
;
281 Loc endloc
; // location of closing curly bracket
283 WhileStatement
*syntaxCopy() override
;
284 bool hasBreak() const override
;
285 bool hasContinue() const override
;
287 void accept(Visitor
*v
) override
{ v
->visit(this); }
290 class DoStatement final
: public Statement
294 Expression
*condition
;
295 Loc endloc
; // location of ';' after while
297 DoStatement
*syntaxCopy() override
;
298 bool hasBreak() const override
;
299 bool hasContinue() const override
;
301 void accept(Visitor
*v
) override
{ v
->visit(this); }
304 class ForStatement final
: public Statement
308 Expression
*condition
;
309 Expression
*increment
;
311 Loc endloc
; // location of closing curly bracket
313 // When wrapped in try/finally clauses, this points to the outermost one,
314 // which may have an associated label. Internal break/continue statements
315 // treat that label as referring to this loop.
316 Statement
*relatedLabeled
;
318 ForStatement
*syntaxCopy() override
;
319 Statement
*getRelatedLabeled() override
{ return relatedLabeled
? relatedLabeled
: this; }
320 bool hasBreak() const override
;
321 bool hasContinue() const override
;
323 void accept(Visitor
*v
) override
{ v
->visit(this); }
326 class ForeachStatement final
: public Statement
329 TOK op
; // TOKforeach or TOKforeach_reverse
330 Parameters
*parameters
; // array of Parameter*'s
333 Loc endloc
; // location of closing curly bracket
336 VarDeclaration
*value
;
338 FuncDeclaration
*func
; // function we're lexically in
340 Statements
*cases
; // put breaks, continues, gotos and returns here
341 ScopeStatements
*gotos
; // forward referenced goto's go here
343 ForeachStatement
*syntaxCopy() override
;
344 bool hasBreak() const override
;
345 bool hasContinue() const override
;
347 void accept(Visitor
*v
) override
{ v
->visit(this); }
350 class ForeachRangeStatement final
: public Statement
353 TOK op
; // TOKforeach or TOKforeach_reverse
354 Parameter
*prm
; // loop index variable
358 Loc endloc
; // location of closing curly bracket
362 ForeachRangeStatement
*syntaxCopy() override
;
363 bool hasBreak() const override
;
364 bool hasContinue() const override
;
366 void accept(Visitor
*v
) override
{ v
->visit(this); }
369 class IfStatement final
: public Statement
373 Expression
*condition
;
376 VarDeclaration
*match
; // for MatchExpression results
377 Loc endloc
; // location of closing curly bracket
379 IfStatement
*syntaxCopy() override
;
381 void accept(Visitor
*v
) override
{ v
->visit(this); }
382 bool isIfCtfeBlock();
385 class ConditionalStatement final
: public Statement
388 Condition
*condition
;
392 ConditionalStatement
*syntaxCopy() override
;
394 void accept(Visitor
*v
) override
{ v
->visit(this); }
397 class StaticForeachStatement final
: public Statement
402 StaticForeachStatement
*syntaxCopy() override
;
404 void accept(Visitor
*v
) override
{ v
->visit(this); }
407 class PragmaStatement final
: public Statement
411 Expressions
*args
; // array of Expression's
414 PragmaStatement
*syntaxCopy() override
;
416 void accept(Visitor
*v
) override
{ v
->visit(this); }
419 class StaticAssertStatement final
: public Statement
424 StaticAssertStatement
*syntaxCopy() override
;
426 void accept(Visitor
*v
) override
{ v
->visit(this); }
429 class SwitchStatement final
: public Statement
433 Expression
*condition
;
438 d_bool hasDefault
; // true if default statement
439 d_bool hasVars
; // true if has variable case values
440 DefaultStatement
*sdefault
;
441 Statement
*tryBody
; // set to TryCatchStatement or TryFinallyStatement if in _body portion
442 TryFinallyStatement
*tf
;
443 GotoCaseStatements gotoCases
; // array of unresolved GotoCaseStatement's
444 CaseStatements
*cases
; // array of CaseStatement's
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
607 d_bool internalCatch
;
612 class TryFinallyStatement final
: public Statement
616 Statement
*finalbody
;
618 Statement
*tryBody
; // set to enclosing TryCatchStatement or TryFinallyStatement if in _body portion
619 d_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
646 d_bool internalThrow
;
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 d_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 d_bool deleted
; // set if rewritten to return in foreach delegate
701 d_bool iasm
; // set if used by inline assembler
702 d_bool duplicated
; // set if multiply defined, to avoid duplicate error messages
704 static LabelDsymbol
*create(Identifier
*ident
);
705 LabelDsymbol
*isLabel() override
;
706 void accept(Visitor
*v
) override
{ v
->visit(this); }
709 Statement
* asmSemantic(AsmStatement
*s
, Scope
*sc
);
711 class AsmStatement
: public Statement
715 bool caseSensitive
; // for register names
717 AsmStatement
*syntaxCopy() override
;
718 void accept(Visitor
*v
) override
{ v
->visit(this); }
721 class InlineAsmStatement final
: public AsmStatement
725 unsigned asmalign
; // alignment of this statement
726 unsigned regs
; // mask of registers modified (must match regm_t in back end)
727 d_bool refparam
; // true if function parameter is referenced
728 d_bool naked
; // true if function is to be naked
730 InlineAsmStatement
*syntaxCopy() override
;
731 void accept(Visitor
*v
) override
{ v
->visit(this); }
734 // A GCC asm statement - assembler instructions with D expression operands
735 class GccAsmStatement final
: public AsmStatement
738 StorageClass stc
; // attributes of the asm {} block
739 Expression
*insn
; // string expression that is the template for assembler code
740 Expressions
*args
; // input and output operands of the statement
741 unsigned outputargs
; // of the operands in 'args', the number of output operands
742 Identifiers
*names
; // list of symbolic names for the operands
743 Expressions
*constraints
; // list of string constants specifying constraints on operands
744 Expressions
*clobbers
; // list of string constants specifying clobbers and scratch registers
745 Identifiers
*labels
; // list of goto labels
746 GotoStatements
*gotos
; // of the goto labels, the equivalent statements they represent
748 GccAsmStatement
*syntaxCopy() override
;
749 void accept(Visitor
*v
) override
{ v
->visit(this); }
752 // a complete asm {} block
753 class CompoundAsmStatement final
: public CompoundStatement
756 StorageClass stc
; // postfix attributes like nothrow/pure/@trusted
758 CompoundAsmStatement
*syntaxCopy() override
;
760 void accept(Visitor
*v
) override
{ v
->visit(this); }
763 class ImportStatement final
: public Statement
766 Dsymbols
*imports
; // Array of Import's
768 ImportStatement
*syntaxCopy() override
;
770 void accept(Visitor
*v
) override
{ v
->visit(this); }