2 * Defines AST nodes for statements.
4 * Specification: $(LINK2 https://dlang.org/spec/statement.html, Statements)
6 * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved
7 * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright)
8 * License: $(LINK2 https://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
16 import core
.stdc
.stdarg
;
17 import core
.stdc
.stdio
;
19 import dmd
.arraytypes
;
25 import dmd
.declaration
;
27 import dmd
.expression
;
32 import dmd
.identifier
;
35 import dmd
.common
.outbuffer
;
36 import dmd
.rootobject
;
38 import dmd
.staticassert
;
42 /***********************************************************
43 * Specification: https://dlang.org/spec/statement.html
45 extern (C
++) abstract class Statement
: ASTNode
50 override final DYNCAST
dyncast() const
52 return DYNCAST
.statement
;
55 final extern (D
) this(const ref Loc loc
, STMT stmt
) @safe
59 // If this is an in{} contract scope statement (skip for determining
60 // inlineStatus of a function body for header content)
63 Statement
syntaxCopy()
68 /*************************************
69 * Do syntax copy of an array of Statement's.
71 static Statements
* arraySyntaxCopy(Statements
* a
)
79 (*b
)[i
] = s ? s
.syntaxCopy() : null;
85 Statement
getRelatedLabeled()
90 /****************************
91 * Determine if an enclosed `break` would apply to this
92 * statement, such as if it is a loop or switch statement.
96 bool hasBreak() const pure nothrow
98 //printf("Statement::hasBreak()\n");
102 /****************************
103 * Determine if an enclosed `continue` would apply to this
104 * statement, such as if it is a loop statement.
108 bool hasContinue() const pure nothrow
113 /**********************************
115 * `true` if statement uses exception handling
117 extern (D
) final bool usesEH()
119 extern (C
++) final class UsesEH
: StoppableVisitor
121 alias visit
= typeof(super).visit
;
123 override void visit(Statement s
)
127 override void visit(TryCatchStatement s
)
132 override void visit(TryFinallyStatement s
)
137 override void visit(ScopeGuardStatement s
)
142 override void visit(SynchronizedStatement s
)
148 scope UsesEH ueh
= new UsesEH();
149 return walkPostorder(this, ueh
);
152 /**********************************
154 * `true` if statement 'comes from' somewhere else, like a goto
156 extern (D
) final bool comeFrom()
158 extern (C
++) final class ComeFrom
: StoppableVisitor
160 alias visit
= typeof(super).visit
;
162 override void visit(Statement s
)
166 override void visit(CaseStatement s
)
171 override void visit(DefaultStatement s
)
176 override void visit(LabelStatement s
)
181 override void visit(AsmStatement s
)
187 scope ComeFrom cf
= new ComeFrom();
188 return walkPostorder(this, cf
);
191 /**********************************
193 * `true` if statement has executable code.
195 extern (D
) final bool hasCode()
197 extern (C
++) final class HasCode
: StoppableVisitor
199 alias visit
= typeof(super).visit
;
201 override void visit(Statement s
)
206 override void visit(ExpStatement s
)
210 stop
= s
.exp
.hasCode();
214 override void visit(CompoundStatement s
)
218 override void visit(ScopeStatement s
)
222 override void visit(ImportStatement s
)
226 override void visit(CaseStatement s
)
230 override void visit(DefaultStatement s
)
234 override void visit(LabelStatement s
)
239 scope HasCode hc
= new HasCode();
240 return walkPostorder(this, hc
);
243 /*******************************
244 * Find last statement in a sequence of statements.
246 * the last statement, or `null` if there isn't one
248 inout(Statement
) last() inout nothrow pure
253 /**************************
254 * Support Visitor Pattern
258 override void accept(Visitor v
)
263 /************************************
264 * Does this statement end with a return statement?
266 * I.e. is it a single return statement or some compound statement
267 * that unconditionally hits a return statement.
269 * return statement it ends with, otherwise null
272 inout(ReturnStatement
) endsWithReturnStatement() inout { return null; }
274 final pure inout nothrow @nogc @safe:
276 /********************
277 * A cheaper method of doing downcasting of Statements.
279 * the downcast statement if it can be downcasted, otherwise `null`
281 inout(ErrorStatement
) isErrorStatement() { return stmt
== STMT
.Error ?
cast(typeof(return))this : null; }
282 inout(PeelStatement
) isPeelStatement() { return stmt
== STMT
.Peel ?
cast(typeof(return))this : null; }
283 inout(ScopeStatement
) isScopeStatement() { return stmt
== STMT
.Scope ?
cast(typeof(return))this : null; }
284 inout(ExpStatement
) isExpStatement() { return stmt
== STMT
.Exp ?
cast(typeof(return))this : null; }
285 inout(CompoundStatement
) isCompoundStatement() { return stmt
== STMT
.Compound ?
cast(typeof(return))this : null; }
286 inout(ReturnStatement
) isReturnStatement() { return stmt
== STMT
.Return ?
cast(typeof(return))this : null; }
287 inout(IfStatement
) isIfStatement() { return stmt
== STMT
.If ?
cast(typeof(return))this : null; }
288 inout(ConditionalStatement
) isConditionalStatement() { return stmt
== STMT
.Conditional ?
cast(typeof(return))this : null; }
289 inout(StaticForeachStatement
) isStaticForeachStatement() { return stmt
== STMT
.StaticForeach ?
cast(typeof(return))this : null; }
290 inout(CaseStatement
) isCaseStatement() { return stmt
== STMT
.Case ?
cast(typeof(return))this : null; }
291 inout(DefaultStatement
) isDefaultStatement() { return stmt
== STMT
.Default ?
cast(typeof(return))this : null; }
292 inout(LabelStatement
) isLabelStatement() { return stmt
== STMT
.Label ?
cast(typeof(return))this : null; }
293 inout(GotoStatement
) isGotoStatement() { return stmt
== STMT
.Goto ?
cast(typeof(return))this : null; }
294 inout(GotoDefaultStatement
) isGotoDefaultStatement() { return stmt
== STMT
.GotoDefault ?
cast(typeof(return))this : null; }
295 inout(GotoCaseStatement
) isGotoCaseStatement() { return stmt
== STMT
.GotoCase ?
cast(typeof(return))this : null; }
296 inout(BreakStatement
) isBreakStatement() { return stmt
== STMT
.Break ?
cast(typeof(return))this : null; }
297 inout(DtorExpStatement
) isDtorExpStatement() { return stmt
== STMT
.DtorExp ?
cast(typeof(return))this : null; }
298 inout(MixinStatement
) isMixinStatement() { return stmt
== STMT
.Mixin ?
cast(typeof(return))this : null; }
299 inout(ForwardingStatement
) isForwardingStatement() { return stmt
== STMT
.Forwarding ?
cast(typeof(return))this : null; }
300 inout(DoStatement
) isDoStatement() { return stmt
== STMT
.Do ?
cast(typeof(return))this : null; }
301 inout(WhileStatement
) isWhileStatement() { return stmt
== STMT
.While ?
cast(typeof(return))this : null; }
302 inout(ForStatement
) isForStatement() { return stmt
== STMT
.For ?
cast(typeof(return))this : null; }
303 inout(ForeachStatement
) isForeachStatement() { return stmt
== STMT
.Foreach ?
cast(typeof(return))this : null; }
304 inout(SwitchStatement
) isSwitchStatement() { return stmt
== STMT
.Switch ?
cast(typeof(return))this : null; }
305 inout(ContinueStatement
) isContinueStatement() { return stmt
== STMT
.Continue ?
cast(typeof(return))this : null; }
306 inout(WithStatement
) isWithStatement() { return stmt
== STMT
.With ?
cast(typeof(return))this : null; }
307 inout(TryCatchStatement
) isTryCatchStatement() { return stmt
== STMT
.TryCatch ?
cast(typeof(return))this : null; }
308 inout(ThrowStatement
) isThrowStatement() { return stmt
== STMT
.Throw ?
cast(typeof(return))this : null; }
309 inout(DebugStatement
) isDebugStatement() { return stmt
== STMT
.Debug ?
cast(typeof(return))this : null; }
310 inout(TryFinallyStatement
) isTryFinallyStatement() { return stmt
== STMT
.TryFinally ?
cast(typeof(return))this : null; }
311 inout(ScopeGuardStatement
) isScopeGuardStatement() { return stmt
== STMT
.ScopeGuard ?
cast(typeof(return))this : null; }
312 inout(SwitchErrorStatement
) isSwitchErrorStatement() { return stmt
== STMT
.SwitchError ?
cast(typeof(return))this : null; }
313 inout(UnrolledLoopStatement
) isUnrolledLoopStatement() { return stmt
== STMT
.UnrolledLoop ?
cast(typeof(return))this : null; }
314 inout(ForeachRangeStatement
) isForeachRangeStatement() { return stmt
== STMT
.ForeachRange ?
cast(typeof(return))this : null; }
315 inout(CompoundDeclarationStatement
) isCompoundDeclarationStatement() { return stmt
== STMT
.CompoundDeclaration ?
cast(typeof(return))this : null; }
316 inout(CompoundAsmStatement
) isCompoundAsmStatement() { return stmt
== STMT
.CompoundAsm ?
cast(typeof(return))this : null; }
317 inout(PragmaStatement
) isPragmaStatement() { return stmt
== STMT
.Pragma ?
cast(typeof(return))this : null; }
318 inout(StaticAssertStatement
) isStaticAssertStatement() { return stmt
== STMT
.StaticAssert ?
cast(typeof(return))this : null; }
319 inout(CaseRangeStatement
) isCaseRangeStatement() { return stmt
== STMT
.CaseRange ?
cast(typeof(return))this : null; }
320 inout(SynchronizedStatement
) isSynchronizedStatement() { return stmt
== STMT
.Synchronized ?
cast(typeof(return))this : null; }
321 inout(AsmStatement
) isAsmStatement() { return stmt
== STMT
.Asm ?
cast(typeof(return))this : null; }
322 inout(InlineAsmStatement
) isInlineAsmStatement() { return stmt
== STMT
.InlineAsm ?
cast(typeof(return))this : null; }
323 inout(GccAsmStatement
) isGccAsmStatement() { return stmt
== STMT
.GccAsm ?
cast(typeof(return))this : null; }
324 inout(ImportStatement
) isImportStatement() { return stmt
== STMT
.Import ?
cast(typeof(return))this : null; }
327 /***********************************************************
328 * Any Statement that fails semantic() or has a component that is an ErrorExp or
329 * a TypeError should return an ErrorStatement from semantic().
331 extern (C
++) final class ErrorStatement
: Statement
335 super(Loc
.initial
, STMT
.Error
);
336 assert(global
.gaggedErrors || global
.errors
);
339 override ErrorStatement
syntaxCopy()
344 override void accept(Visitor v
)
350 /***********************************************************
352 extern (C
++) final class PeelStatement
: Statement
356 extern (D
) this(Statement s
) @safe
358 super(s
.loc
, STMT
.Peel
);
362 override void accept(Visitor v
)
369 /***********************************************************
370 * https://dlang.org/spec/statement.html#ExpressionStatement
372 extern (C
++) class ExpStatement
: Statement
376 final extern (D
) this(const ref Loc loc
, Expression exp
) @safe
378 super(loc
, STMT
.Exp
);
382 final extern (D
) this(const ref Loc loc
, Expression exp
, STMT stmt
) @safe
388 final extern (D
) this(const ref Loc loc
, Dsymbol declaration
) @safe
390 super(loc
, STMT
.Exp
);
391 this.exp
= new DeclarationExp(loc
, declaration
);
394 static ExpStatement
create(const ref Loc loc
, Expression exp
) @safe
396 return new ExpStatement(loc
, exp
);
399 override ExpStatement
syntaxCopy()
401 return new ExpStatement(loc
, exp ? exp
.syntaxCopy() : null);
404 override void accept(Visitor v
)
410 /***********************************************************
412 extern (C
++) final class DtorExpStatement
: ExpStatement
414 // Wraps an expression that is the destruction of 'var'
417 extern (D
) this(const ref Loc loc
, Expression exp
, VarDeclaration var
) @safe
419 super(loc
, exp
, STMT
.DtorExp
);
423 override DtorExpStatement
syntaxCopy()
425 return new DtorExpStatement(loc
, exp ? exp
.syntaxCopy() : null, var
);
428 override void accept(Visitor v
)
434 /***********************************************************
435 * https://dlang.org/spec/statement.html#mixin-statement
437 // Note: was called CompileStatement
438 extern (C
++) final class MixinStatement
: Statement
442 extern (D
) this(const ref Loc loc
, Expression exp
)
444 Expressions
* exps
= new Expressions();
449 extern (D
) this(const ref Loc loc
, Expressions
* exps
) @safe
451 super(loc
, STMT
.Mixin
);
455 override MixinStatement
syntaxCopy()
457 return new MixinStatement(loc
, Expression
.arraySyntaxCopy(exps
));
460 override void accept(Visitor v
)
466 /***********************************************************
468 extern (C
++) class CompoundStatement
: Statement
470 Statements
* statements
;
473 * Construct a `CompoundStatement` using an already existing
474 * array of `Statement`s
477 * loc = Instantiation information
478 * statements = An array of `Statement`s, that will referenced by this class
480 final extern (D
) this(const ref Loc loc
, Statements
* statements
) @safe
482 super(loc
, STMT
.Compound
);
483 this.statements
= statements
;
486 final extern (D
) this(const ref Loc loc
, Statements
* statements
, STMT stmt
) @safe
489 this.statements
= statements
;
493 * Construct a `CompoundStatement` from an array of `Statement`s
496 * loc = Instantiation information
497 * sts = A variadic array of `Statement`s, that will copied in this class
498 * The entries themselves will not be copied.
500 final extern (D
) this(const ref Loc loc
, Statement
[] sts
...)
502 super(loc
, STMT
.Compound
);
503 statements
= new Statements();
504 statements
.reserve(sts
.length
);
509 static CompoundStatement
create(const ref Loc loc
, Statement s1
, Statement s2
)
511 return new CompoundStatement(loc
, s1
, s2
);
514 override CompoundStatement
syntaxCopy()
516 return new CompoundStatement(loc
, Statement
.arraySyntaxCopy(statements
));
519 override final inout(ReturnStatement
) endsWithReturnStatement() inout nothrow pure
521 foreach (s
; *statements
)
525 if (inout rs
= s
.endsWithReturnStatement())
532 override final inout(Statement
) last() inout nothrow pure
535 for (size_t i
= statements
.length
; i
; --i
)
537 s
= cast(Statement
)(*statements
)[i
- 1];
540 s
= cast(Statement
)s
.last();
548 override void accept(Visitor v
)
554 /***********************************************************
556 extern (C
++) final class CompoundDeclarationStatement
: CompoundStatement
558 extern (D
) this(const ref Loc loc
, Statements
* statements
) @safe
560 super(loc
, statements
, STMT
.CompoundDeclaration
);
563 override CompoundDeclarationStatement
syntaxCopy()
565 return new CompoundDeclarationStatement(loc
, Statement
.arraySyntaxCopy(statements
));
568 override void accept(Visitor v
)
574 /***********************************************************
575 * The purpose of this is so that continue will go to the next
576 * of the statements, and break will go to the end of the statements.
578 extern (C
++) final class UnrolledLoopStatement
: Statement
580 Statements
* statements
;
582 extern (D
) this(const ref Loc loc
, Statements
* statements
) @safe
584 super(loc
, STMT
.UnrolledLoop
);
585 this.statements
= statements
;
588 override UnrolledLoopStatement
syntaxCopy()
590 return new UnrolledLoopStatement(loc
, Statement
.arraySyntaxCopy(statements
));
593 override bool hasBreak() const pure nothrow
598 override bool hasContinue() const pure nothrow
603 override void accept(Visitor v
)
609 /***********************************************************
611 extern (C
++) final class ScopeStatement
: Statement
614 Loc endloc
; // location of closing curly bracket
616 extern (D
) this(const ref Loc loc
, Statement statement
, Loc endloc
) @safe
618 super(loc
, STMT
.Scope
);
619 this.statement
= statement
;
620 this.endloc
= endloc
;
623 override ScopeStatement
syntaxCopy()
625 return new ScopeStatement(loc
, statement ? statement
.syntaxCopy() : null, endloc
);
628 override inout(ReturnStatement
) endsWithReturnStatement() inout nothrow pure
631 return statement
.endsWithReturnStatement();
635 override bool hasBreak() const pure nothrow
637 //printf("ScopeStatement::hasBreak() %s\n", toChars());
638 return statement ? statement
.hasBreak() : false;
641 override bool hasContinue() const pure nothrow
643 return statement ? statement
.hasContinue() : false;
646 override void accept(Visitor v
)
652 /***********************************************************
653 * Statement whose symbol table contains foreach index variables in a
654 * local scope and forwards other members to the parent scope. This
657 * Also see: `dmd.attrib.ForwardingAttribDeclaration`
659 extern (C
++) final class ForwardingStatement
: Statement
661 /// The symbol containing the `static foreach` variables.
662 ForwardingScopeDsymbol sym
= null;
663 /// The wrapped statement.
666 extern (D
) this(const ref Loc loc
, ForwardingScopeDsymbol sym
, Statement statement
) @safe
668 super(loc
, STMT
.Forwarding
);
671 this.statement
= statement
;
674 extern (D
) this(const ref Loc loc
, Statement statement
) @safe
676 auto sym
= new ForwardingScopeDsymbol();
677 sym
.symtab
= new DsymbolTable();
678 this(loc
, sym
, statement
);
681 override ForwardingStatement
syntaxCopy()
683 return new ForwardingStatement(loc
, statement
.syntaxCopy());
686 override void accept(Visitor v
)
693 /***********************************************************
694 * https://dlang.org/spec/statement.html#while-statement
696 extern (C
++) final class WhileStatement
: Statement
699 Expression condition
;
701 Loc endloc
; // location of closing curly bracket
703 extern (D
) this(const ref Loc loc
, Expression condition
, Statement _body
, Loc endloc
, Parameter param
= null) @safe
705 super(loc
, STMT
.While
);
706 this.condition
= condition
;
708 this.endloc
= endloc
;
712 override WhileStatement
syntaxCopy()
714 return new WhileStatement(loc
,
715 condition
.syntaxCopy(),
716 _body ? _body
.syntaxCopy() : null,
717 endloc
, param ? param
.syntaxCopy() : null);
720 override bool hasBreak() const pure nothrow
725 override bool hasContinue() const pure nothrow
730 override void accept(Visitor v
)
736 /***********************************************************
737 * https://dlang.org/spec/statement.html#do-statement
739 extern (C
++) final class DoStatement
: Statement
742 Expression condition
;
743 Loc endloc
; // location of ';' after while
745 extern (D
) this(const ref Loc loc
, Statement _body
, Expression condition
, Loc endloc
) @safe
749 this.condition
= condition
;
750 this.endloc
= endloc
;
753 override DoStatement
syntaxCopy()
755 return new DoStatement(loc
,
756 _body ? _body
.syntaxCopy() : null,
757 condition
.syntaxCopy(),
761 override bool hasBreak() const pure nothrow
766 override bool hasContinue() const pure nothrow
771 override void accept(Visitor v
)
777 /***********************************************************
778 * https://dlang.org/spec/statement.html#for-statement
780 extern (C
++) final class ForStatement
: Statement
783 Expression condition
;
784 Expression increment
;
786 Loc endloc
; // location of closing curly bracket
788 // When wrapped in try/finally clauses, this points to the outermost one,
789 // which may have an associated label. Internal break/continue statements
790 // treat that label as referring to this loop.
791 Statement relatedLabeled
;
793 extern (D
) this(const ref Loc loc
, Statement _init
, Expression condition
, Expression increment
, Statement _body
, Loc endloc
) @safe
795 super(loc
, STMT
.For
);
797 this.condition
= condition
;
798 this.increment
= increment
;
800 this.endloc
= endloc
;
803 override ForStatement
syntaxCopy()
805 return new ForStatement(loc
,
806 _init ? _init
.syntaxCopy() : null,
807 condition ? condition
.syntaxCopy() : null,
808 increment ? increment
.syntaxCopy() : null,
813 override Statement
getRelatedLabeled()
815 return relatedLabeled ? relatedLabeled
: this;
818 override bool hasBreak() const pure nothrow
820 //printf("ForStatement::hasBreak()\n");
824 override bool hasContinue() const pure nothrow
829 override void accept(Visitor v
)
835 /***********************************************************
836 * https://dlang.org/spec/statement.html#foreach-statement
838 extern (C
++) final class ForeachStatement
: Statement
840 TOK op
; // TOK.foreach_ or TOK.foreach_reverse_
841 Parameters
* parameters
; // array of Parameters, one for each ForeachType
842 Expression aggr
; // ForeachAggregate
843 Statement _body
; // NoScopeNonEmptyStatement
844 Loc endloc
; // location of closing curly bracket
847 VarDeclaration value
;
849 FuncDeclaration func
; // function we're lexically in
851 Statements
* cases
; // put breaks, continues, gotos and returns here
852 ScopeStatements
* gotos
; // forward referenced goto's go here
854 extern (D
) this(const ref Loc loc
, TOK op
, Parameters
* parameters
, Expression aggr
, Statement _body
, Loc endloc
) @safe
856 super(loc
, STMT
.Foreach
);
858 this.parameters
= parameters
;
861 this.endloc
= endloc
;
864 override ForeachStatement
syntaxCopy()
866 return new ForeachStatement(loc
, op
,
867 Parameter
.arraySyntaxCopy(parameters
),
869 _body ? _body
.syntaxCopy() : null,
873 override bool hasBreak() const pure nothrow
878 override bool hasContinue() const pure nothrow
883 override void accept(Visitor v
)
889 /***********************************************************
890 * https://dlang.org/spec/statement.html#foreach-range-statement
892 extern (C
++) final class ForeachRangeStatement
: Statement
894 TOK op
; // TOK.foreach_ or TOK.foreach_reverse_
895 Parameter prm
; // loop index variable
899 Loc endloc
; // location of closing curly bracket
903 extern (D
) this(const ref Loc loc
, TOK op
, Parameter prm
, Expression lwr
, Expression upr
, Statement _body
, Loc endloc
) @safe
905 super(loc
, STMT
.ForeachRange
);
911 this.endloc
= endloc
;
914 override ForeachRangeStatement
syntaxCopy()
916 return new ForeachRangeStatement(loc
, op
, prm
.syntaxCopy(), lwr
.syntaxCopy(), upr
.syntaxCopy(), _body ? _body
.syntaxCopy() : null, endloc
);
919 override bool hasBreak() const pure nothrow
924 override bool hasContinue() const pure nothrow
929 override void accept(Visitor v
)
935 /***********************************************************
936 * https://dlang.org/spec/statement.html#if-statement
938 extern (C
++) final class IfStatement
: Statement
941 Expression condition
;
944 VarDeclaration match
; // for MatchExpression results
945 Loc endloc
; // location of closing curly bracket
947 extern (D
) this(const ref Loc loc
, Parameter prm
, Expression condition
, Statement ifbody
, Statement elsebody
, Loc endloc
) @safe
951 this.condition
= condition
;
952 this.ifbody
= ifbody
;
953 this.elsebody
= elsebody
;
954 this.endloc
= endloc
;
957 override IfStatement
syntaxCopy()
959 return new IfStatement(loc
,
960 prm ? prm
.syntaxCopy() : null,
961 condition
.syntaxCopy(),
962 ifbody ? ifbody
.syntaxCopy() : null,
963 elsebody ? elsebody
.syntaxCopy() : null,
967 override void accept(Visitor v
)
973 * Returns: true if `if (__ctfe)`
977 if (auto cv
= condition
.isVarExp())
978 return cv
.var
.ident
== Id
.ctfe
;
983 /***********************************************************
984 * https://dlang.org/spec/version.html#ConditionalStatement
986 extern (C
++) final class ConditionalStatement
: Statement
992 extern (D
) this(const ref Loc loc
, Condition condition
, Statement ifbody
, Statement elsebody
) @safe
994 super(loc
, STMT
.Conditional
);
995 this.condition
= condition
;
996 this.ifbody
= ifbody
;
997 this.elsebody
= elsebody
;
1000 override ConditionalStatement
syntaxCopy()
1002 return new ConditionalStatement(loc
, condition
.syntaxCopy(), ifbody
.syntaxCopy(), elsebody ? elsebody
.syntaxCopy() : null);
1005 override void accept(Visitor v
)
1012 /***********************************************************
1013 * https://dlang.org/spec/version.html#StaticForeachStatement
1014 * Static foreach statements, like:
1017 * static foreach(i; 0 .. 10)
1023 extern (C
++) final class StaticForeachStatement
: Statement
1027 extern (D
) this(const ref Loc loc
, StaticForeach sfe
) @safe
1029 super(loc
, STMT
.StaticForeach
);
1033 override StaticForeachStatement
syntaxCopy()
1035 return new StaticForeachStatement(loc
, sfe
.syntaxCopy());
1038 override void accept(Visitor v
)
1044 /***********************************************************
1045 * https://dlang.org/spec/statement.html#pragma-statement
1047 extern (C
++) final class PragmaStatement
: Statement
1049 const Identifier ident
;
1050 Expressions
* args
; // array of Expression's
1053 extern (D
) this(const ref Loc loc
, const Identifier ident
, Expressions
* args
, Statement _body
) @safe
1055 super(loc
, STMT
.Pragma
);
1061 override PragmaStatement
syntaxCopy()
1063 return new PragmaStatement(loc
, ident
, Expression
.arraySyntaxCopy(args
), _body ? _body
.syntaxCopy() : null);
1066 override void accept(Visitor v
)
1072 /***********************************************************
1073 * https://dlang.org/spec/version.html#StaticAssert
1075 extern (C
++) final class StaticAssertStatement
: Statement
1079 extern (D
) this(StaticAssert sa
) @safe
1081 super(sa
.loc
, STMT
.StaticAssert
);
1085 override StaticAssertStatement
syntaxCopy()
1087 return new StaticAssertStatement(sa
.syntaxCopy(null));
1090 override void accept(Visitor v
)
1096 /***********************************************************
1097 * https://dlang.org/spec/statement.html#switch-statement
1099 extern (C
++) final class SwitchStatement
: Statement
1102 Expression condition
; /// switch(condition)
1103 Statement _body
; ///
1104 bool isFinal
; /// https://dlang.org/spec/statement.html#final-switch-statement
1107 bool hasDefault
; /// true if has default statement
1108 bool hasVars
; /// true if has variable case values
1109 DefaultStatement sdefault
; /// default:
1110 Statement tryBody
; /// set to TryCatchStatement or TryFinallyStatement if in _body portion
1111 TryFinallyStatement tf
; /// set if in the 'finally' block of a TryFinallyStatement
1112 GotoCaseStatements gotoCases
; /// array of unresolved GotoCaseStatement's
1113 CaseStatements
* cases
; /// array of CaseStatement's
1114 VarDeclaration lastVar
; /// last observed variable declaration in this statement
1116 extern (D
) this(const ref Loc loc
, Parameter param
, Expression condition
, Statement _body
, bool isFinal
, Loc endloc
)
1118 super(loc
, STMT
.Switch
);
1120 this.condition
= condition
;
1122 this.isFinal
= isFinal
;
1123 this.endloc
= endloc
;
1126 override SwitchStatement
syntaxCopy()
1128 return new SwitchStatement(loc
,
1129 param ? param
.syntaxCopy() : null,
1130 condition
.syntaxCopy(),
1136 override bool hasBreak() const pure nothrow
1141 override void accept(Visitor v
)
1147 /***********************************************************
1148 * https://dlang.org/spec/statement.html#CaseStatement
1150 extern (C
++) final class CaseStatement
: Statement
1153 Statement statement
;
1155 int index
; // which case it is (since we sort this)
1156 VarDeclaration lastVar
;
1157 void* extra
; // for use by Statement_toIR()
1159 extern (D
) this(const ref Loc loc
, Expression exp
, Statement statement
) @safe
1161 super(loc
, STMT
.Case
);
1163 this.statement
= statement
;
1166 override CaseStatement
syntaxCopy()
1168 return new CaseStatement(loc
, exp
.syntaxCopy(), statement
.syntaxCopy());
1171 override void accept(Visitor v
)
1177 /***********************************************************
1178 * https://dlang.org/spec/statement.html#CaseRangeStatement
1180 extern (C
++) final class CaseRangeStatement
: Statement
1184 Statement statement
;
1186 extern (D
) this(const ref Loc loc
, Expression first
, Expression last
, Statement statement
) @safe
1188 super(loc
, STMT
.CaseRange
);
1191 this.statement
= statement
;
1194 override CaseRangeStatement
syntaxCopy()
1196 return new CaseRangeStatement(loc
, first
.syntaxCopy(), last
.syntaxCopy(), statement
.syntaxCopy());
1199 override void accept(Visitor v
)
1205 /***********************************************************
1206 * https://dlang.org/spec/statement.html#DefaultStatement
1208 extern (C
++) final class DefaultStatement
: Statement
1210 Statement statement
;
1212 VarDeclaration lastVar
;
1214 extern (D
) this(const ref Loc loc
, Statement statement
) @safe
1216 super(loc
, STMT
.Default
);
1217 this.statement
= statement
;
1220 override DefaultStatement
syntaxCopy()
1222 return new DefaultStatement(loc
, statement
.syntaxCopy());
1225 override void accept(Visitor v
)
1231 /***********************************************************
1232 * https://dlang.org/spec/statement.html#GotoStatement
1234 extern (C
++) final class GotoDefaultStatement
: Statement
1238 extern (D
) this(const ref Loc loc
) @safe
1240 super(loc
, STMT
.GotoDefault
);
1243 override GotoDefaultStatement
syntaxCopy()
1245 return new GotoDefaultStatement(loc
);
1248 override void accept(Visitor v
)
1254 /***********************************************************
1255 * https://dlang.org/spec/statement.html#GotoStatement
1257 extern (C
++) final class GotoCaseStatement
: Statement
1259 Expression exp
; // null, or which case to goto
1261 CaseStatement cs
; // case statement it resolves to
1263 extern (D
) this(const ref Loc loc
, Expression exp
) @safe
1265 super(loc
, STMT
.GotoCase
);
1269 override GotoCaseStatement
syntaxCopy()
1271 return new GotoCaseStatement(loc
, exp ? exp
.syntaxCopy() : null);
1274 override void accept(Visitor v
)
1280 /***********************************************************
1282 extern (C
++) final class SwitchErrorStatement
: Statement
1286 extern (D
) this(const ref Loc loc
) @safe
1288 super(loc
, STMT
.SwitchError
);
1291 final extern (D
) this(const ref Loc loc
, Expression exp
) @safe
1293 super(loc
, STMT
.SwitchError
);
1297 override void accept(Visitor v
)
1303 /***********************************************************
1304 * https://dlang.org/spec/statement.html#return-statement
1306 extern (C
++) final class ReturnStatement
: Statement
1311 extern (D
) this(const ref Loc loc
, Expression exp
) @safe
1313 super(loc
, STMT
.Return
);
1317 override ReturnStatement
syntaxCopy()
1319 return new ReturnStatement(loc
, exp ? exp
.syntaxCopy() : null);
1322 override inout(ReturnStatement
) endsWithReturnStatement() inout nothrow pure
1327 override void accept(Visitor v
)
1333 /***********************************************************
1334 * https://dlang.org/spec/statement.html#break-statement
1336 extern (C
++) final class BreakStatement
: Statement
1340 extern (D
) this(const ref Loc loc
, Identifier ident
) @safe
1342 super(loc
, STMT
.Break
);
1346 override BreakStatement
syntaxCopy()
1348 return new BreakStatement(loc
, ident
);
1351 override void accept(Visitor v
)
1357 /***********************************************************
1358 * https://dlang.org/spec/statement.html#continue-statement
1360 extern (C
++) final class ContinueStatement
: Statement
1364 extern (D
) this(const ref Loc loc
, Identifier ident
) @safe
1366 super(loc
, STMT
.Continue
);
1370 override ContinueStatement
syntaxCopy()
1372 return new ContinueStatement(loc
, ident
);
1375 override void accept(Visitor v
)
1381 /***********************************************************
1382 * https://dlang.org/spec/statement.html#SynchronizedStatement
1384 extern (C
++) final class SynchronizedStatement
: Statement
1389 extern (D
) this(const ref Loc loc
, Expression exp
, Statement _body
) @safe
1391 super(loc
, STMT
.Synchronized
);
1396 override SynchronizedStatement
syntaxCopy()
1398 return new SynchronizedStatement(loc
, exp ? exp
.syntaxCopy() : null, _body ? _body
.syntaxCopy() : null);
1401 override bool hasBreak() const pure nothrow
1403 return false; //true;
1406 override bool hasContinue() const pure nothrow
1408 return false; //true;
1411 override void accept(Visitor v
)
1417 /***********************************************************
1418 * https://dlang.org/spec/statement.html#with-statement
1420 extern (C
++) final class WithStatement
: Statement
1424 VarDeclaration wthis
;
1427 extern (D
) this(const ref Loc loc
, Expression exp
, Statement _body
, Loc endloc
) @safe
1429 super(loc
, STMT
.With
);
1432 this.endloc
= endloc
;
1435 override WithStatement
syntaxCopy()
1437 return new WithStatement(loc
, exp
.syntaxCopy(), _body ? _body
.syntaxCopy() : null, endloc
);
1440 override void accept(Visitor v
)
1446 /***********************************************************
1447 * https://dlang.org/spec/statement.html#try-statement
1449 extern (C
++) final class TryCatchStatement
: Statement
1454 Statement tryBody
; /// set to enclosing TryCatchStatement or TryFinallyStatement if in _body portion
1456 extern (D
) this(const ref Loc loc
, Statement _body
, Catches
* catches
) @safe
1458 super(loc
, STMT
.TryCatch
);
1460 this.catches
= catches
;
1463 override TryCatchStatement
syntaxCopy()
1465 auto a
= new Catches(catches
.length
);
1466 foreach (i
, c
; *catches
)
1468 (*a
)[i
] = c
.syntaxCopy();
1470 return new TryCatchStatement(loc
, _body
.syntaxCopy(), a
);
1473 override bool hasBreak() const pure nothrow
1478 override void accept(Visitor v
)
1484 /***********************************************************
1485 * https://dlang.org/spec/statement.html#Catch
1487 extern (C
++) final class Catch
: RootObject
1495 bool errors
; // set if semantic processing errors
1497 // was generated by the compiler, wasn't present in source code
1500 extern (D
) this(const ref Loc loc
, Type type
, Identifier ident
, Statement handler
) @safe
1502 //printf("Catch(%s, loc = %s)\n", id.toChars(), loc.toChars());
1506 this.handler
= handler
;
1511 auto c
= new Catch(loc
, type ? type
.syntaxCopy() : getThrowable(), ident
, (handler ? handler
.syntaxCopy() : null));
1512 c
.internalCatch
= internalCatch
;
1517 /***********************************************************
1518 * https://dlang.org/spec/statement.html#try-statement
1520 extern (C
++) final class TryFinallyStatement
: Statement
1523 Statement finalbody
;
1525 Statement tryBody
; /// set to enclosing TryCatchStatement or TryFinallyStatement if in _body portion
1526 bool bodyFallsThru
; /// true if _body falls through to finally
1528 extern (D
) this(const ref Loc loc
, Statement _body
, Statement finalbody
) @safe
1530 super(loc
, STMT
.TryFinally
);
1532 this.finalbody
= finalbody
;
1533 this.bodyFallsThru
= true; // assume true until statementSemantic()
1536 static TryFinallyStatement
create(const ref Loc loc
, Statement _body
, Statement finalbody
) @safe
1538 return new TryFinallyStatement(loc
, _body
, finalbody
);
1541 override TryFinallyStatement
syntaxCopy()
1543 return new TryFinallyStatement(loc
, _body
.syntaxCopy(), finalbody
.syntaxCopy());
1546 override bool hasBreak() const pure nothrow
1548 return false; //true;
1551 override bool hasContinue() const pure nothrow
1553 return false; //true;
1556 override void accept(Visitor v
)
1562 /***********************************************************
1563 * https://dlang.org/spec/statement.html#scope-guard-statement
1565 extern (C
++) final class ScopeGuardStatement
: Statement
1568 Statement statement
;
1570 extern (D
) this(const ref Loc loc
, TOK tok
, Statement statement
) @safe
1572 super(loc
, STMT
.ScopeGuard
);
1574 this.statement
= statement
;
1577 override ScopeGuardStatement
syntaxCopy()
1579 return new ScopeGuardStatement(loc
, tok
, statement
.syntaxCopy());
1582 override void accept(Visitor v
)
1588 /***********************************************************
1589 * https://dlang.org/spec/statement.html#throw-statement
1591 extern (C
++) final class ThrowStatement
: Statement
1595 // was generated by the compiler, wasn't present in source code
1598 extern (D
) this(const ref Loc loc
, Expression exp
) @safe
1600 super(loc
, STMT
.Throw
);
1604 override ThrowStatement
syntaxCopy()
1606 auto s
= new ThrowStatement(loc
, exp
.syntaxCopy());
1607 s
.internalThrow
= internalThrow
;
1611 override void accept(Visitor v
)
1617 /***********************************************************
1619 extern (C
++) final class DebugStatement
: Statement
1621 Statement statement
;
1623 extern (D
) this(const ref Loc loc
, Statement statement
) @safe
1625 super(loc
, STMT
.Debug
);
1626 this.statement
= statement
;
1629 override DebugStatement
syntaxCopy()
1631 return new DebugStatement(loc
, statement ? statement
.syntaxCopy() : null);
1634 override void accept(Visitor v
)
1640 /***********************************************************
1641 * https://dlang.org/spec/statement.html#goto-statement
1643 extern (C
++) final class GotoStatement
: Statement
1647 Statement tryBody
; /// set to TryCatchStatement or TryFinallyStatement if in _body portion
1648 TryFinallyStatement tf
;
1649 ScopeGuardStatement os
;
1650 VarDeclaration lastVar
;
1651 bool inCtfeBlock
; /// set if goto is inside an `if (__ctfe)` block
1653 extern (D
) this(const ref Loc loc
, Identifier ident
) @safe
1655 super(loc
, STMT
.Goto
);
1659 override GotoStatement
syntaxCopy()
1661 return new GotoStatement(loc
, ident
);
1664 override void accept(Visitor v
)
1670 /***********************************************************
1671 * https://dlang.org/spec/statement.html#LabeledStatement
1673 extern (C
++) final class LabelStatement
: Statement
1676 Statement statement
;
1678 Statement tryBody
; /// set to TryCatchStatement or TryFinallyStatement if in _body portion
1679 TryFinallyStatement tf
;
1680 ScopeGuardStatement os
;
1681 VarDeclaration lastVar
;
1682 Statement gotoTarget
; // interpret
1683 void* extra
; // used by Statement_toIR()
1684 bool breaks
; // someone did a 'break ident'
1685 bool inCtfeBlock
; // inside a block dominated by `if (__ctfe)`
1687 extern (D
) this(const ref Loc loc
, Identifier ident
, Statement statement
) @safe
1689 super(loc
, STMT
.Label
);
1691 this.statement
= statement
;
1694 override LabelStatement
syntaxCopy()
1696 return new LabelStatement(loc
, ident
, statement ? statement
.syntaxCopy() : null);
1699 override void accept(Visitor v
)
1705 /***********************************************************
1707 extern (C
++) final class LabelDsymbol
: Dsymbol
1709 LabelStatement statement
;
1711 bool deleted
; // set if rewritten to return in foreach delegate
1712 bool iasm
; // set if used by inline assembler
1714 // set if label was defined multiple times, to avoid duplicate errors
1715 // can be removed if generic error message deduplication is implemented
1718 extern (D
) this(Identifier ident
, const ref Loc loc
= Loc
.initial
) @safe
1723 static LabelDsymbol
create(Identifier ident
) @safe
1725 return new LabelDsymbol(ident
);
1728 // is this a LabelDsymbol()?
1729 override LabelDsymbol
isLabel()
1734 override void accept(Visitor v
)
1740 /***********************************************************
1741 * https://dlang.org/spec/statement.html#asm
1743 extern (C
++) class AsmStatement
: Statement
1746 bool caseSensitive
; // for register names
1748 extern (D
) this(const ref Loc loc
, Token
* tokens
) @safe
1750 super(loc
, STMT
.Asm
);
1751 this.tokens
= tokens
;
1754 extern (D
) this(const ref Loc loc
, Token
* tokens
, STMT stmt
) @safe
1757 this.tokens
= tokens
;
1760 override AsmStatement
syntaxCopy()
1762 return new AsmStatement(loc
, tokens
);
1765 override void accept(Visitor v
)
1771 /***********************************************************
1772 * https://dlang.org/spec/iasm.html
1774 extern (C
++) final class InlineAsmStatement
: AsmStatement
1777 uint asmalign
; // alignment of this statement
1778 uint regs
; // mask of registers modified (must match regm_t in back end)
1779 bool refparam
; // true if function parameter is referenced
1780 bool naked
; // true if function is to be naked
1782 extern (D
) this(const ref Loc loc
, Token
* tokens
) @safe
1784 super(loc
, tokens
, STMT
.InlineAsm
);
1787 override InlineAsmStatement
syntaxCopy()
1789 return new InlineAsmStatement(loc
, tokens
);
1792 override void accept(Visitor v
)
1798 /***********************************************************
1799 * https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html
1800 * Assembler instructions with D expression operands.
1802 extern (C
++) final class GccAsmStatement
: AsmStatement
1804 StorageClass
stc; // attributes of the asm {} block
1805 Expression insn
; // string expression that is the template for assembler code
1806 Expressions
* args
; // input and output operands of the statement
1807 uint outputargs
; // of the operands in 'args', the number of output operands
1808 Identifiers
* names
; // list of symbolic names for the operands
1809 Expressions
* constraints
; // list of string constants specifying constraints on operands
1810 Expressions
* clobbers
; // list of string constants specifying clobbers and scratch registers
1811 Identifiers
* labels
; // list of goto labels
1812 GotoStatements
* gotos
; // of the goto labels, the equivalent statements they represent
1814 extern (D
) this(const ref Loc loc
, Token
* tokens
) @safe
1816 super(loc
, tokens
, STMT
.GccAsm
);
1819 override GccAsmStatement
syntaxCopy()
1821 return new GccAsmStatement(loc
, tokens
);
1824 override void accept(Visitor v
)
1830 /***********************************************************
1831 * a complete asm {} block
1833 extern (C
++) final class CompoundAsmStatement
: CompoundStatement
1835 StorageClass
stc; // postfix attributes like nothrow/pure/@trusted
1837 extern (D
) this(const ref Loc loc
, Statements
* statements
, StorageClass
stc) @safe
1839 super(loc
, statements
, STMT
.CompoundAsm
);
1843 override CompoundAsmStatement
syntaxCopy()
1845 return new CompoundAsmStatement(loc
, Statement
.arraySyntaxCopy(statements
), stc);
1848 override void accept(Visitor v
)
1854 /***********************************************************
1855 * https://dlang.org/spec/module.html#ImportDeclaration
1857 extern (C
++) final class ImportStatement
: Statement
1859 Dsymbols
* imports
; // Array of Import's
1861 extern (D
) this(const ref Loc loc
, Dsymbols
* imports
) @safe
1863 super(loc
, STMT
.Import
);
1864 this.imports
= imports
;
1867 override ImportStatement
syntaxCopy()
1869 auto m
= new Dsymbols(imports
.length
);
1870 foreach (i
, s
; *imports
)
1872 (*m
)[i
] = s
.syntaxCopy(null);
1874 return new ImportStatement(loc
, m
);
1877 override void accept(Visitor v
)
1884 mixin template VisitStatement(Result
)
1886 Result
VisitStatement(Statement s
)
1888 final switch (s
.stmt
)
1890 case STMT
.Error
: mixin(visitStmtCase("Error"));
1891 case STMT
.Scope
: mixin(visitStmtCase("Scope"));
1892 case STMT
.Exp
: mixin(visitStmtCase("Exp"));
1893 case STMT
.Compound
: mixin(visitStmtCase("Compound"));
1894 case STMT
.Return
: mixin(visitStmtCase("Return"));
1895 case STMT
.If
: mixin(visitStmtCase("If"));
1896 case STMT
.Conditional
: mixin(visitStmtCase("Conditional"));
1897 case STMT
.StaticForeach
: mixin(visitStmtCase("StaticForeach"));
1898 case STMT
.Case
: mixin(visitStmtCase("Case"));
1899 case STMT
.Default
: mixin(visitStmtCase("Default"));
1900 case STMT
.Label
: mixin(visitStmtCase("Label"));
1901 case STMT
.Goto
: mixin(visitStmtCase("Goto"));
1902 case STMT
.GotoDefault
: mixin(visitStmtCase("GotoDefault"));
1903 case STMT
.GotoCase
: mixin(visitStmtCase("GotoCase"));
1904 case STMT
.Break
: mixin(visitStmtCase("Break"));
1905 case STMT
.DtorExp
: mixin(visitStmtCase("DtorExp"));
1906 case STMT
.Mixin
: mixin(visitStmtCase("Mixin"));
1907 case STMT
.Forwarding
: mixin(visitStmtCase("Forwarding"));
1908 case STMT
.Do
: mixin(visitStmtCase("Do"));
1909 case STMT
.While
: mixin(visitStmtCase("While"));
1910 case STMT
.For
: mixin(visitStmtCase("For"));
1911 case STMT
.Foreach
: mixin(visitStmtCase("Foreach"));
1912 case STMT
.Switch
: mixin(visitStmtCase("Switch"));
1913 case STMT
.Continue
: mixin(visitStmtCase("Continue"));
1914 case STMT
.With
: mixin(visitStmtCase("With"));
1915 case STMT
.TryCatch
: mixin(visitStmtCase("TryCatch"));
1916 case STMT
.Throw
: mixin(visitStmtCase("Throw"));
1917 case STMT
.Debug
: mixin(visitStmtCase("Debug"));
1918 case STMT
.TryFinally
: mixin(visitStmtCase("TryFinally"));
1919 case STMT
.ScopeGuard
: mixin(visitStmtCase("ScopeGuard"));
1920 case STMT
.SwitchError
: mixin(visitStmtCase("SwitchError"));
1921 case STMT
.UnrolledLoop
: mixin(visitStmtCase("UnrolledLoop"));
1922 case STMT
.ForeachRange
: mixin(visitStmtCase("ForeachRange"));
1923 case STMT
.CompoundDeclaration
: mixin(visitStmtCase("CompoundDeclaration"));
1924 case STMT
.Peel
: mixin(visitStmtCase("Peel"));
1925 case STMT
.CompoundAsm
: mixin(visitStmtCase("CompoundAsm"));
1926 case STMT
.Pragma
: mixin(visitStmtCase("Pragma"));
1927 case STMT
.StaticAssert
: mixin(visitStmtCase("StaticAssert"));
1928 case STMT
.CaseRange
: mixin(visitStmtCase("CaseRange"));
1929 case STMT
.Synchronized
: mixin(visitStmtCase("Synchronized"));
1930 case STMT
.Asm
: mixin(visitStmtCase("Asm"));
1931 case STMT
.InlineAsm
: mixin(visitStmtCase("InlineAsm"));
1932 case STMT
.GccAsm
: mixin(visitStmtCase("GccAsm"));
1933 case STMT
.Import
: mixin(visitStmtCase("Import"));
1938 /****************************************
1939 * CTFE-only helper function for VisitInitializer.
1941 * handler = string for the name of the visit handler
1942 * Returns: boilerplate code for a case
1944 pure string
visitStmtCase(string handler
) @safe
1950 enum isVoid = is(Result == void);
1951 auto sx = s.is"~handler
~"Statement();
1952 static if (__traits(compiles, visit"~handler
~"(sx)))
1956 visit"~handler
~"(sx);
1961 if (Result r = visit"~handler
~"(sx))
1966 else static if (__traits(compiles, visitDefaultCase(s)))
1970 visitDefaultCase(sx);
1975 if (Result r = visitDefaultCase(s))
1981 static assert(0, "~handler
~");